mirror of
https://github.com/badaix/snapcast.git
synced 2025-05-22 05:26:17 +02:00
Added basics for maintaining metadata by stream on server and pushing to clients.
Modified Spotify stream handler to get the track name from Libreelec's stderr. Note, to support artist/album (or album art) we need to modify Libreelec to print these.
This commit is contained in:
parent
034c7f5f98
commit
d444052233
11 changed files with 166 additions and 2 deletions
|
@ -133,6 +133,15 @@ void Controller::onMessageReceived(ClientConnection* connection, const msg::Base
|
|||
player_->setMute(serverSettings_->isMuted());
|
||||
player_->start();
|
||||
}
|
||||
else if (baseMessage.type == message_type::kStreamTags)
|
||||
{
|
||||
streamTags_.reset(new msg::StreamTags());
|
||||
streamTags_->deserialize(baseMessage, buffer);
|
||||
|
||||
LOG(INFO) << "Tag received: artist = " << streamTags_->getArtist() << "\n";
|
||||
LOG(INFO) << "Tag received: album = " << streamTags_->getAlbum() << "\n";
|
||||
LOG(INFO) << "Tag received: track = " << streamTags_->getTrack() << "\n";
|
||||
}
|
||||
|
||||
if (baseMessage.type != message_type::kTime)
|
||||
if (sendTimeSyncMessage(1000))
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "decoder/decoder.h"
|
||||
#include "message/message.h"
|
||||
#include "message/serverSettings.h"
|
||||
#include "message/streamTags.h"
|
||||
#include "player/pcmDevice.h"
|
||||
#ifdef HAS_ALSA
|
||||
#include "player/alsaPlayer.h"
|
||||
|
@ -73,6 +74,7 @@ private:
|
|||
std::unique_ptr<Decoder> decoder_;
|
||||
std::unique_ptr<Player> player_;
|
||||
std::shared_ptr<msg::ServerSettings> serverSettings_;
|
||||
std::shared_ptr<msg::StreamTags> streamTags_;
|
||||
std::shared_ptr<msg::CodecHeader> headerChunk_;
|
||||
std::mutex receiveMutex_;
|
||||
|
||||
|
|
0
common/metatags.cpp
Normal file
0
common/metatags.cpp
Normal file
35
common/metatags.h
Normal file
35
common/metatags.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/***
|
||||
This file is part of snapcast
|
||||
Copyright (C) 2014-2017 Johannes Pohl
|
||||
|
||||
This program 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 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#ifndef METATAGS_DATA_H
|
||||
#define METATAGS_DATA_H
|
||||
|
||||
#include "message/streamTags.h"
|
||||
|
||||
class MetaTags
|
||||
{
|
||||
public:
|
||||
MetaTags();
|
||||
virtual ~MetaTags();
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -57,9 +57,10 @@ enum message_type
|
|||
kServerSettings = 3,
|
||||
kTime = 4,
|
||||
kHello = 5,
|
||||
kStreamTags = 6,
|
||||
|
||||
kFirst = kBase,
|
||||
kLast = kHello
|
||||
kLast = kStreamTags
|
||||
};
|
||||
|
||||
|
||||
|
|
78
message/streamTags.h
Normal file
78
message/streamTags.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
/***
|
||||
This file is part of snapcast
|
||||
Copyright (C) 2014-2017 Johannes Pohl
|
||||
|
||||
This program 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 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#ifndef STREAMTAGS_H
|
||||
#define STREAMTAGS_H
|
||||
|
||||
#include "jsonMessage.h"
|
||||
|
||||
|
||||
namespace msg
|
||||
{
|
||||
|
||||
class StreamTags : public JsonMessage
|
||||
{
|
||||
public:
|
||||
StreamTags() : JsonMessage(message_type::kStreamTags)
|
||||
{
|
||||
msg["meta_artist"] = "";
|
||||
msg["meta_album"] = "";
|
||||
msg["meta_track"] = "";
|
||||
}
|
||||
|
||||
virtual ~StreamTags()
|
||||
{
|
||||
}
|
||||
|
||||
std::string getArtist() const
|
||||
{
|
||||
return msg["meta_artist"];
|
||||
}
|
||||
|
||||
std::string getAlbum() const
|
||||
{
|
||||
return msg["meta_album"];
|
||||
}
|
||||
|
||||
std::string getTrack() const
|
||||
{
|
||||
return msg["meta_track"];
|
||||
}
|
||||
|
||||
void setArtist(std::string artist)
|
||||
{
|
||||
msg["meta_artist"] = artist;
|
||||
}
|
||||
|
||||
void setAlbum(std::string album)
|
||||
{
|
||||
msg["meta_album"] = album;
|
||||
}
|
||||
|
||||
void setTrack(std::string track)
|
||||
{
|
||||
msg["meta_track"] = track;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -33,7 +33,7 @@ endif
|
|||
|
||||
CXXFLAGS += $(ADD_CFLAGS) -std=c++0x -Wall -Wno-unused-function -O3 -DASIO_STANDALONE -DVERSION=\"$(VERSION)\" -I. -I.. -isystem ../externals/asio/asio/include -I../externals/popl/include -I../externals/aixlog/include -I../externals/jsonrpcpp/lib -I../externals
|
||||
LDFLAGS = -lvorbis -lvorbisenc -logg -lFLAC
|
||||
OBJ = snapServer.o config.o controlServer.o controlSession.o streamServer.o streamSession.o streamreader/streamUri.o streamreader/streamManager.o streamreader/pcmStream.o streamreader/pipeStream.o streamreader/fileStream.o streamreader/processStream.o streamreader/airplayStream.o streamreader/spotifyStream.o streamreader/watchdog.o encoder/encoderFactory.o encoder/flacEncoder.o encoder/pcmEncoder.o encoder/oggEncoder.o ../common/sampleFormat.o ../message/pcmChunk.o ../externals/jsonrpcpp/lib/jsonrp.o
|
||||
OBJ = snapServer.o config.o controlServer.o controlSession.o streamServer.o streamSession.o streamreader/streamUri.o streamreader/streamManager.o streamreader/pcmStream.o streamreader/pipeStream.o streamreader/fileStream.o streamreader/processStream.o streamreader/airplayStream.o streamreader/spotifyStream.o streamreader/watchdog.o encoder/encoderFactory.o encoder/flacEncoder.o encoder/pcmEncoder.o encoder/oggEncoder.o ../common/metatags.o ../common/sampleFormat.o ../message/pcmChunk.o ../externals/jsonrpcpp/lib/jsonrp.o
|
||||
|
||||
|
||||
ifneq (,$(TARGET))
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "streamServer.h"
|
||||
#include "message/time.h"
|
||||
#include "message/hello.h"
|
||||
#include "message/streamTags.h"
|
||||
#include "aixlog.hpp"
|
||||
#include "config.h"
|
||||
#include <iostream>
|
||||
|
@ -516,6 +517,14 @@ void StreamServer::onMessageReceived(StreamSession* connection, const msg::BaseM
|
|||
|
||||
Config::instance().save();
|
||||
|
||||
// Send the group stream tags
|
||||
LOG(INFO) << "request kStreamTags\n";
|
||||
//auto metaTags = make_shared<msg::StreamTags>();
|
||||
//metaTags->setArtist(stream->getMeta()->getArtist());
|
||||
//connection->sendAsync(metaTags);
|
||||
connection->sendAsync(stream->getMeta());
|
||||
LOG(INFO) << "kStreamTags sent\n";
|
||||
|
||||
connection->setPcmStream(stream);
|
||||
auto headerChunk = stream->getHeader();
|
||||
connection->sendAsync(headerChunk);
|
||||
|
|
|
@ -55,6 +55,9 @@ PcmStream::PcmStream(PcmListener* pcmListener, const StreamUri& uri) :
|
|||
dryoutMs_ = cpt::stoul(uri_.query["dryout_ms"]);
|
||||
else
|
||||
dryoutMs_ = 2000;
|
||||
|
||||
// meta_.reset(new msg::StreamTags);
|
||||
meta_ = make_shared<msg::StreamTags>();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "externals/json.hpp"
|
||||
#include "common/sampleFormat.h"
|
||||
#include "message/codecHeader.h"
|
||||
#include "message/streamTags.h"
|
||||
|
||||
|
||||
class PcmStream;
|
||||
|
@ -84,6 +85,12 @@ public:
|
|||
virtual ReaderState getState() const;
|
||||
virtual json toJson() const;
|
||||
|
||||
//const msg::StreamTags *getMeta()
|
||||
std::shared_ptr<msg::StreamTags> getMeta()
|
||||
{
|
||||
return meta_;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
std::condition_variable cv_;
|
||||
|
@ -104,6 +111,9 @@ protected:
|
|||
std::unique_ptr<Encoder> encoder_;
|
||||
std::string name_;
|
||||
ReaderState state_;
|
||||
|
||||
// Stream metadata
|
||||
std::shared_ptr<msg::StreamTags> meta_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <regex>
|
||||
#include "spotifyStream.h"
|
||||
#include "common/snapException.h"
|
||||
#include "common/utils/string_utils.h"
|
||||
|
@ -92,6 +93,9 @@ void SpotifyStream::initExeAndPath(const std::string& filename)
|
|||
|
||||
void SpotifyStream::onStderrMsg(const char* buffer, size_t n)
|
||||
{
|
||||
// Watch stderr for 'Loading track' messages and set the stream metadata
|
||||
// For more than track name check: https://github.com/plietar/librespot/issues/154
|
||||
|
||||
/// Watch will kill librespot if there was no message received for 130min
|
||||
// 2016-11-02 22-05-15 [out] TRACE:librespot::stream: allocated stream 3580
|
||||
// 2016-11-02 22-05-15 [Debug] DEBUG:librespot::audio_file2: Got channel 3580
|
||||
|
@ -118,6 +122,19 @@ void SpotifyStream::onStderrMsg(const char* buffer, size_t n)
|
|||
{
|
||||
LOG(INFO) << "(" << getName() << ") " << logmsg << "\n";
|
||||
}
|
||||
|
||||
// Check for metadata
|
||||
if (logmsg.find("Loading track") != string::npos)
|
||||
{
|
||||
regex re("Loading track \"(.*)\"");
|
||||
smatch m;
|
||||
|
||||
if (regex_search(logmsg, m, re))
|
||||
{
|
||||
LOG(INFO) << "Loading track (" << m[1] << ")\n";
|
||||
getMeta()->setTrack(m[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue