diff options
Diffstat (limited to 'audioreceiver.c')
-rw-r--r-- | audioreceiver.c | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/audioreceiver.c b/audioreceiver.c new file mode 100644 index 0000000..43c8723 --- /dev/null +++ b/audioreceiver.c @@ -0,0 +1,259 @@ +/* + * audioreceiver.c + */ + +#include "audioreceiver.h" +#include "postproc.h" +#include "audiorecorder.h" + + +/* --- cAudioReceiver ------------------------------------------------------- */ + +cAudioReceiver::cAudioReceiver(const cChannel *_channel) +:cReceiver(_channel->GetChannelID(), -2, _channel->Apid(0)), cThread() +{ + channel = _channel; + + active = false; + + pes_sync = false; + device_number = -1; + recstat = recWait; + + buffer = NULL; + rds = NULL; + postdata = NULL; + + dsyslog("[audiorecorder]: receiver for channel <%s> created on pid %d " + "(%s, %s())", channel->Name(), channel->Apid(0), __FILE__, + __func__); +} + + +cAudioReceiver::~cAudioReceiver(void) +{ + Activate(false); + + DELETE(buffer); + DELETE(rds); + DELETE(postdata); +} + + +void cAudioReceiver::Receive(uchar *data, int length) +{ + int ts_header_len, header_len, data_len, rb_len; + + if (! active || data[0] != 0x47) + return; + + /* check adaptation field */ + switch (data[3] & 0x30) { + case 0x10: + /* no adaptation field, payload only */ + ts_header_len = 4; + break; + case 0x30: + /* adaptation field followed by payload */ + ts_header_len = data[4] + 5; + break; + default: + return; + } + + header_len = ts_header_len; + + /* check payload unit start indicator */ + if ((data[1] & 0x40) == 0x40) { + /* ts-header is followed by a pes-header */ + header_len += data[ts_header_len + 8] + 9; + pes_sync = true; + } + + if (! pes_sync) + return; + + /* put mp2-data into the ringbuffer */ + data_len = length - header_len; + rb_len = buffer->Put(data + header_len, data_len); + + if (data_len != rb_len) { + buffer->ReportOverflow(data_len - rb_len); + dsyslog("[audiorecorder]: buffer overflow (%s, %s())", __FILE__, + __func__); + buffer->Clear(); + } +} + + +void cAudioReceiver::Activate(bool on) +{ + if (on) { + if (! active) { + active = true; + Start(); + } + } + else if (active) { + active = false; + Cancel(3); + } +} + + +void cAudioReceiver::Action(void) +{ + abuffer input_buf; + + dsyslog("[audiorecorder]: receiving from channel <%s> (%s, %s())", + channel->Name(), __FILE__, __func__); + + buffer = new cRingBufferLinear(KB(100), KB(5), true, NULL); + postdata = new cPostData(channel); + rds = new cRds(postdata); + + while (active) { + input_buf.data = buffer->Get(input_buf.length); + input_buf.offset = 0; + + if (! input_buf.data) { + usleep(10000); + continue; + } + + + get_mpa_frame(&input_buf, &mpa_frame, channel->Name()); + + while (active && mpa_frame.data) { + set_recstat_rds(); + + if (outfile.is_open()) + outfile.write((char *)mpa_frame.data, + mpa_frame.length); + + input_buf.offset += mpa_frame.length; + get_mpa_frame(&input_buf, &mpa_frame, channel->Name()); + } + + buffer->Del(input_buf.offset); + } + + if (outfile.is_open()) { + outfile.close(); + + if (! postdata->get_recpath().empty()) + remove(postdata->get_recpath().c_str()); + } + + + pes_sync = false; + device_number = -1; + recstat = recWait; + + DELETE(rds); + DELETE(postdata); + DELETE(buffer); + + dsyslog("[audiorecorder]: stopped receiving from channel <%s> " + "(%s, %s())", channel->Name(), __FILE__, __func__); +} + + +bool cAudioReceiver::is_attached(int attached_device_number) +{ + if (device_number < 0) + return false; + + if (attached_device_number != device_number && + attached_device_number != -1) + return false; + + return true; +} + + +bool cAudioReceiver::is_recording(void) +{ + if (recstat != recStart && recstat != recRun) + return false; + + return true; +} + + +void cAudioReceiver::set_recstat_rds(void) +{ + rds->put_data(mpa_frame.data, mpa_frame.length); + + while(rds->set_next_frame()) { + recstat = rds->decode_frame(); + + control_track(); + } +} + + +void cAudioReceiver::control_track(void) +{ +//LT + struct stat dir; + std::string recdir; +// + switch (recstat) { + case recStart: + if (outfile.is_open()) + outfile.close(); + + postdata->start_track(); +//LT + recdir = cPluginAudiorecorder::get_recdir(); + stat(recdir.c_str(), &dir); + + if (! (dir.st_mode & S_IFDIR)) { + dsyslog("[audiorecorder]: %s (given with the parameter " + " --recdir|-r) isn't a directory", recdir.c_str()); + return; + } + + if (access(recdir.c_str(), R_OK | W_OK) != 0) { + dsyslog("[audiorecorder]: can't access %s (given with the " + "parameter --recdir|-r)", recdir.c_str()); + return; + } +// + outfile.open(postdata->get_recpath().c_str()); +//LT + if (!outfile.is_open()) + return; +// + dsyslog("[audiorecorder]: started recording track (%s) on <%s> " + "(%s, %s())", postdata->get_recpath().c_str(), + channel->Name(), __FILE__, __func__); + break; + case recStop: + if (outfile.is_open()) + outfile.close(); + + dsyslog("[audiorecorder]: stopped recording track (%s) on <%s> " + "(%s, %s())", postdata->get_recpath().c_str(), + channel->Name(), __FILE__, __func__); + + postdata->stop_track(mpa_frame.bit_rate, mpa_frame.sample_rate, + mpa_frame.channels, mpa_frame.length); + + if (postdata->get_path().empty()) { + remove(postdata->get_recpath().c_str()); + dsyslog("[audiorecorder]: track (%s) removed" + " (%s, %s())", + postdata->get_recpath().c_str(), + __FILE__, __func__); + } else { + cPostproc::add_track(postdata); + } + postdata->clear(); + + break; + default: + break; + } +} |