class LatencyGui(xbmcgui.WindowXMLDialog): def __init__(self, *_args, **_kwargs): self.sock = SocketCom("server") self.latency_info = self.sock.call_func("get", "latency") self.save = self.latency_info.copy() def onInit(self): self.header = self.getControl(100) self.header.setLabel(tr(32022)) self.slider = self.getControl(1900) self.label = self.getControl(2000) self.setFocus(self.slider) latency = int(self.latency_info["latency"] / 1000) self.slider.setInt(latency, 0, 25, 2000) self.label.setLabel("{:d} ms".format(latency)) def setLatency(self): latency = int(self.slider.getInt()) self.label.setLabel("{:d} ms".format(latency)) self.latency_info["latency"] = latency * 1000 self.sock.call_func("set", "latency", [self.latency_info]) def onAction(self, action): aid = action.getId() #log("%s %s"%(aid,self.getFocusId())) #OK pressed if aid == 7: self.close() #Cancel if aid in [92, 10]: self.sock.call_func("set", "latency", [self.save]) self.close() #up/down/left/right if aid in [1, 2, 3, 4, 106]: fid = self.getFocusId() if fid == 0: self.setFocusId(1900) self.setLatency()
class SweepGui(xbmcgui.WindowXMLDialog): def __init__(self, *_args, **kwargs): self.sock = SocketCom("server") self.rec = SocketCom("sweep") self.channel = kwargs["channel"] self.count = kwargs["count"] result = self.sock.call_func("get", "eq_channel") if result is None: return self.eqid, self.name, _ = (result) self.rec.start_func_server(self) def onInit(self): self.prog1 = self.getControl(1900) self.prog2 = self.getControl(1901) self.prog1.setPercent(0.1) self.prog2.setPercent(0.1) #self.getControl(101).setLabel("%s - %s" % (self.name, tr(32410))) self.sock.call_func("play", "sweep", [self.count, self.channel]) @staticmethod def on_sound_play(nr): log("on_sound_play %s" % nr) def on_sound_stop(self): log("on_sound_stop") self.rec.stop_server() self.close() def on_chunk_play(self, c_nr, c_size, c_cnt, c_total): self.prog1.setPercent(c_cnt * 100 / (c_total - 1)) self.prog2.setPercent(c_nr * 100 / (c_size - 1)) def end_gui(self): self.sock.call_func("stop", "tone") self.sock.call_func("stop", "pulseplayer") self.rec.stop_server() self.close() def onAction(self, action): #OK pressed if action.getId() in [7, 100]: self.end_gui() #Cancel if action.getId() in [92, 10]: self.end_gui()
def on_pa_connect(self): log("pamm: start paModuleManager") try: self.load_dyn_equalizer() self.eq_fatal = False except Exception as e: self.eq_fatal = True handle(e) logerror("cannot load pulseaudio-equalizer, maybe not installed?") logerror("run: sudo apt install pulseaudio-equalizer") return None self.config.load_config() self.load_required_module("module-dbus-protocol") self.eq.on_pa_connect() sock = SocketCom("kodi") player = sock.call_func("get", "player") if player and len(player) > 0: self.on_player_play() else: self.on_player_stop()
from helper import SocketCom #sc = SocketCom("sound") sc = SocketCom("server") if not sc.is_server_running(): print("server is not running") sys.exit(0) try: func = sys.argv[1] if func == "exit": sc.stop_server() sys.exit(0) target = sys.argv[2] try: args = [] for arg in sys.argv[3:]: args.append(float(arg)) except Exception: args = [] except Exception: print('usage: control_sound.py "start" "tone" 1000 0.5') sys.exit(0) print(func, target, args) sc.call_func(func, target, args)
def proc_device(self): self.output_sink = None sock = SocketCom("kodi") device = sock.call_func("get", "device") if device: self.proc_device_set(device)
class SweepGenGui( xbmcgui.WindowXMLDialog ): name = None eqid = None channel_id = [] channel = [] channel_sel = 0 profiles= [] save_profile = None sel_profile = 0 corrections=[] save_correction=None sel_correction=0 repeats = 0 def __init__( self, *args, **_kwargs ): self.cwd = args[1] self.skin = args[2] self.sock = SocketCom("server") result = self.sock.call_func("get","eq_channel") if result is None: return self.eqid, self.name, channel = (result) self.channel_id = channel ch_index = [] for ch_name in channel: try: index = chan_num.index(ch_name) ch_index.append(index) except Exception as e: opthandle(e) self.channel = ch_index self.profiles = [tr(32413)] + self.sock.call_func("get","eq_profiles") self.save_profile = self.sock.call_func("get","eq_base_profile") self.sock.call_func("unload","eq_profile",[self.eqid]) self.corrections =[tr(32411)] + self.sock.call_func("get","room_corrections") self.save_correction = self.sock.call_func("get","room_correction") self.sock.call_func("unset","room_correction" , [self.eqid]) def onInit( self ): if self.name is None: self.close() self.getControl(300).setLabel(self.profiles[self.sel_profile]) self.getControl(301).setLabel(self.corrections[self.sel_correction]) def on_sel_profile(self): nsel = contextMenu(items = self.profiles, default = self.profiles[self.sel_profile]) if nsel is None: return if nsel == 0: self.sock.call_func("unload","eq_profile",[self.eqid]) else: self.sock.call_func("load","eq_profile" , [self.eqid, self.profiles[nsel]]) self.sel_profile = nsel self.getControl(300).setLabel(self.profiles[self.sel_profile]) def on_sel_correction(self): nsel = contextMenu(items = self.corrections, default = self.corrections[self.sel_correction]) if nsel is None: return if nsel == 0: self.sock.call_func("unset","room_correction", [self.eqid]) else: self.sock.call_func("set","room_correction" , [self.eqid, self.corrections[nsel]]) self.sel_correction = nsel self.getControl(301).setLabel(self.corrections[nsel]) def on_sel_channel(self): sel_list = [tr(32412) + " (0)"] + [tr(32500 + i)+ " (%s)"%(i+1) for i in self.channel] nsel = contextMenu(items = sel_list, default = sel_list[self.channel_sel]) if nsel is None: return self.channel_sel=nsel self.getControl(302).setLabel(sel_list[nsel]) def on_sel_repeats(self): numbers = ["- %s -" % str(i+1) for i in range(10)] nsel = contextMenu(items = numbers, default = numbers[self.repeats]) if nsel is None: return self.repeats = nsel self.getControl(303).setLabel(str(nsel+1)) def on_sel_play(self): channel = None if self.channel_sel == 0 else self.channel_id[self.channel_sel-1] runDialog(SweepGui,"Sweep",channel=channel , count = self.repeats + 1) def handleOK(self): fid = self.getFocusId() if fid == 3000: self.on_sel_profile() elif fid == 3001: self.on_sel_correction() elif fid == 3002: self.on_sel_channel() elif fid == 3003: self.on_sel_repeats() elif fid == 3004: self.on_sel_play() def end_gui(self): if self.save_profile: self.sock.call_func("load","eq_profile",[self.eqid, self.save_profile]) if self.save_correction: self.sock.call_func("set","room_correction" , [self.eqid, self.save_correction]) self.close() def onAction( self, action ): #OK pressed if action.getId() in [7, 100]: self.handleOK() #Cancel if action.getId() in [92,10]: self.end_gui()
# import sys sys.path.append ('./resources/lib/') sys.path.append ('./fakekodi') from helper import SocketCom sc = SocketCom("server") if not sc.is_server_running(): print("server is not running") sys.exit(0) try: func = sys.argv[1] if func == "exit": sc.stop_server() sys.exit(0) target = sys.argv[2] try: args = sys.argv[3:] except Exception: args = [] except Exception: print('usage: query.py func target args...') sys.exit(0) print(func,target,args) print(sc.call_func(func,target,args))
class EqGui(xbmcgui.WindowXMLDialog): ''' Equalizer Dialog The equalizer dialog is build up dynamically ''' def __init__(self, *args, **kwargs): self.build_dialog(**kwargs) self.index = None self.updating = False self.controlId = 2000 self.cwd = args[1] self.sock = SocketCom("server") self.eqid = kwargs["eqid"] self.desc = kwargs["desc"] try: step = int(get_user_setting("equalstep", 0)) + 1 except Exception: step = int(1) self.dyn_step = DynStep(step, 5, 1, 3) self.sock.call_func("set", "eq_frequencies", [self.freqs]) self.profile = self.sock.call_func("get", "eq_base_profile") self.preamp, self.coef = self.sock.call_func("get", "eq_filter") self.is_changed = False def build_dialog(self, **kwargs): self.freqs = get_frequencies() color = kwargs["color"] file_s = kwargs["file_s"] header_t, itemgap_t, templ_t, end_t = get_template( file_s, [ "<!-- item gap -->", "<!-- element begin -->", "<!-- element end -->" ]) itemgap = int(read_next_tag("itemgap", itemgap_t, 0)) num_freq = len(self.freqs) if num_freq >= 15: itemgap = 0 itemgap_t = itemgap_t.format(itemgap=itemgap) width = int(read_next_tag("width", templ_t, 0)) slider_width = (width + itemgap) * num_freq if slider_width > 1700: slider_width = 1700 total_width = slider_width + 100 xpos = (1920 - total_width) / 2 items = "" i = 0 max_id = 1999 + num_freq for freq in self.freqs: item_r = self.set_replace_item(2000 + i, freq, max_id) items = items + templ_t.format(**item_r, **color) i += 1 glob = { "slider_width": slider_width, "total_width": total_width, "xpos": xpos } write_dialog( file_s, localize( header_t.format(**glob, **color) + itemgap_t + items + end_t)) @staticmethod def set_replace_item(item_id, freq, max_id): item_r = {"sid": item_id, "lid": item_id + 100, "onleft": item_id - 1} if item_id < max_id: item_r["onright"] = item_id + 1 else: item_r["onright"] = "" if freq < 1000: item_r["labelid"] = '$NUMBER[{}]'.format(int(freq)) else: item_r["labelid"] = format_float(freq) return item_r @staticmethod def str(nr): if nr < 1000: return str(nr) fnr = float(nr) / 1000 if round(fnr) == fnr: return "{:d}k".format(int(fnr)) else: return "{:.1f}k".format(fnr) @staticmethod def slider2coef(val): #slider 0-100 into dB [-20db .. 20db] = [0.1 ... 10] return 10.0**((val - 50.0) / 50.0) @staticmethod def coef2slider(val): return int(math.log10(val) * 50 + 50.0) def onInit(self): self.setFocusId(2000) #set slider names self.getControl(3500).setLabel(self.profile) self.getControl(3501).setLabel(self.desc) self.getControl(3502).setLabel("0 dB ") #set slider i = 0 for coef in self.coef[1:]: self.getControl(2000 + i).setInt(self.coef2slider(coef), 0, 0, 100) i = i + 1 # set preamp slider self.getControl(1999).setInt(self.coef2slider(self.preamp), 0, 0, 100) def onFocus(self, controlId): if controlId >= 1999 and controlId < 2100: self.controlId = controlId val = 2 * (self.getControl(self.controlId).getFloat() - 50) / 5 self.getControl(3502).setLabel("{:.1f} dB ".format(val)) def set_filter(self): self.coef[0] = self.coef[1] self.sock.call_func("set", "eq_filter", [self.eqid, self.preamp, self.coef]) def load_profile(self): self.sock.call_func("load", "eq_profile", [self.eqid, self.profile]) def save_profile(self): self.sock.call_func("save", "eq_profile", [self.profile]) def update(self): sleep(0.3) self.set_filter() self.updating = False self.is_changed = True def setFilter(self): val = 2 * (self.getControl(self.controlId).getFloat() - 50) / 5 self.getControl(3502).setLabel("{:.1f} dB ".format(val)) change = False for i in range(1, len(self.coef) - 2): c = self.slider2coef(self.getControl(1999 + i).getFloat()) if c != self.coef[i]: self.coef[i] = c change = True c = self.slider2coef(self.getControl(1999).getFloat()) if c != self.preamp: self.preamp = c change = True if not change: return if not self.updating: self.updating = True Thread(target=self.update).start() def _close(self): self.close() def sel_cancel(self): self.load_profile() self._close() def sel_save(self): self.save_profile() self._close() def onAction(self, action): t = time.time() aid = action.getId() fid = self.getFocusId() buc = action.getButtonCode() & 255 #log("eqdialog: key: %s fid: %s"%(aid,fid)) #OK pressed if aid in [7]: self.save_profile() self._close() if aid in [100]: if fid == 1800: #self.save_profile() self.load_profile() self._close() #Cancel if aid in [92, 10]: if self.is_changed: contextMenu(funcs=[(tr(32622), self.sel_cancel), (tr(32623), self.sel_save)]) else: self.close() self.dyn_step.dynamic_step(buc) if aid in [3, 104]: ctl = self.getControl(self.controlId) new = ctl.getInt() + self.dyn_step.dynstep if ctl.getInt() < 50 and new > 50: new = 50 pos = new if pos > 100: pos = 100 ctl.setInt(pos, 0, 0, 100) if aid in [4, 105]: ctl = self.getControl(self.controlId) new = ctl.getInt() - self.dyn_step.dynstep if ctl.getInt() > 50 and new < 50: new = 50 pos = new if pos < 0: pos = 0 ctl.setInt(pos, 0, 0, 100) if aid in [3, 4, 104, 105, 106]: self.setFocusId(self.controlId) self.setFilter() self.last_key = t
class PaMonitor( xbmc.Monitor ): def __init__( self ): #strat process xbmc.Monitor.__init__( self ) xbmc.log("eq: start PulesEqualizer service",xbmc.LOGDEBUG) self.server_sock = SocketCom("kodi") if not self.server_sock.is_server_running(): self.server_sock.start_func_server(self) else: self.server_sock = None launcher = Launcher("menu") launcher.start() self.sock = SocketCom("server") ps = PulseService() ps.start() self.sock.call_func("set","device",[self.get_device()]) while not self.abortRequested(): if self.waitForAbort( 10 ): break launcher.stop() ps.stop() if self.server_sock: self.server_sock.stop_server() @staticmethod def get_device(): device = "" r_dict = json.loads(xbmc.executeJSONRPC('{"jsonrpc":"2.0", "method":"Settings.GetSettings", "params":{ "filter": {"section":"system", "category":"audio"}}, "id":1}')) for s in r_dict["result"]["settings"]: if s["id"] == "audiooutput.audiodevice": device = s["value"] break return device def on_device_get(self): result = self.get_device() xbmc.log("eq: kodi service: on_device_get %s" % result,xbmc.LOGDEBUG) return result @staticmethod def on_player_get(): r_dict = json.loads(xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"Player.GetActivePlayers","id":0}')) try: return r_dict["result"] except Exception: return None @staticmethod def on_log_write(message, level): xbmc.log(message, level) def on_service_up(self): self.sock.call_func("set","device",[self.get_device()]) def onNotification( self, _sender, method, _data ): target,func = method.lower().replace("on","").split(".") if target in ["system", "player"]: self.sock.call_func(func, target)
class VolumeGui(xbmcgui.WindowXMLDialog): def __init__(self, *args, **kwargs): self.sock = SocketCom("server") self.path = os.path.join(args[1], "resources/skins/" + args[2] + "/media") self.progress1 = None self.updown = kwargs["updown"] try: step = (float(get_user_setting("sysvolstep", 0)) + 1) / 100 except Exception: step = float(0.01) if step <= 0: step = float(0.01) self.dyn_step = DynStep(step, 0.05, 0.01, 3) self.key_up = None self.key_down = None self.updating = False self.vol = self.sock.call_func("get", "volume") if self.updown == "up": self.vol_up() elif self.updown == "down": self.vol_down() self.last = time.time() if self.updown != "none": threading.Thread(target=self.check_close).start() def check_close(self): while True: if time.time() - self.last > 2: break time.sleep(0.5) self.close() def onInit(self): self.progress1 = self.getControl(1900) self.label = self.getControl(1901) self.set_vol_gui() # slow down messages to server def update_to_pulse(self): time.sleep(0.3) self.sock.call_func("set", "volume", [self.vol]) self.updating = False def update(self): if not self.updating: self.updating = True threading.Thread(target=self.update_to_pulse).start() def vol_up(self): if self.vol is None: return vol_new = self.vol + self.dyn_step.dynstep if self.vol < float(1) and vol_new > float(1): vol_new = float(1) self.vol = vol_new if self.vol > float(1.5): self.vol = float(1.5) self.update() def vol_down(self): if self.vol is None: return vol_new = self.vol - self.dyn_step.dynstep if self.vol > float(1) and vol_new < float(1): vol_new = float(1) self.vol = vol_new if self.vol < 0: self.vol = float(0) self.update() def set_vol_gui(self): self.last = time.time() if self.progress1 is None: return if self.vol is None: return v = (self.vol / 1.5) * 100 if v > 100: v = 100 self.progress1.setPercent(v if v > 0 else 0.1) self.label.setLabel("{:d} %".format(int(self.vol * 100))) def onAction(self, action): aid = action.getId() buc = action.getButtonCode() & 255 #log("volumegui: key: {} button code: {} time: {:.2f}".format(aid, buc, t - self.last_key)) #OK pressed if aid == 7: self.close() #Cancel if aid in [92, 10]: self.close() self.dyn_step.dynamic_step(buc) if buc == self.key_up or aid in [2, 3, 104]: self.vol_up() self.set_vol_gui() #log("key up") elif buc == self.key_down or aid in [1, 4, 105]: self.vol_down() self.set_vol_gui() #log("key down") else: if self.updown == "up": if self.key_up is None: self.key_up = buc self.vol_up() elif self.key_down is None: self.key_down = buc self.vol_down() elif self.updown == "down": if self.key_down is None: self.key_down = buc self.vol_down() elif self.key_up is None: self.key_up = buc self.vol_up() self.set_vol_gui() self.last = time.time()