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 0000000..23da7bb Binary files /dev/null and b/htdocs/gfx/openwebrx-mute.png differ 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.