Sigurd Snørteland



loud tweets – a “twitter-to-speak” wp7 app (source code included)

‘loud tweets’ is a wp7 twitter app. You type in a twitter search keyword and the app refreshes the search every 60 seconds. All recived tweets will automatically be translated to english and spoken out loud by the phone.

I found inspiration for making this app in a Tim Heuer article ‘Make your Silverlight applications Speak to you with Microsoft Translator’

I haven’t had the chance to test this app on a wp7 device yet, but it works nice in the emulator 🙂

Go to the bottom off this page to find a link to the source code.

Architecture
  Be aware of this comment from Michael Washington
Cool it works on mt HTC HD7. Note, you just cant hear anything while debugging. This url explains how to debug using media: http://blogs.msdn.com/b/jaimer/archive/2010/11/03/tips-for-debugging-wp7-media-apps-with-wpconnect.aspx

The ‘System.Speech’ library is not included in WP7/SL, but ‘text-to-speek’ can be done using the Speak-service in the Microsoft Bing Traslation API. You can send a string to Bing and get a sound-file back as a byte[]. You can’t play the the file directe (it’s not supported) and insted you have to save it to isolated storage and than load it and send it to a mediaelement-control.

The code requires a Bing Id, something you can get for free from this site: http://www.microsofttranslator.com/dev. Copy your Bing ID into the string ‘_appid’.

public partial class MainPage : PhoneApplicationPage
    {
        ...
        string _appId = "";
    }

The twitter search starts when the search textfield lose it’s focus and when you click on the bird image.

        private void txtTwitte_LostFocus(object sender, RoutedEventArgs e)
        {
            TwitterTimer();
        }

        private void imgTwitter_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            TwitterTimer();
        }

        private void TwitterTimer()
        {
            if (this.timelineTimer == null)
            {
                this.timelineTimer = new DispatcherTimer();
                this.timelineTimer.Tick += new EventHandler(TwitterTimer_Tick);
                this.timelineTimer.Interval = new TimeSpan(0, 1, 0);
                this.timelineTimer.Start();
            }

            this.TwitterTimer_Tick(this, EventArgs.Empty);
        }

        void TwitterTimer_Tick(object sender, EventArgs e)
        {
            twitter();
        }

This is the twitter search code:

        private void twitter()
        {
            try
            {
                if (txtTwitte.Text != "")
                {
                    lblLoading.Visibility = Visibility.Visible;
                    lboTwitte.Opacity = 0.3;

                    WebClient client = new WebClient();
                    client.DownloadStringAsync(new Uri(twitterUrl + txtTwitte.Text));
                    client.DownloadStringCompleted += ((s, e) =>
                    {
                        if (e.Error == null)
                        {
                            XDocument xml = XDocument.Parse(e.Result);
                            XNamespace atomNS = "http://www.w3.org/2005/Atom";

                            var tempList = (from entry in xml.Descendants(atomNS + "entry")
                                            select new TwitterObject()
                                            {
                                                ID = entry.Element(atomNS + "id").Value,
                                                Title = entry.Element(atomNS + "title").Value,
                                                Date = DateTime.Parse(entry.Element(atomNS + "published").Value),
                                                AuthorName = entry.Descendants(atomNS + "author").Elements(atomNS + "name").FirstOrDefault().Value,
                                                AuthorUri = entry.Descendants(atomNS + "author").Elements(atomNS + "uri").FirstOrDefault().Value,
                                                AuthorImage = (from imgElement in entry.Elements(atomNS + "link")
                                                               where imgElement.Attribute("rel") != null
                                                               && imgElement.Attribute("rel").Value.Contains("image")
                                                               && imgElement.Attribute("href") != null
                                                               select imgElement.Attribute("href").Value).FirstOrDefault()
                                            }).ToList();

                            twitteList = tempList.ToList();
                            lboTwitte.ItemsSource = twitteList;
                            lblLoading.Visibility = Visibility.Collapsed;
                            lboTwitte.Opacity = 1;

                            tweetLoud();
                        }
                    });
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

The method ‘tweetLoud()’ gets called when a result is received from twitter. This method keeps track on which tweets that’s already been “spoken out loud”. When it finds a new tweet it calls the ‘translate()’ method.

        private void tweetLoud()
        {
            if (soundOn)
            {
                for (int i = 0; i < lboTwitte.Items.Count; i++)
                {
                    TwitterObject twitterObject = (TwitterObject)lboTwitte.Items[i];

                    if(!tweetLoudList.Contains(twitterObject.Title))
                    {
                        tweetLoudList.Add(twitterObject.Title);
                        translate(twitterObject.Title);
                        break;
                    }
                }
            }
        }

Code for translating the tweet to english using the Bing Translate API:

        private void translate(string text)
        {
            try
            {
                if (soundOn)
                {
                    text = removeHtml(text);
                    WebClient client = new WebClient();
                    client.OpenReadCompleted += new OpenReadCompletedEventHandler(translate_Completed);
                    client.OpenReadAsync(new Uri(string.Format(translateUrl, _appId, "en", HttpUtility.UrlEncode(text))));
                }
            }
            catch (Exception ex)
            {
                tweetLoud();
                MessageBox.Show(ex.ToString());
            }
        }

        void translate_Completed(object sender, OpenReadCompletedEventArgs e)
        {
            try{
                if (e.Error == null)
                {
                    DataContractSerializer data = new DataContractSerializer(typeof(string));
                    string response = data.ReadObject(e.Result) as string;
                    speek(response);
                }
                else
                {
                    tweetLoud();
                }
            }
            catch (Exception ex)
            {
                tweetLoud();
                MessageBox.Show(ex.ToString());
            }
        }

This code recives a byte[] file from Bing, saves the file to isolated storage and plays the file in the medielement control.

        private void speek(string text)
        {
            try
            {
                if (soundOn)
                {
                    WebClient client = new WebClient();
                    client.OpenReadCompleted += new OpenReadCompletedEventHandler(speek_Completed);
                    client.OpenReadAsync(new Uri(string.Format(speakUrl, _appId, text, "en")));
                }
            }
            catch (Exception ex)
            {
                tweetLoud();
                MessageBox.Show(ex.ToString());
            }
        }

        void speek_Completed(object sender, OpenReadCompletedEventArgs e)
        {
            try
            {
                if (e.Error == null)
                {
                    var sound = e.Result;

                    media.Source = null;
                    string filename = "twitter";
                    using (IsolatedStorageFile userStoreForApplication = IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        bool fileExists = userStoreForApplication.FileExists(filename);

                        if (fileExists)
                        {
                            userStoreForApplication.DeleteFile(filename);
                        }

                        var isolatedStorageFileStream = userStoreForApplication.CreateFile(filename);

                        using (isolatedStorageFileStream)
                        {
                            SaveFile(e.Result, isolatedStorageFileStream);

                            if (e.Error == null)
                            {
                                media.SetSource(isolatedStorageFileStream);
                                media.Play();
                                media.MediaEnded += new RoutedEventHandler(media_MediaEnded);
                                //tweetLoud();
                            }
                        }
                    }
                }
                else
                {
                    tweetLoud();
                }
            }
            catch (Exception ex)
`           {
                tweetLoud();
                MessageBox.Show(ex.ToString());
            }
        }

You can’t play the the file directe (it’s not supported) and insted you have to save it to isolated storage using this code:

        public static void SaveFile(Stream input, Stream output)
        {
            try
            {
                byte[] buffer = new byte[32768];
                while (true)
                {
                    int read = input.Read(buffer, 0, buffer.Length);
                    if (read <= 0)
                    {
                        return;
                    }
                    output.Write(buffer, 0, read);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

When the mediaelement is done playing a tweet sound file it calls the method ‘tweetLoud()’ to get the next tweet translated and played.

        void media_MediaEnded(object sender, RoutedEventArgs e)
        {
            try
            {
                tweetLoud();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

Download the source code:

Advertisements

Trackbacks & Pingbacks

  1. my apps « Sigurd Snørteland pingbacked on 6 years, 7 months ago
  2. Tweets that mention loud tweets – a “twitter-to-speak” wp7 app (source code included) « Sigurd Snørteland -- Topsy.com pingbacked on 6 years, 7 months ago
  3. Media coverage « Sigurd Snørteland pingbacked on 6 years, 7 months ago
  4. Loud Tweets–Search Twitter and Hear Results For WP7 (With Source Code) pingbacked on 6 years, 7 months ago

Comments

  1. Cool it works on mt HTC HD7. Note, you just cant hear anything while debugging. This url explains how to debug using media:http://blogs.msdn.com/b/jaimer/archive/2010/11/03/tips-for-debugging-wp7-media-apps-with-wpconnect.aspx

    | Reply Posted 6 years, 7 months ago
  2. * Pham Nguyen says:

    Hi ! Nice to see you !
    it’s great Post !
    thank you very much !

    | Reply Posted 5 years, 11 months ago
  3. I have been surfing online more than 4 hours today, yet I never found any interesting
    article like yours. It is pretty worth enough for me.
    In my opinion, if all web owners and bloggers made good
    content as you did, the net will be a lot more useful than ever before.

    | Reply Posted 4 years, 6 months ago
  4. I wanted to thank you for this good read!!
    I definitely enjoyed every bit of it. I have got you saved as a favorite to look at new things you post…

    | Reply Posted 4 years, 1 month ago
  5. * Trena says:

    Write more, thats all I have to say. Literally, it seems as
    though you relied on the video to make your point.
    You definitely know what youre talking about, why
    throw away your intelligence on just posting videos to
    your weblog when you could be giving us something informative
    to read?

    | Reply Posted 4 years ago
  6. I’m amazed, I must say. Seldom do I encounter a blog that’s both
    equally educative and interesting, and without a doubt, you’ve hit the nail on the head. The problem is something which not enough men and women are speaking intelligently about. I am very happy I came across this in my hunt for something concerning this.

    | Reply Posted 4 years ago
  7. I like the helpful info you provide in your articles. I’ll bookmark your weblog and check again here frequently. I am quite certain I will learn many new stuff right here! Best of luck for the next!

    | Reply Posted 4 years ago
  8. * Damaris says:

    WOW just what I was looking for. Came here by searching for direct
    sportslink

    | Reply Posted 4 years ago
  9. * Sophie says:

    I am truly pleased to read this webpage posts which contains plenty of
    valuable data, thanks for providing these statistics.

    | Reply Posted 4 years ago
  10. * Moses says:

    Good day! This post couldn’t be written any better! Reading through this post reminds me of my old room mate! He always kept talking about this. I will forward this article to him. Pretty sure he will have a good read. Thanks for sharing!

    | Reply Posted 4 years ago
  11. * sleep aid says:

    Heya i am for the primary time here. I found this board and I in finding It truly useful
    & it helped me out much. I’m hoping to offer one thing back and help others such as you helped me.

    | Reply Posted 3 years, 11 months ago
  12. Whats up very nice web site!! Guy .. Beautiful .. Superb .

    . I will bookmark your website and take the feeds also?
    I am glad to seek out a lot of useful info here in the
    submit, we’d like work out extra strategies on this regard, thanks for sharing. . . . . .

    | Reply Posted 3 years, 11 months ago
  13. Thank you for the auspicious writeup. It in fact was a amusement account it.

    Look advanced to more added agreeable from you! However, how could we communicate?

    | Reply Posted 3 years, 11 months ago
  14. * Andra says:

    Its like you read my mind! You seem to know a lot about this, like you wrote the book in it or
    something. I think that you could do with a few pics to drive the message home
    a little bit, but other than that, this is fantastic blog.
    An excellent read. I’ll definitely be back.

    | Reply Posted 3 years, 11 months ago
  15. Hey there this is kind of of off topic but I was wondering if blogs use WYSIWYG editors or if you have to manually code with HTML.

    I’m starting a blog soon but have no coding knowledge so I wanted to get guidance from someone with experience. Any help would be enormously appreciated!

    | Reply Posted 3 years, 10 months ago
  16. Attractive section of content. I just stumbled upon your website and
    in accession capital to assert that I acquire actually enjoyed account your blog posts.
    Anyway I will be subscribing to your feeds and even I achievement you access consistently fast.

    | Reply Posted 3 years, 10 months ago
  17. I always emailed this weblog post page to all my
    friends, since if like to read it next my friends will too.

    | Reply Posted 3 years, 10 months ago
  18. They made use of the exact same innovative science to create Adiphene as they did Phen375,
    and this wound up developing a fantastically safe, unbelievably effective dietary fat
    burning supplement that other business envy. This continues to be not 100% confirmed, but keep tuned.
    Note that you can only buy Adiphene online as they
    aren’t available in stores.

    | Reply Posted 3 years ago
  19. * google says:

    In the signature line provide a link back to your blog.
    Google – Preview – A simple tool, does just as its name says.
    Google reckons that this will improve the search process and save you time.

    | Reply Posted 3 years ago
  20. It reduces fats and carb absorption, reduces urge for
    food, stimulates the metabolism promoting fats burning and offers you
    extra vitality. This means thay everybody who makes use
    of Adiphene should shed pounds. Different
    studies have demonstrated the profits of Ginseng Panax Root Extract.

    | Reply Posted 3 years ago
  21. * facebook says:

    If you ailing abundant active in a big city, this
    bold can gives you the feel of accepting your own farm.
    They can join groups and ‘like’ their favorite musicians, TV shows,
    authors and organizations. A large number of people globally practice the use of affirmations
    to further improve their current situations and empower their
    belief systems.

    | Reply Posted 2 years, 11 months ago
  22. It is not my first time to pay a quick visit this site, i am visiting this web page
    dailly and obtain pleasant facts from here every day.

    | Reply Posted 2 years, 11 months ago
  23. What’s up, I desire to subscribe for this blog to obtain most recent updates, thus where can i do it please help.

    | Reply Posted 2 years, 11 months ago
  24. Hey I am so delighted I found your webpage, I really found you by mistake,
    while I was searching on Askjeeve for something else, Nonetheless I am here now and
    would just like to say thank you for a remarkable post and a all round thrilling blog (I also love the theme/design),
    I don’t have time to read through it all at the moment but I have book-marked it and also added your RSS feeds, so
    when I have time I will be back to read a great deal more,
    Please do keep up the great job.

    | Reply Posted 2 years, 10 months ago
  25. future, the researchers want to find out whether a combination of several educated in the gastrointestinal tract hormones
    can further enhance the effect of the gastric band. Perhaps the main reason behind this
    though is that you have developed a dependence on food.

    There is a section to discuss the biggest loser show, specific diets,
    and much more.

    | Reply Posted 2 years, 9 months ago
  26. You’ll for certain do not have something to lose with Adiphene,
    thus for those that actually need to slim while not losing their time and power, then Adiphene is that the product for you.
    Perhaps the main reason behind this though is that you have developed a dependence on food.
    Different studies have demonstrated the profits of Ginseng Panax Root Extract.

    | Reply Posted 2 years, 9 months ago
  27. Don’t let fat cost-free or perhaps gentle meals trick anyone; them usually comprise copious amounts
    connected with one more unhealthy element. Individuals who have underlying medical condition should also consult a physician before taking
    this diet pill. Different studies have demonstrated the profits of Ginseng Panax Root Extract.

    | Reply Posted 2 years, 9 months ago
  28. Such are the ingredients of Adiphene that its one finest selling level is the shortage of dangerous uncomfortable side effects.
    Adiphene is the newest and fastest weight reduction supplement in market.
    Indeed Adiphene weight reduction pill is the answer for those who always goes on food regimen however can’t endure the meals carving
    hunger and the irritability gave rise by dieting.

    | Reply Posted 2 years, 9 months ago
    • * Bertie says:

      Furrealz? That’s maorllvusey good to know.

      | Reply Posted 2 years, 5 months ago
  29. You as the online business owner must focus your time and energy on business building activities.
    You must constantly create value to your online customers or niche markets.
    Understand that each reader has different learning style.

    | Reply Posted 2 years, 9 months ago
  30. You’ll for certain do not have something to lose with
    Adiphene, thus for those that actually need to slim while not losing their time
    and power, then Adiphene is that the product for you.
    Adiphene is the newest and fastest weight reduction supplement in market.
    Indeed Adiphene weight reduction pill is the answer for those who always goes
    on food regimen however can’t endure the meals carving hunger and the irritability gave rise by dieting.

    | Reply Posted 2 years, 9 months ago
  31. * arabic news says:

    I pay a quick visit day-to-day some web sites and websites to read articles, however this website presents feature based articles.

    | Reply Posted 2 years, 4 months ago
  32. Aw, this was an extremely nice post. Taking the time and
    actual effort to make a very good article… but what can I say… I put things off a lot
    and don’t manage to get nearly anything done.

    | Reply Posted 2 years ago
  33. Currently it sounds like Drupal is the best blogging platform
    out there right now. (from what I’ve read) Is that what you’re using on your blog?

    | Reply Posted 1 year, 9 months ago


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: