2010-04-13 00:44:29 +02:00
|
|
|
/* This file is part of Clementine.
|
2014-11-01 19:30:40 +01:00
|
|
|
Copyright 2010, 2012, David Sansome <me@davidsansome.com>
|
|
|
|
Copyright 2010-2012, 2014, John Maguire <john.maguire@gmail.com>
|
|
|
|
Copyright 2012, Arnaud Bienner <arnaud.bienner@gmail.com>
|
|
|
|
Copyright 2013, Kevin Cox <kevincox.ca@gmail.com>
|
|
|
|
Copyright 2013, Mateusz Kowalczyk <fuuzetsu@fuuzetsu.co.uk>
|
|
|
|
Copyright 2014, Alexander Bikadorov <abiku@cs.tu-berlin.de>
|
2010-04-13 00:44:29 +02:00
|
|
|
|
|
|
|
Clementine 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.
|
|
|
|
|
|
|
|
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2010-05-10 23:50:31 +02:00
|
|
|
#include "config.h"
|
2010-04-13 00:44:29 +02:00
|
|
|
#include "commandlineoptions.h"
|
2011-05-16 21:21:46 +02:00
|
|
|
#include "version.h"
|
2012-01-06 00:22:51 +01:00
|
|
|
#include "core/logging.h"
|
2010-04-13 00:44:29 +02:00
|
|
|
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
#include <QBuffer>
|
2011-05-16 21:21:46 +02:00
|
|
|
#include <QCoreApplication>
|
2010-06-18 02:31:54 +02:00
|
|
|
#include <QFileInfo>
|
2010-04-13 00:44:29 +02:00
|
|
|
|
|
|
|
const char* CommandlineOptions::kHelpText =
|
|
|
|
"%1: clementine [%2] [%3]\n"
|
|
|
|
"\n"
|
|
|
|
"%4:\n"
|
|
|
|
" -p, --play %5\n"
|
|
|
|
" -t, --play-pause %6\n"
|
|
|
|
" -u, --pause %7\n"
|
|
|
|
" -s, --stop %8\n"
|
|
|
|
" -r, --previous %9\n"
|
|
|
|
" -f, --next %10\n"
|
2010-04-13 01:35:47 +02:00
|
|
|
" -v, --volume <value> %11\n"
|
|
|
|
" --volume-up %12\n"
|
|
|
|
" --volume-down %13\n"
|
2013-02-15 14:59:21 +01:00
|
|
|
" --volume-increase-by %14\n"
|
|
|
|
" --volume-decrease-by %15\n"
|
|
|
|
" --seek-to <seconds> %16\n"
|
|
|
|
" --seek-by <seconds> %17\n"
|
2013-05-29 21:27:07 +02:00
|
|
|
" --restart-or-previous %18\n"
|
2010-04-13 00:44:29 +02:00
|
|
|
"\n"
|
2013-05-29 21:27:07 +02:00
|
|
|
"%19:\n"
|
2013-02-15 14:59:21 +01:00
|
|
|
" -a, --append %20\n"
|
|
|
|
" -l, --load %21\n"
|
|
|
|
" -k, --play-track <n> %22\n"
|
2010-04-13 01:35:47 +02:00
|
|
|
"\n"
|
2013-02-15 14:59:21 +01:00
|
|
|
"%23:\n"
|
|
|
|
" -o, --show-osd %24\n"
|
|
|
|
" -y, --toggle-pretty-osd %25\n"
|
|
|
|
" -g, --language <lang> %26\n"
|
|
|
|
" --quiet %27\n"
|
|
|
|
" --verbose %28\n"
|
|
|
|
" --log-levels <levels> %29\n"
|
|
|
|
" --version %30\n";
|
2010-04-13 00:44:29 +02:00
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
const char* CommandlineOptions::kVersionText = "Clementine %1";
|
2010-04-13 00:44:29 +02:00
|
|
|
|
|
|
|
CommandlineOptions::CommandlineOptions(int argc, char** argv)
|
2014-02-07 16:34:20 +01:00
|
|
|
: argc_(argc),
|
|
|
|
argv_(argv),
|
2014-02-07 20:28:37 +01:00
|
|
|
url_list_action_(UrlList_None),
|
2014-02-07 16:34:20 +01:00
|
|
|
player_action_(Player_None),
|
|
|
|
set_volume_(-1),
|
|
|
|
volume_modifier_(0),
|
|
|
|
seek_to_(-1),
|
|
|
|
seek_by_(0),
|
|
|
|
play_track_at_(-1),
|
|
|
|
show_osd_(false),
|
|
|
|
toggle_pretty_osd_(false),
|
|
|
|
log_levels_(logging::kDefaultLogLevels) {
|
2010-07-24 16:57:56 +02:00
|
|
|
#ifdef Q_OS_DARWIN
|
|
|
|
// Remove -psn_xxx option that Mac passes when opened from Finder.
|
2010-12-11 11:04:17 +01:00
|
|
|
RemoveArg("-psn", 1);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Remove the -session option that KDE passes
|
|
|
|
RemoveArg("-session", 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CommandlineOptions::RemoveArg(const QString& starts_with, int count) {
|
2010-07-24 16:57:56 +02:00
|
|
|
for (int i = 0; i < argc_; ++i) {
|
|
|
|
QString opt(argv_[i]);
|
2010-12-11 11:04:17 +01:00
|
|
|
if (opt.startsWith(starts_with)) {
|
|
|
|
for (int j = i; j < argc_ - count + 1; ++j) {
|
2014-02-07 16:34:20 +01:00
|
|
|
argv_[j] = argv_[j + count];
|
2010-07-24 16:57:56 +02:00
|
|
|
}
|
2010-12-11 11:04:17 +01:00
|
|
|
argc_ -= count;
|
2010-07-24 16:57:56 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-04-13 00:44:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CommandlineOptions::Parse() {
|
|
|
|
static const struct option kOptions[] = {
|
2014-02-07 16:34:20 +01:00
|
|
|
{"help", no_argument, 0, 'h'},
|
|
|
|
{"play", no_argument, 0, 'p'},
|
|
|
|
{"play-pause", no_argument, 0, 't'},
|
|
|
|
{"pause", no_argument, 0, 'u'},
|
|
|
|
{"stop", no_argument, 0, 's'},
|
|
|
|
{"previous", no_argument, 0, 'r'},
|
|
|
|
{"next", no_argument, 0, 'f'},
|
|
|
|
{"volume", required_argument, 0, 'v'},
|
|
|
|
{"volume-up", no_argument, 0, VolumeUp},
|
|
|
|
{"volume-down", no_argument, 0, VolumeDown},
|
|
|
|
{"volume-increase-by", required_argument, 0, VolumeIncreaseBy},
|
|
|
|
{"volume-decrease-by", required_argument, 0, VolumeDecreaseBy},
|
|
|
|
{"seek-to", required_argument, 0, SeekTo},
|
|
|
|
{"seek-by", required_argument, 0, SeekBy},
|
|
|
|
{"restart-or-previous", no_argument, 0, RestartOrPrevious},
|
|
|
|
{"append", no_argument, 0, 'a'},
|
|
|
|
{"load", no_argument, 0, 'l'},
|
|
|
|
{"play-track", required_argument, 0, 'k'},
|
|
|
|
{"show-osd", no_argument, 0, 'o'},
|
|
|
|
{"toggle-pretty-osd", no_argument, 0, 'y'},
|
|
|
|
{"language", required_argument, 0, 'g'},
|
|
|
|
{"quiet", no_argument, 0, Quiet},
|
|
|
|
{"verbose", no_argument, 0, Verbose},
|
|
|
|
{"log-levels", required_argument, 0, LogLevels},
|
|
|
|
{"version", no_argument, 0, Version},
|
|
|
|
{0, 0, 0, 0}};
|
2010-04-13 00:44:29 +02:00
|
|
|
|
|
|
|
// Parse the arguments
|
2010-04-13 01:35:47 +02:00
|
|
|
bool ok = false;
|
2010-04-13 00:44:29 +02:00
|
|
|
forever {
|
2014-02-06 16:49:49 +01:00
|
|
|
int c = getopt_long(argc_, argv_, "hptusrfv:alk:oyg:", kOptions, nullptr);
|
2010-04-13 00:44:29 +02:00
|
|
|
|
|
|
|
// End of the options
|
2014-02-07 16:34:20 +01:00
|
|
|
if (c == -1) break;
|
2010-04-13 00:44:29 +02:00
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
case 'h': {
|
2014-02-07 16:34:20 +01:00
|
|
|
QString translated_help_text =
|
|
|
|
QString(kHelpText)
|
|
|
|
.arg(tr("Usage"), tr("options"), tr("URL(s)"),
|
|
|
|
tr("Player options"),
|
|
|
|
tr("Start the playlist currently playing"),
|
|
|
|
tr("Play if stopped, pause if playing"),
|
|
|
|
tr("Pause playback"), tr("Stop playback"),
|
|
|
|
tr("Skip backwards in playlist"))
|
|
|
|
.arg(tr("Skip forwards in playlist"),
|
|
|
|
tr("Set the volume to <value> percent"),
|
|
|
|
tr("Increase the volume by 4%"),
|
|
|
|
tr("Decrease the volume by 4%"),
|
|
|
|
tr("Increase the volume by <value> percent"),
|
|
|
|
tr("Decrease the volume by <value> percent"))
|
|
|
|
.arg(tr("Seek the currently playing track to an absolute "
|
|
|
|
"position"),
|
|
|
|
tr("Seek the currently playing track by a relative "
|
|
|
|
"amount"),
|
|
|
|
tr("Restart the track, or play the previous track if "
|
|
|
|
"within 8 seconds of start."),
|
|
|
|
tr("Playlist options"),
|
|
|
|
tr("Append files/URLs to the playlist"),
|
|
|
|
tr("Loads files/URLs, replacing current playlist"),
|
|
|
|
tr("Play the <n>th track in the playlist"))
|
|
|
|
.arg(tr("Other options"), tr("Display the on-screen-display"),
|
|
|
|
tr("Toggle visibility for the pretty on-screen-display"),
|
|
|
|
tr("Change the language"),
|
|
|
|
tr("Equivalent to --log-levels *:1"),
|
|
|
|
tr("Equivalent to --log-levels *:3"),
|
|
|
|
tr("Comma separated list of class:level, level is 0-3"))
|
|
|
|
.arg(tr("Print out version information"));
|
2010-04-13 00:44:29 +02:00
|
|
|
|
|
|
|
std::cout << translated_help_text.toLocal8Bit().constData();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
case 'p':
|
|
|
|
player_action_ = Player_Play;
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
player_action_ = Player_PlayPause;
|
|
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
player_action_ = Player_Pause;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
player_action_ = Player_Stop;
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
player_action_ = Player_Previous;
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
player_action_ = Player_Next;
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
url_list_action_ = UrlList_Append;
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
url_list_action_ = UrlList_Load;
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
show_osd_ = true;
|
|
|
|
break;
|
|
|
|
case 'y':
|
|
|
|
toggle_pretty_osd_ = true;
|
|
|
|
break;
|
|
|
|
case 'g':
|
|
|
|
language_ = QString(optarg);
|
|
|
|
break;
|
|
|
|
case VolumeUp:
|
|
|
|
volume_modifier_ = +4;
|
|
|
|
break;
|
|
|
|
case VolumeDown:
|
|
|
|
volume_modifier_ = -4;
|
|
|
|
break;
|
|
|
|
case Quiet:
|
|
|
|
log_levels_ = "1";
|
|
|
|
break;
|
|
|
|
case Verbose:
|
|
|
|
log_levels_ = "3";
|
|
|
|
break;
|
|
|
|
case LogLevels:
|
|
|
|
log_levels_ = QString(optarg);
|
|
|
|
break;
|
2011-05-16 21:21:46 +02:00
|
|
|
case Version: {
|
2014-02-07 16:34:20 +01:00
|
|
|
QString version_text =
|
|
|
|
QString(kVersionText).arg(CLEMENTINE_VERSION_DISPLAY);
|
2011-05-16 21:21:46 +02:00
|
|
|
std::cout << version_text.toLocal8Bit().constData() << std::endl;
|
|
|
|
std::exit(0);
|
|
|
|
}
|
2010-04-13 01:35:47 +02:00
|
|
|
case 'v':
|
|
|
|
set_volume_ = QString(optarg).toInt(&ok);
|
|
|
|
if (!ok) set_volume_ = -1;
|
|
|
|
break;
|
|
|
|
|
2013-02-15 14:59:21 +01:00
|
|
|
case VolumeIncreaseBy:
|
|
|
|
volume_modifier_ = QString(optarg).toInt(&ok);
|
|
|
|
if (!ok) volume_modifier_ = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VolumeDecreaseBy:
|
|
|
|
volume_modifier_ = -QString(optarg).toInt(&ok);
|
|
|
|
if (!ok) volume_modifier_ = 0;
|
|
|
|
break;
|
|
|
|
|
2010-04-13 01:35:47 +02:00
|
|
|
case SeekTo:
|
|
|
|
seek_to_ = QString(optarg).toInt(&ok);
|
|
|
|
if (!ok) seek_to_ = -1;
|
|
|
|
break;
|
|
|
|
|
2010-04-13 22:22:29 +02:00
|
|
|
case SeekBy:
|
|
|
|
seek_by_ = QString(optarg).toInt(&ok);
|
|
|
|
if (!ok) seek_by_ = 0;
|
|
|
|
break;
|
|
|
|
|
2013-05-29 21:27:07 +02:00
|
|
|
case RestartOrPrevious:
|
|
|
|
player_action_ = Player_RestartOrPrevious;
|
|
|
|
break;
|
|
|
|
|
2010-04-13 01:35:47 +02:00
|
|
|
case 'k':
|
|
|
|
play_track_at_ = QString(optarg).toInt(&ok);
|
|
|
|
if (!ok) play_track_at_ = -1;
|
|
|
|
break;
|
|
|
|
|
2010-04-13 00:44:29 +02:00
|
|
|
case '?':
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get any filenames or URLs following the arguments
|
2014-02-07 16:34:20 +01:00
|
|
|
for (int i = optind; i < argc_; ++i) {
|
2010-09-25 17:15:05 +02:00
|
|
|
QString value = QFile::decodeName(argv_[i]);
|
2012-09-17 20:47:57 +02:00
|
|
|
QFileInfo file_info(value);
|
|
|
|
if (file_info.exists())
|
|
|
|
urls_ << QUrl::fromLocalFile(file_info.canonicalFilePath());
|
2010-04-13 00:44:29 +02:00
|
|
|
else
|
2012-09-26 17:09:13 +02:00
|
|
|
urls_ << QUrl::fromUserInput(value);
|
2010-04-13 00:44:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-04-13 01:35:47 +02:00
|
|
|
bool CommandlineOptions::is_empty() const {
|
2014-02-07 16:34:20 +01:00
|
|
|
return player_action_ == Player_None && set_volume_ == -1 &&
|
|
|
|
volume_modifier_ == 0 && seek_to_ == -1 && seek_by_ == 0 &&
|
|
|
|
play_track_at_ == -1 && show_osd_ == false &&
|
|
|
|
toggle_pretty_osd_ == false && urls_.isEmpty();
|
2010-04-13 01:35:47 +02:00
|
|
|
}
|
|
|
|
|
2010-04-13 00:44:29 +02:00
|
|
|
QByteArray CommandlineOptions::Serialize() const {
|
|
|
|
QBuffer buf;
|
|
|
|
buf.open(QIODevice::WriteOnly);
|
|
|
|
|
|
|
|
QDataStream s(&buf);
|
|
|
|
s << *this;
|
|
|
|
buf.close();
|
|
|
|
|
|
|
|
return buf.data();
|
|
|
|
}
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
void CommandlineOptions::Load(const QByteArray& serialized) {
|
2010-04-13 00:44:29 +02:00
|
|
|
QByteArray copy(serialized);
|
|
|
|
QBuffer buf(©);
|
|
|
|
buf.open(QIODevice::ReadOnly);
|
|
|
|
|
|
|
|
QDataStream s(&buf);
|
|
|
|
s >> *this;
|
|
|
|
}
|
|
|
|
|
2014-02-07 16:34:20 +01:00
|
|
|
QString CommandlineOptions::tr(const char* source_text) {
|
2010-04-13 00:44:29 +02:00
|
|
|
return QObject::tr(source_text);
|
|
|
|
}
|
|
|
|
|
|
|
|
QDataStream& operator<<(QDataStream& s, const CommandlineOptions& a) {
|
2014-02-07 16:34:20 +01:00
|
|
|
s << qint32(a.player_action_) << qint32(a.url_list_action_) << a.set_volume_
|
|
|
|
<< a.volume_modifier_ << a.seek_to_ << a.seek_by_ << a.play_track_at_
|
|
|
|
<< a.show_osd_ << a.urls_ << a.log_levels_ << a.toggle_pretty_osd_;
|
2010-04-13 00:44:29 +02:00
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
QDataStream& operator>>(QDataStream& s, CommandlineOptions& a) {
|
2010-06-17 16:05:21 +02:00
|
|
|
quint32 player_action = 0;
|
|
|
|
quint32 url_list_action = 0;
|
2014-02-07 16:34:20 +01:00
|
|
|
s >> player_action >> url_list_action >> a.set_volume_ >>
|
|
|
|
a.volume_modifier_ >> a.seek_to_ >> a.seek_by_ >> a.play_track_at_ >>
|
|
|
|
a.show_osd_ >> a.urls_ >> a.log_levels_ >> a.toggle_pretty_osd_;
|
2010-06-17 16:05:21 +02:00
|
|
|
a.player_action_ = CommandlineOptions::PlayerAction(player_action);
|
|
|
|
a.url_list_action_ = CommandlineOptions::UrlListAction(url_list_action);
|
2010-04-13 00:44:29 +02:00
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|