summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md7
-rw-r--r--src/VLCInput.cpp35
-rw-r--r--src/VLCInput.h5
-rw-r--r--src/dabplus-enc.cpp79
4 files changed, 90 insertions, 36 deletions
diff --git a/README.md b/README.md
index b589a6a..d44b957 100644
--- a/README.md
+++ b/README.md
@@ -85,6 +85,13 @@ If two channels are used, PS (Parametric Stereo, also called HE-AAC v2)
is enabled up to 48kbps. Between 56kbps and 80kbps, SBR is enabled. 88kbps
and higher are using AAC-LC.
+ZeroMQ output
+-------------
+
+The ZeroMQ output included in FDK-AAC-DABplus is able to connect to
+one or several instances of ODR-DabMux. The -o option can be used
+more than once to achieve this.
+
Scenario *ALSA*
---------------
Live Stream from ALSA sound card at 32kHz, with ZMQ output for ODR-DabMux:
diff --git a/src/VLCInput.cpp b/src/VLCInput.cpp
index 70381fb..3a2e9ec 100644
--- a/src/VLCInput.cpp
+++ b/src/VLCInput.cpp
@@ -20,6 +20,7 @@
#include <string>
#include <cstring>
#include <chrono>
+#include <functional>
#include "VLCInput.h"
@@ -294,11 +295,39 @@ ssize_t VLCInput::read(uint8_t* buf, size_t length)
return read;
}
-void VLCInput::write_icy_text(const std::string& filename) const
+bool write_icy_to_file(const std::string& text, const std::string& filename)
{
FILE* fd = fopen(filename.c_str(), "wb");
- fputs_unlocked(m_nowplaying.c_str(), fd);
- fclose(fd);
+ if (fd) {
+ int ret = fputs(text.c_str(), fd);
+ fclose(fd);
+
+ return ret >= 0;
+ }
+
+ return false;
+}
+
+void VLCInput::write_icy_text(const std::string& filename)
+{
+ if (icy_text_written.valid()) {
+ auto status = icy_text_written.wait_for(std::chrono::microseconds(1));
+ if (status == std::future_status::ready) {
+ if (not icy_text_written.get()) {
+ fprintf(stderr, "Failed to write ICY Text to file!\n");
+ }
+ }
+ }
+
+ else {
+ if (m_nowplaying_previous != m_nowplaying) {
+ icy_text_written = std::async(std::launch::async,
+ std::bind(write_icy_to_file, m_nowplaying, filename));
+
+ }
+
+ m_nowplaying_previous = m_nowplaying;
+ }
}
/* VLC up to version 2.1.0 used a different callback function signature.
diff --git a/src/VLCInput.h b/src/VLCInput.h
index 048c931..6b0a0f4 100644
--- a/src/VLCInput.h
+++ b/src/VLCInput.h
@@ -29,6 +29,7 @@
#include <deque>
#include <thread>
#include <mutex>
+#include <future>
#include <vlc/vlc.h>
@@ -67,7 +68,7 @@ class VLCInput
/* Write the last received ICY-Text to the
* file.
*/
- void write_icy_text(const std::string& filename) const;
+ void write_icy_text(const std::string& filename);
// Callbacks for VLC
@@ -102,7 +103,9 @@ class VLCInput
unsigned m_channels;
int m_rate;
+ std::future<bool> icy_text_written;
std::string m_nowplaying;
+ std::string m_nowplaying_previous;
// VLC pointers
libvlc_instance_t *m_vlc;
diff --git a/src/dabplus-enc.cpp b/src/dabplus-enc.cpp
index a91e4c9..7e30a79 100644
--- a/src/dabplus-enc.cpp
+++ b/src/dabplus-enc.cpp
@@ -31,6 +31,7 @@ extern "C" {
#include "wavreader.h"
}
+#include <vector>
#include <string>
#include <getopt.h>
#include <cstdio>
@@ -112,9 +113,11 @@ void usage(const char* name) {
" --sbr Force the usage of SBR\n"
" --ps Force the usage of PS\n"
" Output and pad parameters:\n"
- " -o, --output=URI Output zmq uri. (e.g. 'tcp://localhost:9000')\n"
+ " -o, --output=URI Output ZMQ uri. (e.g. 'tcp://localhost:9000')\n"
" -or- Output file uri. (e.g. 'file.dabp')\n"
" -or- a single dash '-' to denote stdout\n"
+ " If more than one ZMQ output is given, the socket\n"
+ " will be connected to all listed endpoints.\n"
" -k, --secret-key=FILE Enable ZMQ encryption with the given secret key.\n"
" -p, --pad=BYTES Set PAD size in bytes.\n"
" -P, --pad-fifo=FILENAME Set PAD data input fifo name"
@@ -256,7 +259,8 @@ int main(int argc, char *argv[])
const char *jack_name = NULL;
- const char *outuri = NULL;
+ std::vector<std::string> output_uris;
+
int sample_rate=48000, channels=2;
void *rs_handler = NULL;
bool afterburner = true;
@@ -393,7 +397,7 @@ int main(int argc, char *argv[])
show_level = 1;
break;
case 'o':
- outuri = optarg;
+ output_uris.push_back(optarg);
break;
case 'p':
padlen = atoi(optarg);
@@ -463,42 +467,53 @@ int main(int argc, char *argv[])
zmq::context_t zmq_ctx;
zmq::socket_t zmq_sock(zmq_ctx, ZMQ_PUB);
- if (outuri) {
- if (strcmp(outuri, "-") == 0) {
- out_fh = stdout;
- }
- else if ((strncmp(outuri, "tcp://", 6) == 0) ||
- (strncmp(outuri, "pgm://", 6) == 0) ||
- (strncmp(outuri, "epgm://", 7) == 0)) {
- if (keyfile) {
- fprintf(stderr, "Enabling encryption\n");
-
- int rc = readkey(keyfile, secretkey);
- if (rc) {
- fprintf(stderr, "Error reading secret key\n");
- return 2;
+ if (not output_uris.empty()) {
+ for (auto uri : output_uris) {
+ if (uri == "-") {
+ if (out_fh != NULL) {
+ fprintf(stderr, "You can't write to more than one file!\n");
+ return 1;
}
-
- const int yes = 1;
- zmq_sock.setsockopt(ZMQ_CURVE_SERVER,
- &yes, sizeof(yes));
-
- zmq_sock.setsockopt(ZMQ_CURVE_SECRETKEY,
- secretkey, CURVE_KEYLEN);
+ out_fh = stdout;
}
- zmq_sock.connect(outuri);
- }
- else { // We assume it's a file name
- out_fh = fopen(outuri, "wb");
+ else if ((uri.compare(0, 6, "tcp://") == 0) ||
+ (uri.compare(0, 6, "pgm://") == 0) ||
+ (uri.compare(0, 7, "epgm://") == 0)) {
+ if (keyfile) {
+ fprintf(stderr, "Enabling encryption\n");
+
+ int rc = readkey(keyfile, secretkey);
+ if (rc) {
+ fprintf(stderr, "Error reading secret key\n");
+ return 2;
+ }
+
+ const int yes = 1;
+ zmq_sock.setsockopt(ZMQ_CURVE_SERVER,
+ &yes, sizeof(yes));
+
+ zmq_sock.setsockopt(ZMQ_CURVE_SECRETKEY,
+ secretkey, CURVE_KEYLEN);
+ }
+ zmq_sock.connect(uri.c_str());
+ }
+ else { // We assume it's a file name
+ if (out_fh != NULL) {
+ fprintf(stderr, "You can't write to more than one file!\n");
+ return 1;
+ }
- if (!out_fh) {
- fprintf(stderr, "Can't open output file!\n");
- return 1;
+ out_fh = fopen(uri.c_str(), "wb");
+
+ if (!out_fh) {
+ fprintf(stderr, "Can't open output file!\n");
+ return 1;
+ }
}
}
}
else {
- fprintf(stderr, "Output URI not defined\n");
+ fprintf(stderr, "No output URI defined\n");
return 1;
}