From 8af8f93434b2b280adc6b7c0720eadd6252de4ba Mon Sep 17 00:00:00 2001 From: Jakob Ketterl Date: Sat, 15 Jun 2019 19:10:33 +0200 Subject: [PATCH] implement dmr timeslot muting --- csdr.py | 26 +++++++++++++++-------- htdocs/gfx/openwebrx-mute.png | Bin 0 -> 3002 bytes htdocs/openwebrx.css | 27 ++++++++++++++++++++++- htdocs/openwebrx.js | 39 +++++++++++++++++++++++++++------- 4 files changed, 74 insertions(+), 18 deletions(-) create mode 100644 htdocs/gfx/openwebrx-mute.png diff --git a/csdr.py b/csdr.py index b7d1ebd..0ef0250 100755 --- a/csdr.py +++ b/csdr.py @@ -67,7 +67,8 @@ class dsp(object): self.secondary_fft_size = 1024 self.secondary_process_fft = None self.secondary_process_demod = None - self.pipe_names=["bpf_pipe", "shift_pipe", "squelch_pipe", "smeter_pipe", "meta_pipe", "iqtee_pipe", "iqtee2_pipe"] + self.pipe_names=["bpf_pipe", "shift_pipe", "squelch_pipe", "smeter_pipe", "meta_pipe", "iqtee_pipe", + "iqtee2_pipe", "dmr_control_pipe"] self.secondary_pipe_names=["secondary_shift_pipe"] self.secondary_offset_freq = 1000 self.unvoiced_quality = 1 @@ -113,7 +114,7 @@ class dsp(object): else: chain += "rrc_filter | gfsk_demodulator | " if which == "dmr": - chain += "dmr_decoder --fifo {meta_pipe} | mbe_synthesizer -f -u {unvoiced_quality} | " + chain += "dmr_decoder --fifo {meta_pipe} --control-fifo {dmr_control_pipe} | mbe_synthesizer -f -u {unvoiced_quality} | " elif which == "ysf": chain += "ysf_decoder --fifo {meta_pipe} | mbe_synthesizer -y -f -u {unvoiced_quality} | " max_gain = 0.0005 @@ -352,7 +353,7 @@ class dsp(object): actual_squelch = 0 if self.isDigitalVoice() else self.squelch_level if self.running: self.modification_lock.acquire() - self.squelch_pipe_file.write( "%g\n"%(float(actual_squelch)) ) + self.squelch_pipe_file.write("%g\n"%(float(actual_squelch))) self.squelch_pipe_file.flush() self.modification_lock.release() @@ -363,6 +364,11 @@ class dsp(object): def get_unvoiced_quality(self): return self.unvoiced_quality + def set_dmr_filter(self, filter): + if self.dmr_control_pipe_file: + self.dmr_control_pipe_file.write("{0}\n".format(filter)) + self.dmr_control_pipe_file.flush() + def mkfifo(self,path): try: os.unlink(path) @@ -410,7 +416,7 @@ class dsp(object): flowcontrol=int(self.samp_rate*2), start_bufsize=self.base_bufsize*self.decimation, nc_port=self.nc_port, squelch_pipe=self.squelch_pipe, smeter_pipe=self.smeter_pipe, meta_pipe=self.meta_pipe, iqtee_pipe=self.iqtee_pipe, iqtee2_pipe=self.iqtee2_pipe, output_rate = self.get_output_rate(), smeter_report_every = int(self.if_samp_rate()/6000), - unvoiced_quality = self.get_unvoiced_quality()) + unvoiced_quality = self.get_unvoiced_quality(), dmr_control_pipe = self.dmr_control_pipe) logger.debug("[openwebrx-dsp-plugin:csdr] Command = %s", command) my_env=os.environ.copy() @@ -430,13 +436,12 @@ class dsp(object): self.output.add_output("audio", partial(self.process.stdout.read, int(self.get_fft_bytes_to_read()) if self.demodulator == "fft" else 256)) # open control pipes for csdr - if self.bpf_pipe != None: - self.bpf_pipe_file=open(self.bpf_pipe,"w") + if self.bpf_pipe: + self.bpf_pipe_file = open(self.bpf_pipe, "w") if self.shift_pipe: - self.shift_pipe_file=open(self.shift_pipe,"w") + self.shift_pipe_file = open(self.shift_pipe, "w") if self.squelch_pipe: - self.squelch_pipe_file=open(self.squelch_pipe,"w") - + self.squelch_pipe_file = open(self.squelch_pipe, "w") self.start_secondary_demodulator() self.modification_lock.release() @@ -468,6 +473,9 @@ class dsp(object): return raw.rstrip("\n") self.output.add_output("meta", read_meta) + if self.dmr_control_pipe: + self.dmr_control_pipe_file = open(self.dmr_control_pipe, "w") + def stop(self): self.modification_lock.acquire() self.running = False diff --git a/htdocs/gfx/openwebrx-mute.png b/htdocs/gfx/openwebrx-mute.png new file mode 100644 index 0000000000000000000000000000000000000000..23da7bbf190917a5797c682e86742e590d9a9143 GIT binary patch literal 3002 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 Z`p#&uy>eZzBMwv@2(Yj*Z!+~t`7bcFYg_;T literal 0 HcmV?d00001 diff --git a/htdocs/openwebrx.css b/htdocs/openwebrx.css index ac90bc6..3ed6deb 100644 --- a/htdocs/openwebrx.css +++ b/htdocs/openwebrx.css @@ -937,11 +937,32 @@ img.openwebrx-mirror-img background-color: #676767; padding: 2px 0; color: #333; + + text-align: center; + position: relative; +} + +.openwebrx-meta-slot, .openwebrx-meta-slot.muted:before { -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; +} - text-align: center; +.openwebrx-meta-slot.muted:before { + display: block; + content: ""; + background-image: url("gfx/openwebrx-mute.png"); + width:100%; + height:133px; + background-position: center; + background-repeat: no-repeat; + + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + background-color: rgba(0,0,0,.3); } .openwebrx-meta-slot.active { @@ -977,3 +998,7 @@ img.openwebrx-mirror-img .openwebrx-meta-slot.active .openwebrx-meta-user-image.group { background-image: url("gfx/openwebrx-groupcall.png"); } + +.openwebrx-dmr-timeslot-panel * { + cursor: pointer; +} diff --git a/htdocs/openwebrx.js b/htdocs/openwebrx.js index 8a8345b..debd351 100644 --- a/htdocs/openwebrx.js +++ b/htdocs/openwebrx.js @@ -619,7 +619,7 @@ function demodulator_analog_replace(subtype, for_digital) } demodulator_add(new demodulator_default_analog(temp_offset,subtype)); demodulator_buttons_update(); - clear_metadata(); + hide_digitalvoice_panels(); toggle_panel("openwebrx-panel-metadata-" + subtype, true); } @@ -1338,8 +1338,7 @@ function update_metadata(meta) { $(el).find(".openwebrx-dmr-target").text(target); $(el).find(".openwebrx-meta-user-image")[group ? "addClass" : "removeClass"]("group"); } else { - $(".openwebrx-meta-panel .openwebrx-meta-autoclear").text(""); - $(".openwebrx-meta-panel").removeClass("active").removeClass("sync"); + clear_metadata(); } break; case 'YSF': @@ -1365,17 +1364,22 @@ function update_metadata(meta) { break; } else { - $(".openwebrx-meta-panel .openwebrx-meta-autoclear").text(""); - $(".openwebrx-meta-panel").removeClass("active").removeClass("sync"); + clear_metadata(); } } -function clear_metadata() { +function hide_digitalvoice_panels() { $(".openwebrx-meta-panel").each(function(_, p){ toggle_panel(p.id, false); }); - update_metadata({}); + clear_metadata(); +} + +function clear_metadata() { + $(".openwebrx-meta-panel .openwebrx-meta-autoclear").text(""); + $(".openwebrx-meta-slot").removeClass("active").removeClass("sync"); + $(".openwebrx-dmr-timeslot-panel").removeClass("muted"); } function add_problem(what) @@ -2327,7 +2331,7 @@ function openwebrx_init() init_rx_photo(); open_websocket(); secondary_demod_init(); - clear_metadata(); + digimodes_init(); place_panels(first_show_panel); window.setTimeout(function(){window.setInterval(debug_audio,1000);},1000); window.addEventListener("resize",openwebrx_resize); @@ -2338,6 +2342,25 @@ function openwebrx_init() } +function digimodes_init() { + hide_digitalvoice_panels(); + + // initialze DMR timeslot muting + $('.openwebrx-dmr-timeslot-panel').click(function(e) { + $(e.currentTarget).toggleClass("muted"); + update_dmr_timeslot_filtering(); + }); +} + +function update_dmr_timeslot_filtering() { + var filter = $('.openwebrx-dmr-timeslot-panel').map(function(index, el){ + return (!$(el).hasClass("muted")) << index; + }).toArray().reduce(function(acc, v){ + return acc | v; + }, 0); + webrx_set_param("dmr_filter", filter); +} + function iosPlayButtonClick() { //On iOS, we can only start audio from a click or touch event.