Thursday 4 October 2012

Ringtones on WP7 using XNA

So, I did a sample for a friend a while back on how to add ringtones to a WP7 title that has been written in XNA. As we all know if you are writing it in Silverlight, there are plenty of samples out there, but I never spotted one for XNA. So I wrote this, as ever I may well be going about it in a cack handed manner, so please feel free to comment and/or correct anything you see in this post by adding a comment below. Thanks.
For this sample, the first thing I did was create some ring tones, now I did this in a very simplistic manor, I got a copy of Hammerhead and just used a few samples off that, 4 ring tones.
Now in XNA, we normally just throw our assets into the content pipeline and it sorts it all out for us, but due to the way MS have implemented ringtones we can’t just do that in XNA, we have to have them in the content pipeline as wav’s and as they are intended to be in the game project it’s self as mp3’s. This is all due to the lack of control XNA has compared with the Silverlight implementation over the MediaPlayer, read into that what you will…
[EDIT]Just found this post, which will get around this :S [/EDIT]
So, with my 4 new super duper ring tones my project(s) look like this:



Here is a quick shot of the code in my Update method
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            {
                // If it's paused, start it back up again...
                if (MediaPlayer.State == MediaState.Paused)
                    MediaPlayer.Resume();

                this.Exit();
            }

            // First of all, and this is probably the only situation you can do this
            // Pause the media player if it is playing, this will also pause the
            // users own music, might be work you wanrning them before you enter
            // your ring tone screen
            if (MediaPlayer.State == MediaState.Playing)
            {
                MediaPlayer.Pause();
            }
When playing your ring tones, you don’t want the media player playing at the same time, this situation is probably the only time you can just pause the media player…
I am not going to go over the code that renders the ringtone options, just show you the method used to play and to save the ringtones to the device.
Play a Ringtone
        class ScreenSprite { }
        public void playThisRingTone(object sender)
        {
            ScreenSprite thisRT = (ScreenSprite)sender;

            if (playingRTNo != -1)
            {
                ringTonesText[playingRTNo].Shadow = true;
                ringTonesText[playingRTNo].Color = Color.Red;
            }

            int rt = int.Parse(thisRT.Tag);
            playingRTNo = rt;

            // Play the RT.
            if (playingRT != null && playingRT.State == SoundState.Playing)
                playingRT.Stop();

            playingRT = Content.Load<SoundEffect>(string.Format("Audio/Ringtones/RingTone {0}", rt + 1)).CreateInstance();

            ringTonesText[rt].Shadow = false;
            ringTonesText[rt].Color = Color.DarkRed;

            playingRT.Play();
        }
The sender is the object that has been taped, so the play button for a given ring tone, this has a tag with the ring tone number to be played, you could put the full ring tone name in there if you liked. I then get that into a SoundEffect object and play it, this is a global SoundEffect object as I only want to play 1 at any given time and may want to stop it mid play.


Save a Ringtone
        public void SaveRingTone(string ringtone)
        {
            try
            {
                if (!Guide.IsTrialMode)
                {
                    SaveRingtoneTask srt = new SaveRingtoneTask();
                    srt.Completed += new EventHandler<TaskEventArgs>(srt_Completed);

                    srt.Source = new Uri(string.Format("appdata:/{0}", ringtone));
                    srt.DisplayName = "";
                    srt.IsShareable = true;
                    srt.Show();
                }
                else
                {
                    dialogButtons.Clear();
                    dialogButtons.Add("OK");

                    Guide.BeginShowMessageBox("Trial Mode",
                                      "Purchase the full game to get the ringtones",
                                      dialogButtons, 0, MessageBoxIcon.Alert, null, null);
                }
            }
            catch (Exception e)
            {
                dialogButtons.Clear();
                dialogButtons.Add("OK");

                Guide.BeginShowMessageBox("Error",
                                  e.Message,
                                  dialogButtons, 0, MessageBoxIcon.Alert, null, null);
            }
        }

        void srt_Completed(object sender, TaskEventArgs e)
        {
            switch (e.TaskResult)
            {
                //Logic for when the ringtone was saved successfully
                case TaskResult.OK:
                    dialogButtons.Clear();
                    dialogButtons.Add("OK");

                    Guide.BeginShowMessageBox("Ringtone Saved",
                                      "The ringtone was saved successfully",
                              dialogButtons, 0, MessageBoxIcon.Alert, null, null);

                    break;

                //Logic for when the task was cancelled by the user
                case TaskResult.Cancel:
                    break;

                //Logic for when the ringtone could not be saved
                case TaskResult.None:
                    dialogButtons.Clear();
                    dialogButtons.Add("OK");

                    Guide.BeginShowMessageBox("Can't Save..",
                                      "Can't save this ringtone",
                              dialogButtons, 0, MessageBoxIcon.Alert, null, null);
                    break;
            }
        }
The method to save a ring tone, first checks we are not in trial, and if not then allows the user to save the ringtone, this is why I put the mp3’s in the game project so they are accessible from “appdata:/”. The SaveRingToneTask Show method is then called:


The srt_Completed call back method then informs the user if it’s all gone well.
So that’s about it, my way of saving/playing ringtones on WP7 in XNA. As ever, comments are more than welcome…
Source code can be found here [Not yet uloaded]












No comments:

Post a Comment