예제 #1
0
        private int WaitForRevision(int currentRevision)
        {
            ContentNode revNode = ContentParser.Parse(bag, fetcher.Fetch("/update",
                                                                         "revision-number=" + currentRevision));

            return((int)revNode.GetChild("dmap.serverrevision").Value);
        }
예제 #2
0
        public void Login(string username, string password)
        {
            fetcher.Username = username;
            fetcher.Password = password;

            try {
                bag = ContentCodeBag.ParseCodes(fetcher.Fetch("/content-codes"));
                ContentNode node = ContentParser.Parse(bag, fetcher.Fetch("/login"));
                ParseSessionId(node);

                FetchDatabases();
                Refresh();

                if (serverInfo.SupportsUpdate)
                {
                    updateRunning = true;
                    Thread thread = new Thread(UpdateLoop);
                    thread.Name         = "DAAP";
                    thread.IsBackground = true;
                    thread.Start();
                }
            } catch (WebException e) {
                if (e.Response != null && (e.Response as HttpWebResponse).StatusCode == HttpStatusCode.Unauthorized)
                {
                    throw new AuthenticationException("Username or password incorrect");
                }
                else
                {
                    throw new LoginException("Failed to login", e);
                }
            } catch (Exception e) {
                throw new LoginException("Failed to login", e);
            }
        }
예제 #3
0
        public Client(IPAddress address, UInt16 port)
        {
            this.address = address;
            this.port    = port;
            fetcher      = new ContentFetcher(address, port);

            ContentNode node = ContentParser.Parse(ContentCodeBag.Default, fetcher.Fetch("/server-info"));

            serverInfo = ServerInfo.FromNode(node);
        }
예제 #4
0
        public static ContentCodeBag ParseCodes(byte[] buffer)
        {
            ContentCodeBag bag = new ContentCodeBag();

            // add some codes to bootstrap us
            bag.AddCode("mccr", "dmap.contentcodesresponse", ContentType.Container);
            bag.AddCode("mdcl", "dmap.dictionary", ContentType.Container);
            bag.AddCode("mcnm", "dmap.contentcodesnumber", ContentType.Long);
            bag.AddCode("mcna", "dmap.contentcodesname", ContentType.String);
            bag.AddCode("mcty", "dmap.contentcodestype", ContentType.Short);
            bag.AddCode("mstt", "dmap.status", ContentType.Long);

            // some photo-specific codes
            bag.AddCode("ppro", "dpap.protocolversion", ContentType.Long);
            bag.AddCode("pret", "dpap.blah", ContentType.Container);

            ContentNode node = ContentParser.Parse(bag, buffer);

            foreach (ContentNode dictNode in (node.Value as ContentNode[]))
            {
                if (dictNode.Name != "dmap.dictionary")
                {
                    continue;
                }

                ContentCode code = new ContentCode();

                foreach (ContentNode item in (dictNode.Value as ContentNode[]))
                {
                    switch (item.Name)
                    {
                    case "dmap.contentcodesnumber":
                        code.Number = (int)item.Value;
                        break;

                    case "dmap.contentcodesname":
                        code.Name = (string)item.Value;
                        break;

                    case "dmap.contentcodestype":
                        code.Type = (ContentType)Enum.ToObject(typeof(ContentType), (short)item.Value);
                        break;
                    }
                }

                bag.codes[code.Number] = code;
            }

            return(bag);
        }
예제 #5
0
        private void RefreshTracks(string revquery)
        {
            byte[] tracksData = client.Fetcher.Fetch(String.Format("/databases/{0}/items", id),
                                                     TrackQuery + "&" + revquery);
            ContentNode tracksNode = ContentParser.Parse(client.Bag, tracksData);

            if (IsUpdateResponse(tracksNode))
            {
                return;
            }

            // handle track additions/changes
            foreach (ContentNode trackNode in (ContentNode[])tracksNode.GetChild("dmap.listing").Value)
            {
                Track track    = Track.FromNode(trackNode);
                Track existing = LookupTrackById(track.Id);

                if (existing == null)
                {
                    AddTrack(track);
                }
                else
                {
                    existing.Update(track);
                }
            }

            if ((byte)tracksNode.GetChild("dmap.updatetype").Value == 1)
            {
                // handle track deletions
                ContentNode deleteList = tracksNode.GetChild("dmap.deletedidlisting");

                if (deleteList != null)
                {
                    foreach (ContentNode deleted in (ContentNode[])deleteList.Value)
                    {
                        Track track = LookupTrackById((int)deleted.Value);

                        if (track != null)
                        {
                            RemoveTrack(track);
                        }
                    }
                }
            }
        }
예제 #6
0
        private void FetchDatabases()
        {
            ContentNode dbnode = ContentParser.Parse(bag, fetcher.Fetch("/databases"));

            foreach (ContentNode child in (ContentNode[])dbnode.Value)
            {
                if (child.Name != "dmap.listing")
                {
                    continue;
                }

                foreach (ContentNode item in (ContentNode[])child.Value)
                {
                    Database db = new Database(this, item);
                    databases.Add(db);
                }
            }
        }
예제 #7
0
        private void RefreshPlaylists(string revquery)
        {
            byte[] playlistsData;

            try {
                playlistsData = client.Fetcher.Fetch(String.Format("/databases/{0}/containers", id), revquery);
            } catch (WebException) {
                return;
            }

            ContentNode playlistsNode = ContentParser.Parse(client.Bag, playlistsData);

            if (IsUpdateResponse(playlistsNode))
            {
                return;
            }

            // handle playlist additions/changes
            List <int> plids = new List <int> ();

            foreach (ContentNode playlistNode in (ContentNode[])playlistsNode.GetChild("dmap.listing").Value)
            {
                Playlist pl = Playlist.FromNode(playlistNode);

                if (pl != null)
                {
                    plids.Add(pl.Id);
                    Playlist existing = LookupPlaylistById(pl.Id);

                    if (existing == null)
                    {
                        AddPlaylist(pl);
                    }
                    else
                    {
                        existing.Update(pl);
                    }
                }
            }

            // delete playlists that no longer exist
            foreach (Playlist pl in new List <Playlist> (playlists))
            {
                if (!plids.Contains(pl.Id))
                {
                    RemovePlaylist(pl);
                }
            }

            plids = null;

            // add/remove tracks in the playlists
            foreach (Playlist pl in playlists)
            {
                byte [] playlistTracksData = client.Fetcher.Fetch(String.Format(
                                                                      "/databases/{0}/containers/{1}/items", id, pl.Id), String.Format("meta=dmap.itemid,dmap.containeritemid&{0}", revquery)
                                                                  );
                ContentNode playlistTracksNode = ContentParser.Parse(client.Bag, playlistTracksData);

                if (IsUpdateResponse(playlistTracksNode))
                {
                    return;
                }

                if ((byte)playlistTracksNode.GetChild("dmap.updatetype").Value == 1)
                {
                    // handle playlist track deletions
                    ContentNode deleteList = playlistTracksNode.GetChild("dmap.deletedidlisting");

                    if (deleteList != null)
                    {
                        foreach (ContentNode deleted in (ContentNode[])deleteList.Value)
                        {
                            int index = pl.LookupIndexByContainerId((int)deleted.Value);

                            if (index < 0)
                            {
                                continue;
                            }

                            pl.RemoveAt(index);
                        }
                    }
                }

                // add new tracks, or reorder existing ones

                int plindex = 0;
                foreach (ContentNode plTrackNode in (ContentNode[])playlistTracksNode.GetChild("dmap.listing").Value)
                {
                    Track pltrack     = null;
                    int   containerId = 0;
                    Track.FromPlaylistNode(this, plTrackNode, out pltrack, out containerId);

                    if (pl[plindex] != null && pl.GetContainerId(plindex) != containerId)
                    {
                        pl.RemoveAt(plindex);
                        pl.InsertTrack(plindex, pltrack, containerId);
                    }
                    else if (pl[plindex] == null)
                    {
                        pl.InsertTrack(plindex, pltrack, containerId);
                    }

                    plindex++;
                }
            }
        }
예제 #8
0
        private int GetCurrentRevision()
        {
            ContentNode revNode = ContentParser.Parse(bag, fetcher.Fetch("/update"), "dmap.serverrevision");

            return((int)revNode.Value);
        }