public static byte[] Write(ContentCodeBag bag, ContentNode node) { MemoryStream stream = new MemoryStream (); BinaryWriter writer = new BinaryWriter (stream); Write (bag, node, writer); writer.Flush (); byte[] buf = stream.GetBuffer (); long len = stream.Length; writer.Close (); byte[] ret = new byte[len]; Array.Copy (buf, ret, len); return ret; }
internal static ServerInfo FromNode(ContentNode node) { ServerInfo info = new ServerInfo (); if (node.Name != "dmap.serverinforesponse") return null; foreach (ContentNode child in (node.Value as ContentNode[])) { switch (child.Name) { case "dmap.itemname": info.Name = (string) child.Value; break; case "dmap.authenticationmethod": info.AuthenticationMethod = (AuthenticationMethod) child.Value; break; case "dmap.supportsupdate": info.SupportsUpdate = (byte) child.Value == 1; break; } } return info; }
private void Parse(ContentNode dbNode) { foreach (ContentNode item in (ContentNode[]) dbNode.Value) { switch (item.Name) { case "dmap.itemid": id = (int) item.Value; break; case "dmap.persistentid": persistentId = (long) item.Value; break; case "dmap.itemname": name = (string) item.Value; break; default: break; } } }
private bool IsUpdateResponse(ContentNode node) { return node.Name == "dmap.updateresponse"; }
private int GetCurrentRevision() { ContentNode revNode = ContentParser.Parse(bag, fetcher.Fetch("/update"), "dmap.serverrevision"); return((int)revNode.Value); }
private void ParseSessionId(ContentNode node) { fetcher.SessionId = (int)node.GetChild("dmap.sessionid").Value; }
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++; } } }
private bool IsUpdateResponse(ContentNode node) { return(node.Name == "dmap.updateresponse"); }
private static void Write(ContentCodeBag bag, ContentNode node, BinaryWriter writer) { ContentCode code = bag.Lookup(node.Name); if (code.Equals(ContentCode.Zero)) { throw new ContentException("Failed to get content code for: " + node.Name); } writer.Write(IPAddress.HostToNetworkOrder(code.Number)); switch (code.Type) { case ContentType.Char: writer.Write(IPAddress.HostToNetworkOrder(1)); writer.Write((byte)node.Value); break; case ContentType.Short: writer.Write(IPAddress.HostToNetworkOrder(2)); writer.Write(IPAddress.HostToNetworkOrder((short)node.Value)); break; case ContentType.SignedLong: case ContentType.Long: writer.Write(IPAddress.HostToNetworkOrder(4)); writer.Write(IPAddress.HostToNetworkOrder((int)node.Value)); break; case ContentType.LongLong: writer.Write(IPAddress.HostToNetworkOrder(8)); writer.Write(IPAddress.HostToNetworkOrder((long)node.Value)); break; case ContentType.String: byte[] data = Encoding.UTF8.GetBytes((string)node.Value); writer.Write(IPAddress.HostToNetworkOrder(data.Length)); writer.Write(data); break; case ContentType.Date: writer.Write(IPAddress.HostToNetworkOrder(4)); writer.Write(IPAddress.HostToNetworkOrder(Utility.FromDateTime((DateTime)node.Value))); break; case ContentType.Version: Version version = (Version)node.Value; writer.Write(IPAddress.HostToNetworkOrder(4)); writer.Write((short)IPAddress.HostToNetworkOrder((short)version.Major)); writer.Write((byte)version.Minor); writer.Write((byte)version.Build); break; case ContentType.Container: MemoryStream childStream = new MemoryStream(); BinaryWriter childWriter = new BinaryWriter(childStream); foreach (ContentNode child in (ContentNode[])node.Value) { Write(bag, child, childWriter); } childWriter.Flush(); byte[] bytes = childStream.GetBuffer(); int len = (int)childStream.Length; writer.Write(IPAddress.HostToNetworkOrder(len)); writer.Write(bytes, 0, len); childWriter.Close(); break; default: Console.Error.WriteLine("Cannot write node of type: " + code.Type); break; } }
public static ContentNode Parse(ContentCodeBag bag, byte[] buffer, string root, ref int offset) { ContentNode node = new ContentNode(); int num = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer, offset)); ContentCode code = bag.Lookup(num); if (code.Equals(ContentCode.Zero)) { // probably a buggy server. fallback to our internal code bag code = ContentCodeBag.Default.Lookup(num); } int length = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer, offset + 4)); if (code.Equals(ContentCode.Zero)) { string s = System.Text.ASCIIEncoding.ASCII.GetString(buffer); throw new ContentException(String.Format("Failed to find content code for '{0}'. Data length is {1}; content is {2}", ContentCodeBag.GetStringFormat(num), length, s)); } node.Name = code.Name; switch (code.Type) { case ContentType.Char: node.Value = (byte)buffer[offset + 8]; break; case ContentType.Short: node.Value = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, offset + 8)); break; case ContentType.SignedLong: case ContentType.Long: node.Value = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer, offset + 8)); break; case ContentType.LongLong: node.Value = IPAddress.NetworkToHostOrder(BitConverter.ToInt64(buffer, offset + 8)); break; case ContentType.String: node.Value = Encoding.UTF8.GetString(buffer, offset + 8, length); break; case ContentType.Date: node.Value = Utility.ToDateTime(IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer, offset + 8))); break; case ContentType.Version: int major = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(buffer, offset + 8)); int minor = (int)buffer[offset + 10]; int micro = (int)buffer[offset + 11]; node.Value = new Version(major, minor, micro); break; case ContentType.Container: node.Value = ParseChildren(bag, buffer, offset + 8, length); break; default: throw new ContentException(String.Format("Unknown content type '{0}' for '{1}'", code.Type, code.Name)); } offset += length + 8; if (root != null) { ContentNode rootNode = node.GetChild(root); if (rootNode == null) { throw new ContentException(String.Format("Could not find root node '{0}'", root)); } return(rootNode); } else { return(node); } }
internal ContentNode ToNode() { List <ContentNode> nodes = new List <ContentNode> (); foreach (int number in codes.Keys) { ContentCode code = (ContentCode) codes[number]; List <ContentNode> contents = new List <ContentNode> (); contents.Add (new ContentNode ("dmap.contentcodesnumber", code.Number)); contents.Add (new ContentNode ("dmap.contentcodesname", code.Name)); contents.Add (new ContentNode ("dmap.contentcodestype", code.Type)); ContentNode dict = new ContentNode ("dmap.dictionary", contents); nodes.Add (dict); } ContentNode status = new ContentNode ("dmap.status", 200); return new ContentNode ("dmap.contentcodesresponse", status, nodes); }
private static void Write(ContentCodeBag bag, ContentNode node, BinaryWriter writer) { ContentCode code = bag.Lookup (node.Name); if (code.Equals (ContentCode.Zero)) { throw new ContentException ("Failed to get content code for: " + node.Name); } writer.Write (IPAddress.HostToNetworkOrder (code.Number)); switch (code.Type) { case ContentType.Char: writer.Write (IPAddress.HostToNetworkOrder (1)); writer.Write ((byte) node.Value); break; case ContentType.Short: writer.Write (IPAddress.HostToNetworkOrder (2)); writer.Write (IPAddress.HostToNetworkOrder ((short) node.Value)); break; case ContentType.SignedLong: case ContentType.Long: writer.Write (IPAddress.HostToNetworkOrder (4)); writer.Write (IPAddress.HostToNetworkOrder ((int) node.Value)); break; case ContentType.LongLong: writer.Write (IPAddress.HostToNetworkOrder (8)); writer.Write (IPAddress.HostToNetworkOrder ((long) node.Value)); break; case ContentType.String: byte[] data = Encoding.UTF8.GetBytes ((string) node.Value); writer.Write (IPAddress.HostToNetworkOrder (data.Length)); writer.Write (data); break; case ContentType.Date: writer.Write (IPAddress.HostToNetworkOrder (4)); writer.Write (IPAddress.HostToNetworkOrder (Utility.FromDateTime ((DateTime) node.Value))); break; case ContentType.Version: Version version = (Version) node.Value; writer.Write (IPAddress.HostToNetworkOrder (4)); writer.Write ((short) IPAddress.HostToNetworkOrder ((short) version.Major)); writer.Write ((byte) version.Minor); writer.Write ((byte) version.Build); break; case ContentType.Container: MemoryStream childStream = new MemoryStream (); BinaryWriter childWriter = new BinaryWriter (childStream); foreach (ContentNode child in (ContentNode[]) node.Value) { Write (bag, child, childWriter); } childWriter.Flush (); byte[] bytes = childStream.GetBuffer (); int len = (int) childStream.Length; writer.Write (IPAddress.HostToNetworkOrder (len)); writer.Write (bytes, 0, len); childWriter.Close (); break; default: Console.Error.WriteLine ("Cannot write node of type: " + code.Type); break; } }
public static ContentNode Parse(ContentCodeBag bag, byte[] buffer, string root, ref int offset) { ContentNode node = new ContentNode (); int num = IPAddress.NetworkToHostOrder (BitConverter.ToInt32 (buffer, offset)); ContentCode code = bag.Lookup (num); if (code.Equals (ContentCode.Zero)) { // probably a buggy server. fallback to our internal code bag code = ContentCodeBag.Default.Lookup (num); } int length = IPAddress.NetworkToHostOrder (BitConverter.ToInt32 (buffer, offset + 4)); if (code.Equals (ContentCode.Zero)) { string s = System.Text.ASCIIEncoding.ASCII.GetString (buffer); throw new ContentException (String.Format ("Failed to find content code for '{0}'. Data length is {1}; content is {2}", ContentCodeBag.GetStringFormat (num), length, s)); } node.Name = code.Name; switch (code.Type) { case ContentType.Char: node.Value = (byte) buffer[offset + 8]; break; case ContentType.Short: node.Value = IPAddress.NetworkToHostOrder (BitConverter.ToInt16 (buffer, offset + 8)); break; case ContentType.SignedLong: case ContentType.Long: node.Value = IPAddress.NetworkToHostOrder (BitConverter.ToInt32 (buffer, offset + 8)); break; case ContentType.LongLong: node.Value = IPAddress.NetworkToHostOrder (BitConverter.ToInt64 (buffer, offset + 8)); break; case ContentType.String: node.Value = Encoding.UTF8.GetString (buffer, offset + 8, length); break; case ContentType.Date: node.Value = Utility.ToDateTime (IPAddress.NetworkToHostOrder (BitConverter.ToInt32 (buffer, offset + 8))); break; case ContentType.Version: int major = IPAddress.NetworkToHostOrder (BitConverter.ToInt16 (buffer, offset + 8)); int minor = (int) buffer[offset + 10]; int micro = (int) buffer[offset + 11]; node.Value = new Version (major, minor, micro); break; case ContentType.Container: node.Value = ParseChildren (bag, buffer, offset + 8, length); break; default: throw new ContentException (String.Format ("Unknown content type '{0}' for '{1}'", code.Type, code.Name)); } offset += length + 8; if (root != null) { ContentNode rootNode = node.GetChild (root); if (rootNode == null) throw new ContentException (String.Format ("Could not find root node '{0}'", root)); return rootNode; } else { return node; } }
internal static Track FromNode(ContentNode node) { Track track = new Track(); foreach (ContentNode field in (ContentNode[])node.Value) { switch (field.Name) { case "dmap.itemid": track.id = (int)field.Value; break; case "daap.songartist": track.artist = (string)field.Value; break; case "dmap.itemname": track.title = (string)field.Value; break; case "daap.songalbum": track.album = (string)field.Value; break; case "daap.songtime": track.duration = TimeSpan.FromMilliseconds((int)field.Value); break; case "daap.songformat": track.format = (string)field.Value; break; case "daap.songgenre": track.genre = (string)field.Value; break; case "daap.songsize": track.size = (int)field.Value; break; case "daap.songtrackcount": track.trackCount = (short)field.Value; break; case "daap.songtracknumber": track.trackNumber = (short)field.Value; break; case "daap.bitrate": track.bitrate = (short)field.Value; break; case "daap.songdateadded": track.dateAdded = (DateTime)field.Value; break; case "daap.songdatemodified": track.dateModified = (DateTime)field.Value; break; default: break; } } return(track); }
internal Database(Client client, ContentNode dbNode) : this() { this.client = client; Parse (dbNode); }
internal Database(Client client, ContentNode dbNode) : this() { this.client = client; Parse(dbNode); }
private void ParseSessionId(ContentNode node) { fetcher.SessionId = (int) node.GetChild ("dmap.sessionid").Value; }