1 |
// Decentralized Media Client |
2 |
// |
3 |
// Douglas Thrift |
4 |
// |
5 |
// $Id$ |
6 |
|
7 |
using Shell32; |
8 |
using System; |
9 |
using System.Collections.Generic; |
10 |
using System.Net; |
11 |
using System.IO; |
12 |
using System.Text; |
13 |
using System.Windows.Forms; |
14 |
using System.Xml; |
15 |
|
16 |
public class DecentralizedMediaClient |
17 |
{ |
18 |
public DecentralizedMediaClient() |
19 |
{ |
20 |
Application.EnableVisualStyles(); |
21 |
|
22 |
Extensions(); |
23 |
|
24 |
/*Shell shell = new ShellClass(); |
25 |
retry: Folder2 folder = (Folder2)shell.BrowseForFolder(0, "Select a media folder", 0, null); |
26 |
|
27 |
if (folder != null) |
28 |
if (folder.Self.IsFileSystem) |
29 |
{ |
30 |
folders.Add(folder.Self.Path, new MediaFolder(new DirectoryInfo(folder.Self.Path), extensions)); |
31 |
|
32 |
Media(); |
33 |
} |
34 |
else if (MessageBox.Show("The selected folder is not a file system directory.", "", MessageBoxButtons.RetryCancel, MessageBoxIcon.Asterisk) == DialogResult.Retry) |
35 |
goto retry;*/ |
36 |
|
37 |
string folder = @"C:\DouglasThrift.net\DecentralizedMedia\Media"; |
38 |
|
39 |
folders[folder] = new MediaFolder(new DirectoryInfo(folder), extensions); |
40 |
|
41 |
Media(); |
42 |
|
43 |
listener.Prefixes.Add("http://+:6996/"); |
44 |
|
45 |
listener.IgnoreWriteExceptions = true; |
46 |
|
47 |
listener.Start(); |
48 |
|
49 |
Console.WriteLine("Listening..."); |
50 |
|
51 |
while (true) |
52 |
{ |
53 |
HttpListenerContext context = listener.GetContext(); |
54 |
|
55 |
Serve(context.Request, context.Response); |
56 |
} |
57 |
} |
58 |
|
59 |
public static void Main(string[] args) |
60 |
{ |
61 |
DecentralizedMediaClient client = new DecentralizedMediaClient(); |
62 |
} |
63 |
|
64 |
private List<string> extensions = new List<string>(); |
65 |
private SortedDictionary<string, MediaFolder> folders = new SortedDictionary<string, MediaFolder>(); |
66 |
private Dictionary<string, MediaFolder> shares = new Dictionary<string, MediaFolder>(); |
67 |
private HttpListener listener = new HttpListener(); |
68 |
|
69 |
private void Extensions() |
70 |
{ |
71 |
Console.WriteLine("EXTENSIONS"); |
72 |
|
73 |
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://daemon:6996/"); |
74 |
|
75 |
request.Method = "EXTENSIONS"; |
76 |
|
77 |
HttpWebResponse response = (HttpWebResponse)request.GetResponse(); |
78 |
StreamReader reader = new StreamReader(response.GetResponseStream()); |
79 |
string extension; |
80 |
|
81 |
while ((extension = reader.ReadLine()) != null) |
82 |
extensions.Add(extension); |
83 |
} |
84 |
|
85 |
private void Media() |
86 |
{ |
87 |
Console.WriteLine("MEDIA"); |
88 |
|
89 |
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://daemon:6996/"); |
90 |
|
91 |
request.Method = "MEDIA"; |
92 |
request.SendChunked = true; |
93 |
|
94 |
XmlWriterSettings settings = new XmlWriterSettings(); |
95 |
|
96 |
settings.Indent = true; |
97 |
|
98 |
Stream stream = request.GetRequestStream(); |
99 |
XmlWriter writer = XmlWriter.Create(stream, settings); |
100 |
|
101 |
writer.WriteStartDocument(); |
102 |
writer.WriteStartElement("media"); |
103 |
|
104 |
foreach (KeyValuePair<string, MediaFolder> folder in folders) |
105 |
{ |
106 |
string share = String.Format("{0:x}", folder.Key.GetHashCode()); |
107 |
|
108 |
shares[share] = folder.Value; |
109 |
|
110 |
Media(folder.Value, share, writer); |
111 |
} |
112 |
|
113 |
writer.WriteEndDocument(); |
114 |
writer.Close(); |
115 |
// XXX: for some reason the XmlWriter's Close() doesn't work right |
116 |
stream.Close(); |
117 |
request.GetResponse().Close(); |
118 |
} |
119 |
|
120 |
private void Media(MediaFolder folder, string path, XmlWriter writer) |
121 |
{ |
122 |
writer.WriteStartElement("folder"); |
123 |
writer.WriteStartElement("path"); |
124 |
writer.WriteString(path); |
125 |
writer.WriteEndElement(); |
126 |
|
127 |
foreach (KeyValuePair<string, MediaFile> file_ in folder.files) |
128 |
{ |
129 |
writer.WriteStartElement("file"); |
130 |
writer.WriteStartElement("path"); |
131 |
writer.WriteString(file_.Key); |
132 |
writer.WriteEndElement(); |
133 |
|
134 |
MediaFile file = file_.Value; |
135 |
|
136 |
if (file.artist != null && file.artist != "") |
137 |
{ |
138 |
writer.WriteStartElement("artist"); |
139 |
writer.WriteString(file.artist); |
140 |
writer.WriteEndElement(); |
141 |
} |
142 |
|
143 |
if (file.title != null && file.title != "") |
144 |
{ |
145 |
writer.WriteStartElement("title"); |
146 |
writer.WriteString(file.title); |
147 |
writer.WriteEndElement(); |
148 |
} |
149 |
|
150 |
if (file.album != null && file.album != "") |
151 |
{ |
152 |
writer.WriteStartElement("album"); |
153 |
writer.WriteString(file.album); |
154 |
writer.WriteEndElement(); |
155 |
} |
156 |
|
157 |
if (file.genre != null && file.album != "") |
158 |
{ |
159 |
writer.WriteStartElement("genre"); |
160 |
writer.WriteString(file.genre); |
161 |
writer.WriteEndElement(); |
162 |
} |
163 |
|
164 |
writer.WriteEndElement(); |
165 |
} |
166 |
|
167 |
foreach (KeyValuePair<string, MediaFolder> folder_ in folder.folders) |
168 |
Media(folder_.Value, folder_.Key, writer); |
169 |
|
170 |
writer.WriteEndElement(); |
171 |
} |
172 |
|
173 |
private void Serve(HttpListenerRequest request, HttpListenerResponse response) |
174 |
{ |
175 |
Console.WriteLine(request.Url.LocalPath); |
176 |
|
177 |
response.SendChunked = true; |
178 |
|
179 |
char[] slash = { '/' }; |
180 |
string[] path = request.Url.LocalPath.Split(slash, 2, StringSplitOptions.RemoveEmptyEntries); |
181 |
MediaFolder share; |
182 |
Stream stream; |
183 |
|
184 |
if (path.Length == 2 && shares.TryGetValue(path[0], out share) && (stream = share.Get(path[1])) != null) |
185 |
{ |
186 |
byte[] buffer = new byte[1024]; |
187 |
int count; |
188 |
|
189 |
while ((count = stream.Read(buffer, 0, buffer.Length)) != 0) |
190 |
response.OutputStream.Write(buffer, 0, count); |
191 |
|
192 |
stream.Close(); |
193 |
} |
194 |
else |
195 |
response.StatusCode = 404; |
196 |
|
197 |
response.OutputStream.Close(); |
198 |
response.Close(); |
199 |
} |
200 |
} |