Skip to content
Snippets Groups Projects
Commit 44730161 authored by Jan Schlüter's avatar Jan Schlüter
Browse files

Cleanly stop recording if interrupted by CTRL+C or SIGTERM

parent e10b9fb6
Branches
No related tags found
2 merge requests!2HighBlueParser dev branch merged to empty main branch,!1High blue rec
This commit is part of merge request !1. Comments created here will be created in the context of that merge request.
......@@ -4,7 +4,7 @@ if(POLICY CMP0063)
endif()
project(jasonrec)
set(JASONREC_VERSION "1.1")
set(JASONREC_VERSION "1.2")
add_definitions(-DJASONREC_VERSION="${JASONREC_VERSION}")
find_path(LIBUSB_INCLUDE_DIR
......
add_executable(jasonrec
recorder.cpp
filewriter.cpp
cleanexit.cpp
main.cpp)
# compile as C++11
set_property(TARGET jasonrec
......@@ -17,4 +18,3 @@ target_link_libraries(jasonrec
${LIBUSB_LIBRARY})
install(TARGETS jasonrec DESTINATION bin)
/**
* Simple signal handler for clean termination of an application.
*
* Author: Jan Schlüter <jan.schluter@lis-lab.fr>
*/
#include <atomic>
#include <csignal>
#ifdef __unix__
#include <unistd.h>
#endif
std::atomic<bool> _exit_requested(false);
void caught_signal(int)
{
_exit_requested.store(true);
}
void allow_clean_exit() {
#ifdef __unix__
struct sigaction sa = {0};
sa.sa_handler = caught_signal;
sigfillset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
#else
signal(SIGINT, caught_signal);
signal(SIGTERM, caught_signal);
#endif
}
bool exit_requested() {
return _exit_requested.load();
}
/**
* Simple signal handler for clean termination of an application.
*
* Author: Jan Schlüter <jan.schluter@lis-lab.fr>
*/
#ifndef CLEANEXIT_H
#define CLEANEXIT_H
/**
* Set up signal handlers to make exit_requested() work.
*/
void allow_clean_exit();
/**
* Check if the application was requested to terminate.
* \returns whether the application was requested to terminate.
*/
bool exit_requested();
#endif
......@@ -8,6 +8,7 @@
#include <memory>
#include "recorder.h"
#include "filewriter.h"
#include "cleanexit.h"
void print_usage(char *name) {
std::cout << "SMIoT JASON Qualilife sound recorder";
......@@ -52,6 +53,7 @@ int record(size_t channels, size_t rate, std::string &filename, float chunklen,
}
// start the recording loop
std::cout << "Starting to record..." << std::endl;
allow_clean_exit();
size_t total_samples_wanted = totallen * rate;
size_t total_samples_read = 0;
std::vector<std::int16_t> samples;
......@@ -59,7 +61,12 @@ int record(size_t channels, size_t rate, std::string &filename, float chunklen,
recorder.start_recording();
// we will record until we have enough (or forever, if totallen == 0)
while ((total_samples_wanted == 0) || (total_samples_read < total_samples_wanted)) {
recorder.get_samples(samples);
if (exit_requested()) {
std::cout << "Termination requested." << std::endl;
break;
}
recorder.get_samples(samples, false, 500);
if (samples.size() > 0) {
total_samples_read += samples.size() / channels;
// if we have too much now, crop the last packet
if ((total_samples_wanted > 0) && (total_samples_read > total_samples_wanted)) {
......@@ -68,6 +75,7 @@ int record(size_t channels, size_t rate, std::string &filename, float chunklen,
// pass it on to the file writer
filewriter->write(samples);
}
}
recorder.stop_recording();
std::cout << "Stopped recording." << std::endl;
}
......
......@@ -158,13 +158,13 @@ size_t JasonRecorder::receive_message(std::uint8_t *buffer, size_t length, size_
return received;
}
void JasonRecorder::get_samples(std::vector<std::int16_t> &samples, bool planar) {
void JasonRecorder::get_samples(std::vector<std::int16_t> &samples, bool planar, size_t max_wait) {
if (!num_channels || !sample_rate) {
throw std::logic_error("must call set_format() first");
}
std::array<std::uint8_t, 4 + MAX_PAYLOAD> buffer;
while (true) {
size_t received = receive_message(buffer.data(), buffer.size());
size_t received = receive_message(buffer.data(), buffer.size(), max_wait);
if (received) {
// we could read the payload length, but it is wrong for sample data
//size_t length = buffer[1] << 8 + buffer[2];
......@@ -194,6 +194,11 @@ void JasonRecorder::get_samples(std::vector<std::int16_t> &samples, bool planar)
break;
}
}
else if (max_wait > 0) {
// we timed out, we do not want to wait again
samples.resize(0);
break;
}
}
}
......
......@@ -95,8 +95,12 @@ public:
* \param[in] planar If true, return the samples in planar form, i.e., one
* channel after the other, the format sent by the device. If false (the
* default), interleave the channels as done in PCM WAVE files.
* \param[in] max_wait Maximum time in milliseconds to block waiting for a
* packet from the device. If the time elapses before receiving any packets,
* or if a different type of packet was received, returns with an empty
* samples vector. Set to zero to wait indefinitely for a sample packet.
*/
void get_samples(std::vector<std::int16_t> &samples, bool planar=false);
void get_samples(std::vector<std::int16_t> &samples, bool planar=false, size_t max_wait=0);
/** Converts samples from planar to interleaved form.
* \param[in] input A pointer to the planar samples to read.
* \param[out] output A pointer to write the interleaved samples to.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment