aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Pöschel <github@basicmaster.de>2016-07-24 19:29:52 +0200
committerStefan Pöschel <github@basicmaster.de>2016-07-24 19:29:52 +0200
commitdb600494aded16956c15205b1a056ee465c9bc49 (patch)
tree381bc61016628c7f1078e940c6acbc301376bffd
parent350195adc995a74ff32f689f3493f2066c8d7b6b (diff)
downloadODR-AudioEnc-db600494aded16956c15205b1a056ee465c9bc49.tar.gz
ODR-AudioEnc-db600494aded16956c15205b1a056ee465c9bc49.tar.bz2
ODR-AudioEnc-db600494aded16956c15205b1a056ee465c9bc49.zip
VLC input: use ICY artist/title if available
-rw-r--r--src/VLCInput.cpp55
-rw-r--r--src/VLCInput.h35
2 files changed, 78 insertions, 12 deletions
diff --git a/src/VLCInput.cpp b/src/VLCInput.cpp
index 9f0aa65..0ce4f00 100644
--- a/src/VLCInput.cpp
+++ b/src/VLCInput.cpp
@@ -324,17 +324,34 @@ ssize_t VLCInput::m_read(uint8_t* buf, size_t length)
break;
}
- char* nowplaying_sz = libvlc_media_get_meta(media, libvlc_meta_NowPlaying);
- if (nowplaying_sz) {
- std::lock_guard<std::mutex> lock(m_nowplaying_mutex);
- m_nowplaying = nowplaying_sz;
+ // handle meta data
+ char* artist_sz = libvlc_media_get_meta(media, libvlc_meta_Artist);
+ char* title_sz = libvlc_media_get_meta(media, libvlc_meta_Title);
- free(nowplaying_sz);
+ if (artist_sz && title_sz) {
+ // use Artist and Title
+ std::lock_guard<std::mutex> lock(m_nowplaying_mutex);
+ m_nowplaying.useArtistTitle(artist_sz, title_sz);
+ } else {
+ // try fallback to NowPlaying
+ char* nowplaying_sz = libvlc_media_get_meta(media, libvlc_meta_NowPlaying);
+ if (nowplaying_sz) {
+ std::lock_guard<std::mutex> lock(m_nowplaying_mutex);
+ m_nowplaying.useNowPlaying(nowplaying_sz);
+ free(nowplaying_sz);
+ }
}
+
+ if (artist_sz)
+ free(artist_sz);
+ if (title_sz)
+ free(title_sz);
}
return err;
}
+const std::string VLCInput::ICY_TEXT_SEPARATOR = " - ";
+
/*! Write the corresponding text to a file readable by mot-encoder, with optional
* DL+ information. The text is passed as a copy because we actually use the
* m_nowplaying variable which is also accessed in another thread, so better
@@ -342,11 +359,12 @@ ssize_t VLCInput::m_read(uint8_t* buf, size_t length)
*
* \return false on failure
*/
-bool write_icy_to_file(const std::string text, const std::string& filename, bool dl_plus)
+bool write_icy_to_file(const ICY_TEXT_T text, const std::string& filename, bool dl_plus)
{
FILE* fd = fopen(filename.c_str(), "wb");
if (fd) {
bool ret = true;
+ bool artist_title_used = !text.artist.empty() && !text.title.empty();
// if desired, prepend DL Plus information
if (dl_plus) {
@@ -354,15 +372,32 @@ bool write_icy_to_file(const std::string text, const std::string& filename, bool
ss << "##### parameters { #####\n";
ss << "DL_PLUS=1\n";
- // if non-empty text, add PROGRAMME.NOW tag
- if (!text.empty())
- ss << "DL_PLUS_TAG=33 0 " << (strlen_utf8(text.c_str()) - 1) << "\n"; // -1 !
+ // if non-empty text, add tag
+ if (artist_title_used) {
+ size_t artist_len = strlen_utf8(text.artist.c_str());
+ size_t title_start = artist_len + strlen_utf8(VLCInput::ICY_TEXT_SEPARATOR.c_str());
+
+ // ITEM.ARTIST
+ ss << "DL_PLUS_TAG=4 0 " << (artist_len - 1) << "\n"; // -1 !
+
+ // ITEM.TITLE
+ ss << "DL_PLUS_TAG=1 " << title_start << " " << (strlen_utf8(text.title.c_str()) - 1) << "\n"; // -1 !
+ } else if (!text.now_playing.empty()) {
+ // PROGRAMME.NOW
+ ss << "DL_PLUS_TAG=33 0 " << (strlen_utf8(text.now_playing.c_str()) - 1) << "\n"; // -1 !
+ }
ss << "##### parameters } #####\n";
ret &= fputs(ss.str().c_str(), fd) >= 0;
}
- ret &= fputs(text.c_str(), fd) >= 0;
+ if (artist_title_used) {
+ ret &= fputs(text.artist.c_str(), fd) >= 0;
+ ret &= fputs(VLCInput::ICY_TEXT_SEPARATOR.c_str(), fd) >= 0;
+ ret &= fputs(text.title.c_str(), fd) >= 0;
+ } else {
+ ret &= fputs(text.now_playing.c_str(), fd) >= 0;
+ }
fclose(fd);
return ret;
diff --git a/src/VLCInput.h b/src/VLCInput.h
index 761492b..da4b7ae 100644
--- a/src/VLCInput.h
+++ b/src/VLCInput.h
@@ -49,6 +49,34 @@ extern "C" {
/*! Common functionality for the direct libvlc input and the
* threaded libvlc input
*/
+
+struct ICY_TEXT_T {
+ std::string artist;
+ std::string title;
+ std::string now_playing;
+
+ bool operator==(const ICY_TEXT_T& other) const {
+ return
+ artist == other.artist &&
+ title == other.title &&
+ now_playing == other.now_playing;
+ }
+ bool operator!=(const ICY_TEXT_T& other) const {
+ return !(*this == other);
+ }
+ void useArtistTitle(std::string artist, std::string title) {
+ this->artist = artist;
+ this->title = title;
+ now_playing = "";
+ }
+ void useNowPlaying(std::string now_playing) {
+ artist = "";
+ title = "";
+ this->now_playing = now_playing;
+ }
+};
+
+
class VLCInput
{
public:
@@ -119,6 +147,9 @@ class VLCInput
bool fault_detected() { return m_fault; };
+ /*! Separator string used when artist/title are written
+ */
+ static const std::string ICY_TEXT_SEPARATOR;
private:
/*! Stop the player and release resources
*/
@@ -160,8 +191,8 @@ class VLCInput
*/
std::future<bool> icy_text_written;
std::mutex m_nowplaying_mutex;
- std::string m_nowplaying;
- std::string m_nowplaying_previous;
+ ICY_TEXT_T m_nowplaying;
+ ICY_TEXT_T m_nowplaying_previous;
// VLC pointers
libvlc_instance_t *m_vlc;