diff options
author | Mike Crute <mcrute@gmail.com> | 2015-07-29 18:38:22 -0700 |
---|---|---|
committer | Mike Crute <mcrute@gmail.com> | 2015-07-29 18:38:22 -0700 |
commit | 53335ce936e758b816cce584665d1d55914b4ef4 (patch) | |
tree | 3822198638830ea0894ba06136a0e29cea7c05b9 /src/parse_smart_playlist.py | |
download | audiocloud-53335ce936e758b816cce584665d1d55914b4ef4.tar.bz2 audiocloud-53335ce936e758b816cce584665d1d55914b4ef4.tar.xz audiocloud-53335ce936e758b816cce584665d1d55914b4ef4.zip |
Diffstat (limited to 'src/parse_smart_playlist.py')
-rw-r--r-- | src/parse_smart_playlist.py | 636 |
1 files changed, 636 insertions, 0 deletions
diff --git a/src/parse_smart_playlist.py b/src/parse_smart_playlist.py new file mode 100644 index 0000000..0bfde9d --- /dev/null +++ b/src/parse_smart_playlist.py | |||
@@ -0,0 +1,636 @@ | |||
1 | # // http://banshee-itunes-import-plugin.googlecode.com/svn/trunk/ | ||
2 | # using System; | ||
3 | # using System.Collections.Generic; | ||
4 | # using System.Text; | ||
5 | # using Banshee.SmartPlaylist; | ||
6 | # | ||
7 | # namespace Banshee.Plugins.iTunesImporter | ||
8 | # { | ||
9 | # internal struct SmartPlaylist | ||
10 | # { | ||
11 | # public string Query, Ignore, OrderBy, Name, Output; | ||
12 | # public uint LimitNumber; | ||
13 | # public byte LimitMethod; | ||
14 | # } | ||
15 | # | ||
16 | # internal static partial class SmartPlaylistParser | ||
17 | # { | ||
18 | # private delegate bool KindEvalDel(Kind kind, string query); | ||
19 | # | ||
20 | # // INFO OFFSETS | ||
21 | # // | ||
22 | # // Offsets for bytes which... | ||
23 | # const int MATCHBOOLOFFSET = 1; // determin whether logical matching is to be performed - Absolute offset | ||
24 | # const int LIMITBOOLOFFSET = 2; // determin whether results are limited - Absolute offset | ||
25 | # const int LIMITMETHODOFFSET = 3; // determin by what criteria the results are limited - Absolute offset | ||
26 | # const int SELECTIONMETHODOFFSET = 7; // determin by what criteria limited playlists are populated - Absolute offset | ||
27 | # const int LIMITINTOFFSET = 11; // determin the limited - Absolute offset | ||
28 | # const int SELECTIONMETHODSIGNOFFSET = 13;// determin whether certain selection methods are "most" or "least" - Absolute offset | ||
29 | # | ||
30 | # // CRITERIA OFFSETS | ||
31 | # // | ||
32 | # // Offsets for bytes which... | ||
33 | # const int LOGICTYPEOFFSET = 15; // determin whether all or any criteria must match - Absolute offset | ||
34 | # const int FIELDOFFSET = 139; // determin what is being matched (Artist, Album, &c) - Absolute offset | ||
35 | # const int LOGICSIGNOFFSET = 1; // determin whether the matching rule is positive or negative (e.g., is vs. is not) - Relative offset from FIELDOFFSET | ||
36 | # const int LOGICRULEOFFSET = 4; // determin the kind of logic used (is, contains, begins, &c) - Relative offset from FIELDOFFSET | ||
37 | # const int STRINGOFFSET = 54; // begin string data - Relative offset from FIELDOFFSET | ||
38 | # const int INTAOFFSET = 60; // begin the first int - Relative offset from FIELDOFFSET | ||
39 | # const int INTBOFFSET = 24; // begin the second int - Relative offset from INTAOFFSET | ||
40 | # const int TIMEMULTIPLEOFFSET = 76;// begin the int with the multiple of time - Relative offset from FIELDOFFSET | ||
41 | # const int TIMEVALUEOFFSET = 68; // begin the inverse int with the value of time - Relative offset from FIELDOFFSET | ||
42 | # | ||
43 | # const int INTLENGTH = 64; // The length on a int criteria starting at the first int | ||
44 | # static DateTime STARTOFTIME = new DateTime(1904, 1, 1); // Dates are recorded as seconds since Jan 1, 1904 | ||
45 | # | ||
46 | # static bool or, again; | ||
47 | # static string conjunctionOutput, conjunctionQuery, output, query, ignore; | ||
48 | # static int offset, logicSignOffset,logicRulesOffset, stringOffset, intAOffset, intBOffset, | ||
49 | # timeMultipleOffset, timeValueOffset; | ||
50 | # static byte[] info, criteria; | ||
51 | # | ||
52 | # static KindEvalDel KindEval; | ||
53 | # | ||
54 | # public static SmartPlaylist Parse(byte[] i, byte[] c) | ||
55 | # { | ||
56 | # info = i; | ||
57 | # criteria = c; | ||
58 | # SmartPlaylist result = new SmartPlaylist(); | ||
59 | # offset = FIELDOFFSET; | ||
60 | # output = ""; | ||
61 | # query = ""; | ||
62 | # ignore = ""; | ||
63 | # | ||
64 | # if(info[MATCHBOOLOFFSET] == 1) { | ||
65 | # or = (criteria[LOGICTYPEOFFSET] == 1) ? true : false; | ||
66 | # if(or) { | ||
67 | # conjunctionQuery = " OR "; | ||
68 | # conjunctionOutput = " or\n"; | ||
69 | # } else { | ||
70 | # conjunctionQuery = " AND "; | ||
71 | # conjunctionOutput = " and\n"; | ||
72 | # } | ||
73 | # do { | ||
74 | # again = false; | ||
75 | # logicSignOffset = offset + LOGICSIGNOFFSET; | ||
76 | # logicRulesOffset = offset + LOGICRULEOFFSET; | ||
77 | # stringOffset = offset + STRINGOFFSET; | ||
78 | # intAOffset = offset + INTAOFFSET; | ||
79 | # intBOffset = intAOffset + INTBOFFSET; | ||
80 | # timeMultipleOffset = offset + TIMEMULTIPLEOFFSET; | ||
81 | # timeValueOffset = offset + TIMEVALUEOFFSET; | ||
82 | # | ||
83 | # if(Enum.IsDefined(typeof(StringFields), (int)criteria[offset])) { | ||
84 | # ProcessStringField(); | ||
85 | # } else if(Enum.IsDefined(typeof(IntFields), (int)criteria[offset])) { | ||
86 | # ProcessIntField(); | ||
87 | # } else if(Enum.IsDefined(typeof(DateFields), (int)criteria[offset])) { | ||
88 | # ProcessDateField(); | ||
89 | # } else { | ||
90 | # ignore += "Not processed"; | ||
91 | # } | ||
92 | # } | ||
93 | # while(again); | ||
94 | # } | ||
95 | # result.Output = output; | ||
96 | # result.Query = query; | ||
97 | # result.Ignore = ignore; | ||
98 | # if(info[LIMITBOOLOFFSET] == 1) { | ||
99 | # uint limit = BytesToUInt(info, LIMITINTOFFSET); | ||
100 | # result.LimitNumber = (info[LIMITMETHODOFFSET] == (byte)LimitMethods.GB) ? limit * 1024 : limit; | ||
101 | # if(output.Length > 0) { | ||
102 | # output += "\n"; | ||
103 | # } | ||
104 | # output += "Limited to " + limit.ToString() + " " + | ||
105 | # Enum.GetName(typeof(LimitMethods), (int)info[LIMITMETHODOFFSET]) + " selected by "; | ||
106 | # switch(info[LIMITMETHODOFFSET]) { | ||
107 | # case (byte)LimitMethods.Items: | ||
108 | # result.LimitMethod = 0; | ||
109 | # break; | ||
110 | # case (byte)LimitMethods.Minutes: | ||
111 | # result.LimitMethod = 1; | ||
112 | # break; | ||
113 | # case (byte)LimitMethods.Hours: | ||
114 | # result.LimitMethod = 2; | ||
115 | # break; | ||
116 | # case (byte)LimitMethods.MB: | ||
117 | # result.LimitMethod = 3; | ||
118 | # break; | ||
119 | # case (byte)LimitMethods.GB: | ||
120 | # goto case (byte)LimitMethods.MB; | ||
121 | # } | ||
122 | # switch(info[SELECTIONMETHODOFFSET]) { | ||
123 | # case (byte)SelectionMethods.Random: | ||
124 | # output += "random"; | ||
125 | # result.OrderBy = "RANDOM()"; | ||
126 | # break; | ||
127 | # case (byte)SelectionMethods.HighestRating: | ||
128 | # output += "highest rated"; | ||
129 | # result.OrderBy = "Rating DESC"; | ||
130 | # break; | ||
131 | # case (byte)SelectionMethods.LowestRating: | ||
132 | # output += "lowest rated"; | ||
133 | # result.OrderBy = "Rating ASC"; | ||
134 | # break; | ||
135 | # case (byte)SelectionMethods.RecentlyPlayed: | ||
136 | # output += (info[SELECTIONMETHODSIGNOFFSET] == 0) | ||
137 | # ? "most recently played" : "least recently played"; | ||
138 | # result.OrderBy = (info[SELECTIONMETHODSIGNOFFSET] == 0) | ||
139 | # ? "LastPlayedStamp DESC" : "LastPlayedStamp ASC"; | ||
140 | # break; | ||
141 | # case (byte)SelectionMethods.OftenPlayed: | ||
142 | # output += (info[SELECTIONMETHODSIGNOFFSET] == 0) | ||
143 | # ? "most often played" : "least often played"; | ||
144 | # result.OrderBy = (info[SELECTIONMETHODSIGNOFFSET] == 0) | ||
145 | # ? "NumberOfPlays DESC" : "NumberOfPlays ASC"; | ||
146 | # break; | ||
147 | # case (byte)SelectionMethods.RecentlyAdded: | ||
148 | # output += (info[SELECTIONMETHODSIGNOFFSET] == 0) | ||
149 | # ? "most recently added" : "least recently added"; | ||
150 | # result.OrderBy = (info[SELECTIONMETHODSIGNOFFSET] == 0) | ||
151 | # ? "DateAddedStamp DESC" : "DateAddedStamp ASC"; | ||
152 | # break; | ||
153 | # default: | ||
154 | # result.OrderBy = Enum.GetName(typeof(SelectionMethods), (int)info[SELECTIONMETHODOFFSET]); | ||
155 | # break; | ||
156 | # } | ||
157 | # } | ||
158 | # if(ignore.Length > 0) { | ||
159 | # output += "\n\nIGNORING:\n" + ignore; | ||
160 | # } | ||
161 | # | ||
162 | # if(query.Length > 0) { | ||
163 | # output += "\n\nQUERY:\n" + query; | ||
164 | # } | ||
165 | # return result; | ||
166 | # } | ||
167 | # | ||
168 | # private static void ProcessStringField() | ||
169 | # { | ||
170 | # bool end = false; | ||
171 | # string workingOutput = Enum.GetName(typeof(StringFields), criteria[offset]); | ||
172 | # string workingQuery = "(lower(" + Enum.GetName(typeof(StringFields), criteria[offset]) + ")"; | ||
173 | # switch(criteria[logicRulesOffset]) { | ||
174 | # case (byte)LogicRule.Contains: | ||
175 | # if((criteria[logicSignOffset] == (byte)LogicSign.StringPositive)) { | ||
176 | # workingOutput += " contains "; | ||
177 | # workingQuery += " LIKE '%"; | ||
178 | # } else { | ||
179 | # workingOutput += " does not contain "; | ||
180 | # workingQuery += " NOT LIKE '%"; | ||
181 | # } | ||
182 | # if(criteria[offset] == (byte)StringFields.Kind) { | ||
183 | # KindEval = delegate(Kind kind, string query) { | ||
184 | # return (kind.Name.IndexOf(query) != -1); | ||
185 | # }; | ||
186 | # } | ||
187 | # end = true; | ||
188 | # break; | ||
189 | # case (byte)LogicRule.Is: | ||
190 | # if((criteria[logicSignOffset] == (byte)LogicSign.StringPositive)) { | ||
191 | # workingOutput += " is "; | ||
192 | # workingQuery += " = '"; | ||
193 | # } else { | ||
194 | # workingOutput += " is not "; | ||
195 | # workingQuery += " != '"; | ||
196 | # } | ||
197 | # if(criteria[offset] == (byte)StringFields.Kind) { | ||
198 | # KindEval = delegate(Kind kind, string query) { | ||
199 | # return (kind.Name == query); | ||
200 | # }; | ||
201 | # } | ||
202 | # break; | ||
203 | # case (byte)LogicRule.Starts: | ||
204 | # workingOutput += " starts with "; | ||
205 | # workingQuery += " LIKE '"; | ||
206 | # if(criteria[offset] == (byte)StringFields.Kind) { | ||
207 | # KindEval = delegate (Kind kind, string query) { | ||
208 | # return (kind.Name.IndexOf(query) == 0); | ||
209 | # }; | ||
210 | # } | ||
211 | # end = true; | ||
212 | # break; | ||
213 | # case (byte)LogicRule.Ends: | ||
214 | # workingOutput += " ends with "; | ||
215 | # workingQuery += " LIKE '%"; | ||
216 | # if(criteria[offset] == (byte)StringFields.Kind) { | ||
217 | # KindEval = delegate (Kind kind, string query) { | ||
218 | # return (kind.Name.IndexOf(query) == (kind.Name.Length - query.Length)); | ||
219 | # }; | ||
220 | # } | ||
221 | # break; | ||
222 | # } | ||
223 | # workingOutput += "\""; | ||
224 | # byte[] character = new byte[1]; | ||
225 | # string content = ""; | ||
226 | # bool onByte = true; | ||
227 | # for(int i = (stringOffset); i < criteria.Length; i++) { | ||
228 | # // Off bytes are 0 | ||
229 | # if(onByte) { | ||
230 | # // If the byte is 0 and it's not the last byte, | ||
231 | # // we have another condition | ||
232 | # if(criteria[i] == 0 && i != (criteria.Length - 1)) { | ||
233 | # again = true; | ||
234 | # FinishStringField(content, workingOutput, workingQuery, end); | ||
235 | # offset = i + 2; | ||
236 | # return; | ||
237 | # } | ||
238 | # character[0] = criteria[i]; | ||
239 | # content += Encoding.UTF8.GetString(character); | ||
240 | # } | ||
241 | # onByte = !onByte; | ||
242 | # } | ||
243 | # FinishStringField(content, workingOutput, workingQuery, end); | ||
244 | # } | ||
245 | # | ||
246 | # private static void FinishStringField(string content, string workingOutput, string workingQuery, bool end) | ||
247 | # { | ||
248 | # workingOutput += content; | ||
249 | # workingOutput += "\" "; | ||
250 | # bool failed = false; | ||
251 | # if(criteria[offset] == (byte)StringFields.Kind) { | ||
252 | # workingQuery = ""; | ||
253 | # foreach(Kind kind in Kinds) { | ||
254 | # if(KindEval(kind, content)) { | ||
255 | # if(workingQuery.Length > 0) { | ||
256 | # if((query.Length == 0 && !again) || or) { | ||
257 | # workingQuery += " OR "; | ||
258 | # } else { | ||
259 | # failed = true; | ||
260 | # break; | ||
261 | # } | ||
262 | # } | ||
263 | # workingQuery += "(lower(Uri)"; | ||
264 | # workingQuery += ((criteria[logicSignOffset] == (byte)LogicSign.StringPositive)) | ||
265 | # ? " LIKE '%" + kind.Extension + "')" : " NOT LIKE '%" + kind.Extension + "%')"; | ||
266 | # } | ||
267 | # } | ||
268 | # } else { | ||
269 | # workingQuery += content.ToLower(); | ||
270 | # workingQuery += (end) ? "%')" : "')"; | ||
271 | # } | ||
272 | # if(Enum.IsDefined(typeof(IgnoreStringFields), | ||
273 | # (int)criteria[offset]) || failed) { | ||
274 | # if(ignore.Length > 0) { | ||
275 | # ignore += conjunctionOutput; | ||
276 | # } | ||
277 | # ignore += workingOutput; | ||
278 | # } else { | ||
279 | # if(output.Length > 0) { | ||
280 | # output += conjunctionOutput; | ||
281 | # } | ||
282 | # if(query.Length > 0) { | ||
283 | # query += conjunctionQuery; | ||
284 | # } | ||
285 | # output += workingOutput; | ||
286 | # query += workingQuery; | ||
287 | # } | ||
288 | # } | ||
289 | # | ||
290 | # private static void ProcessIntField() | ||
291 | # { | ||
292 | # string workingOutput = Enum.GetName(typeof(IntFields), criteria[offset]); | ||
293 | # string workingQuery = "(" + Enum.GetName(typeof(IntFields), criteria[offset]); | ||
294 | # | ||
295 | # switch(criteria[logicRulesOffset]) { | ||
296 | # case (byte)LogicRule.Is: | ||
297 | # if(criteria[logicSignOffset] == (byte)LogicSign.IntPositive) { | ||
298 | # workingOutput += " is "; | ||
299 | # workingQuery += " = "; | ||
300 | # } else { | ||
301 | # workingOutput += " is not "; | ||
302 | # workingQuery += " != "; | ||
303 | # } | ||
304 | # goto case 255; | ||
305 | # case (byte)LogicRule.Greater: | ||
306 | # workingOutput += " is greater than "; | ||
307 | # workingQuery += " > "; | ||
308 | # goto case 255; | ||
309 | # case (byte)LogicRule.Less: | ||
310 | # workingOutput += " is less than "; | ||
311 | # workingQuery += " > "; | ||
312 | # goto case 255; | ||
313 | # case 255: | ||
314 | # uint number = (criteria[offset] == (byte)IntFields.Rating) | ||
315 | # ? (BytesToUInt(criteria, intAOffset) / 20) : BytesToUInt(criteria, intAOffset); | ||
316 | # workingOutput += number.ToString(); | ||
317 | # workingQuery += number.ToString(); | ||
318 | # break; | ||
319 | # case (byte)LogicRule.Other: | ||
320 | # if(criteria[logicSignOffset + 2] == 1) { | ||
321 | # workingOutput += " is in the range of "; | ||
322 | # workingQuery += " BETWEEN "; | ||
323 | # uint num = (criteria[offset] == (byte)IntFields.Rating) | ||
324 | # ? (BytesToUInt(criteria, intAOffset) / 20) : BytesToUInt(criteria, intAOffset); | ||
325 | # workingOutput += num.ToString(); | ||
326 | # workingQuery += num.ToString(); | ||
327 | # workingOutput += " to "; | ||
328 | # workingQuery += " AND "; | ||
329 | # num = (criteria[offset] == (byte)IntFields.Rating) | ||
330 | # ? ((BytesToUInt(criteria, intBOffset) - 19) / 20) : BytesToUInt(criteria, intBOffset); | ||
331 | # workingOutput += num.ToString(); | ||
332 | # workingQuery += num.ToString(); | ||
333 | # } | ||
334 | # break; | ||
335 | # } | ||
336 | # workingQuery += ")"; | ||
337 | # if(Enum.IsDefined(typeof(IgnoreIntFields), | ||
338 | # (int)criteria[offset])) { | ||
339 | # if(ignore.Length > 0) { | ||
340 | # ignore += conjunctionOutput; | ||
341 | # } | ||
342 | # ignore += workingOutput; | ||
343 | # } else { | ||
344 | # if(output.Length > 0) { | ||
345 | # output += conjunctionOutput; | ||
346 | # } | ||
347 | # if(query.Length > 0) { | ||
348 | # query += conjunctionQuery; | ||
349 | # } | ||
350 | # output += workingOutput; | ||
351 | # query += workingQuery; | ||
352 | # } | ||
353 | # offset = intAOffset + INTLENGTH; | ||
354 | # if(criteria.Length > offset) { | ||
355 | # again = true; | ||
356 | # } | ||
357 | # } | ||
358 | # | ||
359 | # private static void ProcessDateField() | ||
360 | # { | ||
361 | # bool isIgnore = false; | ||
362 | # string workingOutput = Enum.GetName(typeof(DateFields), criteria[offset]); | ||
363 | # string workingQuery = "((strftime(\"%s\", current_timestamp) - DateAddedStamp + 3600)"; | ||
364 | # switch(criteria[logicRulesOffset]) { | ||
365 | # case (byte)LogicRule.Greater: | ||
366 | # workingOutput += " is after "; | ||
367 | # workingQuery += " > "; | ||
368 | # goto case 255; | ||
369 | # case (byte)LogicRule.Less: | ||
370 | # workingOutput += " is before "; | ||
371 | # workingQuery += " > "; | ||
372 | # goto case 255; | ||
373 | # case 255: | ||
374 | # isIgnore = true; | ||
375 | # DateTime time = BytesToDateTime(criteria, intAOffset); | ||
376 | # workingOutput += time.ToString(); | ||
377 | # workingQuery += ((int)DateTime.Now.Subtract(time).TotalSeconds).ToString(); | ||
378 | # break; | ||
379 | # case (byte)LogicRule.Other: | ||
380 | # if(criteria[logicSignOffset + 2] == 1) { | ||
381 | # isIgnore = true; | ||
382 | # DateTime t2 = BytesToDateTime(criteria, intAOffset); | ||
383 | # DateTime t1 = BytesToDateTime(criteria, intBOffset); | ||
384 | # if(criteria[logicSignOffset] == (byte)LogicSign.IntPositive) { | ||
385 | # workingOutput += " is in the range of "; | ||
386 | # workingQuery += " BETWEEN " + | ||
387 | # ((int)DateTime.Now.Subtract(t1).TotalSeconds).ToString() + | ||
388 | # " AND " + | ||
389 | # ((int)DateTime.Now.Subtract(t2).TotalSeconds).ToString(); | ||
390 | # } else { | ||
391 | # workingOutput += " is not in the range of "; | ||
392 | # } | ||
393 | # workingOutput += t1.ToString(); | ||
394 | # workingOutput += " to "; | ||
395 | # workingOutput += t2.ToString(); | ||
396 | # } else if(criteria[logicSignOffset + 2] == 2) { | ||
397 | # if(criteria[logicSignOffset] == (byte)LogicSign.IntPositive) { | ||
398 | # workingOutput += " is in the last "; | ||
399 | # workingQuery += " < "; | ||
400 | # } else { | ||
401 | # workingOutput += " is not in the last "; | ||
402 | # workingQuery += " > "; | ||
403 | # } | ||
404 | # uint t = InverseBytesToUInt(criteria, timeValueOffset); | ||
405 | # uint multiple = BytesToUInt(criteria, timeMultipleOffset); | ||
406 | # workingQuery += (t * multiple).ToString(); | ||
407 | # workingOutput += t.ToString() + " "; | ||
408 | # switch(multiple) { | ||
409 | # case 86400: | ||
410 | # workingOutput += "days"; | ||
411 | # break; | ||
412 | # case 604800: | ||
413 | # workingOutput += "weeks"; | ||
414 | # break; | ||
415 | # case 2628000: | ||
416 | # workingOutput += "months"; | ||
417 | # break; | ||
418 | # } | ||
419 | # } | ||
420 | # break; | ||
421 | # } | ||
422 | # workingQuery += ")"; | ||
423 | # if(isIgnore || Enum.IsDefined(typeof(IgnoreDateFields), (int)criteria[offset])) { | ||
424 | # if(ignore.Length > 0) { | ||
425 | # ignore += conjunctionOutput; | ||
426 | # } | ||
427 | # ignore += workingOutput; | ||
428 | # } else { | ||
429 | # if(output.Length > 0) { | ||
430 | # output += conjunctionOutput; | ||
431 | # } | ||
432 | # output += workingOutput; | ||
433 | # if(query.Length > 0) { | ||
434 | # query += conjunctionQuery; | ||
435 | # } | ||
436 | # query += workingQuery; | ||
437 | # } | ||
438 | # offset = intAOffset + INTLENGTH; | ||
439 | # if(criteria.Length > offset) { | ||
440 | # again = true; | ||
441 | # } | ||
442 | # } | ||
443 | # | ||
444 | # /// <summary> | ||
445 | # /// Converts 4 bytes to a uint | ||
446 | # /// </summary> | ||
447 | # /// <param name="byteArray">A byte array</param> | ||
448 | # /// <param name="offset">Should be the byte of the uint with the 0th-power position</param> | ||
449 | # /// <returns></returns> | ||
450 | # private static uint BytesToUInt(byte[] byteArray, int offset) | ||
451 | # { | ||
452 | # uint output = 0; | ||
453 | # for (byte i = 0; i <= 4; i++) { | ||
454 | # output += (uint)(byteArray[offset - i] * Math.Pow(2, (8 * i))); | ||
455 | # } | ||
456 | # return output; | ||
457 | # } | ||
458 | # | ||
459 | # private static uint InverseBytesToUInt(byte[] byteArray, int offset) | ||
460 | # { | ||
461 | # uint output = 0; | ||
462 | # for (byte i = 0; i <= 4; i++) { | ||
463 | # output += (uint)((255 - (uint)(byteArray[offset - i])) * Math.Pow(2, (8 * i))); | ||
464 | # } | ||
465 | # return ++output; | ||
466 | # } | ||
467 | # | ||
468 | # private static DateTime BytesToDateTime (byte[] byteArray, int offset) | ||
469 | # { | ||
470 | # uint number = BytesToUInt(byteArray, offset); | ||
471 | # return STARTOFTIME.AddSeconds(number); | ||
472 | # } | ||
473 | # } | ||
474 | # } | ||
475 | # namespace Banshee.Plugins.iTunesImporter | ||
476 | # { | ||
477 | # internal struct Kind | ||
478 | # { | ||
479 | # public string Name, Extension; | ||
480 | # public Kind(string name, string extension) | ||
481 | # { | ||
482 | # Name = name; | ||
483 | # Extension = extension; | ||
484 | # } | ||
485 | # } | ||
486 | # | ||
487 | # internal partial class SmartPlaylistParser | ||
488 | # { | ||
489 | # private static Kind[] Kinds = { | ||
490 | # new Kind("Protected AAC audio file", ".m4p"), | ||
491 | # new Kind("MPEG audio file", ".mp3"), | ||
492 | # new Kind("AIFF audio file", ".aiff"), | ||
493 | # new Kind("WAV audio file", ".wav"), | ||
494 | # new Kind("QuickTime movie file", ".mov"), | ||
495 | # new Kind("MPEG-4 video file", ".mp4"), | ||
496 | # new Kind("AAC audio file", ".m4a") | ||
497 | # }; | ||
498 | # | ||
499 | # /// <summary> | ||
500 | # /// The methods by which the number of songs in a playlist are limited | ||
501 | # /// </summary> | ||
502 | # private enum LimitMethods | ||
503 | # { | ||
504 | # Minutes = 0x01, | ||
505 | # MB = 0x02, | ||
506 | # Items = 0x03, | ||
507 | # Hours = 0x04, | ||
508 | # GB = 0x05, | ||
509 | # } | ||
510 | # /// <summary> | ||
511 | # /// The methods by which songs are selected for inclusion in a limited playlist | ||
512 | # /// </summary> | ||
513 | # private enum SelectionMethods | ||
514 | # { | ||
515 | # Random = 0x02, | ||
516 | # Title = 0x05, | ||
517 | # AlbumTitle = 0x06, | ||
518 | # Artist = 0x07, | ||
519 | # Genre = 0x09, | ||
520 | # HighestRating = 0x1c, | ||
521 | # LowestRating = 0x01, | ||
522 | # RecentlyPlayed = 0x1a, | ||
523 | # OftenPlayed = 0x19, | ||
524 | # RecentlyAdded = 0x15 | ||
525 | # } | ||
526 | # /// <summary> | ||
527 | # /// The matching criteria which take string data | ||
528 | # /// </summary> | ||
529 | # private enum StringFields | ||
530 | # { | ||
531 | # AlbumTitle = 0x03, | ||
532 | # AlbumArtist = 0x47, | ||
533 | # Artist = 0x04, | ||
534 | # Category = 0x37, | ||
535 | # Comments = 0x0e, | ||
536 | # Composer = 0x12, | ||
537 | # Description = 0x36, | ||
538 | # Genre = 0x08, | ||
539 | # Grouping = 0x27, | ||
540 | # Kind = 0x09, | ||
541 | # Title = 0x02, | ||
542 | # Show = 0x3e | ||
543 | # } | ||
544 | # /// <summary> | ||
545 | # /// The matching criteria which take integer data | ||
546 | # /// </summary> | ||
547 | # private enum IntFields | ||
548 | # { | ||
549 | # BPM = 0x23, | ||
550 | # BitRate = 0x05, | ||
551 | # Compilation = 0x1f, | ||
552 | # DiskNumber = 0x18, | ||
553 | # NumberOfPlays = 0x16, | ||
554 | # Rating = 0x19, | ||
555 | # Playlist = 0x28, // FIXME Move this? | ||
556 | # Podcast = 0x39, | ||
557 | # SampleRate = 0x06, | ||
558 | # Season = 0x3f, | ||
559 | # Size = 0x0c, | ||
560 | # SkipCount = 0x44, | ||
561 | # Duration = 0x0d, | ||
562 | # TrackNumber = 0x0b, | ||
563 | # VideoKind = 0x3c, | ||
564 | # Year = 0x07 | ||
565 | # } | ||
566 | # /// <summary> | ||
567 | # /// The matching criteria which take date data | ||
568 | # /// </summary> | ||
569 | # private enum DateFields | ||
570 | # { | ||
571 | # DateAdded = 0x10, | ||
572 | # DateModified = 0x0a, | ||
573 | # LastPlayed = 0x17, | ||
574 | # LastSkipped = 0x45 | ||
575 | # } | ||
576 | # /// <summary> | ||
577 | # /// The matching criteria which we do no handle | ||
578 | # /// </summary> | ||
579 | # private enum IgnoreStringFields | ||
580 | # { | ||
581 | # AlbumArtist = 0x47, | ||
582 | # Category = 0x37, | ||
583 | # Comments = 0x0e, | ||
584 | # Composer = 0x12, | ||
585 | # Description = 0x36, | ||
586 | # Grouping = 0x27, | ||
587 | # Show = 0x3e | ||
588 | # } | ||
589 | # /// <summary> | ||
590 | # /// The matching criteria which we do no handle | ||
591 | # /// </summary> | ||
592 | # private enum IgnoreIntFields | ||
593 | # { | ||
594 | # BPM = 0x23, | ||
595 | # BitRate = 0x05, | ||
596 | # Compilation = 0x1f, | ||
597 | # DiskNumber = 0x18, | ||
598 | # Playlist = 0x28, | ||
599 | # Podcast = 0x39, | ||
600 | # SampleRate = 0x06, | ||
601 | # Season = 0x3f, | ||
602 | # Size = 0x0c, | ||
603 | # SkipCount = 0x44, | ||
604 | # TrackNumber = 0x0b, | ||
605 | # VideoKind = 0x3c | ||
606 | # } | ||
607 | # private enum IgnoreDateFields | ||
608 | # { | ||
609 | # DateModified = 0x0a, | ||
610 | # LastSkipped = 0x45 | ||
611 | # } | ||
612 | # /// <summary> | ||
613 | # /// The signs which apply to different kinds of logic (is vs. is not, contains vs. doesn't contain, etc.) | ||
614 | # /// </summary> | ||
615 | # private enum LogicSign | ||
616 | # { | ||
617 | # IntPositive = 0x00, | ||
618 | # StringPositive = 0x01, | ||
619 | # IntNegative = 0x02, | ||
620 | # StringNegative = 0x03 | ||
621 | # } | ||
622 | # /// <summary> | ||
623 | # /// The logical rules | ||
624 | # /// </summary> | ||
625 | # private enum LogicRule | ||
626 | # { | ||
627 | # Other = 0x00, | ||
628 | # Is = 0x01, | ||
629 | # Contains = 0x02, | ||
630 | # Starts = 0x04, | ||
631 | # Ends = 0x08, | ||
632 | # Greater = 0x10, | ||
633 | # Less = 0x40 | ||
634 | # } | ||
635 | # } | ||
636 | # } | ||