Apply clang-format

This commit is contained in:
Martchus 2017-05-01 03:39:45 +02:00
parent 742dc25984
commit 778b31c0ed
6 changed files with 128 additions and 122 deletions

3
.gitignore vendored
View File

@ -39,3 +39,6 @@ Makefile*
# documentation # documentation
/doc /doc
# clang-format
/.clang-format

View File

@ -1,14 +1,14 @@
#include "ffmpeglauncher.h" #include "ffmpeglauncher.h"
#include "playerwatcher.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/conversion/stringconversion.h>
#include <c++utilities/io/catchiofailure.h>
#include <c++utilities/io/inifile.h>
#include <QStringBuilder> #include <QStringBuilder>
#include <iostream>
#include <fstream> #include <fstream>
#include <iostream>
using namespace std; using namespace std;
using namespace IoUtilities; using namespace IoUtilities;
@ -16,7 +16,7 @@ using namespace ConversionUtilities;
namespace DBusSoundRecorder { namespace DBusSoundRecorder {
inline ostream &operator <<(ostream &stream, const QString &str) inline ostream &operator<<(ostream &stream, const QString &str)
{ {
stream << str.toLocal8Bit().data(); stream << str.toLocal8Bit().data();
return stream; return stream;
@ -25,45 +25,44 @@ inline ostream &operator <<(ostream &stream, const QString &str)
inline QString validFileName(const QString &text) inline QString validFileName(const QString &text)
{ {
QString copy(text); QString copy(text);
copy copy.replace(QChar('\\'), QLatin1String(" - "))
.replace(QChar('\\'), QLatin1String(" - ")) .replace(QChar('/'), QLatin1String(" - "))
.replace(QChar('/'), QLatin1String(" - ")) .replace(QChar('\n'), QString())
.replace(QChar('\n'), QString()) .replace(QChar('\r'), QString())
.replace(QChar('\r'), QString()) .replace(QChar('\f'), QString())
.replace(QChar('\f'), QString()) .replace(QChar('<'), QString())
.replace(QChar('<'), QString()) .replace(QChar('>'), QString())
.replace(QChar('>'), QString()) .replace(QChar('?'), QString())
.replace(QChar('?'), QString()) .replace(QChar('*'), QString())
.replace(QChar('*'), QString()) .replace(QChar('!'), QString())
.replace(QChar('!'), QString()) .replace(QChar('|'), QString())
.replace(QChar('|'), QString()) .replace(QLatin1String(": "), QLatin1String(" - "))
.replace(QLatin1String(": "), QLatin1String(" - ")) .replace(QChar(':'), QChar('-'));
.replace(QChar(':'), QChar('-'));
return copy; return copy;
} }
FfmpegLauncher::FfmpegLauncher(PlayerWatcher &watcher, QObject *parent) : FfmpegLauncher::FfmpegLauncher(PlayerWatcher &watcher, QObject *parent)
QObject(parent), : QObject(parent)
m_watcher(watcher), , m_watcher(watcher)
m_sink(QStringLiteral("default")), , m_sink(QStringLiteral("default"))
m_inputOptions(), , m_inputOptions()
m_options(), , m_options()
m_targetDir(QStringLiteral(".")), , m_targetDir(QStringLiteral("."))
m_targetExtension(QStringLiteral(".m4a")), , m_targetExtension(QStringLiteral(".m4a"))
m_ffmpeg(new QProcess(this)) , m_ffmpeg(new QProcess(this))
{ {
connect(&watcher, &PlayerWatcher::nextSong, this, &FfmpegLauncher::nextSong); connect(&watcher, &PlayerWatcher::nextSong, this, &FfmpegLauncher::nextSong);
connect(&watcher, &PlayerWatcher::playbackStopped, this, &FfmpegLauncher::stopFfmpeg); connect(&watcher, &PlayerWatcher::playbackStopped, this, &FfmpegLauncher::stopFfmpeg);
connect(m_ffmpeg, &QProcess::started, this, &FfmpegLauncher::ffmpegStarted); 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::*)(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::*)(int)>(&QProcess::finished), this, &FfmpegLauncher::ffmpegFinished);
m_ffmpeg->setProgram(QStringLiteral("ffmpeg")); m_ffmpeg->setProgram(QStringLiteral("ffmpeg"));
m_ffmpeg->setProcessChannelMode(QProcess::ForwardedChannels); m_ffmpeg->setProcessChannelMode(QProcess::ForwardedChannels);
} }
void addMetaData(QStringList &args, const QString &field, const QString &value) void addMetaData(QStringList &args, const QString &field, const QString &value)
{ {
if(!value.isEmpty()) { if (!value.isEmpty()) {
args << QStringLiteral("-metadata"); args << QStringLiteral("-metadata");
args << QStringLiteral("%1=%2").arg(field, value); args << QStringLiteral("%1=%2").arg(field, value);
} }
@ -72,12 +71,12 @@ void addMetaData(QStringList &args, const QString &field, const QString &value)
void FfmpegLauncher::nextSong() void FfmpegLauncher::nextSong()
{ {
// skip ads // skip ads
if(m_watcher.isAd()) { if (m_watcher.isAd()) {
return; return;
} }
// pause player until ffmpeg has been started // pause player until ffmpeg has been started
m_watcher.setSilent(true); m_watcher.setSilent(true);
if(m_watcher.isPlaying()) { if (m_watcher.isPlaying()) {
m_watcher.pause(); m_watcher.pause();
} }
// terminate/kill the current process // terminate/kill the current process
@ -85,8 +84,9 @@ void FfmpegLauncher::nextSong()
// determine output file, create target directory // determine output file, create target directory
static const QString miscCategory(QStringLiteral("misc")); static const QString miscCategory(QStringLiteral("misc"));
static const QString unknownTitle(QStringLiteral("unknown track")); 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())); const auto targetDirPath = QStringLiteral("%1/%2").arg(m_watcher.artist().isEmpty() ? miscCategory : validFileName(m_watcher.artist()),
if(!m_targetDir.mkpath(targetDirPath)) { m_watcher.artist().isEmpty() ? miscCategory : validFileName(m_watcher.album()));
if (!m_targetDir.mkpath(targetDirPath)) {
cerr << "Error: Can not create target directory: " << targetDirPath << endl; cerr << "Error: Can not create target directory: " << targetDirPath << endl;
return; return;
} }
@ -94,52 +94,52 @@ void FfmpegLauncher::nextSong()
targetDir.cd(targetDirPath); targetDir.cd(targetDirPath);
// determine track number // determine track number
QString number, length, year, genre, totalTracks, totalDisks; QString number, length, year, genre, totalTracks, totalDisks;
if(m_watcher.trackNumber()) { if (m_watcher.trackNumber()) {
if(m_watcher.diskNumber()) { if (m_watcher.diskNumber()) {
number = QStringLiteral("%2-%1").arg(m_watcher.trackNumber(), 2, 10, QLatin1Char('0')).arg(m_watcher.diskNumber()); number = QStringLiteral("%2-%1").arg(m_watcher.trackNumber(), 2, 10, QLatin1Char('0')).arg(m_watcher.diskNumber());
} else { } else {
number = QStringLiteral("%1").arg(m_watcher.trackNumber(), 2, 10, QLatin1Char('0')); number = QStringLiteral("%1").arg(m_watcher.trackNumber(), 2, 10, QLatin1Char('0'));
} }
} }
if(!number.isEmpty()) { if (!number.isEmpty()) {
number.append(QStringLiteral(" - ")); number.append(QStringLiteral(" - "));
} }
// read additional meta info // read additional meta info
// - from an INI file called info.ini in the album directory (must be created before recording) // - 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) // - 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 // - 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; fstream infoFile;
infoFile.exceptions(ios_base::badbit | ios_base::failbit); infoFile.exceptions(ios_base::badbit | ios_base::failbit);
try { 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; IniFile infoIni;
infoIni.parse(infoFile); infoIni.parse(infoFile);
for(auto &scope : infoIni.data()) { for (auto &scope : infoIni.data()) {
if(scope.first == "length") { if (scope.first == "length") {
if(m_watcher.trackNumber()) { if (m_watcher.trackNumber()) {
// reading length scope is only possible if track number known because the track number is used for mapping // 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 { 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 entry for this track
length = QString::fromLocal8Bit(entry.second.data()); length = QString::fromLocal8Bit(entry.second.data());
break; break;
} }
} catch(const ConversionException &) { } catch (const ConversionException &) {
cerr << "Warning: Ignoring non-numeric key \"" << entry.first << "\" in [length] section of info.ini." << endl; cerr << "Warning: Ignoring non-numeric key \"" << entry.first << "\" in [length] section of info.ini." << endl;
} }
} }
} }
} else if(scope.first == "general") { } else if (scope.first == "general") {
for(const auto &entry : scope.second) { for (const auto &entry : scope.second) {
if(entry.first == "year") { if (entry.first == "year") {
year = QString::fromLocal8Bit(entry.second.data()); year = QString::fromLocal8Bit(entry.second.data());
} else if(entry.first == "genre") { } else if (entry.first == "genre") {
genre = QString::fromLocal8Bit(entry.second.data()); genre = QString::fromLocal8Bit(entry.second.data());
} else if(entry.first == "total_tracks") { } else if (entry.first == "total_tracks") {
totalTracks = QString::fromLocal8Bit(entry.second.data()); totalTracks = QString::fromLocal8Bit(entry.second.data());
} else if(entry.first == "total_disks") { } else if (entry.first == "total_disks") {
totalDisks = QString::fromLocal8Bit(entry.second.data()); totalDisks = QString::fromLocal8Bit(entry.second.data());
} else { } else {
cerr << "Warning: Ignoring unknown property \"" << entry.first << "\" in [general] section of info.ini." << endl; 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; cerr << "Warning: Ignoring unknown section [" << scope.first << "] in info.ini." << endl;
} }
} }
} catch(...) { } catch (...) {
::IoUtilities::catchIoFailure(); ::IoUtilities::catchIoFailure();
cerr << "Warning: Can't parse info.ini because an IO error occured." << endl; cerr << "Warning: Can't parse info.ini because an IO error occured." << endl;
} }
} }
// determine target name/path // 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; unsigned int count = 1;
while(targetDir.exists(targetName)) { while (targetDir.exists(targetName)) {
++count; ++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); auto targetPath = targetDir.absoluteFilePath(targetName);
// set input device // set input device
@ -170,7 +172,7 @@ void FfmpegLauncher::nextSong()
args << QStringLiteral("-i"); args << QStringLiteral("-i");
args << m_sink; args << m_sink;
// set length if specified in info.ini // set length if specified in info.ini
if(!length.isEmpty() || !m_watcher.length().isNull()) { if (!length.isEmpty() || !m_watcher.length().isNull()) {
args << "-t"; args << "-t";
args << (length.isEmpty() ? QString::number(m_watcher.length().totalSeconds()) : length); 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("artist"), m_watcher.artist());
addMetaData(args, QStringLiteral("genre"), genre.isEmpty() ? m_watcher.genre() : genre); addMetaData(args, QStringLiteral("genre"), genre.isEmpty() ? m_watcher.genre() : genre);
addMetaData(args, QStringLiteral("year"), year.isEmpty() ? m_watcher.year() : year); addMetaData(args, QStringLiteral("year"), year.isEmpty() ? m_watcher.year() : year);
if(m_watcher.trackNumber()) { if (m_watcher.trackNumber()) {
addMetaData(args, QStringLiteral("track"), totalTracks.isEmpty() ? QString::number(m_watcher.trackNumber()) : QString::number(m_watcher.trackNumber()) % QChar('/') % totalTracks); addMetaData(args, QStringLiteral("track"),
totalTracks.isEmpty() ? QString::number(m_watcher.trackNumber()) : QString::number(m_watcher.trackNumber()) % QChar('/') % totalTracks);
} }
if(m_watcher.diskNumber()) { if (m_watcher.diskNumber()) {
addMetaData(args, QStringLiteral("disk"), totalDisks.isEmpty() ? QString::number(m_watcher.diskNumber()) : QString::number(m_watcher.diskNumber()) % QChar('/') % totalDisks); addMetaData(args, QStringLiteral("disk"),
totalDisks.isEmpty() ? QString::number(m_watcher.diskNumber()) : QString::number(m_watcher.diskNumber()) % QChar('/') % totalDisks);
} }
// set output file // set output file
args << targetPath; args << targetPath;
@ -200,13 +204,13 @@ void FfmpegLauncher::nextSong()
void FfmpegLauncher::stopFfmpeg() void FfmpegLauncher::stopFfmpeg()
{ {
if(m_ffmpeg->state() != QProcess::NotRunning) { if (m_ffmpeg->state() != QProcess::NotRunning) {
m_ffmpeg->terminate(); m_ffmpeg->terminate();
m_ffmpeg->waitForFinished(10000); m_ffmpeg->waitForFinished(10000);
if(m_ffmpeg->state() != QProcess::NotRunning) { if (m_ffmpeg->state() != QProcess::NotRunning) {
m_ffmpeg->kill(); m_ffmpeg->kill();
m_ffmpeg->waitForFinished(5000); 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."); throw runtime_error("Unable to terminate/kill ffmpeg process.");
} }
} }
@ -217,7 +221,7 @@ void FfmpegLauncher::ffmpegStarted()
{ {
cerr << "Started ffmpeg: "; cerr << "Started ffmpeg: ";
cerr << m_ffmpeg->program(); cerr << m_ffmpeg->program();
for(const auto &arg : m_ffmpeg->arguments()) { for (const auto &arg : m_ffmpeg->arguments()) {
cerr << ' ' << arg; cerr << ' ' << arg;
} }
cerr << endl; cerr << endl;
@ -232,5 +236,4 @@ void FfmpegLauncher::ffmpegFinished(int exitCode)
{ {
cerr << "FFmpeg finished with exit code " << exitCode << endl; cerr << "FFmpeg finished with exit code " << exitCode << endl;
} }
} }

View File

@ -1,16 +1,15 @@
#ifndef FFMPEGLAUNCHER_H #ifndef FFMPEGLAUNCHER_H
#define FFMPEGLAUNCHER_H #define FFMPEGLAUNCHER_H
#include <QDir>
#include <QObject> #include <QObject>
#include <QProcess> #include <QProcess>
#include <QDir>
namespace DBusSoundRecorder { namespace DBusSoundRecorder {
class PlayerWatcher; class PlayerWatcher;
class FfmpegLauncher : public QObject class FfmpegLauncher : public QObject {
{
Q_OBJECT Q_OBJECT
public: public:
explicit FfmpegLauncher(PlayerWatcher &watcher, QObject *parent = nullptr); 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; m_targetExtension = extension.startsWith(QChar('.')) ? extension : QStringLiteral(".") + extension;
} }
} }
#endif // FFMPEGLAUNCHER_H #endif // FFMPEGLAUNCHER_H

View File

@ -1,5 +1,5 @@
#include "playerwatcher.h"
#include "ffmpeglauncher.h" #include "ffmpeglauncher.h"
#include "playerwatcher.h"
#include "resources/config.h" #include "resources/config.h"
@ -24,35 +24,36 @@ int main(int argc, char *argv[])
recordArg.setDenotesOperation(true); recordArg.setDenotesOperation(true);
Argument applicationArg("application", 'a', "specifies the application providing meta information via D-Bus interface"); Argument applicationArg("application", 'a', "specifies the application providing meta information via D-Bus interface");
applicationArg.setRequired(true); applicationArg.setRequired(true);
applicationArg.setValueNames({"name"}); applicationArg.setValueNames({ "name" });
applicationArg.setRequiredValueCount(1); applicationArg.setRequiredValueCount(1);
Argument sinkArg("sink", 's', "specifies the Pulse Audio sink to be recorded (see pactl list short sinks)"); 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.setRequiredValueCount(1);
sinkArg.setCombinable(true); sinkArg.setCombinable(true);
Argument ffmpegInputOptions("ffmpeg-input-options", 'i', "specifies options for the ffmpeg input device"); Argument ffmpegInputOptions("ffmpeg-input-options", 'i', "specifies options for the ffmpeg input device");
ffmpegInputOptions.setRequiredValueCount(1); ffmpegInputOptions.setRequiredValueCount(1);
ffmpegInputOptions.setCombinable(true); ffmpegInputOptions.setCombinable(true);
Argument targetDirArg("target-dir", 't', "specifies the target directory"); Argument targetDirArg("target-dir", 't', "specifies the target directory");
targetDirArg.setValueNames({"path"}); targetDirArg.setValueNames({ "path" });
targetDirArg.setRequiredValueCount(1); targetDirArg.setRequiredValueCount(1);
targetDirArg.setCombinable(true); targetDirArg.setCombinable(true);
Argument targetExtArg("target-extension", 'e', "specifies the target extension (default is .m4a)"); Argument targetExtArg("target-extension", 'e', "specifies the target extension (default is .m4a)");
targetExtArg.setValueNames({"extension"}); targetExtArg.setValueNames({ "extension" });
targetExtArg.setRequiredValueCount(1); targetExtArg.setRequiredValueCount(1);
targetExtArg.setCombinable(true); targetExtArg.setCombinable(true);
Argument ignorePlaybackStatusArg("ignore-playback-status", '\0', "ignores the playback status (does not call PlaybackStatus())"); Argument ignorePlaybackStatusArg("ignore-playback-status", '\0', "ignores the playback status (does not call PlaybackStatus())");
ignorePlaybackStatusArg.setCombinable(true); ignorePlaybackStatusArg.setCombinable(true);
Argument ffmpegBinArg("ffmpeg-bin", 'f', "specifies the path to the ffmpeg binary"); Argument ffmpegBinArg("ffmpeg-bin", 'f', "specifies the path to the ffmpeg binary");
ffmpegBinArg.setValueNames({"path"}); ffmpegBinArg.setValueNames({ "path" });
ffmpegBinArg.setRequiredValueCount(1); ffmpegBinArg.setRequiredValueCount(1);
ffmpegBinArg.setCombinable(true); ffmpegBinArg.setCombinable(true);
Argument ffmpegOptions("ffmpeg-options", 'o', "specifies options for ffmpeg"); Argument ffmpegOptions("ffmpeg-options", 'o', "specifies options for ffmpeg");
ffmpegOptions.setValueNames({"options"}); ffmpegOptions.setValueNames({ "options" });
ffmpegOptions.setRequiredValueCount(1); ffmpegOptions.setRequiredValueCount(1);
ffmpegOptions.setCombinable(true); ffmpegOptions.setCombinable(true);
recordArg.setSubArguments({&applicationArg, &sinkArg, &ffmpegInputOptions, &targetDirArg, &targetExtArg, &ignorePlaybackStatusArg, &ffmpegBinArg, &ffmpegOptions}); recordArg.setSubArguments(
parser.setMainArguments({&helpArg, &recordArg}); { &applicationArg, &sinkArg, &ffmpegInputOptions, &targetDirArg, &targetExtArg, &ignorePlaybackStatusArg, &ffmpegBinArg, &ffmpegOptions });
parser.setMainArguments({ &helpArg, &recordArg });
// parse command line arguments // parse command line arguments
try { try {
parser.parseArgs(argc, argv); parser.parseArgs(argc, argv);
@ -61,7 +62,7 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
try { try {
if(recordArg.isPresent()) { if (recordArg.isPresent()) {
// start watching/recording // start watching/recording
cerr << "Watching MPRIS service of the specified application \"" << applicationArg.values().front() << "\" ..." << endl; cerr << "Watching MPRIS service of the specified application \"" << applicationArg.values().front() << "\" ..." << endl;
// create app loop, player watcher and ffmpeg launcher // 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()); PlayerWatcher watcher(QString::fromLocal8Bit(applicationArg.values().front()), ignorePlaybackStatusArg.isPresent());
FfmpegLauncher ffmpeg(watcher); FfmpegLauncher ffmpeg(watcher);
// pass specified args to ffmpeg launcher // pass specified args to ffmpeg launcher
if(sinkArg.isPresent()) { if (sinkArg.isPresent()) {
ffmpeg.setSink(QString::fromLocal8Bit(sinkArg.values().front())); ffmpeg.setSink(QString::fromLocal8Bit(sinkArg.values().front()));
} }
if(ffmpegInputOptions.isPresent()) { if (ffmpegInputOptions.isPresent()) {
ffmpeg.setFFmpegInputOptions(QString::fromLocal8Bit(ffmpegInputOptions.values().front())); ffmpeg.setFFmpegInputOptions(QString::fromLocal8Bit(ffmpegInputOptions.values().front()));
} }
if(ffmpegBinArg.isPresent()) { if (ffmpegBinArg.isPresent()) {
ffmpeg.setFFmpegBinary(QString::fromLocal8Bit(ffmpegBinArg.values().front())); ffmpeg.setFFmpegBinary(QString::fromLocal8Bit(ffmpegBinArg.values().front()));
} }
if(ffmpegOptions.isPresent()) { if (ffmpegOptions.isPresent()) {
ffmpeg.setFFmpegOptions(QString::fromLocal8Bit(ffmpegOptions.values().front())); ffmpeg.setFFmpegOptions(QString::fromLocal8Bit(ffmpegOptions.values().front()));
} }
if(targetDirArg.isPresent()) { if (targetDirArg.isPresent()) {
ffmpeg.setTargetDir(QString::fromLocal8Bit(targetDirArg.values().front())); ffmpeg.setTargetDir(QString::fromLocal8Bit(targetDirArg.values().front()));
} }
if(targetExtArg.isPresent()) { if (targetExtArg.isPresent()) {
ffmpeg.setTargetExtension(QString::fromLocal8Bit(targetExtArg.values().front())); ffmpeg.setTargetExtension(QString::fromLocal8Bit(targetExtArg.values().front()));
} }
// enter app loop // enter app loop
return app.exec(); return app.exec();
} else if(!helpArg.isPresent()) { } else if (!helpArg.isPresent()) {
cerr << "No operation specified." << endl; cerr << "No operation specified." << endl;
return 2; return 2;
} }
} catch(const runtime_error &e) { } catch (const runtime_error &e) {
cerr << "Fatal error: " << e.what() << endl; cerr << "Fatal error: " << e.what() << endl;
return 3; return 3;
} }

View File

@ -3,8 +3,8 @@
#include "playerinterface.h" #include "playerinterface.h"
#include "propertiesinterface.h" #include "propertiesinterface.h"
#include <QDBusServiceWatcher>
#include <QDBusConnection> #include <QDBusConnection>
#include <QDBusServiceWatcher>
#include <iostream> #include <iostream>
@ -13,26 +13,29 @@ using namespace ChronoUtilities;
namespace DBusSoundRecorder { namespace DBusSoundRecorder {
inline ostream &operator <<(ostream &stream, const QString &str) inline ostream &operator<<(ostream &stream, const QString &str)
{ {
stream << str.toLocal8Bit().data(); stream << str.toLocal8Bit().data();
return stream; return stream;
} }
PlayerWatcher::PlayerWatcher(const QString &appName, bool ignorePlaybackStatus, QObject *parent) : PlayerWatcher::PlayerWatcher(const QString &appName, bool ignorePlaybackStatus, QObject *parent)
QObject(parent), : QObject(parent)
m_mediaPlayerInterfaceName(QStringLiteral("org.mpris.MediaPlayer2.%1").arg(appName)), , m_mediaPlayerInterfaceName(QStringLiteral("org.mpris.MediaPlayer2.%1").arg(appName))
m_mediaPlayerServiceWatcher(new QDBusServiceWatcher(m_mediaPlayerInterfaceName, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange, this)), , m_mediaPlayerServiceWatcher(
m_propertiesInterface(new OrgFreedesktopDBusPropertiesInterface(m_mediaPlayerInterfaceName, QStringLiteral("/org/mpris/MediaPlayer2"), QDBusConnection::sessionBus(), this)), new QDBusServiceWatcher(m_mediaPlayerInterfaceName, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange, this))
m_playerInterface(new OrgMprisMediaPlayer2PlayerInterface(m_mediaPlayerInterfaceName, QStringLiteral("/org/mpris/MediaPlayer2"), QDBusConnection::sessionBus(), this)), , m_propertiesInterface(new OrgFreedesktopDBusPropertiesInterface(
m_isPlaying(false), m_mediaPlayerInterfaceName, QStringLiteral("/org/mpris/MediaPlayer2"), QDBusConnection::sessionBus(), this))
m_isAd(false), , m_playerInterface(new OrgMprisMediaPlayer2PlayerInterface(
m_trackNumber(0), m_mediaPlayerInterfaceName, QStringLiteral("/org/mpris/MediaPlayer2"), QDBusConnection::sessionBus(), this))
m_diskNumber(0), , m_isPlaying(false)
m_silent(false), , m_isAd(false)
m_ignorePlaybackStatus(ignorePlaybackStatus) , 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; cout << "Warning: Unable to connect \"serviceOwnerChanged\" signal of service watcher." << endl;
} }
// The code below does not work anymore with the newest version of Spotify. // 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; // cout << "Warning: Unable to connect \"PropertiesChanged\" signal of properties interface." << endl;
//} //}
// However, the following works: // 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; cout << "Warning: Unable to connect \"PropertiesChanged\" signal of properties interface." << endl;
} }
propertiesChanged(); propertiesChanged();
@ -68,10 +72,10 @@ void PlayerWatcher::playPause()
void PlayerWatcher::serviceOwnerChanged(const QString &service, const QString &oldOwner, const QString &newOwner) 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; cerr << "MPRIS service \"" << service << "\" is now online" << endl;
} }
if(newOwner.isEmpty()) { if (newOwner.isEmpty()) {
cerr << "MPRIS service \"" << service << "\" went offline" << endl; cerr << "MPRIS service \"" << service << "\" went offline" << endl;
} }
} }
@ -85,18 +89,18 @@ void PlayerWatcher::propertiesChanged()
QString album = metadata.value(QStringLiteral("xesam:album")).toString(); QString album = metadata.value(QStringLiteral("xesam:album")).toString();
QString artist = metadata.value(QStringLiteral("xesam:artist")).toString(); QString artist = metadata.value(QStringLiteral("xesam:artist")).toString();
bool isPlaying; bool isPlaying;
if(m_ignorePlaybackStatus) { if (m_ignorePlaybackStatus) {
// determine playback status by checking whether there is a song title // determine playback status by checking whether there is a song title
isPlaying = !title.isEmpty(); isPlaying = !title.isEmpty();
} else { } else {
isPlaying = !m_playerInterface->playbackStatus().compare(QLatin1String("playing"), Qt::CaseInsensitive); isPlaying = !m_playerInterface->playbackStatus().compare(QLatin1String("playing"), Qt::CaseInsensitive);
} }
if(isPlaying) { if (isPlaying) {
if(!m_isPlaying) { if (!m_isPlaying) {
cerr << "Playback started" << endl; cerr << "Playback started" << endl;
} }
// use title, album and artist to identify song // 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 // next song playing
m_title = title; m_title = title;
m_album = album; m_album = album;
@ -105,34 +109,34 @@ void PlayerWatcher::propertiesChanged()
m_year = metadata.value(QStringLiteral("xesam:contentCreated")).toString(); m_year = metadata.value(QStringLiteral("xesam:contentCreated")).toString();
m_genre = metadata.value(QStringLiteral("xesam:genre")).toString(); m_genre = metadata.value(QStringLiteral("xesam:genre")).toString();
m_trackNumber = metadata.value(QStringLiteral("xesam:tracknumber")).toUInt(); m_trackNumber = metadata.value(QStringLiteral("xesam:tracknumber")).toUInt();
if(!m_trackNumber) { if (!m_trackNumber) {
m_trackNumber = metadata.value(QStringLiteral("xesam:trackNumber")).toUInt(); m_trackNumber = metadata.value(QStringLiteral("xesam:trackNumber")).toUInt();
} }
m_diskNumber = metadata.value(QStringLiteral("xesam:discnumber")).toUInt(); m_diskNumber = metadata.value(QStringLiteral("xesam:discnumber")).toUInt();
if(!m_diskNumber) { if (!m_diskNumber) {
m_diskNumber = metadata.value(QStringLiteral("xesam:discNumber")).toUInt(); m_diskNumber = metadata.value(QStringLiteral("xesam:discNumber")).toUInt();
} }
m_length = TimeSpan(metadata.value(QStringLiteral("mpris:length")).toULongLong() * 10); m_length = TimeSpan(metadata.value(QStringLiteral("mpris:length")).toULongLong() * 10);
// notify // notify
cerr << "Next song: " << m_title << endl; cerr << "Next song: " << m_title << endl;
if(!m_isPlaying && !m_silent) { if (!m_isPlaying && !m_silent) {
m_isPlaying = true; m_isPlaying = true;
emit playbackStarted(); emit playbackStarted();
} }
if(!m_silent) { if (!m_silent) {
m_isPlaying = true; m_isPlaying = true;
emit nextSong(); emit nextSong();
} }
} else if(!m_isPlaying) { } else if (!m_isPlaying) {
if(!m_silent) { if (!m_silent) {
m_isPlaying = true; m_isPlaying = true;
emit playbackStarted(); emit playbackStarted();
} }
} }
} else if(m_isPlaying) { } else if (m_isPlaying) {
m_isPlaying = false; m_isPlaying = false;
cerr << "Playback stopped" << endl; cerr << "Playback stopped" << endl;
if(!m_silent) { if (!m_silent) {
emit playbackStopped(); emit playbackStopped();
} }
} }
@ -147,5 +151,4 @@ void PlayerWatcher::seeked(qlonglong pos)
{ {
cerr << "Seeked: " << pos << endl; cerr << "Seeked: " << pos << endl;
} }
} }

View File

@ -12,8 +12,7 @@ class OrgMprisMediaPlayer2PlayerInterface;
namespace DBusSoundRecorder { namespace DBusSoundRecorder {
class PlayerWatcher : public QObject class PlayerWatcher : public QObject {
{
Q_OBJECT Q_OBJECT
public: public:
explicit PlayerWatcher(const QString &appName, bool ignorePlaybackStatus = false, QObject *parent = nullptr); explicit PlayerWatcher(const QString &appName, bool ignorePlaybackStatus = false, QObject *parent = nullptr);
@ -127,7 +126,6 @@ inline void PlayerWatcher::setSilent(bool silent)
{ {
m_silent = silent; m_silent = silent;
} }
} }
#endif // PLAYERWATCHER_H #endif // PLAYERWATCHER_H