Wenn dies dein erster Besuch hier ist, lies bitte zuerst die Hilfe - Häufig gestellte Fragen durch. Du musst dich vermutlich registrieren, bevor du Beiträge verfassen kannst. Klicke oben auf 'Registrieren', um den Registrierungsprozess zu starten. Du kannst auch jetzt schon Beiträge lesen. Suche dir einfach das Forum aus, das dich am meisten interessiert.
Kannst du den Fehler genauer beschreiben? Hört der Player auf zu spielen? Oder wird nur der Titel/Interpret falsch angezeigt?
In der Anzeige steht dann gar nichts oder der vorherige Titel (ohne Umlaute).Ist unterschiedlich.Der Player spielt dabei weiter.
Sämtliche Funktionen (Lauter, Leiser, vor, Zurück etc.) werden dann bei Betätigen nicht mehr ausgeführt.
F5 bleibt erfolglos.
Springt man dann (z.B. über das Webinterface oder "manuell") zu einem Titel ohne Umlaute muß man die Seite der Visu neu laden oder f5 drücken und es passt läuft wie gewohnt....bis zum nächsten Titel mit Umlaut
Hallo Robert,
hab heute Vormittag noch 2 weitere Player mit Deinem Plugin eingebaut.
Beim Radio ist es in der Tat scheinbar "nur" ein UTF-8 Problem gewesen.
Hast Du auch mal ne Playlist von nem Album abgespielet oder "durchlaufen" lassen? Hier "hängt" sich die Bedienung bei mir bei jedem Song mit Umlauten noch auf.
Geile Arbeit..... Geiles Plugin.
Habs zwar noch nicht zu 100% eigebaut. Aber Lauter, Leiser, Play, Vor, Zurück und Mute gehen bei mir schonmal perfekt.
Außer...... das "bekannte Problem" mit Umlauten in Künstler- oder Songnamen bringt das Plugin bei der Bedienung ins Stocken.
Hinterlegte Playlists (z.B. Radiosender) könnte man ja "vorläufig" via multimedia.station aufrufen.
Hi!
Danke dir!
Songnamen sind schon gefixt - nimm bitte die angehängte Version. Da fehlte die Konvertierung von UTF-8.
Was die Playlist angeht komm ich grad nicht mit - wie du richtig sagst geht vor/zurück. Aber eine neue Playlists geht momentan nur per fixem Boolean-Item (siehe Playlist_Load_Internetradio), da ich keine Möglichkeit kenne einen String auszuwählen?
Achtung: Statt * wird nun für <playerid> die ID der jeweiligen Squeezebox gesetzt - wurde benötigt da manchmal die ID nicht nur an erster Stelle steht und mir * dann einfach zu gefährlich war.
Code:
#!/usr/bin/env python
# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab
#########################################################################
# Copyright 2013 Robert Budde [EMAIL="robert@projekt131.de"]robert@projekt131.de[/EMAIL]
#########################################################################
# Squeezebox-Plugin for SmartHome.py. [url=http://mknx.github.com/smarthome/]SmartHome.py - Overview[/url]
#
# This plugin 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 plugin 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 plugin. If not, see <[url=http://www.gnu.org/licenses/]Licenses - GNU Project - Free Software Foundation (FSF)[/url]>.
#########################################################################
import logging
import struct
import time
import urllib2
import lib.my_asynchat
import re
logger = logging.getLogger('Squeezebox')
class Squeezebox(lib.my_asynchat.AsynChat):
def __init__(self, smarthome, host='127.0.0.1', port=9090):
lib.my_asynchat.AsynChat.__init__(self, smarthome, host, port)
self._sh = smarthome
self._val = {}
self._obj = {}
self._init_cmds = []
smarthome.monitor_connection(self)
def _check_mac(self, mac):
return re.match("[0-9a-f]{2}([:])[0-9a-f]{2}([URL="file://\\1"]\\1[/URL][0-9a-f]{2}){4}$", mac.lower())
def _resolv_full_cmd(self, item, attr):
# check if PlayerID wildcard is used
if '<playerid>' in item.conf[attr]:
# try to get from parent object
parent_item = item.return_parent()
if (parent_item != None) and ('squeezebox_playerid' in parent_item.conf) and self._check_mac(parent_item.conf['squeezebox_playerid']):
item.conf[attr] = item.conf[attr].replace('<playerid>', parent_item.conf['squeezebox_playerid'])
else:
logger.warning("squeezebox: could not resolve playerid for {0} from parent item {1}".format(item, parent_item))
return None
return item.conf[attr]
def parse_item(self, item):
if 'squeezebox_recv' in item.conf:
cmd = self._resolv_full_cmd(item,'squeezebox_recv')
if (cmd == None):
return None
logger.debug("squeezebox: {0} receives updates by \"{1}\"".format(item, cmd))
if not cmd in self._val:
self._val[cmd] = {'items': [item], 'logics': []}
else:
if not item in self._val[cmd]['items']:
self._val[cmd]['items'].append(item)
if ('squeezebox_init' in item.conf):
cmd = self._resolv_full_cmd(item,'squeezebox_init')
if (cmd == None):
return None
logger.debug("squeezebox: {0} is initialized by \"{1}\"".format(item, cmd))
if not cmd in self._val:
self._val[cmd] = {'items': [item], 'logics': []}
else:
if not item in self._val[cmd]['items']:
self._val[cmd]['items'].append(item)
if not cmd in self._init_cmds:
self._init_cmds.append(cmd)
if 'squeezebox_send' in item.conf:
cmd = self._resolv_full_cmd(item,'squeezebox_send')
if (cmd == None):
return None
logger.debug("squeezebox: {0} is send to \"{1}\"".format(item, cmd))
return self.update_item
else:
return None
def parse_logic(self, logic):
pass
def update_item(self, item, caller=None, source=None, dest=None):
# be careful: as the server echoes ALL comands not using this will result in a loop
if caller != 'LMS':
cmd = self._resolv_full_cmd(item, 'squeezebox_send').split()
if self._check_mac(cmd[0]):
cmd[0] = urllib2.quote(cmd[0])
if isinstance(item(), str):
value = urllib2.quote(item().encode('utf-8'))
elif (item._type == 'bool'):
# convert to get '0'/'1' instead of 'True'/'False'
value = int(item())
else:
value = item()
# special handling
if (len(cmd) >= 2):
if (cmd[1] == 'play') and not item():
# if 'play' was set to false, send 'stop' to allow single-item-operation
cmd[1] = 'stop'
value = '1'
elif (cmd[1] == 'pause') and not item():
# squeezebox un-mutes when un-pausing but does not update the state itself - unmute manually to reflect actual state correctly
self._send(cmd[0] + ' mixer muting 0')
self._send(' '.join(cmd_str for cmd_str in cmd).format(value))
def _send(self, cmd):
logger.debug("Sending request: {0}".format(cmd))
self.push(cmd+'\r\n')
def _parse_response(self, response):
data = [urllib2.unquote(data_str) for data_str in response.split()]
logger.debug("Got: {0}".format(data))
# if (data[0].lower() == 'player'):
# if (data[1].lower() == 'count'):
# num_players = int(data[2])
# logger.info("Found {0} player".format(num_players))
# for i in range(0,num_players):
# self._send("player name {0} ?".format(i))
# self._send("player id {0} ?".format(i))
# elif (data[1].lower() == 'name'):
# logger.info("Players {0} name is: {1}".format(data[2], data[3]))
# elif (data[1].lower() == 'id'):
# logger.info("Players {0} id is: {1}".format(data[2], data[3]))
if (data[0].lower() == 'listen'):
value = int(data[1])
if (value == 1):
logger.info("Listen-mode enabled")
else:
logger.info("Listen-mode disabled")
if self._check_mac(data[0]):
if (data[1] == 'play'):
self._update_items_with_data([data[0], 'play', 1])
self._update_items_with_data([data[0], 'stop', 0])
self._update_items_with_data([data[0], 'pause', 0])
# play also overrules mute
self._update_items_with_data([data[0], 'prefset server mute', 0])
return
elif (data[1] == 'stop'):
self._update_items_with_data([data[0], 'play', 0])
self._update_items_with_data([data[0], 'stop', 1])
self._update_items_with_data([data[0], 'pause', 0])
return
elif (data[1] == 'pause'):
self._send(data[0] + ' mode ?')
self._send(data[0] + ' mixer muting ?')
return
elif (data[1] == 'mode'):
self._update_items_with_data([data[0], 'play', data[2] == 'play'])
self._update_items_with_data([data[0], 'stop', data[2] == 'stop'])
self._update_items_with_data([data[0], 'pause', data[2] == 'pause'])
# play also overrules mute
return
elif (data[1] == 'prefset'):
if (data[2] == 'server'):
if (data[3] == 'volume'):
# make sure value is always positive - also if muted!
data[4] = abs(int(data[4]))
elif (data[1] == 'playlist'):
if (data[2] == 'newsong'):
# trigger reading of other song fields
for field in ['genre', 'artist', 'album', 'title', 'duration']:
self._send(data[0] + ' ' + field + ' ?')
elif (data[1] in ['genre', 'artist', 'album', 'title', 'duration']) and (len(data) == 2):
# these fields are returned empty so no update takes plase - append '' to trigger update
data.append('')
self._update_items_with_data(data)
def _update_items_with_data(self, data):
cmd = ' '.join(data_str for data_str in data[:-1])
if (cmd in self._val):
for item in self._val[cmd]['items']:
if isinstance(item(), str):
data[-1] = data[-1].decode('utf-8')
item(data[-1], 'LMS', "{}:{}".format(self.addr[0],self.addr[1]))
def found_terminator(self):
response = self.buffer
self.buffer = ''
self._parse_response(response)
def handle_connect(self):
self.discard_buffers()
# start discovering players and their respective IDs and names
# self._send('players 0')
self._send('listen 1')
if self._init_cmds != []:
if self.is_connected:
logger.debug('squeezebox: init read')
for cmd in self._init_cmds:
self._send(cmd+' ?')
def run(self):
self.alive = True
def stop(self):
self.alive = False
self.handle_close()
Code:
# Hobbyraum/Experimental
[Squeezebox_1]
squeezebox_playerid = 00:04:20:xx:xx:xx
[[Name]]
type = str
visu = yes
squeezebox_send = <playerid> name {}
squeezebox_recv = <playerid> name
[[IP]]
type = str
visu = yes
squeezebox_recv = player ip <playerid>
[[Signal_Strength]]
type = num
visu = yes
squeezebox_recv = <playerid> signalstrength
[[Power]]
type = bool
visu = yes
squeezebox_send = <playerid> power {}
squeezebox_recv = <playerid> prefset server power
squeezebox_init = <playerid> power
[[Mute]]
type = bool
visu = yes
squeezebox_send = <playerid> mixer muting {}
squeezebox_recv = <playerid> prefset server mute
squeezebox_init = <playerid> mixer muting
[[Volume]]
type = num
visu = yes
squeezebox_send = <playerid> mixer volume {}
squeezebox_recv = <playerid> prefset server volume
squeezebox_init = <playerid> mixer volume
[[Volume_Up]]
type = bool
enforce_updates = true
visu = yes
squeezebox_send = <playerid> button volup
[[Volume_Down]]
type = bool
enforce_updates = true
visu = yes
squeezebox_send = <playerid> button voldown
[[Play]]
type = bool
visu = yes
squeezebox_send = <playerid> play
squeezebox_recv = <playerid> play
squeezebox_init = <playerid> mode
[[Stop]]
type = bool
visu = yes
squeezebox_send = <playerid> stop
squeezebox_recv = <playerid> stop
squeezebox_init = <playerid> mode
[[Pause]]
type = bool
visu = yes
squeezebox_send = <playerid> pause {}
squeezebox_recv = <playerid> pause
squeezebox_init = <playerid> mode
[[Current_Title]]
type = str
visu = yes
squeezebox_recv = <playerid> playlist newsong
squeezebox_init = <playerid> current_title
[[Genre]]
type = str
visu = yes
squeezebox_recv = <playerid> genre
[[Artist]]
type = str
visu = yes
squeezebox_recv = <playerid> artist
[[Album]]
type = str
visu = yes
squeezebox_recv = <playerid> album
[[Title]]
type = str
visu = yes
squeezebox_recv = <playerid> title
[[Duration]]
type = num
visu = yes
squeezebox_recv = <playerid> duration
[[Playlist_Index]]
type = num
visu = yes
squeezebox_send = <playerid> playlist index {}
squeezebox_recv = <playerid> playlist index
[[Playlist_Forward]]
type = bool
enforce_updates = true
visu = yes
squeezebox_send = <playerid> playlist index +1
[[Playlist_Backward]]
type = bool
enforce_updates = true
visu = yes
squeezebox_send = <playerid> playlist index -1
[[Playlist_Name]]
type = str
visu = yes
squeezebox_send = <playerid> playlist name {}
squeezebox_recv = <playerid> playlist name
[[Playlist_Save]]
type = str
visu = yes
squeezebox_send = <playerid> playlist save {}
[[Playlist_Load]]
type = str
enforce_updates = true
visu = yes
squeezebox_send = <playerid> playlist play {}
[[Playlist_Load_Internetradio]]
type = bool
enforce_updates = true
visu = yes
squeezebox_send = <playerid> playlist play [URL]file:///home/robert/playlists/Internetradio.m3u[/URL]
Geile Arbeit..... Geiles Plugin.
Habs zwar noch nicht zu 100% eigebaut. Aber Lauter, Leiser, Play, Vor, Zurück und Mute gehen bei mir schonmal perfekt.
Außer...... das "bekannte Problem" mit Umlauten in Künstler- oder Songnamen bringt das Plugin bei der Bedienung ins Stocken.
Hinterlegte Playlists (z.B. Radiosender) könnte man ja "vorläufig" via multimedia.station aufrufen.
Neee ... hätte ich auch so gemacht ... wie gesagt ... Zeit oh Zeit ... vielleicht schmeiß ich zum testen mal den LMS auf meinen (noch Windows) HomeServer.
ja, das ist korrekt. Man könnte wohl auch selektiv mit "subscribe" arbeiten, aber in meinen Augen macht das angesichts der wohl üblicherweise verlangten Informationen keinen Sinn.
Sobald wieder mehr Zeit ist werde ich das testen ... momentan zu viele Baustellen ... sieht aber sauber aus ... du arbeitest auch mit dem "listen" via telnet um den Status der Squeeze aktuell zu halten wenn ich das richtig interpretiere (bin da nur kurz drübergeflogen) ?
Hab gerade in der Docu-Visu geguckt: "popup3" wäre als Basis Klasse! Allerdings weiß ich nicht, wie ich da eine dynamische Liste reinbringe? Sonst ginge ja nur (z.B.) 5 Items für die ersten 5 Playlisten die dann über einen Button ausgewählt werden könnten. Wäre etwas umständlich und halt von der Anzahl limitiert und unübersichtlich (sowohl item.conf als auch in der Visu-Erstellung).
Die Optik des Players ist momentan quasi eine Kopie von Axel Otterstätter "multimedia.music". Da habe ich nur die Sachen angepasst die nicht zu den Items der Squeezebox passen. Wenn alle Features mal fix sind, kann da vielleicht jemand der kreativer als ich ist Hand anlegen.
Was für mich momentan interessant wäre:
"Oben rechts" ist momentan der Playlisten-Button, welcher die Standard-Playliste (bei mir "Internetradio") lädt. Schöner wäre es natürlich, wenn sich ein Popup öffnen würde, welches die verfügbaren Playlisten anzeigt (dynamisch, vl. 5 direkt, sonst zum scrollen?). Wenn man dann eine auswählt wird diese geladen.
Ich könnte ein Item erstellen ("* playlists 0 99"), welches alle Playlisten zurückgeben würde. Evtl. kann man das umformatieren, denn momentan kommt dann:
Danke dir! Das mit dem Abspeichern und Laden einer Playliste scheint dann also der Weg zu sein. Lautstärke wäre dann ja in der Tat genauso: Vorher abspeichern, hinterher wiederherstellen. Ist dann wahrscheinlich eher was für eine "Logik" als für das Plugin.
Folgende Items funktionieren jetzt auch (ohne Änderungen am Plugin!):
Code:
[[Playlist_Index]]
type = num
visu = yes
squeezebox_send = * playlist index {}
squeezebox_recv = * playlist index
[[Playlist_Forward]]
type = bool
enforce_updates = true
visu = yes
squeezebox_send = * playlist index +1
[[Playlist_Backward]]
type = bool
enforce_updates = true
visu = yes
squeezebox_send = * playlist index -1
[[Playlist_Name]]
type = str
visu = yes
squeezebox_send = * playlist name {}
squeezebox_recv = * playlist name
[[Playlist_Save]]
type = str
visu = yes
squeezebox_send = * playlist save {}
[[Playlist_Load]]
type = str
enforce_updates = true
visu = yes
squeezebox_send = * playlist play {}
[[Playlist_Load_Internetradio]]
type = bool
enforce_updates = true
visu = yes
squeezebox_send = * playlist play [URL]file:///home/robert/playlists/Internetradio.m3u[/URL]
Damit müsste es jetzt auch Alarmierungen möglich sein.
Wir verarbeiten personenbezogene Daten über die Nutzer unserer Website mithilfe von Cookies und anderen Technologien, um unsere Dienste bereitzustellen. Weitere Informationen findest Du in unserer Datenschutzerklärung.
Indem Du unten auf "ICH stimme zu" klickst, stimmst Du unserer Datenschutzerklärung und unseren persönlichen Datenverarbeitungs- und Cookie-Praktiken zu, wie darin beschrieben. Du erkennst außerdem an, dass dieses Forum möglicherweise außerhalb Deines Landes gehostet wird und bist damit einverstanden, dass Deine Daten in dem Land, in dem dieses Forum gehostet wird, gesammelt, gespeichert und verarbeitet werden.
Einen Kommentar schreiben: