Add option to disable volume control

This commit is contained in:
Jonas Kvinge 2019-03-09 16:48:45 +01:00
parent 384209ba70
commit 3e658845d2
20 changed files with 287 additions and 151 deletions

View File

@ -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

View File

@ -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();

View File

@ -225,7 +225,7 @@
</widget>
</item>
<item>
<widget class="Amarok::VolumeSlider" name="volume">
<widget class="VolumeSlider" name="volume">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -773,9 +773,9 @@
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>Amarok::VolumeSlider</class>
<class>VolumeSlider</class>
<extends>QSlider</extends>
<header>widgets/sliderwidget.h</header>
<header>widgets/volumeslider.h</header>
</customwidget>
<customwidget>
<class>AnalyzerContainer</class>

View File

@ -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<int>)), app_->player()->engine(), SLOT(SetEqualizerParameters(int,QList<int>)));
@ -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(); }

View File

@ -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<EngineBase> engine_;
@ -228,6 +230,8 @@ class Player : public PlayerInterface {
PreviousBehaviour menu_previousmode_;
int seek_step_sec_;
bool volume_control_;
};
#endif // PLAYER_H

View File

@ -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();

View File

@ -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:

View File

@ -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();

View File

@ -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<PluginDetails> PluginDetailsList;
EngineType type_;
bool volume_control_;
uint volume_;
quint64 beginning_nanosec_;
qint64 end_nanosec_;

View File

@ -803,6 +803,7 @@ shared_ptr<GstEnginePipeline> GstEngine::CreatePipeline() {
shared_ptr<GstEnginePipeline> 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_);

View File

@ -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);

View File

@ -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);
}

View File

@ -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_;

View File

@ -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);
}

View File

@ -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<uint>(vol * preamp_));
}

View File

@ -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<int>(alsa_plugin::alsa_hw));
else if (ui_->radiobutton_alsa_plughw->isChecked()) s_.setValue("alsaplugin", static_cast<int>(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<EngineBase::OutputDetails>();
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<QVariant>();
@ -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()) {

View File

@ -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_;

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>596</width>
<height>740</height>
<height>772</height>
</rect>
</property>
<property name="windowTitle">
@ -172,66 +172,75 @@
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_alsaplugin">
<item>
<widget class="QLabel" name="label_alsaplugin">
<property name="minimumSize">
<size>
<width>90</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>ALSA plugin</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radiobutton_alsa_hw">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>hw</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radiobutton_alsa_plughw">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>p&amp;lughw</string>
</property>
</widget>
</item>
<item>
<spacer name="spacer_alsaplugin">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
<widget class="QWidget" name="widget_alsa_plugin" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_alsaplugin">
<item>
<widget class="QLabel" name="label_alsaplugin">
<property name="minimumSize">
<size>
<width>90</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>ALSA plugin</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radiobutton_alsa_hw">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>hw</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radiobutton_alsa_plughw">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>p&amp;lughw</string>
</property>
</widget>
</item>
<item>
<spacer name="spacer_alsaplugin">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkbox_volume_control">
<property name="text">
<string>Enable volume control</string>
</property>
</widget>
</item>
</layout>
</widget>

View File

@ -19,7 +19,7 @@
#include "config.h"
#include "sliderwidget.h"
#include "volumeslider.h"
#include <QApplication>
#include <QWidget>
@ -48,7 +48,7 @@
#include <QFlags>
#include <QtEvents>
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<QAction*, int> 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
}

View File

@ -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<QPixmap> m_handlePixmaps;
};
}
#endif // SLIDERWIDGET_H
#endif // VOLUMESLIDER_H