Add support for deleting the currently playing track via the commandline (#5899)
This commit is contained in:
parent
27fc915921
commit
eab875c46d
|
@ -45,3 +45,4 @@ dist/windows/Python27.zip
|
||||||
*.swp
|
*.swp
|
||||||
src/translations/translations.pot
|
src/translations/translations.pot
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
|
.vscode
|
||||||
|
|
|
@ -67,7 +67,8 @@ const char* CommandlineOptions::kHelpText =
|
||||||
" --quiet %29\n"
|
" --quiet %29\n"
|
||||||
" --verbose %30\n"
|
" --verbose %30\n"
|
||||||
" --log-levels <levels> %31\n"
|
" --log-levels <levels> %31\n"
|
||||||
" --version %32\n";
|
" --version %32\n"
|
||||||
|
" -x, --delete-current %33\n";
|
||||||
|
|
||||||
const char* CommandlineOptions::kVersionText = "Clementine %1";
|
const char* CommandlineOptions::kVersionText = "Clementine %1";
|
||||||
|
|
||||||
|
@ -81,6 +82,7 @@ CommandlineOptions::CommandlineOptions(int argc, char** argv)
|
||||||
seek_to_(-1),
|
seek_to_(-1),
|
||||||
seek_by_(0),
|
seek_by_(0),
|
||||||
play_track_at_(-1),
|
play_track_at_(-1),
|
||||||
|
delete_current_track_(false),
|
||||||
show_osd_(false),
|
show_osd_(false),
|
||||||
toggle_pretty_osd_(false),
|
toggle_pretty_osd_(false),
|
||||||
log_levels_(logging::kDefaultLogLevels) {
|
log_levels_(logging::kDefaultLogLevels) {
|
||||||
|
@ -135,12 +137,13 @@ bool CommandlineOptions::Parse() {
|
||||||
{"verbose", no_argument, 0, Verbose},
|
{"verbose", no_argument, 0, Verbose},
|
||||||
{"log-levels", required_argument, 0, LogLevels},
|
{"log-levels", required_argument, 0, LogLevels},
|
||||||
{"version", no_argument, 0, Version},
|
{"version", no_argument, 0, Version},
|
||||||
|
{"delete-current", no_argument, 0, 'x'},
|
||||||
{0, 0, 0, 0}};
|
{0, 0, 0, 0}};
|
||||||
|
|
||||||
// Parse the arguments
|
// Parse the arguments
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
forever {
|
forever {
|
||||||
int c = getopt_long(argc_, argv_, "hptusqrfv:c:alk:oyg:", kOptions, nullptr);
|
int c = getopt_long(argc_, argv_, "xhptusqrfv:c:alk:oyg:", kOptions, nullptr);
|
||||||
|
|
||||||
// End of the options
|
// End of the options
|
||||||
if (c == -1) break;
|
if (c == -1) break;
|
||||||
|
@ -179,7 +182,8 @@ bool CommandlineOptions::Parse() {
|
||||||
tr("Equivalent to --log-levels *:1"),
|
tr("Equivalent to --log-levels *:1"),
|
||||||
tr("Equivalent to --log-levels *:3"),
|
tr("Equivalent to --log-levels *:3"),
|
||||||
tr("Comma separated list of class:level, level is 0-3"))
|
tr("Comma separated list of class:level, level is 0-3"))
|
||||||
.arg(tr("Print out version information"));
|
.arg(tr("Print out version information"),
|
||||||
|
tr("Delete the currently playing song"));
|
||||||
|
|
||||||
std::cout << translated_help_text.toLocal8Bit().constData();
|
std::cout << translated_help_text.toLocal8Bit().constData();
|
||||||
return false;
|
return false;
|
||||||
|
@ -280,6 +284,10 @@ bool CommandlineOptions::Parse() {
|
||||||
if (!ok) play_track_at_ = -1;
|
if (!ok) play_track_at_ = -1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
delete_current_track_ = true;
|
||||||
|
break;
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -303,7 +311,8 @@ bool CommandlineOptions::is_empty() const {
|
||||||
return player_action_ == Player_None && set_volume_ == -1 &&
|
return player_action_ == Player_None && set_volume_ == -1 &&
|
||||||
volume_modifier_ == 0 && seek_to_ == -1 && seek_by_ == 0 &&
|
volume_modifier_ == 0 && seek_to_ == -1 && seek_by_ == 0 &&
|
||||||
play_track_at_ == -1 && show_osd_ == false &&
|
play_track_at_ == -1 && show_osd_ == false &&
|
||||||
toggle_pretty_osd_ == false && urls_.isEmpty();
|
toggle_pretty_osd_ == false && urls_.isEmpty() &&
|
||||||
|
delete_current_track_ == false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandlineOptions::contains_play_options() const {
|
bool CommandlineOptions::contains_play_options() const {
|
||||||
|
@ -338,7 +347,8 @@ QString CommandlineOptions::tr(const char* source_text) {
|
||||||
QDataStream& operator<<(QDataStream& s, const CommandlineOptions& a) {
|
QDataStream& operator<<(QDataStream& s, const CommandlineOptions& a) {
|
||||||
s << qint32(a.player_action_) << qint32(a.url_list_action_) << a.set_volume_
|
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.volume_modifier_ << a.seek_to_ << a.seek_by_ << a.play_track_at_
|
||||||
<< a.show_osd_ << a.urls_ << a.log_levels_ << a.toggle_pretty_osd_;
|
<< a.show_osd_ << a.urls_ << a.log_levels_ << a.toggle_pretty_osd_
|
||||||
|
<< a.delete_current_track_;
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
@ -348,7 +358,8 @@ QDataStream& operator>>(QDataStream& s, CommandlineOptions& a) {
|
||||||
quint32 url_list_action = 0;
|
quint32 url_list_action = 0;
|
||||||
s >> player_action >> url_list_action >> a.set_volume_ >>
|
s >> player_action >> url_list_action >> a.set_volume_ >>
|
||||||
a.volume_modifier_ >> a.seek_to_ >> a.seek_by_ >> a.play_track_at_ >>
|
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_;
|
a.show_osd_ >> a.urls_ >> a.log_levels_ >> a.toggle_pretty_osd_ >>
|
||||||
|
a.delete_current_track_;
|
||||||
a.player_action_ = CommandlineOptions::PlayerAction(player_action);
|
a.player_action_ = CommandlineOptions::PlayerAction(player_action);
|
||||||
a.url_list_action_ = CommandlineOptions::UrlListAction(url_list_action);
|
a.url_list_action_ = CommandlineOptions::UrlListAction(url_list_action);
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ class CommandlineOptions {
|
||||||
int seek_to() const { return seek_to_; }
|
int seek_to() const { return seek_to_; }
|
||||||
int seek_by() const { return seek_by_; }
|
int seek_by() const { return seek_by_; }
|
||||||
int play_track_at() const { return play_track_at_; }
|
int play_track_at() const { return play_track_at_; }
|
||||||
|
bool delete_current_track() const { return delete_current_track_; }
|
||||||
bool show_osd() const { return show_osd_; }
|
bool show_osd() const { return show_osd_; }
|
||||||
bool toggle_pretty_osd() const { return toggle_pretty_osd_; }
|
bool toggle_pretty_osd() const { return toggle_pretty_osd_; }
|
||||||
QList<QUrl> urls() const { return urls_; }
|
QList<QUrl> urls() const { return urls_; }
|
||||||
|
@ -113,6 +114,7 @@ class CommandlineOptions {
|
||||||
int seek_to_;
|
int seek_to_;
|
||||||
int seek_by_;
|
int seek_by_;
|
||||||
int play_track_at_;
|
int play_track_at_;
|
||||||
|
bool delete_current_track_;
|
||||||
bool show_osd_;
|
bool show_osd_;
|
||||||
bool toggle_pretty_osd_;
|
bool toggle_pretty_osd_;
|
||||||
QString language_;
|
QString language_;
|
||||||
|
|
|
@ -57,6 +57,15 @@ void DeleteFiles::Start(const SongList& songs) {
|
||||||
thread_->start();
|
thread_->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeleteFiles::Start(const QUrl& url) {
|
||||||
|
SongList songs;
|
||||||
|
Song song;
|
||||||
|
song.set_url(url);
|
||||||
|
songs << song;
|
||||||
|
|
||||||
|
Start(songs);
|
||||||
|
}
|
||||||
|
|
||||||
void DeleteFiles::Start(const QStringList& filenames) {
|
void DeleteFiles::Start(const QStringList& filenames) {
|
||||||
SongList songs;
|
SongList songs;
|
||||||
for (const QString& filename : filenames) {
|
for (const QString& filename : filenames) {
|
||||||
|
|
|
@ -40,6 +40,7 @@ class DeleteFiles : public QObject {
|
||||||
|
|
||||||
void Start(const SongList& songs);
|
void Start(const SongList& songs);
|
||||||
void Start(const QStringList& filenames);
|
void Start(const QStringList& filenames);
|
||||||
|
void Start(const QUrl& url);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void Finished(const SongList& songs_with_errors);
|
void Finished(const SongList& songs_with_errors);
|
||||||
|
|
|
@ -637,6 +637,7 @@ void LibraryView::scrollTo(const QModelIndex& index, ScrollHint hint) {
|
||||||
QTreeView::scrollTo(index, hint);
|
QTreeView::scrollTo(index, hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get selected songs
|
||||||
SongList LibraryView::GetSelectedSongs() const {
|
SongList LibraryView::GetSelectedSongs() const {
|
||||||
QModelIndexList selected_indexes =
|
QModelIndexList selected_indexes =
|
||||||
qobject_cast<QSortFilterProxyModel*>(model())
|
qobject_cast<QSortFilterProxyModel*>(model())
|
||||||
|
|
|
@ -303,7 +303,10 @@ int main(int argc, char* argv[]) {
|
||||||
qLog(Info)
|
qLog(Info)
|
||||||
<< "Clementine is already running - activating existing window";
|
<< "Clementine is already running - activating existing window";
|
||||||
}
|
}
|
||||||
if (a.sendMessage(options.Serialize(), 5000)) {
|
|
||||||
|
QByteArray serializedOptions = options.Serialize();
|
||||||
|
if (a.sendMessage(serializedOptions, 5000)) {
|
||||||
|
qLog(Info) << "Options found, sent message to running instance";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// Couldn't send the message so start anyway
|
// Couldn't send the message so start anyway
|
||||||
|
|
|
@ -2150,6 +2150,8 @@ void MainWindow::CommandlineOptionsReceived(
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::CommandlineOptionsReceived(const CommandlineOptions& options) {
|
void MainWindow::CommandlineOptionsReceived(const CommandlineOptions& options) {
|
||||||
|
qLog(Debug) << "command line options received";
|
||||||
|
|
||||||
switch (options.player_action()) {
|
switch (options.player_action()) {
|
||||||
case CommandlineOptions::Player_Play:
|
case CommandlineOptions::Player_Play:
|
||||||
if (options.urls().empty()) {
|
if (options.urls().empty()) {
|
||||||
|
@ -2229,6 +2231,33 @@ void MainWindow::CommandlineOptionsReceived(const CommandlineOptions& options) {
|
||||||
if (options.play_track_at() != -1)
|
if (options.play_track_at() != -1)
|
||||||
app_->player()->PlayAt(options.play_track_at(), Engine::Manual, true);
|
app_->player()->PlayAt(options.play_track_at(), Engine::Manual, true);
|
||||||
|
|
||||||
|
qLog(Debug) << options.delete_current_track();
|
||||||
|
|
||||||
|
// Just pass the url of the currently playing
|
||||||
|
if (options.delete_current_track()) {
|
||||||
|
qLog(Debug) << "deleting current track";
|
||||||
|
|
||||||
|
Playlist* activePlaylist = app_->playlist_manager()->active();
|
||||||
|
PlaylistItemPtr playlistItemPtr = activePlaylist->current_item();
|
||||||
|
|
||||||
|
if (playlistItemPtr) {
|
||||||
|
const QUrl& url = playlistItemPtr->Url();
|
||||||
|
qLog(Debug) << url;
|
||||||
|
|
||||||
|
std::shared_ptr<MusicStorage> storage(new FilesystemMusicStorage("/"));
|
||||||
|
|
||||||
|
app_->player()->Next();
|
||||||
|
|
||||||
|
DeleteFiles* delete_files = new DeleteFiles(app_->task_manager(), storage);
|
||||||
|
connect(delete_files, SIGNAL(Finished(SongList)),
|
||||||
|
SLOT(DeleteFinished(SongList)));
|
||||||
|
delete_files->Start(url);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
qLog(Debug) << "no currently playing track to delete";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (options.show_osd()) app_->player()->ShowOSD();
|
if (options.show_osd()) app_->player()->ShowOSD();
|
||||||
|
|
||||||
if (options.toggle_pretty_osd()) app_->player()->TogglePrettyOSD();
|
if (options.toggle_pretty_osd()) app_->player()->TogglePrettyOSD();
|
||||||
|
@ -2437,7 +2466,16 @@ void MainWindow::PlaylistOpenInBrowser() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::DeleteFinished(const SongList& songs_with_errors) {
|
void MainWindow::DeleteFinished(const SongList& songs_with_errors) {
|
||||||
if (songs_with_errors.isEmpty()) return;
|
if (songs_with_errors.isEmpty()) {
|
||||||
|
qLog(Debug) << "Finished deleting songs";
|
||||||
|
Playlist* activePlaylist = app_->playlist_manager()->active();
|
||||||
|
if (activePlaylist->id() != -1) {
|
||||||
|
activePlaylist->RemoveUnavailableSongs();
|
||||||
|
qLog(Debug) << "Found active playlist and removed unavailable songs";
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
OrganiseErrorDialog* dialog = new OrganiseErrorDialog(this);
|
OrganiseErrorDialog* dialog = new OrganiseErrorDialog(this);
|
||||||
dialog->Show(OrganiseErrorDialog::Type_Delete, songs_with_errors);
|
dialog->Show(OrganiseErrorDialog::Type_Delete, songs_with_errors);
|
||||||
|
|
Loading…
Reference in New Issue