The branch, dharma-pre has been updated
via 92cb94e150794b48bb7706568733d4bee577cd00 (commit)
from ab62fdec60e5f56ff59906ff8bcf83c31912f3b1 (commit)
- Log -----------------------------------------------------------------
http://xbmc.git.sourceforge.net/git/gitweb.cgi?p=xbmc/scripts;a=commit;h=92cb94e150794b48bb7706568733d4bee577cd00
commit 92cb94e150794b48bb7706568733d4bee577cd00
Author: amet <a...@nospam>
Date: Sun Nov 7 23:00:12 2010 +0400
[script.mpdc] -v0.9.8
- fixed deadlocks/hangs when autoplaying stream
- added context menu in current queue to be able to remove single tracks
from queue
- added: showing song progress when playing - can be disabled in settings
(for low bandwidth connections)
- changed background to fanart in Transparency! skin
diff --git a/script.mpdc/addon.xml b/script.mpdc/addon.xml
index fbafc69..2c80879 100644
--- a/script.mpdc/addon.xml
+++ b/script.mpdc/addon.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="script.mpdc"
name="MPD Client"
- version="0.9.7"
+ version="0.9.8"
provider-name="lzoubek">
<requires>
<import addon="xbmc.python" version="1.0"/>
diff --git a/script.mpdc/changelog.txt b/script.mpdc/changelog.txt
index 57406d3..ac3edfd 100644
--- a/script.mpdc/changelog.txt
+++ b/script.mpdc/changelog.txt
@@ -1,3 +1,8 @@
+[B]0.9.8[/B]
+- fixed deadlocks/hangs when autoplaying stream
+- added context menu in current queue to be able to remove single tracks from
queue
+- added: showing song progress when playing - can be disabled in settings (for
low bandwidth connections)
+- changed background to fanart in Transparency! skin
[B]0.9.7[/B]
- added Transparency! skin support
- fixed non-working STOP action (from remotes)
diff --git a/script.mpdc/default.py b/script.mpdc/default.py
index bb36b62..3513a4a 100644
--- a/script.mpdc/default.py
+++ b/script.mpdc/default.py
@@ -122,7 +122,6 @@ class SelectMPDProfile ( xbmcgui.WindowXMLDialog ) :
skin = 'Confluence'
current_skin=str(xbmc.getSkinDir().lower())
-print current_skin
if current_skin.find('pm3') > -1:
skin = 'PM3.HD'
if current_skin.find('transparency') > -1:
diff --git a/script.mpdc/resources/language/Czech/strings.xml
b/script.mpdc/resources/language/Czech/strings.xml
index 1f002b9..1564a6f 100644
--- a/script.mpdc/resources/language/Czech/strings.xml
+++ b/script.mpdc/resources/language/Czech/strings.xml
@@ -39,7 +39,14 @@
<string id="30032">Aktualizuji databázi</string>
<string id="30033">URL Streamu</string>
<string id="30034">PÅehrávat stream pokud je MPD server ve stavu
'playing'</string>
- <string id="30035">Heslo k servru</string>
+ <string id="30035">Heslo k servru</string>
+ <string id="30036">Odebrat z fronty</string>
+ <string id="30037">Uložit frontu jako</string>
+ <string id="30038">Vyprázdnit frontu</string>
+ <!-- Do not translate - block start -->
+ <string id="30039">Playing stream</string>
+ <!-- Do not translate - block end -->
+ <string id="30040">Zobrazovat Äas pÅehrávané skladby</string>
<string id="200">Fronta</string>
<string id="201">Soubory</string>
<string id="202">AutoÅi</string>
diff --git a/script.mpdc/resources/language/English/strings.xml
b/script.mpdc/resources/language/English/strings.xml
index bd73ed7..f3e8178 100644
--- a/script.mpdc/resources/language/English/strings.xml
+++ b/script.mpdc/resources/language/English/strings.xml
@@ -40,6 +40,13 @@
<string id="30033">Stream URL</string>
<string id="30034">Start playing Stream when MPD server is in 'playing'
state</string>
<string id="30035">Server password</string>
+ <string id="30036">Remove from queue</string>
+ <string id="30037">Save queue as</string>
+ <string id="30038">Clear queue</string>
+ <!-- Do not translate - block start -->
+ <string id="30039">Playing stream</string>
+ <!-- Do not translate - block end -->
+ <string id="30040">Show song progress when playing</string>
<string id="200">Queue</string>
<string id="201">Files</string>
<string id="202">Artists</string>
diff --git a/script.mpdc/resources/lib/gui.py b/script.mpdc/resources/lib/gui.py
index 5ae139d..b2a4ce0 100644
--- a/script.mpdc/resources/lib/gui.py
+++ b/script.mpdc/resources/lib/gui.py
@@ -72,7 +72,11 @@ SAVE_QUEUE_AS=1102
PLAYLIST_BROWSER=1401
ARTIST_BROWSER=1301
RB_CONSUME_MODE=704
+SONG_PROGRESS=991
+SONG_PROGESS_GROUP=99
+SONG_PRORESS_TEXT=992
Addon = xbmcaddon.Addon(id=os.path.basename(os.getcwd()))
+__scriptname__ = Addon.getAddonInfo('name')
#String IDs
STR_STOPPED=Addon.getLocalizedString(30003)
@@ -99,15 +103,25 @@ STR_UPDATE_LIBRARY=Addon.getLocalizedString(30029)
STR_QUEUE_ADD=Addon.getLocalizedString(30030)
STR_QUEUE_REPLACE=Addon.getLocalizedString(30031)
STR_UPDATING_LIBRARY=Addon.getLocalizedString(30032)
+STR_REMOVE_FROM_QUEUE=Addon.getLocalizedString(30036)
+STR_SAVE_QUEUE_AS=Addon.getLocalizedString(30037)
+STR_CLEAR_QUEUE=Addon.getLocalizedString(30038)
+STR_PLAYING_STREAM=Addon.getLocalizedString(30039)
STR_SAVE_AS=Addon.getLocalizedString(205)
class GUI ( xbmcgui.WindowXMLDialog ) :
def __init__( self, *args, **kwargs ):
- self.client = pmpd.PMPDClient()
+ self.addon = xbmcaddon.Addon(id=os.path.basename(os.getcwd()))
+ self.time_polling=False
+ if 'true' == self.addon.getSetting('time-polling'):
+ self.client = pmpd.PMPDClient(poll_time=True)
+
self.client.register_time_callback(self._handle_time_changes)
+ self.time_polling = True
+ else:
+ self.client = pmpd.PMPDClient()
self.client.register_callback(self._handle_changes)
self.profile_id=args[3]
self.skin=args[2]
- self.addon = xbmcaddon.Addon(id=os.path.basename(os.getcwd()))
self.profile_name=
self.addon.getSetting(self.profile_id+'_name')
self.mpd_host =
self.addon.getSetting(self.profile_id+'_mpd_host')
self.mpd_port =
self.addon.getSetting(self.profile_id+'_mpd_port')
@@ -131,6 +145,7 @@ class GUI ( xbmcgui.WindowXMLDialog ) :
self.getControl( PROFILE ).setLabel(self.profile_name)
self._connect()
def _connect(self):
+ self.getControl(SONG_PROGESS_GROUP).setVisible(False)
p = xbmcgui.DialogProgress()
p.create(STR_CONNECTING_TITLE,STR_CONNECTING_TITLE+'
'+self.mpd_host+':'+self.mpd_port)
p.update(0)
@@ -154,6 +169,7 @@ class GUI ( xbmcgui.WindowXMLDialog ) :
self.getControl ( STATUS ).setLabel(STR_CONNECTED_TO +'
'+self.mpd_host+':'+self.mpd_port )
p.update(25,STR_GETTING_QUEUE)
self._handle_changes(self.client,['playlist','player','options'])
+
self._handle_time_changes(self.client,self.client.status())
p.update(50,STR_GETTING_PLAYLISTS)
self._update_file_browser()
self._update_playlist_browser(self.client.listplaylists())
@@ -166,6 +182,39 @@ class GUI ( xbmcgui.WindowXMLDialog ) :
xbmcgui.Dialog().ok('MPD','An error occured, see log')
self.exit()
+ def _update_current_queue(self,client=None):
+ state = client.status()
+ playlist = client.playlistinfo()
+ current = client.currentsong()
+ self.update_fields(current,['id'])
+ current_id = current['id']
+ index = self.getControl(CURRENT_PLAYLIST).getSelectedPosition()
+ if index < 0:
+ index = 0
+ gen_index=0 # generate index value to each item
+ self.getControl( CURRENT_PLAYLIST ).reset()
+ for item in playlist:
+
self.update_fields(item,['title','artist','album','time'])
+ listitem = xbmcgui.ListItem( label=item['title'])
+ listitem.setProperty( 'index', str(gen_index))
+ listitem.setProperty( 'id', item['id'] )
+ listitem.setProperty( 'artist', item['artist'] )
+ listitem.setProperty( 'album', item['album'] )
+ gen_index=gen_index+1
+ if not item['time'] == '':
+ listitem.setProperty( 'time',
self._format_time(item['time']) )
+ if item['title'] == '' and item['artist'] == '' and
item['album'] == '':
+ listitem.setProperty( 'file' , item['file'] )
+ if item['id'] == current_id:
+
listitem.setIconImage(state['state']+'-item.png')
+ self.getControl( CURRENT_PLAYLIST ).addItem( listitem )
+ if current_id == '' and
self.getControl(CURRENT_PLAYLIST).size() > 0:
+ item =
self.getControl(CURRENT_PLAYLIST).getListItem(0)
+ item.setIconImage(state['state']+'-item.png')
+ if self.getControl( CURRENT_PLAYLIST ).size() <= index:
+ index = self.getControl( CURRENT_PLAYLIST ).size()-1
+ self.getControl(CURRENT_PLAYLIST).selectItem(index)
+
def
_update_artist_browser(self,artist_item=None,client=None,back=False):
select_index=0
index = self.getControl(ARTIST_BROWSER).getSelectedPosition()
@@ -281,7 +330,14 @@ class GUI ( xbmcgui.WindowXMLDialog ) :
listitem.setIconImage('DefaultAudio.png')
self.getControl(FILE_BROWSER).addItem(listitem)
self.getControl(FILE_BROWSER).selectItem(select_index)
-
+
+ def _handle_time_changes(self,poller_client,status):
+ if not status['state'] == 'stop' and self.time_polling:
+ time = status['time'].split(':')
+ percent = float(time[0]) / (float(time[1])/100 )
+ self.getControl(SONG_PROGRESS).setPercent(percent)
+
self.getControl(SONG_PRORESS_TEXT).setLabel(self._format_time(time[0])+' -
'+self._format_time(time[1]))
+
def _handle_changes(self,poller_client,changes):
state = poller_client.status()
print 'Handling changes - ' + str(changes)
@@ -292,14 +348,17 @@ class GUI ( xbmcgui.WindowXMLDialog ) :
self.toggleVisible( PLAY, PAUSE )
self.getControl( STATUS
).setLabel(STR_PLAYING + ' : ' + self._current_song(current))
self.update_playlist('play',current)
+
self.getControl(SONG_PROGESS_GROUP).setVisible(self.time_polling)
elif state['state'] == 'pause':
self.toggleVisible( PAUSE, PLAY )
self.getControl( STATUS
).setLabel(STR_PAUSED + ' : ' + self._current_song(current))
self.update_playlist('pause',current)
+
self.getControl(SONG_PROGESS_GROUP).setVisible(self.time_polling)
elif state['state'] == 'stop':
self.getControl( STATUS
).setLabel(STR_STOPPED)
self.toggleVisible( PAUSE, PLAY )
self.update_playlist('stop',current)
+
self.getControl(SONG_PROGESS_GROUP).setVisible(False)
if change == 'options':
if state['repeat'] == '0':
self.toggleVisible( REPEAT_ON,
REPEAT_OFF )
@@ -319,36 +378,12 @@ class GUI ( xbmcgui.WindowXMLDialog ) :
self._update_file_browser(client=poller_client)
self._update_artist_browser(client=poller_client)
if change == 'playlist':
- playlist = poller_client.playlistinfo()
- current = poller_client.currentsong()
- self.update_fields(current,['id'])
- current_id = current['id']
- self.getControl( CURRENT_PLAYLIST
).reset()
- index = 0
- for item in playlist:
-
self.update_fields(item,['title','artist','album','time'])
- listitem = xbmcgui.ListItem(
label=item['title'])
- listitem.setProperty( 'index',
str(index))
- listitem.setProperty( 'id',
item['id'] )
- listitem.setProperty( 'artist',
item['artist'] )
- listitem.setProperty( 'album',
item['album'] )
- if not item['time'] == '':
- listitem.setProperty(
'time', self._format_time(item['time']) )
- if item['title'] == '' and
item['artist'] == '' and item['album'] == '':
- listitem.setProperty(
'file' , item['file'] )
- if item['id'] == current_id:
-
listitem.setIconImage(state['state']+'-item.png')
- self.getControl(
CURRENT_PLAYLIST ).addItem( listitem )
- index = index + 1
- if current_id == '' and
self.getControl(CURRENT_PLAYLIST).size() > 0:
- item =
self.getControl(CURRENT_PLAYLIST).getListItem(0)
-
item.setIconImage(state['state']+'-item.png')
+ self._update_current_queue(client=poller_client)
# print 'Changes handled'
def _format_time(self,time):
return '%d:%02d' % ((int(time) / 60 ),(int(time) % 60))
-
def toggleVisible(self,cFrom,cTo):
self.getControl( cFrom ).setVisible(False)
self.getControl( cTo ).setVisible(True)
@@ -413,6 +448,16 @@ class GUI ( xbmcgui.WindowXMLDialog ) :
self.getControl( STATUS
).setLabel(status)
def _context_menu(self):
+ if self.getFocusId() == CURRENT_PLAYLIST:
+ if self.getControl(CURRENT_PLAYLIST).size() < 1:
+ return
+ ret =
self.dialog(STR_SELECT_ACTION,[STR_REMOVE_FROM_QUEUE,STR_SAVE_QUEUE_AS,STR_CLEAR_QUEUE])
+ if ret==0:
+
self.client.deleteid(self.getControl(CURRENT_PLAYLIST).getSelectedItem().getProperty('id'))
+ if ret==1:
+ self._save_queue_as()
+ if ret==2:
+ self._clear_queue()
if self.getFocusId() == ARTIST_BROWSER:
ret =
self.dialog(STR_SELECT_ACTION,[STR_QUEUE_ADD,STR_QUEUE_REPLACE])
if ret == 0:
@@ -458,10 +503,14 @@ class GUI ( xbmcgui.WindowXMLDialog ) :
return
if player.isPlayingAudio():
if not player.getPlayingFile() ==
self.stream_url:
- player.play(self.stream_url)
+ self._start_media_player()
else:
- player.play(self.stream_url)
-
+ self._start_media_player()
+
+ def _start_media_player(self):
+ icon = os.path.join(os.getcwd(),'icon.png')
+ xbmc.executebuiltin("XBMC.Notification(%s,%s,5000,%s)" %
(__scriptname__,STR_PLAYING_STREAM,'icon.png'))
+ xbmc.executebuiltin('PlayMedia(%s)' % self.stream_url)
def disconnect(self):
p = xbmcgui.DialogProgress()
diff --git a/script.mpdc/resources/lib/pmpd.py
b/script.mpdc/resources/lib/pmpd.py
index 722adf1..e7c59a4 100644
--- a/script.mpdc/resources/lib/pmpd.py
+++ b/script.mpdc/resources/lib/pmpd.py
@@ -1,17 +1,27 @@
-import rmpd,select,threading,traceback,mpd
+import rmpd,select,threading,traceback,mpd,time
# polling MPD Client
class PMPDClient(object):
- def __init__(self):
+ def __init__(self,poll_time=False):
self.client = rmpd.RMPDClient()
self.poller = rmpd.RMPDClient()
+ self.time_poller = rmpd.RMPDClient()
self.callback = None
+ self.time_callback = None
self.thread = threading.Thread(target=self._poll)
self.thread.setDaemon(True)
self._permitted_commands = []
+ self.time_thread = None
+ self.time_event = None
+ if poll_time:
+ self.time_thread =
threading.Thread(target=self._poll_time)
+ self.time_thread.setDaemon(True)
+ self.time_event = threading.Event()
def register_callback(self,callback):
self.callback = callback
+ def register_time_callback(self,callback):
+ self.time_callback=callback;
# need to call try_command before passing any commands to list!
def command_list_ok_begin(self):
self.client.command_list_ok_begin()
@@ -35,6 +45,9 @@ class PMPDClient(object):
self.client.password(password)
self._permitted_commands = self.client.commands()
self.thread.start()
+ if not self.time_thread == None:
+ self.time_poller.connect(host,port)
+ self.time_thread.start()
def disconnect(self):
print 'disconnecting'
@@ -58,11 +71,56 @@ class PMPDClient(object):
self.poller.disconnect()
except:
pass
+
print 'waiting for poller thread'
if self.thread.isAlive():
self.thread.join()
+ print 'done'
+ if not self.time_thread == None:
+ print 'disconnecting time poller'
+ try:
+ self.time_poller.noidle()
+ except:
+ pass
+ try:
+ self.time_poller.close()
+ except:
+ pass
+ try:
+ self.time_poller.disconnect()
+ except:
+ pass
+ print 'waiting for time poller thread'
+ if not self.time_event and self.time_thread.isAlive():
+ return
+ self.time_event.set()
+ self.time_thread.join()
+ self.time_event=None
+ print 'done'
print 'client disconnected'
+ def _poll_time(self):
+ print 'Starting time poller thread'
+ while 1:
+ try:
+ status = self.time_poller.status()
+ while not status['state'] == 'play':
+ self.time_poller.send_idle()
+
select.select([self.time_poller],[],[],1)
+ changes = self.time_poller.fetch_idle()
+ if 'player' in changes:
+ status =
self.time_poller.status()
+ self.time_callback(self.time_poller,status)
+ self.time_event.wait(0.9)
+ if self.time_event.isSet():
+# print 'poller exited on event'
+ break;
+ except:
+# print "time poller error"
+# traceback.print_exc()
+ self.time_event = None
+ return
+
def _poll(self):
while 1:
try:
diff --git a/script.mpdc/resources/settings.xml
b/script.mpdc/resources/settings.xml
index 09b2f4c..a2c3afa 100644
--- a/script.mpdc/resources/settings.xml
+++ b/script.mpdc/resources/settings.xml
@@ -2,6 +2,7 @@
<settings>
<category label="30014">
<setting label="30013" type="bool" id="skip-selector"
default="false" />
+ <setting label="30040" type="bool" id="time-polling"
default="true" />
</category>
<category label="30110">
<setting label="30002" type="text" id="0_name" default="Profile
1"/>
diff --git a/script.mpdc/resources/skins/Confluence/720p/mpd-client-main.xml
b/script.mpdc/resources/skins/Confluence/720p/mpd-client-main.xml
index 7528bc8..774de24 100644
--- a/script.mpdc/resources/skins/Confluence/720p/mpd-client-main.xml
+++ b/script.mpdc/resources/skins/Confluence/720p/mpd-client-main.xml
@@ -52,6 +52,7 @@
<texture>VSeparator.png</texture>
</control>
</control>
+
<control type="group">
<description>left control group (switches content in right
control group)</description>
<posx>0</posx>
@@ -143,6 +144,7 @@
<texture border="40">ContentPanel.png</texture>
</control>
+
<control type="button" id="666">
<posx>20</posx>
@@ -859,5 +861,27 @@
</control>
+
+ <control type="group" id="99">
+ <description>song progress info group</description>
+ <posx>280</posx>
+ <posy>65</posy>
+ <control type="label" id="992">
+ <description>textarea</description>
+ <posx>580</posx>
+ <posy>0</posy>
+ <width>220</width>
+ <height>30</height>
+ <align>right</align>
+ <textcolor>white</textcolor>
+ <label></label>
+ </control>
+ <control type="progress" id="991">
+ <posx>0</posx>
+ <posy>30</posy>
+ <width>590</width>
+ <height>16</height>
+ </control>
+ </control>
</controls>
</window>
diff --git a/script.mpdc/resources/skins/PM3.HD/720p/mpd-client-main.xml
b/script.mpdc/resources/skins/PM3.HD/720p/mpd-client-main.xml
index 8632617..e4d10e4 100644
--- a/script.mpdc/resources/skins/PM3.HD/720p/mpd-client-main.xml
+++ b/script.mpdc/resources/skins/PM3.HD/720p/mpd-client-main.xml
@@ -53,6 +53,27 @@
<label></label>
</control>
</control>
+ <control type="group" id="99">
+ <description>song progress info group</description>
+ <posx>255</posx>
+ <posy>55</posy>
+ <control type="label" id="992">
+ <description>textarea</description>
+ <posx>610</posx>
+ <posy>0</posy>
+ <width>220</width>
+ <height>30</height>
+ <align>right</align>
+ <textcolor>white</textcolor>
+ <label></label>
+ </control>
+ <control type="progress" id="991">
+ <posx>0</posx>
+ <posy>30</posy>
+ <width>620</width>
+ <height>10</height>
+ </control>
+ </control>
<control type="group">
<description>left control group (switches content in right
control group)</description>
<posx>20</posx>
diff --git a/script.mpdc/resources/skins/transparency/720p/mpd-client-main.xml
b/script.mpdc/resources/skins/transparency/720p/mpd-client-main.xml
index d36fdc0..86b78de 100644
--- a/script.mpdc/resources/skins/transparency/720p/mpd-client-main.xml
+++ b/script.mpdc/resources/skins/transparency/720p/mpd-client-main.xml
@@ -17,7 +17,7 @@
<posy>0</posy>
<width>1280</width>
<height>720</height>
- <texture>background-music.jpg</texture>
+ <texture>fanart.jpg</texture>
</control>
<control type="image">
<posx>250</posx>
@@ -53,6 +53,26 @@
<label></label>
</control>
</control>
+ <control type="group" id="99">
+ <description>song progress info group</description>
+ <posx>260</posx>
+ <posy>60</posy>
+ <control type="label" id="992">
+ <description>textarea</description>
+ <posx>610</posx>
+ <posy>0</posy>
+ <width>220</width>
+ <height>30</height>
+ <align>right</align>
+ <textcolor>white</textcolor>
+ <label></label>
+ </control>
+ <control type="progress" id="991">
+ <posx>0</posx>
+ <posy>20</posy>
+ <width>620</width>
+ </control>
+ </control>
<control type="group">
<description>left control group (switches content in right
control group)</description>
<posx>20</posx>
-----------------------------------------------------------------------
Summary of changes:
script.mpdc/addon.xml | 2 +-
script.mpdc/changelog.txt | 5 +
script.mpdc/default.py | 1 -
script.mpdc/resources/language/Czech/strings.xml | 9 ++-
script.mpdc/resources/language/English/strings.xml | 7 ++
script.mpdc/resources/lib/gui.py | 111 ++++++++++++++------
script.mpdc/resources/lib/pmpd.py | 62 +++++++++++-
script.mpdc/resources/settings.xml | 1 +
.../skins/Confluence/720p/mpd-client-main.xml | 24 ++++
.../skins/PM3.HD/720p/mpd-client-main.xml | 21 ++++
.../skins/transparency/720p/mpd-client-main.xml | 22 ++++-
.../skins/transparency/media/background-music.jpg | Bin 329817 -> 0 bytes
.../skins/transparency/media}/fanart.jpg | Bin 86423 -> 86423 bytes
13 files changed, 228 insertions(+), 37 deletions(-)
delete mode 100644
script.mpdc/resources/skins/transparency/media/background-music.jpg
copy script.mpdc/{ => resources/skins/transparency/media}/fanart.jpg (100%)
hooks/post-receive
--
Scripts
------------------------------------------------------------------------------
The Next 800 Companies to Lead America's Growth: New Video Whitepaper
David G. Thomson, author of the best-selling book "Blueprint to a
Billion" shares his insights and actions to help propel your
business during the next growth cycle. Listen Now!
http://p.sf.net/sfu/SAP-dev2dev
_______________________________________________
Xbmc-addons mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/xbmc-addons