From b5977d5e67d68ec18fad1d1130f5a306ce4fe598 Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Fri, 6 Oct 2023 22:00:01 +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. Signed-off-by: Michele Calgaro --- src/app/mainWindow.cpp | 2 +- src/app/mainWindow.h | 2 ++ src/app/stateChange.cpp | 5 ++--- src/app/volumeAction.cpp | 2 +- src/app/volumeAction.h | 4 +++- src/app/xineEngine.cpp | 43 +++++++++++++++++++++++++++++++++++++--- src/app/xineEngine.h | 2 ++ 7 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/app/mainWindow.cpp b/src/app/mainWindow.cpp index 9ca9bc0..b94a2e9 100644 --- a/src/app/mainWindow.cpp +++ b/src/app/mainWindow.cpp @@ -265,7 +265,7 @@ MainWindow::setupActions() (new KWidgetAction( m_positionSlider, i18n("Position Slider"), 0, 0, 0, ac, "position_slider" ))->setAutoSized( true ); - new VolumeAction( toolBar(), ac ); + m_volumeAction = new VolumeAction( toolBar(), ac ); } void diff --git a/src/app/mainWindow.h b/src/app/mainWindow.h index 2139cd5..6ba9e89 100644 --- a/src/app/mainWindow.h +++ b/src/app/mainWindow.h @@ -11,6 +11,7 @@ class KURL; class TQLabel; class TQPopupMenu; class TQSlider; +class VolumeAction; namespace Codeine @@ -65,6 +66,7 @@ namespace Codeine TQLabel *m_timeLabel; TQLabel *m_titleLabel; TQWidget *m_analyzer; + VolumeAction *m_volumeAction; //undefined MainWindow( const MainWindow& ); diff --git a/src/app/stateChange.cpp b/src/app/stateChange.cpp index db07231..e0450d3 100644 --- a/src/app/stateChange.cpp +++ b/src/app/stateChange.cpp @@ -16,6 +16,7 @@ #include "theStream.h" #include "videoSettings.h" //FIXME unfortunate #include "xineEngine.h" +#include "volumeAction.h" //TODO do in Sconstruct @@ -62,9 +63,7 @@ MainWindow::engineStateChanged( Engine::State state ) toggleAction( "play" )->setChecked( state == Playing ); //FIXME bad design to do this way - TQSlider *volume = (TQSlider*)toolBar()->child( "volume" ); - if (volume) - volume->setValue( engine()->volume() ); + m_volumeAction->sliderMoved( engine()->volume() ); } diff --git a/src/app/volumeAction.cpp b/src/app/volumeAction.cpp index 1663190..0d8a181 100644 --- a/src/app/volumeAction.cpp +++ b/src/app/volumeAction.cpp @@ -77,7 +77,7 @@ VolumeAction::toggled( bool const b ) { DEBUG_BLOCK - TQString t = TQString::number(Codeine::engine()->volume()) + "%"; + TQString t = TQString::number(100 - m_widget->slider->value()) + "%"; setToolTip( i18n( "Volume: %1" ).arg( t ) ); m_widget->label->setText( t ); diff --git a/src/app/volumeAction.h b/src/app/volumeAction.h index d2a2520..67cfad0 100644 --- a/src/app/volumeAction.h +++ b/src/app/volumeAction.h @@ -17,9 +17,11 @@ class VolumeAction : public TDEToggleAction virtual int plug( TQWidget*, int ); +public slots: + void sliderMoved( int ); + private slots: void toggled( bool ); - void sliderMoved( int ); void sliderReleased() { setChecked( false ); toggled( false ); } public: diff --git a/src/app/xineEngine.cpp b/src/app/xineEngine.cpp index 74f4f35..3a05862 100644 --- a/src/app/xineEngine.cpp +++ b/src/app/xineEngine.cpp @@ -26,6 +26,7 @@ namespace Codeine { VideoWindow *VideoWindow::s_instance = 0; +bool VideoWindow::s_logarithmicVolume = false; VideoWindow::VideoWindow( TQWidget *parent ) @@ -53,6 +54,13 @@ VideoWindow::VideoWindow( TQWidget *parent ) //TODO sucks //TODO namespace this? myList->next = myList; //init the buffer list + + // 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); } VideoWindow::~VideoWindow() @@ -65,7 +73,12 @@ VideoWindow::~VideoWindow() if( m_stream && xine_get_status( m_stream ) == XINE_STATUS_PLAY ) { int cum = 0; for( int v = 99; v >= 0; v-- ) { - xine_set_param( m_stream, XINE_PARAM_AUDIO_AMP_LEVEL, v ); + int vol = v; + if (s_logarithmicVolume) + { + vol = makeVolumeLogarithmic(vol); + } + xine_set_param( m_stream, XINE_PARAM_AUDIO_AMP_LEVEL, vol ); int sleep = int(32000 * (-std::log10( double(v + 1) ) + 2)); ::usleep( sleep ); @@ -255,6 +268,7 @@ VideoWindow::load( const KURL &url ) setParameter( XINE_PARAM_SPU_CHANNEL, -1 ); setParameter( XINE_PARAM_AUDIO_CHANNEL_LOGICAL, -1 ); setParameter( XINE_PARAM_VO_ASPECT_RATIO, 0 ); + // 100 is the same for both linear and logarithmic volume control setParameter( XINE_PARAM_AUDIO_AMP_LEVEL, 100 ); #undef setParameter @@ -445,8 +459,20 @@ VideoWindow::posTimeLength( PosTimeLength type ) const uint VideoWindow::volume() const { - //TODO I don't like the design - return xine_get_param( m_stream, XINE_PARAM_AUDIO_AMP_LEVEL ); + int vol = xine_get_param( m_stream, XINE_PARAM_AUDIO_AMP_LEVEL ); + if (s_logarithmicVolume) + { + vol = 100 - 100.0 * (pow(10, (100.0 - vol) / 100.0) - 1) / 9.0; + } + if (vol < 0) + { + vol = 0; + } + if (vol > 100) + { + vol = 100; + } + return (uint)vol; } void @@ -532,6 +558,13 @@ VideoWindow::seek( uint pos ) xine_set_param( m_stream, XINE_PARAM_AUDIO_AMP_MUTE, 0 ); } +int +VideoWindow::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 VideoWindow::setStreamParameter( int value ) { @@ -558,6 +591,10 @@ VideoWindow::setStreamParameter( int value ) { parameter = XINE_PARAM_AUDIO_AMP_LEVEL; value = 100 - value; // TQt sliders are wrong way round when vertical + if (s_logarithmicVolume) + { + value = makeVolumeLogarithmic(value); + } } else return; diff --git a/src/app/xineEngine.h b/src/app/xineEngine.h index 70271b9..d152a96 100644 --- a/src/app/xineEngine.h +++ b/src/app/xineEngine.h @@ -39,6 +39,7 @@ namespace Codeine enum PosTimeLength { Pos, Time, Length }; static VideoWindow *s_instance; + static bool s_logarithmicVolume; VideoWindow( const VideoWindow& ); //disable VideoWindow &operator=( const VideoWindow& ); //disable @@ -120,6 +121,7 @@ namespace Codeine private: static void destSizeCallBack( void*, int, int, double, int*, int*, double* ); static void frameOutputCallBack( void*, int, int, double, int*, int*, int*, int*, double*, int*, int* ); + static int makeVolumeLogarithmic(int volume); void initVideo(); void cleanUpVideo();