Apply clang-format
This commit is contained in:
parent
742dc25984
commit
778b31c0ed
|
@ -39,3 +39,6 @@ Makefile*
|
|||
|
||||
# documentation
|
||||
/doc
|
||||
|
||||
# clang-format
|
||||
/.clang-format
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
#include "ffmpeglauncher.h"
|
||||
#include "playerwatcher.h"
|
||||
|
||||
#include <c++utilities/io/inifile.h>
|
||||
#include <c++utilities/io/catchiofailure.h>
|
||||
#include <c++utilities/conversion/stringconversion.h>
|
||||
#include <c++utilities/io/catchiofailure.h>
|
||||
#include <c++utilities/io/inifile.h>
|
||||
|
||||
#include <QStringBuilder>
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace IoUtilities;
|
||||
|
@ -16,7 +16,7 @@ using namespace ConversionUtilities;
|
|||
|
||||
namespace DBusSoundRecorder {
|
||||
|
||||
inline ostream &operator <<(ostream &stream, const QString &str)
|
||||
inline ostream &operator<<(ostream &stream, const QString &str)
|
||||
{
|
||||
stream << str.toLocal8Bit().data();
|
||||
return stream;
|
||||
|
@ -25,45 +25,44 @@ inline ostream &operator <<(ostream &stream, const QString &str)
|
|||
inline QString validFileName(const QString &text)
|
||||
{
|
||||
QString copy(text);
|
||||
copy
|
||||
.replace(QChar('\\'), QLatin1String(" - "))
|
||||
.replace(QChar('/'), QLatin1String(" - "))
|
||||
.replace(QChar('\n'), QString())
|
||||
.replace(QChar('\r'), QString())
|
||||
.replace(QChar('\f'), QString())
|
||||
.replace(QChar('<'), QString())
|
||||
.replace(QChar('>'), QString())
|
||||
.replace(QChar('?'), QString())
|
||||
.replace(QChar('*'), QString())
|
||||
.replace(QChar('!'), QString())
|
||||
.replace(QChar('|'), QString())
|
||||
.replace(QLatin1String(": "), QLatin1String(" - "))
|
||||
.replace(QChar(':'), QChar('-'));
|
||||
copy.replace(QChar('\\'), QLatin1String(" - "))
|
||||
.replace(QChar('/'), QLatin1String(" - "))
|
||||
.replace(QChar('\n'), QString())
|
||||
.replace(QChar('\r'), QString())
|
||||
.replace(QChar('\f'), QString())
|
||||
.replace(QChar('<'), QString())
|
||||
.replace(QChar('>'), QString())
|
||||
.replace(QChar('?'), QString())
|
||||
.replace(QChar('*'), QString())
|
||||
.replace(QChar('!'), QString())
|
||||
.replace(QChar('|'), QString())
|
||||
.replace(QLatin1String(": "), QLatin1String(" - "))
|
||||
.replace(QChar(':'), QChar('-'));
|
||||
return copy;
|
||||
}
|
||||
|
||||
FfmpegLauncher::FfmpegLauncher(PlayerWatcher &watcher, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_watcher(watcher),
|
||||
m_sink(QStringLiteral("default")),
|
||||
m_inputOptions(),
|
||||
m_options(),
|
||||
m_targetDir(QStringLiteral(".")),
|
||||
m_targetExtension(QStringLiteral(".m4a")),
|
||||
m_ffmpeg(new QProcess(this))
|
||||
FfmpegLauncher::FfmpegLauncher(PlayerWatcher &watcher, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_watcher(watcher)
|
||||
, m_sink(QStringLiteral("default"))
|
||||
, m_inputOptions()
|
||||
, m_options()
|
||||
, m_targetDir(QStringLiteral("."))
|
||||
, m_targetExtension(QStringLiteral(".m4a"))
|
||||
, m_ffmpeg(new QProcess(this))
|
||||
{
|
||||
connect(&watcher, &PlayerWatcher::nextSong, this, &FfmpegLauncher::nextSong);
|
||||
connect(&watcher, &PlayerWatcher::playbackStopped, this, &FfmpegLauncher::stopFfmpeg);
|
||||
connect(m_ffmpeg, &QProcess::started, this, &FfmpegLauncher::ffmpegStarted);
|
||||
connect(m_ffmpeg, static_cast<void(QProcess::*)(QProcess::ProcessError)>(&QProcess::error), this, &FfmpegLauncher::ffmpegError);
|
||||
connect(m_ffmpeg, static_cast<void(QProcess::*)(int)>(&QProcess::finished), this, &FfmpegLauncher::ffmpegFinished);
|
||||
connect(m_ffmpeg, static_cast<void (QProcess::*)(QProcess::ProcessError)>(&QProcess::error), this, &FfmpegLauncher::ffmpegError);
|
||||
connect(m_ffmpeg, static_cast<void (QProcess::*)(int)>(&QProcess::finished), this, &FfmpegLauncher::ffmpegFinished);
|
||||
m_ffmpeg->setProgram(QStringLiteral("ffmpeg"));
|
||||
m_ffmpeg->setProcessChannelMode(QProcess::ForwardedChannels);
|
||||
}
|
||||
|
||||
void addMetaData(QStringList &args, const QString &field, const QString &value)
|
||||
{
|
||||
if(!value.isEmpty()) {
|
||||
if (!value.isEmpty()) {
|
||||
args << QStringLiteral("-metadata");
|
||||
args << QStringLiteral("%1=%2").arg(field, value);
|
||||
}
|
||||
|
@ -72,12 +71,12 @@ void addMetaData(QStringList &args, const QString &field, const QString &value)
|
|||
void FfmpegLauncher::nextSong()
|
||||
{
|
||||
// skip ads
|
||||
if(m_watcher.isAd()) {
|
||||
if (m_watcher.isAd()) {
|
||||
return;
|
||||
}
|
||||
// pause player until ffmpeg has been started
|
||||
m_watcher.setSilent(true);
|
||||
if(m_watcher.isPlaying()) {
|
||||
if (m_watcher.isPlaying()) {
|
||||
m_watcher.pause();
|
||||
}
|
||||
// terminate/kill the current process
|
||||
|
@ -85,8 +84,9 @@ void FfmpegLauncher::nextSong()
|
|||
// determine output file, create target directory
|
||||
static const QString miscCategory(QStringLiteral("misc"));
|
||||
static const QString unknownTitle(QStringLiteral("unknown track"));
|
||||
const auto targetDirPath = QStringLiteral("%1/%2").arg(m_watcher.artist().isEmpty() ? miscCategory : validFileName(m_watcher.artist()), m_watcher.artist().isEmpty() ? miscCategory : validFileName(m_watcher.album()));
|
||||
if(!m_targetDir.mkpath(targetDirPath)) {
|
||||
const auto targetDirPath = QStringLiteral("%1/%2").arg(m_watcher.artist().isEmpty() ? miscCategory : validFileName(m_watcher.artist()),
|
||||
m_watcher.artist().isEmpty() ? miscCategory : validFileName(m_watcher.album()));
|
||||
if (!m_targetDir.mkpath(targetDirPath)) {
|
||||
cerr << "Error: Can not create target directory: " << targetDirPath << endl;
|
||||
return;
|
||||
}
|
||||
|
@ -94,52 +94,52 @@ void FfmpegLauncher::nextSong()
|
|||
targetDir.cd(targetDirPath);
|
||||
// determine track number
|
||||
QString number, length, year, genre, totalTracks, totalDisks;
|
||||
if(m_watcher.trackNumber()) {
|
||||
if(m_watcher.diskNumber()) {
|
||||
if (m_watcher.trackNumber()) {
|
||||
if (m_watcher.diskNumber()) {
|
||||
number = QStringLiteral("%2-%1").arg(m_watcher.trackNumber(), 2, 10, QLatin1Char('0')).arg(m_watcher.diskNumber());
|
||||
} else {
|
||||
number = QStringLiteral("%1").arg(m_watcher.trackNumber(), 2, 10, QLatin1Char('0'));
|
||||
}
|
||||
}
|
||||
if(!number.isEmpty()) {
|
||||
if (!number.isEmpty()) {
|
||||
number.append(QStringLiteral(" - "));
|
||||
}
|
||||
// read additional meta info
|
||||
// - from an INI file called info.ini in the album directory (must be created before recording)
|
||||
// - track lengths might be specified for each track in the [length] section (useful to get rid of advertisements at the end)
|
||||
// - year, genre, total_tracks and total_disks might be specified in the [general] section
|
||||
if(targetDir.exists(QStringLiteral("info.ini"))) {
|
||||
if (targetDir.exists(QStringLiteral("info.ini"))) {
|
||||
fstream infoFile;
|
||||
infoFile.exceptions(ios_base::badbit | ios_base::failbit);
|
||||
try {
|
||||
infoFile.open((targetDir.path() + QStringLiteral("/info.ini")).toLocal8Bit().data(), ios_base::in);
|
||||
infoFile.open((targetDir.path() + QStringLiteral("/info.ini")).toLocal8Bit().data(), ios_base::in);
|
||||
IniFile infoIni;
|
||||
infoIni.parse(infoFile);
|
||||
for(auto &scope : infoIni.data()) {
|
||||
if(scope.first == "length") {
|
||||
if(m_watcher.trackNumber()) {
|
||||
for (auto &scope : infoIni.data()) {
|
||||
if (scope.first == "length") {
|
||||
if (m_watcher.trackNumber()) {
|
||||
// reading length scope is only possible if track number known because the track number is used for mapping
|
||||
for(const auto &entry : scope.second) {
|
||||
for (const auto &entry : scope.second) {
|
||||
try {
|
||||
if(stringToNumber<unsigned int>(entry.first) == m_watcher.trackNumber()) {
|
||||
if (stringToNumber<unsigned int>(entry.first) == m_watcher.trackNumber()) {
|
||||
// length entry for this track
|
||||
length = QString::fromLocal8Bit(entry.second.data());
|
||||
break;
|
||||
}
|
||||
} catch(const ConversionException &) {
|
||||
} catch (const ConversionException &) {
|
||||
cerr << "Warning: Ignoring non-numeric key \"" << entry.first << "\" in [length] section of info.ini." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(scope.first == "general") {
|
||||
for(const auto &entry : scope.second) {
|
||||
if(entry.first == "year") {
|
||||
} else if (scope.first == "general") {
|
||||
for (const auto &entry : scope.second) {
|
||||
if (entry.first == "year") {
|
||||
year = QString::fromLocal8Bit(entry.second.data());
|
||||
} else if(entry.first == "genre") {
|
||||
} else if (entry.first == "genre") {
|
||||
genre = QString::fromLocal8Bit(entry.second.data());
|
||||
} else if(entry.first == "total_tracks") {
|
||||
} else if (entry.first == "total_tracks") {
|
||||
totalTracks = QString::fromLocal8Bit(entry.second.data());
|
||||
} else if(entry.first == "total_disks") {
|
||||
} else if (entry.first == "total_disks") {
|
||||
totalDisks = QString::fromLocal8Bit(entry.second.data());
|
||||
} else {
|
||||
cerr << "Warning: Ignoring unknown property \"" << entry.first << "\" in [general] section of info.ini." << endl;
|
||||
|
@ -149,17 +149,19 @@ void FfmpegLauncher::nextSong()
|
|||
cerr << "Warning: Ignoring unknown section [" << scope.first << "] in info.ini." << endl;
|
||||
}
|
||||
}
|
||||
} catch(...) {
|
||||
} catch (...) {
|
||||
::IoUtilities::catchIoFailure();
|
||||
cerr << "Warning: Can't parse info.ini because an IO error occured." << endl;
|
||||
}
|
||||
}
|
||||
// determine target name/path
|
||||
QString targetName(QStringLiteral("%3%1%2").arg(m_watcher.title().isEmpty() ? unknownTitle : validFileName(m_watcher.title()), m_targetExtension, number));
|
||||
QString targetName(
|
||||
QStringLiteral("%3%1%2").arg(m_watcher.title().isEmpty() ? unknownTitle : validFileName(m_watcher.title()), m_targetExtension, number));
|
||||
unsigned int count = 1;
|
||||
while(targetDir.exists(targetName)) {
|
||||
while (targetDir.exists(targetName)) {
|
||||
++count;
|
||||
targetName = QStringLiteral("%3%1 (%4)%2").arg(m_watcher.title().isEmpty() ? unknownTitle : m_watcher.title(), m_targetExtension, number).arg(count);
|
||||
targetName
|
||||
= QStringLiteral("%3%1 (%4)%2").arg(m_watcher.title().isEmpty() ? unknownTitle : m_watcher.title(), m_targetExtension, number).arg(count);
|
||||
}
|
||||
auto targetPath = targetDir.absoluteFilePath(targetName);
|
||||
// set input device
|
||||
|
@ -170,7 +172,7 @@ void FfmpegLauncher::nextSong()
|
|||
args << QStringLiteral("-i");
|
||||
args << m_sink;
|
||||
// set length if specified in info.ini
|
||||
if(!length.isEmpty() || !m_watcher.length().isNull()) {
|
||||
if (!length.isEmpty() || !m_watcher.length().isNull()) {
|
||||
args << "-t";
|
||||
args << (length.isEmpty() ? QString::number(m_watcher.length().totalSeconds()) : length);
|
||||
}
|
||||
|
@ -182,11 +184,13 @@ void FfmpegLauncher::nextSong()
|
|||
addMetaData(args, QStringLiteral("artist"), m_watcher.artist());
|
||||
addMetaData(args, QStringLiteral("genre"), genre.isEmpty() ? m_watcher.genre() : genre);
|
||||
addMetaData(args, QStringLiteral("year"), year.isEmpty() ? m_watcher.year() : year);
|
||||
if(m_watcher.trackNumber()) {
|
||||
addMetaData(args, QStringLiteral("track"), totalTracks.isEmpty() ? QString::number(m_watcher.trackNumber()) : QString::number(m_watcher.trackNumber()) % QChar('/') % totalTracks);
|
||||
if (m_watcher.trackNumber()) {
|
||||
addMetaData(args, QStringLiteral("track"),
|
||||
totalTracks.isEmpty() ? QString::number(m_watcher.trackNumber()) : QString::number(m_watcher.trackNumber()) % QChar('/') % totalTracks);
|
||||
}
|
||||
if(m_watcher.diskNumber()) {
|
||||
addMetaData(args, QStringLiteral("disk"), totalDisks.isEmpty() ? QString::number(m_watcher.diskNumber()) : QString::number(m_watcher.diskNumber()) % QChar('/') % totalDisks);
|
||||
if (m_watcher.diskNumber()) {
|
||||
addMetaData(args, QStringLiteral("disk"),
|
||||
totalDisks.isEmpty() ? QString::number(m_watcher.diskNumber()) : QString::number(m_watcher.diskNumber()) % QChar('/') % totalDisks);
|
||||
}
|
||||
// set output file
|
||||
args << targetPath;
|
||||
|
@ -200,13 +204,13 @@ void FfmpegLauncher::nextSong()
|
|||
|
||||
void FfmpegLauncher::stopFfmpeg()
|
||||
{
|
||||
if(m_ffmpeg->state() != QProcess::NotRunning) {
|
||||
if (m_ffmpeg->state() != QProcess::NotRunning) {
|
||||
m_ffmpeg->terminate();
|
||||
m_ffmpeg->waitForFinished(10000);
|
||||
if(m_ffmpeg->state() != QProcess::NotRunning) {
|
||||
if (m_ffmpeg->state() != QProcess::NotRunning) {
|
||||
m_ffmpeg->kill();
|
||||
m_ffmpeg->waitForFinished(5000);
|
||||
if(m_ffmpeg->state() != QProcess::NotRunning) {
|
||||
if (m_ffmpeg->state() != QProcess::NotRunning) {
|
||||
throw runtime_error("Unable to terminate/kill ffmpeg process.");
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +221,7 @@ void FfmpegLauncher::ffmpegStarted()
|
|||
{
|
||||
cerr << "Started ffmpeg: ";
|
||||
cerr << m_ffmpeg->program();
|
||||
for(const auto &arg : m_ffmpeg->arguments()) {
|
||||
for (const auto &arg : m_ffmpeg->arguments()) {
|
||||
cerr << ' ' << arg;
|
||||
}
|
||||
cerr << endl;
|
||||
|
@ -232,5 +236,4 @@ void FfmpegLauncher::ffmpegFinished(int exitCode)
|
|||
{
|
||||
cerr << "FFmpeg finished with exit code " << exitCode << endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
#ifndef FFMPEGLAUNCHER_H
|
||||
#define FFMPEGLAUNCHER_H
|
||||
|
||||
#include <QDir>
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
#include <QDir>
|
||||
|
||||
namespace DBusSoundRecorder {
|
||||
|
||||
class PlayerWatcher;
|
||||
|
||||
class FfmpegLauncher : public QObject
|
||||
{
|
||||
class FfmpegLauncher : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FfmpegLauncher(PlayerWatcher &watcher, QObject *parent = nullptr);
|
||||
|
@ -68,7 +67,6 @@ inline void FfmpegLauncher::setTargetExtension(const QString &extension)
|
|||
{
|
||||
m_targetExtension = extension.startsWith(QChar('.')) ? extension : QStringLiteral(".") + extension;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // FFMPEGLAUNCHER_H
|
||||
|
|
37
main.cpp
37
main.cpp
|
@ -1,5 +1,5 @@
|
|||
#include "playerwatcher.h"
|
||||
#include "ffmpeglauncher.h"
|
||||
#include "playerwatcher.h"
|
||||
|
||||
#include "resources/config.h"
|
||||
|
||||
|
@ -24,35 +24,36 @@ int main(int argc, char *argv[])
|
|||
recordArg.setDenotesOperation(true);
|
||||
Argument applicationArg("application", 'a', "specifies the application providing meta information via D-Bus interface");
|
||||
applicationArg.setRequired(true);
|
||||
applicationArg.setValueNames({"name"});
|
||||
applicationArg.setValueNames({ "name" });
|
||||
applicationArg.setRequiredValueCount(1);
|
||||
Argument sinkArg("sink", 's', "specifies the Pulse Audio sink to be recorded (see pactl list short sinks)");
|
||||
sinkArg.setValueNames({"sink"});
|
||||
sinkArg.setValueNames({ "sink" });
|
||||
sinkArg.setRequiredValueCount(1);
|
||||
sinkArg.setCombinable(true);
|
||||
Argument ffmpegInputOptions("ffmpeg-input-options", 'i', "specifies options for the ffmpeg input device");
|
||||
ffmpegInputOptions.setRequiredValueCount(1);
|
||||
ffmpegInputOptions.setCombinable(true);
|
||||
Argument targetDirArg("target-dir", 't', "specifies the target directory");
|
||||
targetDirArg.setValueNames({"path"});
|
||||
targetDirArg.setValueNames({ "path" });
|
||||
targetDirArg.setRequiredValueCount(1);
|
||||
targetDirArg.setCombinable(true);
|
||||
Argument targetExtArg("target-extension", 'e', "specifies the target extension (default is .m4a)");
|
||||
targetExtArg.setValueNames({"extension"});
|
||||
targetExtArg.setValueNames({ "extension" });
|
||||
targetExtArg.setRequiredValueCount(1);
|
||||
targetExtArg.setCombinable(true);
|
||||
Argument ignorePlaybackStatusArg("ignore-playback-status", '\0', "ignores the playback status (does not call PlaybackStatus())");
|
||||
ignorePlaybackStatusArg.setCombinable(true);
|
||||
Argument ffmpegBinArg("ffmpeg-bin", 'f', "specifies the path to the ffmpeg binary");
|
||||
ffmpegBinArg.setValueNames({"path"});
|
||||
ffmpegBinArg.setValueNames({ "path" });
|
||||
ffmpegBinArg.setRequiredValueCount(1);
|
||||
ffmpegBinArg.setCombinable(true);
|
||||
Argument ffmpegOptions("ffmpeg-options", 'o', "specifies options for ffmpeg");
|
||||
ffmpegOptions.setValueNames({"options"});
|
||||
ffmpegOptions.setValueNames({ "options" });
|
||||
ffmpegOptions.setRequiredValueCount(1);
|
||||
ffmpegOptions.setCombinable(true);
|
||||
recordArg.setSubArguments({&applicationArg, &sinkArg, &ffmpegInputOptions, &targetDirArg, &targetExtArg, &ignorePlaybackStatusArg, &ffmpegBinArg, &ffmpegOptions});
|
||||
parser.setMainArguments({&helpArg, &recordArg});
|
||||
recordArg.setSubArguments(
|
||||
{ &applicationArg, &sinkArg, &ffmpegInputOptions, &targetDirArg, &targetExtArg, &ignorePlaybackStatusArg, &ffmpegBinArg, &ffmpegOptions });
|
||||
parser.setMainArguments({ &helpArg, &recordArg });
|
||||
// parse command line arguments
|
||||
try {
|
||||
parser.parseArgs(argc, argv);
|
||||
|
@ -61,7 +62,7 @@ int main(int argc, char *argv[])
|
|||
return 1;
|
||||
}
|
||||
try {
|
||||
if(recordArg.isPresent()) {
|
||||
if (recordArg.isPresent()) {
|
||||
// start watching/recording
|
||||
cerr << "Watching MPRIS service of the specified application \"" << applicationArg.values().front() << "\" ..." << endl;
|
||||
// create app loop, player watcher and ffmpeg launcher
|
||||
|
@ -69,31 +70,31 @@ int main(int argc, char *argv[])
|
|||
PlayerWatcher watcher(QString::fromLocal8Bit(applicationArg.values().front()), ignorePlaybackStatusArg.isPresent());
|
||||
FfmpegLauncher ffmpeg(watcher);
|
||||
// pass specified args to ffmpeg launcher
|
||||
if(sinkArg.isPresent()) {
|
||||
if (sinkArg.isPresent()) {
|
||||
ffmpeg.setSink(QString::fromLocal8Bit(sinkArg.values().front()));
|
||||
}
|
||||
if(ffmpegInputOptions.isPresent()) {
|
||||
if (ffmpegInputOptions.isPresent()) {
|
||||
ffmpeg.setFFmpegInputOptions(QString::fromLocal8Bit(ffmpegInputOptions.values().front()));
|
||||
}
|
||||
if(ffmpegBinArg.isPresent()) {
|
||||
if (ffmpegBinArg.isPresent()) {
|
||||
ffmpeg.setFFmpegBinary(QString::fromLocal8Bit(ffmpegBinArg.values().front()));
|
||||
}
|
||||
if(ffmpegOptions.isPresent()) {
|
||||
if (ffmpegOptions.isPresent()) {
|
||||
ffmpeg.setFFmpegOptions(QString::fromLocal8Bit(ffmpegOptions.values().front()));
|
||||
}
|
||||
if(targetDirArg.isPresent()) {
|
||||
if (targetDirArg.isPresent()) {
|
||||
ffmpeg.setTargetDir(QString::fromLocal8Bit(targetDirArg.values().front()));
|
||||
}
|
||||
if(targetExtArg.isPresent()) {
|
||||
if (targetExtArg.isPresent()) {
|
||||
ffmpeg.setTargetExtension(QString::fromLocal8Bit(targetExtArg.values().front()));
|
||||
}
|
||||
// enter app loop
|
||||
return app.exec();
|
||||
} else if(!helpArg.isPresent()) {
|
||||
} else if (!helpArg.isPresent()) {
|
||||
cerr << "No operation specified." << endl;
|
||||
return 2;
|
||||
}
|
||||
} catch(const runtime_error &e) {
|
||||
} catch (const runtime_error &e) {
|
||||
cerr << "Fatal error: " << e.what() << endl;
|
||||
return 3;
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
#include "playerinterface.h"
|
||||
#include "propertiesinterface.h"
|
||||
|
||||
#include <QDBusServiceWatcher>
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusServiceWatcher>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
@ -13,26 +13,29 @@ using namespace ChronoUtilities;
|
|||
|
||||
namespace DBusSoundRecorder {
|
||||
|
||||
inline ostream &operator <<(ostream &stream, const QString &str)
|
||||
inline ostream &operator<<(ostream &stream, const QString &str)
|
||||
{
|
||||
stream << str.toLocal8Bit().data();
|
||||
return stream;
|
||||
}
|
||||
|
||||
PlayerWatcher::PlayerWatcher(const QString &appName, bool ignorePlaybackStatus, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_mediaPlayerInterfaceName(QStringLiteral("org.mpris.MediaPlayer2.%1").arg(appName)),
|
||||
m_mediaPlayerServiceWatcher(new QDBusServiceWatcher(m_mediaPlayerInterfaceName, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange, this)),
|
||||
m_propertiesInterface(new OrgFreedesktopDBusPropertiesInterface(m_mediaPlayerInterfaceName, QStringLiteral("/org/mpris/MediaPlayer2"), QDBusConnection::sessionBus(), this)),
|
||||
m_playerInterface(new OrgMprisMediaPlayer2PlayerInterface(m_mediaPlayerInterfaceName, QStringLiteral("/org/mpris/MediaPlayer2"), QDBusConnection::sessionBus(), this)),
|
||||
m_isPlaying(false),
|
||||
m_isAd(false),
|
||||
m_trackNumber(0),
|
||||
m_diskNumber(0),
|
||||
m_silent(false),
|
||||
m_ignorePlaybackStatus(ignorePlaybackStatus)
|
||||
PlayerWatcher::PlayerWatcher(const QString &appName, bool ignorePlaybackStatus, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_mediaPlayerInterfaceName(QStringLiteral("org.mpris.MediaPlayer2.%1").arg(appName))
|
||||
, m_mediaPlayerServiceWatcher(
|
||||
new QDBusServiceWatcher(m_mediaPlayerInterfaceName, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange, this))
|
||||
, m_propertiesInterface(new OrgFreedesktopDBusPropertiesInterface(
|
||||
m_mediaPlayerInterfaceName, QStringLiteral("/org/mpris/MediaPlayer2"), QDBusConnection::sessionBus(), this))
|
||||
, m_playerInterface(new OrgMprisMediaPlayer2PlayerInterface(
|
||||
m_mediaPlayerInterfaceName, QStringLiteral("/org/mpris/MediaPlayer2"), QDBusConnection::sessionBus(), this))
|
||||
, m_isPlaying(false)
|
||||
, m_isAd(false)
|
||||
, m_trackNumber(0)
|
||||
, m_diskNumber(0)
|
||||
, m_silent(false)
|
||||
, m_ignorePlaybackStatus(ignorePlaybackStatus)
|
||||
{
|
||||
if(!connect(m_mediaPlayerServiceWatcher, &QDBusServiceWatcher::serviceOwnerChanged, this, &PlayerWatcher::serviceOwnerChanged)) {
|
||||
if (!connect(m_mediaPlayerServiceWatcher, &QDBusServiceWatcher::serviceOwnerChanged, this, &PlayerWatcher::serviceOwnerChanged)) {
|
||||
cout << "Warning: Unable to connect \"serviceOwnerChanged\" signal of service watcher." << endl;
|
||||
}
|
||||
// The code below does not work anymore with the newest version of Spotify.
|
||||
|
@ -40,7 +43,8 @@ PlayerWatcher::PlayerWatcher(const QString &appName, bool ignorePlaybackStatus,
|
|||
// cout << "Warning: Unable to connect \"PropertiesChanged\" signal of properties interface." << endl;
|
||||
//}
|
||||
// However, the following works:
|
||||
if(!QDBusConnection::sessionBus().connect(m_mediaPlayerInterfaceName, QStringLiteral("/org/mpris/MediaPlayer2"), QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("PropertiesChanged"), this, SLOT(propertiesChanged()))) {
|
||||
if (!QDBusConnection::sessionBus().connect(m_mediaPlayerInterfaceName, QStringLiteral("/org/mpris/MediaPlayer2"),
|
||||
QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("PropertiesChanged"), this, SLOT(propertiesChanged()))) {
|
||||
cout << "Warning: Unable to connect \"PropertiesChanged\" signal of properties interface." << endl;
|
||||
}
|
||||
propertiesChanged();
|
||||
|
@ -68,10 +72,10 @@ void PlayerWatcher::playPause()
|
|||
|
||||
void PlayerWatcher::serviceOwnerChanged(const QString &service, const QString &oldOwner, const QString &newOwner)
|
||||
{
|
||||
if(oldOwner.isEmpty()) {
|
||||
if (oldOwner.isEmpty()) {
|
||||
cerr << "MPRIS service \"" << service << "\" is now online" << endl;
|
||||
}
|
||||
if(newOwner.isEmpty()) {
|
||||
if (newOwner.isEmpty()) {
|
||||
cerr << "MPRIS service \"" << service << "\" went offline" << endl;
|
||||
}
|
||||
}
|
||||
|
@ -85,18 +89,18 @@ void PlayerWatcher::propertiesChanged()
|
|||
QString album = metadata.value(QStringLiteral("xesam:album")).toString();
|
||||
QString artist = metadata.value(QStringLiteral("xesam:artist")).toString();
|
||||
bool isPlaying;
|
||||
if(m_ignorePlaybackStatus) {
|
||||
if (m_ignorePlaybackStatus) {
|
||||
// determine playback status by checking whether there is a song title
|
||||
isPlaying = !title.isEmpty();
|
||||
} else {
|
||||
isPlaying = !m_playerInterface->playbackStatus().compare(QLatin1String("playing"), Qt::CaseInsensitive);
|
||||
isPlaying = !m_playerInterface->playbackStatus().compare(QLatin1String("playing"), Qt::CaseInsensitive);
|
||||
}
|
||||
if(isPlaying) {
|
||||
if(!m_isPlaying) {
|
||||
if (isPlaying) {
|
||||
if (!m_isPlaying) {
|
||||
cerr << "Playback started" << endl;
|
||||
}
|
||||
// use title, album and artist to identify song
|
||||
if(m_title != title || m_album != album || m_artist != artist) {
|
||||
if (m_title != title || m_album != album || m_artist != artist) {
|
||||
// next song playing
|
||||
m_title = title;
|
||||
m_album = album;
|
||||
|
@ -105,34 +109,34 @@ void PlayerWatcher::propertiesChanged()
|
|||
m_year = metadata.value(QStringLiteral("xesam:contentCreated")).toString();
|
||||
m_genre = metadata.value(QStringLiteral("xesam:genre")).toString();
|
||||
m_trackNumber = metadata.value(QStringLiteral("xesam:tracknumber")).toUInt();
|
||||
if(!m_trackNumber) {
|
||||
if (!m_trackNumber) {
|
||||
m_trackNumber = metadata.value(QStringLiteral("xesam:trackNumber")).toUInt();
|
||||
}
|
||||
m_diskNumber = metadata.value(QStringLiteral("xesam:discnumber")).toUInt();
|
||||
if(!m_diskNumber) {
|
||||
if (!m_diskNumber) {
|
||||
m_diskNumber = metadata.value(QStringLiteral("xesam:discNumber")).toUInt();
|
||||
}
|
||||
m_length = TimeSpan(metadata.value(QStringLiteral("mpris:length")).toULongLong() * 10);
|
||||
// notify
|
||||
cerr << "Next song: " << m_title << endl;
|
||||
if(!m_isPlaying && !m_silent) {
|
||||
if (!m_isPlaying && !m_silent) {
|
||||
m_isPlaying = true;
|
||||
emit playbackStarted();
|
||||
}
|
||||
if(!m_silent) {
|
||||
if (!m_silent) {
|
||||
m_isPlaying = true;
|
||||
emit nextSong();
|
||||
}
|
||||
} else if(!m_isPlaying) {
|
||||
if(!m_silent) {
|
||||
} else if (!m_isPlaying) {
|
||||
if (!m_silent) {
|
||||
m_isPlaying = true;
|
||||
emit playbackStarted();
|
||||
}
|
||||
}
|
||||
} else if(m_isPlaying) {
|
||||
} else if (m_isPlaying) {
|
||||
m_isPlaying = false;
|
||||
cerr << "Playback stopped" << endl;
|
||||
if(!m_silent) {
|
||||
if (!m_silent) {
|
||||
emit playbackStopped();
|
||||
}
|
||||
}
|
||||
|
@ -147,5 +151,4 @@ void PlayerWatcher::seeked(qlonglong pos)
|
|||
{
|
||||
cerr << "Seeked: " << pos << endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,8 +12,7 @@ class OrgMprisMediaPlayer2PlayerInterface;
|
|||
|
||||
namespace DBusSoundRecorder {
|
||||
|
||||
class PlayerWatcher : public QObject
|
||||
{
|
||||
class PlayerWatcher : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PlayerWatcher(const QString &appName, bool ignorePlaybackStatus = false, QObject *parent = nullptr);
|
||||
|
@ -127,7 +126,6 @@ inline void PlayerWatcher::setSilent(bool silent)
|
|||
{
|
||||
m_silent = silent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // PLAYERWATCHER_H
|
||||
|
|
Loading…
Reference in New Issue