diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index d4b05cb3c..ccb03f607 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -215,6 +215,7 @@ list(APPEND libSources audio/AudioEngine.cpp audio/AudioOutput.cpp + audio/VlcDspHack.cpp collection/Collection.cpp collection/ArtistsRequest.cpp @@ -506,6 +507,7 @@ TARGET_LINK_LIBRARIES( tomahawklib LINK_PRIVATE ${PHONON_LIBRARY} ${LIBVLC_LIBRARY} + ${LIBVLCCORE_LIBRARY} # Thirdparty shipped with tomahawk ${LIBPORTFWD_LIBRARIES} diff --git a/src/libtomahawk/audio/AudioEngine.cpp b/src/libtomahawk/audio/AudioEngine.cpp index 149cab3fd..649ca150d 100644 --- a/src/libtomahawk/audio/AudioEngine.cpp +++ b/src/libtomahawk/audio/AudioEngine.cpp @@ -1341,7 +1341,7 @@ AudioEngine::setCurrentTrackPlaylist( const playlistinterface_ptr& playlist ) void -AudioEngine::setDspCallback( void ( *cb ) ( signed short*, int, int ) ) +AudioEngine::setDspCallback( void ( *cb ) ( float*, int, int ) ) { Q_D( AudioEngine ); diff --git a/src/libtomahawk/audio/AudioEngine.h b/src/libtomahawk/audio/AudioEngine.h index eb3d0862f..f00ea04a7 100644 --- a/src/libtomahawk/audio/AudioEngine.h +++ b/src/libtomahawk/audio/AudioEngine.h @@ -109,7 +109,7 @@ public: */ qint64 currentTrackTotalTime() const; - void setDspCallback( void ( *cb ) ( signed short* samples, int nb_channels, int nb_samples ) ); + void setDspCallback( void ( *cb ) ( float* samples, int nb_channels, int nb_samples ) ); public slots: void playPause(); diff --git a/src/libtomahawk/audio/AudioOutput.cpp b/src/libtomahawk/audio/AudioOutput.cpp index f41cd6ce4..e893524d5 100644 --- a/src/libtomahawk/audio/AudioOutput.cpp +++ b/src/libtomahawk/audio/AudioOutput.cpp @@ -20,6 +20,7 @@ #include "AudioEngine.h" #include "AudioOutput.h" +#include "VlcDspHack.h" #include "utils/Logger.h" @@ -85,10 +86,11 @@ AudioOutput::AudioOutput( QObject* parent ) args << "--no-snapshot-preview"; args << "--no-xlib"; args << "--services-discovery=''"; -// args << "--no-one-instance"; args << "--no-video"; -// args << "--audio-filter=dsp"; -// args << QString("--dsp-callback=%1").arg((quint64)&AudioOutput::s_dspCallback, 0, 16).toAscii(); +#ifdef VLC_DSP_PLUGIN_ENABLED + args << "--audio-filter=dsp"; + args << QString("--dsp-callback=%1").arg((quint64)&AudioOutput::s_dspCallback, 0, 16).toAscii(); +#endif QVarLengthArray< const char * , 64 > vlcArgs( args.size() ); for ( int i = 0 ; i < args.size() ; ++i ) { @@ -138,6 +140,8 @@ AudioOutput::AudioOutput( QObject* parent ) AudioOutput::~AudioOutput() { tDebug() << Q_FUNC_INFO; + + // TODO } @@ -218,6 +222,10 @@ AudioOutput::setCurrentSource(MediaStream* stream) libvlc_media_player_set_media( vlcPlayer, vlcMedia ); +#ifdef VLC_DSP_PLUGIN_ENABLED + // This is very, very tricky + VlcDspHackInstall( vlcPlayer ); +#endif if ( stream->type() == MediaStream::Url ) { m_totalTime = libvlc_media_get_duration( vlcMedia ); @@ -479,9 +487,9 @@ AudioOutput::vlcEventCallback( const libvlc_event_t* event, void* opaque ) void -AudioOutput::s_dspCallback( signed short* samples, int nb_channels, int nb_samples ) +AudioOutput::s_dspCallback( float* samples, int nb_channels, int nb_samples ) { - tDebug() << Q_FUNC_INFO; +// tDebug() << Q_FUNC_INFO; if ( AudioOutput::instance()->dspPluginCallback ) { AudioOutput::instance()->dspPluginCallback( samples, nb_channels, nb_samples ); @@ -490,7 +498,7 @@ AudioOutput::s_dspCallback( signed short* samples, int nb_channels, int nb_sampl void -AudioOutput::setDspCallback( void ( *cb ) ( signed short*, int, int ) ) +AudioOutput::setDspCallback( void ( *cb ) ( float*, int, int ) ) { dspPluginCallback = cb; } diff --git a/src/libtomahawk/audio/AudioOutput.h b/src/libtomahawk/audio/AudioOutput.h index 0a0ff7e3c..3d2388031 100644 --- a/src/libtomahawk/audio/AudioOutput.h +++ b/src/libtomahawk/audio/AudioOutput.h @@ -61,7 +61,7 @@ public: qint64 totalTime(); void setAutoDelete ( bool ad ); - void setDspCallback( void ( *cb ) ( signed short*, int, int ) ); + void setDspCallback( void ( *cb ) ( float*, int, int ) ); static AudioOutput* instance(); @@ -78,7 +78,7 @@ private: void setTotalTime( qint64 time ); static void vlcEventCallback( const libvlc_event_t *event, void *opaque ); - static void s_dspCallback( signed short* samples, int nb_channels, int nb_samples ); + static void s_dspCallback( float* samples, int nb_channels, int nb_samples ); static AudioOutput* s_instance; AudioState currentState; @@ -91,7 +91,7 @@ private: qint64 m_totalTime; bool m_aboutToFinish; - void ( *dspPluginCallback ) ( signed short* samples, int nb_channels, int nb_samples ); + void ( *dspPluginCallback ) ( float* samples, int nb_channels, int nb_samples ); libvlc_instance_t* vlcInstance; libvlc_media_player_t* vlcPlayer; diff --git a/src/libtomahawk/audio/VlcDspHack.cpp b/src/libtomahawk/audio/VlcDspHack.cpp new file mode 100644 index 000000000..56f2952b8 --- /dev/null +++ b/src/libtomahawk/audio/VlcDspHack.cpp @@ -0,0 +1,24 @@ +#include "VlcDspHack_p.h" + +#ifdef VLC_DSP_PLUGIN_ENABLED + +void +VlcDspHackInstall( libvlc_media_player_t* vlcPlayer ) +{ + if ( vlcPlayer->input.p_resource != 0 ) { + audio_output_t *aout = input_resource_GetAout( vlcPlayer->input.p_resource ); + if ( aout != 0 ) { + var_Create( (vlc_object_t*)aout, "audio-filter", 0x0040 /*VLC_VAR_STRING*/ ); + + vlc_value_t val; + val.psz_string = (char*)"dsp"; + var_SetChecked( (vlc_object_t*)aout, "audio-filter", 0x0040 /*VLC_VAR_STRING*/, val ); + + aout->event.restart_request( aout, 1 /*AOUT_RESTART_FILTERS*/ ); + + input_resource_PutAout( vlcPlayer->input.p_resource, aout ); + } + } +} + +#endif // VLC_DSP_PLUGIN_ENABLED diff --git a/src/libtomahawk/audio/VlcDspHack.h b/src/libtomahawk/audio/VlcDspHack.h new file mode 100644 index 000000000..1c8a05cc2 --- /dev/null +++ b/src/libtomahawk/audio/VlcDspHack.h @@ -0,0 +1,28 @@ +#ifndef VLCDSPHACK_H +#define VLCDSPHACK_H + +/* + * Very tricky technique to enable DSP plugin support + * There is no other way to do this with libvlc for the moment + * + * A VLC audio filter plugin specificaly made for Tomahawk + * is necessary to get it functionning + * + * TODO : Check thoroughly if both libvlc_media_player_t and audio_output + * structures are identical to those in the running libvlccore.so + * (checking if libVLC version is >= than the one used to compile Tomahawk + * and verifying pointers integrity should be enough. + * + check if audio filter "dsp" is present in libVLC plugins list) +*/ + +//#define VLC_DSP_PLUGIN_ENABLED + +#ifdef VLC_DSP_PLUGIN_ENABLED + +struct libvlc_media_player_t; + +void VlcDspHackInstall( libvlc_media_player_t* vlcPlayer ); + +#endif // VLC_DSP_PLUGIN_ENABLED + +#endif // VLCDSPHACK_H \ No newline at end of file diff --git a/src/libtomahawk/audio/VlcDspHack_p.h b/src/libtomahawk/audio/VlcDspHack_p.h new file mode 100644 index 000000000..0a54f152d --- /dev/null +++ b/src/libtomahawk/audio/VlcDspHack_p.h @@ -0,0 +1,107 @@ +#ifndef VLCDSPHACK_P_H +#define VLCDSPHACK_P_H + +#include "VlcDspHack.h" + +#ifdef VLC_DSP_PLUGIN_ENABLED + +#include + +#include +#include +#include +#include +#include + +// TODO : Replace all these copy-pasted strutures by vlc/plugins/?.h includes + +typedef struct audio_output audio_output_t; +typedef struct input_resource_t input_resource_t; +typedef struct vlc_object_t vlc_object_t; +typedef struct vlc_list_t vlc_list_t; +typedef int64_t mtime_t; +typedef pthread_mutex_t vlc_mutex_t; + +typedef union +{ + int64_t i_int; + bool b_bool; + float f_float; + char * psz_string; + void * p_address; + vlc_object_t * p_object; + vlc_list_t * p_list; + mtime_t i_time; + struct { int32_t x; int32_t y; } coords; + +} vlc_value_t; + +struct audio_output +{ + const char *psz_object_type; + char *psz_header; + int i_flags; + bool b_force; + void *p_libvlc; + void * p_parent; + + void *sys; + int (*start)(audio_output_t *, void *fmt); + void (*stop)(audio_output_t *); + int (*time_get)(audio_output_t *, void *delay); + void (*play)(audio_output_t *, void *); + void (*pause)( audio_output_t *, bool pause, mtime_t date); + void (*flush)( audio_output_t *, bool wait); + int (*volume_set)(audio_output_t *, float volume); + int (*mute_set)(audio_output_t *, bool mute); + int (*device_select)(audio_output_t *, const char *id); + struct { + void (*volume_report)(audio_output_t *, float); + void (*mute_report)(audio_output_t *, bool); + void (*policy_report)(audio_output_t *, bool); + void (*device_report)(audio_output_t *, const char *); + void (*hotplug_report)(audio_output_t *, const char *, const char *); + int (*gain_request)(audio_output_t *, float); + void (*restart_request)(audio_output_t *, unsigned); + } event; +}; + + +struct libvlc_media_player_t +{ + const char *psz_object_type; + char *psz_header; + int i_flags; + bool b_force; + void *p_libvlc; + void *p_parent; + + int i_refcount; + vlc_mutex_t object_lock; + + struct + { + void *p_thread; + input_resource_t *p_resource; + vlc_mutex_t lock; + } input; + + void *p_libvlc_instance; + void *p_md; + void *p_event_manager; + int state; +}; + +extern "C" { + audio_output_t* input_resource_GetAout(input_resource_t*); + void input_resource_PutAout(input_resource_t*, audio_output_t*); + int var_Create(vlc_object_t *, const char *, int ); + int var_SetChecked( vlc_object_t *, const char *, int, vlc_value_t ); + static inline void aout_RestartRequest(audio_output_t *aout, unsigned mode){ + aout->event.restart_request(aout, mode); + } +}; + +#endif // VLC_DSP_PLUGIN_ENABLED + +#endif // VLCDSPHACK_P_H