Ticket #3709: 0001-Media-not-found-SL-3709.patch

File 0001-Media-not-found-SL-3709.patch, 8.2 KB (added by humitos, 11 years ago)

Show an alert at startup if there is missing tracks and show full paths in the canvas

  • jukeboxactivity.py

    From 05bfb3cd17060dd310b81235b968aa6ca646e9d8 Mon Sep 17 00:00:00 2001
    From: Manuel Kaufmann <humitos@gmail.com>
    Date: Thu, 1 Nov 2012 12:09:32 -0300
    Subject: [PATCH Jukebox] Media not found SL #3709
    
     - Show an Alert message at startup when there are some media files
       that couldn't be reached.
    
     - Show full information (media paths) in the main canvas of those
       files that weren't found.
    
     - Listen "Mount" and "Unmount" events to check the availability of
       all media files in the playlist.
    
    Signed-off-by: Manuel Kaufmann <humitos@gmail.com>
    ---
     jukeboxactivity.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
     widgets.py         | 47 +++++++++++++++++++++++++++++++++++++++++++----
     2 files changed, 93 insertions(+), 4 deletions(-)
    
    diff --git a/jukeboxactivity.py b/jukeboxactivity.py
    index 48a5aa8..f106dd8 100644
    a b from sugar3.graphics.toolbarbox import ToolbarButton 
    3737from sugar3.activity.widgets import StopButton
    3838from sugar3.activity.widgets import ActivityToolbarButton
    3939from sugar3.graphics.alert import ErrorAlert
     40from sugar3.graphics.alert import Alert
    4041
    4142import gi
    4243gi.require_version('Gtk', '3.0')
    from gi.repository import GObject 
    4647from gi.repository import Gdk
    4748from gi.repository import Gtk
    4849from gi.repository import Gst
     50from gi.repository import Gio
    4951
    5052# Needed for window.get_xid(), xvimagesink.set_window_handle(),
    5153# respectively:
    class JukeboxActivity(activity.Activity): 
    8890        # FIXME: I don't know what is the mission of this line
    8991        # activity_toolbar.stop.hide()
    9092
     93        self.volume_monitor = Gio.VolumeMonitor.get()
     94        self.volume_monitor.connect('mount-added', self._mount_added_cb)
     95        self.volume_monitor.connect('mount-removed', self._mount_removed_cb)
     96
    9197        _view_toolbar = ViewToolbar()
    9298        _view_toolbar.connect('go-fullscreen',
    9399                              self.__go_fullscreen_cb)
    class JukeboxActivity(activity.Activity): 
    137143        self.playpath = None
    138144        self.currentplaying = None
    139145        self.playflag = False
     146        self._not_found_files = 0
    140147
    141148        # README: I changed this because I was getting an error when I
    142149        # tried to modify self.bin with something different than
    class JukeboxActivity(activity.Activity): 
    304311        alert.connect('response', self._alert_cancel_cb)
    305312        alert.show()
    306313
     314    def _mount_added_cb(self, volume_monitor, device):
     315        self.playlist_widget.update(self.playlist)
     316
     317    def _mount_removed_cb(self, volume_monitor, device):
     318        self.playlist_widget.update(self.playlist)
     319
     320    def _show_missing_tracks_alert(self, nro):
     321        alert = Alert()
     322        title = _('%s tracks not found.') % nro
     323        alert.props.title = title
     324        alert.add_button(Gtk.ResponseType.APPLY, _('Details'))
     325        self.add_alert(alert)
     326        alert.connect('response', self.__missing_tracks_alert_response_cb)
     327
     328    def __missing_tracks_alert_response_cb(self, alert, response_id):
     329        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
     330        vbox.props.valign = Gtk.Align.CENTER
     331        label = Gtk.Label(label='')
     332        label.set_markup(_('<b>Missing tracks</b>'))
     333        vbox.pack_start(label, False, False, 15)
     334
     335        for track in self.playlist_widget.get_missing_tracks():
     336            path = track['url'].replace('journal://', '')\
     337                .replace('file://', '')
     338            label = Gtk.Label(label=path)
     339            vbox.add(label)
     340
     341        _missing_tracks = Gtk.ScrolledWindow()
     342        _missing_tracks.add_with_viewport(vbox)
     343        _missing_tracks.show_all()
     344
     345        self.view_area.append_page(_missing_tracks, None)
     346
     347        self.view_area.set_current_page(2)
     348        self.remove_alert(alert)
     349
    307350    def _alert_cancel_cb(self, alert, response_id):
    308351        self.remove_alert(alert)
    309352
    class JukeboxActivity(activity.Activity): 
    364407        if mimetype == 'audio/x-mpegurl':
    365408            # is a M3U playlist:
    366409            for uri in self._read_m3u_playlist(file_path):
     410                if not self.playlist_widget.check_available_media(uri['url']):
     411                    self._not_found_files += 1
     412
    367413                GObject.idle_add(self._start, uri['url'], uri['title'],
    368414                        uri['object_id'])
    369415        else:
    370416            # is another media file:
    371417            GObject.idle_add(self._start, self.uri, title, object_id)
    372418
     419        if self._not_found_files > 0:
     420            self._show_missing_tracks_alert(self._not_found_files)
     421
    373422    def _create_playlist_jobject(self):
    374423        """Create an object in the Journal to store the playlist.
    375424
    class JukeboxActivity(activity.Activity): 
    451500        self.playpath = os.path.dirname(uri)
    452501        if not uri:
    453502            return False
     503
    454504        if title is not None:
    455505            title = title.strip()
    456506        if object_id is not None:
  • widgets.py

    diff --git a/widgets.py b/widgets.py
    index 2dd5742..fbbd9c5 100644
    a b  
    1414# USA
    1515
    1616import logging
     17import os
    1718from gettext import gettext as _
    1819
    1920import gi
    from gi.repository import GObject 
    2324from gi.repository import Gtk
    2425from gi.repository import Pango
    2526
     27from sugar3.graphics.icon import CellRendererIcon
    2628
    27 COLUMNS_NAME = ('index', 'media')
     29
     30COLUMNS_NAME = ('index', 'media', 'available')
    2831COLUMNS = dict((name, i) for i, name in enumerate(COLUMNS_NAME))
    2932
    3033
    class PlayListWidget(Gtk.ScrolledWindow): 
    3740                                    vadjustment=None)
    3841        self.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
    3942        self.listview = Gtk.TreeView()
    40         self.treemodel = Gtk.ListStore(int, object)
     43        self.treemodel = Gtk.ListStore(int, object, bool)
    4144        self.listview.set_model(self.treemodel)
    4245        selection = self.listview.get_selection()
    4346        selection.set_mode(Gtk.SelectionMode.SINGLE)
    4447
     48        renderer_icon = CellRendererIcon(self.listview)
     49        renderer_icon.props.icon_name = 'emblem-notification'
     50        renderer_icon.props.width = 20
     51        renderer_icon.props.height = 20
     52        renderer_icon.props.size = 20
     53        treecol_icon = Gtk.TreeViewColumn()
     54        treecol_icon.pack_start(renderer_icon, False)
     55        treecol_icon.set_cell_data_func(renderer_icon, self._set_icon)
     56        self.listview.append_column(treecol_icon)
     57
    4558        renderer_idx = Gtk.CellRendererText()
    4659        treecol_idx = Gtk.TreeViewColumn(_('No.'))
    4760        treecol_idx.pack_start(renderer_idx, True)
    class PlayListWidget(Gtk.ScrolledWindow): 
    7588
    7689    def _set_title(self, column, cell, model, it, data):
    7790        playlist_item = model.get_value(it, COLUMNS['media'])
     91        available = model.get_value(it, COLUMNS['available'])
     92
    7893        cell.set_property('text', playlist_item['title'])
     94        sensitive = True
     95        if not available:
     96            sensitive = False
     97        cell.set_property('sensitive', sensitive)
     98
     99    def _set_icon(self, column, cell, model, it, data):
     100        available = model.get_value(it, COLUMNS['available'])
     101        cell.set_property('visible', not available)
    79102
    80103    def update(self, playlist):
    81104        self.treemodel.clear()
    82105        self._playlist = playlist
    83106        pl = list(enumerate(playlist))
    84107        for i, media in pl:
    85             self.treemodel.append((i, media))
    86         self.set_cursor(0)
     108            available = self.check_available_media(media['url'])
     109            media['available'] = available
     110            self.treemodel.append((i, media, available))
     111        #self.set_cursor(0)
    87112
    88113    def set_cursor(self, index):
    89114        self.listview.set_cursor((index,))
    class PlayListWidget(Gtk.ScrolledWindow): 
    96121            self._playlist.pop(index)
    97122            self.treemodel.remove(self.treemodel.get_iter(row))
    98123        self.update(self._playlist)
     124
     125    def check_available_media(self, uri):
     126        path = uri.replace('journal://', '').replace('file://', '')
     127        if os.path.exists(path):
     128            return True
     129        else:
     130            return False
     131
     132    def get_missing_tracks(self):
     133        missing_tracks = []
     134        for track in self._playlist:
     135            if not track['available']:
     136                missing_tracks.append(track)
     137        return missing_tracks