From 42408d861937e50a430304c9a720d2ec0f60fd55 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Sun, 13 Feb 2022 09:40:35 -0500 Subject: [PATCH 01/38] Trying to remove overlap --- lib/gr_blocks/nonstop_wavfile_sink_impl.cc | 46 +++++++---- trunk-recorder/call.cc | 21 ++++- trunk-recorder/call.h | 2 + trunk-recorder/main.cc | 89 ++++++++++++++++++++-- 4 files changed, 133 insertions(+), 25 deletions(-) diff --git a/lib/gr_blocks/nonstop_wavfile_sink_impl.cc b/lib/gr_blocks/nonstop_wavfile_sink_impl.cc index fec116d1f..ceae206c2 100644 --- a/lib/gr_blocks/nonstop_wavfile_sink_impl.cc +++ b/lib/gr_blocks/nonstop_wavfile_sink_impl.cc @@ -140,7 +140,7 @@ bool nonstop_wavfile_sink_impl::start_recording(Call *call) { char formattedTalkgroup[62]; snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tStarting wavfile sink "; + BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tStarting wavfile sink SRC ID: " << curr_src_id; return true; } @@ -219,16 +219,17 @@ void nonstop_wavfile_sink_impl::set_source(long src) { BOOST_LOG_TRIVIAL(error) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tUnit ID externally set, ext: "<< src << "\tcurrent: " << curr_src_id << "\t samples: " << d_sample_count; - if (d_sample_count > 0) { + /*if (d_sample_count > 0) { end_transmission(); - } - - if (!record_more_transmissions) { + }*/ + BOOST_LOG_TRIVIAL(info) << "ENDING TRANSMISSION Voice Channel mismatch source id - current: "<< curr_src_id << " new: " << src; + //state = STOPPED; + /*if (!record_more_transmissions) { state = STOPPED; } else { state = IDLE; d_first_work = true; - } + }*/ } curr_src_id = src; } @@ -254,6 +255,7 @@ void nonstop_wavfile_sink_impl::end_transmission() { this->add_transmission(transmission); d_sample_count = 0; d_first_work = true; + curr_src_id = -1; } else { BOOST_LOG_TRIVIAL(error) << "Trying to end a Transmission, but the sample_count is 0" << std::endl; } @@ -347,25 +349,29 @@ int nonstop_wavfile_sink_impl::work(int noutput_items, gr_vector_const_void_star } else if (src_id != curr_src_id) { if (state == RECORDING) { - if (d_sample_count > 0) { + + BOOST_LOG_TRIVIAL(info) << "ENDING TRANSMISSION from TAGS Voice Channel mismatch source id - current: "<< curr_src_id << " new: " << src_id << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); + /*if (d_sample_count > 0) { end_transmission(); } - - if (!record_more_transmissions) { + state = STOPPED;*/ + /*if (!record_more_transmissions) { state = STOPPED; } else { state = IDLE; d_first_work = true; - } + }*/ + curr_src_id = src_id; } - BOOST_LOG_TRIVIAL(info) << "Updated Voice Channel source id: " << src_id << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); + //BOOST_LOG_TRIVIAL(info) << "Updated Voice Channel source id: " << src_id << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); - curr_src_id = src_id; + } } if (pmt::eq(that_key, tags[i].key)) { d_termination_flag = true; + BOOST_LOG_TRIVIAL(info) << "TEMINATOR!!"; } } tags.clear(); @@ -390,6 +396,13 @@ void nonstop_wavfile_sink_impl::add_transmission(Transmission t) { } void nonstop_wavfile_sink_impl::set_record_more_transmissions(bool more) { + // If a Recorder is STOPPED and record_more is false, prep it so it is ready to go. + if ((record_more_transmissions == false) && (more == true) && (state == STOPPED)) { + BOOST_LOG_TRIVIAL(info) << "wav - setting record_more to true, sample count: " << d_sample_count; + d_sample_count = 0; + d_first_work = true; + state = IDLE; + } record_more_transmissions = more; } @@ -420,13 +433,15 @@ int nonstop_wavfile_sink_impl::dowork(int noutput_items, gr_vector_const_void_st if (d_sample_count > 0) { end_transmission(); } - if (!record_more_transmissions) { + + // Another GRANT message has not arrived. + if (record_more_transmissions == false) { char formattedTalkgroup[62]; snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\trecord_more_transmissions is false, setting recorder state to STOPPED"; - BOOST_LOG_TRIVIAL(trace) << "Call completed - putting recorder into state Completed - we had samples"; + BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\trecord_more_transmissions is false, setting recorder state to STOPPED"; + //BOOST_LOG_TRIVIAL(trace) << "Call completed - putting recorder into state Completed - we had samples"; state = STOPPED; } else { @@ -495,6 +510,7 @@ int nonstop_wavfile_sink_impl::dowork(int noutput_items, gr_vector_const_void_st } if (nwritten > 0) { + record_more_transmissions = false; state = RECORDING; } // fflush (d_fp); // this is added so unbuffered content is written. diff --git a/trunk-recorder/call.cc b/trunk-recorder/call.cc index 2b526087b..36a5bf7cb 100644 --- a/trunk-recorder/call.cc +++ b/trunk-recorder/call.cc @@ -78,6 +78,24 @@ Call::~Call() { void Call::restart_call() { } +void Call::set_record_more_transmissions(bool more) { + if (this->get_recorder() != NULL) { + this->get_recorder()->set_record_more_transmissions(more); + } +} + +void Call::inactive_call() { + if (this->get_recorder() != NULL) { + // If the call is being recorded, check to see if the recorder is currently in an INACTIVE state. This means that the recorder is not + // doing anything and can be stopped. + if ((state == RECORDING) && this->get_recorder()->is_idle()) { + BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\t\033[0;34m" << this->get_call_num() << "C\033[0m\tTG: " << this->get_talkgroup_display() << "\tFreq: " << format_freq(get_freq()) << "\tStopping Recorded Call, setting call state to INACTIVE - Last Update: " << this->since_last_update() << "s"; + this->set_state(INACTIVE); + } + this->get_recorder()->set_record_more_transmissions(false); + } +} + void Call::stop_call() { if (this->get_recorder() != NULL) { @@ -87,10 +105,9 @@ void Call::stop_call() { BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\t\033[0;34m" << this->get_call_num() << "C\033[0m\tTG: " << this->get_talkgroup_display() << "\tFreq: " << format_freq(get_freq()) << "\tStopping Recorded Call, setting call state to COMPLETED - Last Update: " << this->since_last_update() << "s"; this->set_state(COMPLETED); } else { - BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\t\033[0;34m" << this->get_call_num() << "C\033[0m\tTG: " << this->get_talkgroup_display() << "\tFreq: " << format_freq(get_freq()) << "\tStopping Recorded Call, setting call state to INACTIVE - Last Update: " << this->since_last_update() << "s"; + BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\t\033[0;34m" << this->get_call_num() << "C\033[0m\tTG: " << this->get_talkgroup_display() << "\tFreq: " << format_freq(get_freq()) << "\tTrying to COMPLETE, Recorder still active, setting call state to INACTIVE - Last Update: " << this->since_last_update() << "s"; this->set_state(INACTIVE); } - this->get_recorder()->set_record_more_transmissions(false); } } long Call::get_call_num() { diff --git a/trunk-recorder/call.h b/trunk-recorder/call.h index 64ca88554..beba3a5b8 100644 --- a/trunk-recorder/call.h +++ b/trunk-recorder/call.h @@ -29,6 +29,8 @@ class Call { long get_call_num(); virtual ~Call(); virtual void restart_call(); + void set_record_more_transmissions(bool more); + void inactive_call(); void stop_call(); void conclude_call(); void set_sigmf_recorder(Recorder *r); diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index 14a62ab37..8d8b9339a 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -625,7 +625,7 @@ bool start_recorder(Call *call, TrunkMessage message, System *sys) { if (!talkgroup && (sys->get_record_unknown() == false)) { if (sys->get_hideUnknown() == false) { - BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[33mNot Recording: TG not in Talkgroup File\u001b[0m "; + //BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[33mNot Recording: TG not in Talkgroup File\u001b[0m "; } return false; } @@ -638,7 +638,7 @@ bool start_recorder(Call *call, TrunkMessage message, System *sys) { if (call->get_encrypted() == true || (talkgroup && (talkgroup->mode.compare("E") == 0 || talkgroup->mode.compare("TE") == 0 || talkgroup->mode.compare("DE") == 0 ))) { if (sys->get_hideEncrypted() == false) { - BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[31mNot Recording: ENCRYPTED\u001b[0m "; + //BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[31mNot Recording: ENCRYPTED\u001b[0m "; } return false; } @@ -733,7 +733,7 @@ bool start_recorder(Call *call, TrunkMessage message, System *sys) { } if (!source_found) { - BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36mNot Recording: no source covering Freq\u001b[0m"; + //BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36mNot Recording: no source covering Freq\u001b[0m"; return false; } return false; @@ -834,7 +834,7 @@ void manage_calls() { } // Handle Trunked Calls - if ((call->since_last_update() > config.call_timeout) && ((state == RECORDING) || (state == MONITORING))) { + if ((call->since_last_update() > 1.0/*config.call_timeout*/) && ((state == RECORDING) || (state == MONITORING))) { if (state == RECORDING) { ended_call = true; @@ -851,6 +851,8 @@ void manage_calls() { } } + + // If a call's state has been set to COMPLETED, we can conclude the call and delete it // we need to check the Call State again because it could have been updated by the previous command. if (call->get_state() == COMPLETED) { @@ -868,7 +870,7 @@ void manage_calls() { continue; } - // We are checking to make sure a Call has gotten stuck. If it is in the INACTIVE state + // We are checking to make sure a Call hasn't gotten stuck. If it is in the INACTIVE state if (state == INACTIVE) { Recorder *recorder = call->get_recorder(); if (recorder != NULL) { @@ -949,7 +951,8 @@ void unit_group_affiliation(System *sys, long source_id, long talkgroup_num) { plugman_unit_group_affiliation(sys, source_id, talkgroup_num); } -void handle_call(TrunkMessage message, System *sys) { + +void handle_call_grant(TrunkMessage message, System *sys) { bool call_found = false; bool call_retune = false; bool recording_started = false; @@ -962,16 +965,27 @@ void handle_call(TrunkMessage message, System *sys) { going until it gets a termination flag. */ + BOOST_LOG_TRIVIAL(info) << "TG: " << message.talkgroup << " sys num: "<< message.sys_num << " freq: " << message.freq << " TDMA Slot" << message.tdma_slot << " TDMA: " << message.phase2_tdma; + for (vector::iterator it = calls.begin(); it != calls.end(); ++it) { Call *call = *it; - if ((call->get_state() != RECORDING) && (call->get_state() != MONITORING)) { + /* This will skip all calls that are not currently acitve */ + if (call->get_state() == COMPLETED) { continue; } //BOOST_LOG_TRIVIAL(info) << "TG: " << call->get_talkgroup() << " | " << message.talkgroup << " sys num: " << call->get_sys_num() << " | " << message.sys_num << " freq: " << call->get_freq() << " | " << message.freq << " TDMA Slot" << call->get_tdma_slot() << " | " << message.tdma_slot << " TDMA: " << call->get_phase2_tdma() << " | " << message.phase2_tdma; if ((call->get_talkgroup() == message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { call_found = true; + + if (call->get_state() == RECORDING) { + call->set_record_more_transmissions(true); + } + if (call->get_state() == INACTIVE) { + call->set_record_more_transmissions(true); + call->set_state(RECORDING); + } bool source_updated = call->update(message); if (source_updated) { plugman_call_start(call); @@ -981,6 +995,15 @@ void handle_call(TrunkMessage message, System *sys) { // There is an existing call on freq and slot that the new call will be started on. We should stop the older call. The older recorder will // keep writing to the file until it hits a termination flag, so no packets should be dropped. if ((call->get_state() == RECORDING) && (call->get_talkgroup() != message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { + BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Stopping RECORDING call, RX overlapping TG message Freq " << message.talkgroup << "\u001b[0m"; + BOOST_LOG_TRIVIAL(info) << "\t - Stopping call because of overlapping Freq"; + call->stop_call(); + } + + // There is an existing call on freq and slot that the new call will be started on. We should stop the older call. The older recorder will + // keep writing to the file until it hits a termination flag, so no packets should be dropped. + if ((call->get_state() == INACTIVE) && (call->get_talkgroup() != message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { + BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Stopping INACTIVE call, RX overlapping TG message Freq " << message.talkgroup << "\u001b[0m"; BOOST_LOG_TRIVIAL(info) << "\t - Stopping call because of overlapping Freq"; call->stop_call(); } @@ -997,14 +1020,64 @@ void handle_call(TrunkMessage message, System *sys) { } + +void handle_call_update(TrunkMessage message, System *sys) { + bool call_found = false; + bool call_retune = false; + bool recording_started = false; + + /* Notes: it is possible for 2 Calls to exist for the same talkgroup on different freq. This happens when a Talkgroup starts on a freq + that current recorder can't retune to. In this case, the current orig Talkgroup reocrder will keep going on the old freq, while a new + recorder is start on a source that can cover that freq. This makes sure any of the remaining transmission that it is in the buffer + of the original recorder gets flushed. + UPDATED: however if we have 2 different talkgroups on the same freq we should do a stop_call on the original call since it is being used by another TG now. This will let the recorder keep + going until it gets a termination flag. + */ + + for (vector::iterator it = calls.begin(); it != calls.end(); ++it) { + Call *call = *it; + + /* This will skip all calls that are not currently acitve */ + if (call->get_state() == COMPLETED) { + continue; + } + + //BOOST_LOG_TRIVIAL(info) << "TG: " << call->get_talkgroup() << " | " << message.talkgroup << " sys num: " << call->get_sys_num() << " | " << message.sys_num << " freq: " << call->get_freq() << " | " << message.freq << " TDMA Slot" << call->get_tdma_slot() << " | " << message.tdma_slot << " TDMA: " << call->get_phase2_tdma() << " | " << message.phase2_tdma; + if ((call->get_talkgroup() == message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { + call_found = true; + + if (call->get_state() == INACTIVE) { + // Only a RECORDING call can be set to INACTIVE + // We should be safe to set it to RECORDING if it starts to get UPDATE messages + call->set_state(RECORDING) + BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Werid - update for an INACTIVE Call \u001b[0m"; + } + BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Updating Call \u001b[0m"; + + bool source_updated = call->update(message); + if (source_updated) { + plugman_call_start(call); + } + } + } + + if (!call_found) { + //BOOST_LOG_TRIVIAL(error) << "Weird - call not found for UPDATE\tFreq: " << format_freq(message.freq) << "\tTG:" << message.freq; + } + +} + void handle_message(std::vector messages, System *sys) { for (std::vector::iterator it = messages.begin(); it != messages.end(); it++) { TrunkMessage message = *it; switch (message.message_type) { case GRANT: + handle_call_grant(message, sys); + break; + case UPDATE: - handle_call(message, sys); + handle_call_update(message, sys); break; case CONTROL_CHANNEL: From 7ac11d996854605fd3083ce8e038333b5cd06bd3 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Sun, 13 Feb 2022 21:35:40 -0500 Subject: [PATCH 02/38] Switch some names --- CMakeLists.txt | 2 +- docs/notes/STATES.md | 4 +- lib/gr_blocks/transmission_sink.cc | 558 ++++++++++++++++++ lib/gr_blocks/transmission_sink.h | 154 +++++ trunk-recorder/main.cc | 2 +- trunk-recorder/recorders/analog_recorder.cc | 4 +- trunk-recorder/recorders/analog_recorder.h | 4 +- trunk-recorder/recorders/debug_recorder.h | 2 +- trunk-recorder/recorders/dmr_recorder.cc | 4 +- trunk-recorder/recorders/dmr_recorder.h | 6 +- trunk-recorder/recorders/p25_recorder.h | 2 +- .../recorders/p25_recorder_decode.cc | 2 +- .../recorders/p25_recorder_decode.h | 5 +- .../recorders/p25_recorder_fsk4_demod.cc | 2 +- trunk-recorder/recorders/recorder.h | 2 +- trunk-recorder/recorders/sigmf_recorder.cc | 5 +- trunk-recorder/recorders/sigmf_recorder.h | 2 - 17 files changed, 734 insertions(+), 26 deletions(-) create mode 100644 lib/gr_blocks/transmission_sink.cc create mode 100644 lib/gr_blocks/transmission_sink.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ac264449e..f2989a5b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -246,7 +246,7 @@ list(APPEND trunk_recorder_sources lib/lfsr/lfsr.cxx lib/gr_blocks/freq_xlating_fft_filter.cc - lib/gr_blocks/nonstop_wavfile_sink_impl.cc + lib/gr_blocks/transmission_sink.cc lib/gr_blocks/decoders/fsync_decode.cc lib/gr_blocks/decoders/mdc_decode.cc lib/gr_blocks/decoders/star_decode.cc diff --git a/docs/notes/STATES.md b/docs/notes/STATES.md index 9c519b0fa..181c22ac7 100644 --- a/docs/notes/STATES.md +++ b/docs/notes/STATES.md @@ -25,13 +25,13 @@ If there is an existing Call that covers all of this, then it will simply be upd If not, a new Call is created and an attempt to start a recording is made by calling **start_recorder()**. **start_recorder()** first checks to see if a talkgroup entry is defined in the *talkgroup.csv* file for the talkgroup number in the message. If the **recordUnknown** flag is set to false in the *config.json* and a talkgroup entry is not found, then a recording will not be started. Encrypted transmissions are not recorded. If a talkgroup entry does exist and the talkgroup is marked as encrypted, it will be skipped. The same is true if the message's encrypted flag is set. -After these checks, **start_recorder()** will now try to assign a recorder. It does this by going through the Sources and finding the first one that covers the frequency in the message. The function will then try to get either an analog or digital recorder from the Source by calling **get_analog_recorder()** or **get_digital_recorder()**, respectively. The **get_analog_recorder()** and **get_digital_recorder()** functions in *source.cc* simply go through the vector of Recorders that were created for that Source and checking their state. The first recorder with the state of **available** is returned. For both types of recorders, their state actually comes from nonstop_wavefile_sink block that is at the end of the recorders gnuradio graph. We will dive into that lifecycle later. The nonstop_wavefile_sink block that part of the recorder, will receive some information about the call and will set its state to **idle** +After these checks, **start_recorder()** will now try to assign a recorder. It does this by going through the Sources and finding the first one that covers the frequency in the message. The function will then try to get either an analog or digital recorder from the Source by calling **get_analog_recorder()** or **get_digital_recorder()**, respectively. The **get_analog_recorder()** and **get_digital_recorder()** functions in *source.cc* simply go through the vector of Recorders that were created for that Source and checking their state. The first recorder with the state of **available** is returned. For both types of recorders, their state actually comes from transmission_sink block that is at the end of the recorders gnuradio graph. We will dive into that lifecycle later. The transmission_sink block that part of the recorder, will receive some information about the call and will set its state to **idle** Back in *main.cc*, if a recorder was return, it is associated with the call and the call's state is set to **recording**. If it wasn't possible to get a recorder, the call's state is set to **monitoring**. This serves to track that the Talkgroup will be on that frequency and that Trunk Recorder does not have to try and assign a recorder everytime it gets an **UPDATE** trunking message. When a **GRANT** or **UPDATE** message comes in and goes through **handle_call()**, the function will see that a call has already been assigned and will call that call's **update()** function. This function simply sets the call's *last_update* variable to the current time. -As voice samples make their way through the recorder, they eventually end up in the **nonstop_wav_file_sink_impl.cc** block. When a wav_sink and its recorder are first associated with a call, its state is initially set to **idle**. When in **idle** and a voice sample comes in, the wav_sink will change its state to **recording**, open a new file and being writing samples to it. The wav_sink starts a *Transmission* which tracks each of the indivdiual transmissions that make up a call on a digital system. The variable *d_stop_time* is also updated with the current time. This is used in analog systems to determine is there has been a break in writing to the file, signaling a new file should be started. +As voice samples make their way through the recorder, they eventually end up in the **transmission_sink.cc** block. When a wav_sink and its recorder are first associated with a call, its state is initially set to **idle**. When in **idle** and a voice sample comes in, the wav_sink will change its state to **recording**, open a new file and being writing samples to it. The wav_sink starts a *Transmission* which tracks each of the indivdiual transmissions that make up a call on a digital system. The variable *d_stop_time* is also updated with the current time. This is used in analog systems to determine is there has been a break in writing to the file, signaling a new file should be started. In digital system, a Terminator Data Unit (TDU) is sent on the voice channel at the start and end of the call. The digital recorder processes this and passes it along to the wav_sink. When the wav_sink is in the state **recording**, signifying it has written samples to a file, and it receieves a TDU it will end the current transmission. The wav_sink has an internal flag called *record_more_transmissions*. If this flag is set to *false* the wav_sink's state will be set to **stopped**, otherwise it will be set to **idle**. When a wav_sink is in state **stopped**, any voice samples that come in will be dropped and not written to a file, and new Transmission will not be created. However, when the state is **idle**, it will operate like it was just created. diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc new file mode 100644 index 000000000..0cabec678 --- /dev/null +++ b/lib/gr_blocks/transmission_sink.cc @@ -0,0 +1,558 @@ +/* -*- c++ -*- */ + +/* + * Copyright 2004,2006-2011,2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#include "transmission_sink.h" +#include "../../trunk-recorder/call.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// win32 (mingw/msvc) specific +#ifdef HAVE_IO_H +#include +#endif // ifdef HAVE_IO_H +#ifdef O_BINARY +#define OUR_O_BINARY O_BINARY +#else // ifdef O_BINARY +#define OUR_O_BINARY 0 +#endif // ifdef O_BINARY + +// should be handled via configure +#ifdef O_LARGEFILE +#define OUR_O_LARGEFILE O_LARGEFILE +#else // ifdef O_LARGEFILE +#define OUR_O_LARGEFILE 0 +#endif // ifdef O_LARGEFILE + +namespace gr { +namespace blocks { +transmission_sink::sptr +transmission_sink::make(int n_channels, unsigned int sample_rate, int bits_per_sample) { + return gnuradio::get_initial_sptr(new transmission_sink(n_channels, sample_rate, bits_per_sample)); +} + +transmission_sink::transmission_sink( + int n_channels, + unsigned int sample_rate, + int bits_per_sample) + : sync_block("transmission_sink", + io_signature::make(1, n_channels, sizeof(int16_t)), + io_signature::make(0, 0, 0)), + d_sample_rate(sample_rate), d_nchans(n_channels), + d_fp(0), d_current_call(NULL) { + if ((bits_per_sample != 8) && (bits_per_sample != 16)) { + throw std::runtime_error("Invalid bits per sample (supports 8 and 16)"); + } + d_bytes_per_sample = bits_per_sample / 8; + d_sample_count = 0; + d_slot = -1; + d_first_work = true; + d_termination_flag = false; + state = AVAILABLE; +} + +//static int rec_counter=0; +void transmission_sink::create_base_filename() { + time_t work_start_time = d_start_time; + std::stringstream path_stream; + tm *ltm = localtime(&work_start_time); + // Found some good advice on Streams and Strings here: https://blog.sensecodons.com/2013/04/dont-let-stdstringstreamstrcstr-happen.html + path_stream << d_current_call_capture_dir << "/" << d_current_call_short_name << "/" << 1900 + ltm->tm_year << "/" << 1 + ltm->tm_mon << "/" << ltm->tm_mday; + std::string path_string = path_stream.str(); + boost::filesystem::create_directories(path_string); + + int nchars; + + if (d_slot == -1) { + nchars = snprintf(current_base_filename, 255, "%s/%ld-%ld_%.0f", path_string.c_str(), d_current_call_talkgroup, work_start_time, d_current_call_freq); + } else { + // this is for the case when it is a DMR recorder and 2 wav files are created, the slot is needed to keep them separate. + nchars = snprintf(current_base_filename, 255, "%s/%ld-%ld_%.0f.%d", path_string.c_str(), d_current_call_talkgroup, work_start_time, d_current_call_freq,d_slot); + } + if (nchars >= 255) { + BOOST_LOG_TRIVIAL(error) << "Call: Path longer than 255 charecters"; + } +} + +char *transmission_sink::get_filename() { + return current_filename; +} + +bool transmission_sink::start_recording(Call *call, int slot) { + this->d_slot = slot; + this->start_recording(call); + return true; +} + +bool transmission_sink::start_recording(Call *call) { + gr::thread::scoped_lock guard(d_mutex); + if (d_current_call && d_fp) { + BOOST_LOG_TRIVIAL(trace) << "Start() - Current_Call & fp are not null! current_filename is: " << current_filename << " Length: " << d_sample_count << std::endl; + } + d_current_call = call; + d_current_call_num = call->get_call_num(); + d_current_call_recorder_num = 0; //call->get_recorder()->get_num(); + d_current_call_freq = call->get_freq(); + d_current_call_talkgroup = call->get_talkgroup(); + d_current_call_short_name = call->get_short_name(); + d_current_call_capture_dir = call->get_capture_dir(); + d_prior_transmission_length = 0; + record_more_transmissions = true; + + this->clear_transmission_list(); + d_conventional = call->is_conventional(); + curr_src_id = d_current_call->get_current_source_id(); + d_sample_count = 0; + d_first_work = true; + + // when a wav_sink first gets associated with a call, set its lifecycle to idle; + state = IDLE; + /* Should reset more variables here */ + + char formattedTalkgroup[62]; + snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); + std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); + BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tStarting wavfile sink SRC ID: " << curr_src_id; + + return true; +} + +bool transmission_sink::open_internal(const char *filename) { + int d_first_sample_pos; + unsigned d_samples_per_chan; + + // we use the open system call to get access to the O_LARGEFILE flag. + // O_APPEND| + int fd; + + if ((fd = ::open(filename, + O_RDWR | O_CREAT | OUR_O_LARGEFILE | OUR_O_BINARY, + 0664)) < 0) { + perror(filename); + BOOST_LOG_TRIVIAL(error) << "wav error opening: " << filename << std::endl; + return false; + } + + if (d_fp) { // if we've already got a new one open, close it + BOOST_LOG_TRIVIAL(trace) << "File pointer already open, closing " << d_fp << " more" << current_filename << " for " << filename << std::endl; + + // fclose(d_fp); + // d_fp = NULL; + } + + if (strlen(filename) >= 255) { + BOOST_LOG_TRIVIAL(error) << "transmission_sink: Error! filename longer than 255"; + } + + if ((d_fp = fdopen(fd, "rb+")) == NULL) { + perror(filename); + ::close(fd); // don't leak file descriptor if fdopen fails. + BOOST_LOG_TRIVIAL(error) << "wav open failed" << std::endl; + return false; + } + + d_sample_count = 0; + d_first_work = true; + + if (!wavheader_write(d_fp, d_sample_rate, d_nchans, d_bytes_per_sample)) { + fprintf(stderr, "[%s] could not write to WAV file\n", __FILE__); + return false; + } + + if (d_bytes_per_sample == 1) { + d_max_sample_val = UCHAR_MAX; + d_min_sample_val = 0; + d_normalize_fac = d_max_sample_val / 2; + d_normalize_shift = 1; + } else if (d_bytes_per_sample == 2) { + d_max_sample_val = SHRT_MAX; + d_min_sample_val = SHRT_MIN; + d_normalize_fac = d_max_sample_val; + d_normalize_shift = 0; + } + + return true; +} + +void transmission_sink::set_source(long src) { + gr::thread::scoped_lock guard(d_mutex); + + char formattedTalkgroup[62]; + snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); + std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); + + if (curr_src_id == -1) { + + BOOST_LOG_TRIVIAL(error) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tUnit ID externally set, ext: "<< src << "\tcurrent: " << curr_src_id << "\t samples: " << d_sample_count; + + curr_src_id = src; + } else if (src != curr_src_id) { + if (state == RECORDING) { + + BOOST_LOG_TRIVIAL(error) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tUnit ID externally set, ext: "<< src << "\tcurrent: " << curr_src_id << "\t samples: " << d_sample_count; + + /*if (d_sample_count > 0) { + end_transmission(); + }*/ + BOOST_LOG_TRIVIAL(info) << "ENDING TRANSMISSION Voice Channel mismatch source id - current: "<< curr_src_id << " new: " << src; + //state = STOPPED; + /*if (!record_more_transmissions) { + state = STOPPED; + } else { + state = IDLE; + d_first_work = true; + }*/ + } + curr_src_id = src; + } +} + +void transmission_sink::end_transmission() { + if (d_sample_count > 0) { + if (d_fp) { + close_wav(false); + } else { + BOOST_LOG_TRIVIAL(error) << "Ending transmission, sample_count is greater than 0 but d_fp is null" << std::endl; + } + // if an Transmission has ended, send it to Call. + Transmission transmission; + transmission.source = curr_src_id; // Source ID for the Call + transmission.start_time = d_start_time; // Start time of the Call + transmission.stop_time = d_stop_time; // when the Call eneded + transmission.sample_count = d_sample_count; + transmission.length = length_in_seconds(); // length in seconds + d_prior_transmission_length = d_prior_transmission_length + transmission.length; + strcpy(transmission.filename, current_filename); // Copy the filename + strcpy(transmission.base_filename, current_base_filename); + this->add_transmission(transmission); + d_sample_count = 0; + d_first_work = true; + curr_src_id = -1; + } else { + BOOST_LOG_TRIVIAL(error) << "Trying to end a Transmission, but the sample_count is 0" << std::endl; + } +} + +void transmission_sink::stop_recording() { + gr::thread::scoped_lock guard(d_mutex); + + if (d_sample_count > 0) { + end_transmission(); + } + + if (state == RECORDING) { + BOOST_LOG_TRIVIAL(error) << "stop_recording() - stopping wavfile sink but recorder state is: " << state << std::endl; + } + d_current_call = NULL; + d_first_work = true; + d_termination_flag = false; + state = AVAILABLE; +} + +void transmission_sink::close_wav(bool close_call) { + unsigned int byte_count = d_sample_count * d_bytes_per_sample; + wavheader_complete(d_fp, byte_count); + fclose(d_fp); + d_fp = NULL; +} + +transmission_sink::~transmission_sink() { + stop_recording(); +} + +bool transmission_sink::stop() { + return true; +} + +State transmission_sink::get_state() { + return this->state; +} + +int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { + + gr::thread::scoped_lock guard(d_mutex); // hold mutex for duration of this + + // it is possible that we could get part of a transmission after a call has stopped. We shouldn't do any recording if this happens.... this could mean that we miss part of the recording though + if (!d_current_call) { + time_t now = time(NULL); + double its_been = difftime(now, d_stop_time); + char formattedTalkgroup[62]; + snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); + std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); + BOOST_LOG_TRIVIAL(error) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tDropping samples - current_call is null\t Rec State: " << format_state(this->state) << "\tSince close: " << its_been; + + return noutput_items; + } + + // it is possible that we could get part of a transmission after a call has stopped. We shouldn't do any recording if this happens.... this could mean that we miss part of the recording though + if ((state == STOPPED) || (state == AVAILABLE)) { + if (noutput_items > 1) { + time_t now = time(NULL); + double its_been = difftime(now, d_stop_time); + char formattedTalkgroup[62]; + snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); + std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); + BOOST_LOG_TRIVIAL(error) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tDropping samples - Recorder state is: " << format_state(this->state); + + //BOOST_LOG_TRIVIAL(info) << "WAV - state is: " << format_state(this->state) << "\t Dropping samples: " << noutput_items << " Since close: " << its_been << std::endl; + } + return noutput_items; + } + + std::vector tags; + pmt::pmt_t this_key(pmt::intern("src_id")); + pmt::pmt_t that_key(pmt::intern("terminate")); + //pmt::pmt_t squelch_key(pmt::intern("squelch_eob")); + get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0) + noutput_items); + + unsigned pos = 0; + //long curr_src_id = 0; + + for (unsigned int i = 0; i < tags.size(); i++) { + //BOOST_LOG_TRIVIAL(info) << "TAG! " << tags[i].key; + if (pmt::eq(this_key, tags[i].key)) { + long src_id = pmt::to_long(tags[i].value); + pos = d_sample_count + (tags[i].offset - nitems_read(0)); + + if (curr_src_id == -1) { + BOOST_LOG_TRIVIAL(info) << "Updated Voice Channel source id: " << src_id << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); + + curr_src_id = src_id; + } else if (src_id != curr_src_id) { + if (state == RECORDING) { + + + BOOST_LOG_TRIVIAL(info) << "ENDING TRANSMISSION from TAGS Voice Channel mismatch source id - current: "<< curr_src_id << " new: " << src_id << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); + /*if (d_sample_count > 0) { + end_transmission(); + } + state = STOPPED;*/ + /*if (!record_more_transmissions) { + state = STOPPED; + } else { + state = IDLE; + d_first_work = true; + }*/ + curr_src_id = src_id; + } + //BOOST_LOG_TRIVIAL(info) << "Updated Voice Channel source id: " << src_id << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); + + + } + + } + if (pmt::eq(that_key, tags[i].key)) { + d_termination_flag = true; + BOOST_LOG_TRIVIAL(info) << "TEMINATOR!!"; + } + } + tags.clear(); + + // if the System for this call is in Transmission Mode, and we have a recording and we got a flag that a Transmission ended... + int nwritten = dowork(noutput_items, input_items, output_items); + d_stop_time = time(NULL); + + return nwritten; +} + +time_t transmission_sink::get_start_time() { + return d_start_time; +} + +time_t transmission_sink::get_stop_time() { + return d_stop_time; +} + +void transmission_sink::add_transmission(Transmission t) { + transmission_list.push_back(t); +} + +void transmission_sink::set_record_more_transmissions(bool more) { + // If a Recorder is STOPPED and record_more is false, prep it so it is ready to go. + if ((record_more_transmissions == false) && (more == true) && (state == STOPPED)) { + BOOST_LOG_TRIVIAL(info) << "wav - setting record_more to true, sample count: " << d_sample_count; + d_sample_count = 0; + d_first_work = true; + state = IDLE; + } + record_more_transmissions = more; +} + +void transmission_sink::clear_transmission_list() { + transmission_list.clear(); + transmission_list.shrink_to_fit(); +} + +std::vector transmission_sink::get_transmission_list() { + return transmission_list; +} + +int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { + // block + int n_in_chans = input_items.size(); + short int sample_buf_s; + int nwritten; + + + if (d_termination_flag) { + + if (d_current_call == NULL) { + BOOST_LOG_TRIVIAL(error) << "wav - no current call in temination loop"; + state = STOPPED; + return noutput_items; + } + + if (d_sample_count > 0) { + end_transmission(); + } + + // Another GRANT message has not arrived. + if (record_more_transmissions == false) { + char formattedTalkgroup[62]; + snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); + std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); + + BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\trecord_more_transmissions is false, setting recorder state to STOPPED"; + //BOOST_LOG_TRIVIAL(trace) << "Call completed - putting recorder into state Completed - we had samples"; + + state = STOPPED; + } else { + state = IDLE; + d_first_work = true; + } + d_termination_flag = false; + + return noutput_items; + } + + if (d_first_work) { + if (d_fp) { + // if we are already recording a file for this call, close it before starting a new one. + BOOST_LOG_TRIVIAL(info) << "WAV - Weird! we have an existing FP, but d_first_work was true: " << current_filename << std::endl; + + close_wav(false); + } + + time_t current_time = time(NULL); + if (current_time == d_start_time) { + d_start_time = current_time + 1; + } else { + d_start_time = current_time; + } + + // create a new filename, based on the current time and source. + create_base_filename(); + strcpy(current_filename, current_base_filename); + strcat(current_filename, ".wav"); + if (!open_internal(current_filename)) { + BOOST_LOG_TRIVIAL(error) << "can't open file"; + return noutput_items; + } + char formattedTalkgroup[62]; + snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); + std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); + BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tStarting new Transmission \tSrc ID: " << curr_src_id; + + //curr_src_id = d_current_call->get_current_source_id(); + + d_first_work = false; + } + + if (!d_fp) // drop output on the floor + { + BOOST_LOG_TRIVIAL(error) << "Wav - Dropping items, no fp or Current Call: " << noutput_items << " Filename: " << current_filename << " Current sample count: " << d_sample_count << std::endl; + return noutput_items; + } + + for (nwritten = 0; nwritten < noutput_items; nwritten++) { + for (int chan = 0; chan < d_nchans; chan++) { + // Write zeros to channels which are in the WAV file + // but don't have any inputs here + if (chan < n_in_chans) { + int16_t **in = (int16_t **)&input_items[0]; + sample_buf_s = in[chan][nwritten]; + } else { + sample_buf_s = 0; + } + + wav_write_sample(d_fp, sample_buf_s, d_bytes_per_sample); + + d_sample_count++; + } + } + + if (nwritten > 0) { + record_more_transmissions = false; + state = RECORDING; + } + // fflush (d_fp); // this is added so unbuffered content is written. + return nwritten; +} + +void transmission_sink::set_bits_per_sample(int bits_per_sample) { + gr::thread::scoped_lock guard(d_mutex); + + if ((bits_per_sample == 8) || (bits_per_sample == 16)) { + d_bytes_per_sample = bits_per_sample / 8; + } +} + +void transmission_sink::set_sample_rate(unsigned int sample_rate) { + gr::thread::scoped_lock guard(d_mutex); + + d_sample_rate = sample_rate; +} + +int transmission_sink::bits_per_sample() { + return d_bytes_per_sample * 8; +} + +unsigned int +transmission_sink::sample_rate() { + return d_sample_rate; +} + +double transmission_sink::total_length_in_seconds() { + return this->length_in_seconds() + d_prior_transmission_length; +} + +double transmission_sink::length_in_seconds() { + // std::cout << "Filename: "<< current_filename << "Sample #: " << + // d_sample_count << " rate: " << d_sample_rate << " bytes: " << + // d_bytes_per_sample << "\n"; + return (double)d_sample_count / (double)d_sample_rate; + + // return (double) ( d_sample_count * d_bytes_per_sample_new * 8) / (double) + // d_sample_rate; +} + +void transmission_sink::do_update() {} +} /* namespace blocks */ +} /* namespace gr */ diff --git a/lib/gr_blocks/transmission_sink.h b/lib/gr_blocks/transmission_sink.h new file mode 100644 index 000000000..76c6cc0cb --- /dev/null +++ b/lib/gr_blocks/transmission_sink.h @@ -0,0 +1,154 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2013 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio 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, or (at your option) + * any later version. + * + * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_TRANSMISSION_SINK_H +#define INCLUDED_TRANSMISSION_SINK_H + + + +#include +#include + +#include "../../trunk-recorder/global_structs.h" +#include "../../trunk-recorder/formatter.h" + +#include +#include +#include + +class Call; +struct Transmission; +namespace gr { +namespace blocks { + + +class BLOCKS_API transmission_sink : virtual public sync_block +{ +private: + + unsigned d_sample_rate; + int d_nchans; + int d_max_sample_val; + int d_slot; + int d_min_sample_val; + int d_normalize_shift; + int d_normalize_fac; + bool d_conventional; + bool d_first_work; + bool d_termination_flag; + time_t d_start_time; + time_t d_stop_time; + long curr_src_id; + char current_filename[255]; + char current_base_filename[255]; + Call* d_current_call; + long d_current_call_num; + long d_current_call_recorder_num; + std::string d_current_call_short_name; + std::string d_current_call_capture_dir; + double d_current_call_freq; + double d_prior_transmission_length; + long d_current_call_talkgroup; + bool record_more_transmissions; +protected: + + unsigned d_sample_count; + int d_bytes_per_sample; + FILE *d_fp; + boost::mutex d_mutex; + virtual int dowork(int noutput_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items); + + /*! + * \brief If any file changes have occurred, update now. This is called + * internally by work() and thus doesn't usually need to be called by + * hand. + */ + void do_update(); + + /*! + * \brief Writes information to the WAV header which is not available + * a-priori (chunk size etc.) and closes the file. Not thread-safe and + * assumes d_fp is a valid file pointer, should thus only be called by + * other methods. + */ + void close_wav(bool close_call); +protected: + bool stop(); + bool open_internal(const char *filename); + std::vector transmission_list; + State state; +public: + + + #if GNURADIO_VERSION < 0x030900 + typedef boost::shared_ptr sptr; + #else + typedef std::shared_ptr sptr; + #endif + + + /* + * \param filename The .wav file to be opened + * \param n_channels Number of channels (2 = stereo or I/Q output) + * \param sample_rate Sample rate [S/s] + * \param bits_per_sample 16 or 8 bit, default is 16 + */ + static sptr make(int n_channels, + unsigned int sample_rate, + int bits_per_sample = 16); + + transmission_sink(int n_channels, + unsigned int sample_rate, + int bits_per_sample); + virtual ~transmission_sink(); + void create_base_filename(); + char *get_filename(); + bool start_recording(Call *call); + bool start_recording(Call* call, int slot); + void stop_recording(); + void end_transmission(); + void set_source(long src); + void set_sample_rate(unsigned int sample_rate); + void set_bits_per_sample(int bits_per_sample); + void set_record_more_transmissions(bool more); + void clear_transmission_list(); + std::vector get_transmission_list(); + void add_transmission(Transmission t); + int bits_per_sample(); + unsigned int sample_rate(); + double total_length_in_seconds(); + double length_in_seconds(); + Call_Source * get_source_list(); + int get_source_count(); + virtual int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + State get_state(); + time_t get_start_time(); + time_t get_stop_time(); +}; + +} /* namespace blocks */ +} /* namespace gr */ + +#endif + diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index 8d8b9339a..8c9556ee2 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -1049,7 +1049,7 @@ void handle_call_update(TrunkMessage message, System *sys) { if (call->get_state() == INACTIVE) { // Only a RECORDING call can be set to INACTIVE // We should be safe to set it to RECORDING if it starts to get UPDATE messages - call->set_state(RECORDING) + call->set_state(RECORDING); BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Werid - update for an INACTIVE Call \u001b[0m"; } BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Updating Call \u001b[0m"; diff --git a/trunk-recorder/recorders/analog_recorder.cc b/trunk-recorder/recorders/analog_recorder.cc index 1e9de4627..55492bda3 100644 --- a/trunk-recorder/recorders/analog_recorder.cc +++ b/trunk-recorder/recorders/analog_recorder.cc @@ -2,7 +2,7 @@ #include "analog_recorder.h" #include #include -#include +#include #include "../formatter.h" #include "../recorder_globals.h" #include "../plugin_manager/plugin_manager.h" @@ -202,7 +202,7 @@ analog_recorder::analog_recorder(Source *src) //tm *ltm = localtime(&starttime); - wav_sink = gr::blocks::nonstop_wavfile_sink_impl::make(1, wav_sample_rate, 16); // Configurable + wav_sink = gr::blocks::transmission_sink::make(1, wav_sample_rate, 16); // Configurable if(use_streaming) { BOOST_LOG_TRIVIAL(info) << "Creating plugin sink..." << std::endl; diff --git a/trunk-recorder/recorders/analog_recorder.h b/trunk-recorder/recorders/analog_recorder.h index 9b3856990..dfc505540 100644 --- a/trunk-recorder/recorders/analog_recorder.h +++ b/trunk-recorder/recorders/analog_recorder.h @@ -49,7 +49,7 @@ class analog_recorder; #include #include #include -#include +#include #if GNURADIO_VERSION < 0x030900 @@ -150,7 +150,7 @@ class analog_recorder : public gr::hier_block2, public Recorder { gr::analog::quadrature_demod_cf::sptr demod; gr::blocks::float_to_short::sptr converter; - gr::blocks::nonstop_wavfile_sink::sptr wav_sink; + gr::blocks::transmission_sink::sptr wav_sink; gr::blocks::copy::sptr valve; gr::blocks::decoder_wrapper::sptr decoder_sink; diff --git a/trunk-recorder/recorders/debug_recorder.h b/trunk-recorder/recorders/debug_recorder.h index a7e84f3c6..0b5a37f07 100644 --- a/trunk-recorder/recorders/debug_recorder.h +++ b/trunk-recorder/recorders/debug_recorder.h @@ -58,7 +58,7 @@ #include "recorder.h" #include -#include + class Source; class debug_recorder; diff --git a/trunk-recorder/recorders/dmr_recorder.cc b/trunk-recorder/recorders/dmr_recorder.cc index 79d4980f1..3b69a3eb5 100644 --- a/trunk-recorder/recorders/dmr_recorder.cc +++ b/trunk-recorder/recorders/dmr_recorder.cc @@ -212,8 +212,8 @@ void dmr_recorder::initialize(Source *src) { const float l[] = {-2.0, 0.0, 2.0, 4.0}; std::vector slices(l, l + sizeof(l) / sizeof(l[0])); slicer = gr::op25_repeater::fsk4_slicer_fb::make(slices); - wav_sink_slot0 = gr::blocks::nonstop_wavfile_sink_impl::make(1, 8000, 16); - wav_sink_slot1 = gr::blocks::nonstop_wavfile_sink_impl::make(1, 8000, 16); + wav_sink_slot0 = gr::blocks::transmission_sink::make(1, 8000, 16); + wav_sink_slot1 = gr::blocks::transmission_sink::make(1, 8000, 16); //recorder->initialize(src); //OP25 Frame Assembler diff --git a/trunk-recorder/recorders/dmr_recorder.h b/trunk-recorder/recorders/dmr_recorder.h index c0eadd1f0..ec6dc9be5 100644 --- a/trunk-recorder/recorders/dmr_recorder.h +++ b/trunk-recorder/recorders/dmr_recorder.h @@ -76,7 +76,7 @@ #include "recorder.h" #include -#include +#include #include class Source; @@ -222,8 +222,8 @@ gr::op25_repeater::gardner_costas_cc::sptr costas_clock; gr::blocks::short_to_float::sptr converter_slot0; gr::blocks::short_to_float::sptr converter_slot1; gr::blocks::multiply_const_ff::sptr levels; - gr::blocks::nonstop_wavfile_sink::sptr wav_sink_slot0; - gr::blocks::nonstop_wavfile_sink::sptr wav_sink_slot1; + gr::blocks::transmission_sink::sptr wav_sink_slot0; + gr::blocks::transmission_sink::sptr wav_sink_slot1; gr::blocks::plugin_wrapper::sptr plugin_sink; }; diff --git a/trunk-recorder/recorders/p25_recorder.h b/trunk-recorder/recorders/p25_recorder.h index 0538b694a..e39c03b9b 100644 --- a/trunk-recorder/recorders/p25_recorder.h +++ b/trunk-recorder/recorders/p25_recorder.h @@ -54,7 +54,7 @@ #include "p25_recorder_decode.h" #include "p25_recorder_fsk4_demod.h" #include "p25_recorder_qpsk_demod.h" -#include +#include #include class Source; diff --git a/trunk-recorder/recorders/p25_recorder_decode.cc b/trunk-recorder/recorders/p25_recorder_decode.cc index c020f9a64..f8a288ac1 100644 --- a/trunk-recorder/recorders/p25_recorder_decode.cc +++ b/trunk-recorder/recorders/p25_recorder_decode.cc @@ -76,7 +76,7 @@ void p25_recorder_decode::initialize( int silence_frames) { const float l[] = {-2.0, 0.0, 2.0, 4.0}; std::vector slices(l, l + sizeof(l) / sizeof(l[0])); slicer = gr::op25_repeater::fsk4_slicer_fb::make(slices); - wav_sink = gr::blocks::nonstop_wavfile_sink_impl::make(1, 8000, 16); + wav_sink = gr::blocks::transmission_sink::make(1, 8000, 16); //recorder->initialize(src); bool use_streaming = d_recorder->get_enable_audio_streaming(); diff --git a/trunk-recorder/recorders/p25_recorder_decode.h b/trunk-recorder/recorders/p25_recorder_decode.h index b0e991576..c115dc1a4 100644 --- a/trunk-recorder/recorders/p25_recorder_decode.h +++ b/trunk-recorder/recorders/p25_recorder_decode.h @@ -22,8 +22,7 @@ #include #endif -#include -#include +#include #include #include "recorder.h" @@ -52,7 +51,7 @@ class p25_recorder_decode : public gr::hier_block2 { gr::op25_repeater::fsk4_slicer_fb::sptr slicer; gr::blocks::short_to_float::sptr converter; gr::blocks::multiply_const_ss::sptr levels; - gr::blocks::nonstop_wavfile_sink::sptr wav_sink; + gr::blocks::transmission_sink::sptr wav_sink; gr::blocks::plugin_wrapper::sptr plugin_sink; public: p25_recorder_decode(Recorder* recorder); diff --git a/trunk-recorder/recorders/p25_recorder_fsk4_demod.cc b/trunk-recorder/recorders/p25_recorder_fsk4_demod.cc index 225107928..6d1dd792c 100644 --- a/trunk-recorder/recorders/p25_recorder_fsk4_demod.cc +++ b/trunk-recorder/recorders/p25_recorder_fsk4_demod.cc @@ -2,7 +2,7 @@ p25_recorder_fsk4_demod_sptr make_p25_recorder_fsk4_demod() { p25_recorder_fsk4_demod *recorder = new p25_recorder_fsk4_demod(); - //recorder->initialize(src, gr::blocks::nonstop_wavfile_sink_impl::make(1, 8000, 16, false)); + recorder->initialize(); return gnuradio::get_initial_sptr(recorder); } diff --git a/trunk-recorder/recorders/recorder.h b/trunk-recorder/recorders/recorder.h index 8702f9d6a..5a0ca1933 100644 --- a/trunk-recorder/recorders/recorder.h +++ b/trunk-recorder/recorders/recorder.h @@ -58,7 +58,7 @@ #include "../state.h" #include "../call.h" -#include +#include #include diff --git a/trunk-recorder/recorders/sigmf_recorder.cc b/trunk-recorder/recorders/sigmf_recorder.cc index aca59296f..7477feac8 100644 --- a/trunk-recorder/recorders/sigmf_recorder.cc +++ b/trunk-recorder/recorders/sigmf_recorder.cc @@ -54,7 +54,7 @@ long sigmf_recorder::get_source_count() { } Call_Source *sigmf_recorder::get_source_list() { - return NULL; //wav_sink->get_source_list(); + return NULL; } Source *sigmf_recorder::get_source() { @@ -78,7 +78,7 @@ double sigmf_recorder::get_freq() { } double sigmf_recorder::get_current_length() { - return 0; //wav_sink->length_in_seconds(); + return 0; } int sigmf_recorder::lastupdate() { @@ -101,7 +101,6 @@ State sigmf_recorder::get_state() { void sigmf_recorder::stop() { if (state == ACTIVE) { - recording_duration += wav_sink->length_in_seconds(); BOOST_LOG_TRIVIAL(error) << "sigmf_recorder.cc: Stopping Logger \t[ " << rec_num << " ] - freq[ " << freq << "] \t talkgroup[ " << talkgroup << " ]"; state = INACTIVE; valve->set_enabled(false); diff --git a/trunk-recorder/recorders/sigmf_recorder.h b/trunk-recorder/recorders/sigmf_recorder.h index b16f1e884..edab053d2 100644 --- a/trunk-recorder/recorders/sigmf_recorder.h +++ b/trunk-recorder/recorders/sigmf_recorder.h @@ -74,7 +74,6 @@ #include "recorder.h" #include -#include class Source; class sigmf_recorder; @@ -161,7 +160,6 @@ class sigmf_recorder : public gr::hier_block2, public Recorder { gr::analog::feedforward_agc_cc::sptr agc; gr::analog::agc2_ff::sptr demod_agc; gr::analog::agc2_cc::sptr pre_demod_agc; - gr::blocks::nonstop_wavfile_sink::sptr wav_sink; gr::blocks::file_sink::sptr raw_sink; gr::blocks::short_to_float::sptr converter; gr::blocks::copy::sptr valve; From c1b4d60cf4109c2ca6408637edf39d130d921274 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Sun, 13 Feb 2022 22:14:10 -0500 Subject: [PATCH 03/38] Adding support for conventional --- lib/gr_blocks/transmission_sink.cc | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc index 0cabec678..178ff2fcb 100644 --- a/lib/gr_blocks/transmission_sink.cc +++ b/lib/gr_blocks/transmission_sink.cc @@ -350,16 +350,19 @@ int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_ BOOST_LOG_TRIVIAL(info) << "ENDING TRANSMISSION from TAGS Voice Channel mismatch source id - current: "<< curr_src_id << " new: " << src_id << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); - /*if (d_sample_count > 0) { - end_transmission(); - } - state = STOPPED;*/ - /*if (!record_more_transmissions) { + /* + if (d_conventional && (d_sample_count > 0)) { + end_transmission(); + state = IDLE; + } + state = STOPPED; + if (!record_more_transmissions) { state = STOPPED; } else { state = IDLE; d_first_work = true; }*/ + curr_src_id = src_id; } //BOOST_LOG_TRIVIAL(info) << "Updated Voice Channel source id: " << src_id << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); @@ -434,7 +437,10 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu } // Another GRANT message has not arrived. - if (record_more_transmissions == false) { + if (is_conventional || (record_more_transmissions == true)) { + state = IDLE; + d_first_work = true; + } else { char formattedTalkgroup[62]; snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); @@ -443,10 +449,7 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu //BOOST_LOG_TRIVIAL(trace) << "Call completed - putting recorder into state Completed - we had samples"; state = STOPPED; - } else { - state = IDLE; - d_first_work = true; - } + } d_termination_flag = false; return noutput_items; From 41b5580e5a81d1b4d430e06486680d80e6ad45dc Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Thu, 17 Feb 2022 22:14:13 -0500 Subject: [PATCH 04/38] Update transmission_sink.cc --- lib/gr_blocks/transmission_sink.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc index 178ff2fcb..2eb21809d 100644 --- a/lib/gr_blocks/transmission_sink.cc +++ b/lib/gr_blocks/transmission_sink.cc @@ -437,7 +437,7 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu } // Another GRANT message has not arrived. - if (is_conventional || (record_more_transmissions == true)) { + if (d_conventional || (record_more_transmissions == true)) { state = IDLE; d_first_work = true; } else { From 36dd7a2124f84d4fb5516a1e28e8b5db9cf96bc3 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Tue, 22 Feb 2022 21:19:06 -0500 Subject: [PATCH 05/38] adding a grant message print out --- trunk-recorder/main.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index 8c9556ee2..3e89c0998 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -975,10 +975,11 @@ void handle_call_grant(TrunkMessage message, System *sys) { continue; } - //BOOST_LOG_TRIVIAL(info) << "TG: " << call->get_talkgroup() << " | " << message.talkgroup << " sys num: " << call->get_sys_num() << " | " << message.sys_num << " freq: " << call->get_freq() << " | " << message.freq << " TDMA Slot" << call->get_tdma_slot() << " | " << message.tdma_slot << " TDMA: " << call->get_phase2_tdma() << " | " << message.phase2_tdma; if ((call->get_talkgroup() == message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { call_found = true; + BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m GRANT Message\u001b[0m"; + if (call->get_state() == RECORDING) { call->set_record_more_transmissions(true); } From b40268f204b3ae6ababa55d76f775f9e6e20e889 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Tue, 22 Feb 2022 21:22:25 -0500 Subject: [PATCH 06/38] Update main.cc --- trunk-recorder/main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index 3e89c0998..fed8b1c59 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -978,7 +978,7 @@ void handle_call_grant(TrunkMessage message, System *sys) { if ((call->get_talkgroup() == message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { call_found = true; - BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m GRANT Message\u001b[0m"; + BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m GRANT Message\u001b[0m"; if (call->get_state() == RECORDING) { call->set_record_more_transmissions(true); From 889ca51e23cb337b466dece7a92400a5a1635732 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Tue, 22 Feb 2022 22:05:34 -0500 Subject: [PATCH 07/38] cleaning up and changing record more --- lib/gr_blocks/nonstop_wavfile_sink.h | 98 ---- lib/gr_blocks/nonstop_wavfile_sink_impl.cc | 559 --------------------- lib/gr_blocks/nonstop_wavfile_sink_impl.h | 145 ------ lib/gr_blocks/transmission_sink.cc | 7 +- trunk-recorder/main.cc | 2 +- 5 files changed, 4 insertions(+), 807 deletions(-) delete mode 100644 lib/gr_blocks/nonstop_wavfile_sink.h delete mode 100644 lib/gr_blocks/nonstop_wavfile_sink_impl.cc delete mode 100644 lib/gr_blocks/nonstop_wavfile_sink_impl.h diff --git a/lib/gr_blocks/nonstop_wavfile_sink.h b/lib/gr_blocks/nonstop_wavfile_sink.h deleted file mode 100644 index d29871375..000000000 --- a/lib/gr_blocks/nonstop_wavfile_sink.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2009,2013 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_NONSTOP_WAVFILE_SINK_H -#define INCLUDED_GR_NONSTOP_WAVFILE_SINK_H - -#include "../../trunk-recorder/global_structs.h" -#include "../../trunk-recorder/formatter.h" - -//#include "../trunk-recorder/call_conventional.h" -#include -#include -#include - -class Call; -struct Transmission; -namespace gr { -namespace blocks { - -/*! - * \brief Write stream to a Microsoft PCM (.wav) file. - * \ingroup audio_blk - * - * \details - * Values must be floats within [-1;1]. - * Check gr_make_wavfile_sink() for extra info. - */ -class BLOCKS_API nonstop_wavfile_sink : virtual public sync_block -{ -public: - // gr::blocks::wavfile_sink::sptr - - #if GNURADIO_VERSION < 0x030900 - typedef boost::shared_ptr sptr; - #else - typedef std::shared_ptr sptr; - #endif - - - /*! - * \brief Opens a new file and writes a WAV header. Thread-safe. - */ - virtual bool start_recording(Call* call) = 0; - virtual bool start_recording(Call* call, int slot) = 0; - /*! - * \brief Closes the currently active file and completes the WAV - * header. Thread-safe. - */ - virtual void stop_recording() = 0; - - /*! - * \brief Set the sample rate. This will not affect the WAV file - * currently opened. Any following open() calls will use this new - * sample rate. - */ - virtual void set_sample_rate(unsigned int sample_rate) = 0; - - /*! - * \brief Set bits per sample. This will not affect the WAV file - * currently opened (see set_sample_rate()). If the value is - * neither 8 nor 16, the call is ignored and the current value - * is kept. - */ - - virtual void set_source(long src) {}; - virtual void set_bits_per_sample(int bits_per_sample) = 0; - virtual double total_length_in_seconds() = 0; - virtual double length_in_seconds() = 0; - virtual State get_state() = 0; - virtual std::vector get_transmission_list() = 0; - virtual time_t get_stop_time() = 0; - virtual void set_record_more_transmissions(bool more) = 0; - -}; - -} /* namespace blocks */ -} /* namespace gr */ - -#endif /* INCLUDED_GR_WAVFILE_SINK_H */ diff --git a/lib/gr_blocks/nonstop_wavfile_sink_impl.cc b/lib/gr_blocks/nonstop_wavfile_sink_impl.cc deleted file mode 100644 index ceae206c2..000000000 --- a/lib/gr_blocks/nonstop_wavfile_sink_impl.cc +++ /dev/null @@ -1,559 +0,0 @@ -/* -*- c++ -*- */ - -/* - * Copyright 2004,2006-2011,2013 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - - -#include "nonstop_wavfile_sink.h" -#include "nonstop_wavfile_sink_impl.h" -#include "../../trunk-recorder/call.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// win32 (mingw/msvc) specific -#ifdef HAVE_IO_H -#include -#endif // ifdef HAVE_IO_H -#ifdef O_BINARY -#define OUR_O_BINARY O_BINARY -#else // ifdef O_BINARY -#define OUR_O_BINARY 0 -#endif // ifdef O_BINARY - -// should be handled via configure -#ifdef O_LARGEFILE -#define OUR_O_LARGEFILE O_LARGEFILE -#else // ifdef O_LARGEFILE -#define OUR_O_LARGEFILE 0 -#endif // ifdef O_LARGEFILE - -namespace gr { -namespace blocks { -nonstop_wavfile_sink_impl::sptr -nonstop_wavfile_sink_impl::make(int n_channels, unsigned int sample_rate, int bits_per_sample) { - return gnuradio::get_initial_sptr(new nonstop_wavfile_sink_impl(n_channels, sample_rate, bits_per_sample)); -} - -nonstop_wavfile_sink_impl::nonstop_wavfile_sink_impl( - int n_channels, - unsigned int sample_rate, - int bits_per_sample) - : sync_block("nonstop_wavfile_sink", - io_signature::make(1, n_channels, sizeof(int16_t)), - io_signature::make(0, 0, 0)), - d_sample_rate(sample_rate), d_nchans(n_channels), - d_fp(0), d_current_call(NULL) { - if ((bits_per_sample != 8) && (bits_per_sample != 16)) { - throw std::runtime_error("Invalid bits per sample (supports 8 and 16)"); - } - d_bytes_per_sample = bits_per_sample / 8; - d_sample_count = 0; - d_slot = -1; - d_first_work = true; - d_termination_flag = false; - state = AVAILABLE; -} - -//static int rec_counter=0; -void nonstop_wavfile_sink_impl::create_base_filename() { - time_t work_start_time = d_start_time; - std::stringstream path_stream; - tm *ltm = localtime(&work_start_time); - // Found some good advice on Streams and Strings here: https://blog.sensecodons.com/2013/04/dont-let-stdstringstreamstrcstr-happen.html - path_stream << d_current_call_capture_dir << "/" << d_current_call_short_name << "/" << 1900 + ltm->tm_year << "/" << 1 + ltm->tm_mon << "/" << ltm->tm_mday; - std::string path_string = path_stream.str(); - boost::filesystem::create_directories(path_string); - - int nchars; - - if (d_slot == -1) { - nchars = snprintf(current_base_filename, 255, "%s/%ld-%ld_%.0f", path_string.c_str(), d_current_call_talkgroup, work_start_time, d_current_call_freq); - } else { - // this is for the case when it is a DMR recorder and 2 wav files are created, the slot is needed to keep them separate. - nchars = snprintf(current_base_filename, 255, "%s/%ld-%ld_%.0f.%d", path_string.c_str(), d_current_call_talkgroup, work_start_time, d_current_call_freq,d_slot); - } - if (nchars >= 255) { - BOOST_LOG_TRIVIAL(error) << "Call: Path longer than 255 charecters"; - } -} - -char *nonstop_wavfile_sink_impl::get_filename() { - return current_filename; -} - -bool nonstop_wavfile_sink_impl::start_recording(Call *call, int slot) { - this->d_slot = slot; - this->start_recording(call); - return true; -} - -bool nonstop_wavfile_sink_impl::start_recording(Call *call) { - gr::thread::scoped_lock guard(d_mutex); - if (d_current_call && d_fp) { - BOOST_LOG_TRIVIAL(trace) << "Start() - Current_Call & fp are not null! current_filename is: " << current_filename << " Length: " << d_sample_count << std::endl; - } - d_current_call = call; - d_current_call_num = call->get_call_num(); - d_current_call_recorder_num = 0; //call->get_recorder()->get_num(); - d_current_call_freq = call->get_freq(); - d_current_call_talkgroup = call->get_talkgroup(); - d_current_call_short_name = call->get_short_name(); - d_current_call_capture_dir = call->get_capture_dir(); - d_prior_transmission_length = 0; - record_more_transmissions = true; - - this->clear_transmission_list(); - d_conventional = call->is_conventional(); - curr_src_id = d_current_call->get_current_source_id(); - d_sample_count = 0; - d_first_work = true; - - // when a wav_sink first gets associated with a call, set its lifecycle to idle; - state = IDLE; - /* Should reset more variables here */ - - char formattedTalkgroup[62]; - snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); - std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tStarting wavfile sink SRC ID: " << curr_src_id; - - return true; -} - -bool nonstop_wavfile_sink_impl::open_internal(const char *filename) { - int d_first_sample_pos; - unsigned d_samples_per_chan; - - // we use the open system call to get access to the O_LARGEFILE flag. - // O_APPEND| - int fd; - - if ((fd = ::open(filename, - O_RDWR | O_CREAT | OUR_O_LARGEFILE | OUR_O_BINARY, - 0664)) < 0) { - perror(filename); - BOOST_LOG_TRIVIAL(error) << "wav error opening: " << filename << std::endl; - return false; - } - - if (d_fp) { // if we've already got a new one open, close it - BOOST_LOG_TRIVIAL(trace) << "File pointer already open, closing " << d_fp << " more" << current_filename << " for " << filename << std::endl; - - // fclose(d_fp); - // d_fp = NULL; - } - - if (strlen(filename) >= 255) { - BOOST_LOG_TRIVIAL(error) << "nonstop_wavfile_sink: Error! filename longer than 255"; - } - - if ((d_fp = fdopen(fd, "rb+")) == NULL) { - perror(filename); - ::close(fd); // don't leak file descriptor if fdopen fails. - BOOST_LOG_TRIVIAL(error) << "wav open failed" << std::endl; - return false; - } - - d_sample_count = 0; - d_first_work = true; - - if (!wavheader_write(d_fp, d_sample_rate, d_nchans, d_bytes_per_sample)) { - fprintf(stderr, "[%s] could not write to WAV file\n", __FILE__); - return false; - } - - if (d_bytes_per_sample == 1) { - d_max_sample_val = UCHAR_MAX; - d_min_sample_val = 0; - d_normalize_fac = d_max_sample_val / 2; - d_normalize_shift = 1; - } else if (d_bytes_per_sample == 2) { - d_max_sample_val = SHRT_MAX; - d_min_sample_val = SHRT_MIN; - d_normalize_fac = d_max_sample_val; - d_normalize_shift = 0; - } - - return true; -} - -void nonstop_wavfile_sink_impl::set_source(long src) { - gr::thread::scoped_lock guard(d_mutex); - - char formattedTalkgroup[62]; - snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); - std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - - if (curr_src_id == -1) { - - BOOST_LOG_TRIVIAL(error) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tUnit ID externally set, ext: "<< src << "\tcurrent: " << curr_src_id << "\t samples: " << d_sample_count; - - curr_src_id = src; - } else if (src != curr_src_id) { - if (state == RECORDING) { - - BOOST_LOG_TRIVIAL(error) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tUnit ID externally set, ext: "<< src << "\tcurrent: " << curr_src_id << "\t samples: " << d_sample_count; - - /*if (d_sample_count > 0) { - end_transmission(); - }*/ - BOOST_LOG_TRIVIAL(info) << "ENDING TRANSMISSION Voice Channel mismatch source id - current: "<< curr_src_id << " new: " << src; - //state = STOPPED; - /*if (!record_more_transmissions) { - state = STOPPED; - } else { - state = IDLE; - d_first_work = true; - }*/ - } - curr_src_id = src; - } -} - -void nonstop_wavfile_sink_impl::end_transmission() { - if (d_sample_count > 0) { - if (d_fp) { - close_wav(false); - } else { - BOOST_LOG_TRIVIAL(error) << "Ending transmission, sample_count is greater than 0 but d_fp is null" << std::endl; - } - // if an Transmission has ended, send it to Call. - Transmission transmission; - transmission.source = curr_src_id; // Source ID for the Call - transmission.start_time = d_start_time; // Start time of the Call - transmission.stop_time = d_stop_time; // when the Call eneded - transmission.sample_count = d_sample_count; - transmission.length = length_in_seconds(); // length in seconds - d_prior_transmission_length = d_prior_transmission_length + transmission.length; - strcpy(transmission.filename, current_filename); // Copy the filename - strcpy(transmission.base_filename, current_base_filename); - this->add_transmission(transmission); - d_sample_count = 0; - d_first_work = true; - curr_src_id = -1; - } else { - BOOST_LOG_TRIVIAL(error) << "Trying to end a Transmission, but the sample_count is 0" << std::endl; - } -} - -void nonstop_wavfile_sink_impl::stop_recording() { - gr::thread::scoped_lock guard(d_mutex); - - if (d_sample_count > 0) { - end_transmission(); - } - - if (state == RECORDING) { - BOOST_LOG_TRIVIAL(error) << "stop_recording() - stopping wavfile sink but recorder state is: " << state << std::endl; - } - d_current_call = NULL; - d_first_work = true; - d_termination_flag = false; - state = AVAILABLE; -} - -void nonstop_wavfile_sink_impl::close_wav(bool close_call) { - unsigned int byte_count = d_sample_count * d_bytes_per_sample; - wavheader_complete(d_fp, byte_count); - fclose(d_fp); - d_fp = NULL; -} - -nonstop_wavfile_sink_impl::~nonstop_wavfile_sink_impl() { - stop_recording(); -} - -bool nonstop_wavfile_sink_impl::stop() { - return true; -} - -State nonstop_wavfile_sink_impl::get_state() { - return this->state; -} - -int nonstop_wavfile_sink_impl::work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { - - gr::thread::scoped_lock guard(d_mutex); // hold mutex for duration of this - - // it is possible that we could get part of a transmission after a call has stopped. We shouldn't do any recording if this happens.... this could mean that we miss part of the recording though - if (!d_current_call) { - time_t now = time(NULL); - double its_been = difftime(now, d_stop_time); - char formattedTalkgroup[62]; - snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); - std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - BOOST_LOG_TRIVIAL(error) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tDropping samples - current_call is null\t Rec State: " << format_state(this->state) << "\tSince close: " << its_been; - - return noutput_items; - } - - // it is possible that we could get part of a transmission after a call has stopped. We shouldn't do any recording if this happens.... this could mean that we miss part of the recording though - if ((state == STOPPED) || (state == AVAILABLE)) { - if (noutput_items > 1) { - time_t now = time(NULL); - double its_been = difftime(now, d_stop_time); - char formattedTalkgroup[62]; - snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); - std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - BOOST_LOG_TRIVIAL(error) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tDropping samples - Recorder state is: " << format_state(this->state); - - //BOOST_LOG_TRIVIAL(info) << "WAV - state is: " << format_state(this->state) << "\t Dropping samples: " << noutput_items << " Since close: " << its_been << std::endl; - } - return noutput_items; - } - - std::vector tags; - pmt::pmt_t this_key(pmt::intern("src_id")); - pmt::pmt_t that_key(pmt::intern("terminate")); - //pmt::pmt_t squelch_key(pmt::intern("squelch_eob")); - get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0) + noutput_items); - - unsigned pos = 0; - //long curr_src_id = 0; - - for (unsigned int i = 0; i < tags.size(); i++) { - //BOOST_LOG_TRIVIAL(info) << "TAG! " << tags[i].key; - if (pmt::eq(this_key, tags[i].key)) { - long src_id = pmt::to_long(tags[i].value); - pos = d_sample_count + (tags[i].offset - nitems_read(0)); - - if (curr_src_id == -1) { - BOOST_LOG_TRIVIAL(info) << "Updated Voice Channel source id: " << src_id << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); - - curr_src_id = src_id; - } else if (src_id != curr_src_id) { - if (state == RECORDING) { - - - BOOST_LOG_TRIVIAL(info) << "ENDING TRANSMISSION from TAGS Voice Channel mismatch source id - current: "<< curr_src_id << " new: " << src_id << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); - /*if (d_sample_count > 0) { - end_transmission(); - } - state = STOPPED;*/ - /*if (!record_more_transmissions) { - state = STOPPED; - } else { - state = IDLE; - d_first_work = true; - }*/ - curr_src_id = src_id; - } - //BOOST_LOG_TRIVIAL(info) << "Updated Voice Channel source id: " << src_id << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); - - - } - - } - if (pmt::eq(that_key, tags[i].key)) { - d_termination_flag = true; - BOOST_LOG_TRIVIAL(info) << "TEMINATOR!!"; - } - } - tags.clear(); - - // if the System for this call is in Transmission Mode, and we have a recording and we got a flag that a Transmission ended... - int nwritten = dowork(noutput_items, input_items, output_items); - d_stop_time = time(NULL); - - return nwritten; -} - -time_t nonstop_wavfile_sink_impl::get_start_time() { - return d_start_time; -} - -time_t nonstop_wavfile_sink_impl::get_stop_time() { - return d_stop_time; -} - -void nonstop_wavfile_sink_impl::add_transmission(Transmission t) { - transmission_list.push_back(t); -} - -void nonstop_wavfile_sink_impl::set_record_more_transmissions(bool more) { - // If a Recorder is STOPPED and record_more is false, prep it so it is ready to go. - if ((record_more_transmissions == false) && (more == true) && (state == STOPPED)) { - BOOST_LOG_TRIVIAL(info) << "wav - setting record_more to true, sample count: " << d_sample_count; - d_sample_count = 0; - d_first_work = true; - state = IDLE; - } - record_more_transmissions = more; -} - -void nonstop_wavfile_sink_impl::clear_transmission_list() { - transmission_list.clear(); - transmission_list.shrink_to_fit(); -} - -std::vector nonstop_wavfile_sink_impl::get_transmission_list() { - return transmission_list; -} - -int nonstop_wavfile_sink_impl::dowork(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { - // block - int n_in_chans = input_items.size(); - short int sample_buf_s; - int nwritten; - - - if (d_termination_flag) { - - if (d_current_call == NULL) { - BOOST_LOG_TRIVIAL(error) << "wav - no current call in temination loop"; - state = STOPPED; - return noutput_items; - } - - if (d_sample_count > 0) { - end_transmission(); - } - - // Another GRANT message has not arrived. - if (record_more_transmissions == false) { - char formattedTalkgroup[62]; - snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); - std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - - BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\trecord_more_transmissions is false, setting recorder state to STOPPED"; - //BOOST_LOG_TRIVIAL(trace) << "Call completed - putting recorder into state Completed - we had samples"; - - state = STOPPED; - } else { - state = IDLE; - d_first_work = true; - } - d_termination_flag = false; - - return noutput_items; - } - - if (d_first_work) { - if (d_fp) { - // if we are already recording a file for this call, close it before starting a new one. - BOOST_LOG_TRIVIAL(info) << "WAV - Weird! we have an existing FP, but d_first_work was true: " << current_filename << std::endl; - - close_wav(false); - } - - time_t current_time = time(NULL); - if (current_time == d_start_time) { - d_start_time = current_time + 1; - } else { - d_start_time = current_time; - } - - // create a new filename, based on the current time and source. - create_base_filename(); - strcpy(current_filename, current_base_filename); - strcat(current_filename, ".wav"); - if (!open_internal(current_filename)) { - BOOST_LOG_TRIVIAL(error) << "can't open file"; - return noutput_items; - } - char formattedTalkgroup[62]; - snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); - std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tStarting new Transmission \tSrc ID: " << curr_src_id; - - //curr_src_id = d_current_call->get_current_source_id(); - - d_first_work = false; - } - - if (!d_fp) // drop output on the floor - { - BOOST_LOG_TRIVIAL(error) << "Wav - Dropping items, no fp or Current Call: " << noutput_items << " Filename: " << current_filename << " Current sample count: " << d_sample_count << std::endl; - return noutput_items; - } - - for (nwritten = 0; nwritten < noutput_items; nwritten++) { - for (int chan = 0; chan < d_nchans; chan++) { - // Write zeros to channels which are in the WAV file - // but don't have any inputs here - if (chan < n_in_chans) { - int16_t **in = (int16_t **)&input_items[0]; - sample_buf_s = in[chan][nwritten]; - } else { - sample_buf_s = 0; - } - - wav_write_sample(d_fp, sample_buf_s, d_bytes_per_sample); - - d_sample_count++; - } - } - - if (nwritten > 0) { - record_more_transmissions = false; - state = RECORDING; - } - // fflush (d_fp); // this is added so unbuffered content is written. - return nwritten; -} - -void nonstop_wavfile_sink_impl::set_bits_per_sample(int bits_per_sample) { - gr::thread::scoped_lock guard(d_mutex); - - if ((bits_per_sample == 8) || (bits_per_sample == 16)) { - d_bytes_per_sample = bits_per_sample / 8; - } -} - -void nonstop_wavfile_sink_impl::set_sample_rate(unsigned int sample_rate) { - gr::thread::scoped_lock guard(d_mutex); - - d_sample_rate = sample_rate; -} - -int nonstop_wavfile_sink_impl::bits_per_sample() { - return d_bytes_per_sample * 8; -} - -unsigned int -nonstop_wavfile_sink_impl::sample_rate() { - return d_sample_rate; -} - -double nonstop_wavfile_sink_impl::total_length_in_seconds() { - return this->length_in_seconds() + d_prior_transmission_length; -} - -double nonstop_wavfile_sink_impl::length_in_seconds() { - // std::cout << "Filename: "<< current_filename << "Sample #: " << - // d_sample_count << " rate: " << d_sample_rate << " bytes: " << - // d_bytes_per_sample << "\n"; - return (double)d_sample_count / (double)d_sample_rate; - - // return (double) ( d_sample_count * d_bytes_per_sample_new * 8) / (double) - // d_sample_rate; -} - -void nonstop_wavfile_sink_impl::do_update() {} -} /* namespace blocks */ -} /* namespace gr */ diff --git a/lib/gr_blocks/nonstop_wavfile_sink_impl.h b/lib/gr_blocks/nonstop_wavfile_sink_impl.h deleted file mode 100644 index fd81a5682..000000000 --- a/lib/gr_blocks/nonstop_wavfile_sink_impl.h +++ /dev/null @@ -1,145 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2009,2013 Free Software Foundation, Inc. - * - * This file is part of GNU Radio - * - * GNU Radio 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, or (at your option) - * any later version. - * - * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_nonstop_wavfile_SINK_IMPL_H -#define INCLUDED_GR_nonstop_wavfile_SINK_IMPL_H - -#include "nonstop_wavfile_sink.h" - -#include -//#include "wavfile.h" -#include -#include - -namespace gr { -namespace blocks { - -class nonstop_wavfile_sink_impl : public nonstop_wavfile_sink -{ -private: - - unsigned d_sample_rate; - int d_nchans; - int d_max_sample_val; - int d_slot; - int d_min_sample_val; - int d_normalize_shift; - int d_normalize_fac; - bool d_conventional; - bool d_first_work; - bool d_termination_flag; - time_t d_start_time; - time_t d_stop_time; - long curr_src_id; - char current_filename[255]; - char current_base_filename[255]; - Call* d_current_call; - long d_current_call_num; - long d_current_call_recorder_num; - std::string d_current_call_short_name; - std::string d_current_call_capture_dir; - double d_current_call_freq; - double d_prior_transmission_length; - long d_current_call_talkgroup; - bool record_more_transmissions; -protected: - - unsigned d_sample_count; - int d_bytes_per_sample; - FILE *d_fp; - boost::mutex d_mutex; - virtual int dowork(int noutput_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items); - - /*! - * \brief If any file changes have occurred, update now. This is called - * internally by work() and thus doesn't usually need to be called by - * hand. - */ - void do_update(); - - /*! - * \brief Writes information to the WAV header which is not available - * a-priori (chunk size etc.) and closes the file. Not thread-safe and - * assumes d_fp is a valid file pointer, should thus only be called by - * other methods. - */ - void close_wav(bool close_call); -protected: - bool stop(); - bool open_internal(const char *filename); - std::vector transmission_list; - State state; -public: - - - #if GNURADIO_VERSION < 0x030900 - typedef boost::shared_ptr sptr; - #else - typedef std::shared_ptr sptr; - #endif - - - /* - * \param filename The .wav file to be opened - * \param n_channels Number of channels (2 = stereo or I/Q output) - * \param sample_rate Sample rate [S/s] - * \param bits_per_sample 16 or 8 bit, default is 16 - */ - static sptr make(int n_channels, - unsigned int sample_rate, - int bits_per_sample = 16); - - nonstop_wavfile_sink_impl(int n_channels, - unsigned int sample_rate, - int bits_per_sample); - virtual ~nonstop_wavfile_sink_impl(); - void create_base_filename(); - char *get_filename(); - bool start_recording(Call *call); - bool start_recording(Call* call, int slot); - void stop_recording(); - void end_transmission(); - void set_source(long src); - void set_sample_rate(unsigned int sample_rate); - void set_bits_per_sample(int bits_per_sample); - void set_record_more_transmissions(bool more); - void clear_transmission_list(); - std::vector get_transmission_list(); - void add_transmission(Transmission t); - int bits_per_sample(); - unsigned int sample_rate(); - double total_length_in_seconds(); - double length_in_seconds(); - Call_Source * get_source_list(); - int get_source_count(); - virtual int work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - State get_state(); - time_t get_start_time(); - time_t get_stop_time(); -}; - -} /* namespace blocks */ -} /* namespace gr */ - -#endif /* INCLUDED_GR_nonstop_wavfile_SINK_IMPL_H */ diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc index 2eb21809d..2dc35b537 100644 --- a/lib/gr_blocks/transmission_sink.cc +++ b/lib/gr_blocks/transmission_sink.cc @@ -373,7 +373,7 @@ int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_ } if (pmt::eq(that_key, tags[i].key)) { d_termination_flag = true; - BOOST_LOG_TRIVIAL(info) << "TEMINATOR!!"; + //BOOST_LOG_TRIVIAL(info) << "TERMINATOR!!"; } } tags.clear(); @@ -427,7 +427,7 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu if (d_termination_flag) { if (d_current_call == NULL) { - BOOST_LOG_TRIVIAL(error) << "wav - no current call in temination loop"; + BOOST_LOG_TRIVIAL(error) << "wav - no current call, but in temination loop"; state = STOPPED; return noutput_items; } @@ -484,7 +484,7 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tStarting new Transmission \tSrc ID: " << curr_src_id; //curr_src_id = d_current_call->get_current_source_id(); - + record_more_transmissions = false; d_first_work = false; } @@ -512,7 +512,6 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu } if (nwritten > 0) { - record_more_transmissions = false; state = RECORDING; } // fflush (d_fp); // this is added so unbuffered content is written. diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index fed8b1c59..a450afbfe 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -965,7 +965,7 @@ void handle_call_grant(TrunkMessage message, System *sys) { going until it gets a termination flag. */ - BOOST_LOG_TRIVIAL(info) << "TG: " << message.talkgroup << " sys num: "<< message.sys_num << " freq: " << message.freq << " TDMA Slot" << message.tdma_slot << " TDMA: " << message.phase2_tdma; + //BOOST_LOG_TRIVIAL(info) << "TG: " << message.talkgroup << " sys num: "<< message.sys_num << " freq: " << message.freq << " TDMA Slot" << message.tdma_slot << " TDMA: " << message.phase2_tdma; for (vector::iterator it = calls.begin(); it != calls.end(); ++it) { Call *call = *it; From 9cf12f1cde008ee3ceb3b8cd83ebbfb3e228f80a Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Tue, 22 Feb 2022 22:23:40 -0500 Subject: [PATCH 08/38] tighter controls --- lib/gr_blocks/transmission_sink.cc | 36 +++++++++++++++++------------- trunk-recorder/main.cc | 2 +- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc index 2dc35b537..d34feafc4 100644 --- a/lib/gr_blocks/transmission_sink.cc +++ b/lib/gr_blocks/transmission_sink.cc @@ -349,7 +349,7 @@ int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_ if (state == RECORDING) { - BOOST_LOG_TRIVIAL(info) << "ENDING TRANSMISSION from TAGS Voice Channel mismatch source id - current: "<< curr_src_id << " new: " << src_id << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); + //BOOST_LOG_TRIVIAL(info) << "ENDING TRANSMISSION from TAGS Voice Channel mismatch source id - current: "<< curr_src_id << " new: " << src_id << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); /* if (d_conventional && (d_sample_count > 0)) { end_transmission(); @@ -423,7 +423,7 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu short int sample_buf_s; int nwritten; - + // A Termination Tag was receive if (d_termination_flag) { if (d_current_call == NULL) { @@ -436,20 +436,24 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu end_transmission(); } - // Another GRANT message has not arrived. - if (d_conventional || (record_more_transmissions == true)) { - state = IDLE; - d_first_work = true; - } else { - char formattedTalkgroup[62]; - snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); - std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - - BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\trecord_more_transmissions is false, setting recorder state to STOPPED"; - //BOOST_LOG_TRIVIAL(trace) << "Call completed - putting recorder into state Completed - we had samples"; - - state = STOPPED; - } + // Check to see if we have started a Transmission yet + // A Terminator with any Transmission started shouldn't do anything... right? + if (d_first_work) { + // Another GRANT message has arrived. + if (d_conventional || (record_more_transmissions == true)) { + state = IDLE; + d_first_work = true; + } else { + char formattedTalkgroup[62]; + snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); + std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); + + BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tTERM - record_more_transmissions = false, setting Recorder state to STOPPED"; + //BOOST_LOG_TRIVIAL(trace) << "Call completed - putting recorder into state Completed - we had samples"; + + state = STOPPED; + } + } d_termination_flag = false; return noutput_items; diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index a450afbfe..cd898aa67 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -978,7 +978,7 @@ void handle_call_grant(TrunkMessage message, System *sys) { if ((call->get_talkgroup() == message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { call_found = true; - BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m GRANT Message\u001b[0m"; + BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m GRANT Message for existing Call\u001b[0m"; if (call->get_state() == RECORDING) { call->set_record_more_transmissions(true); From acbef70406f714f7c9380d8b4eee159edf0a4545 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Tue, 22 Feb 2022 22:31:07 -0500 Subject: [PATCH 09/38] Update transmission_sink.cc --- lib/gr_blocks/transmission_sink.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc index d34feafc4..ab3070b87 100644 --- a/lib/gr_blocks/transmission_sink.cc +++ b/lib/gr_blocks/transmission_sink.cc @@ -373,6 +373,9 @@ int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_ } if (pmt::eq(that_key, tags[i].key)) { d_termination_flag = true; + pos = d_sample_count + (tags[i].offset - nitems_read(0)); + BOOST_LOG_TRIVIAL(info) << "Termination - rec sample count " << d_sample_count << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); + //BOOST_LOG_TRIVIAL(info) << "TERMINATOR!!"; } } @@ -448,7 +451,7 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tTERM - record_more_transmissions = false, setting Recorder state to STOPPED"; + BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tTERM - record_more_transmissions = false, setting Recorder state to STOPPED - count: " << d_sample_count; //BOOST_LOG_TRIVIAL(trace) << "Call completed - putting recorder into state Completed - we had samples"; state = STOPPED; From 23d7a37e4d1ccf540a25aa2851994fa133044309 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Tue, 22 Feb 2022 22:39:49 -0500 Subject: [PATCH 10/38] Update transmission_sink.cc --- lib/gr_blocks/transmission_sink.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc index ab3070b87..095df8e99 100644 --- a/lib/gr_blocks/transmission_sink.cc +++ b/lib/gr_blocks/transmission_sink.cc @@ -374,7 +374,12 @@ int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_ if (pmt::eq(that_key, tags[i].key)) { d_termination_flag = true; pos = d_sample_count + (tags[i].offset - nitems_read(0)); - BOOST_LOG_TRIVIAL(info) << "Termination - rec sample count " << d_sample_count << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); + char formattedTalkgroup[62]; + snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); + std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); + + BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tTermination - rec sample count " << d_sample_count << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); + //BOOST_LOG_TRIVIAL(info) << "TERMINATOR!!"; } From 1024e8ebc18a2f585b44822cec07f15c4fe77b82 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Tue, 22 Feb 2022 22:45:31 -0500 Subject: [PATCH 11/38] Update transmission_sink.cc --- lib/gr_blocks/transmission_sink.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc index 095df8e99..ca3e053eb 100644 --- a/lib/gr_blocks/transmission_sink.cc +++ b/lib/gr_blocks/transmission_sink.cc @@ -446,7 +446,7 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu // Check to see if we have started a Transmission yet // A Terminator with any Transmission started shouldn't do anything... right? - if (d_first_work) { + if (d_first_work == false) { // Another GRANT message has arrived. if (d_conventional || (record_more_transmissions == true)) { state = IDLE; From 67ca2cfeb8e0b8eb9a48f21a9473c2fa44a0910b Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Tue, 22 Feb 2022 22:59:42 -0500 Subject: [PATCH 12/38] Update transmission_sink.cc --- lib/gr_blocks/transmission_sink.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc index ca3e053eb..e7e96e590 100644 --- a/lib/gr_blocks/transmission_sink.cc +++ b/lib/gr_blocks/transmission_sink.cc @@ -330,8 +330,8 @@ int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_ pmt::pmt_t this_key(pmt::intern("src_id")); pmt::pmt_t that_key(pmt::intern("terminate")); //pmt::pmt_t squelch_key(pmt::intern("squelch_eob")); - get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0) + noutput_items); - + //get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0) + noutput_items); + get_tags_in_window(tags, 0, 0, noutput_items); unsigned pos = 0; //long curr_src_id = 0; @@ -462,6 +462,8 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu state = STOPPED; } } + + d_termination_flag = false; return noutput_items; From c40ba4f916bf1c00ebd587d1f1373232091a7613 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Tue, 22 Feb 2022 23:01:07 -0500 Subject: [PATCH 13/38] Update transmission_sink.cc --- lib/gr_blocks/transmission_sink.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc index e7e96e590..bcabf8828 100644 --- a/lib/gr_blocks/transmission_sink.cc +++ b/lib/gr_blocks/transmission_sink.cc @@ -378,7 +378,7 @@ int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_ snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tTermination - rec sample count " << d_sample_count << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); + BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tTermination - rec sample count " << d_sample_count << " pos: " << pos << " offset: " << tags[i].offset; //BOOST_LOG_TRIVIAL(info) << "TERMINATOR!!"; From c041c7f71480e7b534bbab1ca5a1894e916474ad Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Tue, 22 Feb 2022 23:05:44 -0500 Subject: [PATCH 14/38] Update transmission_sink.cc --- lib/gr_blocks/transmission_sink.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc index bcabf8828..470b79ebd 100644 --- a/lib/gr_blocks/transmission_sink.cc +++ b/lib/gr_blocks/transmission_sink.cc @@ -446,7 +446,7 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu // Check to see if we have started a Transmission yet // A Terminator with any Transmission started shouldn't do anything... right? - if (d_first_work == false) { + //if (d_first_work == false) { // Another GRANT message has arrived. if (d_conventional || (record_more_transmissions == true)) { state = IDLE; @@ -461,7 +461,7 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu state = STOPPED; } - } + //} d_termination_flag = false; From a32bd48725161341ee65a6e95af2941957d9889d Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Wed, 23 Feb 2022 10:02:19 -0500 Subject: [PATCH 15/38] Update main.cc --- trunk-recorder/main.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index cd898aa67..90960ac91 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -837,7 +837,7 @@ void manage_calls() { if ((call->since_last_update() > 1.0/*config.call_timeout*/) && ((state == RECORDING) || (state == MONITORING))) { if (state == RECORDING) { ended_call = true; - + call->set_record_more_transmissions(false); // If the call is being recorded and the wav_sink is already hit a termination flag, the call state is set to COMPLETED call->stop_call(); @@ -876,7 +876,7 @@ void manage_calls() { if (recorder != NULL) { // if the recorder has simply been going for a while and a call is inactive, end things - if (recorder->since_last_write() > 10) { + if (recorder->since_last_write() > 5) { BOOST_LOG_TRIVIAL(info) << "Recorder state: " << recorder->get_state(); BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m Rec Num: " << recorder->get_num() << "\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Removing call with stuck recorder \u001b[0m"; @@ -1055,6 +1055,9 @@ void handle_call_update(TrunkMessage message, System *sys) { } BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Updating Call \u001b[0m"; + + call->set_record_more_transmissions(true); + bool source_updated = call->update(message); if (source_updated) { plugman_call_start(call); From 85810ff9fe5245f3c315ab701afc5043834b9166 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Wed, 23 Feb 2022 22:14:03 -0500 Subject: [PATCH 16/38] Update main.cc --- trunk-recorder/main.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index 90960ac91..f0ff3db4c 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -838,8 +838,13 @@ void manage_calls() { if (state == RECORDING) { ended_call = true; call->set_record_more_transmissions(false); + call->set_state(INACTIVE); + // set the call state to inactive + + + // If the call is being recorded and the wav_sink is already hit a termination flag, the call state is set to COMPLETED - call->stop_call(); + //call->stop_call(); } // we do not need to stop Monitoring Calls, we can just delete them @@ -897,7 +902,7 @@ void manage_calls() { // In this case, the Call is inactive and was waiting for the recorder to finish. In this // case you can now conclude the call. - if ((recorder->get_state() == IDLE) || (recorder->get_state() == STOPPED)) { + /*if ((recorder->get_state() == IDLE) || (recorder->get_state() == STOPPED)) { //BOOST_LOG_TRIVIAL(info) << "Recorder state: " << format_state(recorder->get_state()); //BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36mCompleting Call, its state is INACTIVE and its recorder state is STOPPED or IDLE\u001b[0m"; // since the Call state is INACTIVE and the Recorder has reached a state of IDLE or STOPPED, we can now @@ -914,7 +919,7 @@ void manage_calls() { it = calls.erase(it); delete call; continue; - } + }*/ } else { BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Call set to Inactive, but has no recorder\u001b[0m"; } From 06e80117fde799ef824bc45c8d904fbef8bdeaf6 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Wed, 23 Feb 2022 22:21:17 -0500 Subject: [PATCH 17/38] Update main.cc --- trunk-recorder/main.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index f0ff3db4c..1315eb9f8 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -881,9 +881,9 @@ void manage_calls() { if (recorder != NULL) { // if the recorder has simply been going for a while and a call is inactive, end things - if (recorder->since_last_write() > 5) { - BOOST_LOG_TRIVIAL(info) << "Recorder state: " << recorder->get_state(); - BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m Rec Num: " << recorder->get_num() << "\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Removing call with stuck recorder \u001b[0m"; + if (call->since_last_update() > 5) { + //BOOST_LOG_TRIVIAL(info) << "Recorder state: " << recorder->get_state(); + BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m Rec Num: " << recorder->get_num() << "\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Removing call that has been inactive for more than 5 Sec \u001b[0m Rec last write: " << recorder->since_last_write() << " State: " << recorder->get_state(); // since the Call state is INACTIVE and the Recorder has been going on for a while, we can now // set the Call state to COMPLETED @@ -921,7 +921,7 @@ void manage_calls() { continue; }*/ } else { - BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Call set to Inactive, but has no recorder\u001b[0m"; + BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Call set to Inactive, but has no recorder\u001b[0m"; } } @@ -983,7 +983,7 @@ void handle_call_grant(TrunkMessage message, System *sys) { if ((call->get_talkgroup() == message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { call_found = true; - BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m GRANT Message for existing Call\u001b[0m"; + BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m GRANT Message for existing Call\u001b[0m"; if (call->get_state() == RECORDING) { call->set_record_more_transmissions(true); @@ -1001,7 +1001,7 @@ void handle_call_grant(TrunkMessage message, System *sys) { // There is an existing call on freq and slot that the new call will be started on. We should stop the older call. The older recorder will // keep writing to the file until it hits a termination flag, so no packets should be dropped. if ((call->get_state() == RECORDING) && (call->get_talkgroup() != message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { - BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Stopping RECORDING call, RX overlapping TG message Freq " << message.talkgroup << "\u001b[0m"; + BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Stopping RECORDING call, RX overlapping TG message Freq " << message.talkgroup << "\u001b[0m"; BOOST_LOG_TRIVIAL(info) << "\t - Stopping call because of overlapping Freq"; call->stop_call(); } @@ -1009,7 +1009,7 @@ void handle_call_grant(TrunkMessage message, System *sys) { // There is an existing call on freq and slot that the new call will be started on. We should stop the older call. The older recorder will // keep writing to the file until it hits a termination flag, so no packets should be dropped. if ((call->get_state() == INACTIVE) && (call->get_talkgroup() != message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { - BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Stopping INACTIVE call, RX overlapping TG message Freq " << message.talkgroup << "\u001b[0m"; + BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Stopping INACTIVE call, RX overlapping TG message Freq " << message.talkgroup << "\u001b[0m"; BOOST_LOG_TRIVIAL(info) << "\t - Stopping call because of overlapping Freq"; call->stop_call(); } @@ -1056,9 +1056,9 @@ void handle_call_update(TrunkMessage message, System *sys) { // Only a RECORDING call can be set to INACTIVE // We should be safe to set it to RECORDING if it starts to get UPDATE messages call->set_state(RECORDING); - BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Werid - update for an INACTIVE Call \u001b[0m"; + BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Werid - update for an INACTIVE Call \u001b[0m"; } - BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "\tTTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Updating Call \u001b[0m"; + BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Updating Call \u001b[0m"; call->set_record_more_transmissions(true); From 2fa079d670be983a4940887f9dde0a3d6b3d6d61 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Thu, 24 Feb 2022 21:19:55 -0500 Subject: [PATCH 18/38] less logging --- lib/gr_blocks/transmission_sink.cc | 2 +- trunk-recorder/main.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc index 470b79ebd..564b7d386 100644 --- a/lib/gr_blocks/transmission_sink.cc +++ b/lib/gr_blocks/transmission_sink.cc @@ -378,7 +378,7 @@ int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_ snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tTermination - rec sample count " << d_sample_count << " pos: " << pos << " offset: " << tags[i].offset; + //BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tTermination - rec sample count " << d_sample_count << " pos: " << pos << " offset: " << tags[i].offset; //BOOST_LOG_TRIVIAL(info) << "TERMINATOR!!"; diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index 1315eb9f8..5660049a4 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -983,7 +983,7 @@ void handle_call_grant(TrunkMessage message, System *sys) { if ((call->get_talkgroup() == message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { call_found = true; - BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m GRANT Message for existing Call\u001b[0m"; + //BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m GRANT Message for existing Call\u001b[0m"; if (call->get_state() == RECORDING) { call->set_record_more_transmissions(true); @@ -1058,7 +1058,7 @@ void handle_call_update(TrunkMessage message, System *sys) { call->set_state(RECORDING); BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Werid - update for an INACTIVE Call \u001b[0m"; } - BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Updating Call \u001b[0m"; + //BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Updating Call \u001b[0m"; call->set_record_more_transmissions(true); From d29f15dc6890e9e7bba7598e7c27b886b000aa3d Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Thu, 24 Feb 2022 21:30:38 -0500 Subject: [PATCH 19/38] end overlapping calls --- trunk-recorder/main.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index 5660049a4..60b6107da 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -1003,7 +1003,9 @@ void handle_call_grant(TrunkMessage message, System *sys) { if ((call->get_state() == RECORDING) && (call->get_talkgroup() != message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Stopping RECORDING call, RX overlapping TG message Freq " << message.talkgroup << "\u001b[0m"; BOOST_LOG_TRIVIAL(info) << "\t - Stopping call because of overlapping Freq"; - call->stop_call(); + //call->stop_call(); + call->set_state(COMPLETED); + call->conclude_call(); } // There is an existing call on freq and slot that the new call will be started on. We should stop the older call. The older recorder will @@ -1011,7 +1013,9 @@ void handle_call_grant(TrunkMessage message, System *sys) { if ((call->get_state() == INACTIVE) && (call->get_talkgroup() != message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Stopping INACTIVE call, RX overlapping TG message Freq " << message.talkgroup << "\u001b[0m"; BOOST_LOG_TRIVIAL(info) << "\t - Stopping call because of overlapping Freq"; - call->stop_call(); + //call->stop_call(); + call->set_state(COMPLETED); + call->conclude_call(); } } From 21efa6d1326de42e78b92a5c6041db8fe1df68b7 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Thu, 24 Feb 2022 21:33:07 -0500 Subject: [PATCH 20/38] Update main.cc --- trunk-recorder/main.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index 60b6107da..53d2778ac 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -972,11 +972,12 @@ void handle_call_grant(TrunkMessage message, System *sys) { //BOOST_LOG_TRIVIAL(info) << "TG: " << message.talkgroup << " sys num: "<< message.sys_num << " freq: " << message.freq << " TDMA Slot" << message.tdma_slot << " TDMA: " << message.phase2_tdma; - for (vector::iterator it = calls.begin(); it != calls.end(); ++it) { + for (vector::iterator it = calls.begin(); it != calls.end();) { Call *call = *it; /* This will skip all calls that are not currently acitve */ if (call->get_state() == COMPLETED) { + ++it; continue; } @@ -1006,6 +1007,9 @@ void handle_call_grant(TrunkMessage message, System *sys) { //call->stop_call(); call->set_state(COMPLETED); call->conclude_call(); + it = calls.erase(it); + delete call; + continue; } // There is an existing call on freq and slot that the new call will be started on. We should stop the older call. The older recorder will @@ -1016,6 +1020,9 @@ void handle_call_grant(TrunkMessage message, System *sys) { //call->stop_call(); call->set_state(COMPLETED); call->conclude_call(); + it = calls.erase(it); + delete call; + continue; } } @@ -1027,7 +1034,7 @@ void handle_call_grant(TrunkMessage message, System *sys) { plugman_call_start(call); plugman_calls_active(calls); } - + it++; } From cc0d083cc390d49aee5b9434a0a6df3e9b473524 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Thu, 24 Feb 2022 21:33:59 -0500 Subject: [PATCH 21/38] Update main.cc --- trunk-recorder/main.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index 53d2778ac..89f5e2278 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -1024,7 +1024,7 @@ void handle_call_grant(TrunkMessage message, System *sys) { delete call; continue; } - + it++; } if (!call_found) { @@ -1034,7 +1034,7 @@ void handle_call_grant(TrunkMessage message, System *sys) { plugman_call_start(call); plugman_calls_active(calls); } - it++; + } From 9f9e44792a7f9ec1725fbae0f2993c863717cb58 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Thu, 24 Feb 2022 21:44:21 -0500 Subject: [PATCH 22/38] cleaner logs --- lib/gr_blocks/transmission_sink.cc | 4 ++-- trunk-recorder/main.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc index 564b7d386..8f8120f77 100644 --- a/lib/gr_blocks/transmission_sink.cc +++ b/lib/gr_blocks/transmission_sink.cc @@ -342,7 +342,7 @@ int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_ pos = d_sample_count + (tags[i].offset - nitems_read(0)); if (curr_src_id == -1) { - BOOST_LOG_TRIVIAL(info) << "Updated Voice Channel source id: " << src_id << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); + //BOOST_LOG_TRIVIAL(info) << "Updated Voice Channel source id: " << src_id << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); curr_src_id = src_id; } else if (src_id != curr_src_id) { @@ -408,7 +408,7 @@ void transmission_sink::add_transmission(Transmission t) { void transmission_sink::set_record_more_transmissions(bool more) { // If a Recorder is STOPPED and record_more is false, prep it so it is ready to go. if ((record_more_transmissions == false) && (more == true) && (state == STOPPED)) { - BOOST_LOG_TRIVIAL(info) << "wav - setting record_more to true, sample count: " << d_sample_count; + //BOOST_LOG_TRIVIAL(info) << "wav - setting record_more to true, sample count: " << d_sample_count; d_sample_count = 0; d_first_work = true; state = IDLE; diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index 89f5e2278..9be6f694e 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -883,7 +883,7 @@ void manage_calls() { // if the recorder has simply been going for a while and a call is inactive, end things if (call->since_last_update() > 5) { //BOOST_LOG_TRIVIAL(info) << "Recorder state: " << recorder->get_state(); - BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m Rec Num: " << recorder->get_num() << "\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Removing call that has been inactive for more than 5 Sec \u001b[0m Rec last write: " << recorder->since_last_write() << " State: " << recorder->get_state(); + BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Removing call that has been inactive for more than 5 Sec \u001b[0m Rec last write: " << recorder->since_last_write() << " State: " << recorder->get_state(); // since the Call state is INACTIVE and the Recorder has been going on for a while, we can now // set the Call state to COMPLETED @@ -1067,7 +1067,7 @@ void handle_call_update(TrunkMessage message, System *sys) { // Only a RECORDING call can be set to INACTIVE // We should be safe to set it to RECORDING if it starts to get UPDATE messages call->set_state(RECORDING); - BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Werid - update for an INACTIVE Call \u001b[0m"; + BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Reactivating an INACTIVE Call \u001b[0m"; } //BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Updating Call \u001b[0m"; From 96bb5a3b91359f6a86a8a99ed734d09c444f831d Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Sat, 26 Feb 2022 08:58:48 -0500 Subject: [PATCH 23/38] Update main.cc --- trunk-recorder/main.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index 9be6f694e..eb5d8efb0 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -1002,7 +1002,7 @@ void handle_call_grant(TrunkMessage message, System *sys) { // There is an existing call on freq and slot that the new call will be started on. We should stop the older call. The older recorder will // keep writing to the file until it hits a termination flag, so no packets should be dropped. if ((call->get_state() == RECORDING) && (call->get_talkgroup() != message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { - BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Stopping RECORDING call, RX overlapping TG message Freq " << message.talkgroup << "\u001b[0m"; + BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Stopping RECORDING call, RX overlapping TG message Freq, TG:" << message.talkgroup << "\u001b[0m"; BOOST_LOG_TRIVIAL(info) << "\t - Stopping call because of overlapping Freq"; //call->stop_call(); call->set_state(COMPLETED); @@ -1015,7 +1015,7 @@ void handle_call_grant(TrunkMessage message, System *sys) { // There is an existing call on freq and slot that the new call will be started on. We should stop the older call. The older recorder will // keep writing to the file until it hits a termination flag, so no packets should be dropped. if ((call->get_state() == INACTIVE) && (call->get_talkgroup() != message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { - BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Stopping INACTIVE call, RX overlapping TG message Freq " << message.talkgroup << "\u001b[0m"; + BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Stopping INACTIVE call, RX overlapping TG message Freq TG:" << message.talkgroup << "\u001b[0m"; BOOST_LOG_TRIVIAL(info) << "\t - Stopping call because of overlapping Freq"; //call->stop_call(); call->set_state(COMPLETED); From 973e4adf2155cab6e96cf3b756517f93659e1989 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Sun, 6 Mar 2022 10:23:21 -0500 Subject: [PATCH 24/38] Update transmission_sink.cc --- lib/gr_blocks/transmission_sink.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc index 8f8120f77..69b8d0bda 100644 --- a/lib/gr_blocks/transmission_sink.cc +++ b/lib/gr_blocks/transmission_sink.cc @@ -268,7 +268,7 @@ void transmission_sink::stop_recording() { } if (state == RECORDING) { - BOOST_LOG_TRIVIAL(error) << "stop_recording() - stopping wavfile sink but recorder state is: " << state << std::endl; + BOOST_LOG_TRIVIAL(trace) << "stop_recording() - stopping wavfile sink but recorder state is: " << state << std::endl; } d_current_call = NULL; d_first_work = true; From e82f7d4bbbf0ffbfade2cf963bc55ccfea8d43c0 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Sun, 20 Mar 2022 22:03:01 -0400 Subject: [PATCH 25/38] made logging a trace --- lib/gr_blocks/transmission_sink.cc | 4 ++-- trunk-recorder/main.cc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc index 955338d55..ee664e85e 100644 --- a/lib/gr_blocks/transmission_sink.cc +++ b/lib/gr_blocks/transmission_sink.cc @@ -139,7 +139,7 @@ bool transmission_sink::start_recording(Call *call) { char formattedTalkgroup[62]; snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tStarting wavfile sink SRC ID: " << curr_src_id; + BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tStarting wavfile sink SRC ID: " << curr_src_id; return true; } @@ -495,7 +495,7 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu char formattedTalkgroup[62]; snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tStarting new Transmission \tSrc ID: " << curr_src_id; + BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tStarting new Transmission \tSrc ID: " << curr_src_id; //curr_src_id = d_current_call->get_current_source_id(); record_more_transmissions = false; diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index 8720c6950..455b655bc 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -1067,7 +1067,7 @@ void handle_call_update(TrunkMessage message, System *sys) { // Only a RECORDING call can be set to INACTIVE // We should be safe to set it to RECORDING if it starts to get UPDATE messages call->set_state(RECORDING); - BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Reactivating an INACTIVE Call \u001b[0m"; + BOOST_LOG_TRIVIAL(trace) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Reactivating an INACTIVE Call \u001b[0m"; } //BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Updating Call \u001b[0m"; From 4cc7362186302891951ccc8af5e82661d36ee176 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Wed, 30 Mar 2022 22:03:19 -0400 Subject: [PATCH 26/38] fixes Spike and Error Count --- lib/gr_blocks/transmission_sink.cc | 27 ++++++++++--- lib/gr_blocks/transmission_sink.h | 2 + .../include/op25_repeater/rx_status.h | 4 +- .../lib/p25_frame_assembler_impl.cc | 12 +++++- plugins/openmhz_uploader/openmhz_uploader.cc | 38 +++++++++++++++---- .../call_concluder/call_concluder.cc | 17 ++++++--- .../call_concluder/call_concluder.h | 3 ++ trunk-recorder/global_structs.h | 7 +++- trunk-recorder/main.cc | 2 +- 9 files changed, 87 insertions(+), 25 deletions(-) diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc index ee664e85e..8bd0d103d 100644 --- a/lib/gr_blocks/transmission_sink.cc +++ b/lib/gr_blocks/transmission_sink.cc @@ -124,6 +124,8 @@ bool transmission_sink::start_recording(Call *call) { d_current_call_short_name = call->get_short_name(); d_current_call_capture_dir = call->get_capture_dir(); d_prior_transmission_length = 0; + d_error_count = 0; + d_spike_count = 0; record_more_transmissions = true; this->clear_transmission_list(); @@ -247,12 +249,16 @@ void transmission_sink::end_transmission() { transmission.start_time = d_start_time; // Start time of the Call transmission.stop_time = d_stop_time; // when the Call eneded transmission.sample_count = d_sample_count; + transmission.spike_count = d_spike_count; + transmission.error_count = d_error_count; transmission.length = length_in_seconds(); // length in seconds d_prior_transmission_length = d_prior_transmission_length + transmission.length; strcpy(transmission.filename, current_filename); // Copy the filename strcpy(transmission.base_filename, current_base_filename); this->add_transmission(transmission); d_sample_count = 0; + d_error_count = 0; + d_spike_count = 0; d_first_work = true; curr_src_id = -1; } else { @@ -327,8 +333,10 @@ int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_ } std::vector tags; - pmt::pmt_t this_key(pmt::intern("src_id")); - pmt::pmt_t that_key(pmt::intern("terminate")); + pmt::pmt_t src_id_key(pmt::intern("src_id")); + pmt::pmt_t terminate_key(pmt::intern("terminate")); + pmt::pmt_t spike_count_key(pmt::intern("spike_count")); + pmt::pmt_t error_count_key(pmt::intern("error_count")); //pmt::pmt_t squelch_key(pmt::intern("squelch_eob")); //get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0) + noutput_items); get_tags_in_window(tags, 0, 0, noutput_items); @@ -337,7 +345,7 @@ int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_ for (unsigned int i = 0; i < tags.size(); i++) { //BOOST_LOG_TRIVIAL(info) << "TAG! " << tags[i].key; - if (pmt::eq(this_key, tags[i].key)) { + if (pmt::eq(src_id_key, tags[i].key)) { long src_id = pmt::to_long(tags[i].value); pos = d_sample_count + (tags[i].offset - nitems_read(0)); @@ -367,11 +375,10 @@ int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_ } //BOOST_LOG_TRIVIAL(info) << "Updated Voice Channel source id: " << src_id << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); - } } - if (pmt::eq(that_key, tags[i].key)) { + if (pmt::eq(terminate_key, tags[i].key)) { d_termination_flag = true; pos = d_sample_count + (tags[i].offset - nitems_read(0)); char formattedTalkgroup[62]; @@ -383,6 +390,14 @@ int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_ //BOOST_LOG_TRIVIAL(info) << "TERMINATOR!!"; } + if (pmt::eq(spike_count_key, tags[i].key)) { + d_spike_count = pmt::to_long(tags[i].value); + BOOST_LOG_TRIVIAL(info) << "Spike Count: " << d_spike_count; + } + if (pmt::eq(error_count_key, tags[i].key)) { + d_error_count = pmt::to_long(tags[i].value); + BOOST_LOG_TRIVIAL(info) << "Error Count: " << d_error_count; + } } tags.clear(); @@ -456,7 +471,7 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - BOOST_LOG_TRIVIAL(info) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tTERM - record_more_transmissions = false, setting Recorder state to STOPPED - count: " << d_sample_count; + BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tTERM - record_more_transmissions = false, setting Recorder state to STOPPED - count: " << d_sample_count; //BOOST_LOG_TRIVIAL(trace) << "Call completed - putting recorder into state Completed - we had samples"; state = STOPPED; diff --git a/lib/gr_blocks/transmission_sink.h b/lib/gr_blocks/transmission_sink.h index 76c6cc0cb..a776cec07 100644 --- a/lib/gr_blocks/transmission_sink.h +++ b/lib/gr_blocks/transmission_sink.h @@ -57,6 +57,8 @@ class BLOCKS_API transmission_sink : virtual public sync_block bool d_termination_flag; time_t d_start_time; time_t d_stop_time; + long d_spike_count; + long d_error_count; long curr_src_id; char current_filename[255]; char current_base_filename[255]; diff --git a/lib/op25_repeater/include/op25_repeater/rx_status.h b/lib/op25_repeater/include/op25_repeater/rx_status.h index 79e64b584..d7092751a 100644 --- a/lib/op25_repeater/include/op25_repeater/rx_status.h +++ b/lib/op25_repeater/include/op25_repeater/rx_status.h @@ -4,8 +4,8 @@ #include struct Rx_Status{ double total_len; - double error_count; - double spike_count; + long error_count; + long spike_count; time_t last_update; }; #endif diff --git a/lib/op25_repeater/lib/p25_frame_assembler_impl.cc b/lib/op25_repeater/lib/p25_frame_assembler_impl.cc index aa7d8d656..e6322ec63 100644 --- a/lib/op25_repeater/lib/p25_frame_assembler_impl.cc +++ b/lib/op25_repeater/lib/p25_frame_assembler_impl.cc @@ -230,9 +230,19 @@ p25_frame_assembler_impl::general_work (int noutput_items, } else { if (terminate_call) { - add_item_tag(0, nitems_written(0), pmt::intern("terminate"), pmt::from_long(1), d_tag_src); + add_item_tag(0, nitems_written(0), pmt::intern("terminate"), pmt::from_long(1), d_tag_src ); + + Rx_Status status = p1fdma.get_rx_status(); + + // If something was recorded, send the number of Errors and Spikes that were counted during that period + if (status.total_len > 0 ) { + add_item_tag(0, nitems_written(0), pmt::intern("spike_count"), pmt::from_long(status.spike_count), d_tag_src); + add_item_tag(0, nitems_written(0), pmt::intern("error_count"), pmt::from_long(status.error_count), d_tag_src); + p1fdma.reset_rx_status(); + } std::fill(out, out + 1, 0); amt_produce = 1; + //BOOST_LOG_TRIVIAL(info) << "Call Terminated, NO amount produced: " << amt_produce << " SRC: " << p1fdma.get_curr_src_id() << " n written " << nitems_written(0); } if (silence_frame_count > 0) { diff --git a/plugins/openmhz_uploader/openmhz_uploader.cc b/plugins/openmhz_uploader/openmhz_uploader.cc index c8738ddf9..42a818636 100644 --- a/plugins/openmhz_uploader/openmhz_uploader.cc +++ b/plugins/openmhz_uploader/openmhz_uploader.cc @@ -61,12 +61,6 @@ class Openmhz_Uploader : public Plugin_Api { source_list << std::fixed << std::setprecision(2); source_list << "["; - char formattedTalkgroup[62]; - snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, call_info.talkgroup, 0x1B); - std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - time_t start_time = call_info.start_time; - - if (call_info.transmission_source_list.size() != 0) { for (int i = 0; i < call_info.transmission_source_list.size(); i++) { @@ -82,6 +76,35 @@ class Openmhz_Uploader : public Plugin_Api { source_list << "]"; } + + std::ostringstream freq_list; + std::string freq_list_string; + freq_list << std::fixed << std::setprecision(2); + freq_list << "["; + + if (call_info.transmission_error_list.size() != 0) { + for (std::size_t i = 0; i < call_info.transmission_error_list.size(); i++) { + freq_list << "{\"freq\": " << std::fixed << std::setprecision(0) << call_info.freq << ", \"time\": " << call_info.transmission_error_list[i].time << ", \"pos\": " << std::fixed << std::setprecision(2) << call_info.transmission_error_list[i].position << ", \"len\": " << call_info.transmission_error_list[i].total_len << ", \"error_count\": \"" << std::setprecision(0) <(formattedTalkgroup); + time_t start_time = call_info.start_time; + + + //BOOST_LOG_TRIVIAL(error) << "Got source list: " << source_list.str(); CURL *curl; CURLMcode res; @@ -91,6 +114,7 @@ class Openmhz_Uploader : public Plugin_Api { freq_string = freq.str(); source_list_string = source_list.str(); + freq_list_string = freq_list.str(); call_length_string = call_length.str(); struct curl_httppost *formpost = NULL; @@ -156,7 +180,7 @@ class Openmhz_Uploader : public Plugin_Api { curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "freq_list", - CURLFORM_COPYCONTENTS, "[]", + CURLFORM_COPYCONTENTS, freq_list_string.c_str(), CURLFORM_END); curl = curl_easy_init(); diff --git a/trunk-recorder/call_concluder/call_concluder.cc b/trunk-recorder/call_concluder/call_concluder.cc index 4b369db0e..b61bd36d1 100644 --- a/trunk-recorder/call_concluder/call_concluder.cc +++ b/trunk-recorder/call_concluder/call_concluder.cc @@ -82,17 +82,21 @@ int create_call_json(Call_Data_t call_info) { } json_file << "],\n"; } - - json_file << "\"freqList\": ["; - json_file << "{ \"freq\": " << std::fixed << std::setprecision(0) << call_info.freq << ", \"time\": " << call_info.start_time << ", \"pos\": 0.0, \"len\": " << call_info.length << ", \"error_count\": 0.0, \"spike_count\": 0.0}"; - json_file << "],\n"; + json_file << "\"freqList\": [ "; + for (std::size_t i = 0; i < call_info.transmission_error_list.size(); i++) { + if (i != 0) { + json_file << ", "; + } + json_file << "{\"freq\": " << std::fixed << std::setprecision(0) << call_info.freq << ", \"time\": " << call_info.transmission_error_list[i].time << ", \"pos\": " << std::fixed << std::setprecision(2) << call_info.transmission_error_list[i].position << ", \"len\": " << call_info.transmission_error_list[i].total_len << ", \"error_count\": \"" << std::fixed << std::setprecision(0) << call_info.transmission_error_list[i].error_count << "\", \"spike_count\": \"" << call_info.transmission_error_list[i].spike_count << "\"}"; + } + json_file << " ],\n"; json_file << "\"srcList\": [ "; for (std::size_t i = 0; i < call_info.transmission_source_list.size(); i++) { if (i != 0) { json_file << ", "; } - json_file << "{\"src\": " << std::fixed << call_info.transmission_source_list[i].source << ", \"time\": " << call_info.transmission_source_list[i].time << ", \"pos\": " << call_info.transmission_source_list[i].position << ", \"emergency\": " << call_info.transmission_source_list[i].emergency << ", \"signal_system\": \"" << call_info.transmission_source_list[i].signal_system << "\", \"tag\": \"" << call_info.transmission_source_list[i].tag << "\"}"; + json_file << "{\"src\": " << std::fixed << call_info.transmission_source_list[i].source << ", \"time\": " << call_info.transmission_source_list[i].time << ", \"pos\": " << std::fixed << std::setprecision(2) << call_info.transmission_source_list[i].position << ", \"emergency\": " << call_info.transmission_source_list[i].emergency << ", \"signal_system\": \"" << call_info.transmission_source_list[i].signal_system << "\", \"tag\": \"" << call_info.transmission_source_list[i].tag << "\"}"; } json_file << " ]\n"; json_file << "}\n"; @@ -291,8 +295,9 @@ Call_Data_t Call_Concluder::create_call_data(Call *call, System *sys, Config con UnitTag *unit_tag = sys->find_unit_tag(t.source); std::string tag = (unit_tag == NULL || unit_tag->tag.empty() ? "" : unit_tag->tag); Call_Source call_source = {t.source, t.start_time, total_length, false, "", tag}; - + Call_Error call_error = {t.start_time,total_length,t.length, t.error_count, t.spike_count}; call_info.transmission_source_list.push_back(call_source); + call_info.transmission_error_list.push_back(call_error); total_length = total_length + t.length; } diff --git a/trunk-recorder/call_concluder/call_concluder.h b/trunk-recorder/call_concluder/call_concluder.h index 9999d0117..0aa6e5982 100644 --- a/trunk-recorder/call_concluder/call_concluder.h +++ b/trunk-recorder/call_concluder/call_concluder.h @@ -32,6 +32,8 @@ struct Call_Data_t { double freq; long start_time; long stop_time; + long error_count; + long spike_count; bool encrypted; bool emergency; bool audio_archive; @@ -53,6 +55,7 @@ struct Call_Data_t { bool phase2_tdma; std::vector transmission_source_list; + std::vector transmission_error_list; std::vector transmission_list; Call_Data_Status status; diff --git a/trunk-recorder/global_structs.h b/trunk-recorder/global_structs.h index b86a1e80e..33b73ebd4 100644 --- a/trunk-recorder/global_structs.h +++ b/trunk-recorder/global_structs.h @@ -7,6 +7,8 @@ struct Transmission { long start_time; long stop_time; long sample_count; + long spike_count; + long error_count; double freq; double length; char filename[255]; @@ -56,8 +58,9 @@ struct Call_Freq { }; struct Call_Error { - double freq; - double sample_count; + long time; + double position; + double total_len; double error_count; double spike_count; }; diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index 41d33ce53..c2074f0fc 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -868,7 +868,7 @@ void manage_calls() { // if the recorder has simply been going for a while and a call is inactive, end things if (call->since_last_update() > 5) { //BOOST_LOG_TRIVIAL(info) << "Recorder state: " << recorder->get_state(); - BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Removing call that has been inactive for more than 5 Sec \u001b[0m Rec last write: " << recorder->since_last_write() << " State: " << recorder->get_state(); + BOOST_LOG_TRIVIAL(trace) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Removing call that has been inactive for more than 5 Sec \u001b[0m Rec last write: " << recorder->since_last_write() << " State: " << recorder->get_state(); // since the Call state is INACTIVE and the Recorder has been going on for a while, we can now // set the Call state to COMPLETED From 0f87f2137b559d4454de19b01b6240a6e2851718 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Wed, 30 Mar 2022 22:12:58 -0400 Subject: [PATCH 27/38] Removing the old rx_status code --- .../op25_repeater/p25_frame_assembler.h | 2 -- .../lib/p25_frame_assembler_impl.cc | 9 ------- .../lib/p25_frame_assembler_impl.h | 2 -- trunk-recorder/call.cc | 24 ------------------- trunk-recorder/recorders/dmr_recorder.cc | 6 ----- trunk-recorder/recorders/dmr_recorder.h | 1 - trunk-recorder/recorders/p25_recorder.cc | 13 ---------- trunk-recorder/recorders/p25_recorder.h | 1 - .../recorders/p25_recorder_decode.cc | 6 ----- .../recorders/p25_recorder_decode.h | 2 -- trunk-recorder/recorders/recorder.cc | 6 ----- trunk-recorder/recorders/recorder.h | 4 ---- 12 files changed, 76 deletions(-) diff --git a/lib/op25_repeater/include/op25_repeater/p25_frame_assembler.h b/lib/op25_repeater/include/op25_repeater/p25_frame_assembler.h index 1d261a719..781764410 100644 --- a/lib/op25_repeater/include/op25_repeater/p25_frame_assembler.h +++ b/lib/op25_repeater/include/op25_repeater/p25_frame_assembler.h @@ -60,8 +60,6 @@ namespace gr { virtual void set_debug(int debug) {} virtual void reset_timer() {} virtual void set_phase2_tdma(bool p) {} - virtual void reset_rx_status() {} - virtual Rx_Status get_rx_status() {Rx_Status rx_status; return rx_status; } virtual void clear() {}; virtual void clear_silence_frame_count() {}; }; diff --git a/lib/op25_repeater/lib/p25_frame_assembler_impl.cc b/lib/op25_repeater/lib/p25_frame_assembler_impl.cc index e6322ec63..f8b2d412e 100644 --- a/lib/op25_repeater/lib/p25_frame_assembler_impl.cc +++ b/lib/op25_repeater/lib/p25_frame_assembler_impl.cc @@ -150,15 +150,6 @@ p25_frame_assembler_impl::forecast(int nof_output_items, gr_vector_int &nof_inpu std::fill(&nof_input_items_reqd[0], &nof_input_items_reqd[nof_inputs], nof_samples_reqd); } - - void p25_frame_assembler_impl::reset_rx_status() { - p1fdma.reset_rx_status(); - } - - Rx_Status p25_frame_assembler_impl::get_rx_status() { - return p1fdma.get_rx_status(); - } - void p25_frame_assembler_impl::clear() { p1fdma.clear(); } diff --git a/lib/op25_repeater/lib/p25_frame_assembler_impl.h b/lib/op25_repeater/lib/p25_frame_assembler_impl.h index daeaa7d60..6040893a2 100644 --- a/lib/op25_repeater/lib/p25_frame_assembler_impl.h +++ b/lib/op25_repeater/lib/p25_frame_assembler_impl.h @@ -74,8 +74,6 @@ namespace gr { void p25p2_queue_msg(int duid); void set_phase2_tdma(bool p); - void reset_rx_status(); - Rx_Status get_rx_status(); public: diff --git a/trunk-recorder/call.cc b/trunk-recorder/call.cc index 36a5bf7cb..6933ad98e 100644 --- a/trunk-recorder/call.cc +++ b/trunk-recorder/call.cc @@ -121,14 +121,6 @@ void Call::conclude_call() { if (state == COMPLETED) { final_length = recorder->get_current_length(); - if (freq_count > 0) { - Rx_Status rx_status = recorder->get_rx_status(); - if (rx_status.last_update > 0) - stop_time = rx_status.last_update; - freq_list[freq_count - 1].total_len = rx_status.total_len; - freq_list[freq_count - 1].spike_count = rx_status.spike_count; - freq_list[freq_count - 1].error_count = rx_status.error_count; - } if (!recorder) { BOOST_LOG_TRIVIAL(error) << "Call::end_call() State is recording, but no recorder assigned!"; } @@ -211,15 +203,6 @@ System *Call::get_system() { void Call::set_freq(double f) { if (f != curr_freq) { - - // if there call is being recorded and it isn't the first time the freq is being set - if (recorder && (freq_count > 0)) { - Rx_Status rx_status = recorder->get_rx_status(); - freq_list[freq_count - 1].total_len = rx_status.total_len; - freq_list[freq_count - 1].spike_count = rx_status.spike_count; - freq_list[freq_count - 1].error_count = rx_status.error_count; - } - curr_freq = f; } } @@ -368,15 +351,8 @@ bool Call::update(TrunkMessage message) { } int Call::since_last_update() { - /*long last_rx; - if (get_recorder() && (last_rx = recorder->get_rx_status().last_update)) { - BOOST_LOG_TRIVIAL(trace) << "temp.last_update: " << last_rx << " diff: " << time(NULL) - last_rx; - return time(NULL) - last_rx; - //last_update = temp.last_update; - } else {*/ BOOST_LOG_TRIVIAL(trace) << "last_update: " << last_update << " diff: " << time(NULL) - last_update; return time(NULL) - last_update; - //} } long Call::elapsed() { diff --git a/trunk-recorder/recorders/dmr_recorder.cc b/trunk-recorder/recorders/dmr_recorder.cc index 3b69a3eb5..9515662f5 100644 --- a/trunk-recorder/recorders/dmr_recorder.cc +++ b/trunk-recorder/recorders/dmr_recorder.cc @@ -376,7 +376,6 @@ void dmr_recorder::tune_offset(double f) { lo->set_frequency(freq); } - //op25_frame_assembler->reset_rx_status(); } void dmr_recorder::set_record_more_transmissions(bool more) { @@ -403,9 +402,6 @@ std::vector dmr_recorder::get_transmission_list() { } -Rx_Status dmr_recorder::get_rx_status() { - return op25_frame_assembler->get_rx_status(); -} void dmr_recorder::stop() { @@ -419,8 +415,6 @@ void dmr_recorder::stop() { valve->set_enabled(false); wav_sink_slot0->stop_recording(); wav_sink_slot1->stop_recording(); - //op25_frame_assembler->reset_rx_status(); - } else { BOOST_LOG_TRIVIAL(error) << "dmr_recorder.cc: Trying to Stop an Inactive Logger!!!"; } diff --git a/trunk-recorder/recorders/dmr_recorder.h b/trunk-recorder/recorders/dmr_recorder.h index ec6dc9be5..190d1fb40 100644 --- a/trunk-recorder/recorders/dmr_recorder.h +++ b/trunk-recorder/recorders/dmr_recorder.h @@ -125,7 +125,6 @@ class dmr_recorder : public gr::hier_block2, public Recorder { bool is_squelched(); std::vector get_transmission_list(); State get_state(); - Rx_Status get_rx_status(); int lastupdate(); long elapsed(); Source *get_source(); diff --git a/trunk-recorder/recorders/p25_recorder.cc b/trunk-recorder/recorders/p25_recorder.cc index de2f21422..e51771c4a 100644 --- a/trunk-recorder/recorders/p25_recorder.cc +++ b/trunk-recorder/recorders/p25_recorder.cc @@ -359,10 +359,8 @@ void p25_recorder::tune_offset(double f) { if (!qpsk_mod) { fsk4_demod->reset(); - fsk4_p25_decode->reset_rx_status(); } else { qpsk_demod->reset(); - qpsk_p25_decode->reset_rx_status(); } } @@ -382,15 +380,6 @@ std::vector p25_recorder::get_transmission_list() { } } -Rx_Status p25_recorder::get_rx_status() { - if (qpsk_mod) { - return qpsk_p25_decode->get_rx_status(); - } else { - return fsk4_p25_decode->get_rx_status(); - } -} - - void p25_recorder::stop() { if (state == ACTIVE) { if (qpsk_mod) { @@ -405,10 +394,8 @@ void p25_recorder::stop() { valve->set_enabled(false); if (qpsk_mod) { qpsk_p25_decode->stop(); - qpsk_p25_decode->reset_rx_status(); } else { fsk4_p25_decode->stop(); - fsk4_p25_decode->reset_rx_status(); } } else { BOOST_LOG_TRIVIAL(error) << "p25_recorder.cc: Trying to Stop an Inactive Logger!!!"; diff --git a/trunk-recorder/recorders/p25_recorder.h b/trunk-recorder/recorders/p25_recorder.h index e39c03b9b..c24d29ee1 100644 --- a/trunk-recorder/recorders/p25_recorder.h +++ b/trunk-recorder/recorders/p25_recorder.h @@ -104,7 +104,6 @@ class p25_recorder : public gr::hier_block2, public Recorder { bool is_squelched(); std::vector get_transmission_list(); State get_state(); - Rx_Status get_rx_status(); int lastupdate(); long elapsed(); Source *get_source(); diff --git a/trunk-recorder/recorders/p25_recorder_decode.cc b/trunk-recorder/recorders/p25_recorder_decode.cc index f8a288ac1..af2f06ec4 100644 --- a/trunk-recorder/recorders/p25_recorder_decode.cc +++ b/trunk-recorder/recorders/p25_recorder_decode.cc @@ -64,13 +64,7 @@ void p25_recorder_decode::switch_tdma(bool phase2_tdma) { op25_frame_assembler->set_phase2_tdma(phase2_tdma); } -void p25_recorder_decode::reset_rx_status() { - op25_frame_assembler->reset_rx_status(); -} -Rx_Status p25_recorder_decode::get_rx_status() { - return op25_frame_assembler->get_rx_status(); -} void p25_recorder_decode::initialize( int silence_frames) { //OP25 Slicer const float l[] = {-2.0, 0.0, 2.0, 4.0}; diff --git a/trunk-recorder/recorders/p25_recorder_decode.h b/trunk-recorder/recorders/p25_recorder_decode.h index c115dc1a4..77917f375 100644 --- a/trunk-recorder/recorders/p25_recorder_decode.h +++ b/trunk-recorder/recorders/p25_recorder_decode.h @@ -62,8 +62,6 @@ class p25_recorder_decode : public gr::hier_block2 { void switch_tdma(bool phase2_tdma); void start(Call *call); double since_last_write(); - void reset_rx_status(); - Rx_Status get_rx_status(); void stop(); int tdma_slot; bool delay_open; diff --git a/trunk-recorder/recorders/recorder.cc b/trunk-recorder/recorders/recorder.cc index 17540d468..a8354d3f0 100644 --- a/trunk-recorder/recorders/recorder.cc +++ b/trunk-recorder/recorders/recorder.cc @@ -15,11 +15,5 @@ boost::property_tree::ptree Recorder::get_stats() { node.put("count", recording_count); node.put("duration", recording_duration); node.put("state", get_state()); - - Rx_Status status = get_rx_status(); - node.put("status_len", status.total_len); - node.put("status_error", status.error_count); - node.put("status_spike", status.spike_count); - return node; } \ No newline at end of file diff --git a/trunk-recorder/recorders/recorder.h b/trunk-recorder/recorders/recorder.h index 5a0ca1933..19ad86bd9 100644 --- a/trunk-recorder/recorders/recorder.h +++ b/trunk-recorder/recorders/recorder.h @@ -91,10 +91,6 @@ class Recorder { virtual long get_talkgroup() { return 0; }; virtual void set_record_more_transmissions(bool more){}; virtual State get_state() { return INACTIVE; }; - virtual Rx_Status get_rx_status() { - Rx_Status rx_status = {0, 0, 0, 0}; - return rx_status; - } virtual std::string get_type() { return type; } virtual bool is_active() { return false; }; virtual bool is_analog() { return false; }; From 6b73a0fb0f21730b87b1a9ad71c985d93f683cf1 Mon Sep 17 00:00:00 2001 From: Nick M Date: Thu, 31 Mar 2022 15:49:53 -0400 Subject: [PATCH 28/38] Report Errors/Spikes to Rdio Scanner API-compliant fix for Rdio Scanner to see transmission errors and spikes. --- .../rdioscanner_uploader.cc | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/plugins/rdioscanner_uploader/rdioscanner_uploader.cc b/plugins/rdioscanner_uploader/rdioscanner_uploader.cc index 3910552fd..f96f4de4b 100644 --- a/plugins/rdioscanner_uploader/rdioscanner_uploader.cc +++ b/plugins/rdioscanner_uploader/rdioscanner_uploader.cc @@ -122,6 +122,28 @@ class Rdio_Scanner_Uploader : public Plugin_Api { patch_list << "]"; } + + std::ostringstream freq_list; + std::string freq_list_string; + freq_list << std::fixed << std::setprecision(2); + freq_list << "["; + + if (call_info.transmission_error_list.size() != 0) { + for (std::size_t i = 0; i < call_info.transmission_error_list.size(); i++) { + freq_list << "{\"freq\": " << std::fixed << std::setprecision(0) << call_info.freq << ", \"time\": " << call_info.transmission_error_list[i].time << ", \"pos\": " << std::fixed << std::setprecision(2) << call_info.transmission_error_list[i].position << ", \"len\": " << call_info.transmission_error_list[i].total_len << ", \"errorCount\": " << std::setprecision(0) < Date: Sun, 3 Apr 2022 11:02:33 -0400 Subject: [PATCH 29/38] Create CALL-HANDLING.md --- docs/notes/CALL-HANDLING.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 docs/notes/CALL-HANDLING.md diff --git a/docs/notes/CALL-HANDLING.md b/docs/notes/CALL-HANDLING.md new file mode 100644 index 000000000..86ca5779f --- /dev/null +++ b/docs/notes/CALL-HANDLING.md @@ -0,0 +1,26 @@ +```mermaid +flowchart TD + subgraph Control Channel + A[Control Channel] -->|GRANT| B["handle_call_grant()"] + B --> C{Existing Call on Freq?} + C -.->|Yes| D{Same Talkgroup?} + C -.->|No| G["new Call()"] + D -.->|Yes| E["call->set_record_more_transmissions()"] + D -.->|No| F[Delete Existing Call] + F -.-> G + G -.-> H["start_recording()"] + E -.-> I["transmission_sink->"] + end + subgraph Voice Channel + A1[Voice Channel] -->|Samples| B1[Transmission Sink] + B1 -.-> C1{State} + C1 -.->|STOPPED| D1[Drop Samples] + C1 -.->|IDLE| E1{d_first_work} + C1 -.->|RECORDING| E1 + E1 -.->|True| F1["Setup files\nrecord_more_transmissions = false;\nd_first_work = false;"] + E1 -.->|False| G1[Write Samples] + F1 -.-> G1 + end + + +``` From 8de5ba3de402c18d9cf6c182551760e407b098bb Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Sun, 3 Apr 2022 15:49:02 -0400 Subject: [PATCH 30/38] Update CALL-HANDLING.md --- docs/notes/CALL-HANDLING.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/docs/notes/CALL-HANDLING.md b/docs/notes/CALL-HANDLING.md index 86ca5779f..ad00454db 100644 --- a/docs/notes/CALL-HANDLING.md +++ b/docs/notes/CALL-HANDLING.md @@ -1,5 +1,6 @@ ```mermaid flowchart TD + E -.-> L1 subgraph Control Channel A[Control Channel] -->|GRANT| B["handle_call_grant()"] B --> C{Existing Call on Freq?} @@ -9,17 +10,20 @@ flowchart TD D -.->|No| F[Delete Existing Call] F -.-> G G -.-> H["start_recording()"] - E -.-> I["transmission_sink->"] + end subgraph Voice Channel - A1[Voice Channel] -->|Samples| B1[Transmission Sink] - B1 -.-> C1{State} + A1[Voice Channel] --> B1[Transmission Sink] + B1 -.->|Samples| C1{State} C1 -.->|STOPPED| D1[Drop Samples] - C1 -.->|IDLE| E1{d_first_work} - C1 -.->|RECORDING| E1 - E1 -.->|True| F1["Setup files\nrecord_more_transmissions = false;\nd_first_work = false;"] - E1 -.->|False| G1[Write Samples] + C1 -.->|IDLE| F1["Setup files\nrecord_more_transmissions = false;\nd_first_work = false;\nstate = RECORDING"] + C1 -.->|RECORDING| G1[Write Samples] F1 -.-> G1 + B1 -.->|TERMINATOR| H1["End Transmission"] + H1 -.-> I1{"record_more_transmissions"} + I1 -.->|False| J1["state = STOPPED"] + I1 -.->|True| K1["state = IDLE"] + L1["set_record_more_transmissions()"] -.-> M1["record_mode_transmissions = True"] end From fe6240fcf736f7f5a74f3d21d062fb43f6756f05 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Sun, 3 Apr 2022 15:57:19 -0400 Subject: [PATCH 31/38] Restructured Transmission Sink --- lib/gr_blocks/transmission_sink.cc | 130 +++++++++++++++++------------ trunk-recorder/main.cc | 4 +- 2 files changed, 78 insertions(+), 56 deletions(-) diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc index 8bd0d103d..4390acee5 100644 --- a/lib/gr_blocks/transmission_sink.cc +++ b/lib/gr_blocks/transmission_sink.cc @@ -66,14 +66,13 @@ transmission_sink::transmission_sink( io_signature::make(1, n_channels, sizeof(int16_t)), io_signature::make(0, 0, 0)), d_sample_rate(sample_rate), d_nchans(n_channels), - d_fp(0), d_current_call(NULL) { + d_current_call(NULL), d_fp(0) { if ((bits_per_sample != 8) && (bits_per_sample != 16)) { throw std::runtime_error("Invalid bits per sample (supports 8 and 16)"); } d_bytes_per_sample = bits_per_sample / 8; d_sample_count = 0; d_slot = -1; - d_first_work = true; d_termination_flag = false; state = AVAILABLE; } @@ -132,7 +131,6 @@ bool transmission_sink::start_recording(Call *call) { d_conventional = call->is_conventional(); curr_src_id = d_current_call->get_current_source_id(); d_sample_count = 0; - d_first_work = true; // when a wav_sink first gets associated with a call, set its lifecycle to idle; state = IDLE; @@ -181,7 +179,6 @@ bool transmission_sink::open_internal(const char *filename) { } d_sample_count = 0; - d_first_work = true; if (!wavheader_write(d_fp, d_sample_rate, d_nchans, d_bytes_per_sample)) { fprintf(stderr, "[%s] could not write to WAV file\n", __FILE__); @@ -229,7 +226,6 @@ void transmission_sink::set_source(long src) { state = STOPPED; } else { state = IDLE; - d_first_work = true; }*/ } curr_src_id = src; @@ -259,7 +255,6 @@ void transmission_sink::end_transmission() { d_sample_count = 0; d_error_count = 0; d_spike_count = 0; - d_first_work = true; curr_src_id = -1; } else { BOOST_LOG_TRIVIAL(error) << "Trying to end a Transmission, but the sample_count is 0" << std::endl; @@ -277,7 +272,6 @@ void transmission_sink::stop_recording() { BOOST_LOG_TRIVIAL(trace) << "stop_recording() - stopping wavfile sink but recorder state is: " << state << std::endl; } d_current_call = NULL; - d_first_work = true; d_termination_flag = false; state = AVAILABLE; } @@ -368,7 +362,6 @@ int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_ state = STOPPED; } else { state = IDLE; - d_first_work = true; }*/ curr_src_id = src_id; @@ -390,13 +383,25 @@ int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_ //BOOST_LOG_TRIVIAL(info) << "TERMINATOR!!"; } - if (pmt::eq(spike_count_key, tags[i].key)) { - d_spike_count = pmt::to_long(tags[i].value); - BOOST_LOG_TRIVIAL(info) << "Spike Count: " << d_spike_count; - } - if (pmt::eq(error_count_key, tags[i].key)) { - d_error_count = pmt::to_long(tags[i].value); - BOOST_LOG_TRIVIAL(info) << "Error Count: " << d_error_count; + + // Only process Spike and Error Count tags if the sink is currently recording + if (state == RECORDING) { + if (pmt::eq(spike_count_key, tags[i].key)) { + d_spike_count = pmt::to_long(tags[i].value); + char formattedTalkgroup[62]; + snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); + std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); + + BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tSpike Count: " << d_spike_count << " pos: " << pos << " offset: " << tags[i].offset; + } + if (pmt::eq(error_count_key, tags[i].key)) { + d_error_count = pmt::to_long(tags[i].value); + char formattedTalkgroup[62]; + snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); + std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); + + BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tError Count: " << d_error_count << " pos: " << pos << " offset: " << tags[i].offset; + } } } tags.clear(); @@ -421,11 +426,10 @@ void transmission_sink::add_transmission(Transmission t) { } void transmission_sink::set_record_more_transmissions(bool more) { - // If a Recorder is STOPPED and record_more is false, prep it so it is ready to go. + // If a Recorder is STOPPED and record_more_transmissions is false, prep it so it is ready to go. if ((record_more_transmissions == false) && (more == true) && (state == STOPPED)) { //BOOST_LOG_TRIVIAL(info) << "wav - setting record_more to true, sample count: " << d_sample_count; d_sample_count = 0; - d_first_work = true; state = IDLE; } record_more_transmissions = more; @@ -444,7 +448,7 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu // block int n_in_chans = input_items.size(); int16_t sample_buf_s; - int nwritten; + int nwritten=0; // A Termination Tag was receive if (d_termination_flag) { @@ -461,33 +465,47 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu // Check to see if we have started a Transmission yet // A Terminator with any Transmission started shouldn't do anything... right? - //if (d_first_work == false) { - // Another GRANT message has arrived. - if (d_conventional || (record_more_transmissions == true)) { - state = IDLE; - d_first_work = true; - } else { - char formattedTalkgroup[62]; - snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); - std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - - BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tTERM - record_more_transmissions = false, setting Recorder state to STOPPED - count: " << d_sample_count; - //BOOST_LOG_TRIVIAL(trace) << "Call completed - putting recorder into state Completed - we had samples"; - - state = STOPPED; - } - //} - + // Another GRANT message has arrived. + if (d_conventional || (record_more_transmissions == true)) { + state = IDLE; + } else { + char formattedTalkgroup[62]; + snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); + std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); + + BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tTERM - record_more_transmissions = false, setting Recorder state to STOPPED - count: " << d_sample_count; + //BOOST_LOG_TRIVIAL(trace) << "Call completed - putting recorder into state Completed - we had samples"; + + state = STOPPED; + } d_termination_flag = false; + + if (noutput_items > 1) { + char formattedTalkgroup[62]; + snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); + std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); + BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tTERM - skipped: " << noutput_items; + + } return noutput_items; } - if (d_first_work) { + + + if (state == IDLE) { + if (!record_more_transmissions) { + char formattedTalkgroup[62]; + snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); + std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); + + BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tWAV - Weird! State was IDLE but record_more_transmissions was FALSE - count: " << d_sample_count; + + } if (d_fp) { // if we are already recording a file for this call, close it before starting a new one. - BOOST_LOG_TRIVIAL(info) << "WAV - Weird! we have an existing FP, but d_first_work was true: " << current_filename << std::endl; + BOOST_LOG_TRIVIAL(info) << "WAV - Weird! we have an existing FP, but STATE was IDLE: " << current_filename << std::endl; close_wav(false); } @@ -514,7 +532,7 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu //curr_src_id = d_current_call->get_current_source_id(); record_more_transmissions = false; - d_first_work = false; + state = RECORDING; } if (!d_fp) // drop output on the floor @@ -523,28 +541,32 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu return noutput_items; } - for (nwritten = 0; nwritten < noutput_items; nwritten++) { - for (int chan = 0; chan < d_nchans; chan++) { - // Write zeros to channels which are in the WAV file - // but don't have any inputs here - if (chan < n_in_chans) { - int16_t **in = (int16_t **)&input_items[0]; - sample_buf_s = in[chan][nwritten]; - } else { - sample_buf_s = 0; - } + if (state == RECORDING) { + for (nwritten = 0; nwritten < noutput_items; nwritten++) { + for (int chan = 0; chan < d_nchans; chan++) { + // Write zeros to channels which are in the WAV file + // but don't have any inputs here + if (chan < n_in_chans) { + int16_t **in = (int16_t **)&input_items[0]; + sample_buf_s = in[chan][nwritten]; + } else { + sample_buf_s = 0; + } - wav_write_sample(d_fp, sample_buf_s, d_bytes_per_sample); + wav_write_sample(d_fp, sample_buf_s, d_bytes_per_sample); - d_sample_count++; + d_sample_count++; + } } } - if (nwritten > 0) { - state = RECORDING; + if (nwritten < noutput_items) { + char formattedTalkgroup[62]; + snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); + std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); + BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tFailed to Write! Wrote: " << nwritten << " of " << noutput_items; } - // fflush (d_fp); // this is added so unbuffered content is written. - return nwritten; + return noutput_items; } void transmission_sink::set_bits_per_sample(int bits_per_sample) { diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index c2074f0fc..1577ccc2a 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -987,7 +987,7 @@ void handle_call_grant(TrunkMessage message, System *sys) { // There is an existing call on freq and slot that the new call will be started on. We should stop the older call. The older recorder will // keep writing to the file until it hits a termination flag, so no packets should be dropped. if ((call->get_state() == RECORDING) && (call->get_talkgroup() != message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { - BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Stopping RECORDING call, RX overlapping TG message Freq, TG:" << message.talkgroup << "\u001b[0m"; + BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36mStopping RECORDING call, RX overlapping TG message Freq, TG:" << message.talkgroup << "\u001b[0m"; BOOST_LOG_TRIVIAL(info) << "\t - Stopping call because of overlapping Freq"; //call->stop_call(); call->set_state(COMPLETED); @@ -1000,7 +1000,7 @@ void handle_call_grant(TrunkMessage message, System *sys) { // There is an existing call on freq and slot that the new call will be started on. We should stop the older call. The older recorder will // keep writing to the file until it hits a termination flag, so no packets should be dropped. if ((call->get_state() == INACTIVE) && (call->get_talkgroup() != message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { - BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Stopping INACTIVE call, RX overlapping TG message Freq TG:" << message.talkgroup << "\u001b[0m"; + BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36mStopping INACTIVE call, RX overlapping TG message Freq TG:" << message.talkgroup << "\u001b[0m"; BOOST_LOG_TRIVIAL(info) << "\t - Stopping call because of overlapping Freq"; //call->stop_call(); call->set_state(COMPLETED); From 3026c13395058c6a473548ef2a92996de17d0ac4 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Sun, 3 Apr 2022 15:57:24 -0400 Subject: [PATCH 32/38] Update CALL-HANDLING.md --- docs/notes/CALL-HANDLING.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/notes/CALL-HANDLING.md b/docs/notes/CALL-HANDLING.md index ad00454db..e9a0ba86f 100644 --- a/docs/notes/CALL-HANDLING.md +++ b/docs/notes/CALL-HANDLING.md @@ -23,7 +23,10 @@ flowchart TD H1 -.-> I1{"record_more_transmissions"} I1 -.->|False| J1["state = STOPPED"] I1 -.->|True| K1["state = IDLE"] - L1["set_record_more_transmissions()"] -.-> M1["record_mode_transmissions = True"] + L1["set_record_more_transmissions()"] -.-> N1{state == STOPPED} + N1 -.->|True| O1["state == IDLE"] + N1 -.->|False| P1["record_mode_transmissions = True"] + O1 -.-> P1 end From a77da4b034e676d3886ba8020b0a884cd46545f0 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Sun, 3 Apr 2022 16:18:10 -0400 Subject: [PATCH 33/38] Update CALL-HANDLING.md --- docs/notes/CALL-HANDLING.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/notes/CALL-HANDLING.md b/docs/notes/CALL-HANDLING.md index e9a0ba86f..f308fab20 100644 --- a/docs/notes/CALL-HANDLING.md +++ b/docs/notes/CALL-HANDLING.md @@ -30,4 +30,15 @@ flowchart TD end +``` +```mermaid +flowchart TD +A[Control Channel] -->|UPDATE| B["handle_call_update()"] +B -.-> C[Find Call] +C -.-> D{"call->state"} +D -.->|COMPLETED| E[Do Nothing] +D -.->|INACTIVE| F["call->state==RECORDING"] +F -.-> G["call->update()"] +D -.->|RECORDING| G + ``` From 0ed9b96bd5522f376f8393c26e4d32a209fadaa5 Mon Sep 17 00:00:00 2001 From: Nick M Date: Sun, 3 Apr 2022 17:34:53 -0400 Subject: [PATCH 34/38] Update main.cc conventional console fixes --- trunk-recorder/main.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index c2074f0fc..b526c0b4b 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -1347,16 +1347,16 @@ bool setup_convetional_channel(System *system, double frequency, long channel_in if (system->has_channel_file()) { Talkgroup *tg = system->find_talkgroup_by_freq(frequency); call = new Call_conventional(tg->number, tg->freq, system, config); + call->set_talkgroup_tag(tg->alpha_tag); } else { call = new Call_conventional(channel_index, frequency, system, config); - BOOST_LOG_TRIVIAL(info) << "[" << system->get_short_name() << "]\tMonitoring Conventional Channel: " << format_freq(frequency) << " Talkgroup: " << channel_index; - } + BOOST_LOG_TRIVIAL(info) << "[" << system->get_short_name() << "]\tMonitoring " << system->get_system_type() << " channel: " << format_freq(frequency) << " Talkgroup: " << channel_index; if (system->get_system_type() == "conventional") { analog_recorder_sptr rec; rec = source->create_conventional_recorder(tb); rec->start(call); - call->set_is_analog(true); + call->set_is_analog(true); call->set_recorder((Recorder *)rec.get()); call->set_state(RECORDING); system->add_conventional_recorder(rec); From f7819397117da2d7353aeceb16d2aa7ee44ba8e1 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Mon, 4 Apr 2022 21:52:16 -0400 Subject: [PATCH 35/38] double checked the code --- lib/gr_blocks/transmission_sink.cc | 62 ++++++++++--------- .../lib/p25_frame_assembler_impl.cc | 30 ++++----- lib/op25_repeater/lib/p25p1_fdma.cc | 5 +- trunk-recorder/main.cc | 23 +++++-- 4 files changed, 67 insertions(+), 53 deletions(-) diff --git a/lib/gr_blocks/transmission_sink.cc b/lib/gr_blocks/transmission_sink.cc index 4390acee5..733c2dd3a 100644 --- a/lib/gr_blocks/transmission_sink.cc +++ b/lib/gr_blocks/transmission_sink.cc @@ -319,7 +319,7 @@ int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_ char formattedTalkgroup[62]; snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - BOOST_LOG_TRIVIAL(error) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tDropping samples - Recorder state is: " << format_state(this->state); + BOOST_LOG_TRIVIAL(error) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tDropping " << noutput_items << " samples - Recorder state is: " << format_state(this->state); //BOOST_LOG_TRIVIAL(info) << "WAV - state is: " << format_state(this->state) << "\t Dropping samples: " << noutput_items << " Since close: " << its_been << std::endl; } @@ -369,7 +369,7 @@ int transmission_sink::work(int noutput_items, gr_vector_const_void_star &input_ //BOOST_LOG_TRIVIAL(info) << "Updated Voice Channel source id: " << src_id << " pos: " << pos << " offset: " << tags[i].offset - nitems_read(0); } - + } if (pmt::eq(terminate_key, tags[i].key)) { d_termination_flag = true; @@ -426,13 +426,18 @@ void transmission_sink::add_transmission(Transmission t) { } void transmission_sink::set_record_more_transmissions(bool more) { + if (record_more_transmissions != more) { + BOOST_LOG_TRIVIAL(trace) << "wav - setting record_more to: " << more << ", State: " << format_state(state) << " sample count: " << d_sample_count; + } // If a Recorder is STOPPED and record_more_transmissions is false, prep it so it is ready to go. if ((record_more_transmissions == false) && (more == true) && (state == STOPPED)) { - //BOOST_LOG_TRIVIAL(info) << "wav - setting record_more to true, sample count: " << d_sample_count; d_sample_count = 0; state = IDLE; } + + record_more_transmissions = more; + } void transmission_sink::clear_transmission_list() { @@ -452,43 +457,43 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu // A Termination Tag was receive if (d_termination_flag) { + d_termination_flag = false; + + char formattedTalkgroup[62]; + snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); + std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); if (d_current_call == NULL) { BOOST_LOG_TRIVIAL(error) << "wav - no current call, but in temination loop"; state = STOPPED; + return noutput_items; } if (d_sample_count > 0) { - end_transmission(); - } - - // Check to see if we have started a Transmission yet - // A Terminator with any Transmission started shouldn't do anything... right? + BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tTERM - record_more_transmissions = false, setting Recorder More: " << record_more_transmissions << " - count: " << d_sample_count; + + end_transmission(); - // Another GRANT message has arrived. - if (d_conventional || (record_more_transmissions == true)) { - state = IDLE; - } else { - char formattedTalkgroup[62]; - snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); - std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - - BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tTERM - record_more_transmissions = false, setting Recorder state to STOPPED - count: " << d_sample_count; - //BOOST_LOG_TRIVIAL(trace) << "Call completed - putting recorder into state Completed - we had samples"; - - state = STOPPED; - } - d_termination_flag = false; - if (noutput_items > 1) { - char formattedTalkgroup[62]; - snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); - std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tTERM - skipped: " << noutput_items; + // If it is a conventional call or an UPDATE or GRANT message has been received recently, + // then set it in IDLE state, which allows a new transmission to start. + if (d_conventional || (record_more_transmissions == true)) { + state = IDLE; + } else { + state = STOPPED; + } + + if (noutput_items > 1) { + char formattedTalkgroup[62]; + snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); + std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); + BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tTERM - skipped: " << noutput_items; + } } + // In order to actually transmit the Tag, you need to attach it to a sample. An empty sample is used and it should be discarded. return noutput_items; } @@ -501,7 +506,6 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tWAV - Weird! State was IDLE but record_more_transmissions was FALSE - count: " << d_sample_count; - } if (d_fp) { // if we are already recording a file for this call, close it before starting a new one. @@ -564,7 +568,7 @@ int transmission_sink::dowork(int noutput_items, gr_vector_const_void_star &inpu char formattedTalkgroup[62]; snprintf(formattedTalkgroup, 61, "%c[%dm%10ld%c[0m", 0x1B, 35, d_current_call_talkgroup, 0x1B); std::string talkgroup_display = boost::lexical_cast(formattedTalkgroup); - BOOST_LOG_TRIVIAL(trace) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tFailed to Write! Wrote: " << nwritten << " of " << noutput_items; + BOOST_LOG_TRIVIAL(error) << "[" << d_current_call_short_name << "]\t\033[0;34m" << d_current_call_num << "C\033[0m\tTG: " << formattedTalkgroup << "\tFreq: " << format_freq(d_current_call_freq) << "\tFailed to Write! Wrote: " << nwritten << " of " << noutput_items; } return noutput_items; } diff --git a/lib/op25_repeater/lib/p25_frame_assembler_impl.cc b/lib/op25_repeater/lib/p25_frame_assembler_impl.cc index f8b2d412e..1f8fc2346 100644 --- a/lib/op25_repeater/lib/p25_frame_assembler_impl.cc +++ b/lib/op25_repeater/lib/p25_frame_assembler_impl.cc @@ -193,34 +193,31 @@ p25_frame_assembler_impl::general_work (int noutput_items, BOOST_LOG_TRIVIAL(trace) << "P25 Frame Assembler - Amt Prod: " << amt_produce << " output_queue: " << output_queue.size() << " noutput_items: " << noutput_items; + // output_queue.size() is the number of samples that were actually generated + // amt_produce just defaults to the standard amount expected for the block if (amt_produce > (int)output_queue.size()) { amt_produce = output_queue.size(); - } + } + if (amt_produce > 0) { long src_id = p1fdma.get_curr_src_id(); - if (src_id) { - // fprintf(stderr, "tagging source: %ld at %lu\n", src_id, - // nitems_written(0)); + // If a SRC wasn't received on the voice channel since the last check, it will be -1 + if (src_id > 0) { add_item_tag(0, nitems_written(0), d_tag_key, pmt::from_long(src_id), d_tag_src); } - + for (int i = 0; i < amt_produce; i++) { out[i] = output_queue[i]; } output_queue.erase(output_queue.begin(), output_queue.begin() + amt_produce); - /* - if (amt_produce < noutput_items) { - std::fill(out + amt_produce, out + noutput_items, 0); - amt_produce = noutput_items; - }*/ + BOOST_LOG_TRIVIAL(trace) << "setting silence_frame_count " << silence_frame_count << " to d_silence_frames: " << d_silence_frames << std::endl; silence_frame_count = d_silence_frames; } else { - - if (terminate_call) { + if (terminate_call) { add_item_tag(0, nitems_written(0), pmt::intern("terminate"), pmt::from_long(1), d_tag_src ); Rx_Status status = p1fdma.get_rx_status(); @@ -231,10 +228,9 @@ p25_frame_assembler_impl::general_work (int noutput_items, add_item_tag(0, nitems_written(0), pmt::intern("error_count"), pmt::from_long(status.error_count), d_tag_src); p1fdma.reset_rx_status(); } - std::fill(out, out + 1, 0); - amt_produce = 1; - - //BOOST_LOG_TRIVIAL(info) << "Call Terminated, NO amount produced: " << amt_produce << " SRC: " << p1fdma.get_curr_src_id() << " n written " << nitems_written(0); + + std::fill(out, out + 1, 0); + amt_produce = 1; } if (silence_frame_count > 0) { std::fill(out, out + noutput_items, 0); @@ -244,7 +240,7 @@ p25_frame_assembler_impl::general_work (int noutput_items, } } consume_each(ninput_items[0]); - // Tell runtime system how many output items we produced. + // Tell runtime system how many output items we actually produced. return amt_produce; } diff --git a/lib/op25_repeater/lib/p25p1_fdma.cc b/lib/op25_repeater/lib/p25p1_fdma.cc index 6a4c9d9b3..ab92f5296 100644 --- a/lib/op25_repeater/lib/p25p1_fdma.cc +++ b/lib/op25_repeater/lib/p25p1_fdma.cc @@ -245,7 +245,10 @@ namespace gr { } long p25p1_fdma::get_curr_src_id() { - return curr_src_id; + long addr = curr_src_id; + curr_src_id = -1; + // This makes it easy to tell when a new Src Address has been received, all other times it will be -1 + return addr; } void p25p1_fdma::clear() { p1voice_decode.clear(); diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index 1577ccc2a..bc479ef05 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -987,9 +987,13 @@ void handle_call_grant(TrunkMessage message, System *sys) { // There is an existing call on freq and slot that the new call will be started on. We should stop the older call. The older recorder will // keep writing to the file until it hits a termination flag, so no packets should be dropped. if ((call->get_state() == RECORDING) && (call->get_talkgroup() != message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { - BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36mStopping RECORDING call, RX overlapping TG message Freq, TG:" << message.talkgroup << "\u001b[0m"; - BOOST_LOG_TRIVIAL(info) << "\t - Stopping call because of overlapping Freq"; - //call->stop_call(); + Recorder *recorder = call->get_recorder(); + string recorder_state = "UNKNOWN"; + if (recorder != NULL) { + recorder_state = format_state(recorder->get_state()); + } + BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36mStopping RECORDING call, Recorder State: " << recorder_state << " RX overlapping TG message Freq, TG:" << message.talkgroup << "\u001b[0m"; + call->set_state(COMPLETED); call->conclude_call(); it = calls.erase(it); @@ -1000,9 +1004,13 @@ void handle_call_grant(TrunkMessage message, System *sys) { // There is an existing call on freq and slot that the new call will be started on. We should stop the older call. The older recorder will // keep writing to the file until it hits a termination flag, so no packets should be dropped. if ((call->get_state() == INACTIVE) && (call->get_talkgroup() != message.talkgroup) && (call->get_sys_num() == message.sys_num) && (call->get_freq() == message.freq) && (call->get_tdma_slot() == message.tdma_slot) && (call->get_phase2_tdma() == message.phase2_tdma)) { - BOOST_LOG_TRIVIAL(error) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36mStopping INACTIVE call, RX overlapping TG message Freq TG:" << message.talkgroup << "\u001b[0m"; - BOOST_LOG_TRIVIAL(info) << "\t - Stopping call because of overlapping Freq"; - //call->stop_call(); + Recorder *recorder = call->get_recorder(); + string recorder_state = "UNKNOWN"; + if (recorder != NULL) { + recorder_state = format_state(recorder->get_state()); + } + BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36mStopping INACTIVE call, Recorder State: " << recorder_state << " RX overlapping TG message Freq TG:" << message.talkgroup << "\u001b[0m"; + call->set_state(COMPLETED); call->conclude_call(); it = calls.erase(it); @@ -1057,6 +1065,9 @@ void handle_call_update(TrunkMessage message, System *sys) { //BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Updating Call \u001b[0m"; + // It is helpful to have both GRANT and UPDATE messages allow for new calls to be started + // This is because GRANT message can be sometimes dropped if the control channel is not perfect + // In either event, when a Call times out and goes INACTIVE, then record_more_transmissions gets set to false call->set_record_more_transmissions(true); bool source_updated = call->update(message); From be329d6a983fbdedfa60c03778b6ee6a73012370 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Tue, 5 Apr 2022 21:53:34 -0400 Subject: [PATCH 36/38] Update CALL-HANDLING.md --- docs/notes/CALL-HANDLING.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/docs/notes/CALL-HANDLING.md b/docs/notes/CALL-HANDLING.md index f308fab20..3fa58cf08 100644 --- a/docs/notes/CALL-HANDLING.md +++ b/docs/notes/CALL-HANDLING.md @@ -42,3 +42,31 @@ F -.-> G["call->update()"] D -.->|RECORDING| G ``` + + +```mermaid +flowchart TD +A[For Each Call] -->|Call| B{state} + + + +B -.->|RECORDING| C{"last_update > 1.0"} +C -.->|True| E["call->set_record_more_transmissions(false)\nstate = INACTIVE"] +C -.->|False| D[Next] +E -.-> D +B -.->|MONITORING| F{"last_update > 1.0"} +F -.->|True| G["Delete Call"] +G -.-> D +F -.->|False| D +B -.->|COMPLETED| H["Conclude Call"] +H -.-> Z["Delete Call"] +Z -.-> D +B -.->|INACTIVE| I{"since last_update > 5.0"} +I -.->|True| J[state = COMPLETED] +J -.-> K[Conclude Call] +K -.-> L[Delete Call] +I -.->|False| D +L -.-> D + + +``` From ccf788ffcca773ad9d334f8933e1b2d5c50b0188 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Tue, 5 Apr 2022 22:02:49 -0400 Subject: [PATCH 37/38] Update CALL-HANDLING.md --- docs/notes/CALL-HANDLING.md | 57 +++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/docs/notes/CALL-HANDLING.md b/docs/notes/CALL-HANDLING.md index 3fa58cf08..642bac8d7 100644 --- a/docs/notes/CALL-HANDLING.md +++ b/docs/notes/CALL-HANDLING.md @@ -1,36 +1,36 @@ ```mermaid flowchart TD - E -.-> L1 - subgraph Control Channel - A[Control Channel] -->|GRANT| B["handle_call_grant()"] - B --> C{Existing Call on Freq?} - C -.->|Yes| D{Same Talkgroup?} - C -.->|No| G["new Call()"] - D -.->|Yes| E["call->set_record_more_transmissions()"] - D -.->|No| F[Delete Existing Call] - F -.-> G - G -.-> H["start_recording()"] +A[Control Channel] -->|GRANT| B["handle_call_grant()"] +B --> C{Existing Call on Freq?} +C -.->|Yes| D{Same Talkgroup?} +C -.->|No| G["new Call()"] +D -.->|Yes| E["call->set_record_more_transmissions(True)"] +D -.->|No| F[Delete Existing Call] +F -.-> G +G -.-> H["start_recording()"] +``` - end - subgraph Voice Channel - A1[Voice Channel] --> B1[Transmission Sink] - B1 -.->|Samples| C1{State} - C1 -.->|STOPPED| D1[Drop Samples] - C1 -.->|IDLE| F1["Setup files\nrecord_more_transmissions = false;\nd_first_work = false;\nstate = RECORDING"] - C1 -.->|RECORDING| G1[Write Samples] - F1 -.-> G1 - B1 -.->|TERMINATOR| H1["End Transmission"] - H1 -.-> I1{"record_more_transmissions"} - I1 -.->|False| J1["state = STOPPED"] - I1 -.->|True| K1["state = IDLE"] - L1["set_record_more_transmissions()"] -.-> N1{state == STOPPED} - N1 -.->|True| O1["state == IDLE"] - N1 -.->|False| P1["record_mode_transmissions = True"] - O1 -.-> P1 - end +```mermaid +flowchart TD +A1[Voice Channel] --> B1[Transmission Sink] +B1 -.->|Samples| C1{State} +C1 -.->|STOPPED| D1[Drop Samples] +C1 -.->|IDLE| F1["Setup files\nrecord_more_transmissions = false;\nd_first_work = false;\nstate = RECORDING"] +C1 -.->|RECORDING| G1[Write Samples] +F1 -.-> G1 +B1 -.->|TERMINATOR| H1["End Transmission"] +H1 -.-> I1{"record_more_transmissions"} +I1 -.->|False| J1["state = STOPPED"] +I1 -.->|True| K1["state = IDLE"] +L1["set_record_more_transmissions(True)"] -.-> N1{state == STOPPED} +N1 -.->|True| O1["state == IDLE"] +N1 -.->|False| P1["record_mode_transmissions = True"] +O1 -.-> P1 +``` -``` + + ```mermaid flowchart TD A[Control Channel] -->|UPDATE| B["handle_call_update()"] @@ -40,6 +40,7 @@ D -.->|COMPLETED| E[Do Nothing] D -.->|INACTIVE| F["call->state==RECORDING"] F -.-> G["call->update()"] D -.->|RECORDING| G +G -.-> H["call->set_record_more_transmissions(True)"] ``` From 669ca00ad10c652bacc5b2d7c1a112192c85a8af Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Thu, 7 Apr 2022 21:37:12 -0400 Subject: [PATCH 38/38] switches to use call_timeout --- trunk-recorder/main.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trunk-recorder/main.cc b/trunk-recorder/main.cc index 456e144ef..4a53700aa 100755 --- a/trunk-recorder/main.cc +++ b/trunk-recorder/main.cc @@ -866,9 +866,9 @@ void manage_calls() { if (recorder != NULL) { // if the recorder has simply been going for a while and a call is inactive, end things - if (call->since_last_update() > 5) { + if (call->since_last_update() > config.call_timeout) { //BOOST_LOG_TRIVIAL(info) << "Recorder state: " << recorder->get_state(); - BOOST_LOG_TRIVIAL(trace) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Removing call that has been inactive for more than 5 Sec \u001b[0m Rec last write: " << recorder->since_last_write() << " State: " << recorder->get_state(); + BOOST_LOG_TRIVIAL(trace) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << call->get_talkgroup_display() << "\tFreq: " << format_freq(call->get_freq()) << "\t\u001b[36m Removing call that has been inactive for more than " << config.call_timeout << " Sec \u001b[0m Rec last write: " << recorder->since_last_write() << " State: " << recorder->get_state(); // since the Call state is INACTIVE and the Recorder has been going on for a while, we can now // set the Call state to COMPLETED