Properly update existing episodes (bug 211)
[gpodder.git] / src / gpodder / libplayers.py
blob60a097cab6aaa4a6e08d85d48310b84fbb437b54
1 # -*- coding: utf-8 -*-
3 # gPodder - A media aggregator and podcast client
4 # Copyright (c) 2005-2008 Thomas Perl and the gPodder Team
6 # gPodder is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # gPodder is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 # libplayers.py -- get list of potential playback apps
23 # thomas perl <thp@perli.net> 20060329
27 import glob
28 import os.path
29 import threading
31 from ConfigParser import RawConfigParser
33 import gobject
34 import gtk
35 import gtk.gdk
37 from gpodder.liblogger import log
40 # where are the .desktop files located?
41 userappsdirs = [ '/usr/share/applications/', '/usr/local/share/applications/', '/usr/share/applications/kde/' ]
43 # the name of the section in the .desktop files
44 sect = 'Desktop Entry'
46 class UserApplication(object):
47 def __init__(self, name, cmd, mime, icon):
48 self.name = name
49 self.cmd = cmd
50 self.icon = icon
51 self.mime = mime
53 def get_icon(self):
54 if self.icon is not None:
55 # Load it from an absolute filename
56 if os.path.exists(self.icon):
57 return gtk.gdk.pixbuf_new_from_file_at_size(self.icon, 24, 24)
59 # Load it from the current icon theme
60 (icon_name, extension) = os.path.splitext(os.path.basename(self.icon))
61 theme = gtk.IconTheme()
62 if theme.has_icon(icon_name):
63 return theme.load_icon(icon_name, 24, 0)
65 def is_mime(self, mimetype):
66 return self.mime.find(mimetype+'/') != -1
69 class UserAppsReader(object):
70 def __init__(self, mimetypes):
71 self.apps = []
72 self.mimetypes = mimetypes
73 self.__model_cache = {}
74 self.__has_read = False
75 self.__finished = threading.Event()
77 def read( self):
78 if self.__has_read:
79 return
81 self.__has_read = True
82 log('start reader', bench_start=True)
83 for dir in userappsdirs:
84 if os.path.exists( dir):
85 for file in glob.glob(os.path.join(dir, '*.desktop')):
86 self.parse_and_append( file)
87 log('end reader', bench_end=True)
88 self.__finished.set()
89 self.apps.append(UserApplication('Shell command', '', ';'.join((mime+'/*' for mime in self.mimetypes)), gtk.STOCK_EXECUTE))
91 def parse_and_append( self, filename):
92 try:
93 parser = RawConfigParser()
94 parser.read([filename])
95 if not parser.has_section(sect):
96 return
98 # Find out if we need it by comparing mime types
99 app_mime = parser.get(sect, 'MimeType')
100 for needed_type in self.mimetypes:
101 if app_mime.find(needed_type+'/') != -1:
102 log('Player found: %s', filename, sender=self)
103 app_name = parser.get(sect, 'Name')
104 app_cmd = parser.get(sect, 'Exec')
105 app_icon = parser.get(sect, 'Icon')
106 self.apps.append(UserApplication(app_name, app_cmd, app_mime, app_icon))
107 return
108 except:
109 return
111 def get_applications_as_model(self, mimetype, return_model=True):
112 self.__finished.wait()
113 if mimetype not in self.__model_cache:
114 result = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gtk.gdk.Pixbuf)
115 for app in self.apps:
116 if app.is_mime(mimetype):
117 result.append([app.name, app.cmd, app.get_icon()])
118 self.__model_cache[mimetype] = result
119 else:
120 log('Using cached application list model for %s', mimetype, sender=self)
122 if return_model:
123 return self.__model_cache[mimetype]
124 else:
125 return False