Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManuel Kaufmann <humitos@gmail.com>2012-11-01 15:09:32 (GMT)
committer Gonzalo Odiard <godiard@gmail.com>2012-11-02 21:01:55 (GMT)
commit17bb41d2dea86394d0f9c8d0952ccd135bf7038c (patch)
tree044fefef74ad30872448473803162cc38498e464
parent3798677181bea65594ac740438c3813919593e47 (diff)
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>
-rw-r--r--jukeboxactivity.py50
-rw-r--r--widgets.py47
2 files changed, 93 insertions, 4 deletions
diff --git a/jukeboxactivity.py b/jukeboxactivity.py
index 48a5aa8..f106dd8 100644
--- a/jukeboxactivity.py
+++ b/jukeboxactivity.py
@@ -37,6 +37,7 @@ from sugar3.graphics.toolbarbox import ToolbarButton
from sugar3.activity.widgets import StopButton
from sugar3.activity.widgets import ActivityToolbarButton
from sugar3.graphics.alert import ErrorAlert
+from sugar3.graphics.alert import Alert
import gi
gi.require_version('Gtk', '3.0')
@@ -46,6 +47,7 @@ from gi.repository import GObject
from gi.repository import Gdk
from gi.repository import Gtk
from gi.repository import Gst
+from gi.repository import Gio
# Needed for window.get_xid(), xvimagesink.set_window_handle(),
# respectively:
@@ -88,6 +90,10 @@ class JukeboxActivity(activity.Activity):
# FIXME: I don't know what is the mission of this line
# activity_toolbar.stop.hide()
+ self.volume_monitor = Gio.VolumeMonitor.get()
+ self.volume_monitor.connect('mount-added', self._mount_added_cb)
+ self.volume_monitor.connect('mount-removed', self._mount_removed_cb)
+
_view_toolbar = ViewToolbar()
_view_toolbar.connect('go-fullscreen',
self.__go_fullscreen_cb)
@@ -137,6 +143,7 @@ class JukeboxActivity(activity.Activity):
self.playpath = None
self.currentplaying = None
self.playflag = False
+ self._not_found_files = 0
# README: I changed this because I was getting an error when I
# tried to modify self.bin with something different than
@@ -304,6 +311,42 @@ class JukeboxActivity(activity.Activity):
alert.connect('response', self._alert_cancel_cb)
alert.show()
+ def _mount_added_cb(self, volume_monitor, device):
+ self.playlist_widget.update(self.playlist)
+
+ def _mount_removed_cb(self, volume_monitor, device):
+ self.playlist_widget.update(self.playlist)
+
+ def _show_missing_tracks_alert(self, nro):
+ alert = Alert()
+ title = _('%s tracks not found.') % nro
+ alert.props.title = title
+ alert.add_button(Gtk.ResponseType.APPLY, _('Details'))
+ self.add_alert(alert)
+ alert.connect('response', self.__missing_tracks_alert_response_cb)
+
+ def __missing_tracks_alert_response_cb(self, alert, response_id):
+ vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
+ vbox.props.valign = Gtk.Align.CENTER
+ label = Gtk.Label(label='')
+ label.set_markup(_('<b>Missing tracks</b>'))
+ vbox.pack_start(label, False, False, 15)
+
+ for track in self.playlist_widget.get_missing_tracks():
+ path = track['url'].replace('journal://', '')\
+ .replace('file://', '')
+ label = Gtk.Label(label=path)
+ vbox.add(label)
+
+ _missing_tracks = Gtk.ScrolledWindow()
+ _missing_tracks.add_with_viewport(vbox)
+ _missing_tracks.show_all()
+
+ self.view_area.append_page(_missing_tracks, None)
+
+ self.view_area.set_current_page(2)
+ self.remove_alert(alert)
+
def _alert_cancel_cb(self, alert, response_id):
self.remove_alert(alert)
@@ -364,12 +407,18 @@ class JukeboxActivity(activity.Activity):
if mimetype == 'audio/x-mpegurl':
# is a M3U playlist:
for uri in self._read_m3u_playlist(file_path):
+ if not self.playlist_widget.check_available_media(uri['url']):
+ self._not_found_files += 1
+
GObject.idle_add(self._start, uri['url'], uri['title'],
uri['object_id'])
else:
# is another media file:
GObject.idle_add(self._start, self.uri, title, object_id)
+ if self._not_found_files > 0:
+ self._show_missing_tracks_alert(self._not_found_files)
+
def _create_playlist_jobject(self):
"""Create an object in the Journal to store the playlist.
@@ -451,6 +500,7 @@ class JukeboxActivity(activity.Activity):
self.playpath = os.path.dirname(uri)
if not uri:
return False
+
if title is not None:
title = title.strip()
if object_id is not None:
diff --git a/widgets.py b/widgets.py
index 2dd5742..fbbd9c5 100644
--- a/widgets.py
+++ b/widgets.py
@@ -14,6 +14,7 @@
# USA
import logging
+import os
from gettext import gettext as _
import gi
@@ -23,8 +24,10 @@ from gi.repository import GObject
from gi.repository import Gtk
from gi.repository import Pango
+from sugar3.graphics.icon import CellRendererIcon
-COLUMNS_NAME = ('index', 'media')
+
+COLUMNS_NAME = ('index', 'media', 'available')
COLUMNS = dict((name, i) for i, name in enumerate(COLUMNS_NAME))
@@ -37,11 +40,21 @@ class PlayListWidget(Gtk.ScrolledWindow):
vadjustment=None)
self.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
self.listview = Gtk.TreeView()
- self.treemodel = Gtk.ListStore(int, object)
+ self.treemodel = Gtk.ListStore(int, object, bool)
self.listview.set_model(self.treemodel)
selection = self.listview.get_selection()
selection.set_mode(Gtk.SelectionMode.SINGLE)
+ renderer_icon = CellRendererIcon(self.listview)
+ renderer_icon.props.icon_name = 'emblem-notification'
+ renderer_icon.props.width = 20
+ renderer_icon.props.height = 20
+ renderer_icon.props.size = 20
+ treecol_icon = Gtk.TreeViewColumn()
+ treecol_icon.pack_start(renderer_icon, False)
+ treecol_icon.set_cell_data_func(renderer_icon, self._set_icon)
+ self.listview.append_column(treecol_icon)
+
renderer_idx = Gtk.CellRendererText()
treecol_idx = Gtk.TreeViewColumn(_('No.'))
treecol_idx.pack_start(renderer_idx, True)
@@ -75,15 +88,27 @@ class PlayListWidget(Gtk.ScrolledWindow):
def _set_title(self, column, cell, model, it, data):
playlist_item = model.get_value(it, COLUMNS['media'])
+ available = model.get_value(it, COLUMNS['available'])
+
cell.set_property('text', playlist_item['title'])
+ sensitive = True
+ if not available:
+ sensitive = False
+ cell.set_property('sensitive', sensitive)
+
+ def _set_icon(self, column, cell, model, it, data):
+ available = model.get_value(it, COLUMNS['available'])
+ cell.set_property('visible', not available)
def update(self, playlist):
self.treemodel.clear()
self._playlist = playlist
pl = list(enumerate(playlist))
for i, media in pl:
- self.treemodel.append((i, media))
- self.set_cursor(0)
+ available = self.check_available_media(media['url'])
+ media['available'] = available
+ self.treemodel.append((i, media, available))
+ #self.set_cursor(0)
def set_cursor(self, index):
self.listview.set_cursor((index,))
@@ -96,3 +121,17 @@ class PlayListWidget(Gtk.ScrolledWindow):
self._playlist.pop(index)
self.treemodel.remove(self.treemodel.get_iter(row))
self.update(self._playlist)
+
+ def check_available_media(self, uri):
+ path = uri.replace('journal://', '').replace('file://', '')
+ if os.path.exists(path):
+ return True
+ else:
+ return False
+
+ def get_missing_tracks(self):
+ missing_tracks = []
+ for track in self._playlist:
+ if not track['available']:
+ missing_tracks.append(track)
+ return missing_tracks