Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 8067c67
Showing
6 changed files
with
402 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*.pyc | ||
*~ |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
#!/usr/bin/env python | ||
# Copyright (C) 2010 robstar.cc <info at navarin dot de> | ||
# | ||
# This program is free software; you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation; either version 2, or (at your option) | ||
# any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU General Public License | ||
# along with this program; if not, write to the Free Software | ||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
|
||
|
||
try: | ||
import os | ||
import sys | ||
import subprocess | ||
import rb | ||
import gobject | ||
import gtk, gtk.glade | ||
import gconf, gnome | ||
except ImportError as e: | ||
print "Depencies missing:" | ||
print str(e) | ||
|
||
|
||
class RhythmotePlugin (rb.Plugin): | ||
'''Rhythmote's main class.''' | ||
|
||
def __init__(self): | ||
rb.Plugin.__init__(self) | ||
path = os.path.abspath( __file__ ) | ||
|
||
self.daemon = None | ||
self.cwd = path[:path.rfind("/")] | ||
self.gconf_keys = { | ||
'port' : '/apps/rhythmbox/plugins/rhythmote/port' | ||
} | ||
self.client = gconf.client_get_default() | ||
self.port = self.client.get_string(self.gconf_keys["port"]) or "8484" | ||
|
||
|
||
|
||
def activate(self, shell): | ||
'''Default actication method, automatically called when the plugin is | ||
started from within Rhythmbox. It starts a separated process which acts | ||
as a daemon and listens to the port, entered in the settings dialog.''' | ||
|
||
print "starting Rhythmote" | ||
self.restart() | ||
#self.daemon = subprocess.Popen(["/usr/bin/python", self.cwd+"/daemon.py", str(self.port)]); | ||
|
||
|
||
def deactivate(self, shell): | ||
'''This method is called automatically, when Ryhthmbox is closed or the | ||
plugin is deactivated by the user. It cleans up all objects which are | ||
not needed anymore and sends a SIGTERM to stop the daemon.''' | ||
|
||
print "quitting Rhythmote" | ||
|
||
if self.daemon: | ||
self.daemon.terminate() | ||
|
||
|
||
def create_configure_dialog(self, dialog=None): | ||
'''creates the configuration dialog using a libglade gui''' | ||
|
||
if dialog == None: | ||
|
||
self.configure_callback_dic = { | ||
"rb_rhythmote_port_changed" : lambda w: self.client.set_string(self.gconf_keys['port'], self.port) | ||
} | ||
|
||
gladexml = gtk.glade.XML(self.find_file("rhythmote-prefs.glade")) | ||
gladexml.signal_autoconnect(self.configure_callback_dic) | ||
gladexml.get_widget("port").set_text(self.port) | ||
|
||
dialog = gladexml.get_widget('preferences_dialog') | ||
def dialog_response (dialog, response): | ||
port = gladexml.get_widget("port").get_text() | ||
try: | ||
number = int(port) | ||
except (ValueError, IndexError): | ||
dialog.hide() | ||
|
||
#if port == self.port: | ||
# dialog.hide() | ||
|
||
self.port = port | ||
self.client.set_string(self.gconf_keys['port'], self.port) | ||
self.restart() | ||
print "Rhythmote now running on port: "+ port | ||
dialog.hide() | ||
|
||
dialog.connect("response", dialog_response) | ||
|
||
dialog.present() | ||
return dialog | ||
|
||
|
||
def restart(self): | ||
if self.daemon: | ||
print "terminating daemon" | ||
self.daemon.terminate() | ||
self.daemon = subprocess.Popen(["/usr/bin/python", self.cwd+"/daemon.py", str(self.port)]); | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
|
||
|
||
#Copyright (C) 2009 Nikitas Stamatopoulos | ||
|
||
#This program is free software: you can redistribute it and/or modify | ||
#it under the terms of the GNU General Public License as published by | ||
#the Free Software Foundation, either version 3 of the License, or | ||
#(at your option) any later version. | ||
|
||
#This program is distributed in the hope that it will be useful, | ||
#but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
#GNU General Public License for more details. | ||
|
||
#You should have received a copy of the GNU General Public License | ||
#along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
|
||
|
||
import dbus, re, os, SocketServer, socket,sys | ||
import signal | ||
|
||
if len(sys.argv) == 2: | ||
port = int(sys.argv[1]) | ||
else: | ||
port = 8484 | ||
|
||
def on_exit(sig, func=None): | ||
print "exiting Rhythmote daemon" | ||
server_socket.shutdown(1) | ||
server_socket.close() | ||
|
||
signal.signal(signal.SIGTERM, on_exit) | ||
|
||
|
||
|
||
|
||
bus = dbus.SessionBus() | ||
rbox = bus.get_object( 'org.gnome.Rhythmbox', '/org/gnome/Rhythmbox/Player') | ||
rboxs = bus.get_object( 'org.gnome.Rhythmbox', '/org/gnome/Rhythmbox/Shell') | ||
rboxp = bus.get_object( 'org.gnome.Rhythmbox', '/org/gnome/Rhythmbox/PlaylistManager') | ||
player = dbus.Interface(rbox, 'org.gnome.Rhythmbox.Player') | ||
shell = dbus.Interface(rboxs, 'org.gnome.Rhythmbox.Shell') | ||
playlist = dbus.Interface(rboxp, 'org.gnome.Rhythmbox.PlaylistManager') | ||
|
||
volume = 0 | ||
home = os.environ['HOME'] | ||
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||
server_socket.settimeout(None) | ||
server_socket.bind(("", port)) | ||
server_socket.listen(5) | ||
test_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | ||
test_socket.connect(('google.de',0)) | ||
ip = test_socket.getsockname()[0] | ||
test_socket.close() | ||
client_socket = None | ||
print 'Started Rhythmote on port %s' % (port) | ||
print 'Your IP is %s' % (ip) | ||
while 1: | ||
client_socket, address = server_socket.accept() | ||
received = client_socket.recv(512) | ||
action, var = received.split('/') | ||
|
||
if action == "coverImage": | ||
try: | ||
cover = open(shell.getSongProperties(player.getPlayingUri())['rb:coverArt-uri'] ) | ||
reply=cover.read() | ||
cover.close() | ||
except IOError: | ||
reply="" | ||
|
||
client_socket.send(reply) | ||
|
||
if action == "coverExists": | ||
if shell.getSongProperties(player.getPlayingUri()).has_key('rb:coverArt-uri'): | ||
coverExists="true" | ||
artwork_path = shell.getSongProperties(player.getPlayingUri())['rb:coverArt-uri'] | ||
if os.path.isfile(artwork_path): | ||
size = int(os.path.getsize(artwork_path)) | ||
if size > 200000: | ||
coverExists="false" | ||
else: | ||
coverExists="false" | ||
client_socket.send(reply) | ||
|
||
if action == "playPause": | ||
player.playPause(1) | ||
|
||
if action == "next": | ||
player.next() | ||
|
||
if action == "prev": | ||
player.previous() | ||
|
||
if action == "volumeDown": | ||
currVol = player.getVolume() | ||
currVol = currVol-0.1 | ||
if currVol < 0: | ||
currVol=0 | ||
player.setVolume(currVol) | ||
|
||
if action == "volumeUp": | ||
player.setVolume(player.getVolume()+0.1) | ||
|
||
if action == "mute": | ||
if player.getMute() == True: | ||
player.setMute(False) | ||
else: | ||
player.setMute(True) | ||
|
||
if action == "status": | ||
if player.getPlaying(): | ||
reply = "playing" | ||
else: | ||
reply = "paused" | ||
client_socket.send(reply.encode('utf-8')) | ||
|
||
if action == "album": | ||
reply = str(shell.getSongProperties(player.getPlayingUri())["album"]) | ||
client_socket.send(reply.encode('utf-8')) | ||
|
||
if action == "artist": | ||
reply = str(shell.getSongProperties(player.getPlayingUri())["artist"]) | ||
client_socket.send(reply.encode('utf-8')) | ||
|
||
if action == "title": | ||
reply = str(shell.getSongProperties(player.getPlayingUri())["title"]) | ||
client_socket.send(reply.encode('utf-8')) | ||
|
||
if action == "trackCurrentTime": | ||
reply = str(int(player.getElapsed())) | ||
client_socket.send(reply) | ||
|
||
if action == "trackTotalTime": | ||
reply = str(int(shell.getSongProperties(player.getPlayingUri())['duration'])) | ||
client_socket.send(reply) | ||
|
||
if action == "seek": | ||
player.setElapsed(int(var)) | ||
|
||
if action == "shuffle": | ||
pass | ||
|
||
if action == "repeat": | ||
pass | ||
|
||
|
||
if action == "all": | ||
try: | ||
if player.getPlaying(): | ||
status = "playing" | ||
else: | ||
status = "paused" | ||
album = str(shell.getSongProperties(player.getPlayingUri())["album"]) | ||
artist = str(shell.getSongProperties(player.getPlayingUri())["artist"]) | ||
title = str(shell.getSongProperties(player.getPlayingUri())["title"]) | ||
trackCurrentTime = str(int(player.getElapsed())) | ||
trackTotalTime = str(int(shell.getSongProperties(player.getPlayingUri())['duration'])) | ||
coverExists="false" | ||
if shell.getSongProperties(player.getPlayingUri()).has_key('rb:coverArt-uri'): | ||
coverExists="true" | ||
artwork_path = shell.getSongProperties(player.getPlayingUri())['rb:coverArt-uri'] | ||
if os.path.isfile(artwork_path): | ||
size = int(os.path.getsize(artwork_path)) | ||
if size > 200000: | ||
coverExists="false" | ||
else: | ||
coverExists="false" | ||
sep = '/' | ||
reply=status+sep+album+sep+artist+sep+title+sep+trackCurrentTime+sep+trackTotalTime+sep+coverExists | ||
client_socket.send(reply.encode('utf-8')) | ||
|
||
except Exception as e: | ||
lala=1 | ||
|
||
client_socket.close() | ||
|
||
|
||
### DEBUG ### | ||
# code to get all methods | ||
#from dbus import SessionBus, Interface | ||
#from dbus._expat_introspect_parser import process_introspection_data | ||
|
||
def introspect_object(named_service, object_path): | ||
'''This is debug output function''' | ||
obj = SessionBus().get_object(named_service, object_path) | ||
iface = Interface(obj, 'org.freedesktop.DBus.Introspectable') | ||
return process_introspection_data(iface.Introspect()) | ||
|
||
#introspect_object('org.gnome.Rhythmbox', '/org/gnome/Rhythmbox/Shell') | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> | ||
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> | ||
|
||
<glade-interface> | ||
<requires lib="gnome"/> | ||
<widget class="GtkDialog" id="preferences_dialog"> | ||
<property name="visible">True</property> | ||
<property name="title" translatable="yes">Rhythmote Preferences</property> | ||
<property name="type">GTK_WINDOW_TOPLEVEL</property> | ||
<property name="window_position">GTK_WIN_POS_NONE</property> | ||
<property name="modal">False</property> | ||
<property name="resizable">True</property> | ||
<property name="destroy_with_parent">False</property> | ||
<property name="decorated">True</property> | ||
<property name="skip_taskbar_hint">False</property> | ||
<property name="skip_pager_hint">False</property> | ||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> | ||
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property> | ||
<property name="focus_on_map">True</property> | ||
<property name="urgency_hint">False</property> | ||
<property name="has_separator">True</property> | ||
<child internal-child="vbox"> | ||
<widget class="GtkVBox" id="dialog-vbox2"> | ||
<property name="visible">True</property> | ||
<property name="orientation">vertical</property> | ||
<property name="spacing">2</property> | ||
<child> | ||
<widget class="GtkVBox" id="vbox1"> | ||
<property name="visible">True</property> | ||
<property name="orientation">vertical</property> | ||
<child> | ||
<widget class="GtkLabel" id="port"> | ||
<property name="visible">True</property> | ||
<property name="xalign">0</property> | ||
<property name="yalign">1</property> | ||
<property name="label" translatable="yes">Port:</property> | ||
</widget> | ||
<packing> | ||
<property name="position">0</property> | ||
</packing> | ||
</child> | ||
<child> | ||
<widget class="GtkEntry" id="port"> | ||
<property name="visible">True</property> | ||
<property name="can_focus">True</property> | ||
<property name="invisible_char">●</property> | ||
<property name="text" translatable="yes">8484</property> | ||
<property name="caps_lock_warning">False</property> | ||
</widget> | ||
<packing> | ||
<property name="position">1</property> | ||
</packing> | ||
</child> | ||
</widget> | ||
<packing> | ||
<property name="position">1</property> | ||
</packing> | ||
</child> | ||
<child internal-child="action_area"> | ||
<widget class="GtkHButtonBox" id="dialog-action_area2"> | ||
<property name="visible">True</property> | ||
<property name="layout_style">end</property> | ||
<child> | ||
<widget class="GtkButton" id="button1"> | ||
<property name="label" translatable="yes">close</property> | ||
<property name="visible">True</property> | ||
<property name="can_focus">True</property> | ||
<property name="receives_default">True</property> | ||
</widget> | ||
<packing> | ||
<property name="expand">False</property> | ||
<property name="fill">False</property> | ||
<property name="position">0</property> | ||
</packing> | ||
</child> | ||
</widget> | ||
<packing> | ||
<property name="expand">False</property> | ||
<property name="pack_type">end</property> | ||
<property name="position">0</property> | ||
</packing> | ||
</child> | ||
</widget> | ||
</child> | ||
</widget> | ||
</glade-interface> |
Oops, something went wrong.