Skip to content

Commit

Permalink
Windows: Support for detecting media players
Browse files Browse the repository at this point in the history
For now, we can only detect a hardcoded list, but it's better than
previously where we didn't have any support for players on Win32.
  • Loading branch information
thp committed Oct 22, 2014
1 parent ffa7cb1 commit f6e7d05
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 15 deletions.
70 changes: 55 additions & 15 deletions share/gpodder/extensions/enqueue_in_mediaplayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,51 +21,91 @@
__category__ = 'interface'
__only_for__ = 'gtk'

class Player:

class Player(object):
def __init__(self, application, command):
self.title = '/'.join((_('Enqueue in'), application))
self.command = command
self.gpodder = None

def is_installed(self):
return util.find_command(self.command[0]) is not None
raise NotImplemented('Must be implemented by subclass')

def open_files(self, filenames):
raise NotImplemented('Must be implemented by subclass')

def enqueue_episodes(self, episodes):
filenames = [episode.get_playback_url() for episode in episodes]

subprocess.Popen(self.command + filenames,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
self.open_files(filenames)

for episode in episodes:
episode.playback_mark()
self.gpodder.update_episode_list_icons(selected=True)
if self.gpodder is not None:
self.gpodder.update_episode_list_icons(selected=True)


class FreeDesktopPlayer(Player):
def is_installed(self):
return util.find_command(self.command[0]) is not None

def open_files(self, filenames):
subprocess.Popen(self.command + filenames,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)


class Win32Player(Player):
def is_installed(self):
if not gpodder.ui.win32:
return False

from gpodder.gtkui.desktopfile import win32_read_registry_key
try:
self.command = win32_read_registry_key(self.command)
return True
except Exception as e:
logger.warn('Win32 player not found: %s (%s)', self.command, e)

return False

def open_files(self, filenames):
for cmd in util.format_desktop_command(self.command, filenames):
subprocess.Popen(cmd)


PLAYERS = [
# Amarok, http://amarok.kde.org/
Player('Amarok', ['amarok', '--play', '--append']),
FreeDesktopPlayer('Amarok', ['amarok', '--play', '--append']),

# VLC, http://videolan.org/
Player('VLC', ['vlc', '--started-from-file', '--playlist-enqueue']),
FreeDesktopPlayer('VLC', ['vlc', '--started-from-file', '--playlist-enqueue']),

# Totem, https://live.gnome.org/Totem
Player('Totem', ['totem', '--enqueue']),
FreeDesktopPlayer('Totem', ['totem', '--enqueue']),

# DeaDBeeF, http://deadbeef.sourceforge.net/
Player('DeaDBeeF', ['deadbeef', '--queue']),
FreeDesktopPlayer('DeaDBeeF', ['deadbeef', '--queue']),

# gmusicbrowser, http://gmusicbrowser.org/
Player('gmusicbrowser', ['gmusicbrowser', '-enqueue']),
FreeDesktopPlayer('gmusicbrowser', ['gmusicbrowser', '-enqueue']),

# Audacious, http://audacious-media-player.org/
Player('Audacious', ['audacious', '--enqueue']),
FreeDesktopPlayer('Audacious', ['audacious', '--enqueue']),

# Clementine, http://www.clementine-player.org/
Player('Clementine', ['clementine', '--append']),

#Parole, http://docs.xfce.org/apps/parole/start
Player('Parole', ['parole', '-a']),
FreeDesktopPlayer('Clementine', ['clementine', '--append']),

# Parole, http://docs.xfce.org/apps/parole/start
FreeDesktopPlayer('Parole', ['parole', '-a']),

# Winamp 2.x, http://www.oldversion.com/windows/winamp/
Win32Player('Winamp', r'HKEY_CLASSES_ROOT\Winamp.File\shell\Enqueue\command'),

# VLC media player, http://videolan.org/vlc/
Win32Player('VLC', r'HKEY_CLASSES_ROOT\VLC.mp3\shell\AddToPlaylistVLC\command'),

# foobar2000, http://www.foobar2000.org/
Win32Player('foobar2000', r'HKEY_CLASSES_ROOT\foobar2000.MP3\shell\enqueue\command'),
]

class gPodderExtension:
Expand Down
45 changes: 45 additions & 0 deletions src/gpodder/gtkui/desktopfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#

import glob
import re
import os
import os.path
import threading

Expand Down Expand Up @@ -101,6 +103,40 @@ def is_mime(self, mimetype):
return self.mime.find(mimetype+'/') != -1


WIN32_APP_REG_KEYS = [
('Winamp', ('audio',), r'HKEY_CLASSES_ROOT\Winamp.File\shell\Play\command'),
('foobar2000', ('audio',), r'HKEY_CLASSES_ROOT\Applications\foobar2000.exe\shell\open\command'),
('Windows Media Player 11', ('audio', 'video'), r'HKEY_CLASSES_ROOT\WMP11.AssocFile.MP3\shell\open\command'),
('QuickTime Player', ('audio', 'video'), r'HKEY_CLASSES_ROOT\QuickTime.mp3\shell\open\command'),
('VLC', ('audio', 'video'), r'HKEY_CLASSES_ROOT\VLC.mp3\shell\open\command'),
]


def win32_read_registry_key(path):
import _winreg

rootmap = {
'HKEY_CLASSES_ROOT': _winreg.HKEY_CLASSES_ROOT,
}

parts = path.split('\\')
root = parts.pop(0)
key = _winreg.OpenKey(rootmap[root], parts.pop(0))

while parts:
key = _winreg.OpenKey(key, parts.pop(0))

value, type_ = _winreg.QueryValueEx(key, '')
if type_ == _winreg.REG_EXPAND_SZ:
cmdline = re.sub(r'%([^%]+)%', lambda m: os.environ[m.group(1)], value)
elif type_ == _winreg.REG_SZ:
cmdline = value
else:
raise ValueError('Not a string: ' + path)

return cmdline.replace('%1', '%f').replace('%L', '%f')


class UserAppsReader(object):
def __init__(self, mimetypes):
self.apps = []
Expand All @@ -119,6 +155,15 @@ def read( self):
return

self.__has_read = True
if gpodder.ui.win32:
import _winreg
for caption, types, hkey in WIN32_APP_REG_KEYS:
try:
cmdline = win32_read_registry_key(hkey)
self.apps.append(UserApplication(caption, cmdline, ';'.join(typ + '/*' for typ in types), None))
except Exception as e:
logger.warn('Parse HKEY error: %s (%s)', hkey, e)

for dir in userappsdirs:
if os.path.exists( dir):
for file in glob.glob(os.path.join(dir, '*.desktop')):
Expand Down

0 comments on commit f6e7d05

Please sign in to comment.