Hello All
Attached is a patch that will allow users to select a different media
player for audio and video files. This should be applied to the current
trunk branch in SVN.
This enhancement can also be tracked at the gPodder Bugzilla server:-
http://gpodder.thegithouse.com/show_bug.cgi?id=5
Please review and post any problems, comments or suggested improvements.
Stefan Lohmaier has requested the ability for gPodder to display PDF
files. I will create a seperate enhancement for this and get working to
implementing it in the not too distant future.
Regards
Paul Rudkin
Index: src/gpodder/config.py
===================================================================
--- src/gpodder/config.py (revision 528)
+++ src/gpodder/config.py (working copy)
@@ -38,6 +38,7 @@
gPodderSettings = {
# General settings
'player': ( str, 'xdg-open' ),
+ 'videoplayer': (str, 'unspecified' ),
'opml_url': ( str, 'http://gpodder.berlios.de/directory.opml' ),
'http_proxy': ( str, '' ),
'ftp_proxy': ( str, '' ),
Index: src/gpodder/libplayers.py
===================================================================
--- src/gpodder/libplayers.py (revision 528)
+++ src/gpodder/libplayers.py (working copy)
@@ -72,15 +72,16 @@
class UserAppsReader(object):
- def __init__( self):
+ def __init__( self, mimetype):
self.apps = []
+ self.mimetype = mimetype
def read( self):
for dir in userappsdirs:
if exists( dir):
for file in glob( dir+'/*.desktop'):
self.parse_and_append( file)
- self.apps.append( UserApplication( 'Shell command', '', 'audio/*', gtk.STOCK_EXECUTE))
+ self.apps.append( UserApplication( 'Shell command', '', self.mimetype + '/*', gtk.STOCK_EXECUTE))
def parse_and_append( self, filename):
try:
@@ -93,8 +94,8 @@
app_cmd = parser.get( sect, 'Exec')
app_mime = parser.get( sect, 'MimeType')
app_icon = parser.get( sect, 'Icon')
- if app_mime.find( 'audio/') != -1:
- log( 'Player found: %s (%s)', app_name, filename)
+ if app_mime.find( self.mimetype + '/') != -1:
+ log( 'Player found (%s): %s (%s)', self.mimetype, app_name, filename)
self.apps.append( UserApplication( app_name, app_cmd, app_mime, app_icon))
except:
return
Index: src/gpodder/libgpodder.py
===================================================================
--- src/gpodder/libgpodder.py (revision 528)
+++ src/gpodder/libgpodder.py (working copy)
@@ -72,6 +72,13 @@
self.config = config.Config( os.path.join( gpodder_dir, 'gpodder.conf'))
+ # We need to make a seamless upgrade, so by default the video player is not specified
+ # so the first time this application is run it will detect this and set it to the same
+ # as the audio player. This keeps gPodder functionality identical to that prior to the
+ # upgrade. The user can then set a specific video player if they so wish.
+ if self.config.videoplayer == 'unspecified':
+ self.config.videoplayer = self.config.player
+
self.__download_history = HistoryStore( os.path.join( gpodder_dir, 'download-history.txt'))
self.__playback_history = HistoryStore( os.path.join( gpodder_dir, 'playback-history.txt'))
self.__locked_history = HistoryStore( os.path.join( gpodder_dir, 'lock-history.txt'))
@@ -195,7 +202,15 @@
self.history_mark_played( episode.url)
filename = episode.local_filename()
- command_line = shlex.split( util.format_desktop_command( self.config.player, filename).encode('utf-8'))
+ # Determine the file type and set the player accordingly.
+ file_type = util.file_type_by_extension( util.file_extension_from_url( episode.url))
+
+ # Default to the audio player
+ player = self.config.player
+ if file_type == 'video':
+ player = self.config.videoplayer
+
+ command_line = shlex.split( util.format_desktop_command( player, filename).encode('utf-8'))
log( 'Command line: [ %s ]', ', '.join( [ '"%s"' % p for p in command_line ]), sender = self)
try:
subprocess.Popen( command_line)
Index: src/gpodder/gui.py
===================================================================
--- src/gpodder/gui.py (revision 528)
+++ src/gpodder/gui.py (working copy)
@@ -282,10 +282,14 @@
self.active_channel = None
self.channels = load_channels( load_items = False, offline = True)
- # load list of user applications
- self.user_apps_reader = UserAppsReader()
+ # load list of user applications for audio playback
+ self.user_apps_reader = UserAppsReader('audio')
Thread( target = self.user_apps_reader.read).start()
+ # load list of user applications for video playback
+ self.user_video_apps_reader = UserAppsReader('video')
+ Thread( target = self.user_video_apps_reader.read).start()
+
# Clean up old, orphaned download files
gl.clean_up_downloads( delete_partial = True)
@@ -1187,6 +1191,7 @@
def on_itemPreferences_activate(self, widget, *args):
prop = gPodderProperties( callback_finished = self.properties_closed)
prop.set_uar( self.user_apps_reader)
+ prop.set_video_uar( self.user_video_apps_reader)
def on_itemAddChannel_activate(self, widget, *args):
if self.channelPaned.get_position() < 200:
@@ -1657,6 +1662,7 @@
gl.config.connect_gtk_editable( 'http_proxy', self.httpProxy)
gl.config.connect_gtk_editable( 'ftp_proxy', self.ftpProxy)
gl.config.connect_gtk_editable( 'player', self.openApp)
+ gl.config.connect_gtk_editable( 'videoplayer', self.openVideoApp)
gl.config.connect_gtk_editable( 'opml_url', self.opmlURL)
gl.config.connect_gtk_editable( 'custom_sync_name', self.entryCustomSyncName)
gl.config.connect_gtk_togglebutton( 'custom_sync_name_enabled', self.cbCustomSyncName)
@@ -1706,12 +1712,19 @@
# setup cell renderers
cellrenderer = gtk.CellRendererPixbuf()
- self.comboPlayerApp.pack_start( cellrenderer, False)
- self.comboPlayerApp.add_attribute( cellrenderer, 'pixbuf', 2)
+ self.comboAudioPlayerApp.pack_start( cellrenderer, False)
+ self.comboAudioPlayerApp.add_attribute( cellrenderer, 'pixbuf', 2)
cellrenderer = gtk.CellRendererText()
- self.comboPlayerApp.pack_start( cellrenderer, True)
- self.comboPlayerApp.add_attribute( cellrenderer, 'markup', 0)
+ self.comboAudioPlayerApp.pack_start( cellrenderer, True)
+ self.comboAudioPlayerApp.add_attribute( cellrenderer, 'markup', 0)
+ cellrenderer = gtk.CellRendererPixbuf()
+ self.comboVideoPlayerApp.pack_start( cellrenderer, False)
+ self.comboVideoPlayerApp.add_attribute( cellrenderer, 'pixbuf', 2)
+ cellrenderer = gtk.CellRendererText()
+ self.comboVideoPlayerApp.pack_start( cellrenderer, True)
+ self.comboVideoPlayerApp.add_attribute( cellrenderer, 'markup', 0)
+
self.ipodIcon.set_from_icon_name( 'gnome-dev-ipod', gtk.ICON_SIZE_BUTTON)
def update_mountpoint( self, ipod):
@@ -1721,13 +1734,19 @@
self.iPodMountpoint.set_label( ipod.mount_point)
def set_uar( self, uar):
- self.comboPlayerApp.set_model( uar.get_applications_as_model())
+ self.comboAudioPlayerApp.set_model( uar.get_applications_as_model())
# try to activate an item
- index = self.find_active()
- self.comboPlayerApp.set_active( index)
+ index = self.find_active_audio_app()
+ self.comboAudioPlayerApp.set_active( index)
+
+ def set_video_uar( self, uar):
+ self.comboVideoPlayerApp.set_model( uar.get_applications_as_model())
+ # try to activate an item
+ index = self.find_active_video_app()
+ self.comboVideoPlayerApp.set_active( index)
- def find_active( self):
- model = self.comboPlayerApp.get_model()
+ def find_active_audio_app( self):
+ model = self.comboAudioPlayerApp.get_model()
iter = model.get_iter_first()
index = 0
while iter != None:
@@ -1738,6 +1757,19 @@
index = index + 1
# return last item = custom command
return index-1
+
+ def find_active_video_app( self):
+ model = self.comboVideoPlayerApp.get_model()
+ iter = model.get_iter_first()
+ index = 0
+ while iter != None:
+ command = model.get_value( iter, 1)
+ if command == self.openVideoApp.get_text():
+ return index
+ iter = model.iter_next( iter)
+ index = index + 1
+ # return last item = custom command
+ return index-1
def set_download_dir( self, new_download_dir, event = None):
gl = gPodderLib()
@@ -1772,10 +1804,10 @@
def on_gPodderProperties_destroy(self, widget, *args):
self.on_btnOK_clicked( widget, *args)
- def on_comboPlayerApp_changed(self, widget, *args):
+ def on_comboAudioPlayerApp_changed(self, widget, *args):
# find out which one
- iter = self.comboPlayerApp.get_active_iter()
- model = self.comboPlayerApp.get_model()
+ iter = self.comboAudioPlayerApp.get_active_iter()
+ model = self.comboAudioPlayerApp.get_model()
command = model.get_value( iter, 1)
if command == '':
self.openApp.set_sensitive( True)
@@ -1787,6 +1819,21 @@
self.openApp.hide()
self.labelCustomCommand.hide()
+ def on_comboVideoPlayerApp_changed(self, widget, *args):
+ # find out which one
+ iter = self.comboVideoPlayerApp.get_active_iter()
+ model = self.comboVideoPlayerApp.get_model()
+ command = model.get_value( iter, 1)
+ if command == '':
+ self.openVideoApp.set_sensitive( True)
+ self.openVideoApp.show()
+ self.labelCustomCommand.show()
+ else:
+ self.openVideoApp.set_text( command)
+ self.openVideoApp.set_sensitive( False)
+ self.openVideoApp.hide()
+ self.labelCustomCommand.hide()
+
def on_cbMaxDownloads_toggled(self, widget, *args):
self.spinMaxDownloads.set_sensitive( self.cbMaxDownloads.get_active())
Index: data/gpodder.glade
===================================================================
--- data/gpodder.glade (revision 528)
+++ data/gpodder.glade (working copy)
@@ -368,7 +368,7 @@
<property name="visible">True</property>
<property name="label" translatable="yes">_Close</property>
<property name="use_underline">True</property>
- <signal name="activate" handler="on_gPodder_delete_event" last_modification_time="Sat, 29 Oct 2005 41:54:31 GMT"/>
+ <signal name="activate" handler="on_gPodder_delete_event" last_modification_time="Sun, 30 Oct 2005 17:54:31 GMT"/>
<accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/>
<child internal-child="image">
@@ -716,8 +716,8 @@
<child internal-child="image">
<widget class="GtkImage" id="image2927">
<property name="visible">True</property>
+ <property name="icon_size">1</property>
<property name="icon_name">bug-buddy</property>
- <property name="icon_size">1</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">0</property>
@@ -2123,7 +2123,7 @@
<widget class="GtkTable" id="table2">
<property name="border_width">10</property>
<property name="visible">True</property>
- <property name="n_rows">7</property>
+ <property name="n_rows">10</property>
<property name="n_columns">3</property>
<property name="homogeneous">False</property>
<property name="row_spacing">5</property>
@@ -2180,7 +2180,7 @@
<child>
<widget class="GtkLabel" id="label74">
<property name="visible">True</property>
- <property name="label" translatable="yes"><b>Media Player</b></property>
+ <property name="label" translatable="yes"><b>Audio Media Player</b></property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
@@ -2209,7 +2209,7 @@
<widget class="GtkImage" id="image2411">
<property name="visible">True</property>
<property name="icon_size">6</property>
- <property name="icon_name">applications-multimedia</property>
+ <property name="icon_name">audio-x-generic</property>
<property name="xalign">0.5</property>
<property name="yalign">0.5</property>
<property name="xpad">6</property>
@@ -2246,19 +2246,19 @@
<packing>
<property name="left_attach">0</property>
<property name="right_attach">3</property>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
+ <property name="top_attach">7</property>
+ <property name="bottom_attach">8</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
- <widget class="GtkComboBox" id="comboPlayerApp">
+ <widget class="GtkComboBox" id="comboAudioPlayerApp">
<property name="visible">True</property>
<property name="add_tearoffs">False</property>
<property name="focus_on_click">True</property>
- <signal name="changed" handler="on_comboPlayerApp_changed" last_modification_time="Wed, 29 Mar 2006 21:25:13 GMT"/>
+ <signal name="changed" handler="on_comboAudioPlayerApp_changed" last_modification_time="Sat, 19 Jan 2008 12:49:48 GMT"/>
</widget>
<packing>
<property name="left_attach">1</property>
@@ -2282,8 +2282,8 @@
<packing>
<property name="left_attach">0</property>
<property name="right_attach">1</property>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
+ <property name="top_attach">8</property>
+ <property name="bottom_attach">9</property>
<property name="x_padding">6</property>
<property name="x_options">fill</property>
<property name="y_options">fill</property>
@@ -2303,23 +2303,135 @@
<packing>
<property name="left_attach">1</property>
<property name="right_attach">3</property>
+ <property name="top_attach">8</property>
+ <property name="bottom_attach">9</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHSeparator" id="hseparator9">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
+ <property name="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="openVideoApp">
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label115">
+ <property name="label" translatable="yes">Command line:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
</child>
<child>
- <widget class="GtkHSeparator" id="hseparator9">
+ <widget class="GtkImage" id="image2928">
<property name="visible">True</property>
+ <property name="icon_size">6</property>
+ <property name="icon_name">video-x-generic</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">6</property>
+ <property name="ypad">0</property>
</widget>
<packing>
<property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">6</property>
+ <property name="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkComboBox" id="comboVideoPlayerApp">
+ <property name="visible">True</property>
+ <property name="add_tearoffs">False</property>
+ <property name="focus_on_click">True</property>
+ <signal name="changed" handler="on_comboVideoPlayerApp_changed" last_modification_time="Sat, 19 Jan 2008 12:49:01 GMT"/>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
<property name="right_attach">3</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label114">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>Video Media Player</b></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">3</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
- <property name="y_padding">3</property>
<property name="x_options">fill</property>
<property name="y_options"></property>
</packing>
_______________________________________________
gpodder-devel mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/gpodder-devel