Merge lp:~janez-troha/nuvola-player/8tracks into lp:nuvola-player/2.5.x
- 8tracks
- Merge into trunk
Proposed by
dz0ny
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Jiří Janoušek | ||||
Approved revision: | 107 | ||||
Merged at revision: | 108 | ||||
Proposed branch: | lp:~janez-troha/nuvola-player/8tracks | ||||
Merge into: | lp:nuvola-player/2.5.x | ||||
Diff against target: |
743 lines (+619/-35) 5 files modified
data/google-music-frame/scripts/eighttracks.js (+233/-0) src/8tracks.vala (+307/-0) src/application.vala (+5/-1) src/window.vala (+73/-34) wscript (+1/-0) |
||||
To merge this branch: | bzr merge lp:~janez-troha/nuvola-player/8tracks | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jiří Janoušek | Approve | ||
Review via email: mp+82771@code.launchpad.net |
Commit message
Description of the change
Hi, I've integrated 8tracks.com service, but had to modify the switch service GUI slightly.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'data/google-music-frame/images/8tracks.jpg' |
2 | Binary files data/google-music-frame/images/8tracks.jpg 1970-01-01 00:00:00 +0000 and data/google-music-frame/images/8tracks.jpg 2011-11-19 12:08:23 +0000 differ |
3 | === added file 'data/google-music-frame/scripts/eighttracks.js' |
4 | --- data/google-music-frame/scripts/eighttracks.js 1970-01-01 00:00:00 +0000 |
5 | +++ data/google-music-frame/scripts/eighttracks.js 2011-11-19 12:08:23 +0000 |
6 | @@ -0,0 +1,233 @@ |
7 | +/* |
8 | +8tracks.com |
9 | + |
10 | +Copyright 2011 Janez Troha <janez.troha@gmail.com> |
11 | + |
12 | +This program is free software: you can redistribute it and/or modify it |
13 | +under the terms of the GNU General Public License version 3, as published |
14 | +by the Free Software Foundation. |
15 | + |
16 | +This program is distributed in the hope that it will be useful, but |
17 | +WITHOUT ANY WARRANTY; without even the implied warranties of |
18 | +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
19 | +PURPOSE. See the GNU General Public License for more details. |
20 | + |
21 | +You should have received a copy of the GNU General Public License along |
22 | +with this program. If not, see <http://www.gnu.org/licenses/>. |
23 | +*/ |
24 | + |
25 | +(function(main_obj){ |
26 | + |
27 | +var hasClass = function(elm, klass){ |
28 | + var classes = elm.className.split(" "); |
29 | + for(var j=0; j < classes.length; j++){ |
30 | + console.log(classes[j]); |
31 | + if(classes[j] == klass) return true; |
32 | + } |
33 | + return false; |
34 | +} |
35 | + |
36 | +var toArray = function(obj) { |
37 | + return Array.prototype.slice.call(obj); |
38 | +} |
39 | + |
40 | +var gmf_bind = function(scope, fn) { |
41 | + return function () { |
42 | + return fn.apply(scope, toArray(arguments)); |
43 | + }; |
44 | +} |
45 | + |
46 | + |
47 | + |
48 | +/* used to propagate exception to main program */ |
49 | +var $throw_exception = function(message){ |
50 | + console.log("GMF::exception::" + message); |
51 | +} |
52 | + |
53 | +try{ |
54 | + /* |
55 | + * WebKit.WebView.console_message signal doesn't provide |
56 | + * debug/error/warn flag for console.debug/error/warn(). |
57 | + * Therefore we use these wrappers. |
58 | + */ |
59 | + var $log_debug = function(message){ |
60 | + console.log("GMF::debug::" + message); |
61 | + } |
62 | + |
63 | + var $log_info = function(message){ |
64 | + console.log("GMF::info::" + message); |
65 | + } |
66 | + |
67 | + var $log_warn = function(message){ |
68 | + console.log("GMF::warn::" + message); |
69 | + } |
70 | + |
71 | + var $log_error = function(message){ |
72 | + console.log("GMF::error::" + message); |
73 | + } |
74 | + |
75 | + |
76 | + var $GMF = function(){ |
77 | + this.SEPARATOR = "§#@!@#§"; |
78 | + this.changed_callbacks = []; |
79 | + this.album_art = null; |
80 | + this.artist = null; |
81 | + this.song = null; |
82 | + this.state = "none"; |
83 | + this.can_prev = false; |
84 | + this.can_next = false; |
85 | + this.timeout = null; |
86 | + this.iframe = document.createElement("iframe"); |
87 | + this.iframe.name = "GMF_iframe"; |
88 | + this.iframe.style.display = "none"; |
89 | + document.body.appendChild(this.iframe); |
90 | + var foo = gmf_bind(this, this.saveState); |
91 | + this.changed_callbacks.push(foo); |
92 | + this.update(); |
93 | + this.timeout = setInterval(gmf_bind(this, this.setCallback), 500); |
94 | + }; |
95 | + |
96 | + $GMF.prototype.setCallback = function(){ |
97 | + try{ |
98 | + this.update(window.player.set); |
99 | + //clearInterval(this.timeout); |
100 | + } |
101 | + catch(e){ |
102 | + |
103 | + } |
104 | + } |
105 | + |
106 | + $GMF.prototype.update = function(current_song){ |
107 | + $log_debug("Current song: " + current_song); |
108 | + if(!current_song){ |
109 | + try{ |
110 | + current_song = window.player.set; |
111 | + } |
112 | + catch(e){ |
113 | + console.log(e.message); |
114 | + } |
115 | + } |
116 | + if(!current_song) return; |
117 | + |
118 | + var album_art = null; |
119 | + var artist = null; |
120 | + var song = null; |
121 | + var state = null; |
122 | + try{ |
123 | + var info = current_song.track; |
124 | + if(info){ |
125 | + song = info.name; |
126 | + album = info.release_name; |
127 | + artist = info.performer; |
128 | + album_art = window.mix.cover_urls.sq133; |
129 | + this.can_next = current_song.skip_allowed; |
130 | + } |
131 | + |
132 | + if(window.player.is_playing()){ |
133 | + state = "playing"; |
134 | + } |
135 | + else { |
136 | + state = "paused"; |
137 | + } |
138 | + //~ console.log(current_song.status + " " + song + " by " + artist + " from " + album + ": " + album_art); |
139 | + } |
140 | + catch(e){ |
141 | + album_art = null; |
142 | + artist = null; |
143 | + song = null; |
144 | + state = null; |
145 | + } |
146 | + |
147 | + var changed = false; |
148 | + if(state !== this.state){ |
149 | + this.state = state; |
150 | + changed = true; |
151 | + } |
152 | + if(album_art !== this.album_art){ |
153 | + this.album_art = album_art; |
154 | + changed = true; |
155 | + } |
156 | + if(artist !== this.artist){ |
157 | + this.artist = artist; |
158 | + changed = true; |
159 | + } |
160 | + if(song !== this.song){ |
161 | + this.song = song; |
162 | + changed = true; |
163 | + } |
164 | + |
165 | + if(changed){ |
166 | + this.saveState(); |
167 | + } |
168 | + console.log(this.state + ", " + this.can_next + ", " + this.can_prev + ", " + this.album_art + ", " + this.artist + ", " + this.song); |
169 | + } |
170 | + |
171 | + $GMF.prototype.saveState = function(){ |
172 | + var state = this.state |
173 | + + this.SEPARATOR + (this.can_prev ? "true" : "false") |
174 | + + this.SEPARATOR + (this.can_next ? "true" : "false"); |
175 | + if(this.album_art !== null || this.artist !== null || this.song !== null){ |
176 | + state += this.SEPARATOR + (this.album_art === null ? "" : this.album_art) |
177 | + + this.SEPARATOR + (this.artist === null ? "" : this.artist) |
178 | + + this.SEPARATOR + (this.song === null ? "" : this.song); |
179 | + } |
180 | + |
181 | + var doc = this.iframe.contentDocument; |
182 | + if(doc.title != state) doc.title = state; |
183 | + } |
184 | + |
185 | + $GMF.prototype.command = function(cmd){ |
186 | + try{ |
187 | + console.log("kaj naj: "+cmd); |
188 | + |
189 | + if (cmd == "togglePlayPause") { |
190 | + window.$j('#player_play_button').trigger('click'); |
191 | + } |
192 | + if (cmd == "next") { |
193 | + window.$j('#player_skip_button').trigger('click'); |
194 | + } |
195 | + |
196 | + } |
197 | + catch(e){ |
198 | + $throw_exception(e.message); |
199 | + } |
200 | + } |
201 | + |
202 | + $GMF.prototype._triggerMouseEvent = function(elm, name){ |
203 | + var event = document.createEvent('MouseEvents'); |
204 | + event.initMouseEvent(name, true, true, document.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, elm); |
205 | + elm.dispatchEvent(event); |
206 | + } |
207 | + |
208 | + $GMF.prototype._clickOnElement = function(elm){ |
209 | + this._triggerMouseEvent(elm, 'mouseover'); |
210 | + this._triggerMouseEvent(elm, 'mousedown'); |
211 | + this._triggerMouseEvent(elm, 'mouseup'); |
212 | + } |
213 | + |
214 | + $GMF.prototype.thumbsUp = function(){ |
215 | + try{ |
216 | + window.Grooveshark.voteCurrentSong(1); |
217 | + } |
218 | + catch(e){ |
219 | + $throw_exception(e.message); |
220 | + } |
221 | + } |
222 | + |
223 | + $GMF.prototype.thumbsDown = function(){ |
224 | + try{ |
225 | + window.Grooveshark.voteCurrentSong(-1); |
226 | + } |
227 | + catch(e){ |
228 | + $throw_exception(e.message); |
229 | + } |
230 | + } |
231 | + |
232 | + |
233 | + main_obj.$GMF = new $GMF(); // Singleton ;-) |
234 | +} |
235 | +catch(e){ |
236 | + $throw_exception(e.message); |
237 | +} |
238 | + |
239 | +})(window); |
240 | \ No newline at end of file |
241 | |
242 | === added file 'src/8tracks.vala' |
243 | --- src/8tracks.vala 1970-01-01 00:00:00 +0000 |
244 | +++ src/8tracks.vala 2011-11-19 12:08:23 +0000 |
245 | @@ -0,0 +1,307 @@ |
246 | +/* |
247 | +Google Music Frame :: Frame |
248 | + |
249 | +Copyright 2011 Jiří Janoušek <janousek.jiri@gmail.com> |
250 | + |
251 | +This program is free software: you can redistribute it and/or modify it |
252 | +under the terms of the GNU General Public License version 3, as published |
253 | +by the Free Software Foundation. |
254 | + |
255 | +This program is distributed in the hope that it will be useful, but |
256 | +WITHOUT ANY WARRANTY; without even the implied warranties of |
257 | +MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
258 | +PURPOSE. See the GNU General Public License for more details. |
259 | + |
260 | +You should have received a copy of the GNU General Public License along |
261 | +with this program. If not, see <http://www.gnu.org/licenses/>. |
262 | +*/ |
263 | + |
264 | +using WebKit; |
265 | +using Soup; |
266 | +using Gee; |
267 | +using Fenryxo; |
268 | +using Fenryxo.Logger; |
269 | +using Fenryxo.Config; |
270 | +using Fenryxo.Path; |
271 | +using Fenryxo.Widgets; |
272 | + |
273 | +namespace GMF.Services{ |
274 | + |
275 | + |
276 | + |
277 | + /** |
278 | + * Frame with Google Music web interface. |
279 | + * Handles state changes received from WebView and produced by script |
280 | + * loaded in WebView, console logging, WebView requests, user scripts management, etc. |
281 | + */ |
282 | + public class EightTracks: Service{ |
283 | + /** |
284 | + * Constructs new Frame for application |
285 | + * |
286 | + * @param app Application object |
287 | + */ |
288 | + public class EightTracks(GMF.Application app, GMF.Frame frame, Storage storage){ |
289 | + base(app, frame, storage); |
290 | + this.home_url = "http://8tracks.com/"; |
291 | + this.base_url = "8tracks.com"; |
292 | + this.id = "eighttracks"; |
293 | + this.secure = false; |
294 | + if(this.secure){ |
295 | + log_message("Secure connection check is enabled."); |
296 | + } |
297 | + else{ |
298 | + log_warning("Secure connection check is disabled."); |
299 | + } |
300 | + } |
301 | + |
302 | + /** |
303 | + * Loads Google Music home page |
304 | + */ |
305 | + public override void go_home(){ |
306 | + var uri = this.home_url; |
307 | + if(this.secure && uri.has_prefix("http://")){ |
308 | + uri = "https://" + uri.substring(7); |
309 | + log_message("Redirect to %s", uri); |
310 | + } |
311 | + else if(!this.secure && uri.has_prefix("https://")){ |
312 | + uri = "http://" + uri.substring(8); |
313 | + log_message("Redirect to %s", uri); |
314 | + } |
315 | + this.frame.open(uri); |
316 | + } |
317 | + |
318 | + protected override void on_frame_loaded(WebFrame frame){ |
319 | + unowned string uri = frame.get_uri(); |
320 | + log_debug("Loading scripts for frame with uri: %s", uri ?? "null"); |
321 | + /* check frame and its URI to load scripts only |
322 | + * in Google Music web interface */ |
323 | + if(uri == null |
324 | + || frame != this.frame.get_main_frame() |
325 | + || (!uri.has_prefix("http://" + this.base_url) |
326 | + && !uri.has_prefix("https://" + this.base_url))) return; |
327 | + |
328 | + this.frame.load_scripts(this.id); |
329 | + } |
330 | + |
331 | + /** |
332 | + * Execute Google Music player action |
333 | + * |
334 | + * @param cmd Action |
335 | + * @throw FrameError on failure |
336 | + */ |
337 | + private void command(string cmd) throws FrameError{ |
338 | + log_debug("Frame command %s", cmd); |
339 | + this.frame.execute("$GMF.command('" + cmd + "');"); |
340 | + } |
341 | + |
342 | + /** |
343 | + * Skips to the next track in the tracklist. |
344 | + * |
345 | + * If there is no next track (and endless playback and track repeat are both off), |
346 | + * playback will be stopped. If playback is paused or stopped, it remains that way. |
347 | + * |
348 | + * @param notify if true a notification will be shown if needed |
349 | + */ |
350 | + public override void next_song(bool notify=true){ |
351 | + try{ |
352 | + this.skip_notification = ! notify; |
353 | + this.command("next"); |
354 | + } |
355 | + catch(FrameError e){ |
356 | + log_critical("Player: nextSong command failed: %s", e.message); |
357 | + if(!notify) this.skip_notification = false; |
358 | + } |
359 | + } |
360 | + |
361 | + /*** |
362 | + * Skips to the previous track in the tracklist. |
363 | + * |
364 | + * If there is no previous track (and endless playback and track repeat are both off), |
365 | + * playback will be stopped. If playback is paused or stopped, it remains that way. |
366 | + * |
367 | + * @param notify if true a notification will be shown if needed |
368 | + */ |
369 | + public override void previous_song(bool notify=true){ |
370 | + try{ |
371 | + this.skip_notification = ! notify; |
372 | + this.command("previous"); |
373 | + } |
374 | + catch(FrameError e){ |
375 | + log_critical("Player: prevSong command failed: %s", e.message); |
376 | + if(!notify) this.skip_notification = false; |
377 | + } |
378 | + } |
379 | + |
380 | + /** |
381 | + * Pauses playback. |
382 | + * |
383 | + * If playback is already paused, this has no effect. Calling Play after this should |
384 | + * cause playback to start again from the same position. |
385 | + * |
386 | + * @param notify if true a notification will be shown if needed |
387 | + */ |
388 | + public override void pause(bool notify=true){ |
389 | + /* No notifications are shown on pause action, |
390 | + * therefore notify param has no effect |
391 | + */ |
392 | + try{ |
393 | + this.command("pause"); |
394 | + } |
395 | + catch(FrameError e){ |
396 | + log_critical("Player: pauseSong command failed: %s", e.message); |
397 | + } |
398 | + } |
399 | + |
400 | + /** |
401 | + * Pauses playback. |
402 | + * If playback is already paused, resumes playback. |
403 | + * If playback is stopped, starts playback. |
404 | + * |
405 | + * @param notify if true a notification will be shown if needed |
406 | + */ |
407 | + public override void toggle_play(bool notify=true){ |
408 | + try{ |
409 | + if(this.playback_state != "playing") this.skip_notification = ! notify; |
410 | + this.command("togglePlayPause"); |
411 | + } |
412 | + catch(FrameError e){ |
413 | + log_critical("Player: playPause command failed: %s", e.message); |
414 | + if(!notify) this.skip_notification = false; |
415 | + } |
416 | + } |
417 | + |
418 | + /** |
419 | + * Stops playback. |
420 | + * |
421 | + * If playback is already stopped, this has no effect. Calling Play after this should |
422 | + * cause playback to start again from the beginning of the track. |
423 | + * |
424 | + * @param notify if true a notification will be shown if needed |
425 | + */ |
426 | + public override void stop(bool notify=true){ |
427 | + /* No notifications are shown on pause action, |
428 | + * therefore notify param has no effect |
429 | + */ |
430 | + this.pause(notify); |
431 | + } |
432 | + |
433 | + /** |
434 | + * Starts or resumes playback. |
435 | + * |
436 | + * If already playing, this has no effect. |
437 | + * If there is no track to play, this has no effect. |
438 | + * |
439 | + * @param notify if true a notification will be shown if needed |
440 | + */ |
441 | + public override void play(bool notify=true){ |
442 | + try{ |
443 | + this.skip_notification = ! notify; |
444 | + if(!this.playing) this.command("playPause"); |
445 | + } |
446 | + catch(FrameError e){ |
447 | + log_critical("Player: playPause command failed: %s", e.message); |
448 | + if(!notify) this.skip_notification = false; |
449 | + } |
450 | + } |
451 | + |
452 | + public override void thumbs_up(bool notify=true){ |
453 | + try{ |
454 | + //~ this.skip_notification = ! notify; |
455 | + this.frame.execute("$GMF.thumbsUp();"); |
456 | + } |
457 | + catch(FrameError e){ |
458 | + log_critical("Player: thumbUp command failed: %s", e.message); |
459 | + //~ if(!notify) this.skip_notification = false; |
460 | + } |
461 | + } |
462 | + |
463 | + public override void thumbs_down(bool notify=true){ |
464 | + try{ |
465 | + //~ this.skip_notification = ! notify; |
466 | + this.frame.execute("$GMF.thumbsDown();"); |
467 | + } |
468 | + catch(FrameError e){ |
469 | + log_critical("Player: thumbUp command failed: %s", e.message); |
470 | + //~ if(!notify) this.skip_notification = false; |
471 | + } |
472 | + } |
473 | + |
474 | + /** |
475 | + * Open new window in the default web browser |
476 | + */ |
477 | + protected override bool on_new_window(WebFrame frame, NetworkRequest req, |
478 | + WebNavigationAction action, WebPolicyDecision decision){ |
479 | + unowned string uri = req.get_uri(); |
480 | + log_debug("New window request: %s", uri); |
481 | + |
482 | + if(("accounts.google.com/" in uri) |
483 | + || ("google.com/accounts" in uri)){ |
484 | + this.frame.open(uri); |
485 | + } |
486 | + else{ |
487 | + this.open_in_web_browser(uri); |
488 | + } |
489 | + decision.ignore(); |
490 | + return true; |
491 | + } |
492 | + |
493 | + /** |
494 | + * Decide whether open page in frame or in the default browser |
495 | + */ |
496 | + protected override bool on_new_page(WebFrame frame, NetworkRequest req, |
497 | + WebNavigationAction action, WebPolicyDecision decision){ |
498 | + string uri = req.get_uri(); |
499 | + log_debug("New page request: URI: %s, frame URI: %s", |
500 | + uri, frame.get_uri() ?? "null"); |
501 | + |
502 | + if(frame != this.frame.get_main_frame()){ |
503 | + // don't care about pages in <iframe> elements |
504 | + return false; |
505 | + } |
506 | + |
507 | + /* Open Flash install page in the default browser */ |
508 | + if(uri.has_prefix("http://get.adobe.com/flashplayer")){ |
509 | + this.open_in_web_browser(uri); |
510 | + decision.ignore(); |
511 | + return true; |
512 | + } |
513 | + |
514 | + |
515 | + |
516 | + |
517 | + /* Open Google services in the default browser (except login page) */ |
518 | + if(("google.com" in uri) |
519 | + && !("music.google.com" in uri) |
520 | + && !("accounts.google.com/" in uri) |
521 | + && !("google.com/accounts" in uri)){ |
522 | + this.open_in_web_browser(uri); |
523 | + decision.ignore(); |
524 | + return true; |
525 | + } |
526 | + |
527 | + if(uri.has_prefix("https://" + this.base_url) |
528 | + || uri.has_prefix("http://" + this.base_url)){ |
529 | + if(this.secure && uri.has_prefix("http://")){ |
530 | + // Wanna HTTPS |
531 | + uri = "https://" + uri.substring(7); |
532 | + log_message("Reditect to %s", uri); |
533 | + this.frame.open(uri); |
534 | + decision.ignore(); |
535 | + return true; |
536 | + } |
537 | + else{ |
538 | + this.app.ui_state[this.id + ".last_uri"] = (owned) uri; |
539 | + try{ |
540 | + this.app.ui_state.save(); |
541 | + } |
542 | + catch(Error e){ |
543 | + log_warning("Unable to save UI state: %s", e.message); |
544 | + } |
545 | + |
546 | + } |
547 | + } |
548 | + return false; |
549 | + } |
550 | + } |
551 | + |
552 | +} |
553 | |
554 | === modified file 'src/application.vala' |
555 | --- src/application.vala 2011-11-17 13:46:39 +0000 |
556 | +++ src/application.vala 2011-11-19 12:08:23 +0000 |
557 | @@ -105,7 +105,7 @@ |
558 | */ |
559 | public override void run(){ |
560 | string? service = this.config["service"] ?? ""; |
561 | - if(service != "grooveshark" && service != "google-music"){ |
562 | + if(service != "grooveshark" && service != "google-music" && service != "eighttracks"){ |
563 | var dialog = new SelectServiceWindow(this, this.storage); |
564 | service = dialog.get_service(); |
565 | if(service == null){ |
566 | @@ -229,10 +229,14 @@ |
567 | } |
568 | |
569 | private Service load_service(string id){ |
570 | + if(id == "eighttracks") |
571 | + return new EightTracks(this, this.frame, this.storage); |
572 | if(id == "grooveshark") |
573 | return new Grooveshark(this, this.frame, this.storage); |
574 | if(id == "google-music") |
575 | return new GoogleMusic(this, this.frame, this.storage); |
576 | + |
577 | + |
578 | assert_not_reached(); |
579 | } |
580 | |
581 | |
582 | === modified file 'src/window.vala' |
583 | --- src/window.vala 2011-11-17 22:32:22 +0000 |
584 | +++ src/window.vala 2011-11-19 12:08:23 +0000 |
585 | @@ -315,7 +315,7 @@ |
586 | table.attach(label, 0, 2, line, line + 1, opt, opt, 15, 15); |
587 | |
588 | line++; |
589 | - |
590 | + //Google music start |
591 | button = new Gtk.Button(); |
592 | button.clicked.connect( () => { |
593 | this.service = "google-music"; |
594 | @@ -332,28 +332,8 @@ |
595 | label.use_markup = true; |
596 | button.add(label); |
597 | } |
598 | - table.attach(button, 1, 2, line, line + 1, opt, opt, 0, 10); |
599 | - |
600 | - button = new Gtk.Button(); |
601 | - button.clicked.connect( () => { |
602 | - this.service = "grooveshark"; |
603 | - this.response(ResponseType.OK); |
604 | - }); |
605 | - |
606 | - logo_file = Fenryxo.Path.get_data_file(app.app_name + "/images/grooveshark.png"); |
607 | - if(logo_file != null){ |
608 | - logo = new Gtk.Image.from_file(logo_file.get_path()); |
609 | - button.add(logo); |
610 | - } |
611 | - else{ |
612 | - label = new Gtk.Label("<big><b>Grooveshark</b></big>"); |
613 | - label.use_markup = true; |
614 | - button.add(label); |
615 | - } |
616 | table.attach(button, 0, 1, line, line + 1, opt, opt, 0, 10); |
617 | |
618 | - line++; |
619 | - |
620 | /// '<b>text</b>' makes 'text' bold |
621 | string about = _("""<b>Google Music</b> (formerly Music Beta by Google) is an online music streaming service that supports streaming music to desktop browsers and Android phones and tablets. The service is only available through invitation to US residents only. It supports uploading a user's own music and supports buying music at Android Market. |
622 | |
623 | @@ -363,7 +343,34 @@ |
624 | label.wrap_mode = Pango.WrapMode.WORD; |
625 | label.wrap = true; |
626 | table.attach(label, 1, 2, line, line + 1, opt, opt, 15, 10); |
627 | + |
628 | + button = new Gtk.Button.with_label("Use Music by Google"); |
629 | + button.clicked.connect( () => { |
630 | + this.service = "google-music"; |
631 | + this.response(ResponseType.OK); |
632 | + }); |
633 | + table.attach(button, 2, 3, line, line + 1, opt, opt, 0, 0); |
634 | + line++; |
635 | + //Google music end |
636 | + |
637 | + //Grooveshark start |
638 | + button = new Gtk.Button(); |
639 | + button.clicked.connect( () => { |
640 | + this.service = "grooveshark"; |
641 | + this.response(ResponseType.OK); |
642 | + }); |
643 | |
644 | + logo_file = Fenryxo.Path.get_data_file(app.app_name + "/images/grooveshark.png"); |
645 | + if(logo_file != null){ |
646 | + logo = new Gtk.Image.from_file(logo_file.get_path()); |
647 | + button.add(logo); |
648 | + } |
649 | + else{ |
650 | + label = new Gtk.Label("<big><b>Grooveshark</b></big>"); |
651 | + label.use_markup = true; |
652 | + button.add(label); |
653 | + } |
654 | + table.attach(button, 0, 1, line, line + 1, opt, opt, 0, 10); |
655 | /// '<b>text</b>' makes 'text' bold |
656 | about = _("""<b>Grooveshark</b> is an international online music search engine, music streaming service and music recommendation web software application, allowing users to search for, stream, and upload music that can be played immediately or added to a playlist. An optional paid subscription adds additional functionality and removes advertisements. |
657 | |
658 | @@ -372,28 +379,60 @@ |
659 | label.use_markup = true; |
660 | label.wrap_mode = Pango.WrapMode.WORD; |
661 | label.wrap = true; |
662 | - table.attach(label, 0, 1, line, line + 1, opt, opt, 15, 10); |
663 | - |
664 | - |
665 | -line++; |
666 | - |
667 | - button = new Gtk.Button.with_label("Use Music Beta by Google"); |
668 | - button.clicked.connect( () => { |
669 | - this.service = "google-music"; |
670 | - this.response(ResponseType.OK); |
671 | - }); |
672 | - table.attach(button, 1, 2, line, line + 1, opt, opt, 0, 0); |
673 | + table.attach(label, 1, 2, line, line + 1, opt, opt, 15, 10); |
674 | + |
675 | |
676 | button = new Gtk.Button.with_label("Use Grooveshark"); |
677 | button.clicked.connect( () => { |
678 | this.service = "grooveshark"; |
679 | this.response(ResponseType.OK); |
680 | }); |
681 | - table.attach(button, 0, 1, line, line + 1, opt, opt, 0, 0); |
682 | - |
683 | + table.attach(button, 2, 3, line, line + 1, opt, opt, 0, 0); |
684 | + line++; |
685 | + //Grooveshark end |
686 | + |
687 | + //8Tracks start |
688 | + button = new Gtk.Button(); |
689 | + button.clicked.connect( () => { |
690 | + this.service = "eighttracks"; |
691 | + this.response(ResponseType.OK); |
692 | + }); |
693 | + |
694 | + logo_file = Fenryxo.Path.get_data_file(app.app_name + "/images/8tracks.jpg"); |
695 | + if(logo_file != null){ |
696 | + logo = new Gtk.Image.from_file(logo_file.get_path()); |
697 | + button.add(logo); |
698 | + } |
699 | + else{ |
700 | + label = new Gtk.Label("<big><b>8tracks</b></big>"); |
701 | + label.use_markup = true; |
702 | + button.add(label); |
703 | + } |
704 | + table.attach(button, 0, 1, line, line + 1, opt, opt, 0, 10); |
705 | + /// '<b>text</b>' makes 'text' bold |
706 | + about = _("""<b>8tracks</b> is a website that fuses elements of internet radio and social networking revolving around the concept of streaming user-curated playlists consisting of at least 8 tracks. |
707 | + |
708 | +<i>Source: <a href="http://en.wikipedia.org/wiki/8tracks.com">8tracks.com on Wikipedia</a>, <a href="http://8tracks.com">Official website</a></i>"""); |
709 | + label = new Gtk.Label(about); |
710 | + label.use_markup = true; |
711 | + label.wrap_mode = Pango.WrapMode.WORD; |
712 | + label.wrap = true; |
713 | + table.attach(label, 1, 2, line, line + 1, opt, opt, 15, 10); |
714 | + |
715 | + |
716 | + button = new Gtk.Button.with_label("Use 8tracks"); |
717 | + button.clicked.connect( () => { |
718 | + this.service = "eighttracks"; |
719 | + this.response(ResponseType.OK); |
720 | + }); |
721 | + table.attach(button, 2, 3, line, line + 1, opt, opt, 0, 0); |
722 | + //8Tracks end |
723 | + |
724 | var content = this.get_content_area() as Gtk.Container; |
725 | content.add(table); |
726 | content.show_all(); |
727 | + |
728 | + |
729 | } |
730 | |
731 | public string? get_service(){ |
732 | |
733 | === modified file 'wscript' |
734 | --- wscript 2011-11-17 13:12:43 +0000 |
735 | +++ wscript 2011-11-19 12:08:23 +0000 |
736 | @@ -180,6 +180,7 @@ |
737 | 'src/base-service.vala', |
738 | 'src/google-music.vala', |
739 | 'src/grooveshark.vala', |
740 | + 'src/8tracks.vala', |
741 | 'src/application.vala', |
742 | 'src/player.vala', |
743 | 'src/mpris.vala', |
Thanks for your contribution to the Nuvola Player!