diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bf427b759..3966def33 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -248,7 +248,7 @@ set(SOURCES widgets/osd.cpp widgets/osdpretty.cpp widgets/renametablineedit.cpp - widgets/sliderwidget.cpp + widgets/volumeslider.cpp widgets/stickyslider.cpp widgets/stretchheaderview.cpp widgets/stylehelper.cpp @@ -423,7 +423,7 @@ set(HEADERS widgets/osd.h widgets/osdpretty.h widgets/renametablineedit.h - widgets/sliderwidget.h + widgets/volumeslider.h widgets/stickyslider.h widgets/stretchheaderview.h widgets/trackslider.h diff --git a/src/core/mainwindow.cpp b/src/core/mainwindow.cpp index cb1b2b41c..bd2b3e0da 100644 --- a/src/core/mainwindow.cpp +++ b/src/core/mainwindow.cpp @@ -87,7 +87,7 @@ #include "organise/organisedialog.h" #include "widgets/fancytabwidget.h" #include "widgets/playingwidget.h" -#include "widgets/sliderwidget.h" +#include "widgets/volumeslider.h" #include "widgets/fileview.h" #include "widgets/multiloadingindicator.h" #include "widgets/osd.h" @@ -131,6 +131,7 @@ #include "transcoder/transcodedialog.h" #include "settings/settingsdialog.h" #include "settings/behavioursettingspage.h" +#include "settings/backendsettingspage.h" #include "settings/playlistsettingspage.h" #ifdef HAVE_STREAM_TIDAL # include "settings/tidalsettingspage.h" @@ -248,10 +249,6 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co context_view_->SetApplication(app_, collection_view_->view(), album_cover_choice_controller_); ui_->widget_playing->SetApplication(app_, album_cover_choice_controller_); - int volume = app_->player()->GetVolume(); - ui_->volume->setValue(volume); - VolumeChanged(volume); - // Initialise the search widget StyleHelper::setBaseColor(palette().color(QPalette::Highlight).darker()); @@ -286,6 +283,9 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co app_->player()->SetAnalyzer(ui_->analyzer); app_->player()->SetEqualizer(equalizer_.get()); app_->player()->Init(); + int volume = app_->player()->GetVolume(); + ui_->volume->setValue(volume); + VolumeChanged(volume); // Models qLog(Debug) << "Creating models"; @@ -830,6 +830,21 @@ void MainWindow::ReloadSettings() { album_cover_choice_controller_->search_cover_auto_action()->setChecked(settings.value("search_for_cover_auto", true).toBool()); settings.endGroup(); + settings.beginGroup(BackendSettingsPage::kSettingsGroup); + bool volume_control = settings.value("volume_control", true).toBool(); + settings.endGroup(); + if (volume_control != ui_->volume->isEnabled()) { + ui_->volume->SetEnabled(volume_control); + if (volume_control) { + if (!ui_->action_mute->isVisible()) ui_->action_mute->setVisible(true); + if (tray_icon_ && !tray_icon_->MuteEnabled()) tray_icon_->SetMuteEnabled(true); + } + else { + if (ui_->action_mute->isVisible()) ui_->action_mute->setVisible(false); + if (tray_icon_ && tray_icon_->MuteEnabled()) tray_icon_->SetMuteEnabled(false); + } + } + #ifdef HAVE_STREAM_TIDAL settings.beginGroup(TidalSettingsPage::kSettingsGroup); bool enable_tidal = settings.value("enabled", false).toBool(); diff --git a/src/core/mainwindow.ui b/src/core/mainwindow.ui index 3a4f5ef97..712f19ee6 100644 --- a/src/core/mainwindow.ui +++ b/src/core/mainwindow.ui @@ -225,7 +225,7 @@ - + 0 @@ -773,9 +773,9 @@ - Amarok::VolumeSlider + VolumeSlider QSlider -
widgets/sliderwidget.h
+
widgets/volumeslider.h
AnalyzerContainer diff --git a/src/core/player.cpp b/src/core/player.cpp index 9be4a9fbe..103de00ad 100644 --- a/src/core/player.cpp +++ b/src/core/player.cpp @@ -79,29 +79,30 @@ using std::shared_ptr; +const char *Player::kSettingsGroup = "Player"; + Player::Player(Application *app, QObject *parent) : PlayerInterface(parent), app_(app), stream_change_type_(Engine::First), last_state_(Engine::Empty), nb_errors_received_(0), - volume_before_mute_(50), + volume_before_mute_(100), last_pressed_previous_(QDateTime::currentDateTime()), continue_on_error_(false), greyout_(true), menu_previousmode_(PreviousBehaviour_DontRestart), - seek_step_sec_(10) { + seek_step_sec_(10), + volume_control_(true) + { + + settings_.beginGroup(kSettingsGroup); QSettings s; s.beginGroup(BackendSettingsPage::kSettingsGroup); Engine::EngineType enginetype = Engine::EngineTypeFromName(s.value("engine", EngineName(Engine::GStreamer)).toString().toLower()); s.endGroup(); - CreateEngine(enginetype); - settings_.beginGroup("Player"); - - int volume = settings_.value("volume", 50).toInt(); - SetVolume(volume); } @@ -175,6 +176,15 @@ Engine::EngineType Player::CreateEngine(Engine::EngineType enginetype) { void Player::Init() { + QSettings s; + + if (!engine_.get()) { + s.beginGroup(BackendSettingsPage::kSettingsGroup); + Engine::EngineType enginetype = Engine::EngineTypeFromName(s.value("engine", EngineName(Engine::GStreamer)).toString().toLower()); + s.endGroup(); + CreateEngine(enginetype); + } + if (!engine_->Init()) { qFatal("Error initialising audio engine"); } analyzer_->SetEngine(engine_.get()); @@ -188,9 +198,6 @@ void Player::Init() { connect(engine_.get(), SIGNAL(TrackEnded()), SLOT(TrackEnded())); connect(engine_.get(), SIGNAL(MetaData(Engine::SimpleMetaBundle)), SLOT(EngineMetadataReceived(Engine::SimpleMetaBundle))); - int volume = settings_.value("volume", 50).toInt(); - engine_->SetVolume(volume); - // Equalizer qLog(Debug) << "Creating equalizer"; connect(equalizer_, SIGNAL(ParametersChanged(int,QList)), app_->player()->engine(), SLOT(SetEqualizerParameters(int,QList))); @@ -201,6 +208,15 @@ void Player::Init() { engine_->SetEqualizerParameters(equalizer_->preamp_value(), equalizer_->gain_values()); engine_->SetStereoBalance(equalizer_->stereo_balance()); + s.beginGroup(BackendSettingsPage::kSettingsGroup); + volume_control_ = s.value("volume_control", true).toBool(); + s.endGroup(); + + if (volume_control_) { + int volume = settings_.value("volume", 100).toInt(); + SetVolume(volume); + } + ReloadSettings(); } @@ -219,6 +235,11 @@ void Player::ReloadSettings() { seek_step_sec_ = s.value("seek_step_sec", 10).toInt(); s.endGroup(); + s.beginGroup(BackendSettingsPage::kSettingsGroup); + bool volume_control = s.value("volume_control", true).toBool(); + if (!volume_control && GetVolume() != 100) SetVolume(100); + s.endGroup(); + engine_->ReloadSettings(); } @@ -631,6 +652,8 @@ PlaylistItemPtr Player::GetItemAt(int pos) const { void Player::Mute() { + if (!volume_control_) return; + const int current_volume = engine_->volume(); if (current_volume == 0) { @@ -640,6 +663,7 @@ void Player::Mute() { volume_before_mute_ = current_volume; SetVolume(0); } + } void Player::Pause() { engine_->Pause(); } diff --git a/src/core/player.h b/src/core/player.h index 07e6078c1..6cc5c918b 100644 --- a/src/core/player.h +++ b/src/core/player.h @@ -102,6 +102,7 @@ class PlayerInterface : public QObject { void Stopped(); void Error(); void PlaylistFinished(); + void VolumeEnabled(bool); void VolumeChanged(int volume); void Error(const QString &message); void TrackSkipped(PlaylistItemPtr old_track); @@ -206,10 +207,11 @@ class Player : public PlayerInterface { private: Application *app_; - QSettings settings_; AnalyzerContainer *analyzer_; Equalizer *equalizer_; + QSettings settings_; + PlaylistItemPtr current_item_; std::unique_ptr engine_; @@ -228,6 +230,8 @@ class Player : public PlayerInterface { PreviousBehaviour menu_previousmode_; int seek_step_sec_; + bool volume_control_; + }; #endif // PLAYER_H diff --git a/src/core/qtsystemtrayicon.h b/src/core/qtsystemtrayicon.h index a091a69c9..b2f914715 100644 --- a/src/core/qtsystemtrayicon.h +++ b/src/core/qtsystemtrayicon.h @@ -55,6 +55,9 @@ class QtSystemTrayIcon : public SystemTrayIcon { void SetNowPlaying(const Song &song, const QString &image_path); void ClearNowPlaying(); + bool MuteEnabled() { return action_mute_->isVisible(); } + void SetMuteEnabled(bool enabled) { action_mute_->setVisible(enabled); } + protected: // SystemTrayIcon void UpdateIcon(); diff --git a/src/core/systemtrayicon.h b/src/core/systemtrayicon.h index 70a075592..1d432daaf 100644 --- a/src/core/systemtrayicon.h +++ b/src/core/systemtrayicon.h @@ -50,6 +50,9 @@ class SystemTrayIcon : public QObject { virtual void SetNowPlaying(const Song &song, const QString &image_path) {} virtual void ClearNowPlaying() {} + virtual bool MuteEnabled() { return false; } + virtual void SetMuteEnabled(bool enabled) {} + static SystemTrayIcon *CreateSystemTrayIcon(QObject *parent = nullptr); public slots: diff --git a/src/engine/enginebase.cpp b/src/engine/enginebase.cpp index bfcb4f519..bb02fb751 100644 --- a/src/engine/enginebase.cpp +++ b/src/engine/enginebase.cpp @@ -36,7 +36,7 @@ #include "settings/backendsettingspage.h" Engine::Base::Base() - : volume_(50), + : volume_(100), beginning_nanosec_(0), end_nanosec_(0), scope_(kScopeSize), @@ -103,6 +103,8 @@ void Engine::Base::ReloadSettings() { output_ = s.value("output").toString(); device_ = s.value("device"); + volume_control_ = s.value("volume_control", true).toBool(); + buffer_duration_nanosec_ = s.value("bufferduration", 4000).toLongLong() * kNsecPerMsec; buffer_min_fill_ = s.value("bufferminfill", 33).toInt(); diff --git a/src/engine/enginebase.h b/src/engine/enginebase.h index f610c4386..6c9506dfa 100644 --- a/src/engine/enginebase.h +++ b/src/engine/enginebase.h @@ -112,6 +112,7 @@ public: // Simple accessors EngineType type() const { return type_; } + bool volume_control() const { return volume_control_; } inline uint volume() const { return volume_; } bool is_fadeout_enabled() const { return fadeout_enabled_; } @@ -153,7 +154,7 @@ signals: // Always use the state from event, because it's not guaranteed that immediate subsequent call to state() won't return a stale value. void StateChanged(Engine::State); -protected: + protected: struct PluginDetails { QString name; @@ -163,6 +164,7 @@ protected: typedef QList PluginDetailsList; EngineType type_; + bool volume_control_; uint volume_; quint64 beginning_nanosec_; qint64 end_nanosec_; diff --git a/src/engine/gstengine.cpp b/src/engine/gstengine.cpp index 38dbdb554..8b8d38811 100644 --- a/src/engine/gstengine.cpp +++ b/src/engine/gstengine.cpp @@ -803,6 +803,7 @@ shared_ptr GstEngine::CreatePipeline() { shared_ptr ret(new GstEnginePipeline(this)); ret->set_output_device(output_, device_); + ret->set_volume_control(volume_control_); ret->set_replaygain(rg_enabled_, rg_mode_, rg_preamp_, rg_compression_); ret->set_buffer_duration_nanosec(buffer_duration_nanosec_); ret->set_buffer_min_fill(buffer_min_fill_); diff --git a/src/engine/gstengine.h b/src/engine/gstengine.h index 3d5a2b0aa..3cb659616 100644 --- a/src/engine/gstengine.h +++ b/src/engine/gstengine.h @@ -75,6 +75,7 @@ class GstEngine : public Engine::Base, public GstBufferConsumer { void Pause(); void Unpause(); void Seek(quint64 offset_nanosec); + protected: void SetVolumeSW(uint percent); diff --git a/src/engine/gstenginepipeline.cpp b/src/engine/gstenginepipeline.cpp index 6a804a52f..d9f5be17f 100644 --- a/src/engine/gstenginepipeline.cpp +++ b/src/engine/gstenginepipeline.cpp @@ -53,8 +53,7 @@ const int GstEnginePipeline::kGstStateTimeoutNanosecs = 10000000; const int GstEnginePipeline::kFaderFudgeMsec = 2000; const int GstEnginePipeline::kEqBandCount = 10; -const int GstEnginePipeline::kEqBandFrequencies[] = { - 60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000}; +const int GstEnginePipeline::kEqBandFrequencies[] = { 60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000 }; int GstEnginePipeline::sId = 1; GstElementDeleter *GstEnginePipeline::sElementDeleter = nullptr; @@ -64,8 +63,9 @@ GstEnginePipeline::GstEnginePipeline(GstEngine *engine) engine_(engine), id_(sId++), valid_(false), - output_(""), + output_(QString()), device_(QVariant()), + volume_control_(true), eq_enabled_(false), eq_preamp_(0), stereo_balance_(0.0f), @@ -118,6 +118,12 @@ void GstEnginePipeline::set_output_device(const QString &output, const QVariant } +void GstEnginePipeline::set_volume_control(bool volume_control) { + + volume_control_ = volume_control; + +} + void GstEnginePipeline::set_replaygain(bool enabled, int mode, float preamp, bool compression) { rg_enabled_ = enabled; @@ -239,14 +245,21 @@ bool GstEnginePipeline::InitAudioBin() { probe_sink = engine_->CreateElement("fakesink", audiobin_); audio_queue = engine_->CreateElement("queue", audiobin_); - equalizer_preamp_ = engine_->CreateElement("volume", audiobin_, false); - equalizer_ = engine_->CreateElement("equalizer-nbands", audiobin_, false); - audio_panorama_ = engine_->CreateElement("audiopanorama", audiobin_, false); - volume_ = engine_->CreateElement("volume", audiobin_); audioscale_ = engine_->CreateElement("audioresample", audiobin_); convert = engine_->CreateElement("audioconvert", audiobin_); - if (!queue_ || !audioconvert_ || !tee || !probe_queue || !probe_converter || !probe_sink || !audio_queue || !volume_ || !audioscale_ || !convert) { + if (engine_->volume_control()) { + volume_ = engine_->CreateElement("volume", audiobin_); + } + + audio_panorama_ = engine_->CreateElement("audiopanorama", audiobin_, false); + + if (eq_enabled_) { + equalizer_preamp_ = engine_->CreateElement("volume", audiobin_, false); + equalizer_ = engine_->CreateElement("equalizer-nbands", audiobin_, false); + } + + if (!queue_ || !audioconvert_ || !tee || !probe_queue || !probe_converter || !probe_sink || !audio_queue || !audioscale_ || !convert) { gst_object_unref(GST_OBJECT(audiobin_)); return false; } @@ -348,8 +361,16 @@ bool GstEnginePipeline::InitAudioBin() { // Don't force 16 bit. gst_element_link(probe_queue, probe_converter); - if (engine_->IsEqualizerEnabled() && equalizer_ && equalizer_preamp_ && audio_panorama_) gst_element_link_many(audio_queue, equalizer_preamp_, equalizer_, audio_panorama_, volume_, audioscale_, convert, nullptr); - else gst_element_link_many(audio_queue, volume_, audioscale_, convert, nullptr); + if (eq_enabled_ && equalizer_ && equalizer_preamp_ && audio_panorama_) { + if (volume_) + gst_element_link_many(audio_queue, equalizer_preamp_, equalizer_, audio_panorama_, volume_, audioscale_, convert, nullptr); + else + gst_element_link_many(audio_queue, equalizer_preamp_, equalizer_, audio_panorama_, audioscale_, convert, nullptr); + } + else { + if (volume_) gst_element_link_many(audio_queue, volume_, audioscale_, convert, nullptr); + else gst_element_link_many(audio_queue, audioscale_, convert, nullptr); + } // Let the audio output of the tee autonegotiate the bit depth and format. GstCaps *caps = gst_caps_new_empty_simple("audio/x-raw"); @@ -993,16 +1014,19 @@ void GstEnginePipeline::UpdateStereoBalance() { } void GstEnginePipeline::SetVolume(int percent) { + if (!volume_) return; volume_percent_ = percent; UpdateVolume(); } void GstEnginePipeline::SetVolumeModifier(qreal mod) { + if (!volume_) return; volume_modifier_ = mod; UpdateVolume(); } void GstEnginePipeline::UpdateVolume() { + if (!volume_) return; float vol = double(volume_percent_) * 0.01 * volume_modifier_; g_object_set(G_OBJECT(volume_), "volume", vol, nullptr); } diff --git a/src/engine/gstenginepipeline.h b/src/engine/gstenginepipeline.h index f7ecf8597..e8aa33e3a 100644 --- a/src/engine/gstenginepipeline.h +++ b/src/engine/gstenginepipeline.h @@ -68,6 +68,7 @@ class GstEnginePipeline : public QObject { // Call these setters before Init void set_output_device(const QString &sink, const QVariant &device); + void set_volume_control(bool volume_control); void set_replaygain(bool enabled, int mode, float preamp, bool compression); void set_buffer_duration_nanosec(qint64 duration_nanosec); void set_buffer_min_fill(int percent); @@ -187,6 +188,7 @@ signals: bool valid_; QString output_; QVariant device_; + bool volume_control_; // Equalizer bool eq_enabled_; diff --git a/src/engine/vlcengine.cpp b/src/engine/vlcengine.cpp index 25ce8ee85..b53d2e646 100644 --- a/src/engine/vlcengine.cpp +++ b/src/engine/vlcengine.cpp @@ -173,6 +173,7 @@ void VLCEngine::Seek(quint64 offset_nanosec) { void VLCEngine::SetVolumeSW(uint percent) { if (!Initialised()) return; + if (!volume_control_ && percent != 100) return; libvlc_audio_set_volume(player_, percent); } diff --git a/src/engine/xineengine.cpp b/src/engine/xineengine.cpp index 95581cecf..60aac902a 100644 --- a/src/engine/xineengine.cpp +++ b/src/engine/xineengine.cpp @@ -393,6 +393,7 @@ void XineEngine::Seek(quint64 offset_nanosec) { void XineEngine::SetVolumeSW(uint vol) { if (!stream_) return; + if (!volume_control_ && vol != 100) return; xine_set_param(stream_, XINE_PARAM_AUDIO_AMP_LEVEL, static_cast(vol * preamp_)); } diff --git a/src/settings/backendsettingspage.cpp b/src/settings/backendsettingspage.cpp index 25b2f4fbd..8f80a9ab6 100644 --- a/src/settings/backendsettingspage.cpp +++ b/src/settings/backendsettingspage.cpp @@ -129,6 +129,9 @@ void BackendSettingsPage::Load() { ui_->checkbox_monoplayback->setChecked(s_.value("monoplayback", false).toBool()); +#if defined(HAVE_ALSA) + ui_->lineedit_device->show(); + ui_->widget_alsa_plugin->show(); int alsaplug_int = alsa_plugin(s_.value("alsaplugin", 0).toInt()); if (alsa_plugin(alsaplug_int)) { alsa_plugin alsaplugin = alsa_plugin(alsaplug_int); @@ -141,6 +144,12 @@ void BackendSettingsPage::Load() { break; } } +#else + ui_->lineedit_device->hide(); + ui_->widget_alsa_plugin->hide(); +#endif + + ui_->checkbox_volume_control->setChecked(s_.value("volume_control", true).toBool()); if (!EngineInitialised()) return; @@ -164,8 +173,10 @@ void BackendSettingsPage::ConnectSignals() { connect(ui_->combobox_output, SIGNAL(currentIndexChanged(int)), SLOT(OutputChanged(int))); connect(ui_->combobox_device, SIGNAL(currentIndexChanged(int)), SLOT(DeviceSelectionChanged(int))); connect(ui_->lineedit_device, SIGNAL(textChanged(const QString &)), SLOT(DeviceStringChanged())); +#if defined(HAVE_ALSA) connect(ui_->radiobutton_alsa_hw, SIGNAL(clicked(bool)), SLOT(radiobutton_alsa_hw_clicked(bool))); connect(ui_->radiobutton_alsa_plughw, SIGNAL(clicked(bool)), SLOT(radiobutton_alsa_plughw_clicked(bool))); +#endif connect(ui_->slider_bufferminfill, SIGNAL(valueChanged(int)), SLOT(BufferMinFillChanged(int))); connect(ui_->stickslider_replaygainpreamp, SIGNAL(valueChanged(int)), SLOT(RgPreampChanged(int))); connect(ui_->checkbox_fadeout_stop, SIGNAL(toggled(bool)), SLOT(FadingOptionsChanged())); @@ -300,6 +311,7 @@ void BackendSettingsPage::Load_Device(QString output, QVariant device) { ui_->lineedit_device->setEnabled(false); } +#ifdef HAVE_ALSA if (engine()->ALSADeviceSupport(output)) { ui_->radiobutton_alsa_hw->setEnabled(true); ui_->radiobutton_alsa_plughw->setEnabled(true); @@ -320,6 +332,7 @@ void BackendSettingsPage::Load_Device(QString output, QVariant device) { ui_->radiobutton_alsa_plughw->setEnabled(false); ui_->radiobutton_alsa_plughw->setChecked(false); } +#endif bool found(false); for (int i = 0; i < ui_->combobox_device->count(); ++i) { @@ -391,9 +404,13 @@ void BackendSettingsPage::Save() { s_.setValue("monoplayback", ui_->checkbox_monoplayback->isChecked()); +#ifdef HAVE_ALSA if (ui_->radiobutton_alsa_hw->isChecked()) s_.setValue("alsaplugin", static_cast(alsa_plugin::alsa_hw)); else if (ui_->radiobutton_alsa_plughw->isChecked()) s_.setValue("alsaplugin", static_cast(alsa_plugin::alsa_plughw)); else s_.remove("alsaplugin"); +#endif + + s_.setValue("volume_control", ui_->checkbox_volume_control->isChecked()); } @@ -463,6 +480,7 @@ void BackendSettingsPage::DeviceStringChanged() { EngineBase::OutputDetails output = ui_->combobox_output->itemData(ui_->combobox_output->currentIndex()).value(); bool found(false); +#ifdef HAVE_ALSA if (engine()->ALSADeviceSupport(output.name)) { if (ui_->lineedit_device->text().contains(QRegExp("^hw:.*")) && !ui_->radiobutton_alsa_hw->isChecked()) { ui_->radiobutton_alsa_hw->setChecked(true); @@ -473,6 +491,7 @@ void BackendSettingsPage::DeviceStringChanged() { SwitchALSADevices(alsa_plugin::alsa_plughw); } } +#endif for (int i = 0; i < ui_->combobox_device->count(); ++i) { QVariant device = ui_->combobox_device->itemData(i).value(); @@ -522,6 +541,7 @@ void BackendSettingsPage::BufferMinFillChanged(int value) { ui_->label_bufferminfillvalue->setText(QString::number(value) + "%"); } +#ifdef HAVE_ALSA void BackendSettingsPage::SwitchALSADevices(alsa_plugin alsaplugin) { // All ALSA devices are listed twice, one for "hw" and one for "plughw" @@ -592,6 +612,8 @@ void BackendSettingsPage::radiobutton_alsa_plughw_clicked(bool checked) { } +#endif + void BackendSettingsPage::FadingOptionsChanged() { if (EngineInitialised()) { diff --git a/src/settings/backendsettingspage.h b/src/settings/backendsettingspage.h index 4c9ba547e..225002567 100644 --- a/src/settings/backendsettingspage.h +++ b/src/settings/backendsettingspage.h @@ -63,16 +63,19 @@ public: void DeviceStringChanged(); void RgPreampChanged(int value); void BufferMinFillChanged(int value); +#ifdef HAVE_ALSA void radiobutton_alsa_hw_clicked(bool checked); void radiobutton_alsa_plughw_clicked(bool checked); +#endif void FadingOptionsChanged(); private: - +#ifdef HAVE_ALSA enum alsa_plugin { alsa_hw = 1, alsa_plughw = 2 }; +#endif Ui_BackendSettingsPage *ui_; @@ -84,7 +87,9 @@ private: void Load_Engine(Engine::EngineType enginetype); void Load_Output(QString output, QVariant device); void Load_Device(QString output, QVariant device); +#ifdef HAVE_ALSA void SwitchALSADevices(alsa_plugin alsaplugin); +#endif QSettings s_; bool configloaded_; diff --git a/src/settings/backendsettingspage.ui b/src/settings/backendsettingspage.ui index edea6a455..c7f6145f3 100644 --- a/src/settings/backendsettingspage.ui +++ b/src/settings/backendsettingspage.ui @@ -7,7 +7,7 @@ 0 0 596 - 740 + 772
@@ -172,66 +172,75 @@
- - - - - - 90 - 0 - - - - ALSA plugin - - - - - - - false - - - - 0 - 20 - - - - hw - - - - - - - false - - - - 0 - 20 - - - - p&lughw - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - + + + + + + + 90 + 0 + + + + ALSA plugin + + + + + + + false + + + + 0 + 20 + + + + hw + + + + + + + false + + + + 0 + 20 + + + + p&lughw + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + + + Enable volume control + + diff --git a/src/widgets/sliderwidget.cpp b/src/widgets/volumeslider.cpp similarity index 84% rename from src/widgets/sliderwidget.cpp rename to src/widgets/volumeslider.cpp index 7f3e302c6..1f49a0757 100644 --- a/src/widgets/sliderwidget.cpp +++ b/src/widgets/volumeslider.cpp @@ -19,7 +19,7 @@ #include "config.h" -#include "sliderwidget.h" +#include "volumeslider.h" #include #include @@ -48,7 +48,7 @@ #include #include -Amarok::Slider::Slider(Qt::Orientation orientation, QWidget* parent, uint max) +SliderSlider::SliderSlider(Qt::Orientation orientation, QWidget* parent, uint max) : QSlider(orientation, parent), m_sliding(false), m_outside(false), @@ -56,7 +56,7 @@ Amarok::Slider::Slider(Qt::Orientation orientation, QWidget* parent, uint max) setRange(0, max); } -void Amarok::Slider::wheelEvent(QWheelEvent* e) { +void SliderSlider::wheelEvent(QWheelEvent* e) { if (orientation() == Qt::Vertical) { // Will be handled by the parent widget @@ -74,7 +74,7 @@ void Amarok::Slider::wheelEvent(QWheelEvent* e) { } -void Amarok::Slider::mouseMoveEvent(QMouseEvent *e) { +void SliderSlider::mouseMoveEvent(QMouseEvent *e) { if (m_sliding) { // feels better, but using set value of 20 is bad of course @@ -95,7 +95,7 @@ void Amarok::Slider::mouseMoveEvent(QMouseEvent *e) { } -void Amarok::Slider::slideEvent(QMouseEvent* e) { +void SliderSlider::slideEvent(QMouseEvent* e) { QStyleOptionSlider option; initStyleOption(&option); @@ -118,7 +118,7 @@ void Amarok::Slider::slideEvent(QMouseEvent* e) { } -void Amarok::Slider::mousePressEvent(QMouseEvent* e) { +void SliderSlider::mousePressEvent(QMouseEvent* e) { QStyleOptionSlider option; initStyleOption(&option); @@ -131,15 +131,17 @@ void Amarok::Slider::mousePressEvent(QMouseEvent* e) { } -void Amarok::Slider::mouseReleaseEvent(QMouseEvent*) { +void SliderSlider::mouseReleaseEvent(QMouseEvent*) { + if (!m_outside && QSlider::value() != m_prevValue) emit sliderReleased(value()); m_sliding = false; m_outside = false; + } -void Amarok::Slider::setValue(int newValue) { +void SliderSlider::setValue(int newValue) { // don't adjust the slider while the user is dragging it! if (!m_sliding || m_outside) @@ -155,27 +157,27 @@ void Amarok::Slider::setValue(int newValue) { #define THICKNESS 7 #define MARGIN 3 -Amarok::PrettySlider::PrettySlider(Qt::Orientation orientation, SliderMode mode, QWidget* parent, uint max) - : Amarok::Slider(orientation, parent, max), m_mode(mode) { +PrettySlider::PrettySlider(Qt::Orientation orientation, SliderMode mode, QWidget* parent, uint max) + : SliderSlider(orientation, parent, max), m_mode(mode) { if (m_mode == Pretty) { setFocusPolicy(Qt::NoFocus); } } -void Amarok::PrettySlider::mousePressEvent(QMouseEvent* e) { - Amarok::Slider::mousePressEvent(e); +void PrettySlider::mousePressEvent(QMouseEvent* e) { + SliderSlider::mousePressEvent(e); slideEvent(e); } -void Amarok::PrettySlider::slideEvent(QMouseEvent* e) { +void PrettySlider::slideEvent(QMouseEvent* e) { if (m_mode == Pretty) QSlider::setValue( orientation() == Qt::Horizontal ? QStyle::sliderValueFromPosition(minimum(), maximum(), e->pos().x(), width() - 2) : QStyle::sliderValueFromPosition(minimum(), maximum(), e->pos().y(), height() - 2)); else - Amarok::Slider::slideEvent(e); + SliderSlider::slideEvent(e); } namespace Amarok { @@ -186,18 +188,13 @@ extern QColor Foreground; } #if 0 -/** these functions aren't required in our fixed size world, - but they may become useful one day **/ +/** these functions aren't required in our fixed size world, but they may become useful one day **/ -QSize -Amarok::PrettySlider::minimumSizeHint() const -{ +QSize PrettySlider::minimumSizeHint() const { return sizeHint(); } -QSize -Amarok::PrettySlider::sizeHint() const -{ +QSize PrettySlider::sizeHint() const { constPolish(); return (orientation() == Horizontal @@ -210,8 +207,8 @@ Amarok::PrettySlider::sizeHint() const /// CLASS VolumeSlider ////////////////////////////////////////////////////////////////////////////////////////// -Amarok::VolumeSlider::VolumeSlider(QWidget* parent, uint max) - : Amarok::Slider(Qt::Horizontal, parent, max), +VolumeSlider::VolumeSlider(QWidget* parent, uint max) + : SliderSlider(Qt::Horizontal, parent, max), m_animCount(0), m_animTimer(new QTimer(this)), m_pixmapInset(QPixmap(drawVolumePixmap ())) { @@ -228,9 +225,16 @@ Amarok::VolumeSlider::VolumeSlider(QWidget* parent, uint max) setMinimumHeight(m_pixmapInset.height()); connect(m_animTimer, SIGNAL(timeout()), this, SLOT(slotAnimTimer())); + } -void Amarok::VolumeSlider::generateGradient() { +void VolumeSlider::SetEnabled(const bool enabled) { + QSlider::setEnabled(enabled); + QSlider::setVisible(enabled); +} + +void VolumeSlider::generateGradient() { + const QImage mask(":/pictures/volumeslider-gradient.png"); QImage gradient_image(mask.size(), QImage::Format_ARGB32_Premultiplied); @@ -246,10 +250,11 @@ void Amarok::VolumeSlider::generateGradient() { p.end(); m_pixmapGradient = QPixmap::fromImage(gradient_image); + } -void Amarok::VolumeSlider::slotAnimTimer() // SLOT -{ +void VolumeSlider::slotAnimTimer() { + if (m_animEnter) { m_animCount++; update(); @@ -260,16 +265,20 @@ void Amarok::VolumeSlider::slotAnimTimer() // SLOT update(); if (m_animCount == 0) m_animTimer->stop(); } + } -void Amarok::VolumeSlider::mousePressEvent(QMouseEvent* e) { +void VolumeSlider::mousePressEvent(QMouseEvent* e) { + if (e->button() != Qt::RightButton) { - Amarok::Slider::mousePressEvent(e); + SliderSlider::mousePressEvent(e); slideEvent(e); } + } -void Amarok::VolumeSlider::contextMenuEvent(QContextMenuEvent* e) { +void VolumeSlider::contextMenuEvent(QContextMenuEvent* e) { + QMap values; QMenu menu; menu.setTitle("Volume"); @@ -285,19 +294,23 @@ void Amarok::VolumeSlider::contextMenuEvent(QContextMenuEvent* e) { QSlider::setValue(values[ret]); emit sliderReleased(values[ret]); } + } -void Amarok::VolumeSlider::slideEvent(QMouseEvent* e) { +void VolumeSlider::slideEvent(QMouseEvent* e) { QSlider::setValue(QStyle::sliderValueFromPosition(minimum(), maximum(), e->pos().x(), width() - 2)); } -void Amarok::VolumeSlider::wheelEvent(QWheelEvent* e) { +void VolumeSlider::wheelEvent(QWheelEvent* e) { + const uint step = e->delta() / (e->orientation() == Qt::Vertical ? 30 : -30); QSlider::setValue(QSlider::value() + step); emit sliderReleased(value()); + } -void Amarok::VolumeSlider::paintEvent(QPaintEvent*) { +void VolumeSlider::paintEvent(QPaintEvent*) { + QPainter p(this); const int padding = 7; @@ -326,28 +339,34 @@ void Amarok::VolumeSlider::paintEvent(QPaintEvent*) { p.setFont(vol_font); const QRect rect(0, 0, 34, 15); p.drawText(rect, Qt::AlignRight | Qt::AlignVCenter, QString::number(value()) + '%'); + } -void Amarok::VolumeSlider::enterEvent(QEvent*) { +void VolumeSlider::enterEvent(QEvent*) { + m_animEnter = true; m_animCount = 0; m_animTimer->start(ANIM_INTERVAL); + } -void Amarok::VolumeSlider::leaveEvent(QEvent*) { +void VolumeSlider::leaveEvent(QEvent*) { + // This can happen if you enter and leave the widget quickly if (m_animCount == 0) m_animCount = 1; m_animEnter = false; m_animTimer->start(ANIM_INTERVAL); + } -void Amarok::VolumeSlider::paletteChange(const QPalette&) { +void VolumeSlider::paletteChange(const QPalette&) { generateGradient(); } -QPixmap Amarok::VolumeSlider::drawVolumePixmap () const { +QPixmap VolumeSlider::drawVolumePixmap () const { + QPixmap pixmap(112, 36); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); @@ -358,18 +377,18 @@ QPixmap Amarok::VolumeSlider::drawVolumePixmap () const { painter.setRenderHint(QPainter::SmoothPixmapTransform); // Draw volume control pixmap QPolygon poly; - poly << QPoint(6, 21) << QPoint(104, 21) - << QPoint(104, 7) << QPoint(6, 16) - << QPoint(6, 21); + poly << QPoint(6, 21) << QPoint(104, 21) << QPoint(104, 7) << QPoint(6, 16) << QPoint(6, 21); QPainterPath path; path.addPolygon(poly); painter.drawPolygon(poly); painter.drawLine(6, 29, 104, 29); // Return QPixmap return pixmap; + } -void Amarok::VolumeSlider::drawVolumeSliderHandle() { +void VolumeSlider::drawVolumeSliderHandle() { + QImage pixmapHandle(":/pictures/volumeslider-handle.png"); QImage pixmapHandleGlow(":/pictures/volumeslider-handle_glow.png"); @@ -405,4 +424,5 @@ void Amarok::VolumeSlider::drawVolumeSliderHandle() { opacity += step; } // END + } diff --git a/src/widgets/sliderwidget.h b/src/widgets/volumeslider.h similarity index 86% rename from src/widgets/sliderwidget.h rename to src/widgets/volumeslider.h index a2042eef5..aa06eec55 100644 --- a/src/widgets/sliderwidget.h +++ b/src/widgets/volumeslider.h @@ -17,8 +17,8 @@ * * ***************************************************************************/ -#ifndef SLIDERWIDGET_H -#define SLIDERWIDGET_H +#ifndef VOLUMESLIDER_H +#define VOLUMESLIDER_H #include "config.h" @@ -42,22 +42,19 @@ class QPaintEvent; class QWheelEvent; class QContextMenuEvent; -namespace Amarok { -class Slider : public QSlider { +class SliderSlider : public QSlider { Q_OBJECT public: - Slider(Qt::Orientation, QWidget*, uint max = 0); + SliderSlider(Qt::Orientation, QWidget*, uint max = 0); virtual void setValue(int); - // WARNING non-virtual - and thus only really intended for internal use this is a major flaw in the class presently, - // however it suits our current needs fine + // WARNING non-virtual - and thus only really intended for internal use this is a major flaw in the class presently, however it suits our current needs fine int value() const { return adjustValue(QSlider::value()); } signals: - // we emit this when the user has specifically changed the slider so connect to it if valueChanged() is too generic - // Qt also emits valueChanged( int ) + // we emit this when the user has specifically changed the slider so connect to it if valueChanged() is too generic Qt also emits valueChanged(int) void sliderReleased(int); protected: @@ -79,11 +76,11 @@ signals: bool m_outside; int m_prevValue; - Slider(const Slider&); // undefined - Slider& operator=(const Slider&); // undefined + SliderSlider(const SliderSlider&); // undefined + SliderSlider& operator=(const SliderSlider&); // undefined }; -class PrettySlider : public Slider { +class PrettySlider : public SliderSlider { Q_OBJECT public: @@ -105,11 +102,12 @@ class PrettySlider : public Slider { SliderMode m_mode; }; -class VolumeSlider : public Slider { +class VolumeSlider : public SliderSlider { Q_OBJECT public: VolumeSlider(QWidget* parent, uint max = 0); + void SetEnabled(const bool enabled); protected: virtual void paintEvent(QPaintEvent*); @@ -148,6 +146,5 @@ class VolumeSlider : public Slider { QList m_handlePixmaps; }; -} -#endif // SLIDERWIDGET_H +#endif // VOLUMESLIDER_H