From a16a898ea354ab5f14b5ec7a4dc9f7a07f00637b Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Wed, 4 Oct 2023 11:43:39 +0900 Subject: [PATCH] xine engine: make volume control logarithmic for versions of xine < 1.2.13. For xine versions >= 1.2.13, libxine already makes the volume logarithmic. This relates to TDE/tdemultimedia#40. This commit makes the behavior consistent across different xine versions and aligned with other players like Amarok. Signed-off-by: Michele Calgaro --- .../player-parts/xine-part/kxinewidget.cpp | 29 ++++++++++++++++--- .../src/player-parts/xine-part/kxinewidget.h | 4 +++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/kaffeine/src/player-parts/xine-part/kxinewidget.cpp b/kaffeine/src/player-parts/xine-part/kxinewidget.cpp index 742d55a..80804b2 100644 --- a/kaffeine/src/player-parts/xine-part/kxinewidget.cpp +++ b/kaffeine/src/player-parts/xine-part/kxinewidget.cpp @@ -61,6 +61,8 @@ #define TIMER_EVENT_RESIZE_PARENT 300 +bool KXineWidget::s_logarithmicVolume = false; + KXineWidget::KXineWidget(TQWidget* parent, const char* name, const TQString& pathToConfigFile, const TQString& pathToLogoFile, const TQString& audioDriver, const TQString& videoDriver, @@ -117,6 +119,13 @@ KXineWidget::KXineWidget(TQWidget* parent, const char* name, setUpdatesEnabled(false); setMouseTracking(true); + + // Detect xine version, this is used for volume adjustment. + // Xine versions prior to 1.2.13 use linear volume, so the engine uses logarithmic volume. + // Xine versions starting from 1.2.13 use logarithmic volume, so the engine uses linear volume. + int xinemajor = 0, xineminor = 0, xinemaint = 0; + xine_get_version(&xinemajor, &xineminor, &xinemaint); + s_logarithmicVolume = (xinemajor * 1000000 + xineminor * 1000 + xinemaint < 1002013); } @@ -2667,16 +2676,28 @@ bool KXineWidget::getAutoplayPluginURLS(const TQString& plugin, TQStringList& li } } +int KXineWidget::makeVolumeLogarithmic(int volume) +{ + // We're using a logarithmic function to make the volume ramp more natural. + return static_cast( 100 - 100.0 * std::log10( ( 100 - volume ) * 0.09 + 1.0 ) ); +} + void KXineWidget::slotSetVolume(int vol) { if (!isXineReady()) return; + if (m_softwareMixer) { + int xine_vol = vol; + if (s_logarithmicVolume) + { + xine_vol = makeVolumeLogarithmic(vol); + } //debugOut(TQString("Set software amplification level: %1").arg(vol)); if (m_volumeGain) - xine_set_param(m_xineStream, XINE_PARAM_AUDIO_AMP_LEVEL, vol*2); + xine_set_param(m_xineStream, XINE_PARAM_AUDIO_AMP_LEVEL, xine_vol*2); else - xine_set_param(m_xineStream, XINE_PARAM_AUDIO_AMP_LEVEL, vol); + xine_set_param(m_xineStream, XINE_PARAM_AUDIO_AMP_LEVEL, xine_vol); } else { @@ -2696,8 +2717,8 @@ uint KXineWidget::getVolume() const if (vol > 200) { // when amp is high > 100, xine_get_param sometimes returns incorrect amp level - errorOut("Amp level returned weird results, set Amp to 100"); - vol = 100; + errorOut("Amp level returned weird results, set Amp to 200"); + vol = 200; } if (m_volumeGain) vol = vol/2; } diff --git a/kaffeine/src/player-parts/xine-part/kxinewidget.h b/kaffeine/src/player-parts/xine-part/kxinewidget.h index 4b4a581..811df93 100644 --- a/kaffeine/src/player-parts/xine-part/kxinewidget.h +++ b/kaffeine/src/player-parts/xine-part/kxinewidget.h @@ -316,6 +316,10 @@ protected: void initOSD(); virtual void run(); + static int makeVolumeLogarithmic(int volume); + + static bool s_logarithmicVolume; + private: #ifndef HAVE_XCB bool x11Event(XEvent *);