Merge lp:~didrocks/unity-lens-music/add-local-radio into lp:unity-lens-music
- add-local-radio
- Merge into trunk
Proposed by
Didier Roche-Tolomelli
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Approved by: | Paweł Stołowski | ||||||||
Approved revision: | 86 | ||||||||
Merged at revision: | 83 | ||||||||
Proposed branch: | lp:~didrocks/unity-lens-music/add-local-radio | ||||||||
Merge into: | lp:unity-lens-music | ||||||||
Diff against target: |
668 lines (+354/-74) 10 files modified
Makefile.am (+1/-1) configure.ac (+1/-0) src/categories.vala (+2/-1) src/daemon.vala (+5/-1) src/rhythmbox-collection.vala (+99/-70) src/rhythmbox-scope.vala (+1/-1) src/track.vala (+7/-0) tests/Makefile.am (+45/-0) tests/assertions.vapi (+23/-0) tests/test-rhythmbox-parser.vala (+170/-0) |
||||||||
To merge this branch: | bzr merge lp:~didrocks/unity-lens-music/add-local-radio | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Paweł Stołowski (community) | Approve | ||
Review via email: mp+111875@code.launchpad.net |
Commit message
Description of the change
This branch adds local radio detection from rhythmbox. The category will
only be placed after the "for purchase one" to be unobstrusive (LP: #969697)
Also fix the non translated "Unknown" album filter appearing for non english
users (LP: #1009069)
Add some tests for the parser part (radios and songs)
To post a comment you must log in.
- 86. By Didier Roche-Tolomelli
-
add it to an album if only it's a song, make type_track TypeTrack
Revision history for this message
Didier Roche-Tolomelli (didrocks) wrote : | # |
Good spot! Changes made :)
I only add albums for now if the type is a song. Please rereview
Revision history for this message
Paweł Stołowski (stolowski) wrote : | # |
Looks good now, and works fine. Well done!
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'Makefile.am' | |||
2 | --- Makefile.am 2011-09-14 18:16:32 +0000 | |||
3 | +++ Makefile.am 2012-06-29 15:58:20 +0000 | |||
4 | @@ -1,4 +1,4 @@ | |||
6 | 1 | SUBDIRS = src data po | 1 | SUBDIRS = src data po tests |
7 | 2 | 2 | ||
8 | 3 | # | 3 | # |
9 | 4 | # Install the music.lens and musicstore.scope files | 4 | # Install the music.lens and musicstore.scope files |
10 | 5 | 5 | ||
11 | === modified file 'configure.ac' | |||
12 | --- configure.ac 2012-04-27 07:45:16 +0000 | |||
13 | +++ configure.ac 2012-06-29 15:58:20 +0000 | |||
14 | @@ -121,6 +121,7 @@ | |||
15 | 121 | src/Makefile | 121 | src/Makefile |
16 | 122 | src/config.vala | 122 | src/config.vala |
17 | 123 | po/Makefile.in | 123 | po/Makefile.in |
18 | 124 | tests/Makefile | ||
19 | 124 | ]) | 125 | ]) |
20 | 125 | AC_OUTPUT | 126 | AC_OUTPUT |
21 | 126 | 127 | ||
22 | 127 | 128 | ||
23 | === modified file 'src/categories.vala' | |||
24 | --- src/categories.vala 2012-01-20 11:48:10 +0000 | |||
25 | +++ src/categories.vala 2012-06-29 15:58:20 +0000 | |||
26 | @@ -23,7 +23,8 @@ | |||
27 | 23 | SONGS, | 23 | SONGS, |
28 | 24 | ALBUMS, | 24 | ALBUMS, |
29 | 25 | PURCHASE, | 25 | PURCHASE, |
31 | 26 | MUSIC | 26 | MUSIC, |
32 | 27 | RADIOS | ||
33 | 27 | } | 28 | } |
34 | 28 | 29 | ||
35 | 29 | } | 30 | } |
36 | 30 | 31 | ||
37 | === modified file 'src/daemon.vala' | |||
38 | --- src/daemon.vala 2012-04-23 12:35:38 +0000 | |||
39 | +++ src/daemon.vala 2012-06-29 15:58:20 +0000 | |||
40 | @@ -74,7 +74,7 @@ | |||
41 | 74 | filter.add_option ("1960", _("60s")); | 74 | filter.add_option ("1960", _("60s")); |
42 | 75 | filter.add_option ("1970", _("70s")); | 75 | filter.add_option ("1970", _("70s")); |
43 | 76 | filter.add_option ("1980", _("80s")); | 76 | filter.add_option ("1980", _("80s")); |
45 | 77 | filter.add_option ("1990", _("90s")); | 77 | filter.add_option ("1990", _("90s")); |
46 | 78 | filter.add_option ("2000", _("00s")); | 78 | filter.add_option ("2000", _("00s")); |
47 | 79 | filter.add_option ("2010", _("10s")); | 79 | filter.add_option ("2010", _("10s")); |
48 | 80 | 80 | ||
49 | @@ -135,6 +135,10 @@ | |||
50 | 135 | new FileIcon (icon_dir.get_child ("group-songs.svg"))); | 135 | new FileIcon (icon_dir.get_child ("group-songs.svg"))); |
51 | 136 | categories.append (cat); | 136 | categories.append (cat); |
52 | 137 | 137 | ||
53 | 138 | cat = new Unity.Category (_("Radio"), | ||
54 | 139 | new FileIcon (icon_dir.get_child ("group-songs.svg"))); | ||
55 | 140 | categories.append (cat); | ||
56 | 141 | |||
57 | 138 | lens.categories = categories; | 142 | lens.categories = categories; |
58 | 139 | } | 143 | } |
59 | 140 | } | 144 | } |
60 | 141 | 145 | ||
61 | === modified file 'src/rhythmbox-collection.vala' | |||
62 | --- src/rhythmbox-collection.vala 2012-04-25 17:26:44 +0000 | |||
63 | +++ src/rhythmbox-collection.vala 2012-06-29 15:58:20 +0000 | |||
64 | @@ -26,6 +26,7 @@ | |||
65 | 26 | 26 | ||
66 | 27 | private enum Columns | 27 | private enum Columns |
67 | 28 | { | 28 | { |
68 | 29 | TYPE, | ||
69 | 29 | URI, | 30 | URI, |
70 | 30 | TITLE, | 31 | TITLE, |
71 | 31 | ARTIST, | 32 | ARTIST, |
72 | @@ -43,7 +44,7 @@ | |||
73 | 43 | 44 | ||
74 | 44 | class RhythmboxCollection : Object | 45 | class RhythmboxCollection : Object |
75 | 45 | { | 46 | { |
77 | 46 | const string UNKNOWN_ALBUM = "Unknown"; | 47 | const string UNKNOWN_ALBUM = _("Unknown"); |
78 | 47 | 48 | ||
79 | 48 | SequenceModel all_tracks; | 49 | SequenceModel all_tracks; |
80 | 49 | ModelTag<int> album_art_tag; | 50 | ModelTag<int> album_art_tag; |
81 | @@ -56,7 +57,7 @@ | |||
82 | 56 | 57 | ||
83 | 57 | HashTable<unowned string, Variant> variant_store; | 58 | HashTable<unowned string, Variant> variant_store; |
84 | 58 | HashTable<int, Variant> int_variant_store; | 59 | HashTable<int, Variant> int_variant_store; |
86 | 59 | Variant row_buffer[11]; | 60 | Variant row_buffer[12]; |
87 | 60 | 61 | ||
88 | 61 | Analyzer analyzer; | 62 | Analyzer analyzer; |
89 | 62 | Index? index; | 63 | Index? index; |
90 | @@ -64,7 +65,7 @@ | |||
91 | 64 | 65 | ||
92 | 65 | string media_art_dir; | 66 | string media_art_dir; |
93 | 66 | 67 | ||
95 | 67 | class XmlParser: Object | 68 | public class XmlParser: Object |
96 | 68 | { | 69 | { |
97 | 69 | const MarkupParser parser = | 70 | const MarkupParser parser = |
98 | 70 | { | 71 | { |
99 | @@ -91,7 +92,7 @@ | |||
100 | 91 | return context.parse (content, (ssize_t) len); | 92 | return context.parse (content, (ssize_t) len); |
101 | 92 | } | 93 | } |
102 | 93 | 94 | ||
104 | 94 | bool processing_song; | 95 | bool processing_track; |
105 | 95 | Track current_track; | 96 | Track current_track; |
106 | 96 | int current_data = -1; | 97 | int current_data = -1; |
107 | 97 | 98 | ||
108 | @@ -99,21 +100,24 @@ | |||
109 | 99 | [CCode (array_length = false, array_null_terminated = true)] string[] attr_names, [CCode (array_length = false, array_null_terminated = true)] string[] attr_values) | 100 | [CCode (array_length = false, array_null_terminated = true)] string[] attr_names, [CCode (array_length = false, array_null_terminated = true)] string[] attr_values) |
110 | 100 | throws MarkupError | 101 | throws MarkupError |
111 | 101 | { | 102 | { |
113 | 102 | if (!processing_song) | 103 | if (!processing_track) |
114 | 103 | { | 104 | { |
115 | 104 | switch (name) | 105 | switch (name) |
116 | 105 | { | 106 | { |
117 | 106 | case "rhythmdb": is_rhythmdb_xml = true; break; | 107 | case "rhythmdb": is_rhythmdb_xml = true; break; |
118 | 107 | case "entry": | 108 | case "entry": |
120 | 108 | bool is_song = false; | 109 | string accepted_element_name = null; |
121 | 109 | for (int i = 0; attr_names[i] != null; i++) | 110 | for (int i = 0; attr_names[i] != null; i++) |
122 | 110 | { | 111 | { |
125 | 111 | if (attr_names[i] == "type" && attr_values[i] == "song") | 112 | if (attr_names[i] == "type" && (attr_values[i] == "song" |
126 | 112 | is_song = true; | 113 | || attr_values[i] == "iradio")) |
127 | 114 | accepted_element_name = attr_values[i]; | ||
128 | 113 | } | 115 | } |
131 | 114 | if (!is_song) return; | 116 | if (accepted_element_name == null) return; |
132 | 115 | processing_song = true; | 117 | processing_track = true; |
133 | 116 | current_track = new Track (); | 118 | current_track = new Track (); |
134 | 119 | current_track.type_track = accepted_element_name == "song" ? | ||
135 | 120 | TrackType.SONG : TrackType.RADIO; | ||
136 | 117 | break; | 121 | break; |
137 | 118 | } | 122 | } |
138 | 119 | } | 123 | } |
139 | @@ -156,14 +160,14 @@ | |||
140 | 156 | if (current_data >= 0) current_data = -1; | 160 | if (current_data >= 0) current_data = -1; |
141 | 157 | break; | 161 | break; |
142 | 158 | case "hidden": | 162 | case "hidden": |
144 | 159 | if (processing_song) processing_song = false; | 163 | if (processing_track) processing_track = false; |
145 | 160 | break; | 164 | break; |
146 | 161 | case "entry": | 165 | case "entry": |
148 | 162 | if (processing_song && current_track != null) | 166 | if (processing_track && current_track != null) |
149 | 163 | { | 167 | { |
150 | 164 | track_info_ready (current_track); | 168 | track_info_ready (current_track); |
151 | 165 | } | 169 | } |
153 | 166 | processing_song = false; | 170 | processing_track = false; |
154 | 167 | break; | 171 | break; |
155 | 168 | } | 172 | } |
156 | 169 | } | 173 | } |
157 | @@ -172,7 +176,7 @@ | |||
158 | 172 | string text, size_t text_len) | 176 | string text, size_t text_len) |
159 | 173 | throws MarkupError | 177 | throws MarkupError |
160 | 174 | { | 178 | { |
162 | 175 | if (!processing_song || current_data < 0) return; | 179 | if (!processing_track || current_data < 0) return; |
163 | 176 | switch (current_data) | 180 | switch (current_data) |
164 | 177 | { | 181 | { |
165 | 178 | case Columns.URI: current_track.uri = text; break; | 182 | case Columns.URI: current_track.uri = text; break; |
166 | @@ -203,7 +207,7 @@ | |||
167 | 203 | 207 | ||
168 | 204 | construct | 208 | construct |
169 | 205 | { | 209 | { |
171 | 206 | static_assert (11 == Columns.N_COLUMNS); // sync with row_buffer size | 210 | static_assert (12 == Columns.N_COLUMNS); // sync with row_buffer size |
172 | 207 | media_art_dir = Path.build_filename ( | 211 | media_art_dir = Path.build_filename ( |
173 | 208 | Environment.get_user_cache_dir (), "media-art"); | 212 | Environment.get_user_cache_dir (), "media-art"); |
174 | 209 | 213 | ||
175 | @@ -213,7 +217,7 @@ | |||
176 | 213 | direct_equal); | 217 | direct_equal); |
177 | 214 | all_tracks = new SequenceModel (); | 218 | all_tracks = new SequenceModel (); |
178 | 215 | // the columns correspond to the Columns enum | 219 | // the columns correspond to the Columns enum |
180 | 216 | all_tracks.set_schema ("s", "s", "s", "s", "s", "s", | 220 | all_tracks.set_schema ("i", "s", "s", "s", "s", "s", "s", |
181 | 217 | "s", "s", "i", "i", "i"); | 221 | "s", "s", "i", "i", "i"); |
182 | 218 | assert (all_tracks.get_schema ().length == Columns.N_COLUMNS); | 222 | assert (all_tracks.get_schema ().length == Columns.N_COLUMNS); |
183 | 219 | album_art_tag = new ModelTag<int> (all_tracks); | 223 | album_art_tag = new ModelTag<int> (all_tracks); |
184 | @@ -383,6 +387,7 @@ | |||
185 | 383 | 387 | ||
186 | 384 | private void prepare_row_buffer (Track track) | 388 | private void prepare_row_buffer (Track track) |
187 | 385 | { | 389 | { |
188 | 390 | Variant type = cached_variant_for_int (track.type_track); | ||
189 | 386 | Variant uri = new Variant.string (track.uri); | 391 | Variant uri = new Variant.string (track.uri); |
190 | 387 | Variant title = new Variant.string (track.title); | 392 | Variant title = new Variant.string (track.title); |
191 | 388 | Variant artist = cached_variant_for_string (track.artist); | 393 | Variant artist = cached_variant_for_string (track.artist); |
192 | @@ -395,17 +400,18 @@ | |||
193 | 395 | Variant year = cached_variant_for_int (track.year); | 400 | Variant year = cached_variant_for_int (track.year); |
194 | 396 | Variant play_count = cached_variant_for_int (track.play_count); | 401 | Variant play_count = cached_variant_for_int (track.play_count); |
195 | 397 | 402 | ||
207 | 398 | row_buffer[0] = uri; | 403 | row_buffer[0] = type; |
208 | 399 | row_buffer[1] = title; | 404 | row_buffer[1] = uri; |
209 | 400 | row_buffer[2] = artist; | 405 | row_buffer[2] = title; |
210 | 401 | row_buffer[3] = album; | 406 | row_buffer[3] = artist; |
211 | 402 | row_buffer[4] = artwork; | 407 | row_buffer[4] = album; |
212 | 403 | row_buffer[5] = mime_type; | 408 | row_buffer[5] = artwork; |
213 | 404 | row_buffer[6] = genre; | 409 | row_buffer[6] = mime_type; |
214 | 405 | row_buffer[7] = album_artist; | 410 | row_buffer[7] = genre; |
215 | 406 | row_buffer[8] = track_number; | 411 | row_buffer[8] = album_artist; |
216 | 407 | row_buffer[9] = year; | 412 | row_buffer[9] = track_number; |
217 | 408 | row_buffer[10] = play_count; | 413 | row_buffer[10] = year; |
218 | 414 | row_buffer[11] = play_count; | ||
219 | 409 | } | 415 | } |
220 | 410 | 416 | ||
221 | 411 | public void parse_metadata_file (string path) | 417 | public void parse_metadata_file (string path) |
222 | @@ -475,7 +481,7 @@ | |||
223 | 475 | prepare_row_buffer (track); | 481 | prepare_row_buffer (track); |
224 | 476 | var iter = all_tracks.append_row (row_buffer); | 482 | var iter = all_tracks.append_row (row_buffer); |
225 | 477 | 483 | ||
227 | 478 | if (track.album == UNKNOWN_ALBUM) return; | 484 | if (track.album == "" || track.album == UNKNOWN_ALBUM) return; |
228 | 479 | var album_key = "%s - %s".printf (track.album, track.album_artist != null ? track.album_artist : track.artist); | 485 | var album_key = "%s - %s".printf (track.album, track.album_artist != null ? track.album_artist : track.artist); |
229 | 480 | var arr = album_to_tracks_map[album_key]; | 486 | var arr = album_to_tracks_map[album_key]; |
230 | 481 | if (arr == null) | 487 | if (arr == null) |
231 | @@ -520,7 +526,8 @@ | |||
232 | 520 | private enum ResultType | 526 | private enum ResultType |
233 | 521 | { | 527 | { |
234 | 522 | ALBUM, | 528 | ALBUM, |
236 | 523 | SONG | 529 | SONG, |
237 | 530 | RADIO | ||
238 | 524 | } | 531 | } |
239 | 525 | 532 | ||
240 | 526 | private void add_result (Model results_model, Model model, | 533 | private void add_result (Model results_model, Model model, |
241 | @@ -556,14 +563,15 @@ | |||
242 | 556 | album_art_tag[model, iter] = current_album_art_tag; | 563 | album_art_tag[model, iter] = current_album_art_tag; |
243 | 557 | } | 564 | } |
244 | 558 | 565 | ||
246 | 559 | var title_col = result_type == ResultType.SONG ? | 566 | var title_col = (result_type == ResultType.SONG |
247 | 567 | || result_type == ResultType.RADIO) ? | ||
248 | 560 | Columns.TITLE : Columns.ALBUM; | 568 | Columns.TITLE : Columns.ALBUM; |
249 | 561 | unowned string title = model.get_string (iter, title_col); | 569 | unowned string title = model.get_string (iter, title_col); |
250 | 562 | var uri = model.get_string (iter, Columns.URI); | 570 | var uri = model.get_string (iter, Columns.URI); |
251 | 563 | var dnd_uri = model.get_string (iter, Columns.URI); | 571 | var dnd_uri = model.get_string (iter, Columns.URI); |
252 | 564 | if (result_type == ResultType.ALBUM) | 572 | if (result_type == ResultType.ALBUM) |
253 | 565 | { | 573 | { |
255 | 566 | if (title == UNKNOWN_ALBUM) return; | 574 | if (title == "" || title == UNKNOWN_ALBUM) return; |
256 | 567 | unowned string artist = model.get_string (iter, | 575 | unowned string artist = model.get_string (iter, |
257 | 568 | Columns.ALBUM_ARTIST); | 576 | Columns.ALBUM_ARTIST); |
258 | 569 | if (artist == "") | 577 | if (artist == "") |
259 | @@ -598,6 +606,7 @@ | |||
260 | 598 | int min_year; | 606 | int min_year; |
261 | 599 | int max_year; | 607 | int max_year; |
262 | 600 | int category_id; | 608 | int category_id; |
263 | 609 | ResultType result_type; | ||
264 | 601 | 610 | ||
265 | 602 | Model model = all_tracks; | 611 | Model model = all_tracks; |
266 | 603 | get_decade_filter (filters, out min_year, out max_year); | 612 | get_decade_filter (filters, out min_year, out max_year); |
267 | @@ -639,26 +648,36 @@ | |||
268 | 639 | } | 648 | } |
269 | 640 | } | 649 | } |
270 | 641 | 650 | ||
289 | 642 | unowned string album = model.get_string (iter, | 651 | if (model.get_int32 (iter, Columns.TYPE) == TrackType.SONG) |
290 | 643 | Columns.ALBUM); | 652 | { |
291 | 644 | // it's not first as in track #1, but first found from album | 653 | category_id = Category.SONGS; |
292 | 645 | bool first_track_from_album = !(album in albums_list_nosearch); | 654 | result_type = ResultType.SONG; |
293 | 646 | albums_list_nosearch.add (album); | 655 | |
294 | 647 | 656 | unowned string album = model.get_string (iter, | |
295 | 648 | if (first_track_from_album) | 657 | Columns.ALBUM); |
296 | 649 | { | 658 | // it's not first as in track #1, but first found from album |
297 | 650 | category_id = category_override >= 0 ? | 659 | bool first_track_from_album = !(album in albums_list_nosearch); |
298 | 651 | category_override : Category.ALBUMS; | 660 | albums_list_nosearch.add (album); |
299 | 652 | 661 | ||
300 | 653 | add_result (search.results_model, model, iter, | 662 | if (first_track_from_album) |
301 | 654 | ResultType.ALBUM, category_id); | 663 | { |
302 | 655 | } | 664 | category_id = category_override >= 0 ? |
303 | 656 | 665 | category_override : Category.ALBUMS; | |
304 | 657 | category_id = category_override >= 0 ? | 666 | |
305 | 658 | category_override : Category.SONGS; | 667 | add_result (search.results_model, model, iter, |
306 | 659 | 668 | ResultType.ALBUM, category_id); | |
307 | 669 | } | ||
308 | 670 | } | ||
309 | 671 | else | ||
310 | 672 | { | ||
311 | 673 | category_id = Category.RADIOS; | ||
312 | 674 | result_type = ResultType.RADIO; | ||
313 | 675 | } | ||
314 | 676 | if (category_override >= 0) | ||
315 | 677 | category_id = category_override; | ||
316 | 678 | |||
317 | 660 | add_result (helper_model, model, iter, | 679 | add_result (helper_model, model, iter, |
319 | 661 | ResultType.SONG, category_id); | 680 | result_type, category_id); |
320 | 662 | 681 | ||
321 | 663 | num_results++; | 682 | num_results++; |
322 | 664 | if (max_results >= 0 && num_results >= max_results) break; | 683 | if (max_results >= 0 && num_results >= max_results) break; |
323 | @@ -730,27 +749,37 @@ | |||
324 | 730 | } | 749 | } |
325 | 731 | } | 750 | } |
326 | 732 | 751 | ||
346 | 733 | unowned string album = model.get_string (model_iter, | 752 | |
347 | 734 | Columns.ALBUM); | 753 | if (model.get_int32 (model_iter, Columns.TYPE) == TrackType.SONG) |
348 | 735 | 754 | { | |
349 | 736 | // it's not first as in track #1, but first found from album | 755 | category_id = Category.SONGS; |
350 | 737 | bool first_track_from_album = !(album in albums_list); | 756 | result_type = ResultType.SONG; |
351 | 738 | albums_list.add (album); | 757 | |
352 | 739 | 758 | unowned string album = model.get_string (model_iter, | |
353 | 740 | if (first_track_from_album) | 759 | Columns.ALBUM); |
354 | 741 | { | 760 | // it's not first as in track #1, but first found from album |
355 | 742 | category_id = category_override >= 0 ? | 761 | bool first_track_from_album = !(album in albums_list); |
356 | 743 | category_override : Category.ALBUMS; | 762 | albums_list.add (album); |
357 | 744 | 763 | ||
358 | 745 | add_result (search.results_model, model, model_iter, | 764 | if (first_track_from_album) |
359 | 746 | ResultType.ALBUM, category_id); | 765 | { |
360 | 747 | } | 766 | category_id = category_override >= 0 ? |
361 | 748 | 767 | category_override : Category.ALBUMS; | |
362 | 749 | category_id = category_override >= 0 ? | 768 | |
363 | 750 | category_override : Category.SONGS; | 769 | add_result (search.results_model, model, model_iter, |
364 | 751 | 770 | ResultType.ALBUM, category_id); | |
365 | 771 | } | ||
366 | 772 | } | ||
367 | 773 | else | ||
368 | 774 | { | ||
369 | 775 | category_id = Category.RADIOS; | ||
370 | 776 | result_type = ResultType.RADIO; | ||
371 | 777 | } | ||
372 | 778 | if (category_override >= 0) | ||
373 | 779 | category_id = category_override; | ||
374 | 780 | |||
375 | 752 | add_result (helper_model, model, model_iter, | 781 | add_result (helper_model, model, model_iter, |
377 | 753 | ResultType.SONG, category_id); | 782 | result_type, category_id); |
378 | 754 | 783 | ||
379 | 755 | num_results++; | 784 | num_results++; |
380 | 756 | if (max_results >= 0 && num_results >= max_results) break; | 785 | if (max_results >= 0 && num_results >= max_results) break; |
381 | 757 | 786 | ||
382 | === modified file 'src/rhythmbox-scope.vala' | |||
383 | --- src/rhythmbox-scope.vala 2012-04-25 17:26:44 +0000 | |||
384 | +++ src/rhythmbox-scope.vala 2012-06-29 15:58:20 +0000 | |||
385 | @@ -68,7 +68,7 @@ | |||
386 | 68 | yield; | 68 | yield; |
387 | 69 | } | 69 | } |
388 | 70 | /** | 70 | /** |
390 | 71 | * Tells banshee to play the selected uri(s) | 71 | * Tells rhythmbox to play the selected uri(s) |
391 | 72 | */ | 72 | */ |
392 | 73 | public Unity.ActivationResponse activate (string uri) | 73 | public Unity.ActivationResponse activate (string uri) |
393 | 74 | { | 74 | { |
394 | 75 | 75 | ||
395 | === modified file 'src/track.vala' | |||
396 | --- src/track.vala 2012-03-27 13:31:14 +0000 | |||
397 | +++ src/track.vala 2012-06-29 15:58:20 +0000 | |||
398 | @@ -19,8 +19,15 @@ | |||
399 | 19 | 19 | ||
400 | 20 | namespace Unity.MusicLens { | 20 | namespace Unity.MusicLens { |
401 | 21 | 21 | ||
402 | 22 | public enum TrackType | ||
403 | 23 | { | ||
404 | 24 | SONG, | ||
405 | 25 | RADIO | ||
406 | 26 | } | ||
407 | 27 | |||
408 | 22 | public class Track : GLib.Object | 28 | public class Track : GLib.Object |
409 | 23 | { | 29 | { |
410 | 30 | public TrackType type_track { get; set; } | ||
411 | 24 | public string title { get; set; } | 31 | public string title { get; set; } |
412 | 25 | public string uri { get; set; } | 32 | public string uri { get; set; } |
413 | 26 | public string artist { get; set; } | 33 | public string artist { get; set; } |
414 | 27 | 34 | ||
415 | === added directory 'tests' | |||
416 | === added file 'tests/Makefile.am' | |||
417 | --- tests/Makefile.am 1970-01-01 00:00:00 +0000 | |||
418 | +++ tests/Makefile.am 2012-06-29 15:58:20 +0000 | |||
419 | @@ -0,0 +1,45 @@ | |||
420 | 1 | check_PROGRAMS = test-rhythmbox-parser | ||
421 | 2 | |||
422 | 3 | TESTS = $(check_PROGRAMS) | ||
423 | 4 | |||
424 | 5 | AM_CPPFLAGS = \ | ||
425 | 6 | -w \ | ||
426 | 7 | $(LENS_DAEMON_CFLAGS) \ | ||
427 | 8 | -DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\" \ | ||
428 | 9 | -I$(top_srcdir)/src \ | ||
429 | 10 | $(NULL) | ||
430 | 11 | |||
431 | 12 | AM_VALAFLAGS = \ | ||
432 | 13 | -C \ | ||
433 | 14 | --pkg dee-1.0 \ | ||
434 | 15 | --pkg gee-1.0 \ | ||
435 | 16 | --pkg gio-2.0 \ | ||
436 | 17 | --pkg gio-unix-2.0 \ | ||
437 | 18 | --pkg glib-2.0 \ | ||
438 | 19 | --vapidir $(top_srcdir)/src \ | ||
439 | 20 | --pkg tdb \ | ||
440 | 21 | --pkg unity \ | ||
441 | 22 | $(srcdir)/assertions.vapi \ | ||
442 | 23 | $(NULL) | ||
443 | 24 | |||
444 | 25 | test_libs = \ | ||
445 | 26 | $(LENS_DAEMON_LIBS) \ | ||
446 | 27 | $(NULL) | ||
447 | 28 | |||
448 | 29 | test_rhythmbox_parser_LDADD = $(test_libs) | ||
449 | 30 | |||
450 | 31 | test_rhythmbox_parser_SOURCES = \ | ||
451 | 32 | test-rhythmbox-parser.vala \ | ||
452 | 33 | $(top_srcdir)/src/album.vala \ | ||
453 | 34 | $(top_srcdir)/src/categories.vala \ | ||
454 | 35 | $(top_srcdir)/src/config.vala \ | ||
455 | 36 | $(top_srcdir)/src/filter-parser.vala \ | ||
456 | 37 | $(top_srcdir)/src/filter-parser-decade.vala \ | ||
457 | 38 | $(top_srcdir)/src/filter-parser-genre.vala \ | ||
458 | 39 | $(top_srcdir)/src/genre.vala \ | ||
459 | 40 | $(top_srcdir)/src/rhythmbox-collection.vala \ | ||
460 | 41 | $(top_srcdir)/src/track.vala \ | ||
461 | 42 | $(NULL) | ||
462 | 43 | |||
463 | 44 | CLEANFILES = *.stamp | ||
464 | 45 | |||
465 | 0 | 46 | ||
466 | === added file 'tests/assertions.vapi' | |||
467 | --- tests/assertions.vapi 1970-01-01 00:00:00 +0000 | |||
468 | +++ tests/assertions.vapi 2012-06-29 15:58:20 +0000 | |||
469 | @@ -0,0 +1,23 @@ | |||
470 | 1 | [CCode (cprefix = "G", lower_case_cprefix = "g_", cheader_filename = "glib.h")] | ||
471 | 2 | namespace Assertions { | ||
472 | 3 | public enum OperatorType { | ||
473 | 4 | [CCode (cname = "==")] | ||
474 | 5 | EQUAL, | ||
475 | 6 | [CCode (cname = "!=")] | ||
476 | 7 | NOT_EQUAL, | ||
477 | 8 | [CCode (cname = "<")] | ||
478 | 9 | LESS_THAN, | ||
479 | 10 | [CCode (cname = ">")] | ||
480 | 11 | GREATER_THAN, | ||
481 | 12 | [CCode (cname = "<=")] | ||
482 | 13 | LESS_OR_EQUAL, | ||
483 | 14 | [CCode (cname = ">=")] | ||
484 | 15 | GREATER_OR_EQUAL | ||
485 | 16 | } | ||
486 | 17 | |||
487 | 18 | public void assert_cmpstr (string? s1, OperatorType op, string? s2); | ||
488 | 19 | public void assert_cmpint (int n1, OperatorType op, int n2); | ||
489 | 20 | public void assert_cmpuint (uint n1, OperatorType op, uint n2); | ||
490 | 21 | public void assert_cmphex (uint n1, OperatorType op, uint n2); | ||
491 | 22 | public void assert_cmpfloat (float n1, OperatorType op, float n2); | ||
492 | 23 | } | ||
493 | 0 | 24 | ||
494 | === added file 'tests/test-rhythmbox-parser.vala' | |||
495 | --- tests/test-rhythmbox-parser.vala 1970-01-01 00:00:00 +0000 | |||
496 | +++ tests/test-rhythmbox-parser.vala 2012-06-29 15:58:20 +0000 | |||
497 | @@ -0,0 +1,170 @@ | |||
498 | 1 | /* | ||
499 | 2 | * Copyright (C) 2012 Canonical Ltd | ||
500 | 3 | * | ||
501 | 4 | * This program is free software: you can redistribute it and/or modify | ||
502 | 5 | * it under the terms of the GNU General Public License version 3 as | ||
503 | 6 | * published by the Free Software Foundation. | ||
504 | 7 | * | ||
505 | 8 | * This program is distributed in the hope that it will be useful, | ||
506 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
507 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
508 | 11 | * GNU General Public License for more details. | ||
509 | 12 | * | ||
510 | 13 | * You should have received a copy of the GNU General Public License | ||
511 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
512 | 15 | * | ||
513 | 16 | * Authored by Didier Roche <didrocks@ubuntu.com> | ||
514 | 17 | * | ||
515 | 18 | */ | ||
516 | 19 | |||
517 | 20 | using Unity.MusicLens; | ||
518 | 21 | using Assertions; | ||
519 | 22 | |||
520 | 23 | public class Main | ||
521 | 24 | { | ||
522 | 25 | public static int main (string[] args) | ||
523 | 26 | { | ||
524 | 27 | Test.init (ref args); | ||
525 | 28 | |||
526 | 29 | Test.add_data_func ("/Unit/ParserChecker/Radios", test_radios); | ||
527 | 30 | Test.add_data_func ("/Unit/ParserChecker/Songs", test_songs); | ||
528 | 31 | Test.add_data_func ("/Unit/ParserChecker/LazyLoad", test_lazy_load); | ||
529 | 32 | Test.add_data_func ("/Unit/ParserChecker/LazyLoad", test_invalid_songload); | ||
530 | 33 | |||
531 | 34 | Test.run (); | ||
532 | 35 | |||
533 | 36 | return 0; | ||
534 | 37 | } | ||
535 | 38 | |||
536 | 39 | private static void test_radios () | ||
537 | 40 | { | ||
538 | 41 | var parser = new RhythmboxCollection.XmlParser (); | ||
539 | 42 | |||
540 | 43 | string collection_to_parse = """<?xml version="1.0" standalone="yes"?> | ||
541 | 44 | <rhythmdb version="1.8"> | ||
542 | 45 | <entry type="iradio"> | ||
543 | 46 | <title>Absolute Radio 80s (Modem)</title> | ||
544 | 47 | <genre>80's</genre> | ||
545 | 48 | <artist></artist> | ||
546 | 49 | <album></album> | ||
547 | 50 | <location>http://network.absoluteradio.co.uk/core/audio/ogg/live.pls?service=a8</location> | ||
548 | 51 | <play-count>6</play-count> | ||
549 | 52 | <last-played>1339693331</last-played> | ||
550 | 53 | <bitrate>32</bitrate> | ||
551 | 54 | <date>0</date> | ||
552 | 55 | <media-type>application/octet-stream</media-type> | ||
553 | 56 | </entry> | ||
554 | 57 | </rhythmdb>"""; | ||
555 | 58 | |||
556 | 59 | parser.track_info_ready.connect ((track) => | ||
557 | 60 | { | ||
558 | 61 | assert_cmpstr (track.title, OperatorType.EQUAL, "Absolute Radio 80s (Modem)"); | ||
559 | 62 | assert_cmpstr (track.genre, OperatorType.EQUAL, "other"); | ||
560 | 63 | assert_cmpstr (track.artist, OperatorType.EQUAL, ""); | ||
561 | 64 | assert_cmpstr (track.album, OperatorType.EQUAL, ""); | ||
562 | 65 | assert_cmpstr (track.uri, OperatorType.EQUAL, "http://network.absoluteradio.co.uk/core/audio/ogg/live.pls?service=a8"); | ||
563 | 66 | assert_cmpint (track.year, OperatorType.EQUAL, 0); | ||
564 | 67 | assert (track.type_track == TrackType.RADIO); | ||
565 | 68 | }); | ||
566 | 69 | parser.parse(collection_to_parse, collection_to_parse.length); | ||
567 | 70 | } | ||
568 | 71 | |||
569 | 72 | |||
570 | 73 | private static void test_songs () | ||
571 | 74 | { | ||
572 | 75 | var parser = new RhythmboxCollection.XmlParser (); | ||
573 | 76 | |||
574 | 77 | string collection_to_parse = """<?xml version="1.0" standalone="yes"?> | ||
575 | 78 | <rhythmdb version="1.8"> | ||
576 | 79 | <entry type="song"> | ||
577 | 80 | <title>LA PASSION</title> | ||
578 | 81 | <genre>Dance</genre> | ||
579 | 82 | <artist>GIGI D'AGOSTINO</artist> | ||
580 | 83 | <album>Loulou 007</album> | ||
581 | 84 | <duration>228</duration> | ||
582 | 85 | <file-size>3661842</file-size> | ||
583 | 86 | <location>file:///home/moi/Gigi%20d'agostino%20Passion.mp3</location> | ||
584 | 87 | <mtime>1338273042</mtime> | ||
585 | 88 | <first-seen>1338536342</first-seen> | ||
586 | 89 | <last-seen>1340378542</last-seen> | ||
587 | 90 | <bitrate>128</bitrate> | ||
588 | 91 | <date>730142</date> | ||
589 | 92 | <media-type>audio/mpeg</media-type> | ||
590 | 93 | <comment>http://www.danceparadise.ca.tc</comment> | ||
591 | 94 | </entry> | ||
592 | 95 | </rhythmdb>"""; | ||
593 | 96 | |||
594 | 97 | parser.track_info_ready.connect ((track) => | ||
595 | 98 | { | ||
596 | 99 | assert_cmpstr (track.title, OperatorType.EQUAL, "LA PASSION"); | ||
597 | 100 | assert_cmpstr (track.genre, OperatorType.EQUAL, "techno"); | ||
598 | 101 | assert_cmpstr (track.artist, OperatorType.EQUAL, "GIGI D'AGOSTINO"); | ||
599 | 102 | assert_cmpstr (track.album, OperatorType.EQUAL, "Loulou 007"); | ||
600 | 103 | assert_cmpstr (track.uri, OperatorType.EQUAL, "file:///home/moi/Gigi%20d'agostino%20Passion.mp3"); | ||
601 | 104 | assert_cmpint (track.year, OperatorType.EQUAL, 2000); | ||
602 | 105 | assert_cmpstr (track.mime_type, OperatorType.EQUAL, "audio/mpeg"); | ||
603 | 106 | assert (track.type_track == TrackType.SONG); | ||
604 | 107 | }); | ||
605 | 108 | parser.parse(collection_to_parse, collection_to_parse.length); | ||
606 | 109 | } | ||
607 | 110 | |||
608 | 111 | |||
609 | 112 | private static void test_lazy_load () | ||
610 | 113 | { | ||
611 | 114 | var parser = new RhythmboxCollection.XmlParser (); | ||
612 | 115 | |||
613 | 116 | string collection_to_parse_chunk = """<?xml version="1.0" standalone="yes"?> | ||
614 | 117 | <rhythmdb version="1.8"> | ||
615 | 118 | <entry type="song"> | ||
616 | 119 | <title>LA PASSION</title> | ||
617 | 120 | <genre>Dance</genre> | ||
618 | 121 | <artist>GIGI D'AGOSTINO</artist> | ||
619 | 122 | """; | ||
620 | 123 | parser.parse(collection_to_parse_chunk, collection_to_parse_chunk.length); | ||
621 | 124 | |||
622 | 125 | collection_to_parse_chunk = """ | ||
623 | 126 | <album>Loulou 007</album> | ||
624 | 127 | <duration>228</duration> | ||
625 | 128 | <file-size>3661842</file-size> | ||
626 | 129 | <location>file:///home/moi/Gigi%20d'agostino%20Passion.mp3</location> | ||
627 | 130 | <mtime>1338273042</mtime> | ||
628 | 131 | <first-seen>1338536342</first-seen> | ||
629 | 132 | <last-seen>1340378542</last-seen> | ||
630 | 133 | <bitrate>128</bitrate> | ||
631 | 134 | <date>730142</date> | ||
632 | 135 | <media-type>audio/mpeg</media-type> | ||
633 | 136 | <comment>http://www.danceparadise.ca.tc</comment> | ||
634 | 137 | </entry>"""; | ||
635 | 138 | parser.track_info_ready.connect ((track) => | ||
636 | 139 | { | ||
637 | 140 | assert_cmpstr (track.title, OperatorType.EQUAL, "LA PASSION"); | ||
638 | 141 | assert_cmpstr (track.album, OperatorType.EQUAL, "Loulou 007"); | ||
639 | 142 | assert (track.type_track == TrackType.SONG); | ||
640 | 143 | }); | ||
641 | 144 | parser.parse(collection_to_parse_chunk, collection_to_parse_chunk.length); | ||
642 | 145 | } | ||
643 | 146 | |||
644 | 147 | |||
645 | 148 | private static void test_invalid_songload () | ||
646 | 149 | { | ||
647 | 150 | var parser = new RhythmboxCollection.XmlParser (); | ||
648 | 151 | |||
649 | 152 | string collection_to_parse_chunk = """<?xml version="1.0" standalone="yes"?> | ||
650 | 153 | <rhythmdb version="1.8"> | ||
651 | 154 | <entry type="song"> | ||
652 | 155 | <title>LA PASSION</title> | ||
653 | 156 | <genre>Dance</genre> | ||
654 | 157 | <entry type="song"> | ||
655 | 158 | <title>le poisson</title> | ||
656 | 159 | <genre>Dance</genre> | ||
657 | 160 | </entry>"""; | ||
658 | 161 | |||
659 | 162 | parser.track_info_ready.connect ((track) => | ||
660 | 163 | { | ||
661 | 164 | assert_cmpstr (track.title, OperatorType.EQUAL, "le poisson"); | ||
662 | 165 | assert (track.type_track == TrackType.SONG); | ||
663 | 166 | }); | ||
664 | 167 | parser.parse(collection_to_parse_chunk, collection_to_parse_chunk.length); | ||
665 | 168 | } | ||
666 | 169 | |||
667 | 170 | } | ||
668 | 0 | \ No newline at end of file | 171 | \ No newline at end of file |
1) I think we may need to adjust album handling logic in "search" method, as iradio records seem to have empty album names - I think we should skip album if TYPE == RADIO; see lines 654 - 665, i.e. from_album = !(album in albums_ list_nosearch) ; track_from_ album) results_ model, model, iter, ResultType.ALBUM, category_id);
bool first_track_
...
if (first_
...
add_result (search.
2) Can you use TrackType as the type of Track - type_track instead of int?