mirror of
https://github.com/clementine-player/Clementine
synced 2025-01-27 09:41:32 +01:00
Add track intro mode
This repeat mode plays the beginning of each track, good for quickly getting a feel for a new album for example.
This commit is contained in:
parent
0abdf545a0
commit
b57cebbf2d
@ -127,6 +127,7 @@ enum RepeatMode {
|
||||
Repeat_Album = 2;
|
||||
Repeat_Playlist = 3;
|
||||
Repeat_OneByOne = 4;
|
||||
Repeat_Intro = 5;
|
||||
}
|
||||
|
||||
// Valid Shuffle modes
|
||||
|
@ -589,6 +589,8 @@ void Player::TrackAboutToEnd() {
|
||||
next_item->Metadata().end_nanosec());
|
||||
}
|
||||
|
||||
void Player::IntroPointReached() { NextInternal(Engine::Intro); }
|
||||
|
||||
void Player::ValidSongRequested(const QUrl& url) {
|
||||
emit SongChangeRequestProcessed(url, true);
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ class PlayerInterface : public QObject {
|
||||
virtual void Play() = 0;
|
||||
virtual void ShowOSD() = 0;
|
||||
|
||||
signals:
|
||||
signals:
|
||||
void Playing();
|
||||
void Paused();
|
||||
void Stopped();
|
||||
@ -163,6 +163,7 @@ class Player : public PlayerInterface {
|
||||
void Pause();
|
||||
void Stop(bool stop_after = false);
|
||||
void StopAfterCurrent();
|
||||
void IntroPointReached();
|
||||
void Play();
|
||||
void ShowOSD();
|
||||
void TogglePrettyOSD();
|
||||
|
@ -27,6 +27,7 @@ enum TrackChangeType {
|
||||
First = 0x01,
|
||||
Manual = 0x02,
|
||||
Auto = 0x04,
|
||||
Intro = 0x08,
|
||||
|
||||
// Any of:
|
||||
SameAlbum = 0x10,
|
||||
|
@ -302,8 +302,8 @@ void GstEngine::UpdateScope(int chunk_length) {
|
||||
gst_buffer_map(latest_buffer_, &map, GST_MAP_READ);
|
||||
|
||||
// determine where to split the buffer
|
||||
int chunk_density = (map.size * kNsecPerMsec) /
|
||||
GST_BUFFER_DURATION(latest_buffer_);
|
||||
int chunk_density =
|
||||
(map.size * kNsecPerMsec) / GST_BUFFER_DURATION(latest_buffer_);
|
||||
|
||||
int chunk_size = chunk_length * chunk_density;
|
||||
|
||||
@ -321,10 +321,9 @@ void GstEngine::UpdateScope(int chunk_length) {
|
||||
|
||||
// make sure we don't go beyond the end of the buffer
|
||||
if (scope_chunk_ == scope_chunks_ - 1) {
|
||||
bytes =
|
||||
qMin(static_cast<Engine::Scope::size_type>(
|
||||
map.size - (chunk_size * scope_chunk_)),
|
||||
scope_.size() * sizeof(sample_type));
|
||||
bytes = qMin(static_cast<Engine::Scope::size_type>(
|
||||
map.size - (chunk_size * scope_chunk_)),
|
||||
scope_.size() * sizeof(sample_type));
|
||||
} else {
|
||||
bytes = qMin(static_cast<Engine::Scope::size_type>(chunk_size),
|
||||
scope_.size() * sizeof(sample_type));
|
||||
@ -380,7 +379,9 @@ bool GstEngine::Load(const QUrl& url, Engine::TrackChangeFlags change,
|
||||
|
||||
bool crossfade =
|
||||
current_pipeline_ && ((crossfade_enabled_ && change & Engine::Manual) ||
|
||||
(autocrossfade_enabled_ && change & Engine::Auto));
|
||||
(autocrossfade_enabled_ && change & Engine::Auto) ||
|
||||
((crossfade_enabled_ || autocrossfade_enabled_) &&
|
||||
change & Engine::Intro));
|
||||
|
||||
if (change & Engine::Auto && change & Engine::SameAlbum &&
|
||||
!crossfade_same_album_)
|
||||
@ -767,9 +768,8 @@ GstEngine::PluginDetailsList GstEngine::GetPluginList(
|
||||
if (QString(gst_element_factory_get_klass(factory)).contains(classname)) {
|
||||
PluginDetails details;
|
||||
details.name = QString::fromUtf8(gst_plugin_feature_get_name(p->data));
|
||||
details.description = QString::fromUtf8(
|
||||
gst_element_factory_get_metadata(factory,
|
||||
GST_ELEMENT_METADATA_DESCRIPTION));
|
||||
details.description = QString::fromUtf8(gst_element_factory_get_metadata(
|
||||
factory, GST_ELEMENT_METADATA_DESCRIPTION));
|
||||
ret << details;
|
||||
}
|
||||
p = g_list_next(p);
|
||||
|
@ -79,10 +79,8 @@ void OutgoingDataCreator::SetClients(QList<RemoteClient*>* clients) {
|
||||
SLOT(ResultsAvailable(int, SearchProvider::ResultList)),
|
||||
Qt::QueuedConnection);
|
||||
|
||||
connect(app_->global_search(),
|
||||
SIGNAL(SearchFinished(int)),
|
||||
SLOT(SearchFinished(int)),
|
||||
Qt::QueuedConnection);
|
||||
connect(app_->global_search(), SIGNAL(SearchFinished(int)),
|
||||
SLOT(SearchFinished(int)), Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void OutgoingDataCreator::CheckEnabledProviders() {
|
||||
@ -379,9 +377,11 @@ void OutgoingDataCreator::CreateSong(const Song& song, const QImage& art,
|
||||
song_metadata->set_file_size(song.filesize());
|
||||
song_metadata->set_rating(song.rating());
|
||||
song_metadata->set_url(DataCommaSizeFromQString(song.url().toString()));
|
||||
song_metadata->set_art_automatic(DataCommaSizeFromQString(song.art_automatic()));
|
||||
song_metadata->set_art_automatic(
|
||||
DataCommaSizeFromQString(song.art_automatic()));
|
||||
song_metadata->set_art_manual(DataCommaSizeFromQString(song.art_manual()));
|
||||
song_metadata->set_type(static_cast< ::pb::remote::SongMetadata_Type>(song.filetype()));
|
||||
song_metadata->set_type(
|
||||
static_cast<::pb::remote::SongMetadata_Type>(song.filetype()));
|
||||
|
||||
// Append coverart
|
||||
if (!art.isNull()) {
|
||||
@ -506,6 +506,9 @@ void OutgoingDataCreator::SendRepeatMode(PlaylistSequence::RepeatMode mode) {
|
||||
case PlaylistSequence::Repeat_OneByOne:
|
||||
msg.mutable_repeat()->set_repeat_mode(pb::remote::Repeat_OneByOne);
|
||||
break;
|
||||
case PlaylistSequence::Repeat_Intro:
|
||||
msg.mutable_repeat()->set_repeat_mode(pb::remote::Repeat_Intro);
|
||||
break;
|
||||
}
|
||||
|
||||
SendDataToClients(&msg);
|
||||
@ -673,7 +676,8 @@ void OutgoingDataCreator::DoGlobalSearch(const QString& query,
|
||||
|
||||
// Send status message
|
||||
pb::remote::Message msg;
|
||||
pb::remote::ResponseGlobalSearchStatus* status = msg.mutable_response_global_search_status();
|
||||
pb::remote::ResponseGlobalSearchStatus* status =
|
||||
msg.mutable_response_global_search_status();
|
||||
|
||||
msg.set_type(pb::remote::GLOBAL_SEARCH_STATUS);
|
||||
status->set_id(id);
|
||||
@ -718,7 +722,8 @@ void OutgoingDataCreator::ResultsAvailable(
|
||||
|
||||
client->SendData(&msg);
|
||||
|
||||
qLog(Debug) << "ResultsAvailable" << id << results.first().provider_->name() << results.size();
|
||||
qLog(Debug) << "ResultsAvailable" << id << results.first().provider_->name()
|
||||
<< results.size();
|
||||
}
|
||||
|
||||
void OutgoingDataCreator::SearchFinished(int id) {
|
||||
@ -728,7 +733,8 @@ void OutgoingDataCreator::SearchFinished(int id) {
|
||||
|
||||
// Send status message
|
||||
pb::remote::Message msg;
|
||||
pb::remote::ResponseGlobalSearchStatus* status = msg.mutable_response_global_search_status();
|
||||
pb::remote::ResponseGlobalSearchStatus* status =
|
||||
msg.mutable_response_global_search_status();
|
||||
|
||||
msg.set_type(pb::remote::GLOBAL_SEARCH_STATUS);
|
||||
status->set_id(req.id_);
|
||||
|
@ -563,6 +563,7 @@ int Playlist::next_row(bool ignore_repeat_track) const {
|
||||
|
||||
switch (playlist_sequence_->repeat_mode()) {
|
||||
case PlaylistSequence::Repeat_Off:
|
||||
case PlaylistSequence::Repeat_Intro:
|
||||
return -1;
|
||||
case PlaylistSequence::Repeat_Track:
|
||||
next_virtual_index = current_virtual_index_;
|
||||
|
@ -53,6 +53,7 @@ PlaylistSequence::PlaylistSequence(QWidget* parent, SettingsProvider* settings)
|
||||
repeat_group->addAction(ui_->action_repeat_album);
|
||||
repeat_group->addAction(ui_->action_repeat_playlist);
|
||||
repeat_group->addAction(ui_->action_repeat_onebyone);
|
||||
repeat_group->addAction(ui_->action_repeat_intro);
|
||||
repeat_menu_->addActions(repeat_group->actions());
|
||||
ui_->repeat->setMenu(repeat_menu_);
|
||||
|
||||
@ -120,6 +121,7 @@ void PlaylistSequence::RepeatActionTriggered(QAction* action) {
|
||||
if (action == ui_->action_repeat_album) mode = Repeat_Album;
|
||||
if (action == ui_->action_repeat_playlist) mode = Repeat_Playlist;
|
||||
if (action == ui_->action_repeat_onebyone) mode = Repeat_OneByOne;
|
||||
if (action == ui_->action_repeat_intro) mode = Repeat_Intro;
|
||||
|
||||
SetRepeatMode(mode);
|
||||
}
|
||||
@ -152,6 +154,9 @@ void PlaylistSequence::SetRepeatMode(RepeatMode mode) {
|
||||
case Repeat_OneByOne:
|
||||
ui_->action_repeat_onebyone->setChecked(true);
|
||||
break;
|
||||
case Repeat_Intro:
|
||||
ui_->action_repeat_intro->setChecked(true);
|
||||
break;
|
||||
}
|
||||
|
||||
if (mode != repeat_mode_) {
|
||||
@ -245,6 +250,9 @@ void PlaylistSequence::CycleRepeatMode() {
|
||||
mode = Repeat_OneByOne;
|
||||
break;
|
||||
case Repeat_OneByOne:
|
||||
mode = Repeat_Intro;
|
||||
break;
|
||||
case Repeat_Intro:
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@ class PlaylistSequence : public QWidget {
|
||||
Repeat_Album = 2,
|
||||
Repeat_Playlist = 3,
|
||||
Repeat_OneByOne = 4,
|
||||
Repeat_Intro = 5,
|
||||
};
|
||||
enum ShuffleMode {
|
||||
Shuffle_Off = 0,
|
||||
|
@ -106,6 +106,14 @@
|
||||
<string>Stop after each track</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_repeat_intro">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Intro tracks</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_shuffle_off">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
|
@ -494,6 +494,8 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
|
||||
connect(app_->player(), SIGNAL(Seeked(qlonglong)), SLOT(Seeked(qlonglong)));
|
||||
connect(app_->player(), SIGNAL(TrackSkipped(PlaylistItemPtr)),
|
||||
SLOT(TrackSkipped(PlaylistItemPtr)));
|
||||
connect(this, SIGNAL(IntroPointReached()), app_->player(),
|
||||
SLOT(IntroPointReached()));
|
||||
connect(app_->player(), SIGNAL(VolumeChanged(int)), SLOT(VolumeChanged(int)));
|
||||
|
||||
connect(app_->player(), SIGNAL(Paused()), ui_->playlist,
|
||||
@ -1338,6 +1340,13 @@ void MainWindow::UpdateTrackPosition() {
|
||||
}
|
||||
}
|
||||
|
||||
// (just after) the scrobble point is a good point to change tracks in intro mode
|
||||
if (position >= scrobble_point + 5) {
|
||||
if (playlist->sequence()->repeat_mode() == PlaylistSequence::Repeat_Intro) {
|
||||
emit IntroPointReached();
|
||||
}
|
||||
}
|
||||
|
||||
// Update the tray icon every 10 seconds
|
||||
if (position % 10 == 0) {
|
||||
qLog(Debug) << "position" << position << "scrobble point" << scrobble_point
|
||||
|
@ -137,6 +137,8 @@ signals:
|
||||
// Signals that stop playing after track was toggled.
|
||||
void StopAfterToggled(bool stop);
|
||||
|
||||
void IntroPointReached();
|
||||
|
||||
private slots:
|
||||
void FilePathChanged(const QString& path);
|
||||
|
||||
|
@ -317,6 +317,9 @@ void OSD::RepeatModeChanged(PlaylistSequence::RepeatMode mode) {
|
||||
case PlaylistSequence::Repeat_OneByOne:
|
||||
current_mode = tr("Stop after every track");
|
||||
break;
|
||||
case PlaylistSequence::Repeat_Intro:
|
||||
current_mode = tr("Intro tracks");
|
||||
break;
|
||||
}
|
||||
ShowMessage(QCoreApplication::applicationName(), current_mode);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user