Merge lp:~artem-anufrij/audience/playlist-rewrite into lp:~audience-members/audience/trunk

Proposed by Artem Anufrij
Status: Rejected
Rejected by: Danielle Foré
Proposed branch: lp:~artem-anufrij/audience/playlist-rewrite
Merge into: lp:~audience-members/audience/trunk
Diff against target: 1481 lines (+453/-511)
11 files modified
src/CMakeLists.txt (+2/-2)
src/Objects/Video.vala (+7/-2)
src/Widgets/BottomBar.vala (+28/-21)
src/Widgets/EpisodesPage.vala (+23/-5)
src/Widgets/LibraryPage.vala (+5/-4)
src/Widgets/PlayerPage.vala (+42/-82)
src/Widgets/Playlist.vala (+199/-196)
src/Widgets/PlaylistItem.vala (+66/-0)
src/Widgets/PlaylistPopover.vala (+0/-118)
src/Widgets/WelcomePage.vala (+41/-34)
src/Window.vala (+40/-47)
To merge this branch: bzr merge lp:~artem-anufrij/audience/playlist-rewrite
Reviewer Review Type Date Requested Status
Jeremy Wootten code, ui, function Needs Fixing
Review via email: mp+307248@code.launchpad.net

Description of the change

* Playlist redesign
* Bottom bar: Adden "Next" button
* Playlist: Added "Delete" button
* EpisodesView: Added "Play all" button

To post a comment you must log in.
680. By Artem Anufrij

no autohide for playlist

681. By Artem Anufrij

* save playlist
* restore playlist
* Welcome button: resume playlist
* Welcome button: replay playlist
* Welcome button: resume last video
* welcome button: replay last video

682. By Artem Anufrij

DnD on welcome screen

683. By Artem Anufrij

visiualisize playlist

Revision history for this message
Artem Anufrij (artem-anufrij) wrote :

Perhaps someone could check this branch.

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

Conflicts with trunk. I tested after merging and resolving conflicts.

Compilation warnings:
Bottom Bar: playlist_item.added not used.
PlayList::add_from_file - unhandled GLib.Error, misaligned lines

variable name instand_play should be "instant play".
some formatting issues (see inline)

UI:
Add and remove icons not consistent with other elementary apps - use + - buttons at bottom?
Use of trash icon misleading. User might think the original video will be trashed?
Playlist too narrow when empty - need empty message?

FUNCTION:
After adding file(s) they do not appear until playlist hidden/opened or app restarted.

review: Needs Fixing (code, ui, function)
Revision history for this message
Artem Anufrij (artem-anufrij) wrote :

@Jeremy: Dan said I should to break up to work on this branch. Thank you for your time...

Revision history for this message
Jeremy Wootten (jeremywootten) wrote :

Hi Artem.

Do you mean this branch is abandoned/rejected or just on hold? Or it needs
breaking up into smaller branches?

If so it should be marked as "in progress" or be withdrawn...

On 16 December 2016 at 16:40, Artem Anufrij <email address hidden> wrote:

> @Jeremy: Dan said I should to break up to work on this branch. Thank you
> for your time...
> --
> https://code.launchpad.net/~artem-anufrij/audience/
> playlist-rewrite/+merge/307248
> You are reviewing the proposed merge of lp:~artem-anufrij/audience/playlist-rewrite
> into lp:audience.
>

Revision history for this message
Danielle Foré (danrabbit) wrote :

We can probably resume trying to break up this branch into separate PRs on GitHub. Rejecting for now

Unmerged revisions

683. By Artem Anufrij

visiualisize playlist

682. By Artem Anufrij

DnD on welcome screen

681. By Artem Anufrij

* save playlist
* restore playlist
* Welcome button: resume playlist
* Welcome button: replay playlist
* Welcome button: resume last video
* welcome button: replay last video

680. By Artem Anufrij

no autohide for playlist

679. By Artem Anufrij

development

678. By Artem Anufrij

added missing file

677. By Artem Anufrij

begin playlist rewrite

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/CMakeLists.txt'
2--- src/CMakeLists.txt 2016-09-26 20:52:11 +0000
3+++ src/CMakeLists.txt 2016-09-30 22:31:06 +0000
4@@ -50,11 +50,11 @@
5 DiskManager.vala
6 Window.vala
7 Widgets/BottomBar.vala
8+ Widgets/Playlist.vala
9+ Widgets/PlaylistItem.vala
10 Widgets/SettingsPopover.vala
11 Widgets/PreviewPopover.vala
12 Widgets/TimeWidget.vala
13- Widgets/Playlist.vala
14- Widgets/PlaylistPopover.vala
15 Widgets/WelcomePage.vala
16 Widgets/PlayerPage.vala
17 Widgets/LibraryPage.vala
18
19=== modified file 'src/Objects/Video.vala'
20--- src/Objects/Video.vala 2016-09-27 20:26:37 +0000
21+++ src/Objects/Video.vala 2016-09-30 22:31:06 +0000
22@@ -27,7 +27,7 @@
23 public signal void thumbnail_changed ();
24 public signal void trashed ();
25
26- public File video_file { get; private set; }
27+ public File? video_file { get; private set; default = null;}
28 public string directory { get; construct set; }
29 public string file { get; construct set; }
30
31@@ -55,10 +55,15 @@
32 manager = Audience.Services.LibraryManager.get_instance ();
33 manager.thumbler.finished.connect (dbus_finished);
34
35+ if (directory.has_prefix ("file:///")) {
36+ video_file = File.new_for_uri (directory + "/" + file);
37+ } else {
38+ video_file = File.new_for_path (get_path ());
39+ }
40+
41 title = Audience.get_title (file);
42
43 extract_metadata ();
44- video_file = File.new_for_path (this.get_path ());
45
46 if (directory != Audience.settings.library_folder) {
47 container = Path.get_basename (directory);
48
49=== modified file 'src/Widgets/BottomBar.vala'
50--- src/Widgets/BottomBar.vala 2016-09-28 02:43:54 +0000
51+++ src/Widgets/BottomBar.vala 2016-09-30 22:31:06 +0000
52@@ -24,6 +24,7 @@
53 private const string PULSE_TYPE = "attention";
54
55 public signal void play_toggled ();
56+ public signal void playlist_clicked ();
57 public signal void unfullscreen ();
58 public signal void seeked (double val);
59
60@@ -31,26 +32,27 @@
61 public bool hovered { get; set; default=false; }
62 public bool fullscreen { get; set; default=false; }
63 public SettingsPopover preferences_popover;
64- public PlaylistPopover playlist_popover;
65 public TimeWidget time_widget;
66+ public Audience.Widgets.Playlist playlist;
67
68 private Gtk.Button play_button;
69+ private Gtk.Button next_button;
70 private Gtk.Button preferences_button;
71 private Gtk.Button playlist_button;
72 private Gtk.Revealer unfullscreen_revealer;
73 private uint hiding_timer = 0;
74 private bool playlist_glowing = false;
75
76- public bool repeat {
77- get {
78- return playlist_popover.rep.active;
79- }
80- set {
81- playlist_popover.rep.active = value;
82- }
83- }
84-
85 public BottomBar (ClutterGst.Playback playback) {
86+ playlist = Audience.Widgets.Playlist.get_instance ();
87+ playlist.collection_changed.connect ((size) => { next_button.visible = size > 1; });
88+ playlist.visibility_changed.connect ((visible) => {
89+ if (visible) {
90+ playlist_button.image = new Gtk.Image.from_icon_name ("pane-hide-symbolic", Gtk.IconSize.BUTTON);
91+ } else {
92+ playlist_button.image = new Gtk.Image.from_icon_name ("pane-show-symbolic", Gtk.IconSize.BUTTON);
93+ }
94+ });
95 this.events |= Gdk.EventMask.POINTER_MOTION_MASK;
96 this.events |= Gdk.EventMask.LEAVE_NOTIFY_MASK;
97 this.events |= Gdk.EventMask.ENTER_NOTIFY_MASK;
98@@ -66,34 +68,36 @@
99 play_button.tooltip_text = _("Play");
100 play_button.clicked.connect (() => {play_toggled ();});
101
102- playlist_button = new Gtk.Button.from_icon_name ("view-list-symbolic", Gtk.IconSize.BUTTON);
103+ next_button = new Gtk.Button.from_icon_name ("media-seek-forward-symbolic", Gtk.IconSize.BUTTON);
104+ next_button.tooltip_text = _("Next");
105+ next_button.clicked.connect (() => { playlist.next ();});
106+
107+ playlist_button = new Gtk.Button.from_icon_name ("pane-show-symbolic", Gtk.IconSize.BUTTON);
108 playlist_button.tooltip_text = _("Playlist");
109- playlist_button.clicked.connect (() => {playlist_popover.show_all (); playlist_popover.queue_resize ();});
110+ playlist_button.clicked.connect (() => { playlist.toggle_reveal_control (); });
111
112 preferences_button = new Gtk.Button.from_icon_name ("open-menu-symbolic", Gtk.IconSize.BUTTON);
113 preferences_button.tooltip_text = _("Settings");
114 preferences_button.clicked.connect (() => {
115 preferences_popover.setup ();
116- preferences_popover.show_all ();
117+ preferences_popover.show_all ();
118 preferences_popover.queue_resize ();
119 });
120
121 time_widget = new TimeWidget (playback);
122
123- playlist_popover = new PlaylistPopover ();
124- playlist_popover.relative_to = playlist_button;
125+
126 preferences_popover = new SettingsPopover (playback);
127 preferences_popover.relative_to = preferences_button;
128
129 main_actionbar.pack_start (play_button);
130+ main_actionbar.pack_start (next_button);
131 main_actionbar.set_center_widget (time_widget);
132+ main_actionbar.pack_end (playlist_button);
133 main_actionbar.pack_end (preferences_button);
134- main_actionbar.pack_end (playlist_button);
135 add (main_actionbar);
136
137- playlist_popover.playlist.item_added.connect (() => {
138- playlist_item_added ();
139- });
140+
141
142 notify["hovered"].connect (() => {
143 if (hovered == false) {
144@@ -131,6 +135,7 @@
145 });
146
147 show_all ();
148+ next_button.visible = playlist.size > 1;
149 }
150
151 private void playlist_item_added () {
152@@ -138,7 +143,7 @@
153 playlist_glowing = true;
154 playlist_button.get_child ().get_style_context ().add_class (PULSE_CLASS);
155 playlist_button.get_child ().get_style_context ().add_class (PULSE_TYPE);
156-
157+
158 Timeout.add (6000, () => {
159 playlist_button.get_child ().get_style_context ().remove_class (PULSE_CLASS);
160 playlist_button.get_child ().get_style_context ().remove_class (PULSE_TYPE);
161@@ -188,11 +193,13 @@
162 Source.remove (hiding_timer);
163
164 hiding_timer = GLib.Timeout.add (2000, () => {
165- if (hovered == true || preferences_popover.visible == true || playlist_popover.visible == true || playing == false) {
166+ if (hovered == true || preferences_popover.visible == true || playing == false) {
167 hiding_timer = 0;
168 return false;
169 }
170+ playlist_button.image = new Gtk.Image.from_icon_name ("pane-show-symbolic", Gtk.IconSize.BUTTON);
171 set_reveal_child (false);
172+ playlist.set_reveal_child (false);
173 unfullscreen_revealer.set_reveal_child (false);
174 hiding_timer = 0;
175 return false;
176
177=== modified file 'src/Widgets/EpisodesPage.vala'
178--- src/Widgets/EpisodesPage.vala 2016-09-27 20:26:37 +0000
179+++ src/Widgets/EpisodesPage.vala 2016-09-30 22:31:06 +0000
180@@ -22,15 +22,18 @@
181 namespace Audience {
182 public class EpisodesPage : Gtk.Grid {
183 public Gtk.Image poster { get; set; }
184+ Gtk.Button play_all;
185 Gtk.ScrolledWindow scrolled_window;
186 Gtk.FlowBox view_episodes;
187 Granite.Widgets.AlertView alert_view;
188
189 public Audience.Services.LibraryManager manager;
190+ public Audience.Widgets.Playlist playlist;
191
192 string query;
193
194 construct {
195+ playlist = Audience.Widgets.Playlist.get_instance ();
196 query = "";
197
198 poster = new Gtk.Image ();
199@@ -39,6 +42,13 @@
200 poster.valign = Gtk.Align.START;
201 poster.get_style_context ().add_class ("card");
202
203+ play_all = new Gtk.Button ();
204+ play_all.margin_left = 24;
205+ play_all.vexpand = true;
206+ play_all.valign = Gtk.Align.START;
207+ play_all.label = _("Play all");
208+ play_all.clicked.connect (play_all_episodes);
209+
210 view_episodes = new Gtk.FlowBox ();
211 view_episodes.margin = 24;
212 view_episodes.homogeneous = true;
213@@ -58,9 +68,10 @@
214 alert_view.hide ();
215
216 expand = true;
217- attach (poster, 0, 1, 1, 1);
218- attach (scrolled_window, 1, 1, 1, 1);
219- attach (alert_view, 1, 1, 1, 1);
220+ attach (poster, 0, 0, 1, 1);
221+ attach (play_all, 0, 1, 1 ,1);
222+ attach (scrolled_window, 1, 0, 1, 2);
223+ attach (alert_view, 1, 0, 1, 2);
224
225 manager = Audience.Services.LibraryManager.get_instance ();
226 manager.video_file_deleted.connect (remove_item_from_path);
227@@ -81,8 +92,7 @@
228 var selected = (item as Audience.LibraryItem);
229 var video = selected.episodes.first ();
230 if (video.video_file.query_exists ()) {
231- bool from_beginning = video.video_file.get_uri () != settings.current_video;
232- App.get_instance ().mainwindow.play_file (video.video_file.get_uri (), from_beginning);
233+ playlist.add_item (video);
234 }
235 }
236
237@@ -153,6 +163,14 @@
238 return false;
239 }
240
241+ public void play_all_episodes () {
242+ playlist.clear ();
243+ view_episodes.forall ((item)=> {
244+ playlist.add_item ((item as LibraryItem).episodes.first (), false);
245+ });
246+ playlist.play_playlist ();
247+ }
248+
249 public void show_alert (string primary_text, string secondary_text, string icon_name) {
250 alert_view.no_show_all = false;
251 alert_view.show_all ();
252
253=== modified file 'src/Widgets/LibraryPage.vala'
254--- src/Widgets/LibraryPage.vala 2016-09-27 20:26:37 +0000
255+++ src/Widgets/LibraryPage.vala 2016-09-30 22:31:06 +0000
256@@ -27,6 +27,7 @@
257
258 public Gtk.FlowBox view_movies;
259 public Audience.Services.LibraryManager manager;
260+ public Audience.Widgets.Playlist playlist;
261 public Gtk.ScrolledWindow scrolled_window;
262 bool poster_initialized = false;
263 string query;
264@@ -45,11 +46,12 @@
265
266 construct {
267 manager = Audience.Services.LibraryManager.get_instance ();
268-
269+ playlist = Audience.Widgets.Playlist.get_instance ();
270 query = "";
271
272 scrolled_window = new Gtk.ScrolledWindow (null, null);
273- scrolled_window.expand = true;
274+ scrolled_window.height_request = 100;
275+ scrolled_window.width_request = 100;
276
277 view_movies = new Gtk.FlowBox ();
278 view_movies.margin = 24;
279@@ -88,8 +90,7 @@
280 var selected = (item as Audience.LibraryItem);
281
282 if (selected.episodes.size == 1) {
283- bool from_beginning = selected.episodes.first ().video_file.get_uri () != settings.current_video;
284- App.get_instance ().mainwindow.play_file (selected.episodes.first ().video_file.get_uri (), from_beginning);
285+ playlist.add_item (selected.episodes.first ());
286 } else {
287 last_filter = query;
288 show_episodes (selected);
289
290=== modified file 'src/Widgets/PlayerPage.vala'
291--- src/Widgets/PlayerPage.vala 2016-09-28 02:43:54 +0000
292+++ src/Widgets/PlayerPage.vala 2016-09-30 22:31:06 +0000
293@@ -11,29 +11,22 @@
294 public class PlayerPage : Gtk.EventBox {
295 public signal void unfullscreen_clicked ();
296 public signal void ended ();
297+ public signal void started (Audience.Objects.Video video);
298
299 public GtkClutter.Embed clutter;
300 private Clutter.Actor video_actor;
301 private Audience.Widgets.BottomBar bottom_bar;
302+ private Audience.Widgets.Playlist playlist_bar;
303 private Clutter.Stage stage;
304 private Gtk.Revealer unfullscreen_bar;
305 private GtkClutter.Actor unfullscreen_actor;
306 private GtkClutter.Actor bottom_actor;
307+ private GtkClutter.Actor playlist_actor;
308 private GnomeMediaKeys mediakeys;
309 private ClutterGst.Playback playback;
310
311 private bool mouse_primary_down = false;
312
313- public bool repeat {
314- get{
315- return bottom_bar.repeat;
316- }
317-
318- set{
319- bottom_bar.repeat = value;
320- }
321- }
322-
323 public bool playing {
324 get {
325 return playback.playing;
326@@ -101,8 +94,24 @@
327 bottom_bar.bind_property ("playing", playback, "playing", BindingFlags.BIDIRECTIONAL);
328 bottom_bar.unfullscreen.connect (() => unfullscreen_clicked ());
329
330+ playlist_bar = Audience.Widgets.Playlist.get_instance ();
331+ playlist_bar.play.connect ((video, progress) => { play_video (video, progress); });
332+ playlist_bar.collection_changed.connect ((size) => {
333+ if (size == 0 && playing) {
334+ playing = false;
335+ reset_played_uri ();
336+ ended ();
337+ }
338+ });
339+
340 unfullscreen_bar = bottom_bar.get_unfullscreen_button ();
341
342+ playlist_actor = new GtkClutter.Actor.with_contents (playlist_bar);
343+ playlist_actor.opacity = GLOBAL_OPACITY;
344+ playlist_actor.add_constraint (new Clutter.BindConstraint (stage, Clutter.BindCoordinate.HEIGHT, 0));
345+ playlist_actor.add_constraint (new Clutter.AlignConstraint (stage, Clutter.AlignAxis.X_AXIS, 1));
346+ stage.add_child (playlist_actor);
347+
348 bottom_actor = new GtkClutter.Actor.with_contents (bottom_bar);
349 bottom_actor.opacity = GLOBAL_OPACITY;
350 bottom_actor.add_constraint (new Clutter.BindConstraint (stage, Clutter.BindCoordinate.WIDTH, 0));
351@@ -117,17 +126,16 @@
352
353 //media keys
354 try {
355- mediakeys = Bus.get_proxy_sync (BusType.SESSION,
356- "org.gnome.SettingsDaemon", "/org/gnome/SettingsDaemon/MediaKeys");
357+ mediakeys = Bus.get_proxy_sync (BusType.SESSION, "org.gnome.SettingsDaemon", "/org/gnome/SettingsDaemon/MediaKeys");
358 mediakeys.MediaPlayerKeyPressed.connect ((bus, app, key) => {
359 if (app != "audience")
360 return;
361 switch (key) {
362 case "Previous":
363- get_playlist_widget ().previous ();
364+ playlist_bar.previous ();
365 break;
366 case "Next":
367- get_playlist_widget ().next ();
368+ playlist_bar.next ();
369 break;
370 case "Play":
371 playback.playing = !playback.playing;
372@@ -181,13 +189,11 @@
373 });
374
375 this.destroy.connect (() => {
376- // FIXME:should find better way to decide if its end of playlist
377- if (playback.progress > 0.99)
378+ if (playback.progress < 1) {
379+ settings.last_stopped = playback.progress;
380+ } else {
381 settings.last_stopped = 0;
382- else
383- settings.last_stopped = playback.progress;
384-
385- get_playlist_widget ().save_playlist ();
386+ }
387 Audience.Services.Inhibitor.get_instance ().uninhibit ();
388 });
389
390@@ -195,25 +201,13 @@
391 playback.eos.connect (() => {
392 Idle.add (() => {
393 playback.progress = 0;
394- if (!get_playlist_widget ().next ()) {
395- if (repeat) {
396- play_file (get_playlist_widget ().get_first_item ().get_uri ());
397- playback.playing = true;
398- } else {
399- playback.playing = false;
400- settings.last_stopped = 0;
401- ended ();
402- }
403+ if (!playlist_bar.next ()) {
404+ ended ();
405 }
406 return false;
407 });
408 });
409
410- //playlist wants us to open a file
411- get_playlist_widget ().play.connect ((file) => {
412- this.play_file (file.get_uri ());
413- });
414-
415 bottom_bar.notify["child-revealed"].connect (() => {
416 if (bottom_bar.child_revealed == true) {
417 App.get_instance ().mainwindow.get_window ().set_cursor (null);
418@@ -230,6 +224,7 @@
419 Audience.Services.Inhibitor.get_instance ().inhibit ();
420 } else {
421 Audience.Services.Inhibitor.get_instance ().uninhibit ();
422+ settings.last_stopped = playback.progress;
423 }
424 });
425
426@@ -237,24 +232,20 @@
427 show_all ();
428 }
429
430- public void play_file (string uri, bool from_beginning = true) {
431- debug ("Opening %s", uri);
432- get_playlist_widget ().set_current (uri);
433+ private void play_video (Audience.Objects.Video video, double progress = 0) {
434+ string? uri = video.video_file.get_uri ();
435 playback.uri = uri;
436
437 string? sub_uri = get_subtitle_for_uri (uri);
438- if (sub_uri != null && sub_uri != uri)
439+ if (sub_uri != null && sub_uri != uri) {
440 playback.set_subtitle_uri (sub_uri);
441-
442- App.get_instance ().mainwindow.title = get_title (uri);
443-
444- if (from_beginning) {
445- playback.progress = 0.0;
446- } else {
447- playback.progress = settings.last_stopped;
448- }
449-
450+ }
451+
452+ if (playback.progress != progress) {
453+ playback.progress = progress;
454+ }
455 playback.playing = !settings.playback_wait;
456+
457 Gtk.RecentManager recent_manager = Gtk.RecentManager.get_default ();
458 recent_manager.add_item (uri);
459
460@@ -262,53 +253,26 @@
461
462 Audience.Services.Inhibitor.get_instance ().inhibit ();
463 settings.current_video = uri;
464+
465+ started (video);
466 }
467
468 public double get_progress () {
469 return playback.progress;
470 }
471
472- public string get_played_uri () {
473- return playback.uri;
474- }
475-
476 public void reset_played_uri () {
477 playback.uri = "";
478 }
479
480- public void next () {
481- get_playlist_widget ().next ();
482- }
483-
484- public void prev () {
485- get_playlist_widget ().next ();
486- }
487-
488- public void resume_last_videos () {
489- play_file (settings.current_video);
490- playback.playing = false;
491- if (settings.resume_videos) {
492- playback.progress = settings.last_stopped;
493- } else {
494- playback.progress = 0.0;
495- }
496-
497- playback.playing = !settings.playback_wait;
498- }
499-
500 public void append_to_playlist (File file) {
501 if (playback.playing && is_subtitle (file.get_uri ())) {
502 playback.set_subtitle_uri (file.get_uri ());
503 } else {
504- get_playlist_widget ().add_item (file);
505+ playlist_bar.add_from_file (file);
506 }
507 }
508
509- public void play_first_in_playlist () {
510- var file = get_playlist_widget ().get_first_item ();
511- play_file (file.get_uri ());
512- }
513-
514 public void reveal_control () {
515 bottom_bar.reveal_control ();
516 }
517@@ -328,10 +292,6 @@
518 playback.progress = double.min (new_progress, 1.0);
519 }
520
521- public Widgets.Playlist get_playlist_widget () {
522- return bottom_bar.playlist_popover.playlist;
523- }
524-
525 private string? get_subtitle_for_uri (string uri) {
526 string without_ext;
527 int last_dot = uri.last_index_of (".", 0);
528@@ -365,7 +325,7 @@
529 public bool update_pointer_position (double y, int window_height) {
530 App.get_instance ().mainwindow.get_window ().set_cursor (null);
531
532- bottom_bar.reveal_control ();
533+ reveal_control ();
534
535 return false;
536 }
537
538=== modified file 'src/Widgets/Playlist.vala'
539--- src/Widgets/Playlist.vala 2016-08-19 16:27:45 +0000
540+++ src/Widgets/Playlist.vala 2016-09-30 22:31:06 +0000
541@@ -1,6 +1,6 @@
542 // -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
543 /*-
544- * Copyright (c) 2013-2014 Audience Developers (http://launchpad.net/pantheon-chat)
545+ * Copyright (c) 2016-2016 elementary LLC.
546 *
547 * This program is free software: you can redistribute it and/or modify
548 * it under the terms of the GNU General Public License as published by
549@@ -15,221 +15,224 @@
550 * You should have received a copy of the GNU General Public License
551 * along with this program. If not, see <http://www.gnu.org/licenses/>.
552 *
553- * Authored by: Tom Beckmann <tomjonabc@gmail.com>
554+ * Authored by: Artem Anufrij <artem.anufrij@live.de>
555+ *
556 */
557
558 namespace Audience.Widgets {
559- public class Playlist : Gtk.TreeView {
560- // the player is requested to play path
561- public signal void play (File path);
562- public signal void item_added ();
563-
564- private enum Columns {
565- PLAYING,
566- TITLE,
567- FILENAME,
568- N_COLUMNS
569+ public class Playlist : Gtk.Revealer {
570+
571+ public signal void play (Audience.Objects.Video video, double process = 0);
572+ public signal void collection_changed (uint size);
573+ public signal void visibility_changed (bool visible);
574+
575+ Gtk.Grid grid;
576+ Gtk.ScrolledWindow scrolled_window;
577+ Gtk.ListBox listbox;
578+ Gtk.ToggleButton repeat_button;
579+
580+ public uint size { get { return listbox.get_children ().length (); } }
581+
582+ static Playlist _instance = null;
583+ public static Playlist get_instance () {
584+ if (_instance == null) {
585+ _instance = new Playlist ();
586+ }
587+ return _instance;
588 }
589
590- private int current = 0;
591- private Gtk.ListStore playlist;
592-
593- public Playlist () {
594- this.playlist = new Gtk.ListStore (Columns.N_COLUMNS, typeof (Icon), typeof (string), typeof (string));
595- this.model = this.playlist;
596- this.expand = true;
597- this.headers_visible = false;
598- this.activate_on_single_click = true;
599- this.can_focus = false;
600- get_selection ().mode = Gtk.SelectionMode.NONE;
601-
602- var text_render = new Gtk.CellRendererText ();
603- text_render.ellipsize = Pango.EllipsizeMode.MIDDLE;
604-
605- this.insert_column_with_attributes (-1, "Playing", new Gtk.CellRendererPixbuf (), "gicon", Columns.PLAYING);
606- this.insert_column_with_attributes (-1, "Title", text_render, "text", Columns.TITLE);
607- this.set_tooltip_column (1);
608-
609- this.row_activated.connect ((path ,col) => {
610- Gtk.TreeIter iter;
611- playlist.get_iter (out iter, path);
612- string filename;
613- playlist.get (iter, Columns.FILENAME, out filename);
614- play (File.new_for_commandline_arg (filename));
615- });
616-
617- this.reorderable = true;
618- this.model.row_inserted.connect ((path, iter) => {
619- Gtk.TreeIter it;
620- playlist.get_iter (out it, path);
621- Gdk.Pixbuf playing;
622- playlist.get (it, Columns.PLAYING, out playing);
623- if (playing != null) //if playing is not null it's the current item
624- this.current = int.parse (path.to_string ());
625- });
626-
627- // Automatically load from gsettings last_played_videos
628+ private Playlist () {}
629+
630+ construct {
631+ valign = Gtk.Align.FILL;
632+ transition_type = Gtk.RevealerTransitionType.SLIDE_LEFT;
633+
634+ grid = new Gtk.Grid ();
635+ grid.expand = true;
636+ grid.valign = Gtk.Align.FILL;
637+ grid.halign = Gtk.Align.FILL;
638+ grid.orientation = Gtk.Orientation.VERTICAL;
639+ grid.margin_bottom = 28;
640+
641+ scrolled_window = new Gtk.ScrolledWindow (null, null);
642+ scrolled_window.expand = true;
643+ scrolled_window.set_policy (Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
644+
645+
646+ listbox = new Gtk.ListBox ();
647+ listbox.row_selected.connect ( play_selected );
648+ listbox.expand = true;
649+ listbox.valign = Gtk.Align.FILL;
650+
651+ var toolbar = new Gtk.Toolbar ();
652+ toolbar.get_style_context ().add_class (Gtk.STYLE_CLASS_INLINE_TOOLBAR);
653+ toolbar.icon_size = Gtk.IconSize.SMALL_TOOLBAR;
654+
655+ var add_button = new Gtk.ToolButton (new Gtk.Image.from_icon_name ("document-open-symbolic", Gtk.IconSize.BUTTON), null);
656+ add_button.tooltip_text = _("Add Video…");
657+ add_button.clicked.connect (() => { App.get_instance ().mainwindow.run_open_file (false, false); });
658+ toolbar.add (add_button);
659+
660+ var repeat_item = new Gtk.ToolItem ();
661+ repeat_item.halign = Gtk.Align.END;
662+
663+ repeat_button = new Gtk.ToggleButton ();
664+ repeat_button.set_image (new Gtk.Image.from_icon_name ("media-playlist-no-repeat-symbolic", Gtk.IconSize.BUTTON));
665+ repeat_button.set_tooltip_text (_("Enable Repeat"));
666+ repeat_button.toggled.connect (() => {
667+ if (repeat_button.active) {
668+ repeat_button.set_image (new Gtk.Image.from_icon_name ("media-playlist-repeat-symbolic", Gtk.IconSize.BUTTON));
669+ repeat_button.set_tooltip_text (_("Disable Repeat"));
670+ } else {
671+ repeat_button.set_image (new Gtk.Image.from_icon_name ("media-playlist-no-repeat-symbolic", Gtk.IconSize.BUTTON));
672+ repeat_button.set_tooltip_text (_("Enable Repeat"));
673+ }
674+ });
675+
676+ repeat_item.add (repeat_button);
677+ toolbar.add (repeat_item);
678+ scrolled_window.add (listbox);
679+ grid.attach (scrolled_window, 0, 0, 1, 1);
680+ grid.add (toolbar);
681+ add (grid);
682 restore_playlist ();
683- }
684-
685- ~Playlist () {
686- save_playlist ();
687- }
688+ show_all ();
689+
690+ destroy.connect (() =>{ save_playlist (); });
691+ }
692+
693+ public void toggle_reveal_control () {
694+ if (!child_revealed) {
695+ show_all ();
696+ }
697+ set_reveal_child (!child_revealed);
698+ visibility_changed (!child_revealed);
699+ }
700+
701+ public void hide_reval_control () {
702+ set_reveal_child (false);
703+ visibility_changed (false);
704+ }
705+
706+ public void add_item (Audience.Objects.Video video, bool instand_play = true) {
707+ var new_item = new Audience.Widgets.PlaylistItem (video);
708+ if (instand_play) {
709+ clear ();
710+ }
711+ listbox.add (new_item);
712+ if (instand_play) {
713+ listbox.select_row (new_item);
714+ }
715+ collection_changed (size);
716+ }
717+
718+ public void remove_item (Gtk.ListBoxRow row) {
719+ if (row.is_selected ()) {
720+ next ();
721+ }
722+ listbox.remove (row);
723+ save_playlist ();
724+ collection_changed (size);
725+ }
726+
727+ public void clear () {
728+ listbox.forall ((item)=> {
729+ item.dispose ();
730+ });
731+ }
732+
733+ private void play_selected (Gtk.ListBoxRow? row) {
734+ if (row != null) {
735+ listbox.forall ((item) => {
736+ (item as PlaylistItem).update_state ();
737+ });
738+ start_playing (((PlaylistItem)row).video);
739+ }
740+ }
741+
742+ private void start_playing (Audience.Objects.Video video) {
743+ double progress = 0;
744+ if (video.video_file.get_uri () == settings.current_video) {
745+ progress = settings.last_stopped;
746+ }
747+ play (video, progress);
748+ }
749+
750+ public void play_playlist () {
751+ listbox.select_row (listbox.get_row_at_index(0));
752+ }
753
754 public bool next () {
755- Gtk.TreeIter iter;
756- if (playlist.get_iter_from_string (out iter, (this.current + 1).to_string ())){
757- string filename;
758- playlist.get (iter, Columns.FILENAME, out filename);
759- current++;
760- play (File.new_for_commandline_arg (filename));
761- return true;
762- }
763- current = 0;
764- return false;
765- }
766-
767- public void previous () {
768- Gtk.TreeIter iter;
769- if (playlist.get_iter_from_string (out iter, (this.current - 1).to_string ())){
770- string filename;
771- playlist.get (iter, Columns.FILENAME, out filename);
772- current--;
773- play (File.new_for_commandline_arg (filename));
774- }
775- }
776-
777- public void add_item (File path) {
778- if (!path.query_exists ())
779- return;
780- var file_name = path.get_uri ();
781- bool exist = false;
782- Gtk.TreeIter iter;
783-
784- playlist.foreach ((model, path, iter) => {
785- Value filename;
786- playlist.get_value (iter, Columns.FILENAME, out filename);
787- string name = filename.get_string ();
788- if (name == file_name)
789- exist = true;
790- return false;
791- });
792- if (exist)
793- return;
794-
795- Icon? playing = null;
796- Gtk.TreeIter dummy;
797- if (!playlist.get_iter_first (out dummy)){
798- playing = new ThemedIcon ("media-playback-start-symbolic");
799- } else {
800- playing = null;
801- }
802-
803- playlist.append (out iter);
804- playlist.set (iter, Columns.PLAYING, playing,
805- Columns.TITLE, Audience.get_title (path.get_basename ()),
806- Columns.FILENAME, path.get_uri ());
807- item_added ();
808- }
809-
810- public void remove_item (File path) {
811- var file_name = path.get_uri ();
812-
813- playlist.foreach ((model, path, iter) => {
814- Value filename;
815- playlist.get_value (iter, Columns.FILENAME, out filename);
816- string name = filename.get_string ();
817- if (name == file_name)
818- playlist.remove (iter);
819- return false;
820- });
821- }
822-
823- public void clear_items () {
824- current = 0;
825- playlist.clear ();
826- }
827-
828- public File? get_first_item () {
829- Gtk.TreeIter iter;
830- if (playlist.get_iter_first (out iter)){
831- string filename;
832- playlist.get (iter, Columns.FILENAME, out filename);
833- return File.new_for_commandline_arg (filename);
834- }
835- return null;
836- }
837-
838- public int get_current () {
839- return current;
840- }
841-
842- public void set_current (string current_file) {
843- int count = 0;
844- int current_played = 0;
845- playlist.foreach ((model, path, iter) => {
846- playlist.set (iter, Columns.PLAYING, null);
847- Value filename;
848- playlist.get_value (iter, Columns.FILENAME, out filename);
849- string name = filename.get_string ();
850- if (name == current_file)
851- current_played = count;
852- count++;
853- return false;
854- });
855-
856- Gtk.TreeIter new_iter;
857- playlist.get_iter_from_string (out new_iter, current_played.to_string ());
858- playlist.set (new_iter, Columns.PLAYING, new ThemedIcon ("media-playback-start-symbolic"));
859-
860- this.current = current_played;
861-
862- }
863-
864- public List<string> get_all_items () {
865- var list = new List<string> ();
866- playlist.foreach ((model, path, iter) => {
867- Value filename;
868- playlist.get_value (iter, Columns.FILENAME, out filename);
869- string name = filename.get_string ();
870- list.append (name);
871- return false;
872- });
873- return list.copy ();
874+ if (size > listbox.get_selected_row ().get_index () + 1) {
875+ var next_video = listbox.get_row_at_index (listbox.get_selected_row ().get_index () + 1);
876+ listbox.select_row (next_video);
877+ return true;
878+ } else if (repeat_button.active && size > 0) {
879+ if (size == 1) {
880+ listbox.select_row (null);
881+ }
882+ listbox.select_row (listbox.get_row_at_index (0));
883+ return true;
884+ }
885+ return false;
886+ }
887+
888+ public bool previous () {
889+ if (listbox.get_selected_row ().get_index () > 0) {
890+ var next_video = listbox.get_row_at_index (listbox.get_selected_row ().get_index () - 1);
891+ listbox.select_row (next_video);
892+ return true;
893+ }
894+ return false;
895+ }
896+
897+ public void resume () {
898+ listbox.forall ((item) => {
899+ var video = (item as PlaylistItem).video;
900+ if (video.video_file.get_uri () == settings.current_video) {
901+ if (listbox.get_selected_row () != (item as PlaylistItem)) {
902+ listbox.select_row (item as PlaylistItem);
903+ } else {
904+ start_playing (video);
905+ }
906+ return;
907+ }
908+ });
909+
910+ play_playlist ();
911 }
912
913 public void save_playlist () {
914 if (Audience.App.get_instance ().mainwindow.is_privacy_mode_enabled ()) {
915 return;
916 }
917-
918- var list = new List<string> ();
919- playlist.foreach ((model, path, iter) => {
920- Value filename;
921- playlist.get_value (iter, Columns.FILENAME, out filename);
922- string name = filename.get_string ();
923- list.append (name);
924- return false;
925+ var list = new Gee.ArrayList<string> ();
926+ listbox.forall ((item) => {
927+ list.add ((item as PlaylistItem).video.video_file.get_uri ());
928 });
929-
930- uint i = 0;
931- var videos = new string[list.length ()];
932- foreach (var filename in list) {
933- videos[i] = filename;
934- i++;
935+ settings.last_played_videos = list.to_array ();
936+ if (list.size == 0) {
937+ settings.current_video = "";
938+ settings.last_stopped = 0;
939 }
940-
941- settings.last_played_videos = videos;
942 }
943
944 private void restore_playlist () {
945- this.current = 0;
946- /* foreach (var filename in settings.last_played_videos) { */
947- for (int i = 0;i<settings.last_played_videos.length;i++) {
948- if (settings.last_played_videos[i] == settings.current_video)
949- this.current = i;
950- add_item (File.new_for_uri (settings.last_played_videos[i]));
951+ foreach (var filename in settings.last_played_videos) {
952+ add_from_uri (filename);
953 }
954 }
955+
956+ public void add_from_uri (string uri, bool instand_play = false) {
957+ File file = File.new_for_uri (uri);
958+ add_from_file (file);
959+ }
960+
961+ public void add_from_file (File file, bool instand_play = false) {
962+ if (file.query_exists () && file.get_path () != null) {
963+ FileInfo file_info = file.query_info (FileAttribute.STANDARD_CONTENT_TYPE, 0);
964+ add_item (new Audience.Objects.Video (Path.get_dirname (file.get_path ()) ,Path.get_basename (file.get_path ()),file_info.get_content_type ()), instand_play);
965+ }
966+ }
967 }
968 }
969
970=== added file 'src/Widgets/PlaylistItem.vala'
971--- src/Widgets/PlaylistItem.vala 1970-01-01 00:00:00 +0000
972+++ src/Widgets/PlaylistItem.vala 2016-09-30 22:31:06 +0000
973@@ -0,0 +1,66 @@
974+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
975+/*-
976+ * Copyright (c) 2016-2016 elementary LLC.
977+ *
978+ * This program is free software: you can redistribute it and/or modify
979+ * it under the terms of the GNU General Public License as published by
980+ * the Free Software Foundation, either version 3 of the License, or
981+ * (at your option) any later version.
982+
983+ * This program is distributed in the hope that it will be useful,
984+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
985+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
986+ * GNU General Public License for more details.
987+
988+ * You should have received a copy of the GNU General Public License
989+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
990+ *
991+ * Authored by: Artem Anufrij <artem.anufrij@live.de>
992+ *
993+ */
994+
995+namespace Audience.Widgets {
996+ public class PlaylistItem : Gtk.ListBoxRow {
997+
998+ public Audience.Objects.Video video { get; construct set; }
999+ Gtk.Grid grid;
1000+ Gtk.Label title;
1001+ Gtk.Image image;
1002+ Gtk.Button delete_button;
1003+
1004+ public PlaylistItem (Audience.Objects.Video video) {
1005+ Object (video: video);
1006+ }
1007+
1008+ construct {
1009+ grid = new Gtk.Grid ();
1010+ title = new Gtk.Label (video.title);
1011+ title.expand = true;
1012+ title.halign = Gtk.Align.START;
1013+
1014+ image = new Gtk.Image.from_icon_name ("media-playback-start-symbolic", Gtk.IconSize.MENU);
1015+ image.margin_right = 4;
1016+
1017+ delete_button = new Gtk.Button.from_icon_name ("edit-delete-symbolic", Gtk.IconSize.BUTTON);
1018+ delete_button.tooltip_text = _("Remove from Playlist");
1019+ delete_button.relief = Gtk.ReliefStyle.NONE;
1020+ delete_button.clicked.connect (() => { Audience.Widgets.Playlist.get_instance ().remove_item (this); });
1021+
1022+ grid.margin = 4;
1023+ grid.attach (title, 1, 0, 1, 1);
1024+ grid.attach (delete_button, 2, 0, 1, 1);
1025+ add (grid);
1026+ }
1027+
1028+ public void update_state () {
1029+ if (is_selected () && image.parent != grid) {
1030+ grid.attach (image, 0, 0, 1, 1);
1031+ image.show ();
1032+ } else {
1033+ if (image.parent == grid) {
1034+ grid.remove (image);
1035+ }
1036+ }
1037+ }
1038+ }
1039+}
1040
1041=== removed file 'src/Widgets/PlaylistPopover.vala'
1042--- src/Widgets/PlaylistPopover.vala 2016-07-29 05:02:48 +0000
1043+++ src/Widgets/PlaylistPopover.vala 1970-01-01 00:00:00 +0000
1044@@ -1,118 +0,0 @@
1045-// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
1046-/*-
1047- * Copyright (c) 2013-2014 Audience Developers (http://launchpad.net/pantheon-chat)
1048- *
1049- * This program is free software: you can redistribute it and/or modify
1050- * it under the terms of the GNU General Public License as published by
1051- * the Free Software Foundation, either version 3 of the License, or
1052- * (at your option) any later version.
1053-
1054- * This program is distributed in the hope that it will be useful,
1055- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1056- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1057- * GNU General Public License for more details.
1058-
1059- * You should have received a copy of the GNU General Public License
1060- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1061- *
1062- * Authored by: Corentin Noël <corentin@elementaryos.org>
1063- */
1064-
1065-public class Audience.Widgets.PlaylistPopover : Gtk.Popover {
1066- public Playlist playlist;
1067- public Gtk.ToggleButton rep;
1068- private Gtk.ScrolledWindow playlist_scrolled;
1069- private Gtk.Button dvd;
1070-
1071- public PlaylistPopover () {
1072- opacity = GLOBAL_OPACITY;
1073- var grid = new Gtk.Grid ();
1074- grid.row_spacing = 6;
1075- grid.column_spacing = 12;
1076- grid.margin = 6;
1077-
1078- var fil = new Gtk.Button.from_icon_name ("document-open-symbolic", Gtk.IconSize.BUTTON);
1079- fil.set_tooltip_text (_("Open file"));
1080- dvd = new Gtk.Button.from_icon_name ("media-optical-symbolic", Gtk.IconSize.BUTTON);
1081- dvd.set_tooltip_text (_("Play from Disc"));
1082-
1083- rep = new Gtk.ToggleButton ();
1084- rep.set_image (new Gtk.Image.from_icon_name ("media-playlist-no-repeat-symbolic", Gtk.IconSize.BUTTON));
1085- rep.set_tooltip_text (_("Enable Repeat"));
1086-
1087- playlist_scrolled = new Gtk.ScrolledWindow (null, null);
1088- playlist_scrolled.set_min_content_height (100);
1089- playlist_scrolled.set_min_content_width (260);
1090-
1091- playlist = new Playlist ();
1092- playlist_scrolled.add (playlist);
1093-
1094- fil.clicked.connect ( () => {
1095- hide ();
1096- App.get_instance ().mainwindow.run_open_file (false, false);
1097- });
1098-
1099- dvd.clicked.connect ( () => {
1100- hide ();
1101- App.get_instance ().mainwindow.run_open_dvd ();
1102- });
1103-
1104- rep.toggled.connect ( () => {
1105- /* app.repeat = rep.active; */
1106- if (rep.active) {
1107- rep.set_image (new Gtk.Image.from_icon_name ("media-playlist-repeat-symbolic", Gtk.IconSize.BUTTON));
1108- rep.set_tooltip_text (_("Disable Repeat"));
1109- } else {
1110- rep.set_image (new Gtk.Image.from_icon_name ("media-playlist-no-repeat-symbolic", Gtk.IconSize.BUTTON));
1111- rep.set_tooltip_text (_("Enable Repeat"));
1112- }
1113- });
1114-
1115- grid.attach (playlist_scrolled, 0, 0, 7, 1);
1116- grid.attach (fil, 0, 1, 1, 1);
1117- grid.attach (dvd, 1, 1, 1, 1);
1118- grid.attach (rep, 6, 1, 1, 1);
1119-
1120- add (grid);
1121-
1122- var disk_manager = DiskManager.get_default ();
1123- set_dvd_visibility (disk_manager.has_media_volumes ());
1124- disk_manager.volume_found.connect ((vol) => {
1125- set_dvd_visibility (disk_manager.has_media_volumes ());
1126- });
1127-
1128- disk_manager.volume_removed.connect ((vol) => {
1129- set_dvd_visibility (disk_manager.has_media_volumes ());
1130- });
1131- }
1132-
1133- private void set_dvd_visibility (bool visible) {
1134- dvd.no_show_all = !visible;
1135- dvd.visible = visible;
1136- }
1137-
1138- //Override because the Popover doesn't auto-rejust his size.
1139- public override void get_preferred_height (out int minimum_height, out int natural_height) {
1140- base.get_preferred_height (out minimum_height, out natural_height);
1141- int p_minimum_height;
1142- int p_natural_height;
1143- var app = ((Audience.App) GLib.Application.get_default ());
1144- playlist.get_preferred_height (out p_minimum_height, out p_natural_height);
1145- int temp_minimum_height = minimum_height + p_minimum_height;
1146- int r_minimum_height;
1147- int r_natural_height;
1148- relative_to.get_preferred_height (out r_minimum_height, out r_natural_height);
1149- if (temp_minimum_height < app.mainwindow.get_window ().get_height () - r_minimum_height*2) {
1150- minimum_height = temp_minimum_height;
1151- } else {
1152- minimum_height = app.mainwindow.get_window ().get_height () - r_minimum_height*2;
1153- }
1154-
1155- int temp_natural_height = natural_height + p_natural_height;
1156- if (temp_natural_height < app.mainwindow.get_window ().get_height () - r_natural_height*2) {
1157- natural_height = temp_natural_height;
1158- } else {
1159- natural_height = minimum_height;
1160- }
1161- }
1162-}
1163
1164=== modified file 'src/Widgets/WelcomePage.vala'
1165--- src/Widgets/WelcomePage.vala 2016-09-28 02:32:33 +0000
1166+++ src/Widgets/WelcomePage.vala 2016-09-30 22:31:06 +0000
1167@@ -2,27 +2,19 @@
1168 public class WelcomePage : Granite.Widgets.Welcome {
1169 private DiskManager disk_manager;
1170 private Services.LibraryManager library_manager;
1171+ private Audience.Widgets.Playlist playlist;
1172+
1173 public WelcomePage () {
1174 base (_("No Videos Open"), _("Select a source to begin playing."));
1175 }
1176
1177 construct {
1178+ playlist = Audience.Widgets.Playlist.get_instance ();
1179+ playlist.collection_changed.connect ((playlist_size) => { build_replay_button (playlist_size); });
1180 append ("document-open", _("Open file"), _("Open a saved file."));
1181
1182- var filename = settings.current_video;
1183- var last_file = File.new_for_uri (filename);
1184- bool show_last_file = settings.current_video != "";
1185- if (last_file.query_exists () == false) {
1186- show_last_file = false;
1187- }
1188-
1189- if (settings.last_stopped == 0.0 || !settings.resume_videos) {
1190- append ("media-playlist-repeat", _("Replay last video"), get_title (last_file.get_basename ()));
1191- } else {
1192- append ("media-playback-start", _("Resume last video"), get_title (last_file.get_basename ()));
1193- }
1194-
1195- set_item_visible (1, show_last_file);
1196+ append ("media-playlist-repeat", _("Replay last video"), "");
1197+ set_item_visible (1, false);
1198
1199 //look for dvd
1200 disk_manager = DiskManager.get_default ();
1201@@ -54,11 +46,10 @@
1202 var window = App.get_instance ().mainwindow;
1203 switch (index) {
1204 case 0:
1205- // Open file
1206- window.run_open_file (true);
1207+ window.run_open_file ();
1208 break;
1209 case 1:
1210- window.resume_last_videos ();
1211+ playlist.resume ();
1212 break;
1213 case 2:
1214 window.run_open_dvd ();
1215@@ -67,30 +58,46 @@
1216 window.show_library ();
1217 }
1218 });
1219+
1220+ build_replay_button (playlist.size);
1221 }
1222
1223- public void refresh () {
1224+ private void build_replay_button (uint playlist_size) {
1225+ string current_video = settings.current_video;
1226+
1227 var replay_button = get_button_from_index (1);
1228
1229- var filename = settings.current_video;
1230- var last_file = File.new_for_uri (filename);
1231-
1232- if (settings.last_stopped == 0.0) {
1233+ if (playlist_size > 1 && current_video != "") {
1234+ // Resume Playlist;
1235+ replay_button.title = _("Resume playlist");
1236+ replay_button.icon.icon_name = ("media-playback-start");
1237+ replay_button.description = get_title (Path.get_basename (current_video));
1238+ set_item_visible (1, true);
1239+ replay_button.show_all ();
1240+ } else if (playlist_size > 1 && current_video == "") {
1241+ // Replay Playlist
1242+ replay_button.title = _("Start playing playlist");
1243+ replay_button.icon.icon_name = ("media-playback-start");
1244+ replay_button.description = _("All videos of current playlist");
1245+ set_item_visible (1, true);
1246+ replay_button.show_all ();
1247+ } else if (current_video != "" && settings.last_stopped > 0) {
1248+ // Resume Video
1249+ replay_button.title = _("Resume last video");
1250+ replay_button.icon.icon_name = ("media-playback-start");
1251+ replay_button.description = get_title (Path.get_basename (current_video));
1252+ set_item_visible (1, true);
1253+ replay_button.show_all ();
1254+ } else if (current_video != "" && settings.last_stopped == 0) {
1255+ // Replay Video
1256 replay_button.title = _("Replay last video");
1257 replay_button.icon.icon_name = ("media-playlist-repeat");
1258+ replay_button.description = get_title (Path.get_basename (current_video));
1259+ set_item_visible (1, true);
1260+ replay_button.show_all ();
1261 } else {
1262- replay_button.title = _("Resume last video");
1263- replay_button.icon.icon_name = ("media-playback-start");
1264- }
1265- replay_button.description = get_title (last_file.get_basename ());
1266-
1267- bool show_last_file = settings.current_video != "";
1268- if (last_file.query_exists () == false) {
1269- show_last_file = false;
1270- }
1271-
1272- set_item_visible (1, show_last_file);
1273- set_item_visible (2, disk_manager.has_media_volumes ());
1274+ set_item_visible (1, false);
1275+ }
1276 }
1277 }
1278 }
1279
1280=== modified file 'src/Window.vala'
1281--- src/Window.vala 2016-09-27 19:58:34 +0000
1282+++ src/Window.vala 2016-09-30 22:31:06 +0000
1283@@ -27,6 +27,7 @@
1284 private PlayerPage player_page;
1285 private WelcomePage welcome_page;
1286 private LibraryPage library_page;
1287+ private Audience.Widgets.Playlist playlist;
1288 private EpisodesPage episodes_page;
1289 private Granite.Widgets.AlertView alert_view;
1290 private Toast app_notification;
1291@@ -42,9 +43,7 @@
1292
1293 public signal void media_volumes_changed ();
1294
1295- public Window () {
1296-
1297- }
1298+ public Window () {}
1299
1300 construct {
1301 zeitgeist_manager = new ZeitgeistManager ();
1302@@ -78,6 +77,9 @@
1303
1304 set_titlebar (header);
1305
1306+ welcome_page = new WelcomePage ();
1307+ playlist = Audience.Widgets.Playlist.get_instance ();
1308+
1309 library_page = LibraryPage.get_instance ();
1310 library_page.map.connect (() => {
1311 search_entry.visible = true;
1312@@ -110,18 +112,12 @@
1313 search_entry.text = "";
1314 });
1315
1316- welcome_page = new WelcomePage ();
1317-
1318 player_page = new PlayerPage ();
1319 player_page.ended.connect (on_player_ended);
1320 player_page.unfullscreen_clicked.connect (() => {
1321 unfullscreen ();
1322 });
1323
1324- player_page.notify["playing"].connect (() => {
1325- set_keep_above (player_page.playing && settings.stay_on_top);
1326- });
1327-
1328 player_page.map.connect (() => {
1329 app_notification.visible = false;
1330 });
1331@@ -130,6 +126,11 @@
1332 app_notification.visible = true;
1333 });
1334
1335+ player_page.started.connect ((video) => {
1336+ this.title = video.title;
1337+ show_player ();
1338+ });
1339+
1340 alert_view = new Granite.Widgets.AlertView ("", "", "");
1341 alert_view.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);
1342 alert_view.set_vexpand (true);
1343@@ -154,7 +155,7 @@
1344 app_notification.accept.connect (() => {
1345 library_page.manager.undo_delete_item ();
1346 if (main_stack.visible_child != episodes_page) {
1347- main_stack.set_visible_child (library_page);
1348+ main_stack.visible_child = library_page;
1349 }
1350 });
1351
1352@@ -314,7 +315,7 @@
1353 }
1354 } else if (main_stack.visible_child == welcome_page) {
1355 if (match_keycode (Gdk.Key.p, keycode) || match_keycode (Gdk.Key.space, keycode)) {
1356- resume_last_videos ();
1357+ playlist.resume ();
1358 return true;
1359 } else if (ctrl_pressed && match_keycode (Gdk.Key.o, keycode)) {
1360 run_open_file ();
1361@@ -344,7 +345,7 @@
1362
1363 public void open_files (File[] files, bool clear_playlist = false, bool force_play = true) {
1364 if (clear_playlist) {
1365- player_page.get_playlist_widget ().clear_items ();
1366+ playlist.clear ();
1367 }
1368
1369 string[] videos = {};
1370@@ -365,15 +366,7 @@
1371 }
1372
1373 if (force_play) {
1374- play_file (videos [0]);
1375- }
1376- }
1377-
1378- public void resume_last_videos () {
1379- if (settings.current_video != "") {
1380- play_file (settings.current_video, false);
1381- } else {
1382- run_open_file ();
1383+ playlist.play_playlist ();
1384 }
1385 }
1386
1387@@ -381,13 +374,6 @@
1388 read_first_disk.begin ();
1389 }
1390
1391- public void show_library () {
1392- navigation_button.label = navigation_button_welcomescreen;
1393- navigation_button.show ();
1394- main_stack.visible_child = library_page;
1395- library_page.scrolled_window.grab_focus ();
1396- }
1397-
1398 public void run_open_file (bool clear_playlist = false, bool force_play = true) {
1399 var file = new Gtk.FileChooserDialog (_("Open"), this, Gtk.FileChooserAction.OPEN,
1400 _("_Cancel"), Gtk.ResponseType.CANCEL, _("_Open"), Gtk.ResponseType.ACCEPT);
1401@@ -412,7 +398,7 @@
1402 files += item;
1403 }
1404
1405- open_files (files, clear_playlist, force_play);
1406+ open_files (files, force_play);
1407 settings.last_folder = file.get_current_folder ();
1408 }
1409
1410@@ -445,29 +431,37 @@
1411 }
1412
1413 var root = volume.get_mount ().get_default_location ();
1414- play_file (root.get_uri ().replace ("file:///", "dvd:///"));
1415+ //play_file (root.get_uri ().replace ("file:///", "dvd:///"));
1416 }
1417
1418 private void on_player_ended () {
1419+ unfullscreen ();
1420 navigate_back ();
1421- unfullscreen ();
1422- }
1423-
1424- public void play_file (string uri, bool from_beginning = true) {
1425+ }
1426+
1427+
1428+ public void show_library () {
1429+ navigation_button.label = navigation_button_welcomescreen;
1430+ navigation_button.show ();
1431+ main_stack.visible_child = library_page;
1432+ library_page.scrolled_window.grab_focus ();
1433+ }
1434+
1435+ public void show_player () {
1436 search_entry.visible = false;
1437- if (navigation_button.visible) {
1438- if (navigation_button.label == navigation_button_library) {
1439- navigation_button.label = navigation_button_episodes;
1440+ if (main_stack.visible_child != player_page) {
1441+ if (navigation_button.visible) {
1442+ if (navigation_button.label == navigation_button_library) {
1443+ navigation_button.label = navigation_button_episodes;
1444+ } else {
1445+ navigation_button.label = navigation_button_library;
1446+ }
1447 } else {
1448- navigation_button.label = navigation_button_library;
1449+ navigation_button.show ();
1450+ navigation_button.label = navigation_button_welcomescreen;
1451 }
1452- } else {
1453- navigation_button.show ();
1454- navigation_button.label = navigation_button_welcomescreen;
1455+ main_stack.set_visible_child_full ("player", Gtk.StackTransitionType.SLIDE_LEFT);
1456 }
1457-
1458- main_stack.set_visible_child_full ("player", Gtk.StackTransitionType.SLIDE_LEFT);
1459- player_page.play_file (uri, from_beginning);
1460 if (is_maximized) {
1461 fullscreen ();
1462 }
1463@@ -475,8 +469,6 @@
1464 if (settings.stay_on_top && !settings.playback_wait) {
1465 set_keep_above (true);
1466 }
1467-
1468- welcome_page.refresh ();
1469 }
1470
1471 public void navigate_back () {
1472@@ -502,7 +494,8 @@
1473 main_stack.set_visible_child (welcome_page);
1474 search_entry.visible = false;
1475 }
1476- welcome_page.refresh ();
1477+
1478+ playlist.hide_reval_control ();
1479 }
1480
1481 public void hide_alert () {

Subscribers

People subscribed via source and target branches