private async Task <bool> GetPlayStatusUpdateAsync(CancellationToken cancellationToken)
        {
            // Do not pass the cancellation token to the HTTP request since canceling a request will cause iTunes to close the current session.
            DacpRequest request = new DacpRequest("/ctrl-int/1/playstatusupdate");

            request.QueryParameters["revision-number"] = _playStatusRevisionNumber.ToString();

            try
            {
                var response = await SendRequestAsync(request).ConfigureAwait(false);

                // Do we still need to process this response?
                if (cancellationToken.IsCancellationRequested)
                {
                    return(false);
                }

                // Process response
                var nodes = DacpNodeDictionary.Parse(response.Nodes);
                _playStatusRevisionNumber = nodes.GetInt("cmsr");

                // Current item and container IDs
                if (nodes.ContainsKey("canp"))
                {
                    byte[] value = nodes["canp"];

                    byte[] dbID            = { value[0], value[1], value[2], value[3] };
                    byte[] containerID     = { value[4], value[5], value[6], value[7] };
                    byte[] containerItemID = { value[8], value[9], value[10], value[11] };
                    byte[] itemID          = { value[12], value[13], value[14], value[15] };
                    CurrentDatabaseID      = dbID.GetInt32Value();
                    CurrentContainerID     = containerID.GetInt32Value();
                    CurrentContainerItemID = containerItemID.GetInt32Value();
                    CurrentItemID          = itemID.GetInt32Value();
                }
                else
                {
                    CurrentDatabaseID      = 0;
                    CurrentContainerID     = 0;
                    CurrentContainerItemID = 0;
                    CurrentItemID          = 0;
                }
                CurrentItemSignature = string.Format("{0}|{1}|{2}|{3}", CurrentDatabaseID, CurrentContainerID, CurrentContainerItemID, CurrentItemID);

                // Current item info
                CurrentArtistName        = nodes.GetString("cana");
                CurrentAlbumName         = nodes.GetString("canl");
                CurrentSongName          = nodes.GetString("cann");
                CurrentAlbumPersistentID = (UInt64)nodes.GetLong("asai");

                // Play state
                CurrentPlayState = (PlayState)nodes.GetByte("caps");

                // Track time
                UpdateTrackTime(nodes.GetInt("cast"), nodes.GetNullableInt("cant"));

                // Shuffle
                int caas = nodes.GetInt("caas");
                IsShuffleAvailable = (caas & (1 << 1)) != 0;
                CurrentShuffleMode = nodes.GetBool("cash");

                // Repeat
                int caar = nodes.GetInt("caar");
                IsRepeatOneAvailable = (caar & (1 << 1)) != 0;
                IsRepeatAllAvailable = (caar & (1 << 2)) != 0;
                IsRepeatAvailable    = (IsRepeatOneAvailable || IsRepeatAllAvailable);
                CurrentRepeatMode    = (RepeatMode)nodes.GetByte("carp");

                //CurrentMediaKind = nodes.GetInt("cmmk");
                //ShowUserRating = nodes.GetBool("casu");

                // dacp.visualizer
                IsVisualizerEnabled = nodes.GetBool("cavs");
                // dacp.visualizerenabled
                IsVisualizerAvailable = nodes.GetBool("cave");
                // dacp.fullscreen
                IsFullScreenModeEnabled = nodes.GetBool("cafs");
                // dacp.fullscreenenabled
                IsFullScreenModeAvailable = nodes.GetBool("cafe");

                // iTunes Radio
                iTunesRadioControlState newiTunesRadioControlState = 0;
                if (iTunesRadioDatabase != null && iTunesRadioDatabase.ID == CurrentDatabaseID)
                {
                    IsPlayingiTunesRadio          = true;
                    CurrentiTunesRadioStationName = nodes.GetString("ceNR");

                    // caks = 1 when the next button is disabled, and 2 when it's enabled
                    if (nodes.GetByte("caks") != 1)
                    {
                        newiTunesRadioControlState |= iTunesRadioControlState.NextButtonEnabled;
                    }

                    // "aelb" indicates whether the star button (iTunes Radio menu) should be enabled, but this only seems to be set to true
                    // when connected via Home Sharing. This parameter is missing when an ad is playing, so use this to determine whether
                    // the menu should be enabled.
                    if (nodes.ContainsKey("aelb"))
                    {
                        newiTunesRadioControlState |= iTunesRadioControlState.MenuEnabled;
                    }

                    if (nodes.GetByte("aels") == 2)
                    {
                        newiTunesRadioControlState |= iTunesRadioControlState.CurrentSongFavorited;
                    }
                }
                else
                {
                    IsPlayingiTunesRadio = false;
                }

                CurrentiTunesRadioControlState = newiTunesRadioControlState;

                IsTrackTimePositionBarEnabled = nodes.GetBool("casc", true);

                // Genius Shuffle
                IsPlayingGeniusShuffle = nodes.GetBool("ceGs");
                // There are two other nodes related to Genius Shuffle, "ceGS" and "aeGs" (currently unknown)

                if (CurrentPlayState == PlayState.FastForward || CurrentPlayState == PlayState.Rewind)
                {
                    BeginRepeatedTrackTimeRequests();
                }

                await GetVolumeLevelAsync().ConfigureAwait(false);
                await GetSpeakersAsync().ConfigureAwait(false);

                //var volumeTask = UpdateCurrentVolumeLevelAsync();
                //var userRatingTask = UpdateCurrentSongUserRatingAsync();
                //var playQueueTask = UpdatePlayQueueContentsAsync();

                //Task[] tasks = new[] { volumeTask, userRatingTask, playQueueTask };

#if WP7
                //await TaskEx.WhenAll(tasks).ConfigureAwait(false);
#else
                //await Task.WhenAll(tasks).ConfigureAwait(false);
#endif

                //SubmitGetSpeakersRequest();

                PlayStatusUpdated.RaiseOnUIThread(this, new EventArgs());
            }
            catch { return(false); }
            return(true);
        }
        private async Task <bool> GetSpeakersAsync()
        {
            DacpRequest request = new DacpRequest("/ctrl-int/1/getspeakers");

            try
            {
                var response = await SendRequestAsync(request).ConfigureAwait(false);

                var speakerNodes = response.Nodes.Where(n => n.Key == "mdcl").Select(n => DacpNodeDictionary.Parse(n.Value)).ToList();

                var speakers = Speakers;

                // Determine whether we need to replace the list of speakers
                bool replaceSpeakers = false;
                if (speakers == null || speakers.Count != speakerNodes.Count)
                {
                    replaceSpeakers = true;
                }
                else
                {
                    // Determine whether we still have the same speaker IDs
                    for (int i = 0; i < speakers.Count; i++)
                    {
                        if (speakers[i].ID != (UInt64)speakerNodes[i].GetLong("msma"))
                        {
                            replaceSpeakers = true;
                            break;
                        }
                    }
                }

                // Create the new list of speakers or update the existing speakers
                if (replaceSpeakers)
                {
                    Speakers = speakerNodes.Select(n => new AirPlaySpeaker(this, n)).ToList();
                }
                else
                {
                    for (int i = 0; i < speakers.Count; i++)
                    {
                        speakers[i].ProcessNodes(speakerNodes[i]);
                    }
                }
            }
            catch { return(false); }
            return(true);
        }
Beispiel #3
0
 public AirPlaySpeaker(DacpClient client, DacpNodeDictionary nodes)
 {
     _client = client;
     ProcessNodes(nodes);
 }
 internal Task <IDacpList> GetAlphaGroupedListAsync <T>(DacpRequest request, Func <DacpNodeDictionary, T> itemGenerator, string listKey = DacpUtility.DefaultListKey)
 {
     return(GetAlphaGroupedListAsync(request, b => itemGenerator(DacpNodeDictionary.Parse(b)), listKey));
 }
Beispiel #5
0
 protected virtual void ProcessNodes(DacpNodeDictionary nodes)
 {
     ID           = nodes.GetInt("miid");
     PersistentID = (UInt64)nodes.GetLong("mper");
     Name         = nodes.GetString("minm");
 }
Beispiel #6
0
 public DacpElement(DacpClient client, DacpNodeDictionary nodes)
 {
     Client = client;
     ProcessNodes(nodes);
 }
Beispiel #7
0
 public static IEnumerable <T> GetItemsFromNodes <T>(IEnumerable <DacpNode> nodes, Func <DacpNodeDictionary, T> itemGenerator, string listKey = DefaultListKey)
 {
     return(GetItemsFromNodes(nodes, d => itemGenerator(DacpNodeDictionary.Parse(d)), listKey));
 }
Beispiel #8
0
 public static IEnumerable <T> GetItemsFromNodes <T>(byte[] data, Func <DacpNodeDictionary, T> itemGenerator, string listKey = DefaultListKey)
 {
     return(GetItemsFromNodes(GetResponseNodes(data), d => itemGenerator(DacpNodeDictionary.Parse(d)), listKey));
 }
Beispiel #9
0
 public static IDacpList GetAlphaGroupedDacpList <T>(IEnumerable <DacpNode> nodes, Func <DacpNodeDictionary, T> itemGenerator, out List <T> items, string listKey = DefaultListKey, bool useGroupMinimums = true)
 {
     return(GetAlphaGroupedDacpList(nodes, d => itemGenerator(DacpNodeDictionary.Parse(d)), out items, listKey, useGroupMinimums));
 }