mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-01-17 22:38:33 +01:00
first draft to get rid of phonon and directly use LibVLC
This commit is contained in:
parent
9bb7a06256
commit
f25a3715da
@ -346,6 +346,9 @@ endif()
|
|||||||
macro_log_feature(LIBSNORE_FOUND "Libsnore" "Library for notifications" "https://github.com/TheOneRing/Snorenotify" FALSE "" "")
|
macro_log_feature(LIBSNORE_FOUND "Libsnore" "Library for notifications" "https://github.com/TheOneRing/Snorenotify" FALSE "" "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_package(LIBVLC REQUIRED)
|
||||||
|
macro_log_feature(LIBVLC_FOUND "LibVLC" "Provides audio output" TRUE "" "")
|
||||||
|
|
||||||
set(QXTWEB_FOUND TRUE)
|
set(QXTWEB_FOUND TRUE)
|
||||||
set(QXTWEB_LIBRARIES qxtweb-standalone)
|
set(QXTWEB_LIBRARIES qxtweb-standalone)
|
||||||
set(QXTWEB_INCLUDE_DIRS ${THIRDPARTY_DIR}/qxt/qxtweb-standalone/web ${THIRDPARTY_DIR}/qxt/qxtweb-standalone/network ${THIRDPARTY_DIR}/qxt/qxtweb-standalone/core ${CMAKE_CURRENT_BINARY_DIR})
|
set(QXTWEB_INCLUDE_DIRS ${THIRDPARTY_DIR}/qxt/qxtweb-standalone/web ${THIRDPARTY_DIR}/qxt/qxtweb-standalone/network ${THIRDPARTY_DIR}/qxt/qxtweb-standalone/core ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
@ -377,15 +380,15 @@ if (WITH_KDE4)
|
|||||||
endif(WITH_KDE4)
|
endif(WITH_KDE4)
|
||||||
macro_log_feature(KDE4_FOUND "KDE4" "Provides support for configuring Telepathy Accounts from inside Tomahawk" "https://www.kde.org" FALSE "" "")
|
macro_log_feature(KDE4_FOUND "KDE4" "Provides support for configuring Telepathy Accounts from inside Tomahawk" "https://www.kde.org" FALSE "" "")
|
||||||
|
|
||||||
if(NOT Phonon_FOUND)
|
# if(NOT Phonon_FOUND)
|
||||||
macro_optional_find_package(Phonon 4.5.0)
|
# macro_optional_find_package(Phonon 4.5.0)
|
||||||
endif()
|
# endif()
|
||||||
macro_log_feature(Phonon_FOUND "Phonon" "The Phonon multimedia library" "http://phonon.kde.org" TRUE "" "")
|
# macro_log_feature(Phonon_FOUND "Phonon" "The Phonon multimedia library" "http://phonon.kde.org" TRUE "" "")
|
||||||
|
|
||||||
if(Phonon_FOUND)
|
|
||||||
message(STATUS "Phonon found; ensure that phonon-vlc is at least 0.4")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
# if(Phonon_FOUND)
|
||||||
|
# message(STATUS "Phonon found; ensure that phonon-vlc is at least 0.4")
|
||||||
|
# endif()
|
||||||
|
#
|
||||||
IF( KDE4_FOUND OR Phonon_FOUND )
|
IF( KDE4_FOUND OR Phonon_FOUND )
|
||||||
IF( CMAKE_C_FLAGS )
|
IF( CMAKE_C_FLAGS )
|
||||||
# KDE4 adds and removes some compiler flags that we don't like
|
# KDE4 adds and removes some compiler flags that we don't like
|
||||||
|
93
CMakeModules/FindLIBVLC.cmake
Normal file
93
CMakeModules/FindLIBVLC.cmake
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
|
||||||
|
# CMake module to search for LIBVLC (VLC library)
|
||||||
|
# Authors: Rohit Yadav <rohityadav89@gmail.com>
|
||||||
|
# Harald Sitter <apachelogger@ubuntu.com>
|
||||||
|
#
|
||||||
|
# If it's found it sets LIBVLC_FOUND to TRUE
|
||||||
|
# and following variables are set:
|
||||||
|
# LIBVLC_INCLUDE_DIR
|
||||||
|
# LIBVLC_LIBRARY
|
||||||
|
# LIBVLC_VERSION
|
||||||
|
|
||||||
|
if(NOT LIBVLC_MIN_VERSION)
|
||||||
|
set(LIBVLC_MIN_VERSION "0.0")
|
||||||
|
endif(NOT LIBVLC_MIN_VERSION)
|
||||||
|
|
||||||
|
# find_path and find_library normally search standard locations
|
||||||
|
# before the specified paths. To search non-standard paths first,
|
||||||
|
# FIND_* is invoked first with specified paths and NO_DEFAULT_PATH
|
||||||
|
# and then again with no specified paths to search the default
|
||||||
|
# locations. When an earlier FIND_* succeeds, subsequent FIND_*s
|
||||||
|
# searching for the same item do nothing.
|
||||||
|
|
||||||
|
if (NOT WIN32)
|
||||||
|
find_package(PkgConfig)
|
||||||
|
pkg_check_modules(PC_LIBVLC libvlc)
|
||||||
|
set(LIBVLC_DEFINITIONS ${PC_LIBVLC_CFLAGS_OTHER})
|
||||||
|
endif (NOT WIN32)
|
||||||
|
|
||||||
|
#Put here path to custom location
|
||||||
|
#example: /home/user/vlc/include etc..
|
||||||
|
find_path(LIBVLC_INCLUDE_DIR vlc/vlc.h
|
||||||
|
HINTS "$ENV{LIBVLC_INCLUDE_PATH}"
|
||||||
|
PATHS
|
||||||
|
"$ENV{LIB_DIR}/include"
|
||||||
|
"$ENV{LIB_DIR}/include/vlc"
|
||||||
|
"/usr/include"
|
||||||
|
"/usr/include/vlc"
|
||||||
|
"/usr/local/include"
|
||||||
|
"/usr/local/include/vlc"
|
||||||
|
#mingw
|
||||||
|
c:/msys/local/include
|
||||||
|
)
|
||||||
|
find_path(LIBVLC_INCLUDE_DIR PATHS "${CMAKE_INCLUDE_PATH}/vlc" NAMES vlc.h
|
||||||
|
HINTS ${PC_LIBVLC_INCLUDEDIR} ${PC_LIBVLC_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
#Put here path to custom location
|
||||||
|
#example: /home/user/vlc/lib etc..
|
||||||
|
find_library(LIBVLC_LIBRARY NAMES vlc libvlc
|
||||||
|
HINTS "$ENV{LIBVLC_LIBRARY_PATH}" ${PC_LIBVLC_LIBDIR} ${PC_LIBVLC_LIBRARY_DIRS}
|
||||||
|
PATHS
|
||||||
|
"$ENV{LIB_DIR}/lib"
|
||||||
|
#mingw
|
||||||
|
c:/msys/local/lib
|
||||||
|
)
|
||||||
|
find_library(LIBVLC_LIBRARY NAMES vlc libvlc)
|
||||||
|
find_library(LIBVLCCORE_LIBRARY NAMES vlccore libvlccore
|
||||||
|
HINTS "$ENV{LIBVLC_LIBRARY_PATH}" ${PC_LIBVLC_LIBDIR} ${PC_LIBVLC_LIBRARY_DIRS}
|
||||||
|
PATHS
|
||||||
|
"$ENV{LIB_DIR}/lib"
|
||||||
|
#mingw
|
||||||
|
c:/msys/local/lib
|
||||||
|
)
|
||||||
|
find_library(LIBVLCCORE_LIBRARY NAMES vlccore libvlccore)
|
||||||
|
|
||||||
|
set(LIBVLC_VERSION ${PC_LIBVLC_VERSION})
|
||||||
|
if (NOT LIBVLC_VERSION)
|
||||||
|
# TODO: implement means to detect version on windows (vlc --version && regex? ... ultimately we would get it from a header though...)
|
||||||
|
endif (NOT LIBVLC_VERSION)
|
||||||
|
|
||||||
|
if (LIBVLC_INCLUDE_DIR AND LIBVLC_LIBRARY AND LIBVLCCORE_LIBRARY)
|
||||||
|
set(LIBVLC_FOUND TRUE)
|
||||||
|
endif (LIBVLC_INCLUDE_DIR AND LIBVLC_LIBRARY AND LIBVLCCORE_LIBRARY)
|
||||||
|
|
||||||
|
if (LIBVLC_VERSION STRLESS "${LIBVLC_MIN_VERSION}")
|
||||||
|
message(WARNING "LibVLC version not found: version searched: ${LIBVLC_MIN_VERSION}, found ${LIBVLC_VERSION}\nUnless you are on Windows this is bound to fail.")
|
||||||
|
# TODO: only activate once version detection can be garunteed (which is currently not the case on windows)
|
||||||
|
# set(LIBVLC_FOUND FALSE)
|
||||||
|
endif (LIBVLC_VERSION STRLESS "${LIBVLC_MIN_VERSION}")
|
||||||
|
|
||||||
|
if (LIBVLC_FOUND)
|
||||||
|
if (NOT LIBVLC_FIND_QUIETLY)
|
||||||
|
message(STATUS "Found LibVLC include-dir path: ${LIBVLC_INCLUDE_DIR}")
|
||||||
|
message(STATUS "Found LibVLC library path:${LIBVLC_LIBRARY}")
|
||||||
|
message(STATUS "Found LibVLCcore library path:${LIBVLCCORE_LIBRARY}")
|
||||||
|
message(STATUS "Found LibVLC version: ${LIBVLC_VERSION} (searched for: ${LIBVLC_MIN_VERSION})")
|
||||||
|
endif (NOT LIBVLC_FIND_QUIETLY)
|
||||||
|
else (LIBVLC_FOUND)
|
||||||
|
if (LIBVLC_FIND_REQUIRED)
|
||||||
|
message(FATAL_ERROR "Could not find LibVLC")
|
||||||
|
endif (LIBVLC_FIND_REQUIRED)
|
||||||
|
endif (LIBVLC_FOUND)
|
||||||
|
|
||||||
|
|
@ -214,6 +214,7 @@ list(APPEND libSources
|
|||||||
accounts/spotify/SpotifyInfoPlugin.cpp
|
accounts/spotify/SpotifyInfoPlugin.cpp
|
||||||
|
|
||||||
audio/AudioEngine.cpp
|
audio/AudioEngine.cpp
|
||||||
|
audio/AudioOutput.cpp
|
||||||
|
|
||||||
collection/Collection.cpp
|
collection/Collection.cpp
|
||||||
collection/ArtistsRequest.cpp
|
collection/ArtistsRequest.cpp
|
||||||
@ -353,6 +354,7 @@ list(APPEND libSources
|
|||||||
utils/WeakObjectHash.cpp
|
utils/WeakObjectHash.cpp
|
||||||
utils/WeakObjectList.cpp
|
utils/WeakObjectList.cpp
|
||||||
utils/PluginLoader.cpp
|
utils/PluginLoader.cpp
|
||||||
|
utils/MediaStream.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory( accounts/configstorage )
|
add_subdirectory( accounts/configstorage )
|
||||||
@ -390,6 +392,7 @@ include_directories(
|
|||||||
${ECHONEST_INCLUDE_DIR}
|
${ECHONEST_INCLUDE_DIR}
|
||||||
${LUCENEPP_INCLUDE_DIRS}
|
${LUCENEPP_INCLUDE_DIRS}
|
||||||
${PHONON_INCLUDES}
|
${PHONON_INCLUDES}
|
||||||
|
${LIBVLC_INCLUDES}
|
||||||
${Boost_INCLUDE_DIR}
|
${Boost_INCLUDE_DIR}
|
||||||
|
|
||||||
${LIBPORTFWD_INCLUDE_DIR}
|
${LIBPORTFWD_INCLUDE_DIR}
|
||||||
@ -502,6 +505,7 @@ ENDIF( UNIX AND NOT APPLE )
|
|||||||
TARGET_LINK_LIBRARIES( tomahawklib
|
TARGET_LINK_LIBRARIES( tomahawklib
|
||||||
LINK_PRIVATE
|
LINK_PRIVATE
|
||||||
${PHONON_LIBRARY}
|
${PHONON_LIBRARY}
|
||||||
|
${LIBVLC_LIBRARY}
|
||||||
|
|
||||||
# Thirdparty shipped with tomahawk
|
# Thirdparty shipped with tomahawk
|
||||||
${LIBPORTFWD_LIBRARIES}
|
${LIBPORTFWD_LIBRARIES}
|
||||||
|
@ -53,16 +53,16 @@ static QString s_aeInfoIdentifier = QString( "AUDIOENGINE" );
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioEnginePrivate::onStateChanged( Phonon::State newState, Phonon::State oldState )
|
AudioEnginePrivate::onStateChanged( AudioOutput::AudioState newState, AudioOutput::AudioState oldState )
|
||||||
{
|
{
|
||||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << oldState << newState << expectStop << q_ptr->state();
|
tDebug() << Q_FUNC_INFO << oldState << newState << expectStop << q_ptr->state();
|
||||||
|
|
||||||
if ( newState == Phonon::LoadingState )
|
if ( newState == AudioOutput::Loading )
|
||||||
{
|
{
|
||||||
// We don't emit this state to listeners - yet.
|
// We don't emit this state to listeners - yet.
|
||||||
state = AudioEngine::Loading;
|
state = AudioEngine::Loading;
|
||||||
}
|
}
|
||||||
if ( newState == Phonon::BufferingState )
|
if ( newState == AudioOutput::Buffering )
|
||||||
{
|
{
|
||||||
if ( underrunCount > UNDERRUNTHRESHOLD && !underrunNotified )
|
if ( underrunCount > UNDERRUNTHRESHOLD && !underrunNotified )
|
||||||
{
|
{
|
||||||
@ -72,16 +72,16 @@ AudioEnginePrivate::onStateChanged( Phonon::State newState, Phonon::State oldSta
|
|||||||
else
|
else
|
||||||
underrunCount++;
|
underrunCount++;
|
||||||
}
|
}
|
||||||
if ( newState == Phonon::ErrorState )
|
if ( newState == AudioOutput::Error )
|
||||||
{
|
{
|
||||||
q_ptr->stop( AudioEngine::UnknownError );
|
q_ptr->stop( AudioEngine::UnknownError );
|
||||||
|
|
||||||
tDebug() << "Phonon Error:" << mediaObject->errorString() << mediaObject->errorType();
|
//TODO tDebug() << "Phonon Error:" << audioOutput->errorString() << audioOutput->errorType();
|
||||||
|
|
||||||
emit q_ptr->error( AudioEngine::UnknownError );
|
emit q_ptr->error( AudioEngine::UnknownError );
|
||||||
q_ptr->setState( AudioEngine::Error );
|
q_ptr->setState( AudioEngine::Error );
|
||||||
}
|
}
|
||||||
if ( newState == Phonon::PlayingState )
|
if ( newState == AudioOutput::Playing )
|
||||||
{
|
{
|
||||||
bool emitSignal = false;
|
bool emitSignal = false;
|
||||||
if ( q_ptr->state() != AudioEngine::Paused && q_ptr->state() != AudioEngine::Playing )
|
if ( q_ptr->state() != AudioEngine::Paused && q_ptr->state() != AudioEngine::Playing )
|
||||||
@ -95,23 +95,23 @@ AudioEnginePrivate::onStateChanged( Phonon::State newState, Phonon::State oldSta
|
|||||||
if ( emitSignal )
|
if ( emitSignal )
|
||||||
emit q_ptr->started( currentTrack );
|
emit q_ptr->started( currentTrack );
|
||||||
}
|
}
|
||||||
if ( newState == Phonon::StoppedState && oldState == Phonon::PausedState )
|
if ( newState == AudioOutput::Stopped && oldState == AudioOutput::Paused )
|
||||||
{
|
{
|
||||||
// GStreamer backend hack: instead of going from PlayingState to StoppedState, it traverses PausedState
|
// GStreamer backend hack: instead of going from PlayingState to StoppedState, it traverses PausedState
|
||||||
q_ptr->setState( AudioEngine::Stopped );
|
q_ptr->setState( AudioEngine::Stopped );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( oldState == Phonon::PlayingState )
|
if ( oldState == AudioOutput::Playing )
|
||||||
{
|
{
|
||||||
bool stopped = false;
|
bool stopped = false;
|
||||||
switch ( newState )
|
switch ( newState )
|
||||||
{
|
{
|
||||||
case Phonon::PausedState:
|
case AudioOutput::Paused:
|
||||||
{
|
{
|
||||||
if ( mediaObject && currentTrack )
|
if ( audioOutput && currentTrack )
|
||||||
{
|
{/* TODO
|
||||||
qint64 duration = mediaObject->totalTime() > 0 ? mediaObject->totalTime() : currentTrack->track()->duration() * 1000;
|
qint64 duration = audioOutput->totalTime() > 0 ? audioOutput->totalTime() : currentTrack->track()->duration() * 1000;
|
||||||
stopped = ( duration - 1000 < mediaObject->currentTime() );
|
stopped = ( duration - 1000 < audioOutput->currentTime() ); */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
stopped = true;
|
stopped = true;
|
||||||
@ -121,7 +121,7 @@ AudioEnginePrivate::onStateChanged( Phonon::State newState, Phonon::State oldSta
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Phonon::StoppedState:
|
case AudioOutput::Stopped:
|
||||||
{
|
{
|
||||||
stopped = true;
|
stopped = true;
|
||||||
break;
|
break;
|
||||||
@ -158,40 +158,12 @@ AudioEnginePrivate::onStateChanged( Phonon::State newState, Phonon::State oldSta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void
|
void
|
||||||
AudioEnginePrivate::onAudioDataArrived( QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > data )
|
AudioEnginePrivate::onAudioDataArrived( QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > data )
|
||||||
{
|
{
|
||||||
QMap< AudioEngine::AudioChannel, QVector< qint16 > > result;
|
|
||||||
|
|
||||||
if( data.contains( Phonon::AudioDataOutput::LeftChannel ) )
|
|
||||||
{
|
|
||||||
result[ AudioEngine::LeftChannel ] = QVector< qint16 >( data[ Phonon::AudioDataOutput::LeftChannel ] );
|
|
||||||
}
|
|
||||||
if( data.contains( Phonon::AudioDataOutput::LeftSurroundChannel ) )
|
|
||||||
{
|
|
||||||
result[ AudioEngine::LeftChannel ] = QVector< qint16 >( data[ Phonon::AudioDataOutput::LeftSurroundChannel ] );
|
|
||||||
}
|
|
||||||
if( data.contains( Phonon::AudioDataOutput::RightChannel ) )
|
|
||||||
{
|
|
||||||
result[ AudioEngine::RightChannel ] = QVector< qint16 >( data[ Phonon::AudioDataOutput::RightChannel ] );
|
|
||||||
}
|
|
||||||
if( data.contains( Phonon::AudioDataOutput::RightSurroundChannel ) )
|
|
||||||
{
|
|
||||||
result[ AudioEngine::LeftChannel ] = QVector< qint16 >( data[ Phonon::AudioDataOutput::RightSurroundChannel ] );
|
|
||||||
}
|
|
||||||
if( data.contains( Phonon::AudioDataOutput::CenterChannel ) )
|
|
||||||
{
|
|
||||||
result[ AudioEngine::LeftChannel ] = QVector< qint16 >( data[ Phonon::AudioDataOutput::CenterChannel ] );
|
|
||||||
}
|
|
||||||
if( data.contains( Phonon::AudioDataOutput::SubwooferChannel ) )
|
|
||||||
{
|
|
||||||
result[ AudioEngine::LeftChannel ] = QVector< qint16 >( data[ Phonon::AudioDataOutput::SubwooferChannel ] );
|
|
||||||
}
|
|
||||||
|
|
||||||
s_instance->audioDataArrived( result );
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
AudioEngine* AudioEnginePrivate::s_instance = 0;
|
AudioEngine* AudioEnginePrivate::s_instance = 0;
|
||||||
|
|
||||||
@ -214,30 +186,16 @@ AudioEngine::AudioEngine()
|
|||||||
d->waitingOnNewTrack = false;
|
d->waitingOnNewTrack = false;
|
||||||
d->state = Stopped;
|
d->state = Stopped;
|
||||||
d->coverTempFile = 0;
|
d->coverTempFile = 0;
|
||||||
d->audioEffect = 0;
|
|
||||||
d->dspPluginCallback = 0;
|
|
||||||
|
|
||||||
d->s_instance = this;
|
d->s_instance = this;
|
||||||
tDebug() << "Init AudioEngine";
|
tDebug() << "Init AudioEngine";
|
||||||
|
|
||||||
|
d->audioOutput = new AudioOutput(this);
|
||||||
|
|
||||||
|
QObject::connect( d->audioOutput, SIGNAL( stateChanged( AudioOutput::AudioState, AudioOutput::AudioState ) ), d, SLOT( onStateChanged( AudioOutput::AudioState, AudioOutput::AudioState ) ) );
|
||||||
|
getchar();
|
||||||
qRegisterMetaType< AudioErrorCode >("AudioErrorCode");
|
qRegisterMetaType< AudioErrorCode >("AudioErrorCode");
|
||||||
qRegisterMetaType< AudioState >("AudioState");
|
qRegisterMetaType< AudioState >("AudioState");
|
||||||
|
|
||||||
d->mediaObject = new Phonon::MediaObject( this );
|
|
||||||
d->audioOutput = new Phonon::AudioOutput( Phonon::MusicCategory, this );
|
|
||||||
d->audioPath = Phonon::createPath( d->mediaObject, d->audioOutput );
|
|
||||||
|
|
||||||
d->mediaObject->setTickInterval( 150 );
|
|
||||||
connect( d->mediaObject, SIGNAL( stateChanged( Phonon::State, Phonon::State ) ), d_func(), SLOT( onStateChanged( Phonon::State, Phonon::State ) ) );
|
|
||||||
connect( d->mediaObject, SIGNAL( tick( qint64 ) ), SLOT( timerTriggered( qint64 ) ) );
|
|
||||||
connect( d->mediaObject, SIGNAL( aboutToFinish() ), SLOT( onAboutToFinish() ) );
|
|
||||||
connect( d->audioOutput, SIGNAL( volumeChanged( qreal ) ), SLOT( onVolumeChanged( qreal ) ) );
|
|
||||||
connect( d->audioOutput, SIGNAL( mutedChanged( bool ) ), SIGNAL( mutedChanged( bool ) ) );
|
|
||||||
|
|
||||||
onVolumeChanged( d->audioOutput->volume() );
|
|
||||||
setVolume( TomahawkSettings::instance()->volume() );
|
|
||||||
|
|
||||||
d->mediaObject->setCurrentSource(Phonon::MediaSource("PhononDSP::effectCallback=" + QString::number((qulonglong)&AudioEngine::dspCallback, 16)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -245,7 +203,6 @@ AudioEngine::~AudioEngine()
|
|||||||
{
|
{
|
||||||
tDebug() << Q_FUNC_INFO;
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
d_func()->mediaObject->stop();
|
|
||||||
TomahawkSettings::instance()->setVolume( volume() );
|
TomahawkSettings::instance()->setVolume( volume() );
|
||||||
|
|
||||||
|
|
||||||
@ -258,13 +215,11 @@ AudioEngine::supportedMimeTypes() const
|
|||||||
{
|
{
|
||||||
if ( d_func()->supportedMimeTypes.isEmpty() )
|
if ( d_func()->supportedMimeTypes.isEmpty() )
|
||||||
{
|
{
|
||||||
d_func()->supportedMimeTypes = Phonon::BackendCapabilities::availableMimeTypes();
|
d_func()->supportedMimeTypes << "audio/*";
|
||||||
d_func()->supportedMimeTypes << "audio/basic";
|
d_func()->supportedMimeTypes << "audio/basic";
|
||||||
|
|
||||||
return d_func()->supportedMimeTypes;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return d_func()->supportedMimeTypes;
|
return d_func()->supportedMimeTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -300,7 +255,7 @@ AudioEngine::play()
|
|||||||
|
|
||||||
if ( isPaused() )
|
if ( isPaused() )
|
||||||
{
|
{
|
||||||
d->mediaObject->play();
|
d->audioOutput->play();
|
||||||
emit resumed();
|
emit resumed();
|
||||||
|
|
||||||
sendNowPlayingNotification( Tomahawk::InfoSystem::InfoNowResumed );
|
sendNowPlayingNotification( Tomahawk::InfoSystem::InfoNowResumed );
|
||||||
@ -330,7 +285,7 @@ AudioEngine::pause()
|
|||||||
|
|
||||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO;
|
tDebug( LOGEXTRA ) << Q_FUNC_INFO;
|
||||||
|
|
||||||
d->mediaObject->pause();
|
d->audioOutput->pause();
|
||||||
emit paused();
|
emit paused();
|
||||||
|
|
||||||
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( Tomahawk::InfoSystem::InfoPushData( s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNowPaused, QVariant(), Tomahawk::InfoSystem::PushNoFlag ) );
|
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( Tomahawk::InfoSystem::InfoPushData( s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNowPaused, QVariant(), Tomahawk::InfoSystem::PushNoFlag ) );
|
||||||
@ -358,8 +313,8 @@ AudioEngine::stop( AudioErrorCode errorCode )
|
|||||||
else
|
else
|
||||||
setState( Error );
|
setState( Error );
|
||||||
|
|
||||||
if ( d->mediaObject->state() != Phonon::StoppedState )
|
if ( d->audioOutput->state() != AudioOutput::Stopped )
|
||||||
d->mediaObject->stop();
|
d->audioOutput->stop();
|
||||||
|
|
||||||
emit stopped();
|
emit stopped();
|
||||||
|
|
||||||
@ -382,11 +337,7 @@ bool AudioEngine::activateDataOutput()
|
|||||||
{
|
{
|
||||||
Q_D( AudioEngine );
|
Q_D( AudioEngine );
|
||||||
|
|
||||||
d->audioDataPath = Phonon::createPath( d->mediaObject, d->audioDataOutput );
|
return true;
|
||||||
connect( d->audioDataOutput, SIGNAL( dataReady( QMap< Phonon::AudioDataOutput::Channel, QVector< qint16 > > ) ),
|
|
||||||
d_func(), SLOT( onAudioDataArrived( QMap< Phonon::AudioDataOutput::Channel, QVector< qint16 > > ) ) );
|
|
||||||
|
|
||||||
return d->audioDataPath.isValid();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,15 +346,9 @@ bool AudioEngine::deactivateDataOutput()
|
|||||||
{
|
{
|
||||||
Q_D( AudioEngine );
|
Q_D( AudioEngine );
|
||||||
|
|
||||||
return d->audioDataPath.disconnect();
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioEngine::audioDataArrived( QMap< AudioEngine::AudioChannel, QVector< qint16 > >& data )
|
|
||||||
{
|
|
||||||
emit audioDataReady( data );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioEngine::previous()
|
AudioEngine::previous()
|
||||||
{
|
{
|
||||||
@ -490,16 +435,11 @@ bool
|
|||||||
AudioEngine::canSeek()
|
AudioEngine::canSeek()
|
||||||
{
|
{
|
||||||
Q_D( AudioEngine );
|
Q_D( AudioEngine );
|
||||||
|
/*
|
||||||
bool phononCanSeek = true;
|
|
||||||
/* TODO: When phonon properly reports this, re-enable it
|
|
||||||
if ( d->mediaObject && d->mediaObject->isValid() )
|
|
||||||
phononCanSeek = d->mediaObject->isSeekable();
|
|
||||||
*/
|
|
||||||
if ( d->playlist.isNull() )
|
if ( d->playlist.isNull() )
|
||||||
return phononCanSeek;
|
return true;
|
||||||
|
*/
|
||||||
return !d->playlist.isNull() && ( d->playlist.data()->seekRestrictions() != PlaylistModes::NoSeek ) && phononCanSeek;
|
return !d->playlist.isNull() && ( d->playlist.data()->seekRestrictions() != PlaylistModes::NoSeek );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -517,7 +457,7 @@ AudioEngine::seek( qint64 ms )
|
|||||||
if ( isPlaying() || isPaused() )
|
if ( isPlaying() || isPaused() )
|
||||||
{
|
{
|
||||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << ms;
|
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << ms;
|
||||||
d->mediaObject->seek( ms );
|
d->audioOutput->seek( ms );
|
||||||
emit seeked( ms );
|
emit seeked( ms );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -542,6 +482,7 @@ AudioEngine::setVolume( int percentage )
|
|||||||
|
|
||||||
if ( percentage > 0 && d->audioOutput->isMuted() )
|
if ( percentage > 0 && d->audioOutput->isMuted() )
|
||||||
d->audioOutput->setMuted( false );
|
d->audioOutput->setMuted( false );
|
||||||
|
|
||||||
emit volumeChanged( percentage );
|
emit volumeChanged( percentage );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -564,6 +505,7 @@ bool
|
|||||||
AudioEngine::isMuted() const
|
AudioEngine::isMuted() const
|
||||||
{
|
{
|
||||||
return d_func()->audioOutput->isMuted();
|
return d_func()->audioOutput->isMuted();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -766,18 +708,22 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString
|
|||||||
QSharedPointer<QNetworkReply> qnr = io.objectCast<QNetworkReply>();
|
QSharedPointer<QNetworkReply> qnr = io.objectCast<QNetworkReply>();
|
||||||
if ( !qnr.isNull() )
|
if ( !qnr.isNull() )
|
||||||
{
|
{
|
||||||
d->mediaObject->setCurrentSource( new QNR_IODeviceStream( qnr, this ) );
|
tLog() << "CASE 1";
|
||||||
|
d->audioOutput->setCurrentSource( new QNR_IODeviceStream( qnr, this ) );
|
||||||
// We keep track of the QNetworkReply in QNR_IODeviceStream
|
// We keep track of the QNetworkReply in QNR_IODeviceStream
|
||||||
// and Phonon handles the deletion of the
|
// and Phonon handles the deletion of the
|
||||||
// QNR_IODeviceStream object
|
// QNR_IODeviceStream object
|
||||||
ioToKeep.clear();
|
ioToKeep.clear();
|
||||||
d->mediaObject->currentSource().setAutoDelete( true );
|
// TODO d->audioOutput->setAutoDelete( true );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
d->mediaObject->setCurrentSource( io.data() );
|
tLog() << "CASE 2";
|
||||||
|
/* TODO
|
||||||
|
d->audioOutput->setCurrentSource( io.data() );
|
||||||
// We handle the deletion via tracking in d->input
|
// We handle the deletion via tracking in d->input
|
||||||
d->mediaObject->currentSource().setAutoDelete( false );
|
d->audioOutput->setAutoDelete( false );
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -788,6 +734,7 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString
|
|||||||
*/
|
*/
|
||||||
if ( !TomahawkUtils::isLocalResult( url ) )
|
if ( !TomahawkUtils::isLocalResult( url ) )
|
||||||
{
|
{
|
||||||
|
tLog() << "CASE 3";
|
||||||
QUrl furl = url;
|
QUrl furl = url;
|
||||||
if ( url.contains( "?" ) )
|
if ( url.contains( "?" ) )
|
||||||
{
|
{
|
||||||
@ -796,19 +743,22 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString
|
|||||||
}
|
}
|
||||||
|
|
||||||
tLog( LOGVERBOSE ) << "Passing to Phonon:" << furl;
|
tLog( LOGVERBOSE ) << "Passing to Phonon:" << furl;
|
||||||
d->mediaObject->setCurrentSource( furl );
|
d->audioOutput->setCurrentSource( furl );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
tLog() << "CASE 4";
|
||||||
QString furl = url;
|
QString furl = url;
|
||||||
if ( furl.startsWith( "file://" ) )
|
if ( furl.startsWith( "file://" ) )
|
||||||
furl = furl.right( furl.length() - 7 );
|
furl = furl.right( furl.length() - 7 );
|
||||||
|
|
||||||
tLog( LOGVERBOSE ) << "Passing to Phonon:" << QUrl::fromLocalFile( furl );
|
tLog( LOGVERBOSE ) << "Passing to Phonon:" << QUrl::fromLocalFile( furl );
|
||||||
d->mediaObject->setCurrentSource( QUrl::fromLocalFile( furl ) );
|
d->audioOutput->setCurrentSource( QUrl::fromLocalFile( furl ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
d->mediaObject->currentSource().setAutoDelete( true );
|
/* TODO
|
||||||
|
d->audioOutput->setAutoDelete( true );
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !d->input.isNull() )
|
if ( !d->input.isNull() )
|
||||||
@ -817,7 +767,7 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString
|
|||||||
d->input.clear();
|
d->input.clear();
|
||||||
}
|
}
|
||||||
d->input = ioToKeep;
|
d->input = ioToKeep;
|
||||||
d->mediaObject->play();
|
d->audioOutput->play();
|
||||||
|
|
||||||
if ( TomahawkSettings::instance()->privateListeningMode() != TomahawkSettings::FullyPrivate )
|
if ( TomahawkSettings::instance()->privateListeningMode() != TomahawkSettings::FullyPrivate )
|
||||||
{
|
{
|
||||||
@ -1290,14 +1240,16 @@ AudioEngine::setState( AudioState state )
|
|||||||
qint64
|
qint64
|
||||||
AudioEngine::currentTime() const
|
AudioEngine::currentTime() const
|
||||||
{
|
{
|
||||||
return d_func()->mediaObject->currentTime();
|
// TODO return d_func()->mediaObject->currentTime();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
qint64
|
qint64
|
||||||
AudioEngine::currentTrackTotalTime() const
|
AudioEngine::currentTrackTotalTime() const
|
||||||
{
|
{
|
||||||
return d_func()->mediaObject->totalTime();
|
// TODO return d_func()->mediaObject->totalTime();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1384,29 +1336,10 @@ AudioEngine::setCurrentTrackPlaylist( const playlistinterface_ptr& playlist )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
AudioEngine::dspCallback( signed short* samples, int nb_channels, int nb_samples )
|
|
||||||
{
|
|
||||||
AudioEngine::instance()->dspCallbackInternal( samples, nb_channels, nb_samples );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
AudioEngine::dspCallbackInternal( signed short* samples, int nb_channels, int nb_samples )
|
|
||||||
{
|
|
||||||
Q_D( AudioEngine );
|
|
||||||
|
|
||||||
if ( d->dspPluginCallback != 0 )
|
|
||||||
{
|
|
||||||
d->dspPluginCallback( samples, nb_channels, nb_samples );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioEngine::setDspCallback( void ( *cb ) ( signed short*, int, int ) )
|
AudioEngine::setDspCallback( void ( *cb ) ( signed short*, int, int ) )
|
||||||
{
|
{
|
||||||
Q_D( AudioEngine );
|
Q_D( AudioEngine );
|
||||||
|
|
||||||
d->dspPluginCallback = cb;
|
d->audioOutput->setDspCallback( cb );
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ signals:
|
|||||||
void paused();
|
void paused();
|
||||||
void resumed();
|
void resumed();
|
||||||
|
|
||||||
void audioDataReady( QMap< AudioEngine::AudioChannel, QVector<qint16> > data );
|
// void audioDataReady( QMap< AudioEngine::AudioChannel, QVector<qint16> > data );
|
||||||
|
|
||||||
void stopAfterTrackChanged();
|
void stopAfterTrackChanged();
|
||||||
|
|
||||||
@ -200,9 +200,7 @@ private:
|
|||||||
void setState( AudioState state );
|
void setState( AudioState state );
|
||||||
void setCurrentTrackPlaylist( const Tomahawk::playlistinterface_ptr& playlist );
|
void setCurrentTrackPlaylist( const Tomahawk::playlistinterface_ptr& playlist );
|
||||||
|
|
||||||
static void dspCallback( signed short* samples, int nb_channels, int nb_samples );
|
// void audioDataArrived( QMap< AudioEngine::AudioChannel, QVector< qint16 > >& data );
|
||||||
void dspCallbackInternal( signed short* samples, int nb_channels, int nb_samples );
|
|
||||||
void audioDataArrived( QMap< AudioEngine::AudioChannel, QVector< qint16 > >& data );
|
|
||||||
|
|
||||||
|
|
||||||
Q_DECLARE_PRIVATE( AudioEngine )
|
Q_DECLARE_PRIVATE( AudioEngine )
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
|
/*
|
||||||
#include <phonon/MediaObject>
|
#include <phonon/MediaObject>
|
||||||
#include <phonon/AudioOutput>
|
#include <phonon/AudioOutput>
|
||||||
#include <phonon/Path>
|
#include <phonon/Path>
|
||||||
#include <phonon/BackendCapabilities>
|
#include <phonon/BackendCapabilities>
|
||||||
#include <phonon/Effect>
|
#include <phonon/Effect>
|
||||||
#include <phonon/EffectParameter>
|
#include <phonon/EffectParameter>
|
||||||
|
*/
|
||||||
|
#include "AudioOutput.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@ -29,8 +31,8 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void onStateChanged( Phonon::State newState, Phonon::State oldState );
|
void onStateChanged( AudioOutput::AudioState newState, AudioOutput::AudioState oldState );
|
||||||
void onAudioDataArrived( QMap< Phonon::AudioDataOutput::Channel, QVector< qint16 > > data );
|
// void onAudioDataArrived( QMap< Phonon::AudioDataOutput::Channel, QVector< qint16 > > data );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSharedPointer<QIODevice> input;
|
QSharedPointer<QIODevice> input;
|
||||||
@ -41,6 +43,8 @@ private:
|
|||||||
Tomahawk::playlistinterface_ptr currentTrackPlaylist;
|
Tomahawk::playlistinterface_ptr currentTrackPlaylist;
|
||||||
Tomahawk::playlistinterface_ptr queue;
|
Tomahawk::playlistinterface_ptr queue;
|
||||||
|
|
||||||
|
AudioOutput* audioOutput;
|
||||||
|
/*
|
||||||
Phonon::MediaObject* mediaObject;
|
Phonon::MediaObject* mediaObject;
|
||||||
Phonon::AudioOutput* audioOutput;
|
Phonon::AudioOutput* audioOutput;
|
||||||
|
|
||||||
@ -49,7 +53,7 @@ private:
|
|||||||
|
|
||||||
Phonon::AudioDataOutput* audioDataOutput;
|
Phonon::AudioDataOutput* audioDataOutput;
|
||||||
Phonon::Path audioDataPath;
|
Phonon::Path audioDataPath;
|
||||||
|
*/
|
||||||
|
|
||||||
unsigned int timeElapsed;
|
unsigned int timeElapsed;
|
||||||
bool expectStop;
|
bool expectStop;
|
||||||
|
320
src/libtomahawk/audio/AudioOutput.cpp
Normal file
320
src/libtomahawk/audio/AudioOutput.cpp
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||||
|
*
|
||||||
|
* Copyright 2010-2014, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||||
|
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||||
|
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Tomahawk is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Tomahawk is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "AudioOutput.h"
|
||||||
|
|
||||||
|
#include "utils/Logger.h"
|
||||||
|
|
||||||
|
#include <QVarLengthArray>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
#include <boost/function.hpp>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
|
#include <vlc/libvlc.h>
|
||||||
|
#include <vlc/libvlc_media.h>
|
||||||
|
#include <vlc/libvlc_media_player.h>
|
||||||
|
#include <vlc/libvlc_version.h>
|
||||||
|
|
||||||
|
static QString s_aeInfoIdentifier = QString( "AUDIOOUTPUT" );
|
||||||
|
|
||||||
|
|
||||||
|
AudioOutput* AudioOutput::s_instance = 0;
|
||||||
|
|
||||||
|
|
||||||
|
AudioOutput*
|
||||||
|
AudioOutput::instance()
|
||||||
|
{
|
||||||
|
return AudioOutput::s_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AudioOutput::AudioOutput( QObject* parent )
|
||||||
|
: QObject( parent )
|
||||||
|
, dspPluginCallback( 0 )
|
||||||
|
, currentState( Stopped )
|
||||||
|
, muted( false )
|
||||||
|
, m_volume( 1.0 )
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
AudioOutput::s_instance = this;
|
||||||
|
currentStream = 0;
|
||||||
|
|
||||||
|
QList<QByteArray> args;
|
||||||
|
|
||||||
|
args << "--ignore-config";
|
||||||
|
args << "--verbose=11111";
|
||||||
|
args << "--no-plugins-cache";
|
||||||
|
args << "--extraintf=logger";
|
||||||
|
args << "--no-media-library";
|
||||||
|
args << "--no-osd";
|
||||||
|
args << "--no-stats";
|
||||||
|
args << "--no-video-title-show";
|
||||||
|
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();
|
||||||
|
|
||||||
|
QVarLengthArray< const char * , 64 > vlcArgs( args.size() );
|
||||||
|
for ( int i = 0 ; i < args.size() ; ++i ) {
|
||||||
|
vlcArgs[i] = args.at( i ).constData();
|
||||||
|
tDebug() << args.at( i );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and initialize a libvlc instance (it should be done only once)
|
||||||
|
if ( !( vlcInstance = libvlc_new( vlcArgs.size(), vlcArgs.constData() ) ) ) {
|
||||||
|
tDebug() << "libVLC: could not initialize";
|
||||||
|
}
|
||||||
|
vlcPlayer = libvlc_media_player_new( vlcInstance );
|
||||||
|
|
||||||
|
getchar();
|
||||||
|
tDebug() << "AudioOutput::AudioOutput OK !\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AudioOutput::~AudioOutput()
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioOutput::setCurrentSource(MediaStream stream)
|
||||||
|
{
|
||||||
|
setCurrentSource( new MediaStream(stream) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioOutput::setCurrentSource(MediaStream* stream)
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
currentStream = stream;
|
||||||
|
|
||||||
|
currentState = Loading;
|
||||||
|
|
||||||
|
QByteArray url;
|
||||||
|
switch (stream->type()) {
|
||||||
|
case MediaStream::Unknown:
|
||||||
|
tDebug() << "MediaStream Type is Invalid:" << stream->type();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MediaStream::Empty:
|
||||||
|
tDebug() << "MediaStream is empty.";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MediaStream::Url:
|
||||||
|
tDebug() << "MediaStream::Url:" << stream->url();
|
||||||
|
if (stream->url().scheme().isEmpty()) {
|
||||||
|
url = "file:///";
|
||||||
|
if (stream->url().isRelative())
|
||||||
|
url.append(QFile::encodeName(QDir::currentPath()) + '/');
|
||||||
|
}
|
||||||
|
url += stream->url().toEncoded();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MediaStream::Stream:
|
||||||
|
url = QByteArray("imem://");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
tDebug() << "MediaStream::Final Url:" << url;
|
||||||
|
|
||||||
|
vlcMedia = libvlc_media_new_location( vlcInstance, url.constData() );
|
||||||
|
|
||||||
|
libvlc_media_player_set_media( vlcPlayer, vlcMedia );
|
||||||
|
|
||||||
|
if ( stream->type() == MediaStream::Stream ) {
|
||||||
|
libvlc_media_add_option_flag(vlcMedia, "imem-cat=4", libvlc_media_option_trusted);
|
||||||
|
libvlc_media_add_option_flag(vlcMedia, (QString("imem-data=") + QString::number((quint64)stream)).toUtf8().data(), libvlc_media_option_trusted);
|
||||||
|
libvlc_media_add_option_flag(vlcMedia, (QString("imem-get=") + QString::number((quint64)&MediaStream::readCallback)).toUtf8().data(), libvlc_media_option_trusted);
|
||||||
|
libvlc_media_add_option_flag(vlcMedia, (QString("imem-release=") + QString::number((quint64)&MediaStream::readDoneCallback)).toUtf8().data(), libvlc_media_option_trusted);
|
||||||
|
libvlc_media_add_option_flag(vlcMedia, (QString("imem-seek=") + QString::number((quint64)&MediaStream::seekCallback)).toUtf8().data(), libvlc_media_option_trusted);
|
||||||
|
}
|
||||||
|
libvlc_media_add_option(vlcMedia, "audio-filter=dsp");
|
||||||
|
libvlc_media_add_option(vlcMedia, ":audio-filter=dsp");
|
||||||
|
libvlc_media_add_option(vlcMedia, "--audio-filter=dsp");
|
||||||
|
libvlc_media_add_option(vlcMedia, "audio-filter dsp");
|
||||||
|
libvlc_media_add_option(vlcMedia, ":audio-filter dsp");
|
||||||
|
libvlc_media_add_option(vlcMedia, "--audio-filter dsp");
|
||||||
|
|
||||||
|
currentState = Stopped;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
AudioOutput::AudioState
|
||||||
|
AudioOutput::state()
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
return currentState;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioOutput::setState( AudioState state )
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
emit stateChanged ( state, currentState );
|
||||||
|
currentState = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioOutput::play()
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
if ( libvlc_media_player_is_playing ( vlcPlayer ) ) {
|
||||||
|
libvlc_media_player_set_pause ( vlcPlayer, 0 );
|
||||||
|
} else {
|
||||||
|
libvlc_media_player_play ( vlcPlayer );
|
||||||
|
}
|
||||||
|
|
||||||
|
setState( Playing );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioOutput::pause()
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
// libvlc_media_player_pause( vlcPlayer );
|
||||||
|
libvlc_media_player_set_pause ( vlcPlayer, 1 );
|
||||||
|
|
||||||
|
setState( Paused );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioOutput::stop()
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
libvlc_media_player_stop ( vlcPlayer );
|
||||||
|
|
||||||
|
setState( Stopped );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioOutput::seek( qint64 milliseconds )
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
switch ( currentState ) {
|
||||||
|
case Playing:
|
||||||
|
case Paused:
|
||||||
|
case Loading:
|
||||||
|
case Buffering:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Seeking while not being in a playingish state is cached for later.
|
||||||
|
// TODO m_seekpoint = milliseconds;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tDebug() << "AudioOutput:: seeking" << milliseconds << "msec";
|
||||||
|
|
||||||
|
libvlc_media_player_set_time ( vlcPlayer, milliseconds );
|
||||||
|
/*
|
||||||
|
const qint64 time = currentTime();
|
||||||
|
const qint64 total = totalTime();
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
// Reset last tick marker so we emit time even after seeking
|
||||||
|
if (time < m_lastTick)
|
||||||
|
m_lastTick = time;
|
||||||
|
if (time < total - m_prefinishMark)
|
||||||
|
m_prefinishEmitted = false;
|
||||||
|
if (time < total - ABOUT_TO_FINISH_TIME)
|
||||||
|
m_aboutToFinishEmitted = false;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
AudioOutput::isMuted()
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
return muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioOutput::setMuted(bool m)
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
muted = m;
|
||||||
|
if ( muted == true ) {
|
||||||
|
libvlc_audio_set_volume( vlcPlayer, 0 );
|
||||||
|
} else {
|
||||||
|
libvlc_audio_set_volume( vlcPlayer, m_volume * 100.0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
qreal
|
||||||
|
AudioOutput::volume()
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
return muted ? 0 : m_volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioOutput::setVolume(qreal vol)
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
m_volume = vol;
|
||||||
|
if ( !muted ) {
|
||||||
|
libvlc_audio_set_volume( vlcPlayer, m_volume * 100.0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioOutput::s_dspCallback( signed short* samples, int nb_channels, int nb_samples )
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
AudioOutput::instance()->dspCallback( samples, nb_channels, nb_samples );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioOutput::dspCallback( signed short* samples, int nb_channels, int nb_samples )
|
||||||
|
{
|
||||||
|
if ( dspPluginCallback != 0 )
|
||||||
|
{
|
||||||
|
dspPluginCallback( samples, nb_channels, nb_samples );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioOutput::setDspCallback( void ( *cb ) ( signed short*, int, int ) )
|
||||||
|
{
|
||||||
|
dspPluginCallback = cb;
|
||||||
|
}
|
87
src/libtomahawk/audio/AudioOutput.h
Normal file
87
src/libtomahawk/audio/AudioOutput.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||||
|
*
|
||||||
|
* Copyright 2010-2014, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||||
|
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||||
|
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Tomahawk is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Tomahawk is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AUDIOOUTPUT_H
|
||||||
|
#define AUDIOOUTPUT_H
|
||||||
|
|
||||||
|
#include "../Typedefs.h"
|
||||||
|
|
||||||
|
#include "DllMacro.h"
|
||||||
|
|
||||||
|
#include "utils/MediaStream.h"
|
||||||
|
|
||||||
|
struct libvlc_instance_t;
|
||||||
|
struct libvlc_media_player_t;
|
||||||
|
struct libvlc_media_t;
|
||||||
|
|
||||||
|
class DLLEXPORT AudioOutput : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum AudioState { Stopped = 0, Playing = 1, Paused = 2, Error = 3, Loading = 4, Buffering = 5 };
|
||||||
|
|
||||||
|
explicit AudioOutput(QObject* parent = 0);
|
||||||
|
~AudioOutput();
|
||||||
|
|
||||||
|
AudioState state();
|
||||||
|
|
||||||
|
void setCurrentSource(MediaStream stream);
|
||||||
|
void setCurrentSource(MediaStream* stream);
|
||||||
|
|
||||||
|
void play();
|
||||||
|
void pause();
|
||||||
|
void stop();
|
||||||
|
void seek(qint64 milliseconds);
|
||||||
|
|
||||||
|
bool isMuted();
|
||||||
|
void setMuted(bool m);
|
||||||
|
void setVolume(qreal vol);
|
||||||
|
qreal volume();
|
||||||
|
|
||||||
|
void setDspCallback( void ( *cb ) ( signed short*, int, int ) );
|
||||||
|
|
||||||
|
static AudioOutput* instance();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void stateChanged( AudioOutput::AudioState, AudioOutput::AudioState );
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setState( AudioState state );
|
||||||
|
|
||||||
|
static void s_dspCallback( signed short* samples, int nb_channels, int nb_samples );
|
||||||
|
void dspCallback( signed short* samples, int nb_channels, int nb_samples );
|
||||||
|
|
||||||
|
void ( *dspPluginCallback ) ( signed short* samples, int nb_channels, int nb_samples );
|
||||||
|
|
||||||
|
static AudioOutput* s_instance;
|
||||||
|
AudioState currentState;
|
||||||
|
MediaStream* currentStream;
|
||||||
|
bool muted;
|
||||||
|
qreal m_volume;
|
||||||
|
|
||||||
|
libvlc_instance_t* vlcInstance;
|
||||||
|
libvlc_media_player_t* vlcPlayer;
|
||||||
|
libvlc_media_t* vlcMedia;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // AUDIOOUTPUT_H
|
128
src/libtomahawk/utils/MediaStream.cpp
Normal file
128
src/libtomahawk/utils/MediaStream.cpp
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||||
|
*
|
||||||
|
* Copyright 2010-2014, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||||
|
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||||
|
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Tomahawk is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Tomahawk is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "MediaStream.h"
|
||||||
|
|
||||||
|
#include "utils/Logger.h"
|
||||||
|
|
||||||
|
|
||||||
|
static QString s_aeInfoIdentifier = QString( "MEDIASTREAM" );
|
||||||
|
|
||||||
|
|
||||||
|
MediaStream::MediaStream()
|
||||||
|
: m_type( Unknown )
|
||||||
|
, m_url( QUrl() )
|
||||||
|
, m_pos( 0 )
|
||||||
|
, m_streamSize( 0 )
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MediaStream::MediaStream( const QUrl &url )
|
||||||
|
: m_type(Url)
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
m_url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MediaStream::~MediaStream()
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MediaStream::MediaType
|
||||||
|
MediaStream::type()
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
return m_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QUrl
|
||||||
|
MediaStream::url()
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
return m_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
qint64
|
||||||
|
MediaStream::streamSize()
|
||||||
|
{
|
||||||
|
return m_streamSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaStream::setStreamSize( qint64 size )
|
||||||
|
{
|
||||||
|
m_streamSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
MediaStream::readCallback ( void* data, const char* cookie, int64_t* dts, int64_t* pts, unsigned* flags, size_t* bufferSize, void** buffer )
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
Q_UNUSED(cookie);
|
||||||
|
Q_UNUSED(dts);
|
||||||
|
Q_UNUSED(pts);
|
||||||
|
Q_UNUSED(flags);
|
||||||
|
|
||||||
|
MediaStream* that = static_cast < MediaStream * > ( data );
|
||||||
|
|
||||||
|
*bufferSize = that->needData(buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
MediaStream::readDoneCallback ( void *data, const char *cookie, size_t bufferSize, void *buffer )
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
Q_UNUSED(data);
|
||||||
|
Q_UNUSED(cookie);
|
||||||
|
Q_UNUSED(bufferSize);
|
||||||
|
delete static_cast<char *>(buffer);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
MediaStream::seekCallback ( void *data, const uint64_t pos )
|
||||||
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
MediaStream* that = static_cast < MediaStream * > ( data );
|
||||||
|
if ( static_cast < int64_t > ( pos ) > that->streamSize() ) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
that->m_pos = pos;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
63
src/libtomahawk/utils/MediaStream.h
Normal file
63
src/libtomahawk/utils/MediaStream.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||||
|
*
|
||||||
|
* Copyright 2010-2014, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||||
|
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||||
|
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
|
||||||
|
*
|
||||||
|
* Tomahawk is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Tomahawk is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MEDIASTREAM_H
|
||||||
|
#define MEDIASTREAM_H
|
||||||
|
|
||||||
|
#include "../Typedefs.h"
|
||||||
|
|
||||||
|
#include "DllMacro.h"
|
||||||
|
#include "utils/Logger.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
class DLLEXPORT MediaStream
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum MediaType { Unknown = -1, Empty = 0, Url = 1, Stream = 2 };
|
||||||
|
|
||||||
|
MediaStream();
|
||||||
|
MediaStream( const QUrl &url );
|
||||||
|
virtual ~MediaStream();
|
||||||
|
|
||||||
|
MediaType type();
|
||||||
|
QUrl url();
|
||||||
|
|
||||||
|
void setStreamSize( qint64 size );
|
||||||
|
qint64 streamSize();
|
||||||
|
|
||||||
|
virtual void seekStream( qint64 offset ) { (void)offset; }
|
||||||
|
virtual size_t needData ( void** buffer ) { (void)buffer; tDebug() << Q_FUNC_INFO; return 0; }
|
||||||
|
|
||||||
|
static int readCallback ( void* data, const char* cookie, int64_t* dts, int64_t* pts, unsigned* flags, size_t* bufferSize, void** buffer );
|
||||||
|
static int readDoneCallback ( void *data, const char *cookie, size_t bufferSize, void *buffer );
|
||||||
|
static int seekCallback ( void *data, const uint64_t pos );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MediaType m_type;
|
||||||
|
QUrl m_url;
|
||||||
|
|
||||||
|
qint64 m_pos;
|
||||||
|
qint64 m_streamSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MEDIASTREAM_H
|
@ -33,11 +33,15 @@ using namespace Tomahawk;
|
|||||||
#define BLOCK_SIZE 1048576
|
#define BLOCK_SIZE 1048576
|
||||||
|
|
||||||
QNR_IODeviceStream::QNR_IODeviceStream( const QSharedPointer<QNetworkReply>& reply, QObject* parent )
|
QNR_IODeviceStream::QNR_IODeviceStream( const QSharedPointer<QNetworkReply>& reply, QObject* parent )
|
||||||
: Phonon::AbstractMediaStream( parent )
|
: QObject( parent )
|
||||||
|
, MediaStream()
|
||||||
, m_networkReply( reply )
|
, m_networkReply( reply )
|
||||||
, m_pos( 0 )
|
|
||||||
, m_timer( new QTimer( this ) )
|
, m_timer( new QTimer( this ) )
|
||||||
{
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
m_type = MediaStream::Stream;
|
||||||
|
|
||||||
if ( !m_networkReply->isOpen() ) {
|
if ( !m_networkReply->isOpen() ) {
|
||||||
m_networkReply->open(QIODevice::ReadOnly);
|
m_networkReply->open(QIODevice::ReadOnly);
|
||||||
}
|
}
|
||||||
@ -50,7 +54,7 @@ QNR_IODeviceStream::QNR_IODeviceStream( const QSharedPointer<QNetworkReply>& rep
|
|||||||
// All data is ready, read it!
|
// All data is ready, read it!
|
||||||
m_data = m_networkReply->readAll();
|
m_data = m_networkReply->readAll();
|
||||||
Q_ASSERT( m_networkReply->atEnd() );
|
Q_ASSERT( m_networkReply->atEnd() );
|
||||||
setStreamSeekable( true );
|
//TODO setStreamSeekable( true );
|
||||||
setStreamSize( m_data.size() );
|
setStreamSize( m_data.size() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -59,7 +63,7 @@ QNR_IODeviceStream::QNR_IODeviceStream( const QSharedPointer<QNetworkReply>& rep
|
|||||||
QVariant contentLength = m_networkReply->header( QNetworkRequest::ContentLengthHeader );
|
QVariant contentLength = m_networkReply->header( QNetworkRequest::ContentLengthHeader );
|
||||||
if ( contentLength.isValid() && contentLength.toLongLong() > 0 )
|
if ( contentLength.isValid() && contentLength.toLongLong() > 0 )
|
||||||
{
|
{
|
||||||
setStreamSize( contentLength.toLongLong() );
|
//TODO setStreamSize( contentLength.toLongLong() );
|
||||||
}
|
}
|
||||||
// Just consume all data that is already available.
|
// Just consume all data that is already available.
|
||||||
m_data = m_networkReply->readAll();
|
m_data = m_networkReply->readAll();
|
||||||
@ -73,53 +77,38 @@ QNR_IODeviceStream::QNR_IODeviceStream( const QSharedPointer<QNetworkReply>& rep
|
|||||||
|
|
||||||
QNR_IODeviceStream::~QNR_IODeviceStream()
|
QNR_IODeviceStream::~QNR_IODeviceStream()
|
||||||
{
|
{
|
||||||
}
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
QNR_IODeviceStream::enoughData()
|
|
||||||
{
|
|
||||||
m_timer->stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
QNR_IODeviceStream::needData()
|
|
||||||
{
|
|
||||||
m_timer->start();
|
|
||||||
moreData();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
QNR_IODeviceStream::reset()
|
|
||||||
{
|
|
||||||
m_pos = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
QNR_IODeviceStream::seekStream( qint64 offset )
|
QNR_IODeviceStream::seekStream( qint64 offset )
|
||||||
{
|
{
|
||||||
|
tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
m_pos = offset;
|
m_pos = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
QNR_IODeviceStream::moreData()
|
size_t
|
||||||
|
QNR_IODeviceStream::needData ( void** buffer )
|
||||||
{
|
{
|
||||||
|
// tDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
QByteArray data = m_data.mid( m_pos, BLOCK_SIZE );
|
QByteArray data = m_data.mid( m_pos, BLOCK_SIZE );
|
||||||
m_pos += data.size();
|
m_pos += data.size();
|
||||||
if ( ( data.size() == 0 ) && m_networkReply->atEnd() && m_networkReply->isFinished() )
|
if ( ( data.size() == 0 ) && m_networkReply->atEnd() && m_networkReply->isFinished() )
|
||||||
{
|
{
|
||||||
// We're done.
|
// We're done.
|
||||||
endOfData();
|
//TODO endOfData();
|
||||||
m_timer->stop();
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
writeData( data );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
*buffer = new char[data.size()];
|
||||||
|
memcpy(*buffer, data.data(), data.size());
|
||||||
|
tDebug() << Q_FUNC_INFO << " Returning buffer with size " << data.size();
|
||||||
|
return data.size();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QNR_IODeviceStream::readyRead()
|
QNR_IODeviceStream::readyRead()
|
||||||
|
@ -25,37 +25,35 @@
|
|||||||
|
|
||||||
#include "DllMacro.h"
|
#include "DllMacro.h"
|
||||||
|
|
||||||
#include <phonon/abstractmediastream.h>
|
//#include <phonon/abstractmediastream.h>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QSharedPointer>
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
#include "MediaStream.h"
|
||||||
|
|
||||||
class QIODevice;
|
class QIODevice;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
|
|
||||||
namespace Tomahawk
|
namespace Tomahawk
|
||||||
{
|
{
|
||||||
|
|
||||||
class DLLEXPORT QNR_IODeviceStream : public Phonon::AbstractMediaStream
|
class DLLEXPORT QNR_IODeviceStream : public QObject, public MediaStream
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit QNR_IODeviceStream( const QSharedPointer<QNetworkReply>& reply, QObject *parent = 0 );
|
explicit QNR_IODeviceStream( const QSharedPointer<QNetworkReply>& reply, QObject *parent = 0 );
|
||||||
~QNR_IODeviceStream();
|
~QNR_IODeviceStream();
|
||||||
|
|
||||||
virtual void enoughData();
|
|
||||||
virtual void needData();
|
|
||||||
virtual void reset();
|
|
||||||
virtual void seekStream( qint64 offset );
|
virtual void seekStream( qint64 offset );
|
||||||
|
virtual size_t needData ( void** buffer );
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void moreData();
|
|
||||||
void readyRead();
|
void readyRead();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QByteArray m_data;
|
QByteArray m_data;
|
||||||
QSharedPointer<QNetworkReply> m_networkReply;
|
QSharedPointer<QNetworkReply> m_networkReply;
|
||||||
qint64 m_pos;
|
|
||||||
QTimer* m_timer;
|
QTimer* m_timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user