commit 13b550c5984d6164ce4871e2634ea621bb58b3a7 Author: Martin T. H. Sandsmark Date: Wed Dec 9 14:23:01 2009 +0100 Import an up to date Phonon release from Phonon trunk in KDE's SVN. diff --git a/src/3rdparty/phonon/gstreamer/CMakeLists.txt b/src/3rdparty/phonon/gstreamer/CMakeLists.txt index 4946f5f..d529fb6 100644 --- a/src/3rdparty/phonon/gstreamer/CMakeLists.txt +++ b/src/3rdparty/phonon/gstreamer/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +# Copyright (C) 2009 Nokia Corporation. All rights reserved. # Copyright (C) 2008 Matthias Kretz # # This library is free software: you can redistribute it and/or modify @@ -17,12 +17,23 @@ project(phonon-gstreamer) include(ConfigureChecks.cmake) if (BUILD_PHONON_GSTREAMER) - include_directories(${GSTREAMER_INCLUDE_DIR} ${GLIB2_INCLUDE_DIR} - ${LIBXML2_INCLUDE_DIR}) + include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${GSTREAMER_INCLUDE_DIR} + ${GLIB2_INCLUDE_DIR} + ${LIBXML2_INCLUDE_DIR} + ${X11_X11_INCLUDE_PATH}) + add_definitions(-DPHONON_BACKEND_VERSION_4_2) + + # configure plugin api + if(USE_INSTALL_PLUGIN) + set(PLUGIN_INSTALL_API TRUE) + endif(USE_INSTALL_PLUGIN) + + configure_file(phonon-config-gstreamer.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/phonon-config-gstreamer.h ) set(phonon_gstreamer_SRCS audiooutput.cpp - artssink.cpp backend.cpp devicemanager.cpp effectmanager.cpp @@ -38,24 +49,30 @@ if (BUILD_PHONON_GSTREAMER) message.cpp audioeffect.cpp abstractrenderer.cpp - x11renderer.cpp widgetrenderer.cpp glrenderer.cpp volumefadereffect.cpp + audiodataoutput.cpp ) - find_package(Alsa) - if(ALSA_FOUND) + if(NOT WIN32) + set(phonon_gstreamer_SRCS + ${phonon_gstreamer_SRCS} + artssink.cpp + x11renderer.cpp) + macro_optional_find_package(Alsa) + macro_ensure_version("0.10.22" ${GSTREAMER_VERSION} GSTREAMER_HAS_NONBLOCKING_ALSASINK) + endif(NOT WIN32) + if(ALSA_FOUND AND NOT GSTREAMER_HAS_NONBLOCKING_ALSASINK) add_definitions(-DUSE_ALSASINK2) include_directories(${ALSA_INCLUDES}) set(phonon_gstreamer_SRCS ${phonon_gstreamer_SRCS} alsasink2.c ) - endif(ALSA_FOUND) + endif(ALSA_FOUND AND NOT GSTREAMER_HAS_NONBLOCKING_ALSASINK) - automoc4(phonon_gstreamer phonon_gstreamer_SRCS) - add_library(phonon_gstreamer SHARED ${phonon_gstreamer_SRCS}) + automoc4_add_library(phonon_gstreamer MODULE ${phonon_gstreamer_SRCS}) set_target_properties(phonon_gstreamer PROPERTIES PREFIX "") target_link_libraries(phonon_gstreamer ${QT_QTOPENGL_LIBRARY} @@ -66,6 +83,9 @@ if (BUILD_PHONON_GSTREAMER) if(ALSA_FOUND) target_link_libraries(phonon_gstreamer ${ASOUND_LIBRARY}) endif(ALSA_FOUND) + if(USE_INSTALL_PLUGIN) + target_link_libraries(phonon_gstreamer ${GSTREAMER_PLUGIN_PBUTILS_LIBRARIES}) + endif(USE_INSTALL_PLUGIN) install(TARGETS phonon_gstreamer DESTINATION ${PLUGIN_INSTALL_DIR}/plugins/phonon_backend) install(FILES gstreamer.desktop DESTINATION ${SERVICES_INSTALL_DIR}/phononbackends) diff --git a/src/3rdparty/phonon/gstreamer/ConfigureChecks.cmake b/src/3rdparty/phonon/gstreamer/ConfigureChecks.cmake index f2922e1..095a0e9 100644 --- a/src/3rdparty/phonon/gstreamer/ConfigureChecks.cmake +++ b/src/3rdparty/phonon/gstreamer/ConfigureChecks.cmake @@ -1,4 +1,4 @@ -# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +# Copyright (C) 2009 Nokia Corporation. All rights reserved. # # This library is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by @@ -17,6 +17,7 @@ macro_log_feature(GSTREAMER_FOUND "GStreamer" "gstreamer 0.10 is required for th macro_optional_find_package(GStreamerPlugins) macro_log_feature(GSTREAMER_PLUGIN_VIDEO_LIBRARIES "GStreamer video plugin" "The gstreamer video plugin (part of gstreamer-plugins-base 0.10) is required for the multimedia gstreamer backend" "http://gstreamer.freedesktop.org/modules/" FALSE "0.10") +macro_log_feature(GSTREAMER_PLUGIN_AUDIO_LIBRARIES "GStreamer audio plugin" "The gstreamer audio plugin (part of gstreamer-plugins-base 0.10) is required for the multimedia gstreamer backend" "http://gstreamer.freedesktop.org/modules/" FALSE "0.10") macro_optional_find_package(GLIB2) macro_log_feature(GLIB2_FOUND "GLib2" "GLib 2 is required to compile the gstreamer backend for Phonon" "http://www.gtk.org/download/" FALSE) @@ -30,8 +31,8 @@ macro_log_feature(LIBXML2_FOUND "LibXml2" "LibXml2 is required to compile the gs macro_optional_find_package(OpenGL) macro_log_feature(OPENGL_FOUND "OpenGL" "OpenGL support is required to compile the gstreamer backend for Phonon" "" FALSE) -if (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND) +if (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GSTREAMER_PLUGIN_AUDIO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND) set(BUILD_PHONON_GSTREAMER TRUE) -else (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND) +else (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GSTREAMER_PLUGIN_AUDIO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND) set(BUILD_PHONON_GSTREAMER FALSE) -endif (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND) +endif (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GSTREAMER_PLUGIN_AUDIO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND) diff --git a/src/3rdparty/phonon/gstreamer/abstractrenderer.cpp b/src/3rdparty/phonon/gstreamer/abstractrenderer.cpp index 5d88d10..924b611 100644 --- a/src/3rdparty/phonon/gstreamer/abstractrenderer.cpp +++ b/src/3rdparty/phonon/gstreamer/abstractrenderer.cpp @@ -17,7 +17,6 @@ #include "abstractrenderer.h" -#ifndef QT_NO_PHONON_VIDEO QT_BEGIN_NAMESPACE namespace Phonon @@ -53,5 +52,5 @@ void AbstractRenderer::movieSizeChanged(const QSize &size) } //namespace Phonon::Gstreamer QT_END_NAMESPACE -#endif //QT_NO_PHONON_VIDEO + diff --git a/src/3rdparty/phonon/gstreamer/abstractrenderer.h b/src/3rdparty/phonon/gstreamer/abstractrenderer.h index 10a2822..140413d 100644 --- a/src/3rdparty/phonon/gstreamer/abstractrenderer.h +++ b/src/3rdparty/phonon/gstreamer/abstractrenderer.h @@ -23,7 +23,6 @@ #include "medianode.h" #include -#ifndef QT_NO_PHONON_VIDEO QT_BEGIN_NAMESPACE class QString; @@ -59,5 +58,5 @@ protected: } //namespace Phonon::Gstreamer QT_END_NAMESPACE -#endif //QT_NO_PHONON_VIDEO + #endif // Phonon_GSTREAMER_ABSTRACTRENDERER_H diff --git a/src/3rdparty/phonon/gstreamer/artssink.cpp b/src/3rdparty/phonon/gstreamer/artssink.cpp index 441607d..ff56da9 100644 --- a/src/3rdparty/phonon/gstreamer/artssink.cpp +++ b/src/3rdparty/phonon/gstreamer/artssink.cpp @@ -233,7 +233,7 @@ static void arts_sink_init (ArtsSink * src, ArtsSinkClass * g_class) Q_UNUSED(g_class); GST_DEBUG_OBJECT (src, "initializing artssink"); src->stream = 0; -#ifndef QT_NO_LIBRARY + p_arts_init = (Ptr_arts_init)QLibrary::resolve(QLatin1String("artsc"), 0, "arts_init"); p_arts_play_stream = (Ptr_arts_play_stream)QLibrary::resolve(QLatin1String("artsc"), 0, "arts_play_stream"); p_arts_close_stream = (Ptr_arts_close_stream)QLibrary::resolve(QLatin1String("artsc"), 0, "arts_close_stream"); @@ -250,7 +250,6 @@ static void arts_sink_init (ArtsSink * src, ArtsSinkClass * g_class) } } sinkCount ++; -#endif //QT_NO_LIBRARY } static void arts_sink_dispose (GObject * object) diff --git a/src/3rdparty/phonon/gstreamer/audiodataoutput.cpp b/src/3rdparty/phonon/gstreamer/audiodataoutput.cpp new file mode 100644 index 0000000..30dabdf --- /dev/null +++ b/src/3rdparty/phonon/gstreamer/audiodataoutput.cpp @@ -0,0 +1,143 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz + Copyright (C) 2009 Martin Sandsmark + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#include "audiodataoutput.h" +#include "gsthelper.h" +#include "medianode.h" +#include "mediaobject.h" +#include +#include +#include + +namespace Phonon +{ +namespace Gstreamer +{ +AudioDataOutput::AudioDataOutput(Backend *backend, QObject *parent) + : QObject(parent), + MediaNode(backend, AudioSink | AudioSource) +{ + static int count = 0; + m_name = "AudioDataOutput" + QString::number(count++); + + m_queue = gst_element_factory_make ("identity", NULL); + gst_object_ref(m_queue); + m_isValid = true; +} + +AudioDataOutput::~AudioDataOutput() +{ + gst_element_set_state(m_queue, GST_STATE_NULL); + gst_object_unref(m_queue); +} + +int AudioDataOutput::dataSize() const +{ + return m_dataSize; +} + +int AudioDataOutput::sampleRate() const +{ + return 44100; +} + +void AudioDataOutput::setDataSize(int size) +{ + m_dataSize = size; +} + +typedef QMap > FloatMap; +typedef QMap > IntMap; + +inline void AudioDataOutput::convertAndEmit(const QVector &leftBuffer, const QVector &rightBuffer) +{ + //TODO: Floats + IntMap map; + map.insert(Phonon::AudioDataOutput::LeftChannel, leftBuffer); + map.insert(Phonon::AudioDataOutput::RightChannel, rightBuffer); + emit dataReady(map); +} + +void AudioDataOutput::processBuffer(GstPad*, GstBuffer* buffer, gpointer gThat) +{ + // TODO emit endOfMedia + AudioDataOutput *that = reinterpret_cast(gThat); + + // determine the number of channels + GstStructure* structure = gst_caps_get_structure (GST_BUFFER_CAPS(buffer), 0); + gst_structure_get_int (structure, "channels", &that->m_channels); + + if (that->m_channels > 2 || that->m_channels < 0) { + qWarning() << Q_FUNC_INFO << ": Number of channels not supported: " << that->m_channels; + return; + } + + gint16 *data = reinterpret_cast(GST_BUFFER_DATA(buffer)); + guint size = GST_BUFFER_SIZE(buffer) / sizeof(gint16); + + that->m_pendingData.reserve(that->m_pendingData.size() + size); + + for (uint i=0; im_pendingData.append(data[i]); + } + + while (that->m_pendingData.size() > that->m_dataSize * that->m_channels) { + if (that->m_channels == 1) { + QVector intBuffer(that->m_dataSize); + memcpy(intBuffer.data(), that->m_pendingData.constData(), that->m_dataSize * sizeof(qint16)); + + that->convertAndEmit(intBuffer, intBuffer); + int newSize = that->m_pendingData.size() - that->m_dataSize; + memmove(that->m_pendingData.data(), that->m_pendingData.constData() + that->m_dataSize, newSize * sizeof(qint16)); + that->m_pendingData.resize(newSize); + } else { + QVector left(that->m_dataSize), right(that->m_dataSize); + for (int i=0; im_dataSize; i++) { + left[i] = that->m_pendingData[i*2]; + right[i] = that->m_pendingData[i*2+1]; + } + that->m_pendingData.resize(that->m_pendingData.size() - that->m_dataSize*2); + that->convertAndEmit(left, right); + } + } +} + +void AudioDataOutput::mediaNodeEvent(const MediaNodeEvent *event) +{ + if (event->type() == MediaNodeEvent::MediaObjectConnected && root()) { + g_object_set(G_OBJECT(audioElement()), "sync", true, (const char*)NULL); + GstPad *audiopad = gst_element_get_pad (audioElement(), "src"); + gst_pad_add_buffer_probe (audiopad, G_CALLBACK(processBuffer), this); + gst_object_unref (audiopad); + return; + } + + MediaNode::mediaNodeEvent(event); +} + +}} //namespace Phonon::Gstreamer + +#include "moc_audiodataoutput.cpp" +// vim: sw=4 ts=4 + diff --git a/src/3rdparty/phonon/gstreamer/audiodataoutput.h b/src/3rdparty/phonon/gstreamer/audiodataoutput.h new file mode 100644 index 0000000..5e30a1d --- /dev/null +++ b/src/3rdparty/phonon/gstreamer/audiodataoutput.h @@ -0,0 +1,84 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz + Copyright (C) 2009 Martin Sandsmark + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +#ifndef Phonon_GSTREAMER_AUDIODATAOUTPUT_H +#define Phonon_GSTREAMER_AUDIODATAOUTPUT_H + +#include "abstractaudiooutput.h" +#include "backend.h" +#include "medianode.h" +#include +#include + +namespace Phonon +{ +namespace Gstreamer +{ + /** + * \author Martin Sandsmark + */ + class AudioDataOutput : public QObject, + public AudioDataOutputInterface, + public MediaNode + { + Q_OBJECT + Q_INTERFACES(Phonon::AudioDataOutputInterface Phonon::Gstreamer::MediaNode) + + public: + AudioDataOutput(Backend *, QObject *); + ~AudioDataOutput(); + + public Q_SLOTS: + int dataSize() const; + int sampleRate() const; + void setDataSize(int size); + + public: + /// callback function for handling new audio data + static void processBuffer(GstPad*, GstBuffer*, gpointer); + + Phonon::AudioDataOutput* frontendObject() const { return m_frontend; } + void setFrontendObject(Phonon::AudioDataOutput *frontend) { m_frontend = frontend; } + + GstElement *audioElement() { return m_queue; } + + void mediaNodeEvent(const MediaNodeEvent *event); + + + signals: + void dataReady(const QMap > &data); + void dataReady(const QMap > &data); + void endOfMedia(int remainingSamples); + + private: + void convertAndEmit(const QVector&, const QVector&); + + GstElement *m_queue; + int m_dataSize; + QVector m_pendingData; + Phonon::AudioDataOutput *m_frontend; + int m_channels; + }; +}} //namespace Phonon::Gstreamer + +// vim: sw=4 ts=4 tw=80 +#endif // Phonon_FAKE_AUDIODATAOUTPUT_H diff --git a/src/3rdparty/phonon/gstreamer/audioeffect.cpp b/src/3rdparty/phonon/gstreamer/audioeffect.cpp index d3d7a35..db72c8b 100644 --- a/src/3rdparty/phonon/gstreamer/audioeffect.cpp +++ b/src/3rdparty/phonon/gstreamer/audioeffect.cpp @@ -23,7 +23,7 @@ #include "gsthelper.h" #include -#ifndef QT_NO_PHONON_EFFECT + QT_BEGIN_NAMESPACE namespace Phonon @@ -75,5 +75,4 @@ GstElement* AudioEffect::createEffectBin() } //namespace Phonon::Gstreamer QT_END_NAMESPACE -#endif //QT_NO_PHONON_EFFECT #include "moc_audioeffect.cpp" diff --git a/src/3rdparty/phonon/gstreamer/audioeffect.h b/src/3rdparty/phonon/gstreamer/audioeffect.h index f49f8d2..3a985e5 100644 --- a/src/3rdparty/phonon/gstreamer/audioeffect.h +++ b/src/3rdparty/phonon/gstreamer/audioeffect.h @@ -29,8 +29,8 @@ #include -#ifndef QT_NO_PHONON_EFFECT QT_BEGIN_NAMESPACE + namespace Phonon { namespace Gstreamer @@ -49,7 +49,7 @@ namespace Gstreamer QString m_effectName; }; }} //namespace Phonon::Gstreamer + QT_END_NAMESPACE -#endif //QT_NO_PHONON_EFFECT #endif // Phonon_GSTREAMER_AUDIOEFFECT_H diff --git a/src/3rdparty/phonon/gstreamer/audiooutput.cpp b/src/3rdparty/phonon/gstreamer/audiooutput.cpp index 138a7e4..4cfc42c 100644 --- a/src/3rdparty/phonon/gstreamer/audiooutput.cpp +++ b/src/3rdparty/phonon/gstreamer/audiooutput.cpp @@ -42,7 +42,6 @@ AudioOutput::AudioOutput(Backend *backend, QObject *parent) static int count = 0; m_name = "AudioOutput" + QString::number(count++); if (m_backend->isValid()) { - g_set_application_name(qApp->applicationName().toUtf8()); m_audioBin = gst_bin_new (NULL); gst_object_ref (GST_OBJECT (m_audioBin)); gst_object_sink (GST_OBJECT (m_audioBin)); @@ -126,6 +125,7 @@ void AudioOutput::setVolume(qreal newVolume) bool AudioOutput::setOutputDevice(int newDevice) { m_backend->logMessage(Q_FUNC_INFO + QString::number(newDevice), Backend::Info, this); + if (newDevice == m_device) return true; @@ -136,12 +136,11 @@ bool AudioOutput::setOutputDevice(int newDevice) } bool success = false; - const QList deviceList = m_backend->deviceManager()->audioOutputDevices(); - if (m_audioSink && newDevice >= 0 && newDevice < deviceList.size()) { + if (m_audioSink && newDevice >= 0) { // Save previous state GstState oldState = GST_STATE(m_audioSink); const QByteArray oldDeviceValue = GstHelper::property(m_audioSink, "device"); - const QByteArray deviceId = deviceList.at(newDevice).gstId; + const QByteArray deviceId = m_backend->deviceManager()->gstId(newDevice); m_device = newDevice; // We test if the device can be opened by checking if it can go from NULL to READY state diff --git a/src/3rdparty/phonon/gstreamer/backend.cpp b/src/3rdparty/phonon/gstreamer/backend.cpp index e1ffd1f..86cf92f 100644 --- a/src/3rdparty/phonon/gstreamer/backend.cpp +++ b/src/3rdparty/phonon/gstreamer/backend.cpp @@ -18,6 +18,7 @@ #include "common.h" #include "backend.h" #include "audiooutput.h" +#include "audiodataoutput.h" #include "audioeffect.h" #include "mediaobject.h" #include "videowidget.h" @@ -26,6 +27,7 @@ #include "message.h" #include "volumefadereffect.h" #include +#include #include #include @@ -49,19 +51,28 @@ Backend::Backend(QObject *parent, const QVariantList &) , m_debugLevel(Warning) , m_isValid(false) { + // Initialise PulseAudio support + PulseSupport *pulse = PulseSupport::getInstance(); + connect(pulse, SIGNAL(objectDescriptionChanged(ObjectDescriptionType)), SIGNAL(objectDescriptionChanged(ObjectDescriptionType))); + + // In order to support reloading, we only set the app name once... + static bool first = true; + if (first) { + first = false; + g_set_application_name(qApp->applicationName().toUtf8()); + } GError *err = 0; bool wasInit = gst_init_check(0, 0, &err); //init gstreamer: must be called before any gst-related functions if (err) g_error_free(err); qRegisterMetaType("Message"); -#ifndef QT_NO_PROPERTIES + setProperty("identifier", QLatin1String("phonon_gstreamer")); setProperty("backendName", QLatin1String("Gstreamer")); setProperty("backendComment", QLatin1String("Gstreamer plugin for Phonon")); setProperty("backendVersion", QLatin1String("0.2")); - setProperty("backendWebsite", QLatin1String("http://qt.nokia.com/")); -#endif //QT_NO_PROPERTIES + setProperty("backendWebsite", QLatin1String("http://qtsoftware.com/")); //check if we should enable debug output QString debugLevelString = qgetenv("PHONON_GST_DEBUG"); @@ -85,7 +96,9 @@ Backend::Backend(QObject *parent, const QVariantList &) Backend::~Backend() { - gst_deinit(); + delete m_effectManager; + delete m_deviceManager; + PulseSupport::shutdown(); } gboolean Backend::busCall(GstBus *bus, GstMessage *msg, gpointer data) @@ -113,20 +126,15 @@ QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const case MediaObjectClass: return new MediaObject(this, parent); - case AudioOutputClass: { - AudioOutput *ao = new AudioOutput(this, parent); - m_audioOutputs.append(ao); - return ao; - } -#ifndef QT_NO_PHONON_EFFECT + case AudioOutputClass: + return new AudioOutput(this, parent); + case EffectClass: return new AudioEffect(this, args[0].toInt(), parent); -#endif //QT_NO_PHONON_EFFECT + case AudioDataOutputClass: - logMessage("createObject() : AudioDataOutput not implemented"); - break; + return new AudioDataOutput(this, parent); -#ifndef QT_NO_PHONON_VIDEO case VideoDataOutputClass: logMessage("createObject() : VideoDataOutput not implemented"); break; @@ -135,11 +143,9 @@ QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QWidget *widget = qobject_cast(parent); return new VideoWidget(this, widget); } -#endif //QT_NO_PHONON_VIDEO -#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT + case VolumeFaderEffectClass: return new VolumeFaderEffect(this, parent); -#endif //QT_NO_PHONON_VOLUMEFADEREFFECT case VisualizationClass: //Fall through default: @@ -208,8 +214,15 @@ QStringList Backend::availableMimeTypes() const GstPluginFeature *feature = GST_PLUGIN_FEATURE(iter->data); QString klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature)); - if (klass == QLatin1String("Codec/Decoder/Audio") || - klass == QLatin1String("Codec/Decoder/Video")) { + if (klass == QLatin1String("Codec/Decoder") || + klass == QLatin1String("Codec/Decoder/Audio") || + klass == QLatin1String("Codec/Decoder/Video") || + klass == QLatin1String("Codec/Demuxer") || + klass == QLatin1String("Codec/Demuxer/Audio") || + klass == QLatin1String("Codec/Demuxer/Video") || + klass == QLatin1String("Codec/Parser") || + klass == QLatin1String("Codec/Parser/Audio") || + klass == QLatin1String("Codec/Parser/Video")) { const GList *static_templates; GstElementFactory *factory = GST_ELEMENT_FACTORY(feature); @@ -245,6 +258,10 @@ QList Backend::objectDescriptionIndexes(ObjectDescriptionType type) const if (!isValid()) return list; + PulseSupport *pulse = PulseSupport::getInstance(); + if (pulse->isActive() && (Phonon::AudioOutputDeviceType == type || Phonon::AudioCaptureDeviceType == type)) + return pulse->objectDescriptionIndexes(type); + switch (type) { case Phonon::AudioOutputDeviceType: { QList deviceList = deviceManager()->audioOutputDevices(); @@ -278,13 +295,17 @@ QHash Backend::objectDescriptionProperties(ObjectDescripti if (!isValid()) return ret; + PulseSupport *pulse = PulseSupport::getInstance(); + if (pulse->isActive() && (Phonon::AudioOutputDeviceType == type || Phonon::AudioCaptureDeviceType == type)) + return pulse->objectDescriptionProperties(type, index); + switch (type) { case Phonon::AudioOutputDeviceType: { - QList audioDevices = deviceManager()->audioOutputDevices(); - if (index >= 0 && index < audioDevices.size()) { - ret.insert("name", audioDevices[index].gstId); - ret.insert("description", audioDevices[index].description); - ret.insert("icon", QLatin1String("audio-card")); + AudioDevice* ad; + if ((ad = deviceManager()->audioDevice(index))) { + ret.insert("name", ad->gstId); + ret.insert("description", ad->description); + ret.insert("icon", ad->icon); } } break; @@ -413,7 +434,7 @@ EffectManager* Backend::effectManager() const /** * Returns a debuglevel that is determined by the - * PHONON_GSTREAMER_DEBUG environment variable. + * PHONON_GST_DEBUG environment variable. * * Warning - important warnings * Info - general info diff --git a/src/3rdparty/phonon/gstreamer/backend.h b/src/3rdparty/phonon/gstreamer/backend.h index 2aab6fa..d157f11 100644 --- a/src/3rdparty/phonon/gstreamer/backend.h +++ b/src/3rdparty/phonon/gstreamer/backend.h @@ -86,7 +86,6 @@ private Q_SLOTS: private: static gboolean busCall(GstBus *bus, GstMessage *msg, gpointer data); - QList > m_audioOutputs; DeviceManager *m_deviceManager; EffectManager *m_effectManager; diff --git a/src/3rdparty/phonon/gstreamer/devicemanager.cpp b/src/3rdparty/phonon/gstreamer/devicemanager.cpp index 60e860f..e62d281 100644 --- a/src/3rdparty/phonon/gstreamer/devicemanager.cpp +++ b/src/3rdparty/phonon/gstreamer/devicemanager.cpp @@ -24,6 +24,7 @@ #include "widgetrenderer.h" #include "x11renderer.h" #include "artssink.h" +#include "pulsesupport.h" #ifdef USE_ALSASINK2 #include "alsasink2.h" @@ -44,9 +45,12 @@ namespace Gstreamer AudioDevice::AudioDevice(DeviceManager *manager, const QByteArray &gstId) : gstId(gstId) { - //get an id - static int counter = 0; - id = counter++; + // This should never be called when PulseAudio is active. + Q_ASSERT(!PulseSupport::getInstance()->isActive()); + + id = manager->allocateDeviceId(); + icon = "audio-card"; + //get name from device if (gstId == "default") { description = "Default audio device"; @@ -71,22 +75,25 @@ AudioDevice::AudioDevice(DeviceManager *manager, const QByteArray &gstId) DeviceManager::DeviceManager(Backend *backend) : QObject(backend) , m_backend(backend) + , m_audioDeviceCounter(0) { - m_audioSink = qgetenv("PHONON_GST_AUDIOSINK"); - m_videoSinkWidget = qgetenv("PHONON_GST_VIDEOMODE"); - -#ifndef QT_NO_SETTINGS QSettings settings(QLatin1String("Trolltech")); settings.beginGroup(QLatin1String("Qt")); + PulseSupport *pulse = PulseSupport::getInstance(); + m_audioSink = qgetenv("PHONON_GST_AUDIOSINK"); if (m_audioSink.isEmpty()) { m_audioSink = settings.value(QLatin1String("audiosink"), "Auto").toByteArray().toLower(); + if (m_audioSink == "auto" && pulse->isActive()) + m_audioSink = "pulsesink"; } + if ("pulsesink" != m_audioSink) + pulse->disable(); + m_videoSinkWidget = qgetenv("PHONON_GST_VIDEOMODE"); if (m_videoSinkWidget.isEmpty()) { m_videoSinkWidget = settings.value(QLatin1String("videomode"), "Auto").toByteArray().toLower(); } -#endif //QT_NO_SETTINGS if (m_backend->isValid()) updateDeviceList(); @@ -246,7 +253,6 @@ GstElement *DeviceManager::createAudioSink(Category category) return sink; } -#ifndef QT_NO_PHONON_VIDEO AbstractRenderer *DeviceManager::createVideoRenderer(VideoWidget *parent) { #if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES) @@ -269,11 +275,18 @@ AbstractRenderer *DeviceManager::createVideoRenderer(VideoWidget *parent) #endif return new WidgetRenderer(parent); } -#endif //QT_NO_PHONON_VIDEO -/* - * Returns a positive device id or -1 if device - * does not exist +/** + * Allocate a device id for a new audio device + */ +int DeviceManager::allocateDeviceId() +{ + return m_audioDeviceCounter++; +} + + +/** + * Returns a positive device id or -1 if device does not exist * * The gstId is typically in the format hw:1,0 */ @@ -288,16 +301,30 @@ int DeviceManager::deviceId(const QByteArray &gstId) const } /** - * Get a human-readable description from a device id + * Returns a gstId or "default" if device does not exist + * + * The gstId is typically in the format hw:1,0 */ -QByteArray DeviceManager::deviceDescription(int id) const +const QByteArray DeviceManager::gstId(int deviceId) +{ + if (!PulseSupport::getInstance()->isActive()) { + AudioDevice *ad = audioDevice(deviceId); + if (ad) + return QByteArray(ad->gstId); + } + return QByteArray("default"); +} + +/** +* Get the AudioDevice for a given device id +*/ +AudioDevice* DeviceManager::audioDevice(int id) { for (int i = 0 ; i < m_audioDeviceList.size() ; ++i) { - if (m_audioDeviceList[i].id == id) { - return m_audioDeviceList[i].description; - } + if (m_audioDeviceList[i].id == id) + return &m_audioDeviceList[i]; } - return QByteArray(); + return NULL; } /** @@ -311,8 +338,11 @@ void DeviceManager::updateDeviceList() QList list; if (audioSink) { - list = GstHelper::extractProperties(audioSink, "device"); - list.prepend("default"); + if (!PulseSupport::getInstance()->isActive()) { + // If we're using pulse, the PulseSupport class takes care of things for us. + list = GstHelper::extractProperties(audioSink, "device"); + list.prepend("default"); + } for (int i = 0 ; i < list.size() ; ++i) { QByteArray gstId = list.at(i); diff --git a/src/3rdparty/phonon/gstreamer/devicemanager.h b/src/3rdparty/phonon/gstreamer/devicemanager.h index a5e8289..9c6aa8d 100644 --- a/src/3rdparty/phonon/gstreamer/devicemanager.h +++ b/src/3rdparty/phonon/gstreamer/devicemanager.h @@ -42,6 +42,7 @@ public : int id; QByteArray gstId; QByteArray description; + QString icon; }; class DeviceManager : public QObject { @@ -51,8 +52,10 @@ public: virtual ~DeviceManager(); const QList audioOutputDevices() const; GstPad *requestPad(int device) const; + int allocateDeviceId(); int deviceId(const QByteArray &gstId) const; - QByteArray deviceDescription(int id) const; + const QByteArray gstId(int id); + AudioDevice* audioDevice(int id); GstElement *createGNOMEAudioSink(Category category); GstElement *createAudioSink(Category category = NoCategory); AbstractRenderer *createVideoRenderer(VideoWidget *parent); @@ -68,6 +71,7 @@ private: bool canOpenDevice(GstElement *element) const; Backend *m_backend; QList m_audioDeviceList; + int m_audioDeviceCounter; QTimer m_devicePollTimer; QByteArray m_audioSink; QByteArray m_videoSinkWidget; diff --git a/src/3rdparty/phonon/gstreamer/effect.cpp b/src/3rdparty/phonon/gstreamer/effect.cpp index 4937246..f653535 100644 --- a/src/3rdparty/phonon/gstreamer/effect.cpp +++ b/src/3rdparty/phonon/gstreamer/effect.cpp @@ -25,8 +25,8 @@ #include -#ifndef QT_NO_PHONON_EFFECT QT_BEGIN_NAMESPACE + namespace Phonon { namespace Gstreamer @@ -241,6 +241,6 @@ void Effect::setParameterValue(const EffectParameter &p, const QVariant &v) } } //namespace Phonon::Gstreamer + QT_END_NAMESPACE -#endif //QT_NO_PHONON_EFFECT #include "moc_effect.cpp" diff --git a/src/3rdparty/phonon/gstreamer/effect.h b/src/3rdparty/phonon/gstreamer/effect.h index 51cbe9c..dbbb457 100644 --- a/src/3rdparty/phonon/gstreamer/effect.h +++ b/src/3rdparty/phonon/gstreamer/effect.h @@ -28,8 +28,8 @@ #include -#ifndef QT_NO_PHONON_EFFECT QT_BEGIN_NAMESPACE + namespace Phonon { namespace Gstreamer @@ -58,7 +58,7 @@ namespace Gstreamer QList m_parameterList; }; }} //namespace Phonon::Gstreamer + QT_END_NAMESPACE -#endif //QT_NO_PHONON_EFFECT #endif // Phonon_GSTREAMER_EFFECT_H diff --git a/src/3rdparty/phonon/gstreamer/gstreamer.desktop b/src/3rdparty/phonon/gstreamer/gstreamer.desktop index b62472b..7fb4000 100644 --- a/src/3rdparty/phonon/gstreamer/gstreamer.desktop +++ b/src/3rdparty/phonon/gstreamer/gstreamer.desktop @@ -10,27 +10,69 @@ Icon=phonon-gstreamer InitialPreference=10 Name=GStreamer +Name[bg]=GStreamer +Name[ca]=GStreamer +Name[cs]=GStreamer +Name[da]=GStreamer +Name[de]=GStreamer +Name[el]=GStreamer +Name[en_GB]=GStreamer +Name[es]=GStreamer +Name[et]=GStreamer +Name[eu]=GStreamer +Name[fr]=GStreamer +Name[ga]=GStreamer +Name[gl]=GStreamer +Name[hsb]=GStreamer +Name[hu]=GStreamer +Name[is]=GStreamer +Name[it]=GStreamer +Name[ja]=GStreamer +Name[ko]=GStreamer +Name[ku]=GStreamer +Name[lt]=GStreamer +Name[lv]=GStreamer +Name[nds]=GStreamer +Name[nl]=GStreamer +Name[nn]=GStreamer Name[pa]=ਜੀਸਟੀਰਮਰ +Name[pl]=GStreamer +Name[pt]=GStreamer +Name[pt_BR]=GStreamer +Name[se]=GStreamer +Name[sk]=GStreamer +Name[sl]=GStreamer Name[sr]=Гстример +Name[sr@latin]=GStreamer Name[sv]=Gstreamer +Name[tr]=GStreamer +Name[uk]=GStreamer Name[x-test]=xxGStreamerxx +Name[zh_CN]=GStreamer +Name[zh_TW]=GStreamer Comment=Phonon GStreamer backend Comment[bg]=Phonon GStreamer Comment[ca]=Dorsal GStreamer del Phonon +Comment[cs]=Phonon GStreamer backend Comment[da]=GStreamer-backend til Phonon Comment[de]=Phonon-Treiber für GStreamer Comment[el]=Σύστημα υποστήριξης GStreamer του Phonon +Comment[en_GB]=Phonon GStreamer backend Comment[es]=Motor GStreamer para Phonon Comment[et]=Phononi GStreameri taustaprogramm +Comment[eu]=Phonon GStreamer backend Comment[fr]=Système de gestion GStreamer pour Phonon Comment[ga]=Inneall GStreamer le haghaidh Phonon Comment[gl]=Infraestrutura de GStreamer para Phonon +Comment[hsb]=Phonon GStreamer backend +Comment[hu]=Phonon GStreamer modul Comment[is]=Phonon GStreamer bakendi Comment[it]=Motore Gstreamer di Phonon Comment[ja]=Phonon GStreamer バックエンド Comment[ko]=Phonon GStreamer 백엔드 Comment[ku]=Binesaza Phonon GStreamer +Comment[lt]=Phonon GStreamer galinė sąsaja Comment[lv]=Phonon GStreamer aizmugure Comment[nds]=Phonon-Hülpprogramm GStreamer Comment[nl]=GStreamer-backend (Phonon) @@ -39,6 +81,7 @@ Comment[pa]=ਫੋਨੋਨ ਜਸਟੀਰਮਰ ਬੈਕਐਂਡ Comment[pl]=Obsługa GStreamera przez Phonon Comment[pt]=Infra-estrutura do GStreamer para o Phonon Comment[pt_BR]=Infraestrutura Phonon GStreamer +Comment[se]=Phonon GStreamer duogášmohtor Comment[sk]=GStreamer podsystém Comment[sl]=Phononova hrbtenica GStreamer Comment[sr]=Гстример као позадина Фонона diff --git a/src/3rdparty/phonon/gstreamer/mediaobject.cpp b/src/3rdparty/phonon/gstreamer/mediaobject.cpp index 5713263..10aa8fd 100644 --- a/src/3rdparty/phonon/gstreamer/mediaobject.cpp +++ b/src/3rdparty/phonon/gstreamer/mediaobject.cpp @@ -16,6 +16,7 @@ */ #include #include +#include #include "common.h" #include "mediaobject.h" #include "videowidget.h" @@ -53,6 +54,7 @@ MediaObject::MediaObject(Backend *backend, QObject *parent) , m_tickTimer(new QTimer(this)) , m_prefinishMark(0) , m_transitionTime(0) + , m_isStream(false) , m_posAtSeek(-1) , m_prefinishMarkReachedNotEmitted(true) , m_aboutToFinishEmitted(false) @@ -79,6 +81,7 @@ MediaObject::MediaObject(Backend *backend, QObject *parent) , m_autoplayTitles(true) , m_availableTitles(0) , m_currentTitle(1) + , m_pendingTitle(1) { qRegisterMetaType("GstCaps*"); qRegisterMetaType("State"); @@ -87,7 +90,7 @@ MediaObject::MediaObject(Backend *backend, QObject *parent) m_name = "MediaObject" + QString::number(count++); if (!m_backend->isValid()) { - setError(tr("Cannot start playback. \n\nCheck your GStreamer installation and make sure you " + setError(tr("Cannot start playback. \n\nCheck your Gstreamer installation and make sure you " "\nhave libgstreamer-plugins-base installed."), Phonon::FatalError); } else { m_root = this; @@ -95,7 +98,7 @@ MediaObject::MediaObject(Backend *backend, QObject *parent) m_backend->addBusWatcher(this); connect(m_tickTimer, SIGNAL(timeout()), SLOT(emitTick())); } - connect(this, SIGNAL(stateChanged(Phonon::State, Phonon::State)), + connect(this, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(notifyStateChange(Phonon::State, Phonon::State))); } @@ -136,6 +139,14 @@ QString stateString(const Phonon::State &state) return QString(); } +void +pluginInstallationDone( GstInstallPluginsReturn res, gpointer userData ) +{ + // Nothing inside yet + Q_UNUSED(res); + Q_UNUSED(userData); +} + void MediaObject::saveState() { //Only first resumeState is respected @@ -195,13 +206,35 @@ void MediaObject::noMorePadsAvailable () if (m_missingCodecs.size() > 0) { bool canPlay = (m_hasAudio || m_videoStreamFound); Phonon::ErrorType error = canPlay ? Phonon::NormalError : Phonon::FatalError; +#ifdef PLUGIN_INSTALL_API + GstInstallPluginsContext *ctx = gst_install_plugins_context_new (); + gchar *details[2]; + details[0] = m_missingCodecs[0].toLocal8Bit().data(); + details[1] = NULL; + GstInstallPluginsReturn status; + + status = gst_install_plugins_async( details, ctx, pluginInstallationDone, NULL ); + gst_install_plugins_context_free ( ctx ); + + if ( status != GST_INSTALL_PLUGINS_STARTED_OK ) + { + if( status == GST_INSTALL_PLUGINS_HELPER_MISSING ) + setError(QString(tr("Missing codec helper script assistant.")), Phonon::FatalError ); + else + setError(QString(tr("Plugin codec installation failed for codec: %0")) + .arg(m_missingCodecs[0].split("|")[3]), error); + } + m_missingCodecs.clear(); +#else + QString codecs = m_missingCodecs.join(", "); + if (error == Phonon::NormalError && m_hasVideo && !m_videoStreamFound) { m_hasVideo = false; emit hasVideoChanged(false); } - QString codecs = m_missingCodecs.join(", "); setError(QString(tr("A required codec is missing. You need to install the following codec(s) to play this content: %0")).arg(codecs), error); m_missingCodecs.clear(); +#endif } } @@ -226,7 +259,6 @@ void MediaObject::cb_unknown_type (GstElement *decodebin, GstPad *pad, GstCaps * QString value = "unknown codec"; // These functions require GStreamer > 0.10.12 -#ifndef QT_NO_LIBRARY static Ptr_gst_pb_utils_init p_gst_pb_utils_init = 0; static Ptr_gst_pb_utils_get_codec_description p_gst_pb_utils_get_codec_description = 0; if (!p_gst_pb_utils_init) { @@ -240,15 +272,21 @@ void MediaObject::cb_unknown_type (GstElement *decodebin, GstPad *pad, GstCaps * codecName = p_gst_pb_utils_get_codec_description (caps); value = QString::fromUtf8(codecName); g_free (codecName); - } else -#endif //QT_NO_LIBRARY - { + } else { // For GStreamer versions < 0.10.12 GstStructure *str = gst_caps_get_structure (caps, 0); value = QString::fromUtf8(gst_structure_get_name (str)); - } - media->addMissingCodecName(value); + +#ifdef PLUGIN_INSTALL_API + QString plugins = QString("gstreamer|0.10|%0|%1|decoder-%2") + .arg( qApp->applicationName() ) + .arg( value ) + .arg( QString::fromUtf8(gst_caps_to_string (caps) ) ); + media->addMissingCodecName( plugins ); +#else + media->addMissingCodecName( value ); +#endif } static void notifyVideoCaps(GObject *obj, GParamSpec *, gpointer data) @@ -309,7 +347,7 @@ void MediaObject::connectVideo(GstPad *pad) m_backend->logMessage("Video track connected", Backend::Info, this); // Note that the notify::caps _must_ be installed after linking to work with Dapper m_capsHandler = g_signal_connect(pad, "notify::caps", G_CALLBACK(notifyVideoCaps), this); - + if (!m_loading && !m_hasVideo) { m_hasVideo = m_videoStreamFound; emit hasVideoChanged(m_hasVideo); @@ -344,7 +382,7 @@ void MediaObject::cb_pad_added(GstElement *decodebin, Q_UNUSED(decodebin); GstPad *decodepad = static_cast(data); gst_pad_link (pad, decodepad); - gst_object_unref (decodepad); + //gst_object_unref (decodepad); } /** @@ -368,15 +406,38 @@ bool MediaObject::createPipefromURL(const QUrl &url) } // Create a new datasource based on the input URL - QByteArray encoded_cstr_url = url.toEncoded(); + // add the 'file' scheme if it's missing; the double '/' is needed! + QByteArray encoded_cstr_url = (url.scheme() == QLatin1String("") ? + "file://" + url.toEncoded() : + url.toEncoded()); m_datasource = gst_element_make_from_uri(GST_URI_SRC, encoded_cstr_url.constData(), (const char*)NULL); if (!m_datasource) return false; // Set the device for MediaSource::Disc - QByteArray mediaDevice = QFile::encodeName(m_source.deviceName()); - if (!mediaDevice.isEmpty()) - g_object_set (m_datasource, "device", mediaDevice.constData(), (const char*)NULL); + if (m_source.type() == MediaSource::Disc) { + + if (g_object_class_find_property (G_OBJECT_GET_CLASS (m_datasource), "device")) { + QByteArray mediaDevice = QFile::encodeName(m_source.deviceName()); + if (!mediaDevice.isEmpty()) + g_object_set (G_OBJECT (m_datasource), "device", mediaDevice.constData(), (const char*)NULL); + } + + // Also Set optical disc speed to 2X for Audio CD + if (m_source.discType() == Phonon::Cd + && (g_object_class_find_property (G_OBJECT_GET_CLASS (m_datasource), "read-speed"))) { + g_object_set (G_OBJECT (m_datasource), "read-speed", 2, (const char*)NULL); + m_backend->logMessage(QString("new device speed : 2X"), Backend::Info, this); + } + } + + /* make HTTP sources send extra headers so we get icecast + * metadata in case the stream is an icecast stream */ + if (encoded_cstr_url.startsWith("http://") + && g_object_class_find_property (G_OBJECT_GET_CLASS (m_datasource), "iradio-mode")) { + g_object_set (m_datasource, "iradio-mode", TRUE, NULL); + m_isStream = true; + } // Link data source into pipeline gst_bin_add(GST_BIN(m_pipeline), m_datasource); @@ -396,7 +457,6 @@ bool MediaObject::createPipefromURL(const QUrl &url) */ bool MediaObject::createPipefromStream(const MediaSource &source) { -#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM // Remove any existing data source if (m_datasource) { gst_bin_remove(GST_BIN(m_pipeline), m_datasource); @@ -418,10 +478,6 @@ bool MediaObject::createPipefromStream(const MediaSource &source) return false; } return true; -#else //QT_NO_PHONON_ABSTRACTMEDIASTREAM - Q_UNUSED(source); - return false; -#endif } void MediaObject::createPipeline() @@ -664,7 +720,7 @@ void MediaObject::changeState(State newstate) return; Phonon::State oldState = m_state; - m_state = newstate; // m_state must be set before emitting, since + m_state = newstate; // m_state must be set before emitting, since // Error state requires that state() will return the new value m_pendingState = newstate; emit stateChanged(newstate, oldState); @@ -849,7 +905,7 @@ void MediaObject::setSource(const MediaSource &source) // such as failing duration queries etc GstState state; gst_element_set_state(m_pipeline, GST_STATE_NULL); - gst_element_get_state (m_pipeline, &state, NULL, 2000); + gst_element_get_state(m_pipeline, &state, NULL, 2000); m_source = source; emit currentSourceChanged(m_source); @@ -873,7 +929,7 @@ void MediaObject::setSource(const MediaSource &source) m_aboutToFinishEmitted = false; m_error = NoError; m_errorString = QString(); - + m_bufferPercent = 0; m_prefinishMarkReachedNotEmitted = true; m_aboutToFinishEmitted = false; @@ -882,11 +938,16 @@ void MediaObject::setSource(const MediaSource &source) setTotalTime(-1); m_atEndOfStream = false; - // Clear exising meta tags + m_availableTitles = 0; + m_pendingTitle = 1; + m_currentTitle = 1; + + // Clear existing meta tags m_metaData.clear(); + m_isStream = false; switch (source.type()) { - case MediaSource::Url: { + case MediaSource::Url: { if (createPipefromURL(source.url())) m_loading = true; else @@ -916,23 +977,27 @@ void MediaObject::setSource(const MediaSource &source) setError(tr("Could not open media source.")); break; - case MediaSource::Disc: // CD tracks can be specified by setting the url in the following way uri=cdda:4 + case MediaSource::Disc: { - QUrl url; - switch (source.discType()) { - case Phonon::Cd: - url = QUrl(QLatin1String("cdda://")); - break; - case Phonon::Dvd: - url = QUrl(QLatin1String("dvd://")); - break; - case Phonon::Vcd: - url = QUrl(QLatin1String("vcd://")); - break; - default: - break; + QString mediaUrl; + switch (source.discType()) { + case Phonon::NoDisc: + qWarning() << "I should never get to see a MediaSource that is a disc but doesn't specify which one"; + return; + case Phonon::Cd: // CD tracks can be specified by setting the url in the following way uri=cdda:4 + mediaUrl = QLatin1String("cdda://"); + break; + case Phonon::Dvd: + mediaUrl = QLatin1String("dvd://"); + break; + case Phonon::Vcd: + mediaUrl = QLatin1String("vcd://"); + break; + default: + qWarning() << "media " << source.discType() << " not implemented"; + return; } - if (!url.isEmpty() && createPipefromURL(url)) + if (!mediaUrl.isEmpty() && createPipefromURL(QUrl(mediaUrl))) m_loading = true; else setError(tr("Could not open media source.")); @@ -988,13 +1053,10 @@ void MediaObject::getStreamInfo() emit hasVideoChanged(m_hasVideo); } - m_availableTitles = 1; - gint64 titleCount; - GstFormat format = gst_format_get_by_nick("track"); - if (gst_element_query_duration (m_pipeline, &format, &titleCount)) { - //check if returned format is still "track", - //gstreamer sometimes returns the total time, if tracks information is not available. - if (qstrcmp(gst_format_get_name(format), "track") == 0) { + if (m_source.discType() == Phonon::Cd) { + gint64 titleCount; + GstFormat format = gst_format_get_by_nick("track"); + if (gst_element_query_duration (m_pipeline, &format, &titleCount)) { int oldAvailableTitles = m_availableTitles; m_availableTitles = (int)titleCount; if (m_availableTitles != oldAvailableTitles) { @@ -1061,7 +1123,7 @@ void MediaObject::seek(qint64 time) } quint64 current = currentTime(); - quint64 total = totalTime(); + quint64 total = totalTime(); if (current < total - m_prefinishMark) m_prefinishMarkReachedNotEmitted = true; @@ -1082,7 +1144,7 @@ void MediaObject::emitTick() if (m_tickInterval > 0 && currentTime != m_previousTickTime) { emit tick(currentTime); - m_previousTickTime = currentTime; + m_previousTickTime = currentTime; } if (m_state == Phonon::PlayingState) { if (currentTime >= totalTime - m_prefinishMark) { @@ -1093,7 +1155,12 @@ void MediaObject::emitTick() } // Prepare load of next source if (currentTime >= totalTime - ABOUT_TO_FINNISH_TIME) { - if (!m_aboutToFinishEmitted) { + if (m_source.type() == MediaSource::Disc && + m_autoplayTitles && + m_availableTitles > 1 && + m_currentTitle < m_availableTitles) { + m_aboutToFinishEmitted = false; + } else if (!m_aboutToFinishEmitted) { m_aboutToFinishEmitted = true; // track is about to finish emit aboutToFinish(); } @@ -1197,7 +1264,7 @@ void MediaObject::handleBusMessage(const Message &message) switch (GST_MESSAGE_TYPE (gstMessage)) { - case GST_MESSAGE_EOS: + case GST_MESSAGE_EOS: m_backend->logMessage("EOS recieved", Backend::Info, this); handleEndOfStream(); break; @@ -1206,14 +1273,98 @@ void MediaObject::handleBusMessage(const Message &message) GstTagList* tag_list = 0; gst_message_parse_tag(gstMessage, &tag_list); if (tag_list) { + TagMap newTags; + gst_tag_list_foreach (tag_list, &foreach_tag_function, &newTags); + gst_tag_list_free(tag_list); + + // Determine if we should no fake the album/artist tags. + // This is a little confusing as we want to fake it on initial + // connection where title, album and artist are all missing. + // There are however times when we get just other information, + // e.g. codec, and so we want to only do clever stuff if we + // have a commonly available tag (ORGANIZATION) or we have a + // change in title + bool fake_it = + (m_isStream + && ((!newTags.contains("TITLE") + && newTags.contains("ORGANIZATION")) + || (newTags.contains("TITLE") + && m_metaData.value("TITLE") != newTags.value("TITLE"))) + && !newTags.contains("ALBUM") + && !newTags.contains("ARTIST")); + TagMap oldMap = m_metaData; // Keep a copy of the old one for reference - // Append any new meta tags to the existing tag list - gst_tag_list_foreach (tag_list, &foreach_tag_function, &m_metaData); + + // Now we've checked the new data, append any new meta tags to the existing tag list + // We cannot use TagMap::iterator as this is a multimap and when streaming data + // could in theory be lost. + QList keys = newTags.keys(); + for (QList::iterator i = keys.begin(); i != keys.end(); ++i) { + QString key = *i; + if (m_isStream) { + // If we're streaming, we need to remove data in m_metaData + // in order to stop it filling up indefinitely (as it's a multimap) + m_metaData.remove(key); + } + QList values = newTags.values(key); + for (QList::iterator j = values.begin(); j != values.end(); ++j) { + QString value = *j; + QString currVal = m_metaData.value(key); + if (!m_metaData.contains(key) || currVal != value) { + m_metaData.insert(key, value); + } + } + } + m_backend->logMessage("Meta tags found", Backend::Info, this); - if (oldMap != m_metaData && !m_loading) - emit metaDataChanged(m_metaData); - gst_tag_list_free(tag_list); - } + if (oldMap != m_metaData) { + // This is a bit of a hack to ensure that stream metadata is + // returned. We get as much as we can from the Shoutcast server's + // StreamTitle= header. If further info is decoded from the stream + // itself later, then it will overwrite this info. + if (m_isStream && fake_it) { + m_metaData.remove("ALBUM"); + m_metaData.remove("ARTIST"); + + // Detect whether we want to "fill in the blanks" + QString str; + if (m_metaData.contains("TITLE")) + { + str = m_metaData.value("TITLE"); + int splitpoint; + // Check to see if our title matches "%s - %s" + // Where neither %s are empty... + if ((splitpoint = str.indexOf(" - ")) > 0 + && str.size() > (splitpoint+3)) { + m_metaData.insert("ARTIST", str.left(splitpoint)); + m_metaData.replace("TITLE", str.mid(splitpoint+3)); + } + } else { + str = m_metaData.value("GENRE"); + if (!str.isEmpty()) + m_metaData.insert("TITLE", str); + else + m_metaData.insert("TITLE", "Streaming Data"); + } + if (!m_metaData.contains("ARTIST")) { + str = m_metaData.value("LOCATION"); + if (!str.isEmpty()) + m_metaData.insert("ARTIST", str); + else + m_metaData.insert("ARTIST", "Streaming Data"); + } + str = m_metaData.value("ORGANIZATION"); + if (!str.isEmpty()) + m_metaData.insert("ALBUM", str); + else + m_metaData.insert("ALBUM", "Streaming Data"); + } + // As we manipulate the title, we need to recompare + // oldMap and m_metaData here... + if (oldMap != m_metaData && !m_loading) + emit metaDataChanged(m_metaData); + } + } } break; @@ -1239,6 +1390,9 @@ void MediaObject::handleBusMessage(const Message &message) m_backend->logMessage("gstreamer: pipeline state set to playing", Backend::Info, this); m_tickTimer->start(); changeState(Phonon::PlayingState); + if ((m_source.type() == MediaSource::Disc) && (m_currentTitle != m_pendingTitle)) { + setTrack(m_pendingTitle); + } if (m_resumeState && m_oldState == Phonon::PlayingState) { seek(m_oldPos); m_resumeState = false; @@ -1274,6 +1428,9 @@ void MediaObject::handleBusMessage(const Message &message) changeState(Phonon::StoppedState); m_backend->logMessage("gstreamer: pipeline state set to ready", Backend::Debug, this); m_tickTimer->stop(); + if ((m_source.type() == MediaSource::Disc) && (m_currentTitle != m_pendingTitle)) { + setTrack(m_pendingTitle); + } break; case GST_STATE_VOID_PENDING : @@ -1312,7 +1469,7 @@ void MediaObject::handleBusMessage(const Message &message) setError(err->message, Phonon::FatalError); gst_caps_unref (caps); gst_object_unref (sinkPad); - } + } } else { setError(QString(err->message), Phonon::FatalError); } @@ -1384,8 +1541,8 @@ void MediaObject::handleBusMessage(const Message &message) //case GST_MESSAGE_STEP_DONE: //case GST_MESSAGE_LATENCY: only from 0.10.12 //case GST_MESSAGE_ASYNC_DONE: only from 0.10.13 - default: - break; + default: + break; } } @@ -1401,7 +1558,8 @@ void MediaObject::handleEndOfStream() if (!m_seekable) m_atEndOfStream = true; - if (m_autoplayTitles && + if (m_source.type() == MediaSource::Disc && + m_autoplayTitles && m_availableTitles > 1 && m_currentTitle < m_availableTitles) { _iface_setCurrentTitle(m_currentTitle + 1); @@ -1486,15 +1644,30 @@ int MediaObject::_iface_currentTitle() const void MediaObject::_iface_setCurrentTitle(int title) { - GstFormat trackFormat = gst_format_get_by_nick("track"); m_backend->logMessage(QString("setCurrentTitle %0").arg(title), Backend::Info, this); - if ((title == m_currentTitle) || (title < 1) || (title > m_availableTitles)) + if ((title == m_currentTitle) || (title == m_pendingTitle)) + return; + + m_pendingTitle = title; + + if (m_state == Phonon::PlayingState || m_state == Phonon::StoppedState) { + setTrack(m_pendingTitle); + } else { + setState(Phonon::StoppedState); + } +} + +void MediaObject::setTrack(int title) +{ + if (((m_state != Phonon::PlayingState) && (m_state != Phonon::StoppedState)) || (title < 1) || (title > m_availableTitles)) return; - m_currentTitle = title; //let's seek to the beginning of the song - if (gst_element_seek_simple(m_pipeline, trackFormat, GST_SEEK_FLAG_FLUSH, m_currentTitle - 1)) { + GstFormat trackFormat = gst_format_get_by_nick("track"); + m_backend->logMessage(QString("setTrack %0").arg(title), Backend::Info, this); + if (gst_element_seek_simple(m_pipeline, trackFormat, GST_SEEK_FLAG_FLUSH, title - 1)) { + m_currentTitle = title; updateTotalTime(); m_atEndOfStream = false; emit titleChanged(title); diff --git a/src/3rdparty/phonon/gstreamer/mediaobject.h b/src/3rdparty/phonon/gstreamer/mediaobject.h index 64b3510..2db596d 100644 --- a/src/3rdparty/phonon/gstreamer/mediaobject.h +++ b/src/3rdparty/phonon/gstreamer/mediaobject.h @@ -55,6 +55,7 @@ class MediaObject : public QObject, public MediaObjectInterface , public MediaNode { friend class Stream; + friend class AudioDataOutput; Q_OBJECT Q_INTERFACES(Phonon::MediaObjectInterface #ifndef QT_NO_PHONON_MEDIACONTROLLER @@ -236,6 +237,7 @@ private: int _iface_availableTitles() const; int _iface_currentTitle() const; void _iface_setCurrentTitle(int title); + void setTrack(int title); bool m_resumeState; State m_oldState; @@ -250,6 +252,7 @@ private: MediaSource m_nextSource; qint32 m_prefinishMark; qint32 m_transitionTime; + bool m_isStream; qint64 m_posAtSeek; @@ -285,6 +288,7 @@ private: bool m_autoplayTitles; int m_availableTitles; int m_currentTitle; + int m_pendingTitle; }; } } //namespace Phonon::Gstreamer diff --git a/src/3rdparty/phonon/gstreamer/phononsrc.cpp b/src/3rdparty/phonon/gstreamer/phononsrc.cpp index 97d7220..f893fb5 100644 --- a/src/3rdparty/phonon/gstreamer/phononsrc.cpp +++ b/src/3rdparty/phonon/gstreamer/phononsrc.cpp @@ -109,25 +109,18 @@ static void phonon_src_class_init (PhononSrcClass * klass) static void phonon_src_init (PhononSrc * src, PhononSrcClass * g_class) { Q_UNUSED(g_class); -#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM src->device = 0; -#else - Q_UNUSED(src); -#endif } static void phonon_src_finalize (GObject * object) { -#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM PhononSrc *src; src = GST_PHONON_SRC (object); delete src->device; src->device = 0; -#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM G_OBJECT_CLASS (parent_class)->finalize (object); } -#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM static gboolean phonon_src_set_device(PhononSrc * src, StreamReader* device) { GstState state; @@ -152,7 +145,6 @@ wrong_state: return FALSE; } } -#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM static void phonon_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { @@ -161,7 +153,6 @@ static void phonon_src_set_property (GObject * object, guint prop_id, const GVal src = GST_PHONON_SRC (object); switch (prop_id) { -#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM case ARG_PHONONSRC: { StreamReader *dev = (StreamReader*)(g_value_get_pointer(value)); @@ -169,9 +160,6 @@ static void phonon_src_set_property (GObject * object, guint prop_id, const GVal phonon_src_set_device(src, dev); break; } -#else - Q_UNUSED(value); -#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -186,13 +174,9 @@ static void phonon_src_get_property (GObject * object, guint prop_id, GValue * v src = GST_PHONON_SRC (object); switch (prop_id) { -#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM case ARG_PHONONSRC: g_value_set_pointer(value, src->device); break; -#else //QT_NO_PHONON_ABSTRACTMEDIASTREAM - Q_UNUSED(value); -#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -201,7 +185,6 @@ static void phonon_src_get_property (GObject * object, guint prop_id, GValue * v static GstFlowReturn phonon_src_create_read (PhononSrc * src, guint64 offset, guint length, GstBuffer ** buffer) { -#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM Q_ASSERT(src->device); if (!src->device) return GST_FLOW_ERROR; @@ -221,13 +204,6 @@ static GstFlowReturn phonon_src_create_read (PhononSrc * src, guint64 offset, gu gst_mini_object_unref(GST_MINI_OBJECT(buf)); return GST_FLOW_ERROR; -#else //QT_NO_PHONON_ABSTRACTMEDIASTREAM - Q_UNUSED(src); - Q_UNUSED(offset); - Q_UNUSED(length); - Q_UNUSED(buffer); - return GST_FLOW_ERROR; -#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM } static GstFlowReturn phonon_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** buffer) @@ -242,23 +218,19 @@ static GstFlowReturn phonon_src_create (GstBaseSrc * basesrc, guint64 offset, gu static gboolean phonon_src_is_seekable (GstBaseSrc * basesrc) { PhononSrc *src = GST_PHONON_SRC (basesrc); -#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM if (src->device) return src->device->streamSeekable(); -#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM return false; } static gboolean phonon_src_get_size (GstBaseSrc * basesrc, guint64 * size) { -#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM PhononSrc *src; src = GST_PHONON_SRC (basesrc); if (src->device && src->device->streamSeekable()) { *size = src->device->streamSize(); return TRUE; } -#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM *size = 0; return FALSE; } diff --git a/src/3rdparty/phonon/gstreamer/phononsrc.h b/src/3rdparty/phonon/gstreamer/phononsrc.h index a50f8a2..a2cd8b3 100644 --- a/src/3rdparty/phonon/gstreamer/phononsrc.h +++ b/src/3rdparty/phonon/gstreamer/phononsrc.h @@ -49,9 +49,7 @@ typedef struct _PhononSrcClass PhononSrcClass; // PhononSrc: struct _PhononSrc { GstBaseSrc element; -#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM StreamReader *device; -#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM }; struct _PhononSrcClass { diff --git a/src/3rdparty/phonon/gstreamer/qwidgetvideosink.h b/src/3rdparty/phonon/gstreamer/qwidgetvideosink.h index 73a494a..f83dba5 100644 --- a/src/3rdparty/phonon/gstreamer/qwidgetvideosink.h +++ b/src/3rdparty/phonon/gstreamer/qwidgetvideosink.h @@ -19,6 +19,7 @@ #define Phonon_GSTREAMER_VIDEOSINK_H #include "common.h" +#include "qwidgetvideosink.h" #include #include diff --git a/src/3rdparty/phonon/gstreamer/streamreader.cpp b/src/3rdparty/phonon/gstreamer/streamreader.cpp index f8219e6..04fa6cc 100644 --- a/src/3rdparty/phonon/gstreamer/streamreader.cpp +++ b/src/3rdparty/phonon/gstreamer/streamreader.cpp @@ -20,7 +20,7 @@ along with this library. If not, see . #include QT_BEGIN_NAMESPACE -#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM + namespace Phonon { namespace Gstreamer @@ -49,6 +49,5 @@ bool StreamReader::read(quint64 pos, int length, char * buffer) } } -#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/gstreamer/streamreader.h b/src/3rdparty/phonon/gstreamer/streamreader.h index 387370c..c2e61c8 100644 --- a/src/3rdparty/phonon/gstreamer/streamreader.h +++ b/src/3rdparty/phonon/gstreamer/streamreader.h @@ -23,8 +23,6 @@ along with this library. If not, see . QT_BEGIN_NAMESPACE -#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM - namespace Phonon { class MediaSource; @@ -93,8 +91,6 @@ private: } } -#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM - QT_END_NAMESPACE #endif diff --git a/src/3rdparty/phonon/gstreamer/videowidget.cpp b/src/3rdparty/phonon/gstreamer/videowidget.cpp index e1f0ec9..efc750a 100644 --- a/src/3rdparty/phonon/gstreamer/videowidget.cpp +++ b/src/3rdparty/phonon/gstreamer/videowidget.cpp @@ -33,7 +33,6 @@ #include "widgetrenderer.h" #include "x11renderer.h" -#ifndef QT_NO_PHONON_VIDEO QT_BEGIN_NAMESPACE namespace Phonon @@ -384,6 +383,5 @@ void VideoWidget::mediaNodeEvent(const MediaNodeEvent *event) } //namespace Phonon::Gstreamer QT_END_NAMESPACE -#endif //QT_NO_PHONON_VIDEO #include "moc_videowidget.cpp" diff --git a/src/3rdparty/phonon/gstreamer/videowidget.h b/src/3rdparty/phonon/gstreamer/videowidget.h index dc0754d..47f4e08 100644 --- a/src/3rdparty/phonon/gstreamer/videowidget.h +++ b/src/3rdparty/phonon/gstreamer/videowidget.h @@ -25,10 +25,10 @@ #include "common.h" #include "medianode.h" #include "abstractrenderer.h" +#include "videowidget.h" #include -#ifndef QT_NO_PHONON_VIDEO QT_BEGIN_NAMESPACE class QString; @@ -103,5 +103,5 @@ private: } //namespace Phonon::Gstreamer QT_END_NAMESPACE -#endif //QT_NO_PHONON_VIDEO + #endif // Phonon_GSTREAMER_VIDEOWIDGET_H diff --git a/src/3rdparty/phonon/gstreamer/volumefadereffect.cpp b/src/3rdparty/phonon/gstreamer/volumefadereffect.cpp index bf0d646..d7ee11b 100644 --- a/src/3rdparty/phonon/gstreamer/volumefadereffect.cpp +++ b/src/3rdparty/phonon/gstreamer/volumefadereffect.cpp @@ -21,11 +21,11 @@ QT_BEGIN_NAMESPACE -#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT namespace Phonon { namespace Gstreamer { + VolumeFaderEffect::VolumeFaderEffect(Backend *backend, QObject *parent) : Effect(backend, parent, AudioSource | AudioSink) , m_fadeCurve(Phonon::VolumeFaderEffect::Fade3Decibel) @@ -156,7 +156,7 @@ bool VolumeFaderEffect::event(QEvent *event) } }} //namespace Phonon::Gstreamer -#endif //QT_NO_PHONON_VOLUMEFADEREFFECT + QT_END_NAMESPACE #include "moc_volumefadereffect.cpp" diff --git a/src/3rdparty/phonon/gstreamer/volumefadereffect.h b/src/3rdparty/phonon/gstreamer/volumefadereffect.h index 748d2d6..d74014c 100644 --- a/src/3rdparty/phonon/gstreamer/volumefadereffect.h +++ b/src/3rdparty/phonon/gstreamer/volumefadereffect.h @@ -30,7 +30,7 @@ #include QT_BEGIN_NAMESPACE -#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT + namespace Phonon { namespace Gstreamer @@ -64,7 +64,7 @@ namespace Gstreamer QTime m_fadeStartTime; }; }} //namespace Phonon::Gstreamer -#endif //QT_NO_PHONON_VOLUMEFADEREFFECT + QT_END_NAMESPACE #endif // Phonon_GSTREAMER_VOLUMEFADEREFFECT_H diff --git a/src/3rdparty/phonon/gstreamer/widgetrenderer.cpp b/src/3rdparty/phonon/gstreamer/widgetrenderer.cpp index 423af9d..d4a411f 100644 --- a/src/3rdparty/phonon/gstreamer/widgetrenderer.cpp +++ b/src/3rdparty/phonon/gstreamer/widgetrenderer.cpp @@ -32,7 +32,6 @@ # define GL_TEXTURE2 0x84C2 #endif -#ifndef QT_NO_PHONON_VIDEO QT_BEGIN_NAMESPACE static void frameRendered() @@ -149,4 +148,3 @@ bool WidgetRenderer::eventFilter(QEvent * event) } //namespace Phonon::Gstreamer QT_END_NAMESPACE -#endif //QT_NO_PHONON_VIDEO diff --git a/src/3rdparty/phonon/gstreamer/widgetrenderer.h b/src/3rdparty/phonon/gstreamer/widgetrenderer.h index 03ee9c0..ff64fa7 100644 --- a/src/3rdparty/phonon/gstreamer/widgetrenderer.h +++ b/src/3rdparty/phonon/gstreamer/widgetrenderer.h @@ -26,7 +26,6 @@ #include #endif -#ifndef QT_NO_PHONON_VIDEO QT_BEGIN_NAMESPACE class QString; @@ -60,5 +59,5 @@ private: } //namespace Phonon::Gstreamer QT_END_NAMESPACE -#endif //QT_NO_PHONON_VIDEO + #endif // Phonon_GSTREAMER_WIDGETRENDERER_H diff --git a/src/3rdparty/phonon/gstreamer/x11renderer.cpp b/src/3rdparty/phonon/gstreamer/x11renderer.cpp index 73877a8..9977001 100644 --- a/src/3rdparty/phonon/gstreamer/x11renderer.cpp +++ b/src/3rdparty/phonon/gstreamer/x11renderer.cpp @@ -138,6 +138,7 @@ void X11Renderer::scaleModeChanged(Phonon::VideoWidget::ScaleMode) void X11Renderer::movieSizeChanged(const QSize &movieSize) { Q_UNUSED(movieSize); + if (m_renderWidget) { m_renderWidget->setGeometry(m_videoWidget->calculateDrawFrameRect()); } diff --git a/src/3rdparty/phonon/phonon/CMakeLists.txt b/src/3rdparty/phonon/phonon/CMakeLists.txt index 11d7913..8ce1914 100644 --- a/src/3rdparty/phonon/phonon/CMakeLists.txt +++ b/src/3rdparty/phonon/phonon/CMakeLists.txt @@ -8,6 +8,22 @@ endif (PHONON_BUILD_EXAMPLES) add_subdirectory(experimental) +set(PULSEAUDIO_MINIMUM_VERSION "0.9.21") +macro_optional_find_package(PulseAudio) +macro_log_feature(PULSEAUDIO_FOUND "PulseAudio" "A cross-platform, networked sound server." "http://www.pulseaudio.org" FALSE "" "Allows audio playback via the PulseAudio soundserver when it is running") +macro_optional_find_package(GLIB2) +macro_log_feature(GLIB2_FOUND "GLib2" "GLib 2 is required to compile the pulseaudio for Phonon" "http://www.gtk.org/download/" FALSE) + +if (GLIB2_FOUND AND PULSEAUDIO_FOUND) + add_definitions(-DHAVE_PULSEAUDIO) + include_directories(${GLIB2_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIR}) +else(GLIB2_FOUND AND PULSEAUDIO_FOUND) + set(PULSEAUDIO_INCLUDE_DIR "") + set(PULSEAUDIO_LIBRARY "") + set(PULSEAUDIO_MAINLOOP_LIBRARY "") +endif(GLIB2_FOUND AND PULSEAUDIO_FOUND) + + set(phonon_LIB_SRCS objectdescription.cpp objectdescriptionmodel.cpp @@ -35,9 +51,12 @@ set(phonon_LIB_SRCS videowidget.cpp videoplayer.cpp seekslider.cpp + swiftslider.cpp volumeslider.cpp effectwidget.cpp iodevicestream.cpp + audiodataoutput.cpp + pulsesupport.cpp ) if (QT_QTDBUS_FOUND) @@ -50,6 +69,10 @@ endif (QT_QTDBUS_FOUND) add_definitions(-DPHONON_LIBRARY_PATH="${PLUGIN_INSTALL_DIR}/plugins") automoc4_add_library(phonon SHARED ${phonon_LIB_SRCS}) target_link_libraries(phonon ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY}) +if (GLIB2_FOUND AND PULSEAUDIO_FOUND) +target_link_libraries(phonon ${GLIB2_LIBRARIES} ${GOBJECT_LIBRARIES} ${PULSEAUDIO_LIBRARY} ${PULSEAUDIO_MAINLOOP_LIBRARY}) +endif (GLIB2_FOUND AND PULSEAUDIO_FOUND) + if (QT_QTDBUS_FOUND) target_link_libraries(phonon ${QT_QTDBUS_LIBRARY}) endif (QT_QTDBUS_FOUND) @@ -99,6 +122,10 @@ install(FILES volumeslider.h effectwidget.h platformplugin.h + audiodataoutput.h + audiodataoutputinterface.h + globalconfig.h + pulsesupport_p.h DESTINATION ${INCLUDE_INSTALL_DIR}/phonon COMPONENT Devel) install(FILES org.kde.Phonon.AudioOutput.xml DESTINATION ${DBUS_INTERFACES_INSTALL_DIR}) diff --git a/src/3rdparty/phonon/phonon/abstractaudiooutput.cpp b/src/3rdparty/phonon/phonon/abstractaudiooutput.cpp index 47c5a89..bce7c11 100644 --- a/src/3rdparty/phonon/phonon/abstractaudiooutput.cpp +++ b/src/3rdparty/phonon/phonon/abstractaudiooutput.cpp @@ -6,7 +6,7 @@ Copyright (C) 2005-2006 Matthias Kretz License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/abstractaudiooutput.h b/src/3rdparty/phonon/phonon/abstractaudiooutput.h index a466298..1045f18 100644 --- a/src/3rdparty/phonon/phonon/abstractaudiooutput.h +++ b/src/3rdparty/phonon/phonon/abstractaudiooutput.h @@ -6,7 +6,7 @@ Copyright (C) 2005-2006 Matthias Kretz License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/abstractaudiooutput_p.cpp b/src/3rdparty/phonon/phonon/abstractaudiooutput_p.cpp index 83ee8b0..20e0b3c 100644 --- a/src/3rdparty/phonon/phonon/abstractaudiooutput_p.cpp +++ b/src/3rdparty/phonon/phonon/abstractaudiooutput_p.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/abstractaudiooutput_p.h b/src/3rdparty/phonon/phonon/abstractaudiooutput_p.h index 831eb8d..9b3a57f 100644 --- a/src/3rdparty/phonon/phonon/abstractaudiooutput_p.h +++ b/src/3rdparty/phonon/phonon/abstractaudiooutput_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/abstractmediastream.cpp b/src/3rdparty/phonon/phonon/abstractmediastream.cpp index 5b860f3..26e6fd0 100644 --- a/src/3rdparty/phonon/phonon/abstractmediastream.cpp +++ b/src/3rdparty/phonon/phonon/abstractmediastream.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -49,6 +49,7 @@ AbstractMediaStream::AbstractMediaStream(AbstractMediaStreamPrivate &dd, QObject AbstractMediaStream::~AbstractMediaStream() { + delete d_ptr; } qint64 AbstractMediaStream::streamSize() const diff --git a/src/3rdparty/phonon/phonon/abstractmediastream.h b/src/3rdparty/phonon/phonon/abstractmediastream.h index c4cde85..5d5bce8 100644 --- a/src/3rdparty/phonon/phonon/abstractmediastream.h +++ b/src/3rdparty/phonon/phonon/abstractmediastream.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -214,7 +214,7 @@ class PHONON_EXPORT AbstractMediaStream : public QObject virtual void seekStream(qint64 offset); AbstractMediaStream(AbstractMediaStreamPrivate &dd, QObject *parent); - QScopedPointer d_ptr; + AbstractMediaStreamPrivate *d_ptr; }; } // namespace Phonon diff --git a/src/3rdparty/phonon/phonon/abstractmediastream_p.h b/src/3rdparty/phonon/phonon/abstractmediastream_p.h index 0e87c4d..e4c2be9 100644 --- a/src/3rdparty/phonon/phonon/abstractmediastream_p.h +++ b/src/3rdparty/phonon/phonon/abstractmediastream_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -45,7 +45,6 @@ class PHONON_EXPORT AbstractMediaStreamPrivate : private MediaNodeDestructionHan public: void setStreamInterface(StreamInterface *); void setMediaObjectPrivate(MediaObjectPrivate *); - ~AbstractMediaStreamPrivate(); protected: AbstractMediaStreamPrivate() @@ -57,6 +56,7 @@ class PHONON_EXPORT AbstractMediaStreamPrivate : private MediaNodeDestructionHan errorType(NoError) { } + ~AbstractMediaStreamPrivate(); virtual void setStreamSize(qint64 newSize); virtual void setStreamSeekable(bool s); diff --git a/src/3rdparty/phonon/phonon/abstractvideooutput.cpp b/src/3rdparty/phonon/phonon/abstractvideooutput.cpp index 30dde14..1695b78 100644 --- a/src/3rdparty/phonon/phonon/abstractvideooutput.cpp +++ b/src/3rdparty/phonon/phonon/abstractvideooutput.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/abstractvideooutput.h b/src/3rdparty/phonon/phonon/abstractvideooutput.h index 04cfdf0..824f729 100644 --- a/src/3rdparty/phonon/phonon/abstractvideooutput.h +++ b/src/3rdparty/phonon/phonon/abstractvideooutput.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/abstractvideooutput_p.cpp b/src/3rdparty/phonon/phonon/abstractvideooutput_p.cpp index 83d0650..a9cfa4d 100644 --- a/src/3rdparty/phonon/phonon/abstractvideooutput_p.cpp +++ b/src/3rdparty/phonon/phonon/abstractvideooutput_p.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/abstractvideooutput_p.h b/src/3rdparty/phonon/phonon/abstractvideooutput_p.h index d0e8157..90230d4 100644 --- a/src/3rdparty/phonon/phonon/abstractvideooutput_p.h +++ b/src/3rdparty/phonon/phonon/abstractvideooutput_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/addoninterface.h b/src/3rdparty/phonon/phonon/addoninterface.h index f400523..229129b 100644 --- a/src/3rdparty/phonon/phonon/addoninterface.h +++ b/src/3rdparty/phonon/phonon/addoninterface.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/audiodataoutput.cpp b/src/3rdparty/phonon/phonon/audiodataoutput.cpp new file mode 100644 index 0000000..58870c2 --- /dev/null +++ b/src/3rdparty/phonon/phonon/audiodataoutput.cpp @@ -0,0 +1,67 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#include "audiodataoutput.h" +#include "audiodataoutput_p.h" +#include "factory_p.h" + +#define PHONON_CLASSNAME AudioDataOutput + +namespace Phonon +{ + +PHONON_HEIR_IMPL(AbstractAudioOutput) + +PHONON_GETTER(int, dataSize, d->dataSize) +PHONON_GETTER(int, sampleRate, -1) +PHONON_SETTER(setDataSize, dataSize, int) + +bool AudioDataOutputPrivate::aboutToDeleteBackendObject() +{ + Q_ASSERT(m_backendObject); + pBACKEND_GET(int, dataSize, "dataSize"); + + return AbstractAudioOutputPrivate::aboutToDeleteBackendObject(); +} + +void AudioDataOutputPrivate::setupBackendObject() +{ + Q_Q(AudioDataOutput); + Q_ASSERT(m_backendObject); + AbstractAudioOutputPrivate::setupBackendObject(); + + // set up attributes + pBACKEND_CALL1("setDataSize", int, dataSize); + + qRegisterMetaType > >("QMap >"); + + QObject::connect(m_backendObject, + SIGNAL(dataReady(const QMap > &)), + q, SIGNAL(dataReady(const QMap > &))); + QObject::connect(m_backendObject, SIGNAL(endOfMedia(int)), q, SIGNAL(endOfMedia(int))); +} + +} // namespace Phonon + + +#undef PHONON_CLASSNAME +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/audiodataoutput.h b/src/3rdparty/phonon/phonon/audiodataoutput.h new file mode 100644 index 0000000..fefd68e --- /dev/null +++ b/src/3rdparty/phonon/phonon/audiodataoutput.h @@ -0,0 +1,135 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2006 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ +#ifndef Phonon_AUDIODATAOUTPUT_H +#define Phonon_AUDIODATAOUTPUT_H + +#include "phonon_export.h" +#include "abstractaudiooutput.h" +#include "phonondefs.h" + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template class QVector; +template class QMap; +#endif + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + class AudioDataOutputPrivate; + + /** + * \short This class gives you the audio data (for visualizations). + * + * This class implements a special AbstractAudioOutput that gives your + * application the audio data. Don't expect realtime performance. But + * the latencies should be low enough to use the audio data for + * visualizations. You can also use the audio data for further processing + * (e.g. encoding and saving to a file). + * + * \author Matthias Kretz + */ + class PHONON_EXPORT AudioDataOutput : public AbstractAudioOutput + { + Q_OBJECT + K_DECLARE_PRIVATE(AudioDataOutput) + Q_ENUMS(Channel) + Q_PROPERTY(int dataSize READ dataSize WRITE setDataSize) + PHONON_HEIR(AudioDataOutput) + public: + /** + * Specifies the channel the audio data belongs to. + */ + enum Channel + { + LeftChannel, + RightChannel, + CenterChannel, + LeftSurroundChannel, + RightSurroundChannel, + SubwooferChannel + }; + + /** + * Returns the currently used number of samples passed through + * the signal. + * + * \see setDataSize + */ + int dataSize() const; + + /** + * Returns the sample rate in Hz. Common sample rates are 44100 Hz + * and 48000 Hz. AudioDataOutput will not do any sample rate + * conversion for you. If you need to convert the sample rate you + * might want to take a look at libsamplerate. For visualizations it + * is often enough to do simple interpolation or even drop/duplicate + * samples. + * + * \return The sample rate as reported by the backend. If the + * backend is unavailable -1 is returned. + */ + int sampleRate() const; + + public Q_SLOTS: + /** + * Sets the number of samples to be passed in one signal emission. + * + * Defaults to 512 samples per emitted signal. + * + * \param size the number of samples + */ + void setDataSize(int size); + + Q_SIGNALS: + /** + * Emitted whenever another dataSize number of samples are ready. + * + * \param data A mapping of Channel to a vector holding the audio data. + */ + void dataReady(const QMap > &data); + + + /** + * This signal is emitted before the last dataReady signal of a + * media is emitted. + * + * If, for example, the playback of a media file has finished and the + * last audio data of that file is going to be passed with the next + * dataReady signal, and only the 28 first samples of the data + * vector are from that media file endOfMedia will be emitted right + * before dataReady with \p remainingSamples = 28. + * + * \param remainingSamples The number of samples in the next + * dataReady vector that belong to the media that was playing to + * this point. + */ + void endOfMedia(int remainingSamples); + }; +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +// vim: sw=4 ts=4 tw=80 +#endif // Phonon_AUDIODATAOUTPUT_H diff --git a/src/3rdparty/phonon/phonon/audiodataoutput_p.h b/src/3rdparty/phonon/phonon/audiodataoutput_p.h new file mode 100644 index 0000000..91103a9 --- /dev/null +++ b/src/3rdparty/phonon/phonon/audiodataoutput_p.h @@ -0,0 +1,48 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef AUDIODATAOUTPUT_P_H +#define AUDIODATAOUTPUT_P_H + +#include "audiodataoutput.h" +#include "abstractaudiooutput_p.h" + +namespace Phonon +{ + +class AudioDataOutputPrivate : public AbstractAudioOutputPrivate +{ + Q_DECLARE_PUBLIC(AudioDataOutput) + PHONON_PRIVATECLASS + protected: + AudioDataOutputPrivate() + : dataSize(512) + { + } + + int dataSize; +}; + +} // namespace Phonon + +#endif // AUDIODATAOUTPUT_P_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/audiodataoutputinterface.h b/src/3rdparty/phonon/phonon/audiodataoutputinterface.h new file mode 100644 index 0000000..bc1aad0 --- /dev/null +++ b/src/3rdparty/phonon/phonon/audiodataoutputinterface.h @@ -0,0 +1,44 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_AUDIODATAOUTPUTINTERFACE_H +#define PHONON_AUDIODATAOUTPUTINTERFACE_H + +namespace Phonon +{ + +class AudioDataOutput; + +class AudioDataOutputInterface +{ + public: + virtual ~AudioDataOutputInterface() {} + + virtual AudioDataOutput *frontendObject() const = 0; + virtual void setFrontendObject(AudioDataOutput *) = 0; +}; + +} // namespace Phonon + +Q_DECLARE_INTERFACE(Phonon::AudioDataOutputInterface, "0AudioDataOutputInterface.phonon.kde.org") + +#endif // PHONON_AUDIODATAOUTPUTINTERFACE_H diff --git a/src/3rdparty/phonon/phonon/audiooutput.cpp b/src/3rdparty/phonon/phonon/audiooutput.cpp index 00b2ebd..89b24bd 100644 --- a/src/3rdparty/phonon/phonon/audiooutput.cpp +++ b/src/3rdparty/phonon/phonon/audiooutput.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -24,12 +24,13 @@ #include "factory_p.h" #include "objectdescription.h" #include "audiooutputadaptor_p.h" -#include "globalconfig_p.h" +#include "globalconfig.h" #include "audiooutputinterface.h" #include "phononnamespace_p.h" #include "platform_p.h" +#include "pulsesupport.h" -#include +#include #define PHONON_CLASSNAME AudioOutput #define IFACES2 AudioOutputInterface42 @@ -42,8 +43,12 @@ QT_BEGIN_NAMESPACE namespace Phonon { -static inline bool callSetOutputDevice(MediaNodePrivate *const d, int index) +static inline bool callSetOutputDevice(AudioOutputPrivate *const d, int index) { + PulseSupport *pulse = PulseSupport::getInstance(); + if (pulse->isActive()) + return pulse->setOutputDevice(d->getStreamUuid(), index); + Iface iface(d); if (iface) { return iface->setOutputDevice(AudioOutputDevice::fromIndex(index)); @@ -51,8 +56,12 @@ static inline bool callSetOutputDevice(MediaNodePrivate *const d, int index) return Iface::cast(d)->setOutputDevice(index); } -static inline bool callSetOutputDevice(MediaNodePrivate *const d, const AudioOutputDevice &dev) +static inline bool callSetOutputDevice(AudioOutputPrivate *const d, const AudioOutputDevice &dev) { + PulseSupport *pulse = PulseSupport::getInstance(); + if (pulse->isActive()) + return pulse->setOutputDevice(d->getStreamUuid(), dev.index()); + Iface iface(d); if (iface) { return iface->setOutputDevice(dev); @@ -89,6 +98,8 @@ void AudioOutputPrivate::init(Phonon::Category c) #endif category = c; + streamUuid = QUuid::createUuid().toString(); + PulseSupport::getInstance()->setStreamPropList(category, streamUuid); // select hardware device according to the category device = AudioOutputDevice::fromIndex(GlobalConfig().audioOutputDeviceFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices)); @@ -98,7 +109,10 @@ void AudioOutputPrivate::init(Phonon::Category c) q->connect(Factory::sender(), SIGNAL(availableAudioOutputDevicesChanged()), SLOT(_k_deviceListChanged())); } - +QString AudioOutputPrivate::getStreamUuid() +{ + return streamUuid; +} void AudioOutputPrivate::createBackendObject() { @@ -126,7 +140,9 @@ void AudioOutput::setName(const QString &newName) d->name = newName; setVolume(Platform::loadVolume(newName)); #ifndef QT_NO_DBUS - emit d->adaptor->nameChanged(newName); + if (d->adaptor) { + emit d->adaptor->nameChanged(newName); + } #endif } @@ -232,7 +248,7 @@ bool AudioOutput::setOutputDevice(const AudioOutputDevice &newAudioOutputDevice) d->device = newAudioOutputDevice; } if (k_ptr->backendObject()) { - return callSetOutputDevice(k_ptr, d->device.index()); + return callSetOutputDevice(d, d->device.index()); } return true; } @@ -264,8 +280,8 @@ void AudioOutputPrivate::setupBackendObject() if (deviceList.isEmpty()) { return; } - for (int i = 0; i < deviceList.count(); ++i) { - const AudioOutputDevice &dev = AudioOutputDevice::fromIndex(deviceList.at(i)); + foreach (int devIndex, deviceList) { + const AudioOutputDevice &dev = AudioOutputDevice::fromIndex(devIndex); if (callSetOutputDevice(this, dev)) { handleAutomaticDeviceChange(dev, AudioOutputPrivate::FallbackChange); return; // found one that works @@ -305,9 +321,8 @@ void AudioOutputPrivate::_k_audioDeviceFailed() pDebug() << Q_FUNC_INFO; // outputDeviceIndex identifies a failing device // fall back in the preference list of output devices - const QList deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices); - for (int i = 0; i < deviceList.count(); ++i) { - const int devIndex = deviceList.at(i); + QList deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices); + foreach (int devIndex, deviceList) { // if it's the same device as the one that failed, ignore it if (device.index() != devIndex) { const AudioOutputDevice &info = AudioOutputDevice::fromIndex(devIndex); @@ -327,10 +342,9 @@ void AudioOutputPrivate::_k_deviceListChanged() { pDebug() << Q_FUNC_INFO; // let's see if there's a usable device higher in the preference list - const QList deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings); + QList deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings); DeviceChangeType changeType = HigherPreferenceChange; - for (int i = 0; i < deviceList.count(); ++i) { - const int devIndex = deviceList.at(i); + foreach (int devIndex, deviceList) { const AudioOutputDevice &info = AudioOutputDevice::fromIndex(devIndex); if (!info.property("available").toBool()) { if (device.index() == devIndex) { @@ -402,8 +416,11 @@ void AudioOutputPrivate::handleAutomaticDeviceChange(const AudioOutputDevice &de AudioOutputPrivate::~AudioOutputPrivate() { + PulseSupport::getInstance()->clearStreamCache(streamUuid); #ifndef QT_NO_DBUS - emit adaptor->outputDestroyed(); + if (adaptor) { + emit adaptor->outputDestroyed(); + } #endif } diff --git a/src/3rdparty/phonon/phonon/audiooutput.h b/src/3rdparty/phonon/phonon/audiooutput.h index 54bb389..4edf135 100644 --- a/src/3rdparty/phonon/phonon/audiooutput.h +++ b/src/3rdparty/phonon/phonon/audiooutput.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/audiooutput_p.h b/src/3rdparty/phonon/phonon/audiooutput_p.h index 459b491..0a90c3d 100644 --- a/src/3rdparty/phonon/phonon/audiooutput_p.h +++ b/src/3rdparty/phonon/phonon/audiooutput_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -46,6 +46,7 @@ class AudioOutputPrivate : public AbstractAudioOutputPrivate return 0; } void init(Phonon::Category c); + QString getStreamUuid(); protected: @@ -79,6 +80,7 @@ class AudioOutputPrivate : public AbstractAudioOutputPrivate QString name; Phonon::AudioOutputDevice device; qreal volume; + QString streamUuid; #ifndef QT_NO_DBUS Phonon::AudioOutputAdaptor *adaptor; #endif diff --git a/src/3rdparty/phonon/phonon/audiooutputinterface.cpp b/src/3rdparty/phonon/phonon/audiooutputinterface.cpp index be2780d..1770f4c 100644 --- a/src/3rdparty/phonon/phonon/audiooutputinterface.cpp +++ b/src/3rdparty/phonon/phonon/audiooutputinterface.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/audiooutputinterface.h b/src/3rdparty/phonon/phonon/audiooutputinterface.h index 1511e02..80ba11c 100644 --- a/src/3rdparty/phonon/phonon/audiooutputinterface.h +++ b/src/3rdparty/phonon/phonon/audiooutputinterface.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/backend/Mainpage.dox b/src/3rdparty/phonon/phonon/backend/Mainpage.dox new file mode 100644 index 0000000..db4cac1 --- /dev/null +++ b/src/3rdparty/phonon/phonon/backend/Mainpage.dox @@ -0,0 +1,109 @@ +/** \mainpage Phonon Backend Interface + + +\section phonon_backend_development Backend Development +If you want to write a new backend for %Phonon this is for you: +\li \ref phonon_backend_development_page "Phonon Backend Development" +\li \ref Backend + +\authors +Matthias Kretz \ + +\maintainers +Matthias Kretz \ + +\licenses +\lgpl + + + + + + + + +\page phonon_tut1 Phonon Tutorial Part 1: a simple audio player + +

+\ref index "Overview" | +Application Example | +\ref phonon_backend_development_page "Backend Development" +

+ +\includelineno tutorial2.cpp + + + + + + + + +\page phonon_backend_development_page Phonon Backend Development + +

+\ref index "Overview" | +\ref phonon_tut1 "Application Example" | +Backend Development +

+ +The backend is the most important part in %Phonon to provide functionality. This +document will get you started how backends work, how to start development of a +new backend and how to understand existing backend code. + +\section phonon_backend_introduction Introduction + +The first step is to understand how the %Phonon frontend calls the backend: In +the frontend objects all backend objects are "only" QObjects. But QObject has +powerful introspection capabilities that %Phonon uses to call methods in the +backend. If you're interested look at \ref QMetaObject::invokeMethod. In order +to make sure that a backend is fully operational (there are no abstract classes +that tell the backend developer what method signatures are wrong or what +methods are missing) there are two test programs compiled with kdelibs (if +KDE4_BUILD_TESTS is set in cmake) that inspects the backend. + +In short that requires the backend classes to inherit from QObject and to make +all methods that are to be called from the frontend slots or prefixed with +Q_INVOKABLE (the latter doesn't work reliable with Qt 4.1.3 at least, so you +should simply make those methods slots). + +\section phonon_backend_classes The Backend Classes + +The central class that needs to be implemented is the backend factory class, +throughout this documentation simply called Backend: + +\li \ref phonon_Backend "Backend" + +\subsection phonon_mediaproducingclasses The classes producing media data (sources) + +\li \ref Phonon::MediaObjectInterface "common methods/signals for media producing classes" +\li \ref phonon_MediaObject "MediaObject" + +\subsection phonon_pathclass The path class + +\li \ref phonon_Path "Path" + +\subsection phonon_outputclasses The output classes +\li \ref phonon_AudioDataOutput "AudioDataOutput" +\li \ref phonon_AudioOutput "AudioOutput" +\li \ref phonon_VideoDataOutput "VideoDataOutput" +\li \ref phonon_VideoWidget "VideoWidget" + +\subsection phonon_EffectClasses The effect classes + +\li \ref phonon_Effect "Effect" +\li \ref phonon_Visualization "Visualization" +\li \ref phonon_VolumeFaderEffect "VolumeFaderEffect" + +*/ +// DOXYGEN_REFERENCES = phonon +// DOXYGEN_SET_EXPAND_AS_DEFINED = PHONON_OBJECT PHONON_HEIR PHONON_INTERFACE_GETTER +// DOXYGEN_SET_HIDE_SCOPE_NAMES = YES +// DOXYGEN_SET_HIDE_FRIEND_COMPOUNDS = YES +// DOXYGEN_SET_PROJECT_NAME = Backend +// DOXYGEN_SET_EXTRACT_ALL = NO +// DOXYGEN_SET_HIDE_UNDOC_MEMBERS = YES +// DOXYGEN_SET_SOURCE_BROWSER = NO +// DOXYGEN_SET_INPUT = @topdir@/phonon/phonon +// DOXYGEN_SET_FILE_PATTERNS = *interface.h */phonon/backend/Mainpage.dox */backend.dox +// vim: tw=100 ts=4 sw=4 expandtab filetype=doxygen diff --git a/src/3rdparty/phonon/phonon/backendcapabilities.cpp b/src/3rdparty/phonon/phonon/backendcapabilities.cpp index 62c9cc9..654e87c 100644 --- a/src/3rdparty/phonon/phonon/backendcapabilities.cpp +++ b/src/3rdparty/phonon/phonon/backendcapabilities.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -26,7 +26,7 @@ #include "phonondefs_p.h" #include "backendinterface.h" #include "factory_p.h" -#include "globalconfig_p.h" +#include "globalconfig.h" #include "globalstatic_p.h" #include "objectdescription.h" @@ -76,8 +76,8 @@ QList BackendCapabilities::availableAudioOutputDevices() { QList ret; const QList deviceIndexes = GlobalConfig().audioOutputDeviceListFor(Phonon::NoCategory); - for (int i = 0; i < deviceIndexes.count(); ++i) { - ret.append(AudioOutputDevice::fromIndex(deviceIndexes.at(i))); + foreach (int i, deviceIndexes) { + ret.append(AudioOutputDevice::fromIndex(i)); } return ret; } @@ -88,8 +88,8 @@ QList BackendCapabilities::availableAudioCaptureDevices() { QList ret; const QList deviceIndexes = GlobalConfig().audioCaptureDeviceListFor(Phonon::NoCategory); - for (int i = 0; i < deviceIndexes.count(); ++i) { - ret.append(AudioCaptureDevice::fromIndex(deviceIndexes.at(i))); + foreach (int i, deviceIndexes) { + ret.append(AudioCaptureDevice::fromIndex(i)); } return ret; } @@ -101,9 +101,9 @@ QList BackendCapabilities::availableAudioEffects() BackendInterface *backendIface = qobject_cast(Factory::backend()); QList ret; if (backendIface) { - const QList deviceIndexes = backendIface->objectDescriptionIndexes(Phonon::EffectType); - for (int i = 0; i < deviceIndexes.count(); ++i) { - ret.append(EffectDescription::fromIndex(deviceIndexes.at(i))); + QList deviceIndexes = backendIface->objectDescriptionIndexes(Phonon::EffectType); + foreach (int i, deviceIndexes) { + ret.append(EffectDescription::fromIndex(i)); } } return ret; diff --git a/src/3rdparty/phonon/phonon/backendcapabilities.h b/src/3rdparty/phonon/phonon/backendcapabilities.h index 36454a3..bbe6937 100644 --- a/src/3rdparty/phonon/phonon/backendcapabilities.h +++ b/src/3rdparty/phonon/phonon/backendcapabilities.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -15,7 +15,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public + You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ @@ -88,18 +88,19 @@ namespace BackendCapabilities }; /** - * Use this function to get a QObject pointer to connect to one of the Notifier signals. + * Use this function to get a QObject pointer to connect to the capabilitiesChanged signal. * * \return a pointer to a QObject. * - * To connect to the signal do the following: + * The capabilitiesChanged signal is emitted if the capabilities have changed. This can + * happen if the user has requested a backend change. + * + * To connect to this signal do the following: * \code * QObject::connect(BackendCapabilities::notifier(), SIGNAL(capabilitiesChanged()), ... * \endcode * * \see Notifier::capabilitiesChanged() - * \see Notifier::availableAudioOutputDevicesChanged() - * \see Notifier::availableAudioCaptureDevicesChanged() */ PHONON_EXPORT Notifier *notifier(); diff --git a/src/3rdparty/phonon/phonon/backendcapabilities_p.h b/src/3rdparty/phonon/phonon/backendcapabilities_p.h index c17f24f..5ef18a4 100644 --- a/src/3rdparty/phonon/phonon/backendcapabilities_p.h +++ b/src/3rdparty/phonon/phonon/backendcapabilities_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/backendinterface.h b/src/3rdparty/phonon/phonon/backendinterface.h index e1f11da..5deee75 100644 --- a/src/3rdparty/phonon/phonon/backendinterface.h +++ b/src/3rdparty/phonon/phonon/backendinterface.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/effect.cpp b/src/3rdparty/phonon/phonon/effect.cpp index 98662a5..f0ac454 100644 --- a/src/3rdparty/phonon/phonon/effect.cpp +++ b/src/3rdparty/phonon/phonon/effect.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -107,8 +107,7 @@ bool EffectPrivate::aboutToDeleteBackendObject() { if (m_backendObject) { const QList parameters = pINTERFACE_CALL(parameters()); - for (int i = 0; i < parameters.count(); ++i) { - const EffectParameter &p = parameters.at(i); + foreach (const EffectParameter &p, parameters) { parameterValues[p] = pINTERFACE_CALL(parameterValue(p)); } } @@ -121,8 +120,7 @@ void EffectPrivate::setupBackendObject() // set up attributes const QList parameters = pINTERFACE_CALL(parameters()); - for (int i = 0; i < parameters.count(); ++i) { - const EffectParameter &p = parameters.at(i); + foreach (const EffectParameter &p, parameters) { pINTERFACE_CALL(setParameterValue(p, parameterValues[p])); } } diff --git a/src/3rdparty/phonon/phonon/effect.h b/src/3rdparty/phonon/phonon/effect.h index b3a7975..e403482 100644 --- a/src/3rdparty/phonon/phonon/effect.h +++ b/src/3rdparty/phonon/phonon/effect.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/effect_p.h b/src/3rdparty/phonon/phonon/effect_p.h index 586812a..6cc42d9 100644 --- a/src/3rdparty/phonon/phonon/effect_p.h +++ b/src/3rdparty/phonon/phonon/effect_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/effectinterface.h b/src/3rdparty/phonon/phonon/effectinterface.h index f535105..59c69d9 100644 --- a/src/3rdparty/phonon/phonon/effectinterface.h +++ b/src/3rdparty/phonon/phonon/effectinterface.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/effectparameter.cpp b/src/3rdparty/phonon/phonon/effectparameter.cpp index 6030b6e..0447f5b 100644 --- a/src/3rdparty/phonon/phonon/effectparameter.cpp +++ b/src/3rdparty/phonon/phonon/effectparameter.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/effectparameter.h b/src/3rdparty/phonon/phonon/effectparameter.h index 55c7049..4471a16 100644 --- a/src/3rdparty/phonon/phonon/effectparameter.h +++ b/src/3rdparty/phonon/phonon/effectparameter.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/effectparameter_p.h b/src/3rdparty/phonon/phonon/effectparameter_p.h index 0fc387a..f3f9f88 100644 --- a/src/3rdparty/phonon/phonon/effectparameter_p.h +++ b/src/3rdparty/phonon/phonon/effectparameter_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/effectwidget.cpp b/src/3rdparty/phonon/phonon/effectwidget.cpp index fb9cf6e..6738382 100644 --- a/src/3rdparty/phonon/phonon/effectwidget.cpp +++ b/src/3rdparty/phonon/phonon/effectwidget.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -97,8 +97,7 @@ void EffectWidgetPrivate::autogenerateUi() Q_Q(EffectWidget); QVBoxLayout *mainLayout = new QVBoxLayout(q); mainLayout->setMargin(0); - for (int i = 0; i < effect->parameters().count(); ++i) { - const EffectParameter ¶ = effect->parameters().at(i); + foreach (const EffectParameter ¶, effect->parameters()) { QVariant value = effect->parameterValue(para); QHBoxLayout *pLayout = new QHBoxLayout; mainLayout->addLayout(pLayout); @@ -118,14 +117,13 @@ void EffectWidgetPrivate::autogenerateUi() control = cb; if (value.type() == QVariant::Int) { //value just defines the item index - for (int i = 0; i < para.possibleValues().count(); ++i) { - cb->addItem(para.possibleValues().at(i).toString()); + foreach (const QVariant &item, para.possibleValues()) { + cb->addItem(item.toString()); } cb->setCurrentIndex(value.toInt()); QObject::connect(cb, SIGNAL(currentIndexChanged(int)), q, SLOT(_k_setIntParameter(int))); } else { - for (int i = 0; i < para.possibleValues().count(); ++i) { - const QVariant &item = para.possibleValues().at(i); + foreach (const QVariant &item, para.possibleValues()) { cb->addItem(item.toString()); if (item == value) { cb->setCurrentIndex(cb->count() - 1); @@ -157,20 +155,18 @@ void EffectWidgetPrivate::autogenerateUi() QObject::connect(sb, SIGNAL(valueChanged(int)), q, SLOT(_k_setIntParameter(int))); } break; - case QMetaType::Float: case QVariant::Double: { - const qreal minValue = para.minimumValue().canConvert(QVariant::Double) ? - para.minimumValue().toReal() : DEFAULT_MIN; - const qreal maxValue = para.maximumValue().canConvert(QVariant::Double) ? - para.maximumValue().toReal() : DEFAULT_MAX; + const double minValue = (para.minimumValue().type() == QVariant::Double ? + para.minimumValue().toDouble() : DEFAULT_MIN); + const double maxValue = (para.maximumValue().type() == QVariant::Double ? + para.maximumValue().toDouble() : DEFAULT_MAX); if (minValue == -1. && maxValue == 1.) { //Special case values between -1 and 1.0 to use a slider for improved usability QSlider *slider = new QSlider(Qt::Horizontal, q); - control = slider; slider->setRange(-SLIDER_RANGE, +SLIDER_RANGE); - slider->setValue(int(SLIDER_RANGE * value.toReal())); + slider->setValue(int(SLIDER_RANGE * value.toDouble())); slider->setTickPosition(QSlider::TicksBelow); slider->setTickInterval(TICKINTERVAL); QObject::connect(slider, SIGNAL(valueChanged(int)), q, SLOT(_k_setSliderParameter(int))); @@ -192,10 +188,10 @@ void EffectWidgetPrivate::autogenerateUi() break; } - if (control) { #ifndef QT_NO_TOOLTIP control->setToolTip(para.description()); #endif + if (control) { #ifndef QT_NO_SHORTCUT label->setBuddy(control); #endif diff --git a/src/3rdparty/phonon/phonon/effectwidget.h b/src/3rdparty/phonon/phonon/effectwidget.h index 340b2e3..17a310f 100644 --- a/src/3rdparty/phonon/phonon/effectwidget.h +++ b/src/3rdparty/phonon/phonon/effectwidget.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -39,7 +39,7 @@ class Effect; class EffectWidgetPrivate; /** \class EffectWidget effectwidget.h Phonon/EffectWidget - * \brief Widget to control the parameters of an \ref Effect. + * \brief Widget to control the parameters of an Effect. * * \ingroup PhononWidgets * \ingroup PhononEffects diff --git a/src/3rdparty/phonon/phonon/effectwidget_p.h b/src/3rdparty/phonon/phonon/effectwidget_p.h index 6ce44bf..aad422a 100644 --- a/src/3rdparty/phonon/phonon/effectwidget_p.h +++ b/src/3rdparty/phonon/phonon/effectwidget_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/experimental/CMakeLists.txt b/src/3rdparty/phonon/phonon/experimental/CMakeLists.txt new file mode 100644 index 0000000..d1fcd41 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/CMakeLists.txt @@ -0,0 +1,57 @@ +add_subdirectory(tests) + +########### libphononexperimental ############### +set(phononexperimental_LIB_SRCS + abstractaudiodataoutput.cpp + abstractvideodataoutput.cpp + audiodataoutput.cpp + audioformat.cpp + avcapture.cpp + backendcapabilities.cpp + factory.cpp + globalconfig.cpp + mediasource.cpp + packet.cpp + packetpool.cpp + videodataoutput.cpp + videodataoutput2.cpp + videowidget.cpp + visualization.cpp + ../abstractaudiooutput_p.cpp + ../abstractvideooutput_p.cpp + ) +automoc4_add_library(phononexperimental SHARED ${phononexperimental_LIB_SRCS}) +target_link_libraries(phononexperimental ${PHONON_LIBS}) +set_target_properties(phononexperimental PROPERTIES + VERSION ${PHONON_LIB_VERSION} + SOVERSION ${PHONON_LIB_SOVERSION} + DEFINE_SYMBOL MAKE_PHONONEXPERIMENTAL_LIB + ) +install(TARGETS phononexperimental ${INSTALL_TARGETS_DEFAULT_ARGS}) + +########### install headers ############### +install(FILES + abstractaudiodataoutput.h + abstractvideodataoutput.h + audiodataoutput.h + audiodataoutputinterface.h + audioformat.h + avcapture.h + backendcapabilities.h + backendinterface.h + export.h + mediasource.h + objectdescription.h + snapshotinterface.h + packet.h + packetpool.h + phononnamespace.h + videodataoutput.h + videodataoutput2.h + videodataoutputinterface.h + videoframe.h + videoframe2.h + videowidget.h + visualization.h + globalconfig.h + DESTINATION ${INCLUDE_INSTALL_DIR}/phonon/experimental COMPONENT Devel) diff --git a/src/3rdparty/phonon/phonon/experimental/abstractaudiodataoutput.cpp b/src/3rdparty/phonon/phonon/experimental/abstractaudiodataoutput.cpp new file mode 100644 index 0000000..f7b4f84 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/abstractaudiodataoutput.cpp @@ -0,0 +1,113 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#include "abstractaudiodataoutput.h" +#include "abstractaudiodataoutput_p.h" +#include "audiodataoutputinterface.h" +#include "factory_p.h" +#include "../phonondefs_p.h" + +namespace Phonon +{ +namespace Experimental +{ + +AbstractAudioDataOutput::AbstractAudioDataOutput() + : MediaNode(*new AbstractAudioDataOutputPrivate) +{ + K_D(AbstractAudioDataOutput); + d->isRunning = false; + d->allowedFormats << AudioFormat(); +} + +AbstractAudioDataOutput::~AbstractAudioDataOutput() +{ + setRunning(false); +} + +QSet AbstractAudioDataOutput::allowedFormats() const +{ + K_D(const AbstractAudioDataOutput); + return d->allowedFormats; +} + +void AbstractAudioDataOutput::setAllowedFormats(const QSet &allowedFormats) +{ + K_D(AbstractAudioDataOutput); + d->allowedFormats = allowedFormats; +} + +bool AbstractAudioDataOutput::isRunning() const +{ + K_D(const AbstractAudioDataOutput); + return d->isRunning; +} + +void AbstractAudioDataOutput::setRunning(bool running) +{ + K_D(AbstractAudioDataOutput); + Iface iface(d); + if (iface) { + if (running) { + iface->setFrontendObject(this); + } else { + iface->setFrontendObject(0); + } + } +} + +void AbstractAudioDataOutput::start() +{ + setRunning(true); +} + +void AbstractAudioDataOutput::stop() +{ + setRunning(false); +} + +void AbstractAudioDataOutputPrivate::setupBackendObject() +{ + Q_Q(AbstractAudioDataOutput); + Q_ASSERT(m_backendObject); + //AbstractAudioOutputPrivate::setupBackendObject(); + if (isRunning) { + Iface iface(this); + if (iface) { + iface->setFrontendObject(q); + } + } +} + +void AbstractAudioDataOutputPrivate::createBackendObject() +{ + if (m_backendObject) + return; + //Q_Q(AbstractAudioDataOutput); + m_backendObject = Factory::createAudioDataOutput(0); + if (m_backendObject) { + setupBackendObject(); + } +} + +} // namespace Experimental +} // namespace Phonon diff --git a/src/3rdparty/phonon/phonon/experimental/abstractaudiodataoutput.h b/src/3rdparty/phonon/phonon/experimental/abstractaudiodataoutput.h new file mode 100644 index 0000000..19c9f20 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/abstractaudiodataoutput.h @@ -0,0 +1,100 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2006,2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ +#ifndef PHONON_X_ABSTRACTAUDIODATAOUTPUT_H +#define PHONON_X_ABSTRACTAUDIODATAOUTPUT_H + +#include "export.h" +#include "../medianode.h" +#include "../phonondefs.h" +#include "audioformat.h" + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template class QSet; +#endif + +namespace Phonon +{ +namespace Experimental +{ + +class Packet; +class AbstractAudioDataOutputPrivate; + +/** + * \short This class gives you the audio data. + * + * This class implements a special AbstractAudioOutput that gives your + * application the audio data. This class is usable for realtime performance. + * + * \author Matthias Kretz + */ +class PHONONEXPERIMENTAL_EXPORT AbstractAudioDataOutput : public Phonon::MediaNode +{ + K_DECLARE_PRIVATE(AbstractAudioDataOutput) + public: + /** + * Constructs an AbstractAudioDataOutput + */ + AbstractAudioDataOutput(); + ~AbstractAudioDataOutput(); + + /** + * Lists the formats this output is allowed to pass via frameReady. + */ + virtual QSet allowedFormats() const; + + // TODO: consider to remove the following function and make the above pure virtual + /** + * Defaults to AudioFormat(). + * I.e. 16 bit, stereo, 48000 kHz PCM data. + */ + void setAllowedFormats(const QSet &); + + bool isRunning() const; + + /** + * This function is called whenever an audio packet is ready for + * processing. + * + * \warning packetReady can get called from any thread (other than the + * main thread or the thread affinity of this QObject). + */ + virtual void packetReady(const Packet &) = 0; + + /** + * This function is called after the last packetReady of a media was + * called. + */ + void endOfMedia(); + + void setRunning(bool running); + void start(); + void stop(); + + protected: + AbstractAudioDataOutput(AbstractAudioDataOutputPrivate &dd); +}; + +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_X_ABSTRACTAUDIODATAOUTPUT_H diff --git a/src/3rdparty/phonon/phonon/experimental/abstractaudiodataoutput_p.h b/src/3rdparty/phonon/phonon/experimental/abstractaudiodataoutput_p.h new file mode 100644 index 0000000..af30aec --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/abstractaudiodataoutput_p.h @@ -0,0 +1,50 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_X_ABSTRACTAUDIODATAOUTPUT_P_H +#define PHONON_X_ABSTRACTAUDIODATAOUTPUT_P_H + +#include "abstractaudiodataoutput.h" +#include "../medianode_p.h" + +namespace Phonon +{ +namespace Experimental +{ + +class AbstractAudioDataOutputPrivate : public Phonon::MediaNodePrivate +{ + Q_DECLARE_PUBLIC(AbstractAudioDataOutput) + protected: + virtual bool aboutToDeleteBackendObject() { return true; } + virtual void createBackendObject(); + void setupBackendObject(); + + private: + bool isRunning; + QSet allowedFormats; +}; + +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_X_ABSTRACTAUDIODATAOUTPUT_P_H diff --git a/src/3rdparty/phonon/phonon/experimental/abstractmediastream2.cpp b/src/3rdparty/phonon/phonon/experimental/abstractmediastream2.cpp new file mode 100644 index 0000000..ab80fbe --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/abstractmediastream2.cpp @@ -0,0 +1,191 @@ +/* This file is part of the KDE project + Copyright (C) 2007-2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#include "abstractmediastream2.h" +#include "abstractmediastream2_p.h" +#include "mediaobjectinterface.h" +#include "mediaobject_p.h" +#include "phononnamespace_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +bool AbstractMediaStream2::event(QEvent *e) +{ + if (e->type() == QEvent::ThreadChange) { + Q_D(AbstractMediaStream2); + if (d->eventDispatcher) { + pWarning() << "Do not call moveToThread on an AbstractMediaStream2 object when it is in use."; + QObject::disconnect(d->eventDispatcher, SIGNAL(awake()), this, SLOT(_k_handleStreamEvent())); + d->eventDispatcher = 0; + } + } + return AbstractMediaStream::event(e); +} + +void AbstractMediaStream2Private::dataReady() +{ + Q_Q(AbstractMediaStream2); + if (!eventDispatcher) { + eventDispatcher = QAbstractEventDispatcher::instance(q->thread()); + if (!eventDispatcher) { + pError() << "AbstractMediaStream2 needs to run in a thread with QEventLoop"; + return; + } else { + QObject::connect(eventDispatcher, SIGNAL(awake()), q, SLOT(_k_handleStreamEvent()), Qt::DirectConnection); + } + } + eventDispatcher->wakeUp(); +} + +void AbstractMediaStream2Private::_k_handleStreamEvent() +{ + Q_ASSERT(streamEventQueue); + Q_Q(AbstractMediaStream2); + StreamEventQueue::Command c; + while (streamEventQueue->nextCommandForFrontend(&c)) { + switch (c.command) { + case StreamEventQueue::SetStreamSize: + case StreamEventQueue::SetSeekable: + case StreamEventQueue::Write: + case StreamEventQueue::EndOfData: + case StreamEventQueue::SeekDone: + case StreamEventQueue::ResetDone: + case StreamEventQueue::ConnectDone: + pFatal("AbstractMediaStream2 received wrong Command"); + break; + case StreamEventQueue::NeedData: + q->needData(qvariant_cast(c.data)); + break; + case StreamEventQueue::EnoughData: + q->enoughData(); + break; + case StreamEventQueue::Seek: + q->seekStream(qvariant_cast(c.data)); + break; + case StreamEventQueue::Reset: + q->reset(); + break; + case StreamEventQueue::Connect: + if (firstConnect) { + firstConnect = false; + streamEventQueue->sendToBackend(StreamEventQueue::ConnectDone); + streamEventQueue->sendToBackend(StreamEventQueue::SetSeekable, streamSeekable); + if (streamSize != 0) { + streamEventQueue->sendToBackend(StreamEventQueue::SetStreamSize, streamSize); + } + } else { + ++connectReset; + q->reset(); + } + break; + } + } +} + +AbstractMediaStream2::AbstractMediaStream2(QObject *parent) + : AbstractMediaStream(*new AbstractMediaStream2Private, parent) +{ +} + +AbstractMediaStream2::AbstractMediaStream2(AbstractMediaStream2Private &dd, QObject *parent) + : AbstractMediaStream(dd, parent) +{ +} + +void AbstractMediaStream2Private::setStreamSize(qint64 newSize) +{ + streamSize = newSize; + streamEventQueue->sendToBackend(StreamEventQueue::SetStreamSize, newSize); +} + +void AbstractMediaStream2Private::setStreamSeekable(bool s) +{ + streamSeekable = s; + streamEventQueue->sendToBackend(StreamEventQueue::SetSeekable, s); +} + +void AbstractMediaStream2Private::writeData(const QByteArray &data) +{ + streamEventQueue->sendToBackend(StreamEventQueue::Write, data); +} + +void AbstractMediaStream2Private::endOfData() +{ + streamEventQueue->sendToBackend(StreamEventQueue::EndOfData); +} + +void AbstractMediaStream2::resetDone() +{ + Q_D(AbstractMediaStream2); + if (d->connectReset > 0) { + --d->connectReset; + d->streamEventQueue->sendToBackend(StreamEventQueue::ConnectDone); + } else { + d->streamEventQueue->sendToBackend(StreamEventQueue::ResetDone); + } + d->streamEventQueue->sendToBackend(StreamEventQueue::SetSeekable, d->streamSeekable); + if (d->streamSize != 0) { + d->streamEventQueue->sendToBackend(StreamEventQueue::SetStreamSize, d->streamSize); + } +} + +void AbstractMediaStream2::seekStreamDone() +{ + d_func()->streamEventQueue->sendToBackend(StreamEventQueue::SeekDone); +} + +AbstractMediaStream2Private::AbstractMediaStream2Private() + : streamEventQueue(new StreamEventQueue), + eventDispatcher(0), + connectReset(0), + firstConnect(true) +{ + streamEventQueue->ref(); + streamEventQueue->setFrontendCommandHandler(this); +} + +AbstractMediaStream2Private::~AbstractMediaStream2Private() +{ + // setFrontendCommandHandler blocks internally until a handler that might be called right now is + // done. That means AbstractMediaStream2Private::dataReady will either not run again or it will + // be done before this object and our q object are deleted. + streamEventQueue->setFrontendCommandHandler(0); + streamEventQueue->deref(); + streamEventQueue = 0; + // if eventDispatcher->wakeUp() was called and we are now still connected to its awake() signal + // then the QObject will be deleted until execution reaches the event loop again and + // _k_handleStreamEvent will not get called +} + +} // namespace Phonon + +QT_END_NAMESPACE + +#include "moc_abstractmediastream2.cpp" + +// vim: sw=4 sts=4 et tw=100 diff --git a/src/3rdparty/phonon/phonon/experimental/abstractmediastream2.h b/src/3rdparty/phonon/phonon/experimental/abstractmediastream2.h new file mode 100644 index 0000000..e6c89af --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/abstractmediastream2.h @@ -0,0 +1,153 @@ +/* This file is part of the KDE project + Copyright (C) 2007-2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_ABSTRACTMEDIASTREAM2_H +#define PHONON_ABSTRACTMEDIASTREAM2_H + +#include "abstractmediastream.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +class QByteArray; + +namespace Phonon +{ +class MediaObject; +class AbstractMediaStream2Private; + +/** \class AbstractMediaStream2 abstractmediastream2.h Phonon/AbstractMediaStream2 + * \brief Base class for custom media data streams. + * + * Implement this class to provide a custom data stream to the backend. The class supports both, the + * push and the pull model. + * + * Push: + * \code + * PushStream::PushStream(QObject *parent) + * : AbstractMediaStream2(parent), m_timer(new QTimer(this)) + * { + * setStreamSize(getMediaStreamSize()); + * + * connect(m_timer, SIGNAL(timeout()), SLOT(moreData())); + * m_timer->setInterval(0); + * } + * + * void PushStream::moreData() + * { + * const QByteArray data = getMediaData(); + * if (data.isEmpty()) { + * endOfData(); + * } else { + * writeData(data); + * } + * } + * + * void PushStream::needData() + * { + * m_timer->start(); + * moreData(); + * } + * + * void PushStream::enoughData() + * { + * m_timer->stop(); + * } + * \endcode + * + * Pull: + * \code + * PullStream::PullStream(QObject *parent) + * : AbstractMediaStream2(parent) + * { + * setStreamSize(getMediaStreamSize()); + * } + * + * void PullStream::needData() + * { + * const QByteArray data = getMediaData(); + * if (data.isEmpty()) { + * endOfData(); + * } else { + * writeData(data); + * } + * } + * \endcode + * + * \ingroup Playback + * \author Matthias Kretz + */ +class PHONON_EXPORT AbstractMediaStream2 : public AbstractMediaStream +{ + Q_OBJECT + Q_DECLARE_PRIVATE(AbstractMediaStream2) + friend class MediaObject; + friend class MediaObjectPrivate; + friend class MediaSourcePrivate; + protected: + ///////////////////////////////////////////////////////////// + // functions an implementation will call: + ///////////////////////////////////////////////////////////// + + /** + * Constructs an AbstractMediaStream2 object with a \p parent. + */ + explicit AbstractMediaStream2(QObject *parent = 0); + + void resetDone(); + void seekStreamDone(); + + ///////////////////////////////////////////////////////////// + // functions to implement: + ///////////////////////////////////////////////////////////// + + /** + * Reimplement this function to be notified when the backend needs data. + * + * When this function is called you should try to call writeData or endOfData before + * returning. + * + * \param size The number of bytes that are needed. If possible, pass \p size bytes of media + * data in the next writeData call. + */ + virtual void needData(quint32 size) = 0; + + ///////////////////////////////////////////////////////////// + // internal + ///////////////////////////////////////////////////////////// + + bool event(QEvent *e); + AbstractMediaStream2(AbstractMediaStream2Private &dd, QObject *parent); + + private: + // hide needData() explicitly + virtual void needData() {} + + Q_PRIVATE_SLOT(d_func(), void _k_handleStreamEvent()) +}; + +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_ABSTRACTMEDIASTREAM2_H diff --git a/src/3rdparty/phonon/phonon/experimental/abstractmediastream2_p.h b/src/3rdparty/phonon/phonon/experimental/abstractmediastream2_p.h new file mode 100644 index 0000000..e06e08d --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/abstractmediastream2_p.h @@ -0,0 +1,67 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef ABSTRACTMEDIASTREAM2_P_H +#define ABSTRACTMEDIASTREAM2_P_H + +#include "phonon_export.h" +#include "abstractmediastream2.h" +#include "abstractmediastream_p.h" +#include "mediaobject_p.h" + +#include "medianodedestructionhandler_p.h" +#include "streameventqueue_p.h" + +QT_BEGIN_NAMESPACE + +class MediaObjectPrivate; +class QAbstractEventDispatcher; + +namespace Phonon +{ +class PHONON_EXPORT AbstractMediaStream2Private : public AbstractMediaStreamPrivate, private LockFreeQueueBase::DataReadyHandler +{ + friend class MediaObject; + friend class MediaSourcePrivate; + Q_DECLARE_PUBLIC(AbstractMediaStream2) + protected: + AbstractMediaStream2Private(); + ~AbstractMediaStream2Private(); + + virtual void setStreamSize(qint64 newSize); + virtual void setStreamSeekable(bool s); + virtual void writeData(const QByteArray &data); + virtual void endOfData(); + virtual void dataReady(); + void _k_handleStreamEvent(); + + StreamEventQueue *streamEventQueue; + QAbstractEventDispatcher *eventDispatcher; + int connectReset; + bool firstConnect; +}; +} // namespace Phonon + +QT_END_NAMESPACE + +#endif // ABSTRACTMEDIASTREAM2_P_H +// vim: sw=4 sts=4 et tw=100 diff --git a/src/3rdparty/phonon/phonon/experimental/abstractvideodataoutput.cpp b/src/3rdparty/phonon/phonon/experimental/abstractvideodataoutput.cpp new file mode 100644 index 0000000..67a0431 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/abstractvideodataoutput.cpp @@ -0,0 +1,122 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This program 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 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), Nokia Corporation (or its successors, + if any) and the KDE Free Qt Foundation, which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program 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 this program. If not, see . + +*/ +#include "abstractvideodataoutput.h" +#include "abstractvideodataoutput_p.h" +#include "videodataoutputinterface.h" +#include "factory_p.h" + +namespace Phonon +{ +namespace Experimental +{ + +AbstractVideoDataOutput::AbstractVideoDataOutput() + : AbstractVideoOutput(*new AbstractVideoDataOutputPrivate) +{ + K_D(AbstractVideoDataOutput); + d->isRunning = false; + d->allowedFormats << VideoFrame2::Format_RGB888; +} + +AbstractVideoDataOutput::AbstractVideoDataOutput(AbstractVideoDataOutputPrivate &dd) + : AbstractVideoOutput(dd) +{ +} + +AbstractVideoDataOutput::~AbstractVideoDataOutput() +{ + setRunning(false); +} + +QSet AbstractVideoDataOutput::allowedFormats() const +{ + K_D(const AbstractVideoDataOutput); + return d->allowedFormats; +} + +void AbstractVideoDataOutput::setAllowedFormats(const QSet &allowedFormats) +{ + K_D(AbstractVideoDataOutput); + d->allowedFormats = allowedFormats; +} + +bool AbstractVideoDataOutput::isRunning() const +{ + K_D(const AbstractVideoDataOutput); + return d->isRunning; +} + +void AbstractVideoDataOutput::setRunning(bool running) +{ + K_D(AbstractVideoDataOutput); + d->isRunning = running; + Iface iface(d); + if (iface) { + if (running) { + iface->setFrontendObject(this); + } else { + iface->setFrontendObject(0); + } + } +} + +void AbstractVideoDataOutput::start() +{ + setRunning(true); +} + +void AbstractVideoDataOutput::stop() +{ + setRunning(false); +} + +bool AbstractVideoDataOutputPrivate::aboutToDeleteBackendObject() +{ + return AbstractVideoOutputPrivate::aboutToDeleteBackendObject(); +} + +void AbstractVideoDataOutputPrivate::setupBackendObject() +{ + Q_Q(AbstractVideoDataOutput); + Q_ASSERT(m_backendObject); + //AbstractVideoOutputPrivate::setupBackendObject(); + if (isRunning) { + Iface iface(this); + if (iface) { + iface->setFrontendObject(q); + } + } +} + +void AbstractVideoDataOutputPrivate::createBackendObject() +{ + if (m_backendObject) + return; + //Q_Q(AbstractVideoDataOutput); + m_backendObject = Factory::createVideoDataOutput(0); + if (m_backendObject) { + setupBackendObject(); + } +} + +} // namespace Experimental +} // namespace Phonon diff --git a/src/3rdparty/phonon/phonon/experimental/abstractvideodataoutput.h b/src/3rdparty/phonon/phonon/experimental/abstractvideodataoutput.h new file mode 100644 index 0000000..d66e97d --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/abstractvideodataoutput.h @@ -0,0 +1,107 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_X_ABSTRACTVIDEODATAOUTPUT_H +#define PHONON_X_ABSTRACTVIDEODATAOUTPUT_H + +#include "export.h" +#include "../abstractvideooutput.h" +#include "../phonondefs.h" +#include +#include "videoframe2.h" + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template class QSet; +#endif + +namespace Phonon +{ +namespace Experimental +{ + +class AbstractVideoDataOutputPrivate; + +/** + * \short This class gives you the video data. + * + * This class implements a special AbstractVideoOutput that gives your + * application the video data. + * + * You can also use the video data for further processing (e.g. encoding and + * saving to a file). + * + * \author Matthias Kretz + * + * \see VideoDataOutput2 + */ +class PHONONEXPERIMENTAL_EXPORT AbstractVideoDataOutput : public AbstractVideoOutput +{ + K_DECLARE_PRIVATE(AbstractVideoDataOutput) + + public: + /** + * Constructs an AbstractVideoDataOutput + */ + AbstractVideoDataOutput(); + ~AbstractVideoDataOutput(); + + /** + * Lists the formats this output is allowed to pass via frameReady. + */ + virtual QSet allowedFormats() const; + + // TODO: consider to remove the following function and make the above pure virtual + /** + * Defaults to VideoFrame2::Format_RGB888. + */ + void setAllowedFormats(const QSet &); + + bool isRunning() const; + + /** + * This function is called whenever a frame should be displayed. + * + * \warning frameReady can get called from any thread (other than the + * main thread or the thread affinity of this QObject). A common error to create a deadlock + * situation is to block the thread this function is called from, until the main thread + * has found time to handle the frame. If it is blocking while the main thread decides to + * stop/delete the MediaObject you might get a deadlock. + */ + virtual void frameReady(const VideoFrame2 &) = 0; + + /** + * This function is called after the last frameReady of a MediaObject was called. + */ + virtual void endOfMedia() = 0; + + void setRunning(bool running); + void start(); + void stop(); + + protected: + AbstractVideoDataOutput(AbstractVideoDataOutputPrivate &dd); +}; + +} // namespace Experimental +} //namespace Phonon + +#endif // PHONON_X_ABSTRACTVIDEODATAOUTPUT_H diff --git a/src/3rdparty/phonon/phonon/experimental/abstractvideodataoutput_p.h b/src/3rdparty/phonon/phonon/experimental/abstractvideodataoutput_p.h new file mode 100644 index 0000000..268abd4 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/abstractvideodataoutput_p.h @@ -0,0 +1,50 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ +#ifndef PHONON_X_ABSTRACTVIDEODATAOUTPUT_P_H +#define PHONON_X_ABSTRACTVIDEODATAOUTPUT_P_H + +#include "abstractvideodataoutput.h" +#include "../abstractvideooutput_p.h" +#include + +namespace Phonon +{ +namespace Experimental +{ + +class AbstractVideoDataOutputPrivate : public Phonon::AbstractVideoOutputPrivate +{ + Q_DECLARE_PUBLIC(AbstractVideoDataOutput) + protected: + virtual bool aboutToDeleteBackendObject(); + virtual void createBackendObject(); + void setupBackendObject(); + + private: + bool isRunning; + QSet allowedFormats; +}; + +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_X_ABSTRACTVIDEODATAOUTPUT_P_H diff --git a/src/3rdparty/phonon/phonon/experimental/audiodataoutput.cpp b/src/3rdparty/phonon/phonon/experimental/audiodataoutput.cpp new file mode 100644 index 0000000..62b3b87 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/audiodataoutput.cpp @@ -0,0 +1,74 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ +#include "audiodataoutput.h" +#include "audiodataoutput_p.h" +#include "factory_p.h" + +#define PHONON_CLASSNAME AudioDataOutput + +namespace Phonon +{ +namespace Experimental +{ + +PHONON_HEIR_IMPL(AbstractAudioOutput) + +PHONON_GETTER(Phonon::Experimental::AudioDataOutput::Format, format, d->format) +PHONON_GETTER(int, dataSize, d->dataSize) +PHONON_GETTER(int, sampleRate, -1) +PHONON_SETTER(setFormat, format, Phonon::Experimental::AudioDataOutput::Format) +PHONON_SETTER(setDataSize, dataSize, int) + +bool AudioDataOutputPrivate::aboutToDeleteBackendObject() +{ + Q_ASSERT(m_backendObject); + pBACKEND_GET(Phonon::Experimental::AudioDataOutput::Format, format, "format"); + pBACKEND_GET(int, dataSize, "dataSize"); + + return AbstractAudioOutputPrivate::aboutToDeleteBackendObject(); +} + +void AudioDataOutputPrivate::setupBackendObject() +{ + Q_Q(AudioDataOutput); + Q_ASSERT(m_backendObject); + AbstractAudioOutputPrivate::setupBackendObject(); + + // set up attributes + pBACKEND_CALL1("setFormat", Phonon::Experimental::AudioDataOutput::Format, format); + pBACKEND_CALL1("setDataSize", int, dataSize); + QObject::connect(m_backendObject, + SIGNAL(dataReady(const QMap > &)), + q, SIGNAL(dataReady(const QMap > &))); + QObject::connect(m_backendObject, + SIGNAL(dataReady(const QMap > &)), + q, SIGNAL(dataReady(const QMap > &))); + QObject::connect(m_backendObject, SIGNAL(endOfMedia(int)), q, SIGNAL(endOfMedia(int))); +} + +} // namespace Experimental +} // namespace Phonon + +#include "audiodataoutput.moc" + +#undef PHONON_CLASSNAME +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/experimental/audiodataoutput.h b/src/3rdparty/phonon/phonon/experimental/audiodataoutput.h new file mode 100644 index 0000000..f9547d3 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/audiodataoutput.h @@ -0,0 +1,189 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2006 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ +#ifndef Phonon_AUDIODATAOUTPUT_H +#define Phonon_AUDIODATAOUTPUT_H + +#include "export.h" +#include "../abstractaudiooutput.h" +#include "../phonondefs.h" + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template class QVector; +template class QMap; +#endif + +namespace Phonon +{ +namespace Experimental +{ + class AudioDataOutputPrivate; + + /** + * \short This class gives you the audio data (for visualizations). + * + * This class implements a special AbstractAudioOutput that gives your + * application the audio data. Don't expect realtime performance. But + * the latencies should be low enough to use the audio data for + * visualizations. You can also use the audio data for further processing + * (e.g. encoding and saving to a file). + * + * The class supports different data formats. One of the most common formats + * is to read vectors of integers (which will only use 16 Bit), but you can + * also request floats which some backends use internally. + * + * \author Matthias Kretz + */ + class PHONONEXPERIMENTAL_EXPORT AudioDataOutput : public AbstractAudioOutput + { + Q_OBJECT + K_DECLARE_PRIVATE(AudioDataOutput) + Q_ENUMS(Channel Format) + Q_PROPERTY(Format format READ format WRITE setFormat) + Q_PROPERTY(int dataSize READ dataSize WRITE setDataSize) + PHONON_HEIR(AudioDataOutput) + public: + /** + * Specifies the channel the audio data belongs to. + */ + enum Channel + { + LeftChannel, + RightChannel, + CenterChannel, + LeftSurroundChannel, + RightSurroundChannel, + SubwooferChannel + }; + + /** + * Used for telling the object whether you want 16 bit Integers or + * 32 bit floats. + * + * \see requestFormat + */ + enum Format + { + /** + * Requests 16 bit signed integers. + * + * \see dataReady(const QVector &) + */ + IntegerFormat = 1, + /** + * Requests 32 bit floating point: signed, zero centered, and + * normalized to the unit value (-1.0 to 1.0). + * + * \see dataReady(const QVector &) + */ + FloatFormat = 2 + }; + + /** + * Returns the currently used format. + * + * \see setFormat + */ + Format format() const; + + /** + * Returns the currently used number of samples passed through + * the signal. + * + * \see setDataSize + */ + int dataSize() const; + + /** + * Returns the sample rate in Hz. Common sample rates are 44100 Hz + * and 48000 Hz. AudioDataOutput will not do any sample rate + * conversion for you. If you need to convert the sample rate you + * might want to take a look at libsamplerate. For visualizations it + * is often enough to do simple interpolation or even drop/duplicate + * samples. + * + * \return The sample rate as reported by the backend. If the + * backend is unavailable -1 is returned. + */ + int sampleRate() const; + + public Q_SLOTS: + /** + * Requests the dataformat you'd like to receive. Only one of the + * signals of this class will be emitted when new data is ready. + * + * The default format is IntegerFormat. + * + * \see format() + */ + void setFormat(Format format); + + /** + * Sets the number of samples to be passed in one signal emission. + * + * Defaults to 512 samples per emitted signal. + * + * \param size the number of samples + */ + void setDataSize(int size); + + Q_SIGNALS: + /** + * Emitted whenever another dataSize number of samples are ready and + * format is set to IntegerFormat. + * + * If format is set to FloatFormat the signal is not emitted at all. + * + * \param data A mapping of Channel to a vector holding the audio data. + */ + void dataReady(const QMap > &data); + + /** + * Emitted whenever another dataSize number of samples are ready and + * format is set to FloatFormat. + * + * If format is set to IntegerFormat the signal is not emitted at all. + * + * \param data A mapping of Channel to a vector holding the audio data. + */ + void dataReady(const QMap > &data); + + /** + * This signal is emitted before the last dataReady signal of a + * media is emitted. + * + * If, for example, the playback of a media file has finished and the + * last audio data of that file is going to be passed with the next + * dataReady signal, and only the 28 first samples of the data + * vector are from that media file endOfMedia will be emitted right + * before dataReady with \p remainingSamples = 28. + * + * \param remainingSamples The number of samples in the next + * dataReady vector that belong to the media that was playing to + * this point. + */ + void endOfMedia(int remainingSamples); + }; +} // namespace Experimental +} // namespace Phonon + +// vim: sw=4 ts=4 tw=80 +#endif // Phonon_AUDIODATAOUTPUT_H diff --git a/src/3rdparty/phonon/phonon/experimental/audiodataoutput_p.h b/src/3rdparty/phonon/phonon/experimental/audiodataoutput_p.h new file mode 100644 index 0000000..9cbfcc3 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/audiodataoutput_p.h @@ -0,0 +1,53 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef AUDIODATAOUTPUT_P_H +#define AUDIODATAOUTPUT_P_H + +#include "audiodataoutput.h" +#include "../abstractaudiooutput_p.h" + +namespace Phonon +{ +namespace Experimental +{ + +class AudioDataOutputPrivate : public AbstractAudioOutputPrivate +{ + Q_DECLARE_PUBLIC(AudioDataOutput) + PHONON_PRIVATECLASS + protected: + AudioDataOutputPrivate() + : format(AudioDataOutput::IntegerFormat) + , dataSize(512) + { + } + + AudioDataOutput::Format format; + int dataSize; +}; + +} // namespace Experimental +} // namespace Phonon + +#endif // AUDIODATAOUTPUT_P_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/experimental/audiodataoutputinterface.h b/src/3rdparty/phonon/phonon/experimental/audiodataoutputinterface.h new file mode 100644 index 0000000..866c7a2 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/audiodataoutputinterface.h @@ -0,0 +1,47 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_X_AUDIODATAOUTPUTINTERFACE_H +#define PHONON_X_AUDIODATAOUTPUTINTERFACE_H + +namespace Phonon +{ +namespace Experimental +{ + +class AbstractAudioDataOutput; + +class AudioDataOutputInterface +{ + public: + virtual ~AudioDataOutputInterface() {} + + virtual AbstractAudioDataOutput *frontendObject() const = 0; + virtual void setFrontendObject(AbstractAudioDataOutput *) = 0; +}; + +} // namespace Experimental +} // namespace Phonon + +Q_DECLARE_INTERFACE(Phonon::Experimental::AudioDataOutputInterface, "0AudioDataOutputInterface.phonon.kde.org") + +#endif // PHONON_X_AUDIODATAOUTPUTINTERFACE_H diff --git a/src/3rdparty/phonon/phonon/experimental/audioformat.cpp b/src/3rdparty/phonon/phonon/experimental/audioformat.cpp new file mode 100644 index 0000000..502e0b0 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/audioformat.cpp @@ -0,0 +1,111 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#include "audioformat.h" + +namespace Phonon +{ +namespace Experimental +{ + +class AudioFormatPrivate +{ + Q_DECLARE_PUBLIC(AudioFormat) + protected: + AudioFormat *q_ptr; +}; + +AudioFormat::AudioFormat(int sampleRate, int channelCount, Phonon::Experimental::BitRate bitRate, QSysInfo::Endian byteOrder) +{ + s.m_sampleRate = sampleRate; + s.m_channelCount = channelCount; + s.m_bitRate = bitRate; + s.m_byteOrder = byteOrder; +} + +AudioFormat::~AudioFormat() +{ +} + +int AudioFormat::sampleRate() const +{ + return s.m_sampleRate; +} + +int AudioFormat::channelCount() const +{ + return s.m_channelCount; +} + +Phonon::Experimental::BitRate AudioFormat::bitRate() const +{ + return s.m_bitRate; +} + +QSysInfo::Endian AudioFormat::byteOrder() const +{ + return s.m_byteOrder; +} + +AudioFormat::AudioFormat(const AudioFormat &f) +{ + s.m_sampleRate = f.sampleRate(); + s.m_channelCount = f.channelCount(); + s.m_bitRate = f.bitRate(); + s.m_byteOrder = f.byteOrder(); +} + +AudioFormat &AudioFormat::operator=(const AudioFormat &f) +{ + s.m_sampleRate = f.sampleRate(); + s.m_channelCount = f.channelCount(); + s.m_bitRate = f.bitRate(); + s.m_byteOrder = f.byteOrder(); + return *this; +} + +bool AudioFormat::operator==(const AudioFormat &f) const +{ + return s.m_sampleRate == f.sampleRate() && + s.m_channelCount == f.channelCount() && + s.m_bitRate == f.bitRate() && + s.m_byteOrder == f.byteOrder(); +} + +bool AudioFormat::operator<(const AudioFormat &f) const +{ + return s.m_bitRate < f.bitRate() || + (s.m_bitRate == f.bitRate() && (s.m_sampleRate < f.sampleRate() || + (s.m_sampleRate == f.sampleRate() && (s.m_channelCount < f.channelCount() || + (s.m_channelCount == f.channelCount() && s.m_byteOrder != QSysInfo::ByteOrder && f.byteOrder() == QSysInfo::ByteOrder))))); +} + +quint32 AudioFormat::key() const +{ + return (s.m_byteOrder == QSysInfo::ByteOrder ? 1 : 0) + // 1 bit least significant + (s.m_channelCount << 1) + // give it 8 bits + (s.m_sampleRate) + // 192kHz ~ 18 bits (let the (unimportant) lower 9 bits overlap with channels + byteOrder) + (s.m_bitRate << 18); // most significant +} + +} // namespace Experimental +} // namespace Phonon diff --git a/src/3rdparty/phonon/phonon/experimental/audioformat.h b/src/3rdparty/phonon/phonon/experimental/audioformat.h new file mode 100644 index 0000000..ee19e44 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/audioformat.h @@ -0,0 +1,100 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_X_AUDIOFORMAT_H +#define PHONON_X_AUDIOFORMAT_H + +#include +#include "phononnamespace.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ +namespace Experimental +{ + +class AudioFormatPrivate; +class AudioFormat +{ + //Q_DECLARE_PRIVATE(AudioFormat) + public: + AudioFormat(int sampleRate = 48000, int channelCount = 2, Phonon::Experimental::BitRate bitRate = Phonon::Experimental::Signed16Bit, QSysInfo::Endian byteOrder = QSysInfo::ByteOrder); + AudioFormat(const AudioFormat &); + ~AudioFormat(); + + AudioFormat &operator=(const AudioFormat &); + + int sampleRate() const; + int channelCount() const; + Phonon::Experimental::BitRate bitRate() const; + QSysInfo::Endian byteOrder() const; + + bool operator==(const AudioFormat &) const; + inline bool operator!=(const AudioFormat &f) const { return !operator==(f); } + + /** + * ess than operator for sorting: + * A Format is considered smaller if + * - smaller bit rate + * - smaller sample rate + * - less channels + * - non-native byte order + */ + bool operator<(const AudioFormat &) const; + + quint32 key() const; + + private: + union + { + struct + { + int m_sampleRate; + int m_channelCount; + Phonon::Experimental::BitRate m_bitRate; + QSysInfo::Endian m_byteOrder; + } s; + // for future use: + AudioFormatPrivate *d_ptr; + }; +}; + +inline uint qHash(const AudioFormat &p) +{ + return p.key(); +} + +} // namespace Experimental +} // namespace Phonon + +#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 +//this ensures that code outside Phonon can use the hash function +//it also a workaround for some compilers +inline uint qHash(const Phonon::Experimental::AudioFormat &p) { return Phonon::Experimental::qHash(p); } //krazy:exclude=inline +#endif + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_X_AUDIOFORMAT_H diff --git a/src/3rdparty/phonon/phonon/experimental/audiowriter.h b/src/3rdparty/phonon/phonon/experimental/audiowriter.h new file mode 100644 index 0000000..36c44c4 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/audiowriter.h @@ -0,0 +1,61 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_AUDIOWRITER_H +#define PHONON_AUDIOWRITER_H + +#include "export.h" +#include "../abstractaudiooutput.h" +#include "../phonondefs.h" + +namespace Phonon +{ +namespace Experimental +{ + +class AudioWriterPrivate; +class PHONONEXPERIMENTAL_EXPORT AudioWriter : public AbstractAudioOutput +{ + Q_OBJECT + K_DECLARE_PRIVATE(AudioWriter) + PHONON_HEIR(AudioWriter) + /** + * This property defines the codec to be used for encoding the audio signal. + * Possible codecs can be retrieved from BackendCapabilities using the + * availableAudioCodecs() function. + * + * The default codec is an invalid codec (audioCodec().isValid() == false) + */ + Q_PROPERTY(AudioCodec audioCodec READ audioCodec WRITE setAudioCodec) + public: + AudioCodec audioCodec() const; + + public Q_SLOTS: + setAudioCodec(AudioCodec audioCodec); + // codec parameters? reuse EffectParameter class? +}; + +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_AUDIOWRITER_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/experimental/avcapture.cpp b/src/3rdparty/phonon/phonon/experimental/avcapture.cpp new file mode 100644 index 0000000..570ed7e --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/avcapture.cpp @@ -0,0 +1,131 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2006, 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#include "avcapture.h" +#include "avcaptureinterface.h" +#include "avcapture_p.h" +#include "factory_p.h" +#include "objectdescription.h" +#include "globalconfig.h" + +#define PHONON_CLASSNAME AvCapture +#define PHONON_INTERFACENAME AvCaptureInterface + +namespace Phonon +{ +namespace Experimental +{ +PHONON_OBJECT_IMPL + +void AvCapture::start() +{ + K_D(AvCapture); + if (d->backendObject()) { + INTERFACE_CALL(start()); + } +} + +void AvCapture::stop() +{ + K_D(AvCapture); + if (d->backendObject()) { + INTERFACE_CALL(stop()); + } +} + +AudioCaptureDevice AvCapture::audioCaptureDevice() const +{ + K_D(const AvCapture); + if (d->m_backendObject) { + return INTERFACE_CALL(audioCaptureDevice()); + } + return d->audioCaptureDevice; +} + +void AvCapture::setAudioCaptureDevice(const AudioCaptureDevice &audioCaptureDevice) +{ + K_D(AvCapture); + d->audioCaptureDevice = audioCaptureDevice; + if (d->m_backendObject) { + INTERFACE_CALL(setAudioCaptureDevice(d->audioCaptureDevice)); + } +} + +void AvCapture::setAudioCaptureDevice(Phonon::Category category) +{ + K_D(AvCapture); + d->audioCaptureDevice = AudioCaptureDevice::fromIndex(GlobalConfig().audioCaptureDeviceFor(category)); + if (d->m_backendObject) { + INTERFACE_CALL(setAudioCaptureDevice(d->audioCaptureDevice)); + } +} + +VideoCaptureDevice AvCapture::videoCaptureDevice() const +{ + K_D(const AvCapture); + if (d->m_backendObject) { + return INTERFACE_CALL(videoCaptureDevice()); + } + return d->videoCaptureDevice; +} + +void AvCapture::setVideoCaptureDevice(const VideoCaptureDevice &videoCaptureDevice) +{ + K_D(AvCapture); + d->videoCaptureDevice = videoCaptureDevice; + if (d->m_backendObject) { + INTERFACE_CALL(setVideoCaptureDevice(d->videoCaptureDevice)); + } +} + +void AvCapture::setVideoCaptureDevice(Phonon::Category category) +{ + K_D(AvCapture); + d->videoCaptureDevice = VideoCaptureDevice::fromIndex(GlobalConfig().videoCaptureDeviceFor(category)); + if (d->m_backendObject) { + INTERFACE_CALL(setVideoCaptureDevice(d->videoCaptureDevice)); + } +} + +bool AvCapturePrivate::aboutToDeleteBackendObject() +{ + audioCaptureDevice = pINTERFACE_CALL(audioCaptureDevice()); + videoCaptureDevice = pINTERFACE_CALL(videoCaptureDevice()); + return true; +} + +void AvCapturePrivate::setupBackendObject() +{ + Q_ASSERT(m_backendObject); + + // set up attributes + pINTERFACE_CALL(setAudioCaptureDevice(audioCaptureDevice)); + pINTERFACE_CALL(setVideoCaptureDevice(videoCaptureDevice)); +} + +} // namespace Experimental +} // namespace Phonon + +#include "moc_avcapture.cpp" + +#undef PHONON_CLASSNAME +#undef PHONON_INTERFACENAME diff --git a/src/3rdparty/phonon/phonon/experimental/avcapture.h b/src/3rdparty/phonon/phonon/experimental/avcapture.h new file mode 100644 index 0000000..cf3e6bf --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/avcapture.h @@ -0,0 +1,123 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2006, 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ +#ifndef PHONON_EXPERIMENTAL_AVCAPTURE_H +#define PHONON_EXPERIMENTAL_AVCAPTURE_H + +#include "export.h" +#include "../medianode.h" +#include "../phonondefs.h" +#include "objectdescription.h" +#include "../phononnamespace.h" + +class QString; +class QStringList; + +namespace Phonon +{ +namespace Experimental +{ + + class AvCapturePrivate; + + /** + * @short Media data from a soundcard, soundserver, camera or any other + * hardware device supported by the backend. + * + * This class gives you access to the capture capabilities of the backend. + * There might be more than only one possible capture source, for audio, as + * well as for video. The list of available sources is available through + * BackendCapabilities::availableAudioCaptureDevices and + * BackendCapabilities::availableVideoCaptureDevices. + * + * @ingroup Recording + * @author Matthias Kretz + * @see BackendCapabilities::availableAudioCaptureDevices + * @see BackendCapabilities::availableVideoCaptureDevices + */ + class PHONONEXPERIMENTAL_EXPORT AvCapture : public QObject, public Phonon::MediaNode + { + Q_OBJECT + K_DECLARE_PRIVATE(AvCapture) + PHONON_OBJECT(AvCapture) + Q_PROPERTY(AudioCaptureDevice audioCaptureDevice READ audioCaptureDevice WRITE setAudioCaptureDevice) + Q_PROPERTY(VideoCaptureDevice videoCaptureDevice READ videoCaptureDevice WRITE setVideoCaptureDevice) + public: + /** + * Returns the currently used capture source for the audio signal. + * + * @see AudioCaptureDevice + * @see setAudioCaptureDevice(const AudioCaptureDevice &) + * @see setAudioCaptureDevice(int) + */ + AudioCaptureDevice audioCaptureDevice() const; + + /** + * Returns the currently used capture source for the video signal. + * + * @see VideoCaptureDevice + * @see setVideoCaptureDevice(const VideoCaptureDevice &) + * @see setVideoCaptureDevice(int) + */ + VideoCaptureDevice videoCaptureDevice() const; + + /** + * Sets the audio capture source to use. + * + * @param source An object of class AudioCaptureDevice. A list of + * available objects can be queried from + * BackendCapabilities::availableAudioCaptureDevices. + * + * @see audioCaptureDevice + * @see setAudioCaptureDevice(int) + */ + void setAudioCaptureDevice(const AudioCaptureDevice &source); + void setAudioCaptureDevice(Phonon::Category category); + + /** + * Sets the video capture source to use. + * + * @param source An object of class VideoCaptureDevice. A list of + * available objects can be queried from + * BackendCapabilities::availableVideoCaptureDevices. + * + * @see videoCaptureDevice + * @see setVideoCaptureDevice(int) + */ + void setVideoCaptureDevice(const VideoCaptureDevice &source); + void setVideoCaptureDevice(Phonon::Category category); + + public Q_SLOTS: + /** + * Start capture. + */ + void start(); + + /** + * Stop capture. + */ + void stop(); + }; + +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_EXPERIMENTAL_AVCAPTURE_H diff --git a/src/3rdparty/phonon/phonon/experimental/avcapture_p.h b/src/3rdparty/phonon/phonon/experimental/avcapture_p.h new file mode 100644 index 0000000..34627ed --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/avcapture_p.h @@ -0,0 +1,49 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef AVCAPTURE_P_H +#define AVCAPTURE_P_H + +#include "avcapture.h" +#include "../medianode_p.h" +#include "../phonondefs_p.h" + +namespace Phonon +{ +namespace Experimental +{ + +class AvCapturePrivate : public MediaNodePrivate +{ + Q_DECLARE_PUBLIC(AvCapture) + PHONON_PRIVATECLASS + public: + protected: + AudioCaptureDevice audioCaptureDevice; + VideoCaptureDevice videoCaptureDevice; +}; + +} // namespace Experimental +} // namespace Phonon + +#endif // AVCAPTURE_P_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/experimental/avcaptureinterface.h b/src/3rdparty/phonon/phonon/experimental/avcaptureinterface.h new file mode 100644 index 0000000..1641769 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/avcaptureinterface.h @@ -0,0 +1,50 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_EXPERIMENTAL_AVCAPTUREINTERFACE_H +#define PHONON_EXPERIMENTAL_AVCAPTUREINTERFACE_H + +namespace Phonon +{ +namespace Experimental +{ + +class AvCaptureInterface +{ + public: + virtual ~AvCaptureInterface() {} + + virtual void start() = 0; + virtual void stop() = 0; + + virtual AudioCaptureDevice audioCaptureDevice() const = 0; + virtual VideoCaptureDevice videoCaptureDevice() const = 0; + virtual void setAudioCaptureDevice(const AudioCaptureDevice &) = 0; + virtual void setVideoCaptureDevice(const VideoCaptureDevice &) = 0; +}; + +} // namespace Experimental +} // namespace Phonon + +Q_DECLARE_INTERFACE(Phonon::Experimental::AvCaptureInterface, "0AvCaptureInterface.Phonon.kde.org") + +#endif // PHONON_EXPERIMENTAL_AVCAPTUREINTERFACE_H diff --git a/src/3rdparty/phonon/phonon/experimental/avwriter.cpp b/src/3rdparty/phonon/phonon/experimental/avwriter.cpp new file mode 100644 index 0000000..3019580 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/avwriter.cpp @@ -0,0 +1,43 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#include "avwriter.h" +#include "avwriter_p.h" + +namespace Phonon +{ +namespace Experimental +{ + +AvWriter::AvWriter(QObject *parent) + : QObject(parent) + , k_ptr(new AvWriterPrivate) +{ + K_D(AvWriter); + d->q_ptr = this; +} + +} // namespace Experimental +} // namespace Phonon + +#include "avwriter.moc" +// vim: sw=4 ts=4 diff --git a/src/3rdparty/phonon/phonon/experimental/avwriter.h b/src/3rdparty/phonon/phonon/experimental/avwriter.h new file mode 100644 index 0000000..3f0facf --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/avwriter.h @@ -0,0 +1,86 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_AVWRITER_H +#define PHONON_AVWRITER_H + +#include "export.h" +#include "../phonondefs.h" +#include "../abstractaudiooutput.h" +#include "../abstractvideooutput.h" + +namespace Phonon +{ +namespace Experimental +{ + +class AvWriterPrivate; + +//TODO: +// Container formats can support multiple audio, video and subtitle streams, a +// control track (menus) and chapters. Anything else? +// How should those features be mapped to this API? Multiple audio and video +// streams should be covered already. Are the subtitle streams implicit +// depending on the source material? +// Chapters: call a method when to add a chapter? How does that map to a +// specific frame/sample? Chapter support is probably overkill for Phonon. +class PHONONEXPERIMENTAL_EXPORT AvWriter : public QObject +{ + Q_OBJECT + K_DECLARE_PRIVATE(AvWriter) + Q_PROPERTY(ContainerFormat containerFormat READ containerFormat WRITE setContainerFormat) + Q_PROPERTY(KUrl url READ url WRITE setUrl) + public: + /** + * Standard QObject constructor. + * + * \param parent QObject parent + */ + AvWriter(QObject *parent); + + KUrl url() const; + setUrl(const KUrl &url); + + /** + * Creates a new AudioWriter object to be used for sending the audio + * data to this file + * + * \param streamName A name identifying the stream. Often this name is + * used for the language identifier. + * + * \return Returns the new AudioWriter object or 0 if the container + * format does not support multiple audio streams. + */ + AudioWriter *addAudioStream(const QString &streamName); + VideoWriter *addVideoStream(const QString &streamName); + + ContainerFormat containerFormat() const; + + public Q_SLOTS: + void setContainerFormat(ContainerFormat format); +}; + +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_AVWRITER_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/experimental/avwriter_p.h b/src/3rdparty/phonon/phonon/experimental/avwriter_p.h new file mode 100644 index 0000000..8f42479 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/avwriter_p.h @@ -0,0 +1,44 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_AVWRITER_P_H +#define PHONON_AVWRITER_P_H + +#include "rtpsender.h" + +namespace Phonon +{ +namespace Experimental +{ + +class AvWriterPrivate +{ + Q_DECLARE_PUBLIC(AvWriter) + protected: + AvWriter *q_ptr; +}; + +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_AVWRITER_P_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/experimental/backendcapabilities.cpp b/src/3rdparty/phonon/phonon/experimental/backendcapabilities.cpp new file mode 100644 index 0000000..331c6d6 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/backendcapabilities.cpp @@ -0,0 +1,41 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This program 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 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), Nokia Corporation (or its successors, + if any) and the KDE Free Qt Foundation, which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program 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 this program. If not, see . + +*/ +#include "backendcapabilities.h" +#include "globalconfig.h" + +namespace Phonon +{ +namespace Experimental +{ + +QList BackendCapabilities::availableVideoCaptureDevices() +{ + QList ret; + const QList deviceIndexes = GlobalConfig().videoCaptureDeviceListFor(Phonon::NoCategory); + foreach (int i, deviceIndexes) { + ret.append(VideoCaptureDevice::fromIndex(i)); + } + return ret; +} + +} // namespace Experimental +} // namespace Phonon diff --git a/src/3rdparty/phonon/phonon/experimental/backendcapabilities.h b/src/3rdparty/phonon/phonon/experimental/backendcapabilities.h new file mode 100644 index 0000000..2a63f73 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/backendcapabilities.h @@ -0,0 +1,46 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ +#ifndef PHONON_EXPERIMENTAL_BACKENDCAPABILITIES_H +#define PHONON_EXPERIMENTAL_BACKENDCAPABILITIES_H + +#include "export.h" +#include "objectdescription.h" + +namespace Phonon +{ +namespace Experimental +{ +namespace BackendCapabilities +{ + + /** + * Returns the video capture devices the backend supports. + * + * \return A list of VideoCaptureDevice objects that give a name and + * description for every supported video capture device. + */ + PHONONEXPERIMENTAL_EXPORT QList availableVideoCaptureDevices(); + +} // namespace BackendCapabilities +} // namespace Experimental +} // namespace Phonon +#endif // PHONON_EXPERIMENTAL_BACKENDCAPABILITIES_H diff --git a/src/3rdparty/phonon/phonon/experimental/backendinterface.h b/src/3rdparty/phonon/phonon/experimental/backendinterface.h new file mode 100644 index 0000000..1590dc1 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/backendinterface.h @@ -0,0 +1,41 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ +#ifndef PHONON_EXPERIMENTAL_BACKENDINTERFACE_H +#define PHONON_EXPERIMENTAL_BACKENDINTERFACE_H + +namespace Phonon +{ +namespace Experimental +{ +namespace BackendInterface +{ +enum Class { + VideoDataOutputClass = 0x10000, + AudioDataOutputClass, + VisualizationClass, + AvCaptureClass +}; +} // namespace BackendInterface +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_EXPERIMENTAL_BACKENDINTERFACE_H diff --git a/src/3rdparty/phonon/phonon/experimental/export.h b/src/3rdparty/phonon/phonon/experimental/export.h new file mode 100644 index 0000000..2ca8fba --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/export.h @@ -0,0 +1,39 @@ +/* This file is part of the KDE project + Copyright (C) 2007 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_EXPERIMENTAL_EXPORT_H +#define PHONON_EXPERIMENTAL_EXPORT_H + +/* needed for KDE_EXPORT and KDE_IMPORT macros */ +#include + +#ifndef PHONONEXPERIMENTAL_EXPORT +# if defined(MAKE_PHONONEXPERIMENTAL_LIB) + /* We are building this library */ +# define PHONONEXPERIMENTAL_EXPORT Q_DECL_EXPORT +# else + /* We are using this library */ +# define PHONONEXPERIMENTAL_EXPORT Q_DECL_IMPORT +# endif +#endif + +#endif diff --git a/src/3rdparty/phonon/phonon/experimental/factory.cpp b/src/3rdparty/phonon/phonon/experimental/factory.cpp new file mode 100644 index 0000000..f2b7daf --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/factory.cpp @@ -0,0 +1,129 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This program 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 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), Nokia Corporation (or its successors, + if any) and the KDE Free Qt Foundation, which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program 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 this program. If not, see . + +*/ + +#include "factory_p.h" +#include "objectdescription.h" +#include "../factory_p.h" +#include "../globalstatic_p.h" +#include "../backendinterface.h" +#include "backendinterface.h" +#include + +namespace Phonon +{ +namespace Experimental +{ + +class FactoryPrivate : public Phonon::Experimental::Factory::Sender +{ + public: + FactoryPrivate(); + ~FactoryPrivate(); + //QPointer m_backendObject; + + private Q_SLOTS: + void objectDescriptionChanged(ObjectDescriptionType); +}; + +PHONON_GLOBAL_STATIC(Phonon::Experimental::FactoryPrivate, globalFactory) + +FactoryPrivate::FactoryPrivate() +{ + QObject *backendObj = Phonon::Factory::backend(); + Q_ASSERT(backendObj); + //QMetaObject::invokeMethod(backendObj, "experimentalBackend", Qt::DirectConnection, + //Q_RETURN_ARG(QObject *, m_backendObject)); + //if (!m_backendObject) { + //qDebug() << "The backend does not support Phonon::Experimental"; + //return; + //} + connect(backendObj, SIGNAL(objectDescriptionChanged(ObjectDescriptionType)), + SLOT(objectDescriptionChanged(ObjectDescriptionType))); +} + +FactoryPrivate::~FactoryPrivate() +{ +} + +void FactoryPrivate::objectDescriptionChanged(ObjectDescriptionType type) +{ + qDebug() << Q_FUNC_INFO << type; + switch (type) { + case VideoCaptureDeviceType: + emit availableVideoCaptureDevicesChanged(); + break; + default: + break; + } +} + +Factory::Sender *Factory::sender() +{ + return globalFactory; +} + +QObject *Factory::createAudioDataOutput(QObject *parent) +{ + Phonon::BackendInterface *b = qobject_cast(Phonon::Factory::backend()); + if (b) { + return Phonon::Factory::registerQObject(b->createObject( + static_cast(Phonon::BackendInterface::AudioDataOutputClass), + parent)); + } + return 0; +} + +QObject *Factory::createVideoDataOutput(QObject *parent) +{ + Phonon::BackendInterface *b = qobject_cast(Phonon::Factory::backend()); + if (b) { + return Phonon::Factory::registerQObject(b->createObject( + static_cast(Phonon::Experimental::BackendInterface::VideoDataOutputClass), + parent)); + } + return 0; +} + +QObject *Factory::createAvCapture(QObject *parent) +{ + Phonon::BackendInterface *b = qobject_cast(Phonon::Factory::backend()); + if (b) { + return Phonon::Factory::registerQObject(b->createObject( + static_cast(Phonon::Experimental::BackendInterface::AvCaptureClass), + parent)); + } + return 0; +} + +QObject *Factory::createVisualization(QObject *parent) +{ + Phonon::BackendInterface *b = qobject_cast(Phonon::Factory::backend()); + if (b) { + return Phonon::Factory::registerQObject(b->createObject( + static_cast(Phonon::Experimental::BackendInterface::VisualizationClass), + parent)); + } + return 0; +} + +} // namespace Experimental +} // namespace Phonon diff --git a/src/3rdparty/phonon/phonon/experimental/factory_p.h b/src/3rdparty/phonon/phonon/experimental/factory_p.h new file mode 100644 index 0000000..68ab77b --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/factory_p.h @@ -0,0 +1,76 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ +#ifndef PHONON_EXPERIMENTAL_FACTORY_P_H +#define PHONON_EXPERIMENTAL_FACTORY_P_H + +#include +#include "export.h" + +namespace Phonon +{ +namespace Experimental +{ +namespace Factory +{ + /** + * Emits signals for Phonon::Experimental::Factory. + */ + class Sender : public QObject + { + Q_OBJECT + Q_SIGNALS: + /** + * \copydoc Phonon::Experimental::BackendCapabilities::Notifier::availableVideoCaptureDevicesChanged + */ + void availableVideoCaptureDevicesChanged(); + }; + + PHONONEXPERIMENTAL_EXPORT Sender *sender(); + + /** + * Create a new backend object for a AudioDataOutput. + * + * \return a pointer to the AudioDataOutput the backend provides. + */ + PHONONEXPERIMENTAL_EXPORT QObject *createAudioDataOutput(QObject *parent = 0); + + /** + * Create a new backend object for a VideoDataOutput. + * + * \return a pointer to the VideoDataOutput the backend provides. + */ + QObject *createVideoDataOutput(QObject *parent = 0); + + QObject *createAvCapture(QObject *parent = 0); + + /** + * Create a new backend object for a Visualization. + * + * \return a pointer to the Visualization the backend provides. + */ + PHONONEXPERIMENTAL_EXPORT QObject *createVisualization(QObject *parent = 0); + +} // namespace Factory +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_EXPERIMENTAL_FACTORY_P_H diff --git a/src/3rdparty/phonon/phonon/experimental/globalconfig.cpp b/src/3rdparty/phonon/phonon/experimental/globalconfig.cpp new file mode 100644 index 0000000..6f118c5 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/globalconfig.cpp @@ -0,0 +1,131 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#include "globalconfig.h" +#include "../globalconfig_p.h" + +#include "../factory_p.h" +#include "objectdescription.h" +#include "../phonondefs_p.h" +#include "../backendinterface.h" +#include "../qsettingsgroup_p.h" + +#include +#include + +namespace Phonon +{ +namespace Experimental +{ + +enum WhatToFilter { + FilterAdvancedDevices = 1, + FilterUnavailableDevices = 4 +}; + +static void filter(BackendInterface *backendIface, QList *list, int whatToFilter) +{ + QMutableListIterator it(*list); + while (it.hasNext()) { + const QHash properties = backendIface->objectDescriptionProperties( + static_cast(Phonon::Experimental::VideoCaptureDeviceType), it.next()); + QVariant var; + if (whatToFilter & FilterAdvancedDevices) { + var = properties.value("isAdvanced"); + if (var.isValid() && var.toBool()) { + it.remove(); + continue; + } + } + if (whatToFilter & FilterUnavailableDevices) { + var = properties.value("available"); + if (var.isValid() && !var.toBool()) { + it.remove(); + continue; + } + } + } +} + +QList GlobalConfig::videoCaptureDeviceListFor(Phonon::Category category, int override) const +{ + K_D(const GlobalConfig); + + //The devices need to be stored independently for every backend + const QSettingsGroup backendConfig(&d->config, QLatin1String("VideoCaptureDevice")); // + Factory::identifier()); + const QSettingsGroup generalGroup(&d->config, QLatin1String("General")); + const bool hideAdvancedDevices = ((override & AdvancedDevicesFromSettings) + ? generalGroup.value(QLatin1String("HideAdvancedDevices"), true) + : static_cast(override & HideAdvancedDevices)); + + //First we lookup the available devices directly from the backend + BackendInterface *backendIface = qobject_cast(Phonon::Factory::backend()); + if (!backendIface) { + return QList(); + } + + // this list already is in default order (as defined by the backend) + QList defaultList = backendIface->objectDescriptionIndexes(static_cast(Phonon::Experimental::VideoCaptureDeviceType)); + if (hideAdvancedDevices || (override & HideUnavailableDevices)) { + filter(backendIface, &defaultList, + (hideAdvancedDevices ? FilterAdvancedDevices : 0) | + ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0) + ); + } + + QString categoryKey = QLatin1String("Category") + QString::number(static_cast(category)); + if (!backendConfig.hasKey(categoryKey)) { + // no list in config for the given category + QString categoryKey = QLatin1String("Category") + QString::number(static_cast(Phonon::NoCategory)); + if (!backendConfig.hasKey(categoryKey)) { + // no list in config for NoCategory + return defaultList; + } + } + + //Now the list from d->config + QList deviceList = backendConfig.value(categoryKey, QList()); + + //if there are devices in d->config that the backend doesn't report, remove them from the list + QMutableListIterator i(deviceList); + while (i.hasNext()) { + if (0 == defaultList.removeAll(i.next())) { + i.remove(); + } + } + + //if the backend reports more devices that are not in d->config append them to the list + deviceList += defaultList; + + return deviceList; +} + +int GlobalConfig::videoCaptureDeviceFor(Phonon::Category category, int override) const +{ + QList ret = videoCaptureDeviceListFor(category, override); + if (ret.isEmpty()) + return -1; + return ret.first(); +} + +} // namespace Experimental +} // namespace Phonon diff --git a/src/3rdparty/phonon/phonon/experimental/globalconfig.h b/src/3rdparty/phonon/phonon/experimental/globalconfig.h new file mode 100644 index 0000000..8a5dba9 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/globalconfig.h @@ -0,0 +1,57 @@ +/* This file is part of the KDE project +Copyright (C) 2006-2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_EXPERIMENTAL_GLOBALCONFIG_P_H +#define PHONON_EXPERIMENTAL_GLOBALCONFIG_P_H + +#include +#include + +#include "../phononnamespace.h" +#include "../globalconfig.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ +namespace Experimental +{ + +class GlobalConfig : public Phonon::GlobalConfig +{ + K_DECLARE_PRIVATE(Phonon::GlobalConfig) +public: + QList videoCaptureDeviceListFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const; + int videoCaptureDeviceFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const; + +Q_SIGNALS: + void videoCaptureDeviceConfigChanged(); +}; + +} // namespace Experimental +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_EXPERIMENTAL_GLOBALCONFIG_P_H diff --git a/src/3rdparty/phonon/phonon/experimental/lockfreequeue.cpp b/src/3rdparty/phonon/phonon/experimental/lockfreequeue.cpp new file mode 100644 index 0000000..6153697 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/lockfreequeue.cpp @@ -0,0 +1,309 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#include "lockfreequeue_p.h" +#include +#include +#include +#include +#include "globalstatic_p.h" + +struct MemoryPool +{ + ~MemoryPool(); + // Stack structure: + QAtomicPointer stack; + QAtomicInt count; + QAtomicInt size; + + void clear(); +}; + +void MemoryPool::clear() +{ + LockFreeQueueBase::NodeBase *node = stack; + while (node) { + if (stack.testAndSetAcquire(node, const_cast(node->next))) { + count.deref(); + free(node); + } + node = stack; + } +} + +MemoryPool::~MemoryPool() +{ + LockFreeQueueBase::NodeBase *node = stack; + while (node) { + void *toDelete = node; + node = const_cast(node->next); + ::free(toDelete); + } +} + +struct MemoryPoolVector +{ + static const int POOL_COUNT = 16; + ~MemoryPoolVector() { delete next; } + inline MemoryPool &operator[](size_t s) + { + for (int i = 0; i < POOL_COUNT; ++i) { + if (m_pools[i].size == static_cast(s)) { + return m_pools[i]; + } else if (m_pools[i].size == 0) { + if (m_pools[i].size.testAndSetRelaxed(0, static_cast(s))) { + return m_pools[i]; + } + if (m_pools[i].size == static_cast(s)) { + return m_pools[i]; + } + } + } + if (!next) { + MemoryPoolVector *newPoolVector = new MemoryPoolVector; + if (!next.testAndSetRelaxed(0, newPoolVector)) { + delete newPoolVector; + } + } + return (*next)[s]; + } + + void clearAllPools() + { + for (int i = 0; i < POOL_COUNT; ++i) { + if (0 == m_pools[i].size) { + return; + } + m_pools[i].clear(); + } + if (next) { + next->clearAllPools(); + } + } + + MemoryPool m_pools[POOL_COUNT]; + QAtomicPointer next; +}; + +static int s_poolSize = 128; +PHONON_GLOBAL_STATIC(MemoryPoolVector, s_memoryPool) + +void *LockFreeQueueBase::NodeBaseKeepNodePool::operator new(size_t s) +{ + MemoryPool &p = (*s_memoryPool)[s]; + NodeBase *node = p.stack; + if (node) { + if (!p.stack.testAndSetAcquire(node, const_cast(node->next))) { + return ::malloc(s); + } + p.count.deref(); + return node; + } + return ::malloc(s); +} + +void LockFreeQueueBase::NodeBaseKeepNodePool::operator delete(void *ptr, size_t s) +{ + MemoryPool &p = (*s_memoryPool)[s]; + if (p.count > s_poolSize) { + ::free(ptr); + return; + } + NodeBase *node = static_cast(ptr); + NodeBase *next = p.stack; + node->next = next; + if (!p.stack.testAndSetOrdered(next, node)) { + ::free(ptr); + return; + } + p.count.ref(); +} + +void LockFreeQueueBase::NodeBaseKeepNodePool::clear() +{ + s_memoryPool->clearAllPools(); +} + +void LockFreeQueueBase::NodeBaseKeepNodePool::setPoolSize(int s) +{ + s_poolSize = s; +} + +int LockFreeQueueBase::NodeBaseKeepNodePool::poolSize() +{ + return s_poolSize; +} + +class LockFreeQueueBasePrivate +{ + public: + LockFreeQueueBasePrivate(); + ~LockFreeQueueBasePrivate(); + QReadWriteLock dataReadyHandlerMutex; + LockFreeQueueBase::NodeBase *sentinel; // end marker + LockFreeQueueBase::NodeBase *lastHeadNode; + QAtomicPointer queueHead; + QAtomicPointer queueTail; + QAtomicInt size; + LockFreeQueueBase::DataReadyHandler *dataReadyHandler; +}; + +LockFreeQueueBasePrivate::LockFreeQueueBasePrivate() + : sentinel(new LockFreeQueueBase::NodeBase(0)), + lastHeadNode(new LockFreeQueueBase::NodeBase(sentinel)), + queueHead(&lastHeadNode->next), + queueTail(&lastHeadNode->next), + size(0), + dataReadyHandler(0) +{ + // let d->sentinel point to itself so that we can use d->sentinel->next as + // QAtomicPointer for d->queueHead and d->queueTail + sentinel->next = sentinel; +} + +LockFreeQueueBasePrivate::~LockFreeQueueBasePrivate() +{ + Q_ASSERT(queueHead); + LockFreeQueueBase::NodeBase *node = lastHeadNode; + while (node != sentinel) { + LockFreeQueueBase::NodeBase *toDelete = node; + node = const_cast(node->next); + toDelete->deref(); + } +} + +LockFreeQueueBase::LockFreeQueueBase() + : d(new LockFreeQueueBasePrivate) +{ +} + +LockFreeQueueBase::~LockFreeQueueBase() +{ + delete d; +} + +void LockFreeQueueBase::setDataReadyHandler(DataReadyHandler *h) +{ + QWriteLocker lock(&d->dataReadyHandlerMutex); + d->dataReadyHandler = h; +} + +void LockFreeQueueBase::_enqueue(NodeBase *newNode) +{ + newNode->ref(); + newNode->next = d->sentinel; + /*if (d->size > 0 && newNode->priority > std::numeric_limits::min()) { + NodeBasePointer *node = d->queueHead.fetchAndStoreRelaxed(&d->sentinel->next); + if (node == &d->sentinel->next) { + // Another thread got the real node, we just got the placeholder telling us to not touch + // anything. As we replaced &d->sentinel->next with &d->sentinel->next in + // d->queueHead we don't have to reset anything. + } + // node is a pointer to a Node::next member pointing to the first entry in + // the list + if (*node == d->sentinel) { + // the list is empty, good + } + } else {*/ + // just append + NodeBasePointer &lastNextPointer = *d->queueTail.fetchAndStoreAcquire(&newNode->next); + lastNextPointer = newNode; + d->size.ref(); + + if (d->dataReadyHandler) { + QReadLocker lock(&d->dataReadyHandlerMutex); + if (d->dataReadyHandler) { + d->dataReadyHandler->dataReady(); + } + } + //} +} + +LockFreeQueueBase::NodeBase *LockFreeQueueBase::_acquireHeadNodeBlocking() +{ + NodeBasePointer *node = 0; + while (d->size > 0) { + if ((node = d->queueHead.fetchAndStoreRelaxed(&d->sentinel->next)) != &d->sentinel->next) { + // node is a pointer to a Node::next member pointing to the first entry in the list + if (*node != d->sentinel) { + d->size.deref(); + NodeBase *_node = const_cast(*node); // cast volatile away + _node->ref(); + + NodeBase *toDeref = d->lastHeadNode; + d->lastHeadNode = _node; + const bool check = d->queueHead.testAndSetRelease(&d->sentinel->next, &_node->next); + Q_ASSERT(check); Q_UNUSED(check); + toDeref->deref(); + + return _node; + } + // empty (d->size == 0), put it back + const bool check = d->queueHead.testAndSetRelaxed(&d->sentinel->next, node); + Q_ASSERT(check); Q_UNUSED(check); + // try again, with some luck d->size is > 0 again + } + } + return 0; +} + +LockFreeQueueBase::NodeBase *LockFreeQueueBase::_acquireHeadNode() +{ + if (*d->queueHead == d->sentinel || d->queueHead == &d->sentinel->next) { + return 0; + } + // setting d->queueHead to &d->sentinel->next makes the above check fail (i.e. all + // other threads in a dequeue function will exit). Also enqueue will not modify + // this as d->queueTail references d->lastHeadNode->next which != d->sentinel->next + NodeBasePointer *node = d->queueHead.fetchAndStoreRelaxed(&d->sentinel->next); + if (node == &d->sentinel->next) { + // Another thread got the real node, we just got the placeholder telling us to not touch + // anything. As we replaced &d->sentinel->next with &d->sentinel->next in + // d->queueHead we don't have to reset anything. + return 0; + } + // node is a pointer to a Node::next member pointing to the first entry in + // the list + if (*node == d->sentinel) { + //qDebug() << "empty, put it back"; + const bool check = d->queueHead.testAndSetRelaxed(&d->sentinel->next, node); + Q_ASSERT(check); Q_UNUSED(check); + return 0; + } + d->size.deref(); + + NodeBase *_node = const_cast(*node); + _node->ref(); + + NodeBase *toDeref = d->lastHeadNode; + d->lastHeadNode = _node; + const bool check = d->queueHead.testAndSetRelease(&d->sentinel->next, &_node->next); + Q_ASSERT(check); Q_UNUSED(check); + toDeref->deref(); + + return _node; +} + +int LockFreeQueueBase::size() const +{ + return d->size; +} diff --git a/src/3rdparty/phonon/phonon/experimental/lockfreequeue_p.h b/src/3rdparty/phonon/phonon/experimental/lockfreequeue_p.h new file mode 100644 index 0000000..dace7f0 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/lockfreequeue_p.h @@ -0,0 +1,156 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef LOCKFREEQUEUE_P_H +#define LOCKFREEQUEUE_P_H + +#include + +class LockFreeQueueBasePrivate; +struct MemoryPool; +class LockFreeQueueBase +{ + friend class LockFreeQueueBasePrivate; + public: + struct DataReadyHandler + { + virtual ~DataReadyHandler() {} + virtual void dataReady() = 0; + }; + + void setDataReadyHandler(DataReadyHandler *); + + int size() const; + bool isEmpty() const { return 0 == size(); } + + protected: + friend struct MemoryPool; + LockFreeQueueBase(); + ~LockFreeQueueBase(); + + public: + class NodeBase; + typedef volatile NodeBase * NodeBasePointer; + class NodeBase + { + public: + inline NodeBase(int p) : priority(p) {} + inline NodeBase(NodeBase *n) : next(n), priority(0) {} + NodeBasePointer next; + int priority; + + inline void ref() { refCount.ref(); } + inline void deref() { if (!refCount.deref()) delete this; } + + protected: + ~NodeBase() { Q_ASSERT(refCount == 0); } + private: + QAtomicInt refCount; + }; + + struct NodeBaseKeepNodePool : public NodeBase + { + inline NodeBaseKeepNodePool(int priority) : NodeBase(priority) {} + // allocation is a bottleneck in _enqueue + void *operator new(size_t s); + void operator delete(void *p, size_t s); + + static void clear(); + static void setPoolSize(int); + static int poolSize(); + }; + + typedef NodeBase StdNewDeleteMemoryManagement; + typedef NodeBaseKeepNodePool KeepNodePoolMemoryManagement; + protected: + + void _enqueue(NodeBase *); + NodeBase *_acquireHeadNode(); + NodeBase *_acquireHeadNodeBlocking(); + + LockFreeQueueBasePrivate *const d; + +}; + +template +class LockFreeQueue : public LockFreeQueueBase +{ + public: + enum BlockingSwitch { + BlockUnlessEmpty, + NeverBlock + }; + + struct Node : public MemoryManagementNodeBase + { + inline Node(const T &d, int priority) : MemoryManagementNodeBase(priority), data(d) {} + T data; + }; + + inline void enqueue(const T &data, int priority = 0) + { + _enqueue(new Node(data, 0)); + } + + inline void dequeue(QVector &data, BlockingSwitch block = BlockUnlessEmpty) + { + int count = 0; + while (count < data.capacity()) { + NodeBase *node = (block == NeverBlock) ? _acquireHeadNode() : _acquireHeadNodeBlocking(); + if (!node) { + break; + } + if (count < data.size()) { + data[count] = static_cast(node)->data; + } else { + data << static_cast(node)->data; + } + ++count; + node->deref(); + } + data.resize(count); + } + + inline bool dequeue(T *data, BlockingSwitch block = BlockUnlessEmpty) + { + NodeBase *node = (block == NeverBlock) ? _acquireHeadNode() : _acquireHeadNodeBlocking(); + if (node) { + *data = static_cast(node)->data; + node->deref(); + return true; + } + return false; + } + + inline LockFreeQueue &operator<<(const T &data) { enqueue(data); return *this; } + inline LockFreeQueue &operator>>(T &data) + { + NodeBase *node = _acquireHeadNodeBlocking(); + if (node) { + data = static_cast(node)->data; + node->deref(); + } + return *this; + } +}; + +#endif // LOCKFREEQUEUE_P_H diff --git a/src/3rdparty/phonon/phonon/experimental/mediasource.cpp b/src/3rdparty/phonon/phonon/experimental/mediasource.cpp new file mode 100644 index 0000000..1fd0d93 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/mediasource.cpp @@ -0,0 +1,79 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This program 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 2 of + the License or (at your option) version 3 or any later version + accepted by the membership of KDE e.V. (or its successor approved + by the membership of KDE e.V.), Nokia Corporation (or its successors, + if any) and the KDE Free Qt Foundation, which shall act as a proxy + defined in Section 14 of version 3 of the license. + + This program 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 this program. If not, see . + +*/ + +#include "mediasource.h" +#include "mediasource_p.h" + +#define S_D(Class) Class##Private *d = reinterpret_cast(Phonon::MediaSource::d.data()) + +namespace Phonon +{ +namespace Experimental +{ + +MediaSource::MediaSource(const MediaSource &rhs) + : Phonon::MediaSource(rhs) +{ +} + +MediaSource &MediaSource::operator=(const MediaSource &rhs) +{ + d = rhs.d; + return *this; +} + +bool MediaSource::operator==(const MediaSource &rhs) const +{ + return d == rhs.d; +} + +VideoCaptureDevice MediaSource::videoCaptureDevice() const +{ + S_D(const MediaSource); + return d->videoCaptureDevice; +} + +MediaSource::MediaSource(const VideoCaptureDevice &videoDevice) + : Phonon::MediaSource(*new MediaSourcePrivate(VideoCaptureDeviceSource)) +{ + S_D(MediaSource); + d->videoCaptureDevice = videoDevice; +} + +MediaSource::MediaSource(const QList &mediaList) + : Phonon::MediaSource(*new MediaSourcePrivate(Link)) +{ + S_D(MediaSource); + d->linkedSources = mediaList; + foreach (const Phonon::MediaSource &ms, mediaList) { + Q_ASSERT(static_cast(ms.type()) != Link); + } +} + +QList MediaSource::substreams() const +{ + S_D(MediaSource); + return d->linkedSources; +} + +} // namespace Experimental +} // namespace Phonon diff --git a/src/3rdparty/phonon/phonon/experimental/mediasource.h b/src/3rdparty/phonon/phonon/experimental/mediasource.h new file mode 100644 index 0000000..a68446f --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/mediasource.h @@ -0,0 +1,73 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_EXPERIMENTAL_MEDIASOURCE_H +#define PHONON_EXPERIMENTAL_MEDIASOURCE_H + +#include "../mediasource.h" +#include "export.h" +#include "objectdescription.h" + +namespace Phonon +{ +namespace Experimental +{ + +class PHONONEXPERIMENTAL_EXPORT MediaSource : public Phonon::MediaSource +{ + public: + enum Type { + Link = 0xffff, + VideoCaptureDeviceSource + }; + + /** + * Constructs a copy of \p rhs. + * + * This constructor is fast thanks to explicit sharing. + */ + MediaSource(const MediaSource &rhs); + + /** + * Assigns \p rhs to this MediaSource and returns a reference to this MediaSource. + * + * This operation is fast thanks to explicit sharing. + */ + MediaSource &operator=(const MediaSource &rhs); + + /** + * Returns \p true if this MediaSource is equal to \p rhs; otherwise returns \p false. + */ + bool operator==(const MediaSource &rhs) const; + + VideoCaptureDevice videoCaptureDevice() const; + + MediaSource(const VideoCaptureDevice &videoDevice); + MediaSource(const QList &mediaList); + + QList substreams() const; +}; + +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_EXPERIMENTAL_MEDIASOURCE_H diff --git a/src/3rdparty/phonon/phonon/experimental/mediasource_p.h b/src/3rdparty/phonon/phonon/experimental/mediasource_p.h new file mode 100644 index 0000000..ee3d1dd --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/mediasource_p.h @@ -0,0 +1,50 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_EXPERIMENTAL_MEDIASOURCE_P_H +#define PHONON_EXPERIMENTAL_MEDIASOURCE_P_H + +#include "mediasource.h" +#include "../mediasource_p.h" +#include "objectdescription.h" + +namespace Phonon +{ +namespace Experimental +{ + +class MediaSourcePrivate : public Phonon::MediaSourcePrivate +{ + public: + MediaSourcePrivate(MediaSource::Type t) + : Phonon::MediaSourcePrivate(static_cast(t)) + { + } + + VideoCaptureDevice videoCaptureDevice; + QList linkedSources; +}; + +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_EXPERIMENTAL_MEDIASOURCE_P_H diff --git a/src/3rdparty/phonon/phonon/experimental/objectdescription.h b/src/3rdparty/phonon/phonon/experimental/objectdescription.h new file mode 100644 index 0000000..334e262 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/objectdescription.h @@ -0,0 +1,42 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ +#ifndef PHONON_EXPERIMENTAL_OBJECTDESCRIPTION_H +#define PHONON_EXPERIMENTAL_OBJECTDESCRIPTION_H + +#include "../objectdescription.h" + +namespace Phonon +{ +namespace Experimental +{ + +enum ObjectDescriptionType +{ + VideoCaptureDeviceType = 0x10000 +}; + +typedef Phonon::ObjectDescription(Phonon::Experimental::VideoCaptureDeviceType)> VideoCaptureDevice; + +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_EXPERIMENTAL_OBJECTDESCRIPTION_H diff --git a/src/3rdparty/phonon/phonon/experimental/packet.cpp b/src/3rdparty/phonon/phonon/experimental/packet.cpp new file mode 100644 index 0000000..d60e624 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/packet.cpp @@ -0,0 +1,60 @@ +/* This file is part of the KDE project + Copyright (C) 2007-2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "packet.h" +#include "packet_p.h" +#include "packetpool.h" +#include "packetpool_p.h" + +namespace Phonon +{ + +Q_GLOBAL_STATIC(PacketPrivate, shared_null_packet) + +Packet::Packet() : d_ptr(shared_null_packet()) { d_ptr->ref.ref(); } +Packet::Packet(PacketPool &pool) : d_ptr(pool.d_ptr->acquirePacket().d_ptr) { d_ptr->ref.ref(); } +Packet::Packet(const Packet &rhs) : d_ptr(rhs.d_ptr) { d_ptr->ref.ref(); } +Packet::Packet(PacketPrivate &dd) : d_ptr(&dd) { d_ptr->ref.ref(); } +Packet &Packet::operator=(const Packet &rhs) +{ + if (!d_ptr->ref.deref()) { + Q_ASSERT(d_ptr->m_pool); + d_ptr->m_pool->releasePacket(*this); + } + d_ptr = rhs.d_ptr; + d_ptr->ref.ref(); + return *this; +} +Packet::~Packet() +{ + if (!d_ptr->ref.deref()) { + Q_ASSERT(d_ptr->m_pool); + d_ptr->m_pool->releasePacket(*this); + } +} +bool Packet::operator==(const Packet &rhs) const { return d_ptr == rhs.d_ptr; } +bool Packet::operator!=(const Packet &rhs) const { return d_ptr != rhs.d_ptr; } +bool Packet::isNull() const { return d_ptr->m_pool == 0; } +const char *Packet::data() const { return d_ptr->m_data; } +char *Packet::data() { return d_ptr->m_data; } +int Packet::size() const { return d_ptr->m_size; } +void Packet::setSize(int size) { d_ptr->m_size = size; } +int Packet::capacity() const { return d_ptr->m_pool ? d_ptr->m_pool->packetSize : 0; } + +} // namespace Phonon diff --git a/src/3rdparty/phonon/phonon/experimental/packet.h b/src/3rdparty/phonon/phonon/experimental/packet.h new file mode 100644 index 0000000..ca4d9a2 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/packet.h @@ -0,0 +1,129 @@ +/* This file is part of the KDE project + Copyright (C) 2007-2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef PHONON_PACKET_H +#define PHONON_PACKET_H + +#include "export.h" + +namespace Phonon +{ + +class PacketPool; + +struct PacketPrivate; +/** \class Packet packetpool.h Phonon/Packet + * \brief Class to access memory preallocated by PacketPool + * + * \note PacketPool and Packet are threadsafe. + * + * \author Matthias Kretz + */ +class PHONONEXPERIMENTAL_EXPORT Packet +{ + friend class PacketPoolPrivate; + Q_DECLARE_PRIVATE(Packet) + public: + /** + * Constructs a null packet. + * + * \see isNull + */ + Packet(); + /** + * Returns a packet with a capacity of pool.packetSize if there is still free data in the + * PacketPool. Returns a null packet otherwise. The size will initially be set to 0. + */ + explicit Packet(PacketPool &pool); + /** + * Returns a shared copy of the object. Note that Packet will not detach (and it can not + * detach as there's a fixed amount of memory preallocated. If you want to copy the actual + * memory data you have to request another packet from the pool and copy the memory + * yourself.) + */ + Packet(const Packet &rhs); + /** + * Assigns a shared copy of the object. Note that Packet will not detach (and it can not + * detach as there's a fixed amount of memory preallocated. If you want to copy the actual + * memory data you have to request another packet from the pool and copy the memory + * yourself.) + */ + Packet &operator=(const Packet &rhs); + + /** + * Dereferences the packet data. If this is the last reference that gets released the packet + * becomes available in the PacketPool again automatically. + */ + ~Packet(); + + /** + * Returns whether the packets reference the same data. + */ + bool operator==(const Packet &rhs) const; + + /** + * Returns whether the packets reference different data. + */ + bool operator!=(const Packet &rhs) const; + + /** + * Returns whether this object is a null packet. + * + * \see Packet() + */ + bool isNull() const; + + /** + * Returns a pointer to read the data this packet references. + * + * You may read size() bytes. + */ + const char *data() const; + + /** + * Returns a pointer to read and write the data this packet references. + * + * You may read size() bytes. + * You may write capacity() bytes. + * If you write to this pointer do not forget to adjust the size by calling setSize(). + */ + char *data(); + + /** + * Returns the number of bytes that have a defined value. + */ + int size() const; + + /** + * Sets how many bytes in the data pointer have a defined value. + */ + void setSize(int size); + + /** + * Returns the number of bytes that may be accessed. + */ + int capacity() const; + + protected: + explicit Packet(PacketPrivate &dd); + PacketPrivate *d_ptr; +}; + +} // namespace Phonon +#endif // PHONON_PACKET_H diff --git a/src/3rdparty/phonon/phonon/experimental/packet_p.h b/src/3rdparty/phonon/phonon/experimental/packet_p.h new file mode 100644 index 0000000..30824cc --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/packet_p.h @@ -0,0 +1,45 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) version 3. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef PHONON_PACKET_P_H +#define PHONON_PACKET_P_H + +#include + +namespace Phonon +{ + +class PacketPoolPrivate; +struct PacketPrivate +{ + inline PacketPrivate(char *_data, PacketPoolPrivate *_pool) + : ref(0), m_size(0), m_data(_data), m_pool(_pool) {} + inline PacketPrivate() : ref(1), m_size(0), m_data(0), m_pool(0) {} + + QAtomicInt ref; + + int m_size; + char *const m_data; + PacketPoolPrivate *const m_pool; +}; + +} // namespace Phonon + +#endif // PHONON_PACKET_P_H diff --git a/src/3rdparty/phonon/phonon/experimental/packetpool.cpp b/src/3rdparty/phonon/phonon/experimental/packetpool.cpp new file mode 100644 index 0000000..e9c47dd --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/packetpool.cpp @@ -0,0 +1,115 @@ +/* This file is part of the KDE project + Copyright (C) 2007-2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "packetpool.h" +#include "packetpool_p.h" +#include "packet.h" +#include "packet_p.h" + +namespace Phonon +{ + +int PacketPool::packetSize() const { return d_ptr->packetSize; } +int PacketPool::poolSize() const { return d_ptr->poolSize; } +int PacketPool::unusedPackets() const { return d_ptr->ringBufferSize; } + +PacketPoolPrivate::PacketPoolPrivate(int _packetSize, int _poolSize) + : freePackets(new PacketPrivate *[_poolSize]), + packetMemory(new char[packetSize * _poolSize]), + readPosition(0), writePosition(0), + ringBufferSize(_poolSize), + packetSize(_packetSize), + poolSize(_poolSize) +{ + for (int i = 0; i < _poolSize; ++i) { + freePackets[i] = new PacketPrivate(&packetMemory[i * packetSize], this); + } +} + +PacketPoolPrivate::~PacketPoolPrivate() +{ + Q_ASSERT(poolSize == ringBufferSize); + for (int i = 0; i < poolSize; ++i) { + delete freePackets[i]; + } + delete[] freePackets; + delete[] packetMemory; +} + +void PacketPoolPrivate::releasePacket(const Packet &packet) +{ + const int _writePos = writePosition.fetchAndAddAcquire(1); + int pos = _writePos; + while (pos >= poolSize) { + pos -= poolSize; + } + writePosition.testAndSetRelease(_writePos, pos); + freePackets[pos] = packet.d_ptr; + ringBufferSize.ref(); +} + +Packet PacketPoolPrivate::acquirePacket() +{ + const int s = ringBufferSize.fetchAndAddRelaxed(-1); + if (s <= 0) { + ringBufferSize.fetchAndAddRelaxed(1); + return Packet(); + } + const int _readPos = readPosition.fetchAndAddRelaxed(1); + int pos = _readPos; + while (pos >= poolSize) { + pos -= poolSize; + } + readPosition.testAndSetRelease(_readPos, pos); + freePackets[pos]->m_size = 0; + return Packet(*freePackets[pos]); +} + +PacketPool::PacketPool(int packetSize, int _poolSize) + : d_ptr(new PacketPoolPrivate(packetSize, _poolSize)) +{ + d_ptr->ref.ref(); +} + +PacketPool::PacketPool(const PacketPool &rhs) + : d_ptr(rhs.d_ptr) +{ + d_ptr->ref.ref(); +} + +PacketPool &PacketPool::operator=(const PacketPool &rhs) +{ + if (d_ptr != rhs.d_ptr) { + if (!d_ptr->ref.deref()) { + delete d_ptr; + } + d_ptr = rhs.d_ptr; + d_ptr->ref.ref(); + } + return *this; +} + +PacketPool::~PacketPool() +{ + if (!d_ptr->ref.deref()) { + delete d_ptr; + } +} + +} // namespace Phonon diff --git a/src/3rdparty/phonon/phonon/experimental/packetpool.h b/src/3rdparty/phonon/phonon/experimental/packetpool.h new file mode 100644 index 0000000..6d527a9 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/packetpool.h @@ -0,0 +1,79 @@ +/* This file is part of the KDE project + Copyright (C) 2007-2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#ifndef PHONON_PACKETPOOL_H +#define PHONON_PACKETPOOL_H + +#include "export.h" + +namespace Phonon +{ + +class Packet; +class PacketPoolPrivate; +/** \class PacketPool packetpool.h Phonon/PacketPool + * \brief Class to preallocate memory. + * + * \note PacketPool and Packet are threadsafe. + * + * \author Matthias Kretz + */ +class PHONONEXPERIMENTAL_EXPORT PacketPool +{ + Q_DECLARE_PRIVATE(PacketPool) + friend class Packet; + public: + /** + * Allocates \p numberOfPackets packets of \p packetSize bytes each. The memory can be + * accessed through Packet objects. + */ + PacketPool(int packetSize, int numberOfPackets); + /** + * Copy constructor. Copying is fast since the class is explicitly shared. + */ + PacketPool(const PacketPool &); + /** + * Destructs this object. If this is the last reference to the pool the memory will be + * freed. + */ + ~PacketPool(); + /** + * Assignmen operator. Copying is fast since the class is explicitly shared. + */ + PacketPool &operator=(const PacketPool &); + + /** + * Returns the packet size that was set in the constructor. + */ + int packetSize() const; + /** + * Returns the number of packets that was requested in the constructor. + */ + int poolSize() const; + /** + * Returns the number of packets that are still available for use. + */ + int unusedPackets() const; + + private: + PacketPoolPrivate *d_ptr; +}; + +} // namespace Phonon +#endif // PHONON_PACKETPOOL_H diff --git a/src/3rdparty/phonon/phonon/experimental/packetpool_p.h b/src/3rdparty/phonon/phonon/experimental/packetpool_p.h new file mode 100644 index 0000000..05d7375 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/packetpool_p.h @@ -0,0 +1,61 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) version 3. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + + +#ifndef PHONON_PACKETPOOL_P_H +#define PHONON_PACKETPOOL_P_H + +#include + +namespace Phonon +{ + +struct PacketPrivate; +class PacketPoolPrivate +{ + friend class PacketPool; + friend class Packet; + public: + ~PacketPoolPrivate(); + + Packet acquirePacket(); + void releasePacket(const Packet &); + + protected: + QAtomicInt ref; + + private: + PacketPoolPrivate(int packetSize, int _poolSize); + + // C-array of PacketPrivate* + PacketPrivate **freePackets; + char *const packetMemory; + + QAtomicInt readPosition; + QAtomicInt writePosition; + QAtomicInt ringBufferSize; + + const int packetSize; + const int poolSize; +}; + +} // namespace Phonon + +#endif // PHONON_PACKETPOOL_P_H diff --git a/src/3rdparty/phonon/phonon/experimental/phononnamespace.h b/src/3rdparty/phonon/phonon/experimental/phononnamespace.h new file mode 100644 index 0000000..d727238 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/phononnamespace.h @@ -0,0 +1,67 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_X_PHONONNAMESPACE_H +#define PHONON_X_PHONONNAMESPACE_H + +#include "../phononnamespace.h" + +namespace Phonon +{ +namespace Experimental +{ + + enum BitRate { + UnknownBitRate = -1, + /** + * Audio Data is transported as values from -128 to 127. + */ + Signed8Bit = 100, + /** + * Audio Data is transported as values from 0 to 255 + */ + Unsigned8Bit = 200, + /** + * Audio Data is transported as values from -2^15 to 2^15-1 + */ + Signed16Bit = 300, + Signed18Bit = 400, + Signed20Bit = 500, + /** + * Audio Data is transported as values from -2^23 to 2^23-1. The data is packed in 3 + * Bytes and not padded with a 0 Byte. + */ + Signed24Bit = 600, + /** + * Audio Data is transported as values from -2^31 to 2^31-1 + */ + Signed32Bit = 700, + /** + * Audio Data is transported as values from -1.0 to 1.0 + */ + Float32Bit = 800 + }; + +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_X_PHONONNAMESPACE_H diff --git a/src/3rdparty/phonon/phonon/experimental/rtpreceiver.h b/src/3rdparty/phonon/phonon/experimental/rtpreceiver.h new file mode 100644 index 0000000..34238e7 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/rtpreceiver.h @@ -0,0 +1,47 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_RTPRECEIVER_H +#define PHONON_RTPRECEIVER_H + +#include "../mediaobject.h" +#include "../phonondefs.h" + +namespace Phonon +{ +namespace Experimental +{ + +class RtpReceiver : public MediaProducer +{ + Q_OBJECT + K_DECLARE_PRIVATE(RtpReceiver) + PHONON_HEIR(VideoDataOutput) + public: + setUrl(const KUrl &); + setBandwidth(int kiloBitPerSecond); +}; + +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_RTPRECEIVER_H diff --git a/src/3rdparty/phonon/phonon/experimental/snapshotinterface.h b/src/3rdparty/phonon/phonon/experimental/snapshotinterface.h new file mode 100644 index 0000000..950fbdb --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/snapshotinterface.h @@ -0,0 +1,44 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_EXPERIMENTAL_SNAPSHOTINTERFACE_H +#define PHONON_EXPERIMENTAL_SNAPSHOTINTERFACE_H + +namespace Phonon +{ +namespace Experimental +{ + +class SnapshotInterface +{ + public: + virtual ~SnapshotInterface() {} + + virtual QImage snapshot() const = 0; +}; + +} // namespace Experimental +} // namespace Phonon + +Q_DECLARE_INTERFACE(Phonon::Experimental::SnapshotInterface, "0SnapshotInterface.Phonon.kde.org") + +#endif // PHONON_EXPERIMENTAL_SNAPSHOTINTERFACE_H diff --git a/src/3rdparty/phonon/phonon/experimental/streameventqueue.cpp b/src/3rdparty/phonon/phonon/experimental/streameventqueue.cpp new file mode 100644 index 0000000..a75286b --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/streameventqueue.cpp @@ -0,0 +1,123 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#include "streameventqueue_p.h" +#include "phononnamespace_p.h" +#include + +namespace Phonon +{ + +////////////////////////////////////////// +// any thread + +StreamEventQueue::StreamEventQueue() + : m_dropWriteCommands(0), + m_connecting(0) +{ +} + +StreamEventQueue::~StreamEventQueue() +{ +} + +void StreamEventQueue::setBackendCommandHandler(LockFreeQueueBase::DataReadyHandler *h) +{ + m_forBackend.setDataReadyHandler(h); +} + +void StreamEventQueue::setFrontendCommandHandler(LockFreeQueueBase::DataReadyHandler *h) +{ + m_forFrontend.setDataReadyHandler(h); +} + + +////////////////////////////////////////// +// frontend thread + +void StreamEventQueue::sendToBackend(CommandType command, const QVariant &data) +{ + m_forBackend.enqueue(Command(command, data)); +} + +bool StreamEventQueue::nextCommandForFrontend(Command *command) +{ + Q_ASSERT(command); + return m_forFrontend.dequeue(command); +} + + +////////////////////////////////////////// +// backend thread + +void StreamEventQueue::sendToFrontend(CommandType command, const QVariant &data) +{ + switch (command) { + case Seek: + case Reset: + ++m_dropWriteCommands; + break; + case Connect: + ++m_connecting; + m_dropWriteCommands = 0; + break; + default: + break; + } + m_forFrontend.enqueue(Command(command, data)); +} + +bool StreamEventQueue::nextCommandForBackend(Command *command) +{ + Q_ASSERT(command); + bool valid = m_forBackend.dequeue(command); + while (valid) { + if (m_connecting) { + if (command->command == ConnectDone) { + --m_connecting; + } + // drop all other commands until m_connecting == 0 + } else if (m_dropWriteCommands) { + switch (command->command) { + case Write: + case EndOfData: + // drop until m_dropWriteCommands == 0 + break; + case SeekDone: + case ResetDone: + --m_dropWriteCommands; + break; + case ConnectDone: + pFatal("received a ConnectDone, but there was no Connect request"); + break; + default: + return valid; + } + } else { + return valid; + } + valid = m_forBackend.dequeue(command); + } + return valid; +} + +} // namespace Phonon diff --git a/src/3rdparty/phonon/phonon/experimental/streameventqueue_p.h b/src/3rdparty/phonon/phonon/experimental/streameventqueue_p.h new file mode 100644 index 0000000..66b5858 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/streameventqueue_p.h @@ -0,0 +1,92 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_STREAMEVENTQUEUE_P_H +#define PHONON_STREAMEVENTQUEUE_P_H + +#include +#include "lockfreequeue_p.h" + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +class StreamEventQueue +{ + public: + StreamEventQueue(); + ~StreamEventQueue(); + + void setBackendCommandHandler(LockFreeQueueBase::DataReadyHandler *); + void setFrontendCommandHandler(LockFreeQueueBase::DataReadyHandler *); + + enum CommandType { + // Frontend -> Backend + SetStreamSize, + SetSeekable, + Write, + EndOfData, + SeekDone, + ResetDone, + ConnectDone, + + // Backend -> Frontend + NeedData, + EnoughData, + Seek, + Reset, + Connect + }; + + struct Command + { + inline Command(CommandType &c, const QVariant &d) : data(d), command(c) {} + inline Command() {} + QVariant data; + CommandType command; + }; + + // called from AbstractMediaStream thread + void sendToBackend(CommandType, const QVariant & = QVariant()); + bool nextCommandForFrontend(Command *); + + // called from StreamInterface thread + void sendToFrontend(CommandType, const QVariant & = QVariant()); + bool nextCommandForBackend(Command *); + + void ref() { m_references.ref(); } + void deref() { if (!m_references.deref()) delete this; } + + private: + LockFreeQueue m_forBackend; + LockFreeQueue m_forFrontend; + int m_dropWriteCommands; + int m_connecting; + QAtomicInt m_references; +}; + +} // namespace Phonon + +QT_END_NAMESPACE + +#endif // PHONON_STREAMEVENTQUEUE_P_H diff --git a/src/3rdparty/phonon/phonon/experimental/tests/CMakeLists.txt b/src/3rdparty/phonon/phonon/experimental/tests/CMakeLists.txt new file mode 100644 index 0000000..558204d --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/tests/CMakeLists.txt @@ -0,0 +1,54 @@ +set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) + +MACRO(PHONON_UNIT_TESTS) + FOREACH(_testname ${ARGN}) + set(srcs ${_testname}.cpp) + if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_testname}.qrc) + qt4_add_resources(srcs ${_testname}.qrc) + endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_testname}.qrc) + phonon_add_unit_test(${_testname} ${srcs}) + target_link_libraries(${_testname} ${PHONON_LIBS} phononexperimental ${QT_QTTEST_LIBRARY}) + ENDFOREACH(_testname) +ENDMACRO(PHONON_UNIT_TESTS) + +# same as above but using the fake backend +MACRO(PHONON_UNIT_TESTS_FAKE) + FOREACH(_testname ${ARGN}) + set(srcs ${_testname}.cpp) + if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_testname}.qrc) + qt4_add_resources(srcs ${_testname}.qrc) + endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_testname}.qrc) + phonon_add_unit_test(${_testname}_fake ${srcs}) + target_link_libraries(${_testname}_fake ${PHONON_LIBS} phononexperimental ${QT_QTTEST_LIBRARY} phonon_fake) + SET_TARGET_PROPERTIES(${_testname}_fake PROPERTIES COMPILE_FLAGS -DUSE_FAKE_BACKEND) + ENDFOREACH(_testname) +ENDMACRO(PHONON_UNIT_TESTS_FAKE) + +MACRO(PHONON_EXECUTABLE_TESTS) + FOREACH(_testname ${ARGN}) + set(_add_executable_param) + if (Q_WS_MAC) + set(_add_executable_param MACOSX_BUNDLE) + endif (Q_WS_MAC) +# this breaks compilation +# if (WIN32) +# set(_add_executable_param WIN32) +# endif (WIN32) + if (NOT PHONON_BUILD_TESTS) + set(_add_executable_param ${_add_executable_param} EXCLUDE_FROM_ALL) + endif (NOT PHONON_BUILD_TESTS) + set(srcs ${_testname}.cpp) + if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_testname}.qrc) + qt4_add_resources(srcs ${_testname}.qrc) + endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_testname}.qrc) + automoc4_add_executable(${_testname} ${_add_executable_param} ${srcs}) + target_link_libraries(${_testname} ${PHONON_LIBS} phononexperimental ${QT_QTTEST_LIBRARY}) + ENDFOREACH(_testname) +ENDMACRO(PHONON_EXECUTABLE_TESTS) + +PHONON_EXECUTABLE_TESTS( + videodataoutputtest + ) + +PHONON_UNIT_TESTS_FAKE( + ) diff --git a/src/3rdparty/phonon/phonon/experimental/tests/methods/audiodataoutput.cpp b/src/3rdparty/phonon/phonon/experimental/tests/methods/audiodataoutput.cpp new file mode 100644 index 0000000..ff017b2 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/tests/methods/audiodataoutput.cpp @@ -0,0 +1,8 @@ +addSignal("dataReady(const QMap>&)"); +addMethod("int", "sampleRate()"); +addMethod("", "setFormat(Phonon::Experimental::AudioDataOutput::Format)"); +addMethod("Phonon::Experimental::AudioDataOutput::Format", "format()"); +addSignal("endOfMedia(int)"); +addMethod("int", "dataSize()"); +addSignal("dataReady(const QMap>&)"); +addMethod("", "setDataSize(int)"); diff --git a/src/3rdparty/phonon/phonon/experimental/tests/methods/avcapture.cpp b/src/3rdparty/phonon/phonon/experimental/tests/methods/avcapture.cpp new file mode 100644 index 0000000..d645946 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/tests/methods/avcapture.cpp @@ -0,0 +1,4 @@ +addMethod("int", "videoCaptureDevice()"); +addMethod("", "setAudioCaptureDevice(int)"); +addMethod("int", "audioCaptureDevice()"); +addMethod("", "setVideoCaptureDevice(int)"); diff --git a/src/3rdparty/phonon/phonon/experimental/tests/methods/avwriter.cpp b/src/3rdparty/phonon/phonon/experimental/tests/methods/avwriter.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/3rdparty/phonon/phonon/experimental/tests/methods/overlayapi.cpp b/src/3rdparty/phonon/phonon/experimental/tests/methods/overlayapi.cpp new file mode 100644 index 0000000..d952a0d --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/tests/methods/overlayapi.cpp @@ -0,0 +1 @@ +addMethod("bool", "createOverlay(QWidget*,int)", true); diff --git a/src/3rdparty/phonon/phonon/experimental/tests/methods/videodataoutput.cpp b/src/3rdparty/phonon/phonon/experimental/tests/methods/videodataoutput.cpp new file mode 100644 index 0000000..8a9e21b --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/tests/methods/videodataoutput.cpp @@ -0,0 +1,9 @@ +addSignal("endOfMedia()"); +addMethod("", "setFrameRate(int)"); +addMethod("quint32", "format()"); +addMethod("QSize", "frameSize()"); +addSignal("frameReady(const Phonon::Experimental::VideoFrame&)"); +addMethod("QSize", "naturalFrameSize()"); +addMethod("", "setFormat(quint32)"); +addMethod("int", "frameRate()"); +addMethod("", "setFrameSize(QSize)"); diff --git a/src/3rdparty/phonon/phonon/experimental/tests/methods/visualization.cpp b/src/3rdparty/phonon/phonon/experimental/tests/methods/visualization.cpp new file mode 100644 index 0000000..3ec7900 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/tests/methods/visualization.cpp @@ -0,0 +1,4 @@ +addMethod("", "setVisualization(int)"); +addMethod("", "setVideoOutput(QObject*)"); +addMethod("", "setAudioPath(QObject*)"); +addMethod("int", "visualization()"); diff --git a/src/3rdparty/phonon/phonon/experimental/tests/test.mng b/src/3rdparty/phonon/phonon/experimental/tests/test.mng new file mode 100644 index 0000000..3911090 Binary files /dev/null and b/src/3rdparty/phonon/phonon/experimental/tests/test.mng differ diff --git a/src/3rdparty/phonon/phonon/experimental/tests/videodataoutputtest.cpp b/src/3rdparty/phonon/phonon/experimental/tests/videodataoutputtest.cpp new file mode 100644 index 0000000..7fe0af0 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/tests/videodataoutputtest.cpp @@ -0,0 +1,135 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#define QT_GUI_LIB +#include "../abstractvideodataoutput.h" +#include "../videoframe2.h" +#include "../../mediaobject.h" +#include "../../tests/qtesthelper.h" +#include +#include +#include +#include +#include +#ifdef Q_OS_WIN +#include +#endif + +class Output : public QObject, public Phonon::Experimental::AbstractVideoDataOutput +{ + Q_OBJECT + public: + Output() : receivedEnd(0) {} + virtual QSet allowedFormats() const; + virtual void frameReady(const Phonon::Experimental::VideoFrame2 &); + virtual void endOfMedia(); + + QList frames; + int receivedEnd; + QMutex mutex; +}; + +QSet Output::allowedFormats() const +{ + return QSet() << Phonon::Experimental::VideoFrame2::Format_RGB888; +} + +void Output::frameReady(const Phonon::Experimental::VideoFrame2 &frame) +{ + qDebug() << Q_FUNC_INFO; + Q_ASSERT(frame.format == Phonon::Experimental::VideoFrame2::Format_RGB888); + QMutexLocker lock(&mutex); + frames << frame.qImage(); +} + +void Output::endOfMedia() +{ + ++receivedEnd; +} + +class VideoDataOutputTest : public QObject +{ + Q_OBJECT + private slots: + void initTestCase(); + void testDelete(); + void playMedia(); + void cleanupTestCase(); + private: + Phonon::MediaObject *m_media; + Output *m_output; +}; + +void VideoDataOutputTest::initTestCase() +{ + m_media = new Phonon::MediaObject; + m_output = new Output; + Phonon::createPath(m_media, m_output); +} + +void VideoDataOutputTest::testDelete() +{ + delete m_output; + m_output = new Output; + m_output->start(); + QVERIFY(m_output->isRunning()); + Phonon::createPath(m_media, m_output); +#ifdef Q_OS_WIN + Sleep(1000); +#else + sleep(1); +#endif +} + +void VideoDataOutputTest::playMedia() +{ + m_media->setCurrentSource(QString(":/test.mng")); + m_media->play(); + QVERIFY(QTest::kWaitForSignal(m_media, SIGNAL(finished()), 4000)); + QEXPECT_FAIL("", "endOfMedia not yet implemented for xine", Continue); + QCOMPARE(m_output->receivedEnd, 1); + QList frames; + { + QImageReader movie(":/test.mng"); + QImage frame; + while (movie.read(&frame)) { + frames << frame.convertToFormat(QImage::Format_RGB888); + } + } + qDebug() << frames.size(); + QMutexLocker lock(&m_output->mutex); + QVERIFY(!m_output->frames.isEmpty()); + QCOMPARE(m_output->frames.size(), frames.size()); + for (int i = 0; i < frames.size(); ++i) { + QCOMPARE(m_output->frames[i], frames[i]); + } +} + +void VideoDataOutputTest::cleanupTestCase() +{ + delete m_output; + delete m_media; +} + +QTEST_MAIN(VideoDataOutputTest) + +#include "videodataoutputtest.moc" diff --git a/src/3rdparty/phonon/phonon/experimental/tests/videodataoutputtest.qrc b/src/3rdparty/phonon/phonon/experimental/tests/videodataoutputtest.qrc new file mode 100644 index 0000000..dd6243d --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/tests/videodataoutputtest.qrc @@ -0,0 +1,5 @@ + + + test.mng + + diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/CMakeLists.txt b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/CMakeLists.txt new file mode 100644 index 0000000..a070fe5 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/CMakeLists.txt @@ -0,0 +1,16 @@ +project(videocapturetestapp) + +include(CheckIncludeFile) +include(CheckIncludeFiles) + + +check_include_files(linux/videodev2.h V4L2_FOUND) + +if(NOT V4L2_FOUND) + message(FATAL_ERROR "Video4Linux2 not found") +endif(NOT V4L2_FOUND) + +find_package(KDE4 REQUIRED) + +add_subdirectory( videocapture ) +add_subdirectory( videocapturetestapp ) diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/CMakeLists.txt b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/CMakeLists.txt new file mode 100644 index 0000000..6944b0b --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/CMakeLists.txt @@ -0,0 +1,12 @@ +add_definitions(-DQT3_SUPPORT -DQT3_SUPPORT_WARNINGS) + +include_directories( ${KDE4_INCLUDES} ) +add_definitions( ${KDE4_DEFINITIONS} ) + +set(videocapture_LIB_SRCS bayer.cpp sonix_compress.cpp videodevice.cpp videodevicemodelpool.cpp videodevicepool.cpp videoinput.cpp) + +kde4_add_library(videocapture SHARED ${videocapture_LIB_SRCS} ) + +target_link_libraries(videocapture ${KDE4_KDECORE_LIBS} ${KDE4_SOLID_LIBS}) + +install(TARGETS videocapture ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/bayer.cpp b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/bayer.cpp new file mode 100644 index 0000000..69189ba --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/bayer.cpp @@ -0,0 +1,118 @@ +/* + * BAYER2RGB24 ROUTINE TAKEN FROM: + * + * Sonix SN9C101 based webcam basic I/F routines + * Copyright (C) 2004 Takafumi Mizuno + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +void bayer2rgb24(unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT) +{ + long int i; + unsigned char *rawpt, *scanpt; + long int size; + + rawpt = src; + scanpt = dst; + size = WIDTH*HEIGHT; + + for ( i = 0; i < size; i++ ) + { + if ( (i/WIDTH) % 2 == 0 ) + { + if ( (i % 2) == 0 ) + { + // B + if ( (i > WIDTH) && ((i % WIDTH) > 0) ) + { + *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+*(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; // R + *scanpt++ = (*(rawpt-1)+*(rawpt+1)+*(rawpt+WIDTH)+*(rawpt-WIDTH))/4; // G + *scanpt++ = *rawpt; // B + } + else + { + // first line or left column + *scanpt++ = *(rawpt+WIDTH+1); // R + *scanpt++ = (*(rawpt+1)+*(rawpt+WIDTH))/2; // G + *scanpt++ = *rawpt; // B + } + } + else + { + // (B)G + if ( (i > WIDTH) && ((i % WIDTH) < (WIDTH-1)) ) + { + *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; // R + *scanpt++ = *rawpt; // G + *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; // B + } + else + { + // first line or right column + *scanpt++ = *(rawpt+WIDTH); // R + *scanpt++ = *rawpt; // G + *scanpt++ = *(rawpt-1); // B + } + } + } + else + { + if ( (i % 2) == 0 ) + { + // G(R) + if ( (i < (WIDTH*(HEIGHT-1))) && ((i % WIDTH) > 0) ) + { + *scanpt++ = (*(rawpt-1)+*(rawpt+1))/2; // R + *scanpt++ = *rawpt; // G + *scanpt++ = (*(rawpt+WIDTH)+*(rawpt-WIDTH))/2; // B + } + else + { + // bottom line or left column + *scanpt++ = *(rawpt+1); /* R */ + *scanpt++ = *rawpt; /* G */ + *scanpt++ = *(rawpt-WIDTH); /* B */ + } + } + else + { + // R + if ( i < (WIDTH*(HEIGHT-1)) && ((i % WIDTH) < (WIDTH-1)) ) + { + *scanpt++ = *rawpt; // R + *scanpt++ = (*(rawpt-1)+*(rawpt+1)+*(rawpt-WIDTH)+*(rawpt+WIDTH))/4; // G + *scanpt++ = (*(rawpt-WIDTH-1)+*(rawpt-WIDTH+1)+*(rawpt+WIDTH-1)+*(rawpt+WIDTH+1))/4; // B + } + else + { + // bottom line or right column + *scanpt++ = *rawpt; /* R */ + *scanpt++ = (*(rawpt-1)+*(rawpt-WIDTH))/2; /* G */ + *scanpt++ = *(rawpt-WIDTH-1); /* B */ + } + } + } + rawpt++; + } +} + diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/bayer.h b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/bayer.h new file mode 100644 index 0000000..af6d8ba --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/bayer.h @@ -0,0 +1,30 @@ +/* + * BAYER2RGB24 ROUTINE TAKEN FROM: + * + * Sonix SN9C101 based webcam basic I/F routines + * Copyright (C) 2004 Takafumi Mizuno + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +void bayer2rgb24 (unsigned char *dst, unsigned char *src, long int WIDTH, long int HEIGHT); diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/sonix_compress.cpp b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/sonix_compress.cpp new file mode 100644 index 0000000..400635c --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/sonix_compress.cpp @@ -0,0 +1,180 @@ +#include "sonix_compress.h" + +#define CLAMP(x) ((x)<0?0:((x)>255)?255:(x)) + +typedef struct { + int is_abs; + int len; + int val; + int unk; +} code_table_t; + + +/* local storage */ +static code_table_t table[256]; +static int init_done = 0; + +/* global variable */ +int sonix_unknown = 0; + +/* + sonix_decompress_init + ===================== + pre-calculates a locally stored table for efficient huffman-decoding. + + Each entry at index x in the table represents the codeword + present at the MSB of byte x. + +*/ +void sonix_decompress_init(void) +{ + int i; + int is_abs, val, len, unk; + + for (i = 0; i < 256; i++) { + is_abs = 0; + val = 0; + len = 0; + unk = 0; + if ((i & 0x80) == 0) { + /* code 0 */ + val = 0; + len = 1; + } + else if ((i & 0xE0) == 0x80) { + /* code 100 */ + val = +4; + len = 3; + } + else if ((i & 0xE0) == 0xA0) { + /* code 101 */ + val = -4; + len = 3; + } + else if ((i & 0xF0) == 0xD0) { + /* code 1101 */ + val = +11; + len = 4; + } + else if ((i & 0xF0) == 0xF0) { + /* code 1111 */ + val = -11; + len = 4; + } + else if ((i & 0xF8) == 0xC8) { + /* code 11001 */ + val = +20; + len = 5; + } + else if ((i & 0xFC) == 0xC0) { + /* code 110000 */ + val = -20; + len = 6; + } + else if ((i & 0xFC) == 0xC4) { + /* code 110001xx: unknown */ + val = 0; + len = 8; + unk = 1; + } + else if ((i & 0xF0) == 0xE0) { + /* code 1110xxxx */ + is_abs = 1; + val = (i & 0x0F) << 4; + len = 8; + } + table[i].is_abs = is_abs; + table[i].val = val; + table[i].len = len; + table[i].unk = unk; + } + + sonix_unknown = 0; + init_done = 1; +} + + +/* + sonix_decompress + ================ + decompresses an image encoded by a SN9C101 camera controller chip. + + IN width + height + inp pointer to compressed frame (with header already stripped) + OUT outp pointer to decompressed frame + + Returns 0 if the operation was successful. + Returns <0 if operation failed. + +*/ +int sonix_decompress(int width, int height, unsigned char *inp, unsigned char *outp) +{ + int row, col; + int val; + int bitpos; + unsigned char code; + unsigned char *addr; + + if (!init_done) { + /* do sonix_decompress_init first! */ + return -1; + } + + bitpos = 0; + for (row = 0; row < height; row++) { + + col = 0; + + /* first two pixels in first two rows are stored as raw 8-bit */ + if (row < 2) { + addr = inp + (bitpos >> 3); + code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7))); + bitpos += 8; + *outp++ = code; + + addr = inp + (bitpos >> 3); + code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7))); + bitpos += 8; + *outp++ = code; + + col += 2; + } + + while (col < width) { + /* get bitcode from bitstream */ + addr = inp + (bitpos >> 3); + code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7))); + + /* update bit position */ + bitpos += table[code].len; + + /* update code statistics */ + sonix_unknown += table[code].unk; + + /* calculate pixel value */ + val = table[code].val; + if (!table[code].is_abs) { + /* value is relative to top and left pixel */ + if (col < 2) { + /* left column: relative to top pixel */ + val += outp[-2*width]; + } + else if (row < 2) { + /* top row: relative to left pixel */ + val += outp[-2]; + } + else { + /* main area: average of left pixel and top pixel */ + val += (outp[-2] + outp[-2*width]) / 2; + } + } + + /* store pixel */ + *outp++ = CLAMP(val); + col++; + } + } + + return 0; +} diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/sonix_compress.h b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/sonix_compress.h new file mode 100644 index 0000000..509bcb0 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/sonix_compress.h @@ -0,0 +1,8 @@ +// Call this function first (just once is needed), before calling sonix_decompress +void sonix_decompress_init(void); + +// decompresses data at inp until a full image of widthxheight has been written to outp +int sonix_decompress(int width, int height, unsigned char *inp, unsigned char *outp); + +// counter to detect presence of currently unknown huffman codes +extern int sonix_unknown; diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevice.cpp b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevice.cpp new file mode 100644 index 0000000..cd87bea --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevice.cpp @@ -0,0 +1,2847 @@ +/* + videodevice.cpp - Video Device Low-level Support + + Copyright (c) 2005-2006 by Cláudio da Silveira Pinheiro + + ************************************************************************* + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + ************************************************************************* +*/ + +#define ENABLE_AV + +#include +#include +#include + +#include + +#include "videoinput.h" +#include "videodevice.h" + +#include "bayer.h" +#include "sonix_compress.h" + +#define CLEAR(x) memset (&(x), 0, sizeof (x)) + +namespace Phonon { +namespace VideoCapture { + +VideoDevice::VideoDevice() +{ +// kDebug() << "libkopete (avdevice): VideoDevice() called"; + descriptor = -1; + m_streambuffers = 0; + m_current_input = 0; +// kDebug() << "libkopete (avdevice): VideoDevice() exited successfuly"; +} + + +VideoDevice::~VideoDevice() +{ +} + +#ifdef V4L2_CAP_VIDEO_CAPTURE + +void VideoDevice::enumerateControls (void) +{ +// ----------------------------------------------------------------------------------------------------------------- +// This must turn up to be a proper method to check for controls' existence. + CLEAR (queryctrl); +// v4l2_queryctrl may zero the .id in some cases, even if the IOCTL returns EXIT_SUCCESS (tested with a bttv card, when testing for V4L2_CID_AUDIO_VOLUME). +// As of 6th Aug 2007, according to the V4L2 specification version 0.21, this behavior is undocumented, and the example 1-8 code found at +// http://www.linuxtv.org/downloads/video4linux/API/V4L2_API/spec/x519.htm fails because of this behavior with a bttv card. + + int currentid = V4L2_CID_BASE; + +kDebug() << "Checking CID controls"; + + for (currentid = V4L2_CID_BASE; currentid < V4L2_CID_LASTP1; currentid++) +//for (queryctrl.id = 9963776; queryctrl.id < 9963800; queryctrl.id++) + { + queryctrl.id = currentid; + if (0 == xioctl (VIDIOC_QUERYCTRL, &queryctrl)) + { + if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) + continue; + +kDebug() << " Control: " << QString::fromLocal8Bit((const char*)queryctrl.name) << " Values from " << queryctrl.minimum << " to " << queryctrl.maximum << " with steps of " << queryctrl.step << ". Default: " << queryctrl.default_value; + +// switch (queryctrl.type) +// { +// case V4L2_CTRL_TYPE_INTEGER : +// } + if (queryctrl.type == V4L2_CTRL_TYPE_MENU) + enumerateMenu (); + } + else + { + if (errno == EINVAL) + continue; + + perror ("VIDIOC_QUERYCTRL"); +// exit (EXIT_FAILURE); + } + } + +kDebug() << "Checking CID private controls"; + + for (currentid = V4L2_CID_PRIVATE_BASE;; currentid++) + { + queryctrl.id = currentid; + if ( 0 == xioctl (VIDIOC_QUERYCTRL, &queryctrl)) + { + if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) + continue; + +kDebug() << " Control: " << QString::fromLocal8Bit((const char*)queryctrl.name) << " Values from " << queryctrl.minimum << " to " << queryctrl.maximum << " with steps of " << queryctrl.step << ". Default: " << queryctrl.default_value; + + if (queryctrl.type == V4L2_CTRL_TYPE_MENU) + enumerateMenu (); + } + else + { + if (errno == EINVAL) + break; + + perror ("VIDIOC_QUERYCTRL"); +// exit (EXIT_FAILURE); + } + } +} + +void VideoDevice::enumerateMenu (void) +{ + kDebug() << " Menu items:"; + + memset (&querymenu, 0, sizeof (querymenu)); + querymenu.id = queryctrl.id; + + for (querymenu.index = queryctrl.minimum; querymenu.index <= queryctrl.maximum; querymenu.index++) + { + if (0 == xioctl (VIDIOC_QUERYMENU, &querymenu)) + { + kDebug() << " " << QString::fromLocal8Bit((const char*)querymenu.name); + } + else + { + perror ("VIDIOC_QUERYMENU"); + exit (EXIT_FAILURE); + } + } +} +#endif + +/*! + \fn VideoDevice::xioctl(int fd, int request, void *arg) + */ +int VideoDevice::xioctl(int request, void *arg) +{ + int r; + + do r = ioctl (descriptor, request, arg); + while (-1 == r && EINTR == errno); + return r; +} + +/*! + \fn VideoDevice::errnoReturn(const char* s) + */ +int VideoDevice::errnoReturn(const char* s) +{ + /// @todo implement me + fprintf (stderr, "%s error %d, %s\n",s, errno, strerror (errno)); + return EXIT_FAILURE; +} + +/*! + \fn VideoDevice::setFileName(QString name) + */ +int VideoDevice::setFileName(QString filename) +{ + /// @todo implement me + full_filename=filename; + return EXIT_SUCCESS; +} + +/*! + \fn VideoDevice::open() + */ +int VideoDevice::open() +{ + /// @todo implement me + + kDebug() << "called"; + if(-1 != descriptor) + { + kDebug() << "Device is already open"; + return EXIT_SUCCESS; + } + descriptor = ::open (QFile::encodeName(full_filename), O_RDWR, 0); + if(isOpen()) + { + kDebug() << "File " << full_filename << " was opened successfuly"; + if(EXIT_FAILURE==checkDevice()) + { + kDebug() << "File " << full_filename << " could not be opened"; + close(); + return EXIT_FAILURE; + } + } + else + { + kDebug() << "Unable to open file " << full_filename << "Err: "<< errno; + return EXIT_FAILURE; + } + + initDevice(); + selectInput(m_current_input); + kDebug() << "exited successfuly"; + return EXIT_SUCCESS; +} + +bool VideoDevice::isOpen() +{ + if(-1 == descriptor) + { +// kDebug() << "VideoDevice::isOpen() File is not open"; + return false; + } +// kDebug() << "VideoDevice::isOpen() File is open"; + return true; +} + +int VideoDevice::checkDevice() +{ + kDebug() << "checkDevice() called."; + if(isOpen()) + { + m_videocapture=false; + m_videochromakey=false; + m_videoscale=false; + m_videooverlay=false; + m_videoread=false; + m_videoasyncio=false; + m_videostream=false; + + m_driver=VIDEODEV_DRIVER_NONE; +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + + CLEAR(V4L2_capabilities); + + if (-1 != xioctl (VIDIOC_QUERYCAP, &V4L2_capabilities)) + { + if (!(V4L2_capabilities.capabilities & V4L2_CAP_VIDEO_CAPTURE)) + { + kDebug() << "checkDevice(): " << full_filename << " is not a video capture device."; + m_driver = VIDEODEV_DRIVER_NONE; + return EXIT_FAILURE; + } + m_videocapture=true; + kDebug() << "checkDevice(): " << full_filename << " is a V4L2 device."; + m_driver = VIDEODEV_DRIVER_V4L2; + m_model=QString::fromLocal8Bit((const char*)V4L2_capabilities.card); + + +// Detect maximum and minimum resolution supported by the V4L2 device. VIDIOC_ENUM_FRAMESIZES is still experimental. + CLEAR (fmt); + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == xioctl (VIDIOC_G_FMT, &fmt)) + kDebug() << "VIDIOC_G_FMT failed (" << errno << ")."; + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.fmt.pix.width = 32767; + fmt.fmt.pix.height = 32767; + fmt.fmt.pix.field = V4L2_FIELD_ANY; + if (-1 == xioctl (VIDIOC_S_FMT, &fmt)) + { + kDebug() << "Detecting maximum size with VIDIOC_S_FMT failed (" << errno << ").Returned maxwidth: " << pixelFormatName(fmt.fmt.pix.pixelformat) << " " << fmt.fmt.pix.width << "x" << fmt.fmt.pix.height; + // Note VIDIOC_S_FMT may change width and height. + } + else + { + maxwidth = fmt.fmt.pix.width; + maxheight = fmt.fmt.pix.height; + } + if (-1 == xioctl (VIDIOC_G_FMT, &fmt)) + kDebug() << "VIDIOC_G_FMT failed (" << errno << ")."; + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.fmt.pix.width = 1; + fmt.fmt.pix.height = 1; + fmt.fmt.pix.field = V4L2_FIELD_ANY; + if (-1 == xioctl (VIDIOC_S_FMT, &fmt)) + { + kDebug() << "Detecting minimum size with VIDIOC_S_FMT failed (" << errno << ").Returned maxwidth: " << fmt.fmt.pix.width << "x" << fmt.fmt.pix.height; + // Note VIDIOC_S_FMT may change width and height. + } + else + { + minwidth = fmt.fmt.pix.width; + minheight = fmt.fmt.pix.height; + } + +// Buggy driver paranoia +/* min = fmt.fmt.pix.width * 2; + if (fmt.fmt.pix.bytesperline < min) + fmt.fmt.pix.bytesperline = min; + min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height; + if (fmt.fmt.pix.sizeimage < min) + fmt.fmt.pix.sizeimage = min; + m_buffer_size=fmt.fmt.pix.sizeimage ;*/ + + int inputisok=EXIT_SUCCESS; + m_input.clear(); + for(unsigned int loop=0; inputisok==EXIT_SUCCESS; loop++) + { + struct v4l2_input videoinput; + CLEAR(videoinput); + videoinput.index = loop; + inputisok=xioctl(VIDIOC_ENUMINPUT, &videoinput); + if(inputisok==EXIT_SUCCESS) + { + VideoInput tempinput; + tempinput.name = QString::fromLocal8Bit((const char*)videoinput.name); + tempinput.hastuner = videoinput.type & V4L2_INPUT_TYPE_TUNER; +detectSignalStandards(); + tempinput.m_standards = videoinput.std; + m_input.push_back(tempinput); + kDebug() << "Input " << loop << ": " << tempinput.name << " (tuner: " << ((videoinput.type & V4L2_INPUT_TYPE_TUNER) != 0) << ")"; + if((videoinput.type & V4L2_INPUT_TYPE_TUNER) != 0) + { +// _tunerForInput[name] = desc.tuner; +// _isTuner = true; + } + else + { +// _tunerForInput[name] = -1; + } + } + } + } + else + { +// V4L-only drivers should return an EINVAL in errno to indicate they cannot handle V4L2 calls. Not every driver is compliant, so +// it will try the V4L api even if the error code is different than expected. + kDebug() << "checkDevice(): " << full_filename << " is not a V4L2 device."; + } + +#endif + + CLEAR(V4L_capabilities); + + if(m_driver==VIDEODEV_DRIVER_NONE) + { + kDebug() << "checkDevice(): " << full_filename << " Trying V4L API."; + if (-1 == xioctl (VIDIOCGCAP, &V4L_capabilities)) + { + perror ("ioctl (VIDIOCGCAP)"); + m_driver = VIDEODEV_DRIVER_NONE; + return EXIT_FAILURE; + } + else + { + kDebug() << full_filename << " is a V4L device."; + m_driver = VIDEODEV_DRIVER_V4L; + m_model=QString::fromLocal8Bit((const char*)V4L_capabilities.name); + if(V4L_capabilities.type & VID_TYPE_CAPTURE) + m_videocapture=true; + if(V4L_capabilities.type & VID_TYPE_CHROMAKEY) + m_videochromakey=true; + if(V4L_capabilities.type & VID_TYPE_SCALES) + m_videoscale=true; + if(V4L_capabilities.type & VID_TYPE_OVERLAY) + m_videooverlay=true; +// kDebug() << "libkopete (avdevice): Inputs : " << V4L_capabilities.channels; +// kDebug() << "libkopete (avdevice): Audios : " << V4L_capabilities.audios; + minwidth = V4L_capabilities.minwidth; + maxwidth = V4L_capabilities.maxwidth; + minheight = V4L_capabilities.minheight; + maxheight = V4L_capabilities.maxheight; + + + int inputisok=EXIT_SUCCESS; + m_input.clear(); + for(int loop=0; loop < V4L_capabilities.channels; loop++) + { + struct video_channel videoinput; + CLEAR(videoinput); + videoinput.channel = loop; + videoinput.norm = 1; + inputisok=xioctl(VIDIOCGCHAN, &videoinput); + if(inputisok==EXIT_SUCCESS) + { + VideoInput tempinput; + tempinput.name = QString::fromLocal8Bit((const char*)videoinput.name); + tempinput.hastuner=videoinput.flags & VIDEO_VC_TUNER; +// TODO: The routine to detect the appropriate video standards for V4L must be placed here + m_input.push_back(tempinput); +// kDebug() << "libkopete (avdevice): Input " << loop << ": " << tempinput.name << " (tuner: " << ((videoinput.flags & VIDEO_VC_TUNER) != 0) << ")"; +/* if((input.type & V4L2_INPUT_TYPE_TUNER) != 0) + { +// _tunerForInput[name] = desc.tuner; +// _isTuner = true; + } + else + { +// _tunerForInput[name] = -1; + } +*/ } + } + + } + } +#endif + m_name=m_model; // Take care about changing the name to be different from the model itself... + + detectPixelFormats(); +#ifdef V4L2_CAP_VIDEO_CAPTURE + enumerateControls(); +#endif +// TODO: Now we must execute the proper initialization according to the type of the driver. + kDebug() << "checkDevice() exited successfuly."; + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} + + +/*! + \fn VideoDevice::showDeviceCapabilities() + */ +int VideoDevice::showDeviceCapabilities() +{ + kDebug() << "showDeviceCapabilities() called."; + if(isOpen()) + { +/* kDebug() << "libkopete (avdevice): Driver: " << (const char*)V4L2_capabilities.driver << " " + << ((V4L2_capabilities.version>>16) & 0xFF) << "." + << ((V4L2_capabilities.version>> 8) & 0xFF) << "." + << ((V4L2_capabilities.version ) & 0xFF) << endl; + kDebug() << "libkopete (avdevice): Device: " << name; + kDebug() << "libkopete (avdevice): Capabilities:"; + if(V4L2_capabilities.capabilities & V4L2_CAP_VIDEO_CAPTURE) + kDebug() << "libkopete (avdevice): Video capture"; + if(V4L2_capabilities.capabilities & V4L2_CAP_VIDEO_OUTPUT) + kDebug() << "libkopete (avdevice): Video output"; + if(V4L2_capabilities.capabilities & V4L2_CAP_VIDEO_OVERLAY) + kDebug() << "libkopete (avdevice): Video overlay"; + if(V4L2_capabilities.capabilities & V4L2_CAP_VBI_CAPTURE) + kDebug() << "libkopete (avdevice): VBI capture"; + if(V4L2_capabilities.capabilities & V4L2_CAP_VBI_OUTPUT) + kDebug() << "libkopete (avdevice): VBI output"; + if(V4L2_capabilities.capabilities & V4L2_CAP_RDS_CAPTURE) + kDebug() << "libkopete (avdevice): RDS capture"; + if(V4L2_capabilities.capabilities & V4L2_CAP_TUNER) + kDebug() << "libkopete (avdevice): Tuner IO"; + if(V4L2_capabilities.capabilities & V4L2_CAP_AUDIO) + kDebug() << "libkopete (avdevice): Audio IO"; +;*/ + kDebug() << "Device model: " << m_model; + kDebug() << "Device name : " << m_name; + kDebug() << "Capabilities:"; + if(canCapture()) + kDebug() << " Video capture"; + if(canRead()) + kDebug() << " Read"; + if(canAsyncIO()) + kDebug() << " Asynchronous input/output"; + if(canStream()) + kDebug() << " Streaming"; + if(canChromakey()) + kDebug() << " Video chromakey"; + if(canScale()) + kDebug() << " Video scales"; + if(canOverlay()) + kDebug() << " Video overlay"; +// kDebug() << "libkopete (avdevice): Audios : " << V4L_capabilities.audios; + kDebug() << " Max res: " << maxWidth() << " x " << maxHeight(); + kDebug() << " Min res: " << minWidth() << " x " << minHeight(); + kDebug() << " Inputs : " << inputs(); + for (int loop=0; loop < inputs(); loop++) + kDebug() << "Input " << loop << ": " << m_input[loop].name << " (tuner: " << m_input[loop].hastuner << ")"; + kDebug() << "showDeviceCapabilities() exited successfuly."; + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} + +/*! + \fn VideoDevicePool::initDevice() + */ +int VideoDevice::initDevice() +{ + /// @todo implement me + kDebug() << "initDevice() started"; + if(-1 == descriptor) + { + kDebug() << "initDevice() Device is not open"; + return EXIT_FAILURE; + } + m_io_method = IO_METHOD_NONE; + switch(m_driver) + { +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + case VIDEODEV_DRIVER_V4L2: + if(V4L2_capabilities.capabilities & V4L2_CAP_READWRITE) + { + m_videoread=true; + m_io_method = IO_METHOD_READ; + kDebug() << " Read/Write interface"; + } + if(V4L2_capabilities.capabilities & V4L2_CAP_ASYNCIO) + { + m_videoasyncio=true; + kDebug() << " Async IO interface"; + } + if(V4L2_capabilities.capabilities & V4L2_CAP_STREAMING) + { + m_videostream=true; + m_io_method = IO_METHOD_MMAP; +// m_io_method = IO_METHOD_USERPTR; + kDebug() << " Streaming interface"; + } + if(m_io_method==IO_METHOD_NONE) + { + kDebug() << "initDevice() Found no suitable input/output method for " << full_filename; + return EXIT_FAILURE; + } + break; +#endif + case VIDEODEV_DRIVER_V4L: + m_videoread=true; + m_io_method=IO_METHOD_READ; + if(-1 != xioctl(VIDIOCGFBUF,&V4L_videobuffer)) + { +// m_videostream=true; +// m_io_method = IO_METHOD_MMAP; + kDebug() << " Streaming interface"; + } + break; +#endif + case VIDEODEV_DRIVER_NONE: + default: + + break; + } + +// Select video input, video standard and tune here. +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == xioctl (VIDIOC_CROPCAP, &cropcap)) + { // Errors ignored. + } + crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + crop.c = cropcap.defrect; // reset to default + if (-1 == xioctl (VIDIOC_S_CROP, &crop)) + { + switch (errno) + { + case EINVAL: break; // Cropping not supported. + default: break; // Errors ignored. + } + } +#endif +#endif + + showDeviceCapabilities(); + kDebug() << "initDevice() exited successfuly"; + return EXIT_SUCCESS; +} + +int VideoDevice::inputs() +{ + return m_input.size(); +} + + +int VideoDevice::width() +{ + return currentwidth; +} + +int VideoDevice::minWidth() +{ + return minwidth; +} + +int VideoDevice::maxWidth() +{ + return maxwidth; +} + +int VideoDevice::height() +{ + return currentheight; +} + +int VideoDevice::minHeight() +{ + return minheight; +} + +int VideoDevice::maxHeight() +{ + return maxheight; +} + +int VideoDevice::setSize( int newwidth, int newheight) +{ +kDebug() << "setSize(" << newwidth << ", " << newheight << ") called."; + if(isOpen()) + { +// It should not be there. It must remain in a completely distict place, cause this method should not change the pixelformat. +// It shouldn't try to find a suitable pixel format this way. It should use values discovered by - detectPixelFormats() - to choose a valid one. + kDebug() << "Trying YUY422P"; + if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_YUV422P)) + { + kDebug() << "Device doesn't seem to support YUV422P format. Trying YUYV."; + if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_YUYV)) + { + kDebug() << "Device doesn't seem to support YUYV format. Trying UYVY."; + if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_UYVY)) + { + kDebug() << "Device doesn't seem to support UYVY format. Trying YUV420P."; + if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_YUV420P)) + { + kDebug() << "Device doesn't seem to support YUV420P format. Trying RGB24."; + if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_RGB24)) + { + kDebug() << "Device doesn't seem to support RGB24 format. Trying BGR24."; + if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_BGR24)) + { + kDebug() << "Device doesn't seem to support RGB24 format. Trying RGB32."; + if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_RGB32)) + { + kDebug() << "Device doesn't seem to support RGB32 format. Trying BGR32."; + if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_BGR32)) + { + kDebug() << "Device doesn't seem to support BGR32 format. Trying SBGGR8."; + if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_SBGGR8)) + { + kDebug() << "Device doesn't seem to support SBGGR8 format. Trying SN9C10X."; + if(PIXELFORMAT_NONE == setPixelFormat(PIXELFORMAT_SN9C10X)) + kDebug() << "Device doesn't seem to support BGR32 format. Fallback to it is not yet implemented."; + } + } + } + } + } + } + } + } + } + + if(newwidth > maxwidth ) newwidth = maxwidth; + if(newheight > maxheight) newheight = maxheight; + if(newwidth < minwidth ) newwidth = minwidth; + if(newheight < minheight) newheight = minheight; + + currentwidth = newwidth; + currentheight = newheight; + +//kDebug() << "width: " << pixelFormatName(fmt.fmt.pix.pixelformat) << " " << width() << "x" << height(); +// Change resolution for the video device + switch(m_driver) + { +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + case VIDEODEV_DRIVER_V4L2: +// CLEAR (fmt); + if (-1 == xioctl (VIDIOC_G_FMT, &fmt)) + kDebug() << "VIDIOC_G_FMT failed (" << errno << ").Returned width: " << pixelFormatName(fmt.fmt.pix.pixelformat) << " " << fmt.fmt.pix.width << "x" << fmt.fmt.pix.height; + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.fmt.pix.width = width(); + fmt.fmt.pix.height = height(); + fmt.fmt.pix.field = V4L2_FIELD_ANY; + if (-1 == xioctl (VIDIOC_S_FMT, &fmt)) + { + kDebug() << "VIDIOC_S_FMT failed (" << errno << ").Returned width: " << pixelFormatName(fmt.fmt.pix.pixelformat) << " " << fmt.fmt.pix.width << "x" << fmt.fmt.pix.height; + // Note VIDIOC_S_FMT may change width and height. + } + else + { +// Buggy driver paranoia. +kDebug() << "VIDIOC_S_FMT worked (" << errno << ").Returned width: " << pixelFormatName(fmt.fmt.pix.pixelformat) << " " << fmt.fmt.pix.width << "x" << fmt.fmt.pix.height; + unsigned int min = fmt.fmt.pix.width * 2; + if (fmt.fmt.pix.bytesperline < min) + fmt.fmt.pix.bytesperline = min; + min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height; + if (fmt.fmt.pix.sizeimage < min) + fmt.fmt.pix.sizeimage = min; + m_buffer_size=fmt.fmt.pix.sizeimage ; + } + break; +#endif + case VIDEODEV_DRIVER_V4L: + { + struct video_window V4L_videowindow; + + if (xioctl (VIDIOCGWIN, &V4L_videowindow)== -1) + { + perror ("ioctl VIDIOCGWIN"); +// return (NULL); + } + V4L_videowindow.width = width(); + V4L_videowindow.height = height(); + V4L_videowindow.clipcount=0; + if (xioctl (VIDIOCSWIN, &V4L_videowindow)== -1) + { + perror ("ioctl VIDIOCSWIN"); +// return (NULL); + } +kDebug() << "------------- width: " << V4L_videowindow.width << " Height: " << V4L_videowindow.height << " Clipcount: " << V4L_videowindow.clipcount << " -----------------"; + +// kDebug() << "libkopete (avdevice): V4L_picture.palette: " << V4L_picture.palette << " Depth: " << V4L_picture.depth; + +/* if(-1 == xioctl(VIDIOCGFBUF,&V4L_videobuffer)) + kDebug() << "libkopete (avdevice): VIDIOCGFBUF failed (" << errno << "): Device cannot stream";*/ + + } + break; +#endif + case VIDEODEV_DRIVER_NONE: + default: + break; + } + m_buffer_size = width() * height() * pixelFormatDepth(m_pixelformat) / 8; +kDebug() << "------------------------- ------- -- m_buffer_size: " << m_buffer_size << " !!! -- ------- -----------------------------------------"; + + m_currentbuffer.pixelformat=m_pixelformat; + m_currentbuffer.data.resize(m_buffer_size); + + switch (m_io_method) + { + case IO_METHOD_NONE: break; + case IO_METHOD_READ: initRead (); break; + case IO_METHOD_MMAP: initMmap (); break; + case IO_METHOD_USERPTR: initUserptr (); break; + } + +kDebug() << "setSize(" << newwidth << ", " << newheight << ") exited successfuly."; + return EXIT_SUCCESS; + } +kDebug() << "setSize(" << newwidth << ", " << newheight << ") Device is not open."; + return EXIT_FAILURE; +} + + + + + + + + + + + + + +pixel_format VideoDevice::setPixelFormat(pixel_format newformat) +{ + pixel_format ret = PIXELFORMAT_NONE; +//kDebug() << "called."; +// Change the pixel format for the video device + switch(m_driver) + { +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + case VIDEODEV_DRIVER_V4L2: +// CLEAR (fmt); + if (-1 == xioctl (VIDIOC_G_FMT, &fmt)) + { +// return errnoReturn ("VIDIOC_S_FMT"); +// kDebug() << "VIDIOC_G_FMT failed (" << errno << ").Returned width: " << pixelFormatName(fmt.fmt.pix.pixelformat) << " " << fmt.fmt.pix.width << "x" << fmt.fmt.pix.height; + } + else + m_pixelformat = pixelFormatForPalette(fmt.fmt.pix.pixelformat); + + fmt.fmt.pix.pixelformat = pixelFormatCode(newformat); + if (-1 == xioctl (VIDIOC_S_FMT, &fmt)) + { +// kDebug() << "VIDIOC_S_FMT failed (" << errno << ").Returned width: " << pixelFormatName(fmt.fmt.pix.pixelformat) << " " << fmt.fmt.pix.width << "x" << fmt.fmt.pix.height; + } + else + { + if (fmt.fmt.pix.pixelformat == pixelFormatCode(newformat)) // Thih "if" (not what is contained within) is a fix for a bug in sn9c102 driver. + { + m_pixelformat = newformat; + ret = m_pixelformat; + } + } + break; +#endif + case VIDEODEV_DRIVER_V4L: + { + struct video_picture V4L_picture; + if(-1 == xioctl(VIDIOCGPICT, &V4L_picture)) + kDebug() << "VIDIOCGPICT failed (" << errno << ")."; +// kDebug() << "V4L_picture.palette: " << V4L_picture.palette << " Depth: " << V4L_picture.depth; + V4L_picture.palette = pixelFormatCode(newformat); + V4L_picture.depth = pixelFormatDepth(newformat); + if(-1 == xioctl(VIDIOCSPICT,&V4L_picture)) + { +// kDebug() << "Device seems to not support " << pixelFormatName(newformat) << " format. Fallback to it is not yet implemented."; + } + + if(-1 == xioctl(VIDIOCGPICT, &V4L_picture)) + kDebug() << "VIDIOCGPICT failed (" << errno << ")."; + +// kDebug() << "V4L_picture.palette: " << V4L_picture.palette << " Depth: " << V4L_picture.depth; + m_pixelformat=pixelFormatForPalette(V4L_picture.palette); + if (m_pixelformat == newformat) + ret = newformat; + + } + break; +#endif + case VIDEODEV_DRIVER_NONE: + default: + break; + } + return ret; +} + + + + + + +/*! + \fn Kopete::AV::VideoDevice::currentInput() + */ +int VideoDevice::currentInput() +{ + /// @todo implement me + if(isOpen()) + { + return m_current_input; + } + return 0; +} + +/*! + \fn Kopete::AV::VideoDevice::selectInput(int input) + */ +int VideoDevice::selectInput(int newinput) +{ + /// @todo implement me + if(m_current_input >= inputs()) + return EXIT_FAILURE; + + if(isOpen()) + { + switch (m_driver) + { +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + case VIDEODEV_DRIVER_V4L2: + if (-1 == ioctl (descriptor, VIDIOC_S_INPUT, &newinput)) + { + perror ("VIDIOC_S_INPUT"); + return EXIT_FAILURE; + } + break; +#endif + case VIDEODEV_DRIVER_V4L: + struct video_channel V4L_input; + V4L_input.channel=newinput; + V4L_input.norm=4; // Hey, it's plain wrong! It should be input's signal standard! + if (-1 == ioctl (descriptor, VIDIOCSCHAN, &V4L_input)) + { + perror ("ioctl (VIDIOCSCHAN)"); + return EXIT_FAILURE; + } + break; +#endif + case VIDEODEV_DRIVER_NONE: + default: + break; + } + kDebug() << "Selected input " << newinput << " (" << m_input[newinput].name << ")"; + m_current_input = newinput; + setInputParameters(); + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} + +/*! + \fn Kopete::AV::VideoDevice::setInputParameters() + */ +int VideoDevice::setInputParameters() +{ + /// @todo implement me + if( (isOpen()) && (m_current_input < inputs() ) ) + { + setBrightness( getBrightness() ); + setContrast( getContrast() ); + setSaturation( getSaturation() ); + setWhiteness( getWhiteness() ); + setHue( getHue() ); + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} + +/*! + \fn VideoDevice::startCapturing() + */ +int VideoDevice::startCapturing() +{ + + kDebug() << "called."; + if(isOpen()) + { + switch (m_io_method) + { + case IO_METHOD_NONE: // Device cannot capture frames + return EXIT_FAILURE; + break; + case IO_METHOD_READ: // Nothing to do + break; + case IO_METHOD_MMAP: +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + { + unsigned int loop; + for (loop = 0; loop < m_streambuffers; ++loop) + { + struct v4l2_buffer buf; + CLEAR (buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = loop; + if (-1 == xioctl (VIDIOC_QBUF, &buf)) + return errnoReturn ("VIDIOC_QBUF"); + } + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == xioctl (VIDIOC_STREAMON, &type)) + return errnoReturn ("VIDIOC_STREAMON"); + } +#endif +#endif + break; + case IO_METHOD_USERPTR: +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + { + unsigned int loop; + for (loop = 0; loop < m_streambuffers; ++loop) + { + struct v4l2_buffer buf; + CLEAR (buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_USERPTR; + buf.m.userptr = (unsigned long) m_rawbuffers[loop].start; + buf.length = m_rawbuffers[loop].length; + if (-1 == xioctl (VIDIOC_QBUF, &buf)) + return errnoReturn ("VIDIOC_QBUF"); + } + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == xioctl (VIDIOC_STREAMON, &type)) + return errnoReturn ("VIDIOC_STREAMON"); + } +#endif +#endif + break; + } + + kDebug() << "exited successfuly."; + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} + +/*! + \fn VideoDevice::getFrame() + */ +int VideoDevice::getFrame() +{ + /// @todo implement me + ssize_t bytesread; + +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + struct v4l2_buffer v4l2buffer; +#endif +#endif +// kDebug() << "getFrame() called."; + if(isOpen()) + { + switch (m_io_method) + { + case IO_METHOD_NONE: // Device cannot capture frames + return EXIT_FAILURE; + break; + case IO_METHOD_READ: +// kDebug() << "Using IO_METHOD_READ.File descriptor: " << descriptor << " Buffer address: " << &m_currentbuffer.data[0] << " Size: " << m_currentbuffer.data.size(); + bytesread = read (descriptor, &m_currentbuffer.data[0], m_currentbuffer.data.size()); + if (-1 == bytesread) // must verify this point with ov511 driver. + { + kDebug() << "IO_METHOD_READ failed."; + switch (errno) + { + case EAGAIN: + return EXIT_FAILURE; + case EIO: /* Could ignore EIO, see spec. fall through */ + default: + return errnoReturn ("read"); + } + } + if((int)m_currentbuffer.data.size() < bytesread) + { + kDebug() << "IO_METHOD_READ returned less bytes (" << bytesread << ") than it was asked for (" << m_currentbuffer.data.size() <<")."; + } + break; + case IO_METHOD_MMAP: +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + CLEAR (v4l2buffer); + v4l2buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + v4l2buffer.memory = V4L2_MEMORY_MMAP; + if (-1 == xioctl (VIDIOC_DQBUF, &v4l2buffer)) + { + kDebug() << full_filename << " MMAPed getFrame failed."; + switch (errno) + { + case EAGAIN: + { + kDebug() << full_filename << " MMAPed getFrame failed: EAGAIN. Pointer: "; + return EXIT_FAILURE; + } + case EIO: /* Could ignore EIO, see spec. fall through */ + default: + return errnoReturn ("VIDIOC_DQBUF"); + } + } +/* if (v4l2buffer.index < m_streambuffers) + return EXIT_FAILURE;*/ //it was an assert() +// kDebug() << "m_rawbuffers[" << v4l2buffer.index << "].start: " << (void *)m_rawbuffers[v4l2buffer.index].start << " Size: " << m_currentbuffer.data.size(); + +memcpy(&m_currentbuffer.data[0], m_rawbuffers[v4l2buffer.index].start, m_currentbuffer.data.size()); + if (-1 == xioctl (VIDIOC_QBUF, &v4l2buffer)) + return errnoReturn ("VIDIOC_QBUF"); +#endif +#endif + break; + case IO_METHOD_USERPTR: +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + { + unsigned int i; + CLEAR (v4l2buffer); + v4l2buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + v4l2buffer.memory = V4L2_MEMORY_USERPTR; + if (-1 == xioctl (VIDIOC_DQBUF, &v4l2buffer)) + { + switch (errno) + { + case EAGAIN: + return EXIT_FAILURE; + case EIO: /* Could ignore EIO, see spec. fall through */ + default: + return errnoReturn ("VIDIOC_DQBUF"); + } + } + for (i = 0; i < m_streambuffers; ++i) + if (v4l2buffer.m.userptr == (unsigned long) m_rawbuffers[i].start && v4l2buffer.length == m_rawbuffers[i].length) + break; + if (i < m_streambuffers) + return EXIT_FAILURE; + if (-1 == xioctl (VIDIOC_QBUF, &v4l2buffer)) + return errnoReturn ("VIDIOC_QBUF"); + } +#endif +#endif + break; + } +// kDebug() << "exited successfuly."; + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} + +/*! + \fn VideoDevice::getFrame(imagebuffer *imgbuffer) + */ +int VideoDevice::getFrame(imagebuffer *imgbuffer) +{ + if(imgbuffer) + { + getFrame(); + imgbuffer->height = m_currentbuffer.height; + imgbuffer->width = m_currentbuffer.width; + imgbuffer->pixelformat = m_currentbuffer.pixelformat; + imgbuffer->data = m_currentbuffer.data; + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} + +/*! + \fn Kopete::AV::VideoDevice::getImage(const QImage *qimage) + */ +int VideoDevice::getImage(QImage *qimage) +{ + /// @todo implement me + + // do NOT delete qimage here, as it is received as a parameter + if (qimage->width() != width() || qimage->height() != height()) + *qimage = QImage(width(), height(), QImage::Format_RGB32); + + uchar *bits=qimage->bits(); +// kDebug() << "Capturing in " << pixelFormatName(m_currentbuffer.pixelformat); + switch(m_currentbuffer.pixelformat) + { + case PIXELFORMAT_NONE : break; + +// Packed RGB formats + case PIXELFORMAT_RGB332 : + { + int step=0; + for(int loop=0;loop < qimage->numBytes();loop+=4) + { + bits[loop] = (m_currentbuffer.data[step]>>5<<5)+(m_currentbuffer.data[step]>>5<<2)+(m_currentbuffer.data[step]>>6); + bits[loop+1] = (m_currentbuffer.data[step]>>2<<5)+(m_currentbuffer.data[step]<<3>>5<<2)+(m_currentbuffer.data[step]<<3>>6); + bits[loop+2] = (m_currentbuffer.data[step]<<6)+(m_currentbuffer.data[step]<<6>>2)+(m_currentbuffer.data[step]<<6>>4)+(m_currentbuffer.data[step]<<6>>6); + bits[loop+3] = 255; + step++; + } + } + break; + case PIXELFORMAT_RGB444 : break; + case PIXELFORMAT_RGB555 : break; + case PIXELFORMAT_RGB565 : + { + int step=0; + for(int loop=0;loop < qimage->numBytes();loop+=4) + { + bits[loop] = (m_currentbuffer.data[step]<<3)+(m_currentbuffer.data[step]<<3>>5); + bits[loop+1] = ((m_currentbuffer.data[step+1])<<5)|m_currentbuffer.data[step]>>5; + bits[loop+2] = ((m_currentbuffer.data[step+1])&248)+((m_currentbuffer.data[step+1])>>5); + bits[loop+3] = 255; + step+=2; + } + } + break; + case PIXELFORMAT_RGB555X: break; + case PIXELFORMAT_RGB565X: break; + case PIXELFORMAT_BGR24 : + { + int step=0; + for(int loop=0;loop < qimage->numBytes();loop+=4) + { + bits[loop] = m_currentbuffer.data[step+2]; + bits[loop+1] = m_currentbuffer.data[step+1]; + bits[loop+2] = m_currentbuffer.data[step]; + bits[loop+3] = 255; + step+=3; + } + } + break; + case PIXELFORMAT_RGB24 : + { + int step=0; + for(int loop=0;loop < qimage->numBytes();loop+=4) + { + bits[loop] = m_currentbuffer.data[step]; + bits[loop+1] = m_currentbuffer.data[step+1]; + bits[loop+2] = m_currentbuffer.data[step+2]; + bits[loop+3] = 255; + step+=3; + } + } + break; + case PIXELFORMAT_BGR32 : + { + int step=0; + for(int loop=0;loop < qimage->numBytes();loop+=4) + { + bits[loop] = m_currentbuffer.data[step+2]; + bits[loop+1] = m_currentbuffer.data[step+1]; + bits[loop+2] = m_currentbuffer.data[step]; + bits[loop+3] = m_currentbuffer.data[step+3]; + step+=4; + } + } + break; + case PIXELFORMAT_RGB32 : memcpy(bits,&m_currentbuffer.data[0], m_currentbuffer.data.size()); + break; + +// Bayer RGB format + case PIXELFORMAT_SBGGR8 : + { + unsigned char *d = (unsigned char *) malloc (width() * height() * 3); + bayer2rgb24(d, &m_currentbuffer.data.first(), width(), height()); + int step=0; + for(int loop=0;loop < qimage->numBytes();loop+=4) + { + bits[loop] = d[step+2]; + bits[loop+1] = d[step+1]; + bits[loop+2] = d[step]; + bits[loop+3] = 255; + step+=3; + } + free(d); + } + break; + +// YUV formats + case PIXELFORMAT_GREY : + { + int step=0; + for(int loop=0;loop < qimage->numBytes();loop+=4) + { + bits[loop] = m_currentbuffer.data[step]; + bits[loop+1] = m_currentbuffer.data[step]; + bits[loop+2] = m_currentbuffer.data[step]; + bits[loop+3] = 255; + step++; + } + } + break; + case PIXELFORMAT_YUYV: + case PIXELFORMAT_UYVY: + case PIXELFORMAT_YUV420P: + case PIXELFORMAT_YUV422P: + { + uchar *yptr, *cbptr, *crptr; + bool halfheight=false; + bool packed=false; +// Adjust algorythm to specific YUV data arrangements. + if (m_currentbuffer.pixelformat == PIXELFORMAT_YUV420P) + halfheight=true; + if (m_currentbuffer.pixelformat == PIXELFORMAT_YUYV) + { + yptr = &m_currentbuffer.data[0]; + cbptr = yptr + 1; + crptr = yptr + 3; + packed=true; + } + else if (m_currentbuffer.pixelformat == PIXELFORMAT_UYVY) + { + cbptr = &m_currentbuffer.data[0]; + yptr = cbptr + 1; + crptr = cbptr + 2; + packed=true; + } + else + { + yptr = &m_currentbuffer.data[0]; + cbptr = yptr + (width()*height()); + crptr = cbptr + (width()*height()/(halfheight ? 4:2)); + } + + for(int y=0; y>1<<2])-128; + e = (crptr[x>>1<<2])-128; + } + else + { + c = (yptr[x])-16; + d = (cbptr[x>>1])-128; + e = (crptr[x>>1])-128; + } + + int r = (298 * c + 409 * e + 128)>>8; + int g = (298 * c - 100 * d - 208 * e + 128)>>8; + int b = (298 * c + 516 * d + 128)>>8; + + if (r<0) r=0; if (r>255) r=255; + if (g<0) g=0; if (g>255) g=255; + if (b<0) b=0; if (b>255) b=255; + + uint *p = (uint*)qimage->scanLine(y)+x; + *p = qRgba(r,g,b,255); + + } +// Jump to next line + if (packed) + { + yptr+=width()*2; + cbptr+=width()*2; + crptr+=width()*2; + } + else + { + yptr+=width(); + if (!halfheight || y&1) + { + cbptr+=width()/2; + crptr+=width()/2; + } + } + } + } + break; + +// Compressed formats + case PIXELFORMAT_JPEG : break; + case PIXELFORMAT_MPEG : break; + +// Reserved formats + case PIXELFORMAT_DV : break; + case PIXELFORMAT_ET61X251:break; + case PIXELFORMAT_HI240 : break; + case PIXELFORMAT_HM12 : break; + case PIXELFORMAT_MJPEG : break; + case PIXELFORMAT_PWC1 : break; + case PIXELFORMAT_PWC2 : break; + case PIXELFORMAT_SN9C10X: + { + unsigned char *s = new unsigned char [width() * height()]; + unsigned char *d = new unsigned char [width() * height() * 3]; + sonix_decompress_init(); + sonix_decompress(width(), height(), &m_currentbuffer.data.first(), s); + bayer2rgb24(d, s, width(), height()); + int step=0; + for(int loop=0;loop < qimage->numBytes();loop+=4) + { + bits[loop] = d[step+2]; + bits[loop+1] = d[step+1]; + bits[loop+2] = d[step]; + bits[loop+3] = 255; + step+=3; + } + delete[] s; + delete[] d; + } + case PIXELFORMAT_WNVA : break; + case PIXELFORMAT_YYUV : break; + } + +// Proccesses image for automatic Brightness/Contrast/Color correction + if (getAutoBrightnessContrast()||getAutoColorCorrection()) + { + unsigned long long result=0; + unsigned long long R=0, G=0, B=0, A=0, global=0; + int Rmax=0, Gmax=0, Bmax=0, Amax=0, globalmax=0; + int Rmin=255, Gmin=255, Bmin=255, Amin=255, globalmin=255; + int Rrange=255, Grange=255, Brange=255, Arange=255, globarange=255; + +// Finds minimum and maximum intensity for each color component + for(unsigned int loop=0;loop < qimage->numBytes();loop+=4) + { + R+=bits[loop]; + G+=bits[loop+1]; + B+=bits[loop+2]; +// A+=bits[loop+3]; + if (bits[loop] < Rmin) Rmin = bits[loop]; + if (bits[loop+1] < Gmin) Gmin = bits[loop+1]; + if (bits[loop+2] < Bmin) Bmin = bits[loop+2]; +// if (bits[loop+3] < Amin) Amin = bits[loop+3]; + if (bits[loop] > Rmax) Rmax = bits[loop]; + if (bits[loop+1] > Gmax) Gmax = bits[loop+1]; + if (bits[loop+2] > Bmax) Bmax = bits[loop+2]; +// if (bits[loop+3] > Amax) Amax = bits[loop+3]; + } + global = R + G + B; +// Finds overall minimum and maximum intensity + if (Rmin > Gmin) globalmin = Gmin; else globalmin = Rmin; if (Bmin < globalmin) globalmin = Bmin; + if (Rmax > Gmax) globalmax = Rmax; else globalmax = Gmax; if (Bmax > globalmax) globalmax = Bmax; +// If no color correction should be performed, simply level all the intensities so they're just the same. +// In fact color correction should use the R, G and B variables to detect color deviation and "bump up" the saturation, +// but it's computationally more expensive and the current way returns better results to the user. + if(!getAutoColorCorrection()) + { + Rmin = globalmin ; Rmax = globalmax; + Gmin = globalmin ; Gmax = globalmax; + Bmin = globalmin ; Bmax = globalmax; +// Amin = globalmin ; Amax = globalmax; + } +// Calculates ranges and prevent a division by zero later on. + Rrange = Rmax - Rmin; if (Rrange == 0) Rrange = 255; + Grange = Gmax - Gmin; if (Grange == 0) Grange = 255; + Brange = Bmax - Bmin; if (Brange == 0) Brange = 255; +// Arange = Amax - Amin; if (Arange == 0) Arange = 255; + + kDebug() << " R: " << R << " G: " << G << " B: " << B << " A: " << A << " global: " << global << + " Rmin: " << Rmin << " Gmin: " << Gmin << " Bmin: " << Bmin << " Amin: " << Amin << " globalmin: " << globalmin << + " Rmax: " << Rmax << " Gmax: " << Gmax << " Bmax: " << Bmax << " Amax: " << Amax << " globalmax: " << globalmax ; + + for(unsigned int loop=0;loop < qimage->numBytes();loop+=4) + { + bits[loop] = (bits[loop] - Rmin) * 255 / (Rrange); + bits[loop+1] = (bits[loop+1] - Gmin) * 255 / (Grange); + bits[loop+2] = (bits[loop+2] - Bmin) * 255 / (Brange); +// bits[loop+3] = (bits[loop+3] - Amin) * 255 / (Arange); + } + } + return EXIT_SUCCESS; +} + +/*! + \fn VideoDevice::stopCapturing() + */ +int VideoDevice::stopCapturing() +{ + /// @todo implement me + kDebug() << "called."; + if(isOpen()) + { + switch (m_io_method) + { + case IO_METHOD_NONE: // Device cannot capture frames + return EXIT_FAILURE; + break; + case IO_METHOD_READ: // Nothing to do + break; + case IO_METHOD_MMAP: + case IO_METHOD_USERPTR: +#ifdef V4L2_CAP_VIDEO_CAPTURE + { + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == xioctl (VIDIOC_STREAMOFF, &type)) + return errnoReturn ("VIDIOC_STREAMOFF"); + + if (m_io_method == IO_METHOD_MMAP) + { + unsigned int loop; + for (loop = 0; loop < m_streambuffers; ++loop) + { + if (munmap(m_rawbuffers[loop].start,m_rawbuffers[loop].length) != 0) + { + kDebug() << "unable to munmap."; + } + } + } + } +#endif + break; + } + kDebug() << "exited successfuly."; + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} + + +/*! + \fn VideoDevice::close() + */ +int VideoDevice::close() +{ + /// @todo implement me + kDebug() << " called."; + if(isOpen()) + { + kDebug() << " Device is open. Trying to properly shutdown the device."; + stopCapturing(); + kDebug() << "::close() returns " << ::close(descriptor); + } + descriptor = -1; + return EXIT_SUCCESS; +} + +float VideoDevice::getBrightness() +{ + if (m_current_input < m_input.size() ) + return m_input[m_current_input].getBrightness(); + else + return 0; +} + +float VideoDevice::setBrightness(float brightness) +{ + kDebug() << "(" << brightness << ") called."; + m_input[m_current_input].setBrightness(brightness); // Just to check bounds + + switch(m_driver) + { +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + case VIDEODEV_DRIVER_V4L2: + { + struct v4l2_queryctrl queryctrl; + struct v4l2_control control; + + CLEAR (queryctrl); + queryctrl.id = V4L2_CID_BRIGHTNESS; + + if (-1 == xioctl (VIDIOC_QUERYCTRL, &queryctrl)) + { + if (errno != EINVAL) + { + kDebug() << "VIDIOC_QUERYCTRL failed (" << errno << ")."; + } else + { + kDebug() << "Device doesn't support the Brightness control."; + } + } else + if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) + { + kDebug() << "Brightness control is disabled."; + } else + { + CLEAR (control); + control.id = V4L2_CID_BRIGHTNESS; + control.value = (__s32)((queryctrl.maximum - queryctrl.minimum)*getBrightness()); + + if (-1 == xioctl (VIDIOC_S_CTRL, &control)) + { + kDebug() << "VIDIOC_S_CTRL failed (" << errno << ")."; + } + } + } + break; +#endif + case VIDEODEV_DRIVER_V4L: + { + struct video_picture V4L_picture; + if(-1 == xioctl(VIDIOCGPICT, &V4L_picture)) + kDebug() << "VIDIOCGPICT failed (" << errno << ")."; + V4L_picture.brightness = uint(65535 * getBrightness()); + if(-1 == xioctl(VIDIOCSPICT,&V4L_picture)) + kDebug() << "Device seems to not support adjusting image brightness. Fallback to it is not yet implemented."; + } + break; +#endif + case VIDEODEV_DRIVER_NONE: + default: + break; + } + return getBrightness(); +} + +float VideoDevice::getContrast() +{ + if (m_current_input < m_input.size() ) + return m_input[m_current_input].getContrast(); + else + return 0; +} + +float VideoDevice::setContrast(float contrast) +{ + kDebug() << "(" << contrast << ") called."; + m_input[m_current_input].setContrast(contrast); // Just to check bounds + + switch(m_driver) + { +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + case VIDEODEV_DRIVER_V4L2: + { + struct v4l2_queryctrl queryctrl; + struct v4l2_control control; + + CLEAR (queryctrl); + queryctrl.id = V4L2_CID_CONTRAST; + + if (-1 == xioctl (VIDIOC_QUERYCTRL, &queryctrl)) + { + if (errno != EINVAL) + { + kDebug() << "VIDIOC_QUERYCTRL failed (" << errno << ")."; + } else + { + kDebug() << "Device doesn't support the Contrast control."; + } + } else + if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) + { + kDebug() << "Contrast control is disabled."; + } else + { + CLEAR (control); + control.id = V4L2_CID_CONTRAST; + control.value = (__s32)((queryctrl.maximum - queryctrl.minimum)*getContrast()); + + if (-1 == xioctl (VIDIOC_S_CTRL, &control)) + { + kDebug() << "VIDIOC_S_CTRL failed (" << errno << ")."; + } + } + } + break; +#endif + case VIDEODEV_DRIVER_V4L: + { + struct video_picture V4L_picture; + if(-1 == xioctl(VIDIOCGPICT, &V4L_picture)) + kDebug() << "VIDIOCGPICT failed (" << errno << ")."; + V4L_picture.contrast = uint(65535*getContrast()); + if(-1 == xioctl(VIDIOCSPICT,&V4L_picture)) + kDebug() << "Device seems to not support adjusting image contrast. Fallback to it is not yet implemented."; + } + break; +#endif + case VIDEODEV_DRIVER_NONE: + default: + break; + } + return getContrast(); +} + +float VideoDevice::getSaturation() +{ + if (m_current_input < m_input.size() ) + return m_input[m_current_input].getSaturation(); + else + return 0; +} + +float VideoDevice::setSaturation(float saturation) +{ + kDebug() << "(" << saturation << ") called."; + m_input[m_current_input].setSaturation(saturation); // Just to check bounds + + switch(m_driver) + { +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + case VIDEODEV_DRIVER_V4L2: + { + struct v4l2_queryctrl queryctrl; + struct v4l2_control control; + + CLEAR (queryctrl); + queryctrl.id = V4L2_CID_SATURATION; + + if (-1 == xioctl (VIDIOC_QUERYCTRL, &queryctrl)) + { + if (errno != EINVAL) + { + kDebug() << "VIDIOC_QUERYCTRL failed (" << errno << ")."; + } else + { + kDebug() << "Device doesn't support the Saturation control."; + } + } else + if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) + { + kDebug() << "Saturation control is disabled."; + } else + { + CLEAR (control); + control.id = V4L2_CID_SATURATION; + control.value = (__s32)((queryctrl.maximum - queryctrl.minimum)*getSaturation()); + + if (-1 == xioctl (VIDIOC_S_CTRL, &control)) + { + kDebug() << "VIDIOC_S_CTRL failed (" << errno << ")."; + } + } + } + break; +#endif + case VIDEODEV_DRIVER_V4L: + { + struct video_picture V4L_picture; + if(-1 == xioctl(VIDIOCGPICT, &V4L_picture)) + kDebug() << "VIDIOCGPICT failed (" << errno << ")."; + V4L_picture.colour = uint(65535*getSaturation()); + if(-1 == xioctl(VIDIOCSPICT,&V4L_picture)) + kDebug() << "Device seems to not support adjusting image saturation. Fallback to it is not yet implemented."; + } + break; +#endif + case VIDEODEV_DRIVER_NONE: + default: + break; + } + return getSaturation(); +} + +float VideoDevice::getWhiteness() +{ + if (m_current_input < m_input.size() ) + return m_input[m_current_input].getWhiteness(); + else + return 0; +} + +float VideoDevice::setWhiteness(float whiteness) +{ + kDebug() << "(" << whiteness << ") called."; + m_input[m_current_input].setWhiteness(whiteness); // Just to check bounds + + switch(m_driver) + { +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + case VIDEODEV_DRIVER_V4L2: + { + struct v4l2_queryctrl queryctrl; + struct v4l2_control control; + + CLEAR (queryctrl); + queryctrl.id = V4L2_CID_WHITENESS; + + if (-1 == xioctl (VIDIOC_QUERYCTRL, &queryctrl)) + { + if (errno != EINVAL) + { + kDebug() << "VIDIOC_QUERYCTRL failed (" << errno << ")."; + } else + { + kDebug() << "Device doesn't support the Whiteness control."; + } + } else + if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) + { + kDebug() << "Whiteness control is disabled."; + } else + { + CLEAR (control); + control.id = V4L2_CID_WHITENESS; + control.value = (__s32)((queryctrl.maximum - queryctrl.minimum)*getWhiteness()); + + if (-1 == xioctl (VIDIOC_S_CTRL, &control)) + { + kDebug() << "VIDIOC_S_CTRL failed (" << errno << ")."; + } + } + } + break; +#endif + case VIDEODEV_DRIVER_V4L: + { + struct video_picture V4L_picture; + if(-1 == xioctl(VIDIOCGPICT, &V4L_picture)) + kDebug() << "VIDIOCGPICT failed (" << errno << ")."; + V4L_picture.whiteness = uint(65535*getWhiteness()); + if(-1 == xioctl(VIDIOCSPICT,&V4L_picture)) + kDebug() << "Device seems to not support adjusting white level. Fallback to it is not yet implemented."; + } + break; +#endif + case VIDEODEV_DRIVER_NONE: + default: + break; + } + return getWhiteness(); +} + +float VideoDevice::getHue() +{ + if (m_current_input < m_input.size() ) + return m_input[m_current_input].getHue(); + else + return 0; +} + +float VideoDevice::setHue(float hue) +{ + kDebug() << "(" << hue << ") called."; + m_input[m_current_input].setHue(hue); // Just to check bounds + + switch(m_driver) + { +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + case VIDEODEV_DRIVER_V4L2: + { + struct v4l2_queryctrl queryctrl; + struct v4l2_control control; + + CLEAR (queryctrl); + queryctrl.id = V4L2_CID_HUE; + + if (-1 == xioctl (VIDIOC_QUERYCTRL, &queryctrl)) + { + if (errno != EINVAL) + { + kDebug() << "VIDIOC_QUERYCTRL failed (" << errno << ")."; + } else + { + kDebug() << "Device doesn't support the Hue control."; + } + } else + if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) + { + kDebug() << "Hue control is disabled."; + } else + { + CLEAR (control); + control.id = V4L2_CID_HUE; + control.value = (__s32)((queryctrl.maximum - queryctrl.minimum)*getHue()); + + if (-1 == xioctl (VIDIOC_S_CTRL, &control)) + { + kDebug() << "VIDIOC_S_CTRL failed (" << errno << ")."; + } + } + } + break; +#endif + case VIDEODEV_DRIVER_V4L: + { + struct video_picture V4L_picture; + if(-1 == xioctl(VIDIOCGPICT, &V4L_picture)) + kDebug() << "VIDIOCGPICT failed (" << errno << ")."; + V4L_picture.hue = uint(65535*getHue()); + if(-1 == xioctl(VIDIOCSPICT,&V4L_picture)) + kDebug() << "Device seems to not support adjusting image hue. Fallback to it is not yet implemented."; + } + break; +#endif + case VIDEODEV_DRIVER_NONE: + default: + break; + } + return getHue(); +} + + +bool VideoDevice::getAutoBrightnessContrast() +{ + if (m_current_input < m_input.size() ) + return m_input[m_current_input].getAutoBrightnessContrast(); + else + return false; +} + +bool VideoDevice::setAutoBrightnessContrast(bool brightnesscontrast) +{ + kDebug() << "VideoDevice::setAutoBrightnessContrast(" << brightnesscontrast << ") called."; + if (m_current_input < m_input.size() ) + { + m_input[m_current_input].setAutoBrightnessContrast(brightnesscontrast); + return m_input[m_current_input].getAutoBrightnessContrast(); + } + else + return false; + +} + +bool VideoDevice::getAutoColorCorrection() +{ + if (m_current_input < m_input.size() ) + return m_input[m_current_input].getAutoColorCorrection(); + else + return false; +} + +bool VideoDevice::setAutoColorCorrection(bool colorcorrection) +{ + kDebug() << "VideoDevice::setAutoColorCorrection(" << colorcorrection << ") called."; + if (m_current_input < m_input.size() ) + { + m_input[m_current_input].setAutoColorCorrection(colorcorrection); + return m_input[m_current_input].getAutoColorCorrection(); + } + else + return false; +} + +bool VideoDevice::getImageAsMirror() +{ + if (m_current_input < m_input.size() ) + return m_input[m_current_input].getImageAsMirror(); + else + return false; +} + +bool VideoDevice::setImageAsMirror(bool imageasmirror) +{ + kDebug() << "VideoDevice::setImageAsMirror(" << imageasmirror << ") called."; + if (m_current_input < m_input.size() ) + { + m_input[m_current_input].setImageAsMirror(imageasmirror); + return m_input[m_current_input].getImageAsMirror(); + } + else + return false; +} + +pixel_format VideoDevice::pixelFormatForPalette( int palette ) +{ + switch(m_driver) + { +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + case VIDEODEV_DRIVER_V4L2: + switch(palette) + { + case 0 : return PIXELFORMAT_NONE; break; + +// Packed RGB formats + case V4L2_PIX_FMT_RGB332 : return PIXELFORMAT_RGB332; break; +#if defined( V4L2_PIX_FMT_RGB444 ) + case V4L2_PIX_FMT_RGB444 : return PIXELFORMAT_RGB444; break; +#endif + case V4L2_PIX_FMT_RGB555 : return PIXELFORMAT_RGB555; break; + case V4L2_PIX_FMT_RGB565 : return PIXELFORMAT_RGB565; break; + case V4L2_PIX_FMT_RGB555X : return PIXELFORMAT_RGB555X; break; + case V4L2_PIX_FMT_RGB565X : return PIXELFORMAT_RGB565X; break; + case V4L2_PIX_FMT_BGR24 : return PIXELFORMAT_BGR24; break; + case V4L2_PIX_FMT_RGB24 : return PIXELFORMAT_RGB24; break; + case V4L2_PIX_FMT_BGR32 : return PIXELFORMAT_BGR32; break; + case V4L2_PIX_FMT_RGB32 : return PIXELFORMAT_RGB32; break; + +// Bayer RGB format + case V4L2_PIX_FMT_SBGGR8 : return PIXELFORMAT_SBGGR8; break; + +// YUV formats + case V4L2_PIX_FMT_GREY : return PIXELFORMAT_GREY; break; + case V4L2_PIX_FMT_YUYV : return PIXELFORMAT_YUYV; break; + case V4L2_PIX_FMT_UYVY : return PIXELFORMAT_UYVY; break; + case V4L2_PIX_FMT_YUV420 : return PIXELFORMAT_YUV420P; break; + case V4L2_PIX_FMT_YUV422P : return PIXELFORMAT_YUV422P; break; + +// Compressed formats + case V4L2_PIX_FMT_JPEG : return PIXELFORMAT_JPEG; break; + case V4L2_PIX_FMT_MPEG : return PIXELFORMAT_MPEG; break; + +// Reserved formats + case V4L2_PIX_FMT_DV : return PIXELFORMAT_DV; break; + case V4L2_PIX_FMT_ET61X251 : return PIXELFORMAT_ET61X251; break; + case V4L2_PIX_FMT_HI240 : return PIXELFORMAT_HI240; break; +#if defined( V4L2_PIX_FMT_HM12 ) + case V4L2_PIX_FMT_HM12 : return PIXELFORMAT_HM12; break; +#endif + case V4L2_PIX_FMT_MJPEG : return PIXELFORMAT_MJPEG; break; + case V4L2_PIX_FMT_PWC1 : return PIXELFORMAT_PWC1; break; + case V4L2_PIX_FMT_PWC2 : return PIXELFORMAT_PWC2; break; + case V4L2_PIX_FMT_SN9C10X : return PIXELFORMAT_SN9C10X; break; + case V4L2_PIX_FMT_WNVA : return PIXELFORMAT_WNVA; break; + case V4L2_PIX_FMT_YYUV : return PIXELFORMAT_YYUV; break; + } + break; +#endif + case VIDEODEV_DRIVER_V4L: + switch(palette) + { + case 0 : return PIXELFORMAT_NONE; break; + case VIDEO_PALETTE_GREY : return PIXELFORMAT_GREY; break; + case VIDEO_PALETTE_HI240 : return PIXELFORMAT_RGB332; break; + case VIDEO_PALETTE_RGB555 : return PIXELFORMAT_RGB555; break; + case VIDEO_PALETTE_RGB565 : return PIXELFORMAT_RGB565; break; + case VIDEO_PALETTE_RGB24 : return PIXELFORMAT_RGB24; break; + case VIDEO_PALETTE_RGB32 : return PIXELFORMAT_RGB32; break; + case VIDEO_PALETTE_YUYV : return PIXELFORMAT_YUYV; break; + case VIDEO_PALETTE_UYVY : return PIXELFORMAT_UYVY; break; + case VIDEO_PALETTE_YUV420 : + case VIDEO_PALETTE_YUV420P : return PIXELFORMAT_YUV420P; break; + case VIDEO_PALETTE_YUV422P : return PIXELFORMAT_YUV422P; break; + } + break; +#endif + case VIDEODEV_DRIVER_NONE: + default: + return PIXELFORMAT_NONE; break; + } + return PIXELFORMAT_NONE; +} + +int VideoDevice::pixelFormatCode(pixel_format pixelformat) +{ + switch(m_driver) + { +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + case VIDEODEV_DRIVER_V4L2: + switch(pixelformat) + { + case PIXELFORMAT_NONE : return 0; break; + +// Packed RGB formats + case PIXELFORMAT_RGB332 : return V4L2_PIX_FMT_RGB332; break; +#if defined( V4L2_PIX_FMT_RGB444 ) + case PIXELFORMAT_RGB444 : return V4L2_PIX_FMT_RGB444; break; +#endif + case PIXELFORMAT_RGB555 : return V4L2_PIX_FMT_RGB555; break; + case PIXELFORMAT_RGB565 : return V4L2_PIX_FMT_RGB565; break; + case PIXELFORMAT_RGB555X: return V4L2_PIX_FMT_RGB555X; break; + case PIXELFORMAT_RGB565X: return V4L2_PIX_FMT_RGB565X; break; + case PIXELFORMAT_BGR24 : return V4L2_PIX_FMT_BGR24; break; + case PIXELFORMAT_RGB24 : return V4L2_PIX_FMT_RGB24; break; + case PIXELFORMAT_BGR32 : return V4L2_PIX_FMT_BGR32; break; + case PIXELFORMAT_RGB32 : return V4L2_PIX_FMT_RGB32; break; + +// Bayer RGB format + case PIXELFORMAT_SBGGR8 : return V4L2_PIX_FMT_SBGGR8; break; + +// YUV formats + case PIXELFORMAT_GREY : return V4L2_PIX_FMT_GREY; break; + case PIXELFORMAT_YUYV : return V4L2_PIX_FMT_YUYV; break; + case PIXELFORMAT_UYVY : return V4L2_PIX_FMT_UYVY; break; + case PIXELFORMAT_YUV420P: return V4L2_PIX_FMT_YUV420; break; + case PIXELFORMAT_YUV422P: return V4L2_PIX_FMT_YUV422P; break; + +// Compressed formats + case PIXELFORMAT_JPEG : return V4L2_PIX_FMT_JPEG; break; + case PIXELFORMAT_MPEG : return V4L2_PIX_FMT_MPEG; break; + +// Reserved formats + case PIXELFORMAT_DV : return V4L2_PIX_FMT_DV; break; + case PIXELFORMAT_ET61X251:return V4L2_PIX_FMT_ET61X251;break; + case PIXELFORMAT_HI240 : return V4L2_PIX_FMT_HI240; break; +#if defined( V4L2_PIX_FMT_HM12 ) + case PIXELFORMAT_HM12 : return V4L2_PIX_FMT_HM12; break; +#endif + case PIXELFORMAT_MJPEG : return V4L2_PIX_FMT_MJPEG; break; + case PIXELFORMAT_PWC1 : return V4L2_PIX_FMT_PWC1; break; + case PIXELFORMAT_PWC2 : return V4L2_PIX_FMT_PWC2; break; + case PIXELFORMAT_SN9C10X: return V4L2_PIX_FMT_SN9C10X; break; + case PIXELFORMAT_WNVA : return V4L2_PIX_FMT_WNVA; break; + case PIXELFORMAT_YYUV : return V4L2_PIX_FMT_YYUV; break; + } + break; +#endif + case VIDEODEV_DRIVER_V4L: + switch(pixelformat) + { + case PIXELFORMAT_NONE : return 0; break; + +// Packed RGB formats + case PIXELFORMAT_RGB332 : return VIDEO_PALETTE_HI240; break; + case PIXELFORMAT_RGB444 : return 0; break; + case PIXELFORMAT_RGB555 : return VIDEO_PALETTE_RGB555; break; + case PIXELFORMAT_RGB565 : return VIDEO_PALETTE_RGB565; break; + case PIXELFORMAT_RGB555X: return 0; break; + case PIXELFORMAT_RGB565X: return 0; break; + case PIXELFORMAT_BGR24 : return 0; break; + case PIXELFORMAT_RGB24 : return VIDEO_PALETTE_RGB24; break; + case PIXELFORMAT_BGR32 : return 0; break; + case PIXELFORMAT_RGB32 : return VIDEO_PALETTE_RGB32; break; + +// Bayer RGB format + case PIXELFORMAT_SBGGR8 : return 0; break; + +// YUV formats + case PIXELFORMAT_GREY : return VIDEO_PALETTE_GREY; break; + case PIXELFORMAT_YUYV : return VIDEO_PALETTE_YUYV; break; + case PIXELFORMAT_UYVY : return VIDEO_PALETTE_UYVY; break; + case PIXELFORMAT_YUV420P: return VIDEO_PALETTE_YUV420; break; + case PIXELFORMAT_YUV422P: return VIDEO_PALETTE_YUV422P; break; + +// Compressed formats + case PIXELFORMAT_JPEG : return 0; break; + case PIXELFORMAT_MPEG : return 0; break; + +// Reserved formats + case PIXELFORMAT_DV : return 0; break; + case PIXELFORMAT_ET61X251:return 0; break; + case PIXELFORMAT_HI240 : return VIDEO_PALETTE_HI240; break; + case PIXELFORMAT_HM12 : return 0; break; + case PIXELFORMAT_MJPEG : return 0; break; + case PIXELFORMAT_PWC1 : return 0; break; + case PIXELFORMAT_PWC2 : return 0; break; + case PIXELFORMAT_SN9C10X: return 0; break; + case PIXELFORMAT_WNVA : return 0; break; + case PIXELFORMAT_YYUV : return 0; break; + } + break; +#endif + case VIDEODEV_DRIVER_NONE: + default: + return PIXELFORMAT_NONE; break; + } + return PIXELFORMAT_NONE; +} + +int VideoDevice::pixelFormatDepth(pixel_format pixelformat) +{ + switch(pixelformat) + { + case PIXELFORMAT_NONE : return 0; break; + +// Packed RGB formats + case PIXELFORMAT_RGB332 : return 8; break; + case PIXELFORMAT_RGB444 : return 16; break; + case PIXELFORMAT_RGB555 : return 16; break; + case PIXELFORMAT_RGB565 : return 16; break; + case PIXELFORMAT_RGB555X: return 16; break; + case PIXELFORMAT_RGB565X: return 16; break; + case PIXELFORMAT_BGR24 : return 24; break; + case PIXELFORMAT_RGB24 : return 24; break; + case PIXELFORMAT_BGR32 : return 32; break; + case PIXELFORMAT_RGB32 : return 32; break; + +// Bayer RGB format + case PIXELFORMAT_SBGGR8 : return 0; break; + +// YUV formats + case PIXELFORMAT_GREY : return 8; break; + case PIXELFORMAT_YUYV : return 16; break; + case PIXELFORMAT_UYVY : return 16; break; + case PIXELFORMAT_YUV420P: return 16; break; + case PIXELFORMAT_YUV422P: return 16; break; + +// Compressed formats + case PIXELFORMAT_JPEG : return 0; break; + case PIXELFORMAT_MPEG : return 0; break; + +// Reserved formats + case PIXELFORMAT_DV : return 0; break; + case PIXELFORMAT_ET61X251:return 0; break; + case PIXELFORMAT_HI240 : return 8; break; + case PIXELFORMAT_HM12 : return 0; break; + case PIXELFORMAT_MJPEG : return 0; break; + case PIXELFORMAT_PWC1 : return 0; break; + case PIXELFORMAT_PWC2 : return 0; break; + case PIXELFORMAT_SN9C10X: return 0; break; + case PIXELFORMAT_WNVA : return 0; break; + case PIXELFORMAT_YYUV : return 0; break; + } + return 0; +} + +QString VideoDevice::pixelFormatName(pixel_format pixelformat) +{ + QString returnvalue; + returnvalue = "None"; + switch(pixelformat) + { + case PIXELFORMAT_NONE : returnvalue = "None"; break; + +// Packed RGB formats + case PIXELFORMAT_RGB332 : returnvalue = "8-bit RGB332"; break; + case PIXELFORMAT_RGB444 : returnvalue = "8-bit RGB444"; break; + case PIXELFORMAT_RGB555 : returnvalue = "16-bit RGB555"; break; + case PIXELFORMAT_RGB565 : returnvalue = "16-bit RGB565"; break; + case PIXELFORMAT_RGB555X: returnvalue = "16-bit RGB555X"; break; + case PIXELFORMAT_RGB565X: returnvalue = "16-bit RGB565X"; break; + case PIXELFORMAT_BGR24 : returnvalue = "24-bit BGR24"; break; + case PIXELFORMAT_RGB24 : returnvalue = "24-bit RGB24"; break; + case PIXELFORMAT_BGR32 : returnvalue = "32-bit BGR32"; break; + case PIXELFORMAT_RGB32 : returnvalue = "32-bit RGB32"; break; + +// Bayer RGB format + case PIXELFORMAT_SBGGR8 : returnvalue = "Bayer RGB format"; break; + +// YUV formats + case PIXELFORMAT_GREY : returnvalue = "8-bit Grayscale"; break; + case PIXELFORMAT_YUYV : returnvalue = "Packed YUV 4:2:2"; break; + case PIXELFORMAT_UYVY : returnvalue = "Packed YVU 4:2:2"; break; + case PIXELFORMAT_YUV420P: returnvalue = "Planar YUV 4:2:0"; break; + case PIXELFORMAT_YUV422P: returnvalue = "Planar YUV 4:2:2"; break; + + +// Compressed formats + case PIXELFORMAT_JPEG : returnvalue = "JPEG image"; break; + case PIXELFORMAT_MPEG : returnvalue = "MPEG stream"; break; + +// Reserved formats + case PIXELFORMAT_DV : returnvalue = "DV (unknown)"; break; + case PIXELFORMAT_ET61X251:returnvalue = "ET61X251"; break; + case PIXELFORMAT_HI240 : returnvalue = "8-bit HI240 (RGB332)"; break; + case PIXELFORMAT_HM12 : returnvalue = "Packed YUV 4:2:2"; break; + case PIXELFORMAT_MJPEG : returnvalue = "8-bit Grayscale"; break; + case PIXELFORMAT_PWC1 : returnvalue = "PWC1"; break; + case PIXELFORMAT_PWC2 : returnvalue = "PWC2"; break; + case PIXELFORMAT_SN9C10X: returnvalue = "SN9C102"; break; + case PIXELFORMAT_WNVA : returnvalue = "Winnov Videum"; break; + case PIXELFORMAT_YYUV : returnvalue = "YYUV (unknown)"; break; + } + return returnvalue; +} + +QString VideoDevice::pixelFormatName(int pixelformat) +{ + QString returnvalue; + returnvalue = "None"; + switch(m_driver) + { +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + case VIDEODEV_DRIVER_V4L2: + switch(pixelformat) + { + case 0 : returnvalue = pixelFormatName(PIXELFORMAT_NONE); break; + +// Packed RGB formats + case V4L2_PIX_FMT_RGB332 : returnvalue = pixelFormatName(PIXELFORMAT_RGB332); break; +#if defined( V4L2_PIX_FMT_RGB444 ) + case V4L2_PIX_FMT_RGB444 : returnvalue = pixelFormatName(PIXELFORMAT_RGB444); break; +#endif + case V4L2_PIX_FMT_RGB555 : returnvalue = pixelFormatName(PIXELFORMAT_RGB555); break; + case V4L2_PIX_FMT_RGB565 : returnvalue = pixelFormatName(PIXELFORMAT_RGB565); break; + case V4L2_PIX_FMT_RGB555X : returnvalue = pixelFormatName(PIXELFORMAT_RGB555X); break; + case V4L2_PIX_FMT_RGB565X : returnvalue = pixelFormatName(PIXELFORMAT_RGB565X); break; + case V4L2_PIX_FMT_BGR24 : returnvalue = pixelFormatName(PIXELFORMAT_BGR24); break; + case V4L2_PIX_FMT_RGB24 : returnvalue = pixelFormatName(PIXELFORMAT_RGB24); break; + case V4L2_PIX_FMT_BGR32 : returnvalue = pixelFormatName(PIXELFORMAT_BGR32); break; + case V4L2_PIX_FMT_RGB32 : returnvalue = pixelFormatName(PIXELFORMAT_RGB32); break; + +// Bayer RGB format + case V4L2_PIX_FMT_SBGGR8 : returnvalue = pixelFormatName(PIXELFORMAT_SBGGR8); break; + +// YUV formats + case V4L2_PIX_FMT_GREY : returnvalue = pixelFormatName(PIXELFORMAT_GREY); break; + case V4L2_PIX_FMT_YUYV : returnvalue = pixelFormatName(PIXELFORMAT_YUYV); break; + case V4L2_PIX_FMT_UYVY : returnvalue = pixelFormatName(PIXELFORMAT_UYVY); break; + case V4L2_PIX_FMT_YUV420 : returnvalue = pixelFormatName(PIXELFORMAT_YUV420P); break; + case V4L2_PIX_FMT_YUV422P : returnvalue = pixelFormatName(PIXELFORMAT_YUV422P); break; + +// Compressed formats + case V4L2_PIX_FMT_JPEG : returnvalue = pixelFormatName(PIXELFORMAT_JPEG); break; + case V4L2_PIX_FMT_MPEG : returnvalue = pixelFormatName(PIXELFORMAT_MPEG); break; + +// Reserved formats + case V4L2_PIX_FMT_DV : returnvalue = pixelFormatName(PIXELFORMAT_DV); break; + case V4L2_PIX_FMT_ET61X251 : returnvalue = pixelFormatName(PIXELFORMAT_ET61X251); break; + case V4L2_PIX_FMT_HI240 : returnvalue = pixelFormatName(PIXELFORMAT_HI240); break; +#if defined( V4L2_PIX_FMT_HM12 ) + case V4L2_PIX_FMT_HM12 : returnvalue = pixelFormatName(PIXELFORMAT_HM12); break; +#endif + case V4L2_PIX_FMT_MJPEG : returnvalue = pixelFormatName(PIXELFORMAT_MJPEG); break; + case V4L2_PIX_FMT_PWC1 : returnvalue = pixelFormatName(PIXELFORMAT_PWC1); break; + case V4L2_PIX_FMT_PWC2 : returnvalue = pixelFormatName(PIXELFORMAT_PWC2); break; + case V4L2_PIX_FMT_SN9C10X : returnvalue = pixelFormatName(PIXELFORMAT_SN9C10X); break; + case V4L2_PIX_FMT_WNVA : returnvalue = pixelFormatName(PIXELFORMAT_WNVA); break; + case V4L2_PIX_FMT_YYUV : returnvalue = pixelFormatName(PIXELFORMAT_YYUV); break; + } + break; +#endif + case VIDEODEV_DRIVER_V4L: + switch(pixelformat) + { + case VIDEO_PALETTE_GREY : returnvalue = pixelFormatName(PIXELFORMAT_GREY); break; + case VIDEO_PALETTE_HI240 : returnvalue = pixelFormatName(PIXELFORMAT_RGB332); break; + case VIDEO_PALETTE_RGB555 : returnvalue = pixelFormatName(PIXELFORMAT_RGB555); break; + case VIDEO_PALETTE_RGB565 : returnvalue = pixelFormatName(PIXELFORMAT_RGB565); break; + case VIDEO_PALETTE_RGB24 : returnvalue = pixelFormatName(PIXELFORMAT_RGB24); break; + case VIDEO_PALETTE_RGB32 : returnvalue = pixelFormatName(PIXELFORMAT_RGB32); break; + case VIDEO_PALETTE_YUYV : returnvalue = pixelFormatName(PIXELFORMAT_YUYV); break; + case VIDEO_PALETTE_UYVY : returnvalue = pixelFormatName(PIXELFORMAT_UYVY); break; + case VIDEO_PALETTE_YUV420 : + case VIDEO_PALETTE_YUV420P : returnvalue = pixelFormatName(PIXELFORMAT_YUV420P); break; + case VIDEO_PALETTE_YUV422P : returnvalue = pixelFormatName(PIXELFORMAT_YUV422P); break; + } + break; +#endif + case VIDEODEV_DRIVER_NONE: + default: + break; + } + return returnvalue; +} + +int VideoDevice::detectPixelFormats() +{ + int err = 0; + switch(m_driver) + { +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + case VIDEODEV_DRIVER_V4L2: + fmtdesc.index = 0; + fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + while ( err == 0 ) + { + if (-1 == xioctl (VIDIOC_ENUM_FMT, &fmtdesc)) +// if (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) < 0 ) + { + perror("VIDIOC_ENUM_FMT"); + err = errno; + } + else + { + kDebug () << fmtdesc.pixelformat << " " << pixelFormatName(fmtdesc.pixelformat); // Need a cleanup. PixelFormatForPalette is a really bad name + fmtdesc.index++; + } + } +// break; +#endif + case VIDEODEV_DRIVER_V4L: +// TODO: THis thing can be used to detec what pixel formats are supported in a API-independent way, but V4L2 has VIDIOC_ENUM_PIXFMT. +// The correct thing to do is to isolate these calls and do a proper implementation for V4L and another for V4L2 when this thing will be migrated to a plugin architecture. + +// Packed RGB formats + kDebug() << "Supported pixel formats:"; + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_RGB332)) kDebug() << pixelFormatName(PIXELFORMAT_RGB332); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_RGB444)) kDebug() << pixelFormatName(PIXELFORMAT_RGB444); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_RGB555)) kDebug() << pixelFormatName(PIXELFORMAT_RGB555); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_RGB565)) kDebug() << pixelFormatName(PIXELFORMAT_RGB565); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_RGB555X)) kDebug() << pixelFormatName(PIXELFORMAT_RGB555X); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_RGB565X)) kDebug() << pixelFormatName(PIXELFORMAT_RGB565X); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_BGR24)) kDebug() << pixelFormatName(PIXELFORMAT_BGR24); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_RGB24)) kDebug() << pixelFormatName(PIXELFORMAT_RGB24); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_BGR32)) kDebug() << pixelFormatName(PIXELFORMAT_BGR32); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_RGB32)) kDebug() << pixelFormatName(PIXELFORMAT_RGB32); + +// Bayer RGB format + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_SBGGR8)) kDebug() << pixelFormatName(PIXELFORMAT_SBGGR8); + +// YUV formats + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_GREY)) kDebug() << pixelFormatName(PIXELFORMAT_GREY); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_YUYV)) kDebug() << pixelFormatName(PIXELFORMAT_YUYV); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_UYVY)) kDebug() << pixelFormatName(PIXELFORMAT_UYVY); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_YUV420P)) kDebug() << pixelFormatName(PIXELFORMAT_YUV420P); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_YUV422P)) kDebug() << pixelFormatName(PIXELFORMAT_YUV422P); + +// Compressed formats + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_JPEG)) kDebug() << pixelFormatName(PIXELFORMAT_JPEG); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_MPEG)) kDebug() << pixelFormatName(PIXELFORMAT_MPEG); + +// Reserved formats + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_DV)) kDebug() << pixelFormatName(PIXELFORMAT_DV); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_ET61X251)) kDebug() << pixelFormatName(PIXELFORMAT_ET61X251); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_HI240)) kDebug() << pixelFormatName(PIXELFORMAT_HI240); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_HM12)) kDebug() << pixelFormatName(PIXELFORMAT_HM12); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_MJPEG)) kDebug() << pixelFormatName(PIXELFORMAT_MJPEG); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_PWC1)) kDebug() << pixelFormatName(PIXELFORMAT_PWC1); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_PWC2)) kDebug() << pixelFormatName(PIXELFORMAT_PWC2); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_SN9C10X)) kDebug() << pixelFormatName(PIXELFORMAT_SN9C10X); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_WNVA)) kDebug() << pixelFormatName(PIXELFORMAT_WNVA); + if(PIXELFORMAT_NONE != setPixelFormat(PIXELFORMAT_YYUV)) kDebug() << pixelFormatName(PIXELFORMAT_YYUV); + break; +#endif + case VIDEODEV_DRIVER_NONE: + default: + return PIXELFORMAT_NONE; break; + } + return PIXELFORMAT_NONE; +} + +__u64 VideoDevice::signalStandardCode(signal_standard standard) +{ + switch(m_driver) + { +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + case VIDEODEV_DRIVER_V4L2: + switch(standard) + { + case STANDARD_PAL_B : return V4L2_STD_PAL_B; break; + case STANDARD_PAL_B1 : return V4L2_STD_PAL_B1; break; + case STANDARD_PAL_G : return V4L2_STD_PAL_G; break; + case STANDARD_PAL_H : return V4L2_STD_PAL_H; break; + case STANDARD_PAL_I : return V4L2_STD_PAL_I; break; + case STANDARD_PAL_D : return V4L2_STD_PAL_D; break; + case STANDARD_PAL_D1 : return V4L2_STD_PAL_D1; break; + case STANDARD_PAL_K : return V4L2_STD_PAL_K; break; + + case STANDARD_PAL_M : return V4L2_STD_PAL_M; break; + case STANDARD_PAL_N : return V4L2_STD_PAL_N; break; + case STANDARD_PAL_Nc : return V4L2_STD_PAL_Nc; break; + case STANDARD_PAL_60 : return V4L2_STD_PAL_60; break; + + case STANDARD_NTSC_M : return V4L2_STD_NTSC_M; break; + case STANDARD_NTSC_M_JP : return V4L2_STD_NTSC_M_JP; break; + case STANDARD_NTSC_443 : return V4L2_STD_NTSC_443; break; + case STANDARD_NTSC_M_KR : return V4L2_STD_NTSC_M_KR; break; + + case STANDARD_SECAM_B : return V4L2_STD_SECAM_B; break; + case STANDARD_SECAM_D : return V4L2_STD_SECAM_D; break; + case STANDARD_SECAM_G : return V4L2_STD_SECAM_G; break; + case STANDARD_SECAM_H : return V4L2_STD_SECAM_H; break; + case STANDARD_SECAM_K : return V4L2_STD_SECAM_K; break; + case STANDARD_SECAM_K1 : return V4L2_STD_SECAM_K1; break; + case STANDARD_SECAM_L : return V4L2_STD_SECAM_L; break; + case STANDARD_SECAM_LC : return V4L2_STD_SECAM_LC; break; + + case STANDARD_ATSC_8_VSB: return V4L2_STD_ATSC_8_VSB; break; + case STANDARD_ATSC_16_VSB:return V4L2_STD_ATSC_16_VSB; break; + + case STANDARD_PAL_BG : return V4L2_STD_PAL_BG; break; + case STANDARD_PAL_DK : return V4L2_STD_PAL_DK; break; + case STANDARD_PAL : return V4L2_STD_PAL; break; + case STANDARD_NTSC : return V4L2_STD_NTSC; break; + case STANDARD_SECAM_DK : return V4L2_STD_SECAM_DK; break; + case STANDARD_SECAM : return V4L2_STD_SECAM; break; + + case STANDARD_MN : return V4L2_STD_MN; break; + case STANDARD_B : return V4L2_STD_B; break; + case STANDARD_GH : return V4L2_STD_GH; break; + case STANDARD_DK : return V4L2_STD_DK; break; + + case STANDARD_525_60 : return V4L2_STD_525_60; break; + case STANDARD_625_50 : return V4L2_STD_625_50; break; + case STANDARD_ATSC : return V4L2_STD_ATSC; break; + + case STANDARD_UNKNOWN : return V4L2_STD_UNKNOWN; break; + case STANDARD_ALL : return V4L2_STD_ALL; break; + } + break; +#endif + case VIDEODEV_DRIVER_V4L: + switch(standard) + { + case STANDARD_PAL_B : return VIDEO_MODE_PAL; break; + case STANDARD_PAL_B1 : return VIDEO_MODE_PAL; break; + case STANDARD_PAL_G : return VIDEO_MODE_PAL; break; + case STANDARD_PAL_H : return VIDEO_MODE_PAL; break; + case STANDARD_PAL_I : return VIDEO_MODE_PAL; break; + case STANDARD_PAL_D : return VIDEO_MODE_PAL; break; + case STANDARD_PAL_D1 : return VIDEO_MODE_PAL; break; + case STANDARD_PAL_K : return VIDEO_MODE_PAL; break; + + case STANDARD_PAL_M : return 5; break; // Undocumented value found to be compatible with V4L bttv driver + case STANDARD_PAL_N : return 6; break; // Undocumented value found to be compatible with V4L bttv driver + case STANDARD_PAL_Nc : return 4; break; // Undocumented value found to be compatible with V4L bttv driver + case STANDARD_PAL_60 : return VIDEO_MODE_PAL; break; + + case STANDARD_NTSC_M : return VIDEO_MODE_NTSC; break; + case STANDARD_NTSC_M_JP : return 7; break; // Undocumented value found to be compatible with V4L bttv driver + case STANDARD_NTSC_443 : return VIDEO_MODE_NTSC; break; + case STANDARD_NTSC_M_KR : return VIDEO_MODE_NTSC; break; + + case STANDARD_SECAM_B : return VIDEO_MODE_SECAM; break; + case STANDARD_SECAM_D : return VIDEO_MODE_SECAM; break; + case STANDARD_SECAM_G : return VIDEO_MODE_SECAM; break; + case STANDARD_SECAM_H : return VIDEO_MODE_SECAM; break; + case STANDARD_SECAM_K : return VIDEO_MODE_SECAM; break; + case STANDARD_SECAM_K1 : return VIDEO_MODE_SECAM; break; + case STANDARD_SECAM_L : return VIDEO_MODE_SECAM; break; + case STANDARD_SECAM_LC : return VIDEO_MODE_SECAM; break; + + case STANDARD_ATSC_8_VSB: return VIDEO_MODE_AUTO; break; + case STANDARD_ATSC_16_VSB:return VIDEO_MODE_AUTO; break; + + case STANDARD_PAL_BG : return VIDEO_MODE_PAL; break; + case STANDARD_PAL_DK : return VIDEO_MODE_PAL; break; + case STANDARD_PAL : return VIDEO_MODE_PAL; break; + case STANDARD_NTSC : return VIDEO_MODE_NTSC; break; + case STANDARD_SECAM_DK : return VIDEO_MODE_SECAM; break; + case STANDARD_SECAM : return VIDEO_MODE_SECAM; break; + + case STANDARD_MN : return VIDEO_MODE_AUTO; break; + case STANDARD_B : return VIDEO_MODE_AUTO; break; + case STANDARD_GH : return VIDEO_MODE_AUTO; break; + case STANDARD_DK : return VIDEO_MODE_AUTO; break; + + case STANDARD_525_60 : return VIDEO_MODE_PAL; break; + case STANDARD_625_50 : return VIDEO_MODE_SECAM; break; + case STANDARD_ATSC : return VIDEO_MODE_AUTO; break; + + case STANDARD_UNKNOWN : return VIDEO_MODE_AUTO; break; + case STANDARD_ALL : return VIDEO_MODE_AUTO; break; + } + break; +#endif + case VIDEODEV_DRIVER_NONE: + default: + return STANDARD_UNKNOWN; break; + } + return STANDARD_UNKNOWN; +} + +QString VideoDevice::signalStandardName(signal_standard standard) +{ + QString returnvalue; + returnvalue = "None"; + switch(standard) + { + case STANDARD_PAL_B : returnvalue = "PAL-B"; break; + case STANDARD_PAL_B1 : returnvalue = "PAL-B1"; break; + case STANDARD_PAL_G : returnvalue = "PAL-G"; break; + case STANDARD_PAL_H : returnvalue = "PAL-H"; break; + case STANDARD_PAL_I : returnvalue = "PAL-I"; break; + case STANDARD_PAL_D : returnvalue = "PAL-D"; break; + case STANDARD_PAL_D1 : returnvalue = "PAL-D1"; break; + case STANDARD_PAL_K : returnvalue = "PAL-K"; break; + + case STANDARD_PAL_M : returnvalue = "PAL-M"; break; + case STANDARD_PAL_N : returnvalue = "PAL-N"; break; + case STANDARD_PAL_Nc : returnvalue = "PAL-Nc"; break; + case STANDARD_PAL_60 : returnvalue = "PAL-60"; break; + + case STANDARD_NTSC_M : returnvalue = "NTSC-M"; break; + case STANDARD_NTSC_M_JP : returnvalue = "NTSC-M(JP)"; break; + case STANDARD_NTSC_443 : returnvalue = "NTSC-443"; break; + case STANDARD_NTSC_M_KR : returnvalue = "NTSC-M(KR)"; break; + + case STANDARD_SECAM_B : returnvalue = "SECAM-B"; break; + case STANDARD_SECAM_D : returnvalue = "SECAM-D"; break; + case STANDARD_SECAM_G : returnvalue = "SECAM-G"; break; + case STANDARD_SECAM_H : returnvalue = "SECAM-H"; break; + case STANDARD_SECAM_K : returnvalue = "SECAM-K"; break; + case STANDARD_SECAM_K1 : returnvalue = "SECAM-K1"; break; + case STANDARD_SECAM_L : returnvalue = "SECAM-L"; break; + case STANDARD_SECAM_LC : returnvalue = "SECAM-LC"; break; + + case STANDARD_ATSC_8_VSB: returnvalue = "ATSC-8-VSB"; break; + case STANDARD_ATSC_16_VSB:returnvalue = "ATSC-16-VSB"; break; + + case STANDARD_PAL_BG : returnvalue = "PAL-BG"; break; + case STANDARD_PAL_DK : returnvalue = "PAL-DK"; break; + case STANDARD_PAL : returnvalue = "PAL"; break; + case STANDARD_NTSC : returnvalue = "NTSC"; break; + case STANDARD_SECAM_DK : returnvalue = "SECAM-DK"; break; + case STANDARD_SECAM : returnvalue = "SECAM"; break; + + case STANDARD_MN : returnvalue = "DK"; break; + case STANDARD_B : returnvalue = "B"; break; + case STANDARD_GH : returnvalue = "GH"; break; + case STANDARD_DK : returnvalue = "DK"; break; + + case STANDARD_525_60 : returnvalue = "525 lines 60Hz";break; + case STANDARD_625_50 : returnvalue = "625 lines 50Hz";break; + case STANDARD_ATSC : returnvalue = "ATSC"; break; + + case STANDARD_UNKNOWN : returnvalue = "Unknown"; break; + case STANDARD_ALL : returnvalue = "All"; break; + } + return returnvalue; +} + +QString VideoDevice::signalStandardName(int standard) +{ + QString returnvalue; + returnvalue = "None"; + switch(m_driver) + { +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + case VIDEODEV_DRIVER_V4L2: + switch(standard) + { + case V4L2_STD_PAL_B : returnvalue = signalStandardName(STANDARD_PAL_B); break; + case V4L2_STD_PAL_B1 : returnvalue = signalStandardName(STANDARD_PAL_B1); break; + case V4L2_STD_PAL_G : returnvalue = signalStandardName(STANDARD_PAL_G); break; + case V4L2_STD_PAL_H : returnvalue = signalStandardName(STANDARD_PAL_H); break; + case V4L2_STD_PAL_I : returnvalue = signalStandardName(STANDARD_PAL_I); break; + case V4L2_STD_PAL_D : returnvalue = signalStandardName(STANDARD_PAL_D); break; + case V4L2_STD_PAL_D1 : returnvalue = signalStandardName(STANDARD_PAL_D1); break; + case V4L2_STD_PAL_K : returnvalue = signalStandardName(STANDARD_PAL_K); break; + case V4L2_STD_PAL_M : returnvalue = signalStandardName(STANDARD_PAL_M); break; + case V4L2_STD_PAL_N : returnvalue = signalStandardName(STANDARD_PAL_N); break; + case V4L2_STD_PAL_Nc : returnvalue = signalStandardName(STANDARD_PAL_Nc); break; + case V4L2_STD_PAL_60 : returnvalue = signalStandardName(STANDARD_PAL_60); break; + case V4L2_STD_NTSC_M : returnvalue = signalStandardName(STANDARD_NTSC_M); break; + case V4L2_STD_NTSC_M_JP : returnvalue = signalStandardName(STANDARD_NTSC_M_JP); break; + case V4L2_STD_NTSC_443 : returnvalue = signalStandardName(STANDARD_NTSC_443); break; // Commented out because my videodev2.h header seems to not include this standard in struct __u64 v4l2_std_id + case V4L2_STD_NTSC_M_KR : returnvalue = signalStandardName(STANDARD_NTSC_M_KR); break; // Commented out because my videodev2.h header seems to not include this standard in struct __u64 v4l2_std_id + case V4L2_STD_SECAM_B : returnvalue = signalStandardName(STANDARD_SECAM_B); break; + case V4L2_STD_SECAM_D : returnvalue = signalStandardName(STANDARD_SECAM_D); break; + case V4L2_STD_SECAM_G : returnvalue = signalStandardName(STANDARD_SECAM_G); break; + case V4L2_STD_SECAM_H : returnvalue = signalStandardName(STANDARD_SECAM_H); break; + case V4L2_STD_SECAM_K : returnvalue = signalStandardName(STANDARD_SECAM_K); break; + case V4L2_STD_SECAM_K1 : returnvalue = signalStandardName(STANDARD_SECAM_K1); break; + case V4L2_STD_SECAM_L : returnvalue = signalStandardName(STANDARD_SECAM_L); break; + case V4L2_STD_SECAM_LC : returnvalue = signalStandardName(STANDARD_SECAM_LC); break; + + case V4L2_STD_ATSC_8_VSB: returnvalue = signalStandardName(STANDARD_ATSC_8_VSB);break; + case V4L2_STD_ATSC_16_VSB:returnvalue = signalStandardName(STANDARD_ATSC_16_VSB);break; + + case V4L2_STD_PAL_BG : returnvalue = signalStandardName(STANDARD_PAL_BG); break; + case V4L2_STD_PAL_DK : returnvalue = signalStandardName(STANDARD_PAL_DK); break; + case V4L2_STD_PAL : returnvalue = signalStandardName(STANDARD_PAL); break; + case V4L2_STD_NTSC : returnvalue = signalStandardName(STANDARD_NTSC); break; + case V4L2_STD_SECAM_DK : returnvalue = signalStandardName(STANDARD_SECAM_DK); break; + case V4L2_STD_SECAM : returnvalue = signalStandardName(STANDARD_SECAM); break; + + case V4L2_STD_MN : returnvalue = signalStandardName(STANDARD_MN); break; + case V4L2_STD_B : returnvalue = signalStandardName(STANDARD_B); break; + case V4L2_STD_GH : returnvalue = signalStandardName(STANDARD_GH); break; + case V4L2_STD_DK : returnvalue = signalStandardName(STANDARD_DK); break; + + case V4L2_STD_525_60 : returnvalue = signalStandardName(STANDARD_525_60); break; + case V4L2_STD_625_50 : returnvalue = signalStandardName(STANDARD_625_50); break; + case V4L2_STD_ATSC : returnvalue = signalStandardName(STANDARD_ATSC); break; + + case V4L2_STD_UNKNOWN : returnvalue = signalStandardName(STANDARD_UNKNOWN); break; + case V4L2_STD_ALL : returnvalue = signalStandardName(STANDARD_ALL); break; + } + break; +#endif + case VIDEODEV_DRIVER_V4L: + switch(standard) + { + case VIDEO_MODE_PAL : returnvalue = signalStandardName(STANDARD_PAL); break; + case VIDEO_MODE_NTSC : returnvalue = signalStandardName(STANDARD_NTSC); break; + case VIDEO_MODE_SECAM : returnvalue = signalStandardName(STANDARD_SECAM); break; + case VIDEO_MODE_AUTO : returnvalue = signalStandardName(STANDARD_ALL); break; // It must be disabled until I find a correct way to handle those non-standard bttv modes +// case VIDEO_MODE_PAL_Nc : returnvalue = signalStandardName(STANDARD_PAL_Nc); break; // Undocumented value found to be compatible with V4L bttv driver + case VIDEO_MODE_PAL_M : returnvalue = signalStandardName(STANDARD_PAL_M); break; // Undocumented value found to be compatible with V4L bttv driver + case VIDEO_MODE_PAL_N : returnvalue = signalStandardName(STANDARD_PAL_N); break; // Undocumented value found to be compatible with V4L bttv driver + case VIDEO_MODE_NTSC_JP : returnvalue = signalStandardName(STANDARD_NTSC_M_JP); break; // Undocumented value found to be compatible with V4L bttv driver + } + break; +#endif + case VIDEODEV_DRIVER_NONE: + default: + break; + } + return returnvalue; +} + +/*! + \fn VideoDevice::detectSignalStandards() +// this must be done once for each _input_. + */ +int VideoDevice::detectSignalStandards() +{ + kDebug() << "called."; + if(isOpen()) + { + switch(m_driver) + { +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + case VIDEODEV_DRIVER_V4L2: + + + struct v4l2_input input; + struct v4l2_standard standard; + + memset (&input, 0, sizeof (input)); + + if (-1 == xioctl (VIDIOC_G_INPUT, &input.index)) { + perror ("VIDIOC_G_INPUT"); + return EXIT_FAILURE; + } + + if (-1 == xioctl (VIDIOC_ENUMINPUT, &input)) { + perror ("VIDIOC_ENUM_INPUT"); + return EXIT_FAILURE; + } + +// printf ("Current input %s supports:\n", input.name); + + memset (&standard, 0, sizeof (standard)); + standard.index = 0; + + while (0 == xioctl (VIDIOC_ENUMSTD, &standard)) { + if (standard.id & input.std) +// kDebug() << standard.name; + kDebug() << signalStandardName(standard.id) << " (" << standard.id << ")" << V4L2_STD_NTSC; + + standard.index++; + } + +/* EINVAL indicates the end of the enumeration, which cannot be + empty unless this device falls under the USB exception. */ + + if (errno != EINVAL || standard.index == 0) { + perror ("VIDIOC_ENUMSTD"); + return EXIT_FAILURE; + } + + + break; +#endif + case VIDEODEV_DRIVER_V4L: + break; +#endif + case VIDEODEV_DRIVER_NONE: + default: + break; + } + //FIXME: return a real value + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} + +/*! + \fn VideoDevice::initRead() + */ +int VideoDevice::initRead() +{ + /// @todo implement me + + kDebug() << "called."; + if(isOpen()) + { + m_rawbuffers.resize(1); + if (m_rawbuffers.size()==0) + { + fprintf (stderr, "Out of memory\n"); + return EXIT_FAILURE; + } + kDebug() << "m_buffer_size: " << m_buffer_size; + +// m_rawbuffers[0].pixelformat=m_pixelformat; + m_rawbuffers[0].length = m_buffer_size; + m_rawbuffers[0].start = (uchar *)malloc (m_buffer_size); + + if (!m_rawbuffers[0].start) + { + fprintf (stderr, "Out of memory\n"); + return EXIT_FAILURE; + } + kDebug() << "exited successfuly."; + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} + + +/*! + \fn VideoDevice::initMmap() + */ +int VideoDevice::initMmap() +{ + /// @todo implement me +#define BUFFERS 2 + if(isOpen()) + { + kDebug() << full_filename << " Trying to MMAP"; +#ifdef V4L2_CAP_VIDEO_CAPTURE + struct v4l2_requestbuffers req; + + CLEAR (req); + + req.count = BUFFERS; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_MMAP; + + if (-1 == xioctl (VIDIOC_REQBUFS, &req)) + { + if (EINVAL == errno) + { + kDebug() << full_filename << " does not support memory mapping"; + return EXIT_FAILURE; + } + else + { + return errnoReturn ("VIDIOC_REQBUFS"); + } + } + + if (req.count < BUFFERS) + { + kDebug() << "Insufficient buffer memory on " << full_filename; + return EXIT_FAILURE; + } + + m_rawbuffers.resize(req.count); + + if (m_rawbuffers.size()==0) + { + kDebug() << "Out of memory"; + return EXIT_FAILURE; + } + + for (m_streambuffers = 0; m_streambuffers < req.count; ++m_streambuffers) + { + struct v4l2_buffer v4l2buffer; + + CLEAR (v4l2buffer); + + v4l2buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + v4l2buffer.memory = V4L2_MEMORY_MMAP; + v4l2buffer.index = m_streambuffers; + + if (-1 == xioctl (VIDIOC_QUERYBUF, &v4l2buffer)) + return errnoReturn ("VIDIOC_QUERYBUF"); + + m_rawbuffers[m_streambuffers].length = v4l2buffer.length; + m_rawbuffers[m_streambuffers].start = (uchar *) mmap (NULL /* start anywhere */, v4l2buffer.length, PROT_READ | PROT_WRITE /* required */, MAP_SHARED /* recommended */, descriptor, v4l2buffer.m.offset); + + if (MAP_FAILED == m_rawbuffers[m_streambuffers].start) + return errnoReturn ("mmap"); + } +#endif + m_currentbuffer.data.resize(m_rawbuffers[0].length); // Makes the imagesize.data buffer size equal to the rawbuffer size + kDebug() << full_filename << " m_currentbuffer.data.size(): " << m_currentbuffer.data.size(); + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} + + +/*! + \fn VideoDevice::initUserptr() + */ +int VideoDevice::initUserptr() +{ + /// @todo implement me + if(isOpen()) + { +#ifdef V4L2_CAP_VIDEO_CAPTURE + struct v4l2_requestbuffers req; + + CLEAR (req); + + req.count = 2; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_USERPTR; + + if (-1 == xioctl (VIDIOC_REQBUFS, &req)) + { + if (EINVAL == errno) + { + kDebug() << full_filename << " does not support memory mapping"; + return EXIT_FAILURE; + } + else + { + return errnoReturn ("VIDIOC_REQBUFS"); + } + } + + m_rawbuffers.resize(4); + + if (m_rawbuffers.size()==0) + { + fprintf (stderr, "Out of memory\n"); + return EXIT_FAILURE; + } + + for (m_streambuffers = 0; m_streambuffers < 4; ++m_streambuffers) + { + m_rawbuffers[m_streambuffers].length = m_buffer_size; + m_rawbuffers[m_streambuffers].start = (uchar *) malloc (m_buffer_size); + + if (!m_rawbuffers[m_streambuffers].start) + { + kDebug() << "Out of memory"; + return EXIT_FAILURE; + } + } +#endif + return EXIT_SUCCESS; + } + return EXIT_FAILURE; +} + +bool VideoDevice::canCapture() +{ + return m_videocapture; +} + +bool VideoDevice::canChromakey() +{ + return m_videochromakey; +} + +bool VideoDevice::canScale() +{ + return m_videoscale; +} + +bool VideoDevice::canOverlay() +{ + return m_videooverlay; +} + +bool VideoDevice::canRead() +{ + return m_videoread; +} + +bool VideoDevice::canAsyncIO() +{ + return m_videoasyncio; +} + +bool VideoDevice::canStream() +{ + return m_videostream; +} + +void VideoDevice::setUdi( const QString & udi ) +{ + m_udi = udi; +} + +QString VideoDevice::udi() const +{ + return m_udi; +} + +} +} diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevice.h b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevice.h new file mode 100644 index 0000000..bebbba5 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevice.h @@ -0,0 +1,338 @@ +/* + videodevice.cpp - Video Device Low-level Support + + Copyright (c) 2005-2008 by Cláudio da Silveira Pinheiro + + ************************************************************************* + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + ************************************************************************* +*/ + +#define ENABLE_AV + +#ifndef VIDEODEVICELISTITEM_H +#define VIDEODEVICELISTITEM_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__linux__) && defined(ENABLE_AV) + +#include +#undef __STRICT_ANSI__ +#ifndef __u64 //required by videodev.h +#define __u64 unsigned long long +#endif // __u64 +#ifndef __s64 //required by videodev.h +#define __s64 signed long long +#endif // __s64 + + +#ifndef pgoff_t +#define pgoff_t unsigned long +#endif + +#include +#include +#include +#define VIDEO_MODE_PAL_Nc 3 +#define VIDEO_MODE_PAL_M 4 +#define VIDEO_MODE_PAL_N 5 +#define VIDEO_MODE_NTSC_JP 6 +#define __STRICT_ANSI__ + +#endif // __linux__ + +#include +#include +#include +#include +#include + +#include "videoinput.h" + +namespace Phonon { +namespace VideoCapture { + +/** +@author Kopete Developers +*/ +typedef enum +{ + VIDEODEV_DRIVER_NONE +#if defined( __linux__) && defined(ENABLE_AV) + , + VIDEODEV_DRIVER_V4L +#ifdef V4L2_CAP_VIDEO_CAPTURE + , + VIDEODEV_DRIVER_V4L2 +#endif +#endif +} videodev_driver; + +typedef enum +{ +// Packed RGB formats + PIXELFORMAT_NONE = 0, + PIXELFORMAT_GREY = (1 << 0), + PIXELFORMAT_RGB332 = (1 << 1), + PIXELFORMAT_RGB444 = (1 << 2), + PIXELFORMAT_RGB555 = (1 << 3), + PIXELFORMAT_RGB565 = (1 << 4), + PIXELFORMAT_RGB555X = (1 << 5), + PIXELFORMAT_RGB565X = (1 << 6), + PIXELFORMAT_BGR24 = (1 << 7), + PIXELFORMAT_RGB24 = (1 << 8), + PIXELFORMAT_BGR32 = (1 << 9), + PIXELFORMAT_RGB32 = (1 << 10), + +// Bayer RGB format + PIXELFORMAT_SBGGR8 = (1 << 11), + +// YUV formats + PIXELFORMAT_YUYV = (1 << 12), + PIXELFORMAT_UYVY = (1 << 13), + PIXELFORMAT_YUV420P = (1 << 14), + PIXELFORMAT_YUV422P = (1 << 15), + +// Compressed formats + PIXELFORMAT_JPEG = (1 << 16), + PIXELFORMAT_MPEG = (1 << 17), + +// Reserved formats + PIXELFORMAT_DV = (1 << 18), + PIXELFORMAT_ET61X251 = (1 << 19), + PIXELFORMAT_HI240 = (1 << 20), + PIXELFORMAT_HM12 = (1 << 21), + PIXELFORMAT_MJPEG = (1 << 22), + PIXELFORMAT_PWC1 = (1 << 23), + PIXELFORMAT_PWC2 = (1 << 24), + PIXELFORMAT_SN9C10X = (1 << 25), + PIXELFORMAT_WNVA = (1 << 26), + PIXELFORMAT_YYUV = (1 << 27) + +// PIXELFORMAT_ALL = 0x00003FFF +} pixel_format; + +typedef enum +{ +// One bit for each + STANDARD_PAL_B = (1 << 0), + STANDARD_PAL_B1 = (1 << 1), + STANDARD_PAL_G = (1 << 2), + STANDARD_PAL_H = (1 << 3), + STANDARD_PAL_I = (1 << 4), + STANDARD_PAL_D = (1 << 5), + STANDARD_PAL_D1 = (1 << 6), + STANDARD_PAL_K = (1 << 7), + + STANDARD_PAL_M = (1 << 8), + STANDARD_PAL_N = (1 << 9), + STANDARD_PAL_Nc = (1 << 10), + STANDARD_PAL_60 = (1 << 11), +// STANDARD_PAL_60 is a hybrid standard with 525 lines, 60 Hz refresh rate, and PAL color modulation with a 4.43 MHz color subcarrier. Some PAL video recorders can play back NTSC tapes in this mode for display on a 50/60 Hz agnostic PAL TV. + + STANDARD_NTSC_M = (1 << 12), + STANDARD_NTSC_M_JP = (1 << 13), + STANDARD_NTSC_443 = (1 << 14), +// STANDARD_NTSC_443 is a hybrid standard with 525 lines, 60 Hz refresh rate, and NTSC color modulation with a 4.43 MHz color subcarrier. + STANDARD_NTSC_M_KR = (1 << 15), + + STANDARD_SECAM_B = (1 << 16), + STANDARD_SECAM_D = (1 << 17), + STANDARD_SECAM_G = (1 << 18), + STANDARD_SECAM_H = (1 << 19), + STANDARD_SECAM_K = (1 << 20), + STANDARD_SECAM_K1 = (1 << 21), + STANDARD_SECAM_L = (1 << 22), + STANDARD_SECAM_LC = (1 << 23), + +// ATSC/HDTV + STANDARD_ATSC_8_VSB = (1 << 24), + STANDARD_ATSC_16_VSB = (1 << 25), + +// Some common needed stuff + STANDARD_PAL_BG = ( STANDARD_PAL_B | STANDARD_PAL_B1 | STANDARD_PAL_G ), + STANDARD_PAL_DK = ( STANDARD_PAL_D | STANDARD_PAL_D1 | STANDARD_PAL_K ), + STANDARD_PAL = ( STANDARD_PAL_BG | STANDARD_PAL_DK | STANDARD_PAL_H | STANDARD_PAL_I ), + STANDARD_NTSC = ( STANDARD_NTSC_M | STANDARD_NTSC_M_JP| STANDARD_NTSC_M_KR ), + STANDARD_SECAM_DK = ( STANDARD_SECAM_D | STANDARD_SECAM_K | STANDARD_SECAM_K1 ), + STANDARD_SECAM = ( STANDARD_SECAM_B | STANDARD_SECAM_G | STANDARD_SECAM_H | STANDARD_SECAM_DK | STANDARD_SECAM_L | STANDARD_SECAM_LC ), + +// some merged standards */ + STANDARD_MN = ( STANDARD_PAL_M | STANDARD_PAL_N | STANDARD_PAL_Nc | STANDARD_NTSC ), + STANDARD_B = ( STANDARD_PAL_B | STANDARD_PAL_B1 | STANDARD_SECAM_B ), + STANDARD_GH = ( STANDARD_PAL_G | STANDARD_PAL_H | STANDARD_SECAM_G | STANDARD_SECAM_H ), + STANDARD_DK = ( STANDARD_PAL_DK | STANDARD_SECAM_DK ), + + STANDARD_525_60 = ( STANDARD_PAL_M | STANDARD_PAL_60 | STANDARD_NTSC | STANDARD_NTSC_443), + STANDARD_625_50 = ( STANDARD_PAL | STANDARD_PAL_N | STANDARD_PAL_Nc | STANDARD_SECAM), + STANDARD_ATSC = ( STANDARD_ATSC_8_VSB | STANDARD_ATSC_16_VSB ), + + STANDARD_UNKNOWN = 0, + STANDARD_ALL = ( STANDARD_525_60 | STANDARD_625_50) +} signal_standard; + + +typedef enum +{ + IO_METHOD_NONE, + IO_METHOD_READ, + IO_METHOD_MMAP, + IO_METHOD_USERPTR +} io_method; + +struct imagebuffer +{ + int height; + int width; + pixel_format pixelformat; + QVector data; // maybe it should be a rawbuffer instead of it? It could make us avoid a memory copy +}; +struct rawbuffer // raw buffer +{ + uchar * start; + size_t length; +}; + + +class VideoDevice{ +public: + VideoDevice(); + ~VideoDevice(); + int setFileName(QString filename); + int open(); + bool isOpen(); + int checkDevice(); + int showDeviceCapabilities(); + int initDevice(); + int inputs(); + int width(); + int minWidth(); + int maxWidth(); + int height(); + int minHeight(); + int maxHeight(); + int setSize( int newwidth, int newheight); + + pixel_format setPixelFormat(pixel_format newformat); + int pixelFormatCode(pixel_format pixelformat); + pixel_format pixelFormatForPalette( int palette ); + int pixelFormatDepth(pixel_format pixelformat); + QString pixelFormatName(pixel_format pixelformat); + QString pixelFormatName(int pixelformat); + int detectPixelFormats(); + + __u64 signalStandardCode(signal_standard standard); + QString signalStandardName(signal_standard standard); + QString signalStandardName(int standard); + int detectSignalStandards(); + + int currentInput(); + int selectInput(int input); + int setInputParameters(); + int startCapturing(); + int getFrame(); + int getFrame(imagebuffer *imgbuffer); + int getImage(QImage *qimage); + int stopCapturing(); + int close(); + + float getBrightness(); + float setBrightness(float brightness); + float getContrast(); + float setContrast(float contrast); + float getSaturation(); + float setSaturation(float saturation); + float getWhiteness(); + float setWhiteness(float whiteness); + float getHue(); + float setHue(float Hue); + + bool getAutoBrightnessContrast(); + bool setAutoBrightnessContrast(bool brightnesscontrast); + bool getAutoColorCorrection(); + bool setAutoColorCorrection(bool colorcorrection); + bool getImageAsMirror(); + bool setImageAsMirror(bool imageasmirror); + + bool canCapture(); + bool canChromakey(); + bool canScale(); + bool canOverlay(); + bool canRead(); + bool canAsyncIO(); + bool canStream(); + + void setUdi( const QString & ); + QString udi() const; + QString m_model; + QString m_name; + size_t m_modelindex; // Defines what's the number of a device when more than 1 device of a given model is present; + QString full_filename; + videodev_driver m_driver; + int descriptor; + +//protected: +#if defined(__linux__) && defined(ENABLE_AV) +#ifdef V4L2_CAP_VIDEO_CAPTURE + struct v4l2_capability V4L2_capabilities; + struct v4l2_cropcap cropcap; + struct v4l2_crop crop; + struct v4l2_format fmt; + struct v4l2_fmtdesc fmtdesc; // Not sure if it must be here or inside detectPixelFormats(). Should inve +// struct v4l2_input m_input; + struct v4l2_queryctrl queryctrl; + struct v4l2_querymenu querymenu; + void enumerateControls (void); + void enumerateMenu (void); +#endif + struct video_capability V4L_capabilities; + struct video_buffer V4L_videobuffer; +#endif + QVector m_input; +// QFile file; +protected: + int currentwidth, minwidth, maxwidth, currentheight, minheight, maxheight; + + QVector m_rawbuffers; + unsigned int m_streambuffers; + imagebuffer m_currentbuffer; + int m_buffer_size; + + int m_current_input; + pixel_format m_pixelformat; + + io_method m_io_method; + bool m_videocapture; + bool m_videochromakey; + bool m_videoscale; + bool m_videooverlay; + bool m_videoread; + bool m_videoasyncio; + bool m_videostream; + + int xioctl(int request, void *arg); + int errnoReturn(const char* s); + int initRead(); + int initMmap(); + int initUserptr(); + + QString m_udi; +}; + +} +} + +#endif diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevicemodelpool.cpp b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevicemodelpool.cpp new file mode 100644 index 0000000..c3e6972 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevicemodelpool.cpp @@ -0,0 +1,64 @@ +/* + videodevicemodelpool.h - Multiple Video Device Model Handler Class + + Copyright (c) 2005-2008 by Cláudio da Silveira Pinheiro + + ************************************************************************* + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + ************************************************************************* +*/ + +#include "videodevicemodelpool.h" + +namespace Phonon { +namespace VideoCapture { + +VideoDeviceModelPool::VideoDeviceModelPool() +{ +} + + +VideoDeviceModelPool::~VideoDeviceModelPool() +{ +} + +void VideoDeviceModelPool::clear() +{ + m_devicemodel.clear(); +} + +size_t VideoDeviceModelPool::size() +{ + return m_devicemodel.size(); +} + +size_t VideoDeviceModelPool::addModel( QString newmodel ) +{ + VideoDeviceModel newdevicemodel; + newdevicemodel.model=newmodel; + newdevicemodel.count=0; + + if(m_devicemodel.size()) + { + for ( int loop = 0 ; loop < m_devicemodel.size(); loop++) + if (newmodel == m_devicemodel[loop].model) + { + kDebug() << "Model " << newmodel << " already exists."; + m_devicemodel[loop].count++; + return m_devicemodel[loop].count; + } + } + m_devicemodel.push_back(newdevicemodel); + m_devicemodel[m_devicemodel.size()-1].model = newmodel; + m_devicemodel[m_devicemodel.size()-1].count = 0; + return 0; +} + + +} +} diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevicemodelpool.h b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevicemodelpool.h new file mode 100644 index 0000000..d7d35e0 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevicemodelpool.h @@ -0,0 +1,48 @@ +/* + videodevicemodelpool.h - Multiple Video Device Model Handler Class + + Copyright (c) 2005-2008 by Cláudio da Silveira Pinheiro + + ************************************************************************* + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + ************************************************************************* +*/ + +#ifndef VIDEODEVICEMODELPOOL_H +#define VIDEODEVICEMODELPOOL_H + +#include +#include +#include + +namespace Phonon { +namespace VideoCapture { + +/** + @author Kopete Developers +*/ +class VideoDeviceModelPool{ + + struct VideoDeviceModel + { + QString model; + size_t count; + }; + QVector m_devicemodel; +public: + VideoDeviceModelPool(); + ~VideoDeviceModelPool(); + void clear(); + size_t size(); + size_t addModel(QString newmodel); +}; + +} +} + +#endif diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevicepool.cpp b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevicepool.cpp new file mode 100644 index 0000000..623e382 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevicepool.cpp @@ -0,0 +1,894 @@ +/* + videodevicepool.cpp - Multiple Video Device Handler Class + + Copyright (c) 2005-2008 by Cláudio da Silveira Pinheiro + + ************************************************************************* + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + ************************************************************************* +*/ + +#define ENABLE_AV + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "videodevice.h" +#include "videodevicepool.h" + +#define CLEAR(x) memset (&(x), 0, sizeof (x)) + +namespace Phonon { +namespace VideoCapture { + +VideoDevicePool *VideoDevicePool::s_self = NULL; +__u64 VideoDevicePool::m_clients = 0; + +VideoDevicePool* VideoDevicePool::self() +{ +// kDebug() << "libkopete (avdevice): self() called"; + if (s_self == NULL) + { + s_self = new VideoDevicePool; + if (s_self) + m_clients = 0; + } +// kDebug() << "libkopete (avdevice): self() exited successfuly"; + return s_self; +} + +VideoDevicePool::VideoDevicePool() +{ + connect( Solid::DeviceNotifier::instance(), SIGNAL(deviceAdded(const QString&)), SLOT(deviceAdded(const QString &)) ); + connect( Solid::DeviceNotifier::instance(), SIGNAL(deviceRemoved(const QString&)), SLOT(deviceRemoved(const QString &)) ); +} + + +VideoDevicePool::~VideoDevicePool() +{ +} + + + + +/*! + \fn VideoDevicePool::open() + */ +int VideoDevicePool::open() +{ + /// @todo implement me + + m_ready.lock(); + if(!m_videodevice.size()) + { + kDebug() << "open(): No devices found. Must scan for available devices." << m_current_device; + scanDevices(); + } + if(!m_videodevice.size()) + { + kDebug() << "open(): No devices found. bailing out." << m_current_device; + m_ready.unlock(); + return EXIT_FAILURE; + } + if(m_current_device >= m_videodevice.size()) + { + kDebug() << "open(): Device out of scope (" << m_current_device << "). Defaulting to the first one."; + m_current_device = 0; + } + int isopen = m_videodevice[currentDevice()].open(); + if ( isopen == EXIT_SUCCESS) + { + loadConfig(); // Temporary hack. The open() seems to clean the input parameters. Need to find a way to fix it. + + } + m_clients++; + kDebug() << "Number of clients: " << m_clients; + m_ready.unlock(); + return isopen; +} + +/*! + \fn VideoDevicePool::open(int device) + */ +int VideoDevicePool::open(int device) +{ + /// @todo implement me + kDebug() << "open(" << device << ") called."; + if(device >= m_videodevice.size()) + { + kDebug() << "open(" << device <<"): Device does not exist."; + return EXIT_FAILURE; + } + close(); + kDebug() << "open(" << device << ") Setting m_current_Device to " << device; + m_current_device = device; + kDebug() << "open(" << device << ") Calling open()."; + saveConfig(); + + return open(); +} + +bool VideoDevicePool::isOpen() +{ + return m_videodevice[currentDevice()].isOpen(); +} + +/*! + \fn VideoDevicePool::showDeviceCapabilities(int device) + */ +int VideoDevicePool::showDeviceCapabilities(unsigned int device) +{ + return m_videodevice[device].showDeviceCapabilities(); +} + +int VideoDevicePool::width() +{ + return m_videodevice[currentDevice()].width(); +} + +int VideoDevicePool::minWidth() +{ + return m_videodevice[currentDevice()].minWidth(); +} + +int VideoDevicePool::maxWidth() +{ + return m_videodevice[currentDevice()].maxWidth(); +} + +int VideoDevicePool::height() +{ + return m_videodevice[currentDevice()].height(); +} + +int VideoDevicePool::minHeight() +{ + return m_videodevice[currentDevice()].minHeight(); +} + +int VideoDevicePool::maxHeight() +{ + return m_videodevice[currentDevice()].maxHeight(); +} + +int VideoDevicePool::setSize( int newwidth, int newheight) +{ + if(m_videodevice.size()) + return m_videodevice[currentDevice()].setSize(newwidth, newheight); + else + { + kDebug() << "VideoDevicePool::setSize() fallback for no device."; + m_buffer.width=newwidth; + m_buffer.height=newheight; + m_buffer.pixelformat= PIXELFORMAT_RGB24; + m_buffer.data.resize(m_buffer.width*m_buffer.height*3); + kDebug() << "VideoDevicePool::setSize() buffer size: "<< m_buffer.data.size(); + } + return EXIT_SUCCESS; +} + +/*! + \fn VideoDevicePool::close() + */ +int VideoDevicePool::close() +{ + /// @todo implement me + if(m_clients) + m_clients--; + if((currentDevice() < m_videodevice.size())&&(!m_clients)) + return m_videodevice[currentDevice()].close(); + if(m_clients) + kDebug() << "VideoDevicePool::close() The video device is still in use."; + if(currentDevice() >= m_videodevice.size()) + kDebug() << "VideoDevicePool::close() Current device out of range."; + return EXIT_FAILURE; +} + +/*! + \fn VideoDevicePool::startCapturing() + */ +int VideoDevicePool::startCapturing() +{ + kDebug() << "startCapturing() called."; + if(m_videodevice.size()) + return m_videodevice[currentDevice()].startCapturing(); + return EXIT_FAILURE; +} + + +/*! + \fn VideoDevicePool::stopCapturing() + */ +int VideoDevicePool::stopCapturing() +{ + if(m_videodevice.size()) + return m_videodevice[currentDevice()].stopCapturing(); + return EXIT_FAILURE; +} + +// Implementation of the methods that get / set input's adjustment parameters +/*! + \fn VideoDevicePool::getBrightness() + */ +float VideoDevicePool::getBrightness() +{ + if (currentDevice() < m_videodevice.size() ) + return m_videodevice[currentDevice()].getBrightness(); + else + return 0; +} + +/*! + \fn VideoDevicePool::setBrightness(float brightness) + */ +float VideoDevicePool::setBrightness(float brightness) +{ + if (currentDevice() < m_videodevice.size() ) + return m_videodevice[currentDevice()].setBrightness(brightness); + else + return 0; +} + +/*! + \fn VideoDevicePool::getContrast() + */ +float VideoDevicePool::getContrast() +{ + if (currentDevice() < m_videodevice.size() ) + return m_videodevice[currentDevice()].getContrast(); + else + return 0; +} + +/*! + \fn VideoDevicePool::setContrast(float contrast) + */ +float VideoDevicePool::setContrast(float contrast) +{ + if (currentDevice() < m_videodevice.size() ) + return m_videodevice[currentDevice()].setContrast(contrast); + else + return 0; +} + +/*! + \fn VideoDevicePool::getSaturation() + */ +float VideoDevicePool::getSaturation() +{ + if (currentDevice() < m_videodevice.size() ) + return m_videodevice[currentDevice()].getSaturation(); + else + return 0; +} + +/*! + \fn VideoDevicePool::setSaturation(float saturation) + */ +float VideoDevicePool::setSaturation(float saturation) +{ + if (currentDevice() < m_videodevice.size() ) + return m_videodevice[currentDevice()].setSaturation(saturation); + else + return 0; +} + +/*! + \fn VideoDevicePool::getWhiteness() + */ +float VideoDevicePool::getWhiteness() +{ + if (currentDevice() < m_videodevice.size() ) + return m_videodevice[currentDevice()].getWhiteness(); + else + return 0; +} + +/*! + \fn VideoDevicePool::setWhiteness(float whiteness) + */ +float VideoDevicePool::setWhiteness(float whiteness) +{ + if (currentDevice() < m_videodevice.size() ) + return m_videodevice[currentDevice()].setWhiteness(whiteness); + else + return 0; +} + +/*! + \fn VideoDevicePool::getHue() + */ +float VideoDevicePool::getHue() +{ + if (currentDevice() < m_videodevice.size() ) + return m_videodevice[currentDevice()].getHue(); + else + return 0; +} + +/*! + \fn VideoDevicePool::setHue(float hue) + */ +float VideoDevicePool::setHue(float hue) +{ + if (currentDevice() < m_videodevice.size() ) + return m_videodevice[currentDevice()].setHue(hue); + else + return 0; +} + +/*! + \fn VideoDevicePool::getAutoBrightnessContrast() + */ +bool VideoDevicePool::getAutoBrightnessContrast() +{ + if(m_videodevice.size()) + return m_videodevice[currentDevice()].getAutoBrightnessContrast(); + return false; +} + +/*! + \fn VideoDevicePool::setAutoBrightnessContrast(bool brightnesscontrast) + */ +bool VideoDevicePool::setAutoBrightnessContrast(bool brightnesscontrast) +{ + kDebug() << "VideoDevicePool::setAutoBrightnessContrast(" << brightnesscontrast << ") called."; + if(m_videodevice.size()) + return m_videodevice[currentDevice()].setAutoBrightnessContrast(brightnesscontrast); + return false; +} + +/*! + \fn VideoDevicePool::getAutoColorCorrection() + */ +bool VideoDevicePool::getAutoColorCorrection() +{ + if(m_videodevice.size()) + return m_videodevice[currentDevice()].getAutoColorCorrection(); + return false; +} + +/*! + \fn VideoDevicePool::setAutoColorCorrection(bool colorcorrection) + */ +bool VideoDevicePool::setAutoColorCorrection(bool colorcorrection) +{ + kDebug() << "VideoDevicePool::setAutoColorCorrection(" << colorcorrection << ") called."; + if(m_videodevice.size()) + return m_videodevice[currentDevice()].setAutoColorCorrection(colorcorrection); + return false; +} + +/*! + \fn VideoDevicePool::getIMageAsMirror() + */ +bool VideoDevicePool::getImageAsMirror() +{ + if(m_videodevice.size()) + return m_videodevice[currentDevice()].getImageAsMirror(); + return false; +} + +/*! + \fn VideoDevicePool::setImageAsMirror(bool imageasmirror) + */ +bool VideoDevicePool::setImageAsMirror(bool imageasmirror) +{ + kDebug() << "VideoDevicePool::setImageAsMirror(" << imageasmirror << ") called."; + if(m_videodevice.size()) + return m_videodevice[currentDevice()].setImageAsMirror(imageasmirror); + return false; +} + +/*! + \fn VideoDevicePool::getFrame() + */ +int VideoDevicePool::getFrame() +{ +// kDebug() << "VideoDevicePool::getFrame() called."; + if(m_videodevice.size()) + return m_videodevice[currentDevice()].getFrame(); + else + { + kDebug() << "VideoDevicePool::getFrame() fallback for no device."; + for(int loop=0; loop < m_buffer.data.size(); loop+=3) + { + m_buffer.data[loop] = 255; + m_buffer.data[loop+1] = 0; + m_buffer.data[loop+2] = 0; + } + } + kDebug() << "VideoDevicePool::getFrame() exited successfuly."; + + return EXIT_SUCCESS; +} + +/*! + \fn VideoDevicePool::getQImage(QImage *qimage) + */ +int VideoDevicePool::getImage(QImage *qimage) +{ +// kDebug() << "VideoDevicePool::getImage() called."; + if(m_videodevice.size()) + return m_videodevice[currentDevice()].getImage(qimage); + else + { + kDebug() << "VideoDevicePool::getImage() fallback for no device."; + + // do NOT delete qimage here, as it is received as a parameter + if (qimage->width() != width() || qimage->height() != height()) + *qimage = QImage(width(), height(), QImage::Format_RGB32); + + uchar *bits=qimage->bits(); + switch(m_buffer.pixelformat) + { + case PIXELFORMAT_NONE : break; + case PIXELFORMAT_GREY : break; + case PIXELFORMAT_RGB332 : break; + case PIXELFORMAT_RGB555 : break; + case PIXELFORMAT_RGB555X: break; + case PIXELFORMAT_RGB565 : break; + case PIXELFORMAT_RGB565X: break; + case PIXELFORMAT_RGB24 : + { + kDebug() << "VideoDevicePool::getImage() fallback for no device - RGB24."; + int step=0; + for(int loop=0;loop < qimage->numBytes();loop+=4) + { + bits[loop] = m_buffer.data[step]; + bits[loop+1] = m_buffer.data[step+1]; + bits[loop+2] = m_buffer.data[step+2]; + bits[loop+3] = 255; + step+=3; + } + } + break; + case PIXELFORMAT_BGR24 : break; + { + int step=0; + for(int loop=0;loop < qimage->numBytes();loop+=4) + { + bits[loop] = m_buffer.data[step+2]; + bits[loop+1] = m_buffer.data[step+1]; + bits[loop+2] = m_buffer.data[step]; + bits[loop+3] = 255; + step+=3; + } + } + break; + case PIXELFORMAT_RGB32 : memcpy(bits,&m_buffer.data[0], m_buffer.data.size()); + break; + case PIXELFORMAT_BGR32 : break; + case PIXELFORMAT_YUYV : break; + case PIXELFORMAT_UYVY : break; + case PIXELFORMAT_YUV420P: break; + case PIXELFORMAT_YUV422P: break; + } + } + kDebug() << "VideoDevicePool::getImage() exited successfuly."; + return EXIT_SUCCESS; +} + +/*! + \fn Kopete::AV::VideoDevicePool::selectInput(int input) + */ +int VideoDevicePool::selectInput(int newinput) +{ + kDebug() << "VideoDevicePool::selectInput(" << newinput << ") called."; + if(m_videodevice.size()) + return m_videodevice[currentDevice()].selectInput(newinput); + else + return 0; +} + +/*! + \fn Kopete::AV::VideoDevicePool::setInputParameters() + */ +int VideoDevicePool::setInputParameters() +{ + if(m_videodevice.size()) + return m_videodevice[currentDevice()].setInputParameters(); + else + return EXIT_FAILURE; +} + +/*! + \fn Kopete::AV::VideoDevicePool::fillDeviceKComboBox(KComboBox *combobox) + */ +int VideoDevicePool::fillDeviceKComboBox(KComboBox *combobox) +{ + /// @todo implement me + kDebug() << "Called."; +// check if KComboBox is a valid pointer. + if (combobox != NULL) + { + combobox->clear(); + kDebug() << "Combobox cleaned."; + if(m_videodevice.size()) + { + for (int loop=0; loop < m_videodevice.size(); loop++) + { + combobox->addItem(m_videodevice[loop].m_name); + kDebug() << "Added device " << loop << ": " << m_videodevice[loop].m_name; + } + combobox->setCurrentIndex(currentDevice()); + return EXIT_SUCCESS; + } + } + return EXIT_FAILURE; +} + +/*! + \fn Kopete::AV::VideoDevicePool::fillInputKComboBox(KComboBox *combobox) + */ +int VideoDevicePool::fillInputKComboBox(KComboBox *combobox) +{ + /// @todo implement me + kDebug() << "Called."; + if (combobox != NULL) + { + combobox->clear(); + if ( !m_videodevice.isEmpty() && (currentDevice()>=0) && currentDevice() < m_videodevice.size() ) + { + if(m_videodevice[currentDevice()].inputs()>0) + { + for (int loop=0; loop < m_videodevice[currentDevice()].inputs(); loop++) + { + combobox->addItem(m_videodevice[currentDevice()].m_input[loop].name); + kDebug() << "Added input " << loop << ": " << m_videodevice[currentDevice()].m_input[loop].name << " (tuner: " << m_videodevice[currentDevice()].m_input[loop].hastuner << ")"; + } + combobox->setCurrentIndex(currentInput()); + return EXIT_SUCCESS; + } + } + } + return EXIT_FAILURE; +} + +/*! + \fn Kopete::AV::VideoDevicePool::fillStandardKComboBox(KComboBox *combobox) + */ +int VideoDevicePool::fillStandardKComboBox(KComboBox *combobox) +{ + /// @todo implement me + kDebug() << "Called."; + if (combobox != NULL) + { + combobox->clear(); + if ( !m_videodevice.isEmpty() && currentDevice() < m_videodevice.size() ) + { + if(m_videodevice[currentDevice()].inputs()>0) + { + for (unsigned int loop=0; loop < 25; loop++) + { + if ( (m_videodevice[currentDevice()].m_input[currentInput()].m_standards) & (1 << loop) ) + combobox->addItem(m_videodevice[currentDevice()].signalStandardName( 1 << loop)); +/* + case STANDARD_PAL_B1 : return V4L2_STD_PAL_B1; break; + case STANDARD_PAL_G : return V4L2_STD_PAL_G; break; + case STANDARD_PAL_H : return V4L2_STD_PAL_H; break; + case STANDARD_PAL_I : return V4L2_STD_PAL_I; break; + case STANDARD_PAL_D : return V4L2_STD_PAL_D; break; + case STANDARD_PAL_D1 : return V4L2_STD_PAL_D1; break; + case STANDARD_PAL_K : return V4L2_STD_PAL_K; break; + case STANDARD_PAL_M : return V4L2_STD_PAL_M; break; + case STANDARD_PAL_N : return V4L2_STD_PAL_N; break; + case STANDARD_PAL_Nc : return V4L2_STD_PAL_Nc; break; + case STANDARD_PAL_60 : return V4L2_STD_PAL_60; break; + case STANDARD_NTSC_M : return V4L2_STD_NTSC_M; break; + case STANDARD_NTSC_M_JP : return V4L2_STD_NTSC_M_JP; break; + case STANDARD_NTSC_443 : return V4L2_STD_NTSC; break; // Using workaround value because my videodev2.h header seems to not include this standard in struct __u64 v4l2_std_id + case STANDARD_SECAM_B : return V4L2_STD_SECAM_B; break; + case STANDARD_SECAM_D : return V4L2_STD_SECAM_D; break; + case STANDARD_SECAM_G : return V4L2_STD_SECAM_G; break; + case STANDARD_SECAM_H : return V4L2_STD_SECAM_H; break; + case STANDARD_SECAM_K : return V4L2_STD_SECAM_K; break; + case STANDARD_SECAM_K1 : return V4L2_STD_SECAM_K1; break; + case STANDARD_SECAM_L : return V4L2_STD_SECAM_L; break; + case STANDARD_SECAM_LC : return V4L2_STD_SECAM; break; // Using workaround value because my videodev2.h header seems to not include this standard in struct __u64 v4l2_std_id + case STANDARD_ATSC_8_VSB : return V4L2_STD_ATSC_8_VSB; break; // ATSC/HDTV Standard officially not supported by V4L2 but exists in videodev2.h + case STANDARD_ATSC_16_VSB : return V4L2_STD_ATSC_16_VSB; break; // ATSC/HDTV Standard officially not supported by V4L2 but exists in videodev2.h + case STANDARD_PAL_BG : return V4L2_STD_PAL_BG; break; + case STANDARD_PAL_DK : return V4L2_STD_PAL_DK; break; + case STANDARD_PAL : return V4L2_STD_PAL; break; + case STANDARD_NTSC : return V4L2_STD_NTSC; break; + case STANDARD_SECAM_DK : return V4L2_STD_SECAM_DK; break; + case STANDARD_SECAM : return V4L2_STD_SECAM; break; + case STANDARD_525_60 : return V4L2_STD_525_60; break; + case STANDARD_625_50 : return V4L2_STD_625_50; break; + case STANDARD_ALL : return V4L2_STD_ALL; break; + + combobox->insertItem(m_videodevice[currentDevice()].m_input[loop].name); + kDebug() << "StandardKCombobox: Added input " << loop << ": " << m_videodevice[currentDevice()].m_input[loop].name << " (tuner: " << m_videodevice[currentDevice()].m_input[loop].hastuner << ")";*/ + } + combobox->setCurrentIndex(currentInput()); + return EXIT_SUCCESS; + } + } + } + return EXIT_FAILURE; +} + +/*! + \fn Kopete::AV::VideoDevicePool::scanDevices() + */ +int VideoDevicePool::scanDevices() +{ + /// @todo implement me + + kDebug() << "called"; +#if defined(__linux__) && defined(ENABLE_AV) + foreach (Solid::Device device, + Solid::Device::listFromType(Solid::DeviceInterface::Video, QString())) { + registerDevice( device ); + } + +#endif + kDebug() << "exited successfuly"; + return EXIT_SUCCESS; +} + +void VideoDevicePool::registerDevice( Solid::Device & device ) +{ + kDebug() << "New video device at " << device.udi(); + const Solid::Device * vendorDevice = &device; + while ( vendorDevice->isValid() && vendorDevice->vendor().isEmpty() ) + { + vendorDevice = new Solid::Device( vendorDevice->parentUdi() ); + } + if ( vendorDevice->isValid() ) + { + kDebug() << "vendor: " << vendorDevice->vendor() << ", product: " << vendorDevice->product(); + } + Solid::Video * solidVideoDevice = device.as(); + if ( solidVideoDevice ) { + QStringList protocols = solidVideoDevice->supportedProtocols(); + if ( protocols.contains( "video4linux" ) ) + { + QStringList drivers = solidVideoDevice->supportedDrivers( "video4linux" ); + if ( drivers.contains( "video4linux" ) ) + { + kDebug() << "V4L device path is" << solidVideoDevice->driverHandle( "video4linux" ).toString(); + VideoDevice videodevice; + videodevice.setUdi( device.udi() ); + videodevice.setFileName(solidVideoDevice->driverHandle( "video4linux" ).toString()); + kDebug() << "Found device " << videodevice.full_filename; + videodevice.open(); + if(videodevice.isOpen()) + { + kDebug() << "File " << videodevice.full_filename << " was opened successfuly"; + videodevice.close(); + videodevice.m_modelindex=m_modelvector.addModel (videodevice.m_model); // Adds device to the device list and sets model number + m_videodevice.push_back(videodevice); + } + } + } + } +} + +/*! + \fn Kopete::AV::VideoDevicePool::hasDevices() + */ +bool VideoDevicePool::hasDevices() +{ + /// @todo implement me + if(m_videodevice.size()) + return true; + return false; +} + +/*! + \fn Kopete::AV::VideoDevicePool::size() + */ +size_t VideoDevicePool::size() +{ + /// @todo implement me + return m_videodevice.size(); +} + +/*! + \fn Kopete::AV::VideoDevicePool::currentDevice() + */ +int VideoDevicePool::currentDevice() +{ + /// @todo implement me + return m_current_device; +} + +/*! + \fn Kopete::AV::VideoDevicePool::currentInput() + */ +int VideoDevicePool::currentInput() +{ + /// @todo implement me + return m_videodevice[currentDevice()].currentInput(); +} + +/*! + \fn Kopete::AV::VideoDevicePool::currentInput() + */ +unsigned int VideoDevicePool::inputs() +{ + /// @todo implement me + return m_videodevice[currentDevice()].inputs(); +} + +/*! + \fn Kopete::AV::VideoDevicePool::loadConfig() + */ +void VideoDevicePool::loadConfig() +{ + /// @todo implement me + kDebug() << "called"; + if((hasDevices())&&(m_clients==0)) + { + KConfigGroup config(KGlobal::config(), "Video Device Settings"); + QString currentdevice = config.readEntry("Current Device", QString()); + kDebug() << "Current device: " << currentdevice; + +// m_current_device = 0; // Must check this thing because of the fact that multiple loadConfig in other methodas can do bad things. Watch out! + + VideoDeviceVector::iterator vditerator; + for( vditerator = m_videodevice.begin(); vditerator != m_videodevice.end(); ++vditerator ) + { + const QString modelindex = QString::fromLocal8Bit ( "Model %1 Device %2") .arg ((*vditerator).m_name ) .arg ((*vditerator).m_modelindex); + if(modelindex == currentdevice) + { + m_current_device = std::distance (m_videodevice.begin(), vditerator); +// kDebug() << "This place will be used to set " << modelindex << " as the current device ( " << std::distance(m_videodevice.begin(), vditerator ) << " )."; + } + const QString name = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Name") .arg ((*vditerator).m_name ) .arg ((*vditerator).m_modelindex)), (*vditerator).m_model); + const int currentinput = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Current input") .arg ((*vditerator).m_name ) .arg ((*vditerator).m_modelindex)), 0); + kDebug() << "Device name: " << name; + kDebug() << "Device current input: " << currentinput; + (*vditerator).selectInput(currentinput); + + for (int input = 0 ; input < (*vditerator).m_input.size(); input++) + { + const float brightness = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Brightness").arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input)) , 0.5 ); + const float contrast = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Contrast") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input)) , 0.5 ); + const float saturation = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Saturation").arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input)) , 0.5 ); + const float whiteness = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Whiteness") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input)) , 0.5 ); + const float hue = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Hue") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input)) , 0.5 ); + const bool autobrightnesscontrast = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 AutoBrightnessContrast") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input)) , false ); + const bool autocolorcorrection = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 AutoColorCorrection") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input)) , false ); + const bool imageasmirror = config.readEntry((QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 mageAsMirror") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input)) , false ); + (*vditerator).setBrightness(brightness); + (*vditerator).setContrast(contrast); + (*vditerator).setSaturation(saturation); + (*vditerator).setHue(hue); + (*vditerator).setAutoBrightnessContrast(autobrightnesscontrast); + (*vditerator).setAutoColorCorrection(autocolorcorrection); + (*vditerator).setImageAsMirror(imageasmirror); + kDebug() << "Brightness:" << brightness; + kDebug() << "Contrast :" << contrast; + kDebug() << "Saturation:" << saturation; + kDebug() << "Whiteness :" << whiteness; + kDebug() << "Hue :" << hue; + kDebug() << "AutoBrightnessContrast:" << autobrightnesscontrast; + kDebug() << "AutoColorCorrection :" << autocolorcorrection; + kDebug() << "ImageAsMirror :" << imageasmirror; + } + } + } +} + +/*! + \fn Kopete::AV::VideoDevicePool::saveConfig() + */ +void VideoDevicePool::saveConfig() +{ + /// @todo implement me + kDebug() << "called"; + if(hasDevices()) + { + KConfigGroup config(KGlobal::config(), "Video Device Settings"); + +/* if(m_modelvector.size()) + { + VideoDeviceModelPool::m_devicemodel::iterator vmiterator; + for( vmiterator = m_modelvector.begin(); vmiterator != m_modelvector.end(); ++vmiterator ) + { + kDebug() << "Device Model: " << (*vmiterator).name; + kDebug() << "Device Count: " << (*vmiterator).count; + } + } +*/ +// Stores what is the current video device in use + const QString currentdevice = QString::fromLocal8Bit ( "Model %1 Device %2" ) .arg(m_videodevice[m_current_device].m_model) .arg(m_videodevice[m_current_device].m_modelindex); + config.writeEntry( "Current Device", currentdevice); + + VideoDeviceVector::iterator vditerator; + for( vditerator = m_videodevice.begin(); vditerator != m_videodevice.end(); ++vditerator ) + { + kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Name:" << (*vditerator).m_name; + kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Current input:" << (*vditerator).currentInput(); + +// Stores current input for the given video device + const QString name = QString::fromLocal8Bit ( "Model %1 Device %2 Name") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex); + const QString currentinput = QString::fromLocal8Bit ( "Model %1 Device %2 Current input") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex); + config.writeEntry( name, (*vditerator).m_name); + config.writeEntry( currentinput, (*vditerator).currentInput()); + + for (int input = 0 ; input < (*vditerator).m_input.size(); input++) + { + kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Input:" << input << ":Brightness: " << (*vditerator).m_input[input].getBrightness(); + kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Input:" << input << ":Contrast : " << (*vditerator).m_input[input].getContrast(); + kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Input:" << input << ":Saturation: " << (*vditerator).m_input[input].getSaturation(); + kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Input:" << input << ":Whiteness : " << (*vditerator).m_input[input].getWhiteness(); + kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Input:" << input << ":Hue : " << (*vditerator).m_input[input].getHue(); + kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Input:" << input << ":Automatic brightness / contrast: " << (*vditerator).m_input[input].getAutoBrightnessContrast(); + kDebug() << "Model:" << (*vditerator).m_model << ":Index:" << (*vditerator).m_modelindex << ":Input:" << input << ":Automatic color correction : " << (*vditerator).m_input[input].getAutoColorCorrection(); + +// Stores configuration about each channel + const QString brightness = QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Brightness") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input); + const QString contrast = QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Contrast") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input); + const QString saturation = QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Saturation") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input); + const QString whiteness = QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Whiteness") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input); + const QString hue = QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 Hue") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input); + const QString autobrightnesscontrast = QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 AutoBrightnessContrast") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input); + const QString autocolorcorrection = QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 AutoColorCorrection") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input); + const QString imageasmirror = QString::fromLocal8Bit ( "Model %1 Device %2 Input %3 ImageAsMirror") .arg ((*vditerator).m_model ) .arg ((*vditerator).m_modelindex) .arg (input); + config.writeEntry( brightness, (double)(*vditerator).m_input[input].getBrightness()); + config.writeEntry( contrast, (double)(*vditerator).m_input[input].getContrast()); + config.writeEntry( saturation, (double)(*vditerator).m_input[input].getSaturation()); + config.writeEntry( whiteness, (double)(*vditerator).m_input[input].getWhiteness()); + config.writeEntry( hue, (double)(*vditerator).m_input[input].getHue()); + config.writeEntry( autobrightnesscontrast, (*vditerator).m_input[input].getAutoBrightnessContrast()); + config.writeEntry( autocolorcorrection, (*vditerator).m_input[input].getAutoColorCorrection()); + config.writeEntry( imageasmirror, (*vditerator).m_input[input].getImageAsMirror()); + } + } + config.sync(); + kDebug(); + } +} + +void VideoDevicePool::deviceAdded( const QString & udi ) +{ + kDebug() << "("<< udi << ") called"; + Solid::Device dev( udi ); + if ( dev.is() ) + { + registerDevice( dev ); + emit deviceRegistered( udi ); + } +} + +void VideoDevicePool::deviceRemoved( const QString & udi ) +{ + kDebug() << "("<< udi << ") called"; + int i = 0; + foreach ( VideoDevice vd, m_videodevice ) { + + if ( vd.udi() == udi ) { + kDebug() << "Video device '" << udi << "' has been removed!"; + } + emit deviceUnregistered( udi ); + m_videodevice.remove( i ); // not sure if this is safe but at this point the device node is + // gone already anyway + i++; + } +} + +} +} diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevicepool.h b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevicepool.h new file mode 100644 index 0000000..b35310a --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videodevicepool.h @@ -0,0 +1,134 @@ +/* + videodevicepool.h - Multiple Video Device Handler Class + + Copyright (c) 2005-2008 by Cláudio da Silveira Pinheiro + + ************************************************************************* + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + ************************************************************************* +*/ + +#ifndef VIDEODEVICEPOOL_H +#define VIDEODEVICEPOOL_H + +#include + + +#include "videoinput.h" +#include "videodevicemodelpool.h" +#include +#include +#include +#include +#include +#include "videodevice.h" +#include +#include +#include + +namespace Phonon { +namespace VideoCapture { + +/** +This class allows kopete to check for the existence, open, configure, test, set parameters, grab frames from and close a given video capture card using the Video4Linux API. + +@author Cláudio da Silveira Pinheiro +*/ + +typedef QVector VideoDeviceVector; + + +class KDE_EXPORT VideoDevicePool : public QObject +{ +Q_OBJECT +public: + static VideoDevicePool* self(); + int open(); + int open(int device); + bool isOpen(); + int getFrame(); + int width(); + int minWidth(); + int maxWidth(); + int height(); + int minHeight(); + int maxHeight(); + int setSize( int newwidth, int newheight); + int close(); + int startCapturing(); + int stopCapturing(); + int readFrame(); + int getImage(QImage *qimage); + int selectInput(int newinput); + int setInputParameters(); + int scanDevices(); + void registerDevice( Solid::Device & dev ); + bool hasDevices(); + size_t size(); + ~VideoDevicePool(); + VideoDeviceVector m_videodevice; // Vector to be filled with found devices + VideoDeviceModelPool m_modelvector; // Vector to be filled with unique device models + int fillDeviceKComboBox(KComboBox *combobox); + int fillInputKComboBox(KComboBox *combobox); + int fillStandardKComboBox(KComboBox *combobox); + int currentDevice(); + int currentInput(); + unsigned int inputs(); + + float getBrightness(); + float setBrightness(float brightness); + float getContrast(); + float setContrast(float contrast); + float getSaturation(); + float setSaturation(float saturation); + float getWhiteness(); + float setWhiteness(float whiteness); + float getHue(); + float setHue(float hue); + + bool getAutoBrightnessContrast(); + bool setAutoBrightnessContrast(bool brightnesscontrast); + bool getAutoColorCorrection(); + bool setAutoColorCorrection(bool colorcorrection); + bool getImageAsMirror(); + bool setImageAsMirror(bool imageasmirror); + + void loadConfig(); // Load configuration parameters; + void saveConfig(); // Save configuretion parameters; + +signals: + /** + * Provisional signatures, probably more useful to indicate which device was registered + */ + void deviceRegistered( const QString & udi ); + void deviceUnregistered( const QString & udi ); +protected slots: + /** + * Slot called when a new device is added to the system + */ + void deviceAdded( const QString & udi ); + void deviceRemoved( const QString & udi ); +protected: + int xioctl(int request, void *arg); + int errnoReturn(const char* s); + int showDeviceCapabilities(unsigned int device); + void guessDriver(); + int m_current_device; + struct imagebuffer m_buffer; // only used when no devices were found + + QMutex m_ready; +private: + VideoDevicePool(); + static VideoDevicePool* s_self; + static __u64 m_clients; // Number of instances +}; + +} +} + +#endif // VIDEODEVICEPOOL_H diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videoinput.cpp b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videoinput.cpp new file mode 100644 index 0000000..f959cf1 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videoinput.cpp @@ -0,0 +1,168 @@ +/* + videoinput.cpp - Video Input Class + + Copyright (c) 2005-2008 by Cláudio da Silveira Pinheiro + + ************************************************************************* + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + ************************************************************************* +*/ + +#include "videoinput.h" + +namespace Phonon { +namespace VideoCapture { + +VideoInput::VideoInput() +{ + kDebug() << "Executing Video Input's constructor!!!"; + m_brightness = 0.5; + m_contrast = 0.5; + m_saturation = 0.5; + m_hue = 0.5; + m_autobrightnesscontrast = false; + m_autocolorcorrection = false; +} + + +VideoInput::~VideoInput() +{ +} + +float VideoInput::getBrightness() +{ +// kDebug() << " called."; + return m_brightness; +} + +float VideoInput::setBrightness(float brightness) +{ +// kDebug() << " called."; + if ( brightness > 1 ) + brightness = 1; + else + if ( brightness < 0 ) + brightness = 0; + m_brightness = brightness; + return getBrightness(); +} + +float VideoInput::getContrast() +{ +// kDebug() << " called."; + return m_contrast; +} + +float VideoInput::setContrast(float contrast) +{ +// kDebug() << " called."; + if ( contrast > 1 ) + contrast = 1; + else + if ( contrast < 0 ) + contrast = 0; + m_contrast = contrast; + return getContrast(); +} + +float VideoInput::getSaturation() +{ +// kDebug() << " called."; + return m_saturation; +} + +float VideoInput::setSaturation(float saturation) +{ +// kDebug() << " called."; + if ( saturation > 1 ) + saturation = 1; + else + if ( saturation < 0 ) + saturation = 0; + m_saturation = saturation; + return getSaturation(); +} + +float VideoInput::getWhiteness() +{ +// kDebug() << " called."; + return m_whiteness; +} + +float VideoInput::setWhiteness(float whiteness) +{ +// kDebug() << " called."; + if ( whiteness > 1 ) + whiteness = 1; + else + if ( whiteness < 0 ) + whiteness = 0; + m_whiteness = whiteness; + return getWhiteness(); +} + +float VideoInput::getHue() +{ +// kDebug() << " called."; + return m_hue; +} + +float VideoInput::setHue(float hue) +{ +// kDebug() << " called."; + if ( hue > 1 ) + hue = 1; + else + if ( hue < 0 ) + hue = 0; + m_hue = hue; + return getHue(); +} + + +bool VideoInput::getAutoBrightnessContrast() +{ +// kDebug() << " called."; + return m_autobrightnesscontrast; +} + +bool VideoInput::setAutoBrightnessContrast(bool brightnesscontrast) +{ +// kDebug() << " called."; + m_autobrightnesscontrast = brightnesscontrast; + return getAutoBrightnessContrast(); +} + +bool VideoInput::getAutoColorCorrection() +{ +// kDebug() << " called."; + return m_autocolorcorrection; +} + +bool VideoInput::setAutoColorCorrection(bool colorcorrection) +{ +// kDebug() << " called."; + m_autocolorcorrection = colorcorrection; + return getAutoColorCorrection(); +} + +bool VideoInput::getImageAsMirror() +{ +// kDebug() << " called."; + return m_imageasmirror; +} + +bool VideoInput::setImageAsMirror(bool imageasmirror) +{ +// kDebug() << " called."; + m_imageasmirror = imageasmirror; + return getImageAsMirror(); +} + +} +} diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videoinput.h b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videoinput.h new file mode 100644 index 0000000..932f66a --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapture/videoinput.h @@ -0,0 +1,81 @@ +/* + videoinput.h - Video Input Class + + Copyright (c) 2005-2006 by Cláudio da Silveira Pinheiro + + ************************************************************************* + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + ************************************************************************* +*/ + +#define ENABLE_AV + +#ifndef VIDEOINPUT_H +#define VIDEOINPUT_H + +#ifdef __linux__ +#include +#undef __STRICT_ANSI__ +#endif // __linux__ +#ifndef __u64 //required by videodev.h +#define __u64 unsigned long long +#endif // __u64*/ + +#include +#include + +namespace Phonon { +namespace VideoCapture { + +/** +@author Kopete Developers +*/ +class VideoInput{ +public: + VideoInput(); + ~VideoInput(); + QString name; + int hastuner; + __u64 m_standards; + float getBrightness(); + float setBrightness(float brightness); + float getContrast(); + float setContrast(float contrast); + float getSaturation(); + float setSaturation(float saturation); + float getWhiteness(); + float setWhiteness(float whiteness); + float getHue(); + float setHue(float Hue); + bool getAutoBrightnessContrast(); + bool setAutoBrightnessContrast(bool brightnesscontrast); + bool getAutoColorCorrection(); + bool setAutoColorCorrection(bool colorcorrection); + bool getImageAsMirror(); + bool setImageAsMirror(bool imageasmirror); + +protected: +// this block must be changed to use a vector of controls instead of fixed ones + float m_brightness; + float m_contrast; + float m_saturation; + float m_whiteness; + float m_hue; + + bool m_autobrightnesscontrast; + bool m_autocolorcorrection; + bool m_imageasmirror; + + +}; + +} +} + + +#endif diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/CMakeLists.txt b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/CMakeLists.txt new file mode 100644 index 0000000..006c388 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/CMakeLists.txt @@ -0,0 +1,17 @@ +include_directories( ${KDE4_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/videocapture/) + +add_definitions( ${KDE4_DEFINITIONS} ) + +set(videocapturetestapp_SRCS videocapturetestappmain.cpp mainwindow.cpp ) + +kde4_add_ui_files(videocapturetestapp_SRCS mainwidget.ui ) + +kde4_add_executable(videocapturetestapp_bin ${videocapturetestapp_SRCS}) + +set_target_properties(videocapturetestapp_bin PROPERTIES OUTPUT_NAME videocapturetestapp) + +target_link_libraries( videocapturetestapp_bin ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBS} videocapture) + +install(TARGETS videocapturetestapp_bin DESTINATION ${BIN_INSTALL_DIR} ) +install(FILES videocapturetestapp.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}) +kde4_install_icons(${ICON_INSTALL_DIR} ) diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi128-app-videocapturetestapp.png b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi128-app-videocapturetestapp.png new file mode 100644 index 0000000..0bb33f4 Binary files /dev/null and b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi128-app-videocapturetestapp.png differ diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi16-app-videocapturetestapp.png b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi16-app-videocapturetestapp.png new file mode 100644 index 0000000..db115cd Binary files /dev/null and b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi16-app-videocapturetestapp.png differ diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi22-app-videocapturetestapp.png b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi22-app-videocapturetestapp.png new file mode 100644 index 0000000..8a0b339 Binary files /dev/null and b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi22-app-videocapturetestapp.png differ diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi32-app-videocapturetestapp.png b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi32-app-videocapturetestapp.png new file mode 100644 index 0000000..f9d3213 Binary files /dev/null and b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi32-app-videocapturetestapp.png differ diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi48-app-videocapturetestapp.png b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi48-app-videocapturetestapp.png new file mode 100644 index 0000000..696bc13 Binary files /dev/null and b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi48-app-videocapturetestapp.png differ diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi64-app-videocapturetestapp.png b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi64-app-videocapturetestapp.png new file mode 100644 index 0000000..c95f65c Binary files /dev/null and b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hi64-app-videocapturetestapp.png differ diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hisc-app-videocapturetestapp.svgz b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hisc-app-videocapturetestapp.svgz new file mode 100644 index 0000000..d315496 Binary files /dev/null and b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/hisc-app-videocapturetestapp.svgz differ diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/mainwidget.ui b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/mainwidget.ui new file mode 100644 index 0000000..2510eb7 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/mainwidget.ui @@ -0,0 +1,528 @@ + + MainWidget + + + + 0 + 0 + 352 + 519 + + + + + 0 + 0 + + + + videocapturetestapp + + + + + + + + Qt::Horizontal + + + + 0 + 20 + + + + + + + + + 0 + 0 + + + + + 320 + 240 + + + + QFrame::Box + + + true + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + + 0 + 20 + + + + + + + + + + + + Take a Photo + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Help + + + + + + + Quit + + + + + + + + + + 0 + 0 + + + + 1 + + + + Device + + + + + + + + + + Device: + + + + + + + Input: + + + + + + + Standard: + + + + + + + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + Select the device to take video input from + + + + + + + + 0 + 0 + + + + Select from multiple inputs provided by some devices + + + + + + + + 0 + 0 + + + + Select the video standard to use + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::MinimumExpanding + + + + 20 + 0 + + + + + + + + + Optio&ns + + + + + + + 0 + 0 + + + + Enable automatic brightness/contrast adjustment + + + Adjust brightness/contrast + + + + + + + + 0 + 0 + + + + Enable automatic color correction + + + Correct colors + + + + + + + + + + + 0 + 0 + + + + Show the video input mirrored + + + Mirror preview + + + + + + + + + + Qt::Vertical + + + QSizePolicy::MinimumExpanding + + + + 20 + 0 + + + + + + + + + Con&trols + + + + + + + + + 0 + 0 + + + + Brightness: + + + + + + + + 0 + 0 + + + + 65535 + + + 256 + + + 4096 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + Contrast: + + + + + + + + 0 + 0 + + + + 65535 + + + 256 + + + 4096 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + Saturation: + + + + + + + + 0 + 0 + + + + 65535 + + + 256 + + + 4096 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + Whiteness: + + + + + + + + 0 + 0 + + + + 65535 + + + 256 + + + 4096 + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + Hue: + + + + + + + + 0 + 0 + + + + 65535 + + + 256 + + + 4096 + + + Qt::Horizontal + + + + + + + + + Qt::Vertical + + + QSizePolicy::MinimumExpanding + + + + 20 + 0 + + + + + + + + + + + + + + KComboBox + QComboBox +
kcombobox.h
+
+ + KPushButton + QPushButton +
kpushbutton.h
+
+
+ + +
diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/mainwindow.cpp b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/mainwindow.cpp new file mode 100644 index 0000000..d8421dd --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/mainwindow.cpp @@ -0,0 +1,290 @@ +/* +mainwindow.cpp - MainWindow class implementation + +Copyright (c) 2005-2008 by Cláudio da Silveira Pinheiro + +This program 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 2 of +the License or (at your option) version 3 or any later version +accepted by the membership of KDE e.V. (or its successor approved +by the membership of KDE e.V.), which shall act as a proxy +defined in Section 14 of version 3 of the license. + +This program 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 this program. If not, see . +*/ + +#include "mainwindow.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MainWindow::MainWindow( QWidget *parent ) +: QWidget( parent ) +{ + main_widget = new Ui_MainWidget(); + main_widget->setupUi( this ); + + main_widget->video_image_label->setScaledContents( false ); + main_widget->video_image_label->setPixmap( KIcon( "videocapturetestapp" ).pixmap( 128, 128 ) ); + + connect( main_widget->device_combo_box, SIGNAL( activated( int ) ), this, SLOT( deviceChanged( int ) ) ); + connect( main_widget->input_combo_box, SIGNAL( activated( int ) ), this, SLOT( inputChanged( int ) ) ); + + connect( main_widget->standard_combo_box, SIGNAL( activated( int ) ), this, SLOT( standardChanged( int ) ) ); + connect( main_widget->brightness_slider, SIGNAL( valueChanged( int ) ), this, SLOT( brightnessChanged( int ) ) ); + connect( main_widget->contrast_slider, SIGNAL( valueChanged( int ) ), this, SLOT( contrastChanged( int ) ) ); + connect( main_widget->saturation_slider, SIGNAL( valueChanged( int ) ), this, SLOT( saturationChanged( int ) ) ); + connect( main_widget->whiteness_slider, SIGNAL( valueChanged( int ) ), this, SLOT( whitenessChanged( int ) ) ); + connect( main_widget->hue_slider, SIGNAL( valueChanged( int ) ), this, SLOT( hueChanged( int ) ) ); + + connect( main_widget->adjust_brightness_combo_box, SIGNAL( toggled( bool ) ), this, SLOT( adjustBrightnessContrastChanged( bool ) ) ); + connect( main_widget->correct_colors_combo_box, SIGNAL( toggled( bool ) ), this, SLOT( colorCorrectionChanged( bool ) ) ); + connect( main_widget->mirror_preview_check_box, SIGNAL( toggled( bool ) ), this, SLOT( mirrorPreviewChanged( bool ) ) ); + + connect( main_widget->take_photo_button, SIGNAL( clicked( bool ) ), this, SLOT( takePhoto( bool ) ) ); + connect(main_widget->quit_button, SIGNAL( clicked() ), KApplication::kApplication(), SLOT( quit() ) ); + + vdpool = Phonon::VideoCapture::VideoDevicePool::self(); + vdpool->open(); + vdpool->setSize( 320, 240 ); + + vdpool->fillDeviceKComboBox( main_widget->device_combo_box ); + vdpool->fillInputKComboBox( main_widget->input_combo_box ); + vdpool->fillStandardKComboBox( main_widget->standard_combo_box ); + + vdpool->setBrightness( 0 ); + vdpool->setHue( 0 ); + + setVideoInputParameters(); + + vdpool->startCapturing(); + + connect( vdpool, SIGNAL( deviceRegistered( const QString & ) ), SLOT( deviceRegistered( const QString & ) ) ); + connect( vdpool, SIGNAL( deviceUnregistered( const QString & ) ), SLOT( deviceUnregistered( const QString & ) ) ); + + connect( &update_timer, SIGNAL( timeout() ), this, SLOT( updateImage() ) ); + + if( vdpool->hasDevices() ) { + update_timer.start( 80 ); + main_widget->video_image_label->setScaledContents( true ); + } + + KHelpMenu *help_menu = new KHelpMenu( this, KGlobal::mainComponent().aboutData(), false ); + main_widget->help_button->setMenu( help_menu->menu() ); + main_widget->help_button->setIcon( KIcon( "help-contents" ) ); + main_widget->quit_button->setIcon( KIcon( "application-exit" ) ); + main_widget->take_photo_button->setIcon( KIcon( "videocapturetestapp" ) ); + +} + + +MainWindow::~MainWindow() +{ + vdpool->close(); +} + + +void MainWindow::setVideoInputParameters() +{ + if( vdpool->size() ) { + main_widget->brightness_slider->setValue( ( int )( vdpool->getBrightness() * main_widget->brightness_slider->maximum() ) ); + main_widget->contrast_slider->setValue( ( int )( vdpool->getContrast() * main_widget->contrast_slider->maximum() ) ); + main_widget->saturation_slider->setValue( ( int )( vdpool->getSaturation() * main_widget->saturation_slider->maximum() ) ); + main_widget->whiteness_slider->setValue( ( int )( vdpool->getWhiteness() * main_widget->whiteness_slider->maximum() ) ); + main_widget->hue_slider->setValue( ( int )( vdpool->getHue() * main_widget->hue_slider->maximum() ) ); + main_widget->adjust_brightness_combo_box->setChecked( vdpool->getAutoBrightnessContrast() ); + main_widget->correct_colors_combo_box->setChecked( vdpool->getAutoColorCorrection() ); + main_widget->mirror_preview_check_box->setChecked( vdpool->getImageAsMirror() ); + } +} + +void MainWindow::deviceChanged( int ) +{ + int new_device = main_widget->device_combo_box->currentIndex(); + + if( ( new_device < vdpool->m_videodevice.size() ) && ( new_device != vdpool->currentDevice() ) ) { + vdpool->open( new_device ); + vdpool->setSize( 320, 240 ); + vdpool->fillInputKComboBox( main_widget->input_combo_box ); + vdpool->startCapturing(); + setVideoInputParameters(); + } +} + +void MainWindow::inputChanged( int ) +{ + int new_input = main_widget->input_combo_box->currentIndex(); + + if( ( new_input < vdpool->inputs() ) && ( new_input != vdpool->currentInput() ) ) { + vdpool->selectInput( main_widget->input_combo_box->currentIndex() ); + vdpool->fillStandardKComboBox( main_widget->standard_combo_box ); + setVideoInputParameters(); + } +} + +void MainWindow::standardChanged( int ) +{ +} + +void MainWindow::brightnessChanged( int ) +{ + vdpool->setBrightness( main_widget->brightness_slider->value() / (float)main_widget->brightness_slider->maximum() ); +} + +void MainWindow::contrastChanged( int ) +{ + vdpool->setContrast( main_widget->contrast_slider->value() / (float)main_widget->contrast_slider->maximum() ); +} + +void MainWindow::saturationChanged( int ) +{ + vdpool->setSaturation( main_widget->saturation_slider->value() / (float)main_widget->saturation_slider->maximum() ); +} + +void MainWindow::whitenessChanged( int ) +{ + vdpool->setWhiteness( main_widget->whiteness_slider->value() / (float)main_widget->whiteness_slider->maximum() ); +} + +void MainWindow::hueChanged( int ) +{ + vdpool->setHue( main_widget->hue_slider->value() / (float)main_widget->hue_slider->maximum() ); +} + +void MainWindow::adjustBrightnessContrastChanged( bool ) +{ + vdpool->setAutoBrightnessContrast( main_widget->adjust_brightness_combo_box->isChecked() ); +} + +void MainWindow::colorCorrectionChanged( bool ) +{ + vdpool->setAutoColorCorrection( main_widget->correct_colors_combo_box->isChecked() ); +} + +void MainWindow::mirrorPreviewChanged( bool ) +{ + vdpool->setImageAsMirror( main_widget->mirror_preview_check_box->isChecked() ); +} + +void MainWindow::updateImage() +{ + vdpool->getFrame(); + vdpool->getImage( &captured_frame ); + main_widget->video_image_label->setPixmap( QPixmap::fromImage( captured_frame.mirrored( vdpool->getImageAsMirror(), false ) ) ); +} + +void MainWindow::deviceRegistered( const QString& ) +{ + vdpool->fillDeviceKComboBox( main_widget->device_combo_box ); + vdpool->fillInputKComboBox( main_widget->input_combo_box ); + vdpool->fillStandardKComboBox( main_widget->standard_combo_box ); +} + + +void MainWindow::deviceUnregistered( const QString& ) +{ + vdpool->fillDeviceKComboBox( main_widget->device_combo_box ); + vdpool->fillInputKComboBox( main_widget->input_combo_box ); + vdpool->fillStandardKComboBox( main_widget->standard_combo_box ); +} + +void MainWindow::takePhoto( bool ) +{ + QPixmap captured_image = QPixmap::fromImage( captured_frame ); + + KUrl image_url( QDir::currentPath() + '/' + "videocapturetestapp_image.png" ); + QStringList mime_types = KImageIO::mimeTypes( KImageIO::Writing ); + KFileDialog file_dilaog( image_url, mime_types.join( " " ), this ); + + file_dilaog.setOperationMode( KFileDialog::Saving ); + file_dilaog.setCaption( i18n( "Save As" ) ); + + KImageFilePreview *image_preview = new KImageFilePreview( &file_dilaog ); + file_dilaog.setPreviewWidget( image_preview ); + + if ( !file_dilaog.exec() ) { + return; + } + + image_url = file_dilaog.selectedUrl(); + if ( !image_url.isValid() ) { + return; + } + + saveImage( captured_image, image_url ); + +} + + +void MainWindow::saveImage( const QPixmap &image, const KUrl &image_url) +{ + if( KIO::NetAccess::exists( image_url, KIO::NetAccess::DestinationSide, this ) ) { + const QString title = i18n( "File Exists" ); + const QString text = i18n( "Do you really want to overwrite %1?", image_url.prettyUrl() ); + if( KMessageBox::Continue != KMessageBox::warningContinueCancel( this, text, title, KGuiItem( i18n( "Overwrite" ) ) ) ) { + return; + } + } + + QByteArray type = "PNG"; + QString mime_type = KMimeType::findByUrl( image_url.url(), 0, image_url.isLocalFile(), true )->name(); + QStringList types = KImageIO::typeForMime( mime_type ); + if( !types.isEmpty() ) { + type = types.first().toLatin1(); + } + + bool ok = false; + + if( image_url.isLocalFile() ) { + bool supported = false; + QByteArray format; + foreach( format, QImageWriter::supportedImageFormats() ) { + if( format.toLower() == type.toLower() ) { + supported = true; + } + } + + if( supported && image.save( image_url.path(), type ) ) { + ok = true; + } + } + else { + KTemporaryFile temp_file; + if( temp_file.open() ) { + if( image.save( &temp_file, type ) ) { + ok = KIO::NetAccess::upload( temp_file.fileName(), image_url, this ); + } + } + } + + QApplication::restoreOverrideCursor(); + + if( !ok ) { + QString caption = i18n( "Unable to Save Image" ); + QString text = i18n( "videocapturetestapp was unable to save the image to\n%1.", image_url.prettyUrl() ); + KMessageBox::error( this, text, caption ); + } +} diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/mainwindow.h b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/mainwindow.h new file mode 100644 index 0000000..47bd584 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/mainwindow.h @@ -0,0 +1,86 @@ +/* +mainwindow.h - MainWindow class header + +Copyright (c) 2005-2008 by Cláudio da Silveira Pinheiro + +This program 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 2 of +the License or (at your option) version 3 or any later version +accepted by the membership of KDE e.V. (or its successor approved +by the membership of KDE e.V.), which shall act as a proxy +defined in Section 14 of version 3 of the license. + +This program 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 this program. If not, see . +*/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include + +class QPixmap; +class KUrl; + +#include "videodevicepool.h" +#include "ui_mainwidget.h" + +class MainWindow : public QWidget +{ + +Q_OBJECT + +public: + + MainWindow( QWidget *parent = 0 ); + + ~MainWindow(); + + +private slots: + + void deviceChanged( int ); + void inputChanged( int ); + void standardChanged( int ); + + void brightnessChanged( int ); + void contrastChanged( int ); + void saturationChanged( int ); + void whitenessChanged( int ); + void hueChanged( int ); + + void adjustBrightnessContrastChanged( bool ); + void colorCorrectionChanged( bool ); + void mirrorPreviewChanged( bool ); + + void updateImage(); + + void deviceRegistered( const QString & ); + void deviceUnregistered( const QString & ); + + void takePhoto( bool ); + +private: + + Ui_MainWidget *main_widget; + + Phonon::VideoCapture::VideoDevicePool *vdpool; + + QImage captured_frame; + + QTimer update_timer; + + void saveImage( const QPixmap&, const KUrl& ); + + void setVideoInputParameters(); + +}; + +#endif diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/videocapturetestapp.desktop b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/videocapturetestapp.desktop new file mode 100644 index 0000000..14afae1 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/videocapturetestapp.desktop @@ -0,0 +1,96 @@ +[Desktop Entry] +Categories=Qt;KDE;Graphics; +Comment= +Exec=videocapturetestapp +GenericName=Video Capture Test Application +GenericName[bg]=Пробно приложение за прихващане на видео +GenericName[ca]=Aplicació de proves de captura de vídeo +GenericName[cs]=Testovací aplikace pro nahrávání videa +GenericName[da]=Testprogram til videooptagelse +GenericName[de]=Videoaufnahme-Testanwendung +GenericName[el]=Δοκιμαστική εφαρμογή σύλληψης βίντεο +GenericName[en_GB]=Video Capture Test Application +GenericName[es]=Aplicación para probar la de captura de vídeo +GenericName[et]=Videohõive testrakendus +GenericName[eu]=Bideoa jasotzeko froga egiteko aplikazioa +GenericName[fr]=Application de test pour la capture vidéo +GenericName[ga]=Feidhmchlár Tástála Físghabhála +GenericName[gl]=Programa de probas para a captura de vídeo +GenericName[hsb]=Testowa aplikacija za widejo-capture +GenericName[hu]=Teszt videofelvétel +GenericName[is]=Prófunarforrit fyrir vídeóupptökur +GenericName[it]=Applicazione di prova per l'acquisizione video +GenericName[ja]=映像キャプチャをテストするアプリケーション +GenericName[ko]=비디오 캡처 테스트 프로그램 +GenericName[ku]=Sepana Ceribandina Girtina Vîdeoyê +GenericName[lt]=Video įrašymo bandomoji programa +GenericName[lv]=Video tveršanas testa programma +GenericName[nds]=Video-Opnehm-Testprogramm +GenericName[nl]=Testprogramma voor video-opname +GenericName[nn]=Testprogram for videoopptak +GenericName[pa]=ਵੀਡਿਓ ਕੈਪਚਰ ਟੈਸਟ ਐਪਲੀਕੇਸ਼ਨ +GenericName[pl]=Program testowy do nagrywania wideo +GenericName[pt]=Aplicação de Testes de Captura de Vídeo +GenericName[pt_BR]=Aplicativo de teste de captura de vídeo +GenericName[se]=Videobádden geahččalanprográmma +GenericName[sk]=Video testovacia aplikácia +GenericName[sl]=Program za preizkus zajema videa +GenericName[sr]=Програм за пробу хватања видеа +GenericName[sr@latin]=Program za probu hvatanja videa +GenericName[sv]=Testprogram för videoinspelning +GenericName[tr]=Video Yakalama Test Uygulaması +GenericName[uk]=Тестова програма для захоплення відео +GenericName[x-test]=xxVideo Capture Test Applicationxx +GenericName[zh_CN]=视频捕获测试程序 +GenericName[zh_TW]=影像擷取測試應用程式 +Icon=videocapturetestapp +MimeType= +Name=videocapturetestapp +Name[bg]=Пробно прихващане на видео +Name[ca]=videocapturetestapp +Name[cs]=videocapturetestapp +Name[da]=videooptager-testprogram +Name[de]=videocapturetestapp +Name[el]=videocapturetestapp +Name[en_GB]=videocapturetestapp +Name[es]=videocapturetestapp +Name[et]=videocapturetestapp +Name[eu]=videocapturetestapp +Name[fr]=videocapturetestapp +Name[ga]=videocapturetestapp +Name[gl]=videocapturetestapp +Name[hsb]=videocapturetestapp +Name[hu]=videocapturetestapp +Name[is]=videocapturetestapp +Name[it]=videocapturetestapp +Name[ja]=videocapturetestapp +Name[ko]=videocapturetestapp +Name[ku]=videocapturetestapp +Name[lt]=videocapturetestapp +Name[lv]=videocapturetestapp +Name[nds]=videocapturetestapp +Name[nl]=videocapturetestapp +Name[nn]=videocapturetestapp +Name[pa]=videocapturetestapp +Name[pl]=videocapturetestapp +Name[pt]=videocapturetestapp +Name[pt_BR]=videocapturetestapp +Name[se]=videocapturetestapp +Name[sk]=Video testovacia aplikácia +Name[sl]=videocapturetestapp +Name[sr]=videocapturetestapp +Name[sr@latin]=videocapturetestapp +Name[sv]=Videoinspelningstest +Name[tr]=videocapturetestapp +Name[uk]=videocapturetestapp +Name[x-test]=xxvideocapturetestappxx +Name[zh_CN]=videocapturetestapp +Name[zh_TW]=videocapturetestapp +Path= +StartupNotify=true +Terminal=false +TerminalOptions= +Type=Application +X-DBUS-StartupType= +X-KDE-SubstituteUID=false +X-KDE-Username= diff --git a/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/videocapturetestappmain.cpp b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/videocapturetestappmain.cpp new file mode 100644 index 0000000..97c08bc --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videocapturedevice/videocapturetestapp/videocapturetestappmain.cpp @@ -0,0 +1,47 @@ +/* +videocapturetestapp.cpp - main() function + +Copyright (c) 2005-2008 by Cláudio da Silveira Pinheiro + +This program 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 2 of +the License or (at your option) version 3 or any later version +accepted by the membership of KDE e.V. (or its successor approved +by the membership of KDE e.V.), which shall act as a proxy +defined in Section 14 of version 3 of the license. + +This program 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 this program. If not, see . +*/ + +#include +#include +#include + +#include "mainwindow.h" + +#define VIDEOCAPTURETESTAPP_VERSION "0.1" + +int main( int argc, char *argv[] ) +{ + KAboutData about_data( "videocapturetestapp", 0, + ki18n( "videocapturetestapp" ), VIDEOCAPTURETESTAPP_VERSION, + ki18n( "Video Capture Test Application." ), + KAboutData::License_GPL, + ki18n( "Copyright 2005-2008 Cláudio da Silveira Pinheiro" ), ki18n( "taupter@gmail.com" ) ); + + KCmdLineArgs::init( argc, argv, &about_data ); + + KApplication app; + + MainWindow* window = new MainWindow(); + window->show(); + + return app.exec(); +} diff --git a/src/3rdparty/phonon/phonon/experimental/videodataoutput.cpp b/src/3rdparty/phonon/phonon/experimental/videodataoutput.cpp new file mode 100644 index 0000000..0acbe20 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videodataoutput.cpp @@ -0,0 +1,115 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2007 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ +#include "videodataoutput.h" +#include "videodataoutput_p.h" +#include "factory_p.h" +#include + +#define PHONON_CLASSNAME VideoDataOutput + +namespace Phonon +{ +namespace Experimental +{ + +VideoDataOutput::VideoDataOutput(QObject *parent) + : QObject(parent) + , AbstractVideoOutput(*new VideoDataOutputPrivate) +{ + K_D(VideoDataOutput); + d->createBackendObject(); +} + +void VideoDataOutputPrivate::createBackendObject() +{ + if (m_backendObject) + return; + Q_Q(VideoDataOutput); + m_backendObject = Factory::createVideoDataOutput(q); + if (m_backendObject) { + setupBackendObject(); + } +} + + +PHONON_GETTER(int, latency, d->latency) + +bool VideoDataOutputPrivate::aboutToDeleteBackendObject() +{ + Q_ASSERT(m_backendObject); + + return AbstractVideoOutputPrivate::aboutToDeleteBackendObject(); +} + +void VideoDataOutputPrivate::setupBackendObject() +{ + Q_Q(VideoDataOutput); + Q_ASSERT(m_backendObject); + //AbstractVideoOutputPrivate::setupBackendObject(); + + //QObject::connect(m_backendObject, SIGNAL(frameReady(const Phonon::Experimental::VideoFrame &)), + // q, SIGNAL(frameReady(const Phonon::Experimental::VideoFrame &))); + + QObject::connect(m_backendObject, SIGNAL(displayFrame(qint64, qint64)), + q, SIGNAL(displayFrame(qint64, qint64))); + QObject::connect(m_backendObject, SIGNAL(endOfMedia()), q, SIGNAL(endOfMedia())); +} + +bool VideoDataOutput::isRunning() const +{ + //K_D(const VideoDataOutput); + //return d->m_backendObject->isRunning(); + return false; +} + +VideoFrame VideoDataOutput::frameForTime(qint64 timestamp) +{ + Q_UNUSED(timestamp); + + //return d->m_backendObject->frameForTime(timestamp); + return VideoFrame(); +} + +void VideoDataOutput::setRunning(bool running) +{ + Q_UNUSED(running); + + //return d->m_backendObject->setRunning(running); +} + +void VideoDataOutput::start() +{ + //return d->m_backendObject->setRunning(true); +} + +void VideoDataOutput::stop() +{ + //return d->m_backendObject->setRunning(false); +} + +} // namespace Experimental +} // namespace Phonon + +#include "videodataoutput.moc" + +#undef PHONON_CLASSNAME +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/experimental/videodataoutput.h b/src/3rdparty/phonon/phonon/experimental/videodataoutput.h new file mode 100644 index 0000000..8f49761 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videodataoutput.h @@ -0,0 +1,114 @@ +/* This file is part of the KDE project + Copyright (C) 2005-2007 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_VIDEODATAOUTPUT_H +#define PHONON_VIDEODATAOUTPUT_H + +#include "export.h" +#include "../abstractvideooutput.h" +#include "../phonondefs.h" +#include + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template class QVector; +template class QMap; +#endif +class QSize; + +namespace Phonon +{ +namespace Experimental +{ + class VideoDataOutputPrivate; + struct VideoFrame; + + /** + * \short This class gives you nothing. ;-) + * \deprecated + * + * \author Matthias Kretz + */ + class PHONONEXPERIMENTAL_EXPORT VideoDataOutput : public QObject, public AbstractVideoOutput + { + Q_OBJECT + K_DECLARE_PRIVATE(VideoDataOutput) + /** + * This property retrieves the nominal latency of the + * backend. + */ + Q_PROPERTY(int latency READ latency) + + /** + * This property indicates the state of the data output. + */ + Q_PROPERTY(bool running READ isRunning WRITE setRunning) + + PHONON_HEIR(VideoDataOutput) + public: + int latency() const; + + bool isRunning() const; + + Phonon::Experimental::VideoFrame frameForTime(qint64 timestamp); + + public Q_SLOTS: + void setRunning(bool running); + void start(); + void stop(); + + Q_SIGNALS: + /* FIXME: disabled this piece of documentation - add another * to enable + * Fixme: I don't think this makes sense, but I've been wrong before. + * + * Emitted whenever another dataSize number of samples are ready and + * format is set to IntegerFormat. + * + * If format is set to FloatFormat the signal is not emitted at all. + * + * \param frame An object of class VideoFrame holding the video data + * and some additional information. + * void frameReady(const Phonon::Experimental::VideoFrame &frame); + */ + + /** + * The signal is emitted whenever a frame should be displayed. + * + * The relevant frames should be fetched and displayed using frameForTime + * method. + * + * \param nowStamp the current time + * \param outStamp the time the frame should be displayed with + */ + void displayFrame(qint64 nowStamp, qint64 outStamp); + + /** + * This signal is emitted after the last frameReady signal of a + * media is emitted. + */ + void endOfMedia(); + }; + +} // namespace Experimental +} //namespace Phonon + +// vim: sw=4 ts=4 tw=80 +#endif // PHONON_VIDEODATAOUTPUT_H diff --git a/src/3rdparty/phonon/phonon/experimental/videodataoutput2.cpp b/src/3rdparty/phonon/phonon/experimental/videodataoutput2.cpp new file mode 100644 index 0000000..f201951 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videodataoutput2.cpp @@ -0,0 +1,81 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#include "videodataoutput2.h" +#include "videodataoutput2_p.h" +#include "../factory_p.h" +#include +#include + +#define PHONON_CLASSNAME VideoDataOutput2 + +namespace Phonon +{ +namespace Experimental +{ + +VideoDataOutput2::VideoDataOutput2(QObject *parent) + : QObject(parent), + AbstractVideoDataOutput(*new VideoDataOutput2Private) +{ +} + +void VideoDataOutput2::frameReady(const VideoFrame2 &frame) +{ + if (QThread::currentThread() == thread()) { + emit frameReadySignal(frame); + } else { + QMetaObject::invokeMethod(this, "frameReadySignal", Qt::BlockingQueuedConnection, Q_ARG(VideoFrame2, frame)); + } +} + +void VideoDataOutput2::endOfMedia() +{ + if (QThread::currentThread() == thread()) { + emit endOfMediaSignal(); + } else { + QMetaObject::invokeMethod(this, "endOfMediaSignal", Qt::BlockingQueuedConnection); + } +} + +void VideoDataOutput2Private::createBackendObject() +{ + AbstractVideoDataOutputPrivate::createBackendObject(); +} + +bool VideoDataOutput2Private::aboutToDeleteBackendObject() +{ + return AbstractVideoDataOutputPrivate::aboutToDeleteBackendObject(); +} + +void VideoDataOutput2Private::setupBackendObject() +{ + AbstractVideoDataOutputPrivate::setupBackendObject(); +} + +} // namespace Experimental +} // namespace Phonon + +#include "videodataoutput2.moc" + +#undef PHONON_CLASSNAME +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/experimental/videodataoutput2.h b/src/3rdparty/phonon/phonon/experimental/videodataoutput2.h new file mode 100644 index 0000000..13b7577 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videodataoutput2.h @@ -0,0 +1,80 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_VIDEODATAOUTPUT2_H +#define PHONON_VIDEODATAOUTPUT2_H + +#include "export.h" +#include +#include "abstractvideodataoutput.h" + +namespace Phonon +{ +namespace Experimental +{ + +class VideoDataOutput2Private; + +/** + * \short This class gives you the video data. + * + * This class implements a special AbstractVideoOutput that gives your + * application the video data. + * + * You can also use the video data for further processing (e.g. encoding and + * saving to a file). + * + * \author Matthias Kretz + */ +class PHONONEXPERIMENTAL_EXPORT VideoDataOutput2 : public QObject, public AbstractVideoDataOutput +{ + Q_OBJECT + K_DECLARE_PRIVATE(VideoDataOutput2) + PHONON_HEIR(VideoDataOutput2) + + protected: + virtual void frameReady(const VideoFrame2 &); + + virtual void endOfMedia(); + + Q_SIGNALS: + /** + * The signal is emitted whenever a frame should be displayed. + * nowStamp is the current time, outStamp tells the users + * what time the frame should be displayed with. + * + * The relevant frames should be fetched and displayed using frameForTime + * method. + */ + void frameReadySignal(const VideoFrame2 &); + + /** + * This signal is emitted after the last frameReady signal of a + * media is emitted. + */ + void endOfMediaSignal(); +}; + +} // namespace Experimental +} //namespace Phonon + +#endif // PHONON_VIDEODATAOUTPUT2_H diff --git a/src/3rdparty/phonon/phonon/experimental/videodataoutput2_p.h b/src/3rdparty/phonon/phonon/experimental/videodataoutput2_p.h new file mode 100644 index 0000000..fbf1de2 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videodataoutput2_p.h @@ -0,0 +1,45 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_VIDEODATAOUTPUT2_P_H +#define PHONON_VIDEODATAOUTPUT2_P_H + +#include "videodataoutput2.h" +#include "abstractvideodataoutput_p.h" + +namespace Phonon +{ +namespace Experimental +{ + +class VideoDataOutput2Private : public AbstractVideoDataOutputPrivate +{ + Q_DECLARE_PUBLIC(VideoDataOutput2) + PHONON_PRIVATECLASS + public: + virtual QObject *qObject() { return q_func(); } +}; + +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_VIDEODATAOUTPUT2_P_H diff --git a/src/3rdparty/phonon/phonon/experimental/videodataoutput_p.h b/src/3rdparty/phonon/phonon/experimental/videodataoutput_p.h new file mode 100644 index 0000000..bb883df --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videodataoutput_p.h @@ -0,0 +1,54 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_VIDEODATAOUTPUT_P_H +#define PHONON_VIDEODATAOUTPUT_P_H + +#include "videodataoutput.h" +#include "../abstractvideooutput_p.h" +#include "videoframe.h" +#include + +namespace Phonon +{ +namespace Experimental +{ +class VideoDataOutputPrivate : public AbstractVideoOutputPrivate +{ + Q_DECLARE_PUBLIC(VideoDataOutput) + PHONON_PRIVATECLASS + public: + virtual QObject *qObject() { return q_func(); } + protected: + VideoDataOutputPrivate() + : latency(0) + { + } + + int latency; +}; + +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_VIDEODATAOUTPUT_P_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/experimental/videodataoutputinterface.h b/src/3rdparty/phonon/phonon/experimental/videodataoutputinterface.h new file mode 100644 index 0000000..2411212 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videodataoutputinterface.h @@ -0,0 +1,47 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_X_VIDEODATAOUTPUTINTERFACE_H +#define PHONON_X_VIDEODATAOUTPUTINTERFACE_H + +namespace Phonon +{ +namespace Experimental +{ + +class AbstractVideoDataOutput; + +class VideoDataOutputInterface +{ + public: + virtual ~VideoDataOutputInterface() {} + + virtual AbstractVideoDataOutput *frontendObject() const = 0; + virtual void setFrontendObject(AbstractVideoDataOutput *) = 0; +}; + +} // namespace Experimental +} // namespace Phonon + +Q_DECLARE_INTERFACE(Phonon::Experimental::VideoDataOutputInterface, "0VideoDataOutputInterface.phonon.kde.org") + +#endif // PHONON_X_VIDEODATAOUTPUTINTERFACE_H diff --git a/src/3rdparty/phonon/phonon/experimental/videoframe.h b/src/3rdparty/phonon/phonon/experimental/videoframe.h new file mode 100644 index 0000000..0a4eee8 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videoframe.h @@ -0,0 +1,73 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_EXPERIMENTAL_VIDEOFRAME_H +#define PHONON_EXPERIMENTAL_VIDEOFRAME_H + +#include "export.h" +#include "videodataoutput.h" +#include + +namespace Phonon +{ +namespace Experimental +{ + /** + * \brief A single video frame. + * + * This simple class contains the data of a frame and metadata describing + * how to interpret the data. + * + * \author Matthias Kretz + */ + struct PHONONEXPERIMENTAL_EXPORT VideoFrame + { + enum Format { + Format_YUV422, + Format_YUV420, + Format_RGBA8 + //Format_RGBA8_Premultiplied, + //Format_RGBA16F, + //Format_RGBA32F, + //Colorspace_XVYCC + }; + //Qt::HANDLE handle() const; + + QByteArray data; + /** + * The width of the video frame in pixels. + */ + int width; + /** + * The height of the video frame in pixels. + */ + int height; + /** + * Colorspace of the frame + */ + Format colorspace; + }; +} // namespace Experimental +} // namespace Phonon + +// vim: sw=4 ts=4 tw=80 +#endif // PHONON_EXPERIMENTAL_VIDEOFRAME_H diff --git a/src/3rdparty/phonon/phonon/experimental/videoframe2.h b/src/3rdparty/phonon/phonon/experimental/videoframe2.h new file mode 100644 index 0000000..beb5474 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videoframe2.h @@ -0,0 +1,158 @@ +/* This file is part of the KDE project + Copyright (C) 2006,2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_EXPERIMENTAL_VIDEOFRAME2_H +#define PHONON_EXPERIMENTAL_VIDEOFRAME2_H + +#include "export.h" +#include "videodataoutput.h" +#include +#include + +namespace Phonon +{ +namespace Experimental +{ + /** + * \brief A single video frame. + * + * This simple class contains the data of a frame and metadata describing + * how to interpret the data. + * + * \author Matthias Kretz + */ + struct PHONONEXPERIMENTAL_EXPORT VideoFrame2 + { + /** + * Video frames come in a variety of formats. Depending on the format + * you have to process it differently to convert it for displaying or + * encoding. + */ + enum Format { + /** + * The frame is invalid. + */ + Format_Invalid = QImage::Format_Invalid, + /** + * The frame is stored in data0 using a 24-bit RGB format (8-8-8). + */ + Format_RGB888 = QImage::Format_RGB888, + /** + * The frame is stored in data0, data1 and data2 using data0 for the + * Y data, data1 for the Cb data and data2 for the Cr data. + * + * data1 and data2 contain one byte per for adjacent pixels whereas data0 + * has one byte per pixel. + */ + Format_YCbCr420 = 0x10000, + Format_YV12 = Format_YCbCr420, + /** + * The frame is stored in data0 using a 32-bit Y0-Cb-Y1-Cr format (8-8-8-8). + */ + Format_YCbCr422 = 0x10001, + Format_YUY2 = Format_YCbCr422 + }; + + /** + * The width of the video frame in number of pixels. + */ + int width; + + /** + * The height of the video frame in number of pixels. + */ + int height; + + /** + * The aspect ratio the frame should be displayed with. + * + * Common values are 4/3, 16/9. + */ + double aspectRatio; + + /** + * Convenience function to calculate the aspect corrected width from the + * aspectRatio and height values. + * + * It is recommended to display video frames with aspectCorrectedWidth x height + */ + inline int aspectCorrectedWidth() const { return qRound(aspectRatio * height); } + + /** + * Convenience function to calculate the aspect corrected height from the + * aspectRatio and width values. + * + * It is recommended to display video frames with aspectCorrectedWidth x height + */ + inline int aspectCorrectedHeight() const { return qRound(width / aspectRatio); } + + /** + * Format of the frame. + * + * \see Format + */ + Format format; + + /** + * RGB8, YUY2 or Y-plane + * + * If format is Format_RGB888 then the data contains each pixel as three + * consecutive bytes for red, green and blue. + * + * If format is Format_YUY2 the data contains every two pixels as four + * consecutive bytes for Y0, Cb, Y1, Cr + * + * If format is Format_YV12 the data contains one byte per pixel with + * the Y value. + */ + QByteArray data0; + + /** + * YV12 U-plane + * + * If format is Format_YV12 the data contains one byte per four adjacent + * pixels with the Cb value. + */ + QByteArray data1; + + /** + * YV12 V-plane + * + * If format is Format_YV12 the data contains one byte per four adjacent + * pixels with the Cr value. + */ + QByteArray data2; + + inline QImage qImage() const + { + if (format == Format_RGB888) { + return QImage(reinterpret_cast(data0.constData()), + width, height, QImage::Format_RGB888); + } + return QImage(); + } + }; +} // namespace Experimental +} // namespace Phonon + +// vim: sw=4 ts=4 tw=80 +#endif // PHONON_EXPERIMENTAL_VIDEOFRAME2_H diff --git a/src/3rdparty/phonon/phonon/experimental/videowidget.cpp b/src/3rdparty/phonon/phonon/experimental/videowidget.cpp new file mode 100644 index 0000000..0e17cf2 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videowidget.cpp @@ -0,0 +1,48 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#include "videowidget.h" +#include "snapshotinterface.h" +#include "videowidget_p.h" + +namespace Phonon +{ +namespace Experimental +{ + +VideoWidget::VideoWidget(QWidget *w) + : Phonon::VideoWidget(w) +{ +} + +QImage VideoWidget::snapshot() const +{ + K_D(const Phonon::VideoWidget); + SnapshotInterface *iface = qobject_cast(d->m_backendObject); + if (iface) { + return iface->snapshot(); + } + return QImage(); +} + +} // namespace Experimental +} // namespace Phonon diff --git a/src/3rdparty/phonon/phonon/experimental/videowidget.h b/src/3rdparty/phonon/phonon/experimental/videowidget.h new file mode 100644 index 0000000..bbc7d3e --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videowidget.h @@ -0,0 +1,46 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_EXPERIMENTAL_VIDEOWIDGET_H +#define PHONON_EXPERIMENTAL_VIDEOWIDGET_H + +#include "../videowidget.h" +namespace Phonon +{ +namespace Experimental +{ + +class VideoWidgetPrivate; +class VideoWidget : public Phonon::VideoWidget +{ + K_DECLARE_PRIVATE(VideoWidget) + Q_OBJECT + public: + VideoWidget(QWidget *parent = 0); + + QImage snapshot() const; +}; + +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_EXPERIMENTAL_VIDEOWIDGET_H diff --git a/src/3rdparty/phonon/phonon/experimental/videowidget_p.h b/src/3rdparty/phonon/phonon/experimental/videowidget_p.h new file mode 100644 index 0000000..6038e74 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/videowidget_p.h @@ -0,0 +1,46 @@ +/* This file is part of the KDE project + Copyright (C) 2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ +#ifndef PHONON_EXPERIMENTAL_VIDEOWIDGET_P_H +#define PHONON_EXPERIMENTAL_VIDEOWIDGET_P_H + +#include "videowidget.h" +#include "../videowidget_p.h" + +namespace Phonon +{ +namespace Experimental +{ + +class VideoWidgetPrivate : public Phonon::VideoWidgetPrivate +{ + Q_DECLARE_PUBLIC(VideoWidget) + protected: + VideoWidgetPrivate(VideoWidget *parent) + : Phonon::VideoWidgetPrivate(parent) + { + } +}; + +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_EXPERIMENTAL_VIDEOWIDGET_P_H diff --git a/src/3rdparty/phonon/phonon/experimental/visualization.cpp b/src/3rdparty/phonon/phonon/experimental/visualization.cpp new file mode 100644 index 0000000..0dfb184 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/visualization.cpp @@ -0,0 +1,130 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#include "visualization.h" +#include "visualization_p.h" +#include "../objectdescription.h" +#include "../path.h" +#include "factory_p.h" + +#define PHONON_CLASSNAME Visualization + +namespace Phonon +{ +namespace Experimental +{ +PHONON_OBJECT_IMPL + +Visualization::~Visualization() +{ +} + +VisualizationDescription Visualization::visualization() const +{ + K_D(const Visualization); + if (!d->m_backendObject) { + return d->description; + } + int index; + BACKEND_GET(int, index, "visualization"); + return VisualizationDescription::fromIndex(index); +} + +void Visualization::setVisualization(const VisualizationDescription &newVisualization) +{ + K_D(Visualization); + d->description = newVisualization; + if (k_ptr->backendObject()) { + BACKEND_CALL1("setVisualization", int, newVisualization.index()); + } +} + +/* +bool Visualization::hasParameterWidget() const +{ + K_D(const Visualization); + if (d->m_backendObject) + { + bool ret; + BACKEND_GET(bool, ret, "hasParameterWidget"); + return ret; + } + return false; +} + +QWidget *Visualization::createParameterWidget(QWidget *parent) +{ + K_D(Visualization); + if (k_ptr->backendObject()) + { + QWidget *ret; + BACKEND_GET1(QWidget *, ret, "createParameterWidget", QWidget *, parent); + return ret; + } + return 0; +} +*/ + +void VisualizationPrivate::phononObjectDestroyed(MediaNodePrivate *bp) +{ + Q_UNUSED(bp); + // this method is called from Phonon::MediaNodePrivate::~MediaNodePrivate(), meaning the AudioEffect + // dtor has already been called and the private class is down to MediaNodePrivate + /* + Q_ASSERT(bp); + if (audioPath->k_ptr == bp) + { + pBACKEND_CALL1("setAudioPath", QObject *, static_cast(0)); + audioPath = 0; + } + else if (videoOutput->k_ptr == bp) + { + pBACKEND_CALL1("setVideoOutput", QObject *, static_cast(0)); + videoOutput = 0; + } + */ +} + +bool VisualizationPrivate::aboutToDeleteBackendObject() +{ + return true; +} + +void VisualizationPrivate::setupBackendObject() +{ + Q_ASSERT(m_backendObject); + + pBACKEND_CALL1("setVisualization", int, description.index()); + /* + if (audioPath) + pBACKEND_CALL1("setAudioPath", QObject *, audioPath->k_ptr->backendObject()); + if (videoOutput) + pBACKEND_CALL1("setVideoOutput", QObject *, videoOutput->k_ptr->backendObject()); + */ +} + +} // namespace Experimental +} // namespace Phonon + +#include "visualization.moc" +#undef PHONON_CLASSNAME +// vim: sw=4 ts=4 diff --git a/src/3rdparty/phonon/phonon/experimental/visualization.h b/src/3rdparty/phonon/phonon/experimental/visualization.h new file mode 100644 index 0000000..33074d7 --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/visualization.h @@ -0,0 +1,107 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2007 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_VISUALIZATION_H +#define PHONON_VISUALIZATION_H + +#include "export.h" +#include "../phonondefs.h" +#include +#include "../objectdescription.h" +#include "../objectdescriptionmodel.h" +#include "../medianode.h" + +namespace Phonon +{ +class AudioPath; +class AbstractVideoOutput; + +namespace Experimental +{ + class VisualizationPrivate; + +enum { + VisualizationType = 0xfffffffe +}; +typedef ObjectDescription(VisualizationType)> VisualizationDescription; +typedef ObjectDescriptionModel(VisualizationType)> VisualizationDescriptionModel; + +/** + * \short A class to create visual effects from an audio signal. + * + * This class is used to define how an audio signal from an AudioPath object + * should be visualized. What visualization effects are available depends solely + * on the backend. You can list the available visualization effects using + * BackendCapabilities::availableVisualizationEffects(). + * + * The following example code takes the first effect from the list and uses that + * to display a visualization on a new VideoWidget. + * \code + * QList list = BackendCapabilities::availableVisualizationEffects(); + * if (list.size() > 0) + * { + * VideoWidget *visWidget = new VideoWidget(parent); + * Visualization *vis = new Visualization(visWidget); + * vis->setAudioPath(audioPath); + * vis->setVideoOutput(visWidget); + * vis->setVisualization(list.first()); + * } + * \endcode + * + * \author Matthias Kretz + * \see AudioDataOutput + * \see BackendCapabilities::availableVisualizationEffects() + */ +class PHONONEXPERIMENTAL_EXPORT Visualization : public QObject, public MediaNode +{ + Q_OBJECT + K_DECLARE_PRIVATE(Visualization) + PHONON_OBJECT(Visualization) + Q_PROPERTY(VisualizationDescription visualization READ visualization WRITE setVisualization) + + public: + ~Visualization(); + + VisualizationDescription visualization() const; + void setVisualization(const VisualizationDescription &newVisualization); + + /** + * Returns whether the selected visualization effect can be configured + * by the user with a widget returned by createParameterWidget(). In + * short it tells you whether createParameterWidget() will return 0 or + * not. + */ + //bool hasParameterWidget() const; + + /** + * Returns a widget that displays effect parameter controls to the user. + * + * \param parent The parent widget for the new widget. + */ + //QWidget *createParameterWidget(QWidget *parent = 0); +}; + +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_VISUALIZATION_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/experimental/visualization_p.h b/src/3rdparty/phonon/phonon/experimental/visualization_p.h new file mode 100644 index 0000000..2c1a0db --- /dev/null +++ b/src/3rdparty/phonon/phonon/experimental/visualization_p.h @@ -0,0 +1,51 @@ +/* This file is part of the KDE project + Copyright (C) 2006 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_VISUALIZATION_P_H +#define PHONON_VISUALIZATION_P_H + +#include "visualization.h" +#include "../medianode_p.h" +#include "../medianodedestructionhandler_p.h" +#include "../phonondefs_p.h" + +namespace Phonon +{ +namespace Experimental +{ +class VisualizationPrivate : public MediaNodePrivate, private MediaNodeDestructionHandler +{ + Q_DECLARE_PUBLIC(Visualization) + PHONON_PRIVATECLASS + public: + virtual QObject *qObject() { return q_func(); } + protected: + VisualizationDescription description; + + private: + void phononObjectDestroyed(MediaNodePrivate *); +}; +} // namespace Experimental +} // namespace Phonon + +#endif // PHONON_VISUALIZATION_P_H +// vim: sw=4 ts=4 tw=80 diff --git a/src/3rdparty/phonon/phonon/factory.cpp b/src/3rdparty/phonon/phonon/factory.cpp index d5010e7..b26c4f3 100644 --- a/src/3rdparty/phonon/phonon/factory.cpp +++ b/src/3rdparty/phonon/phonon/factory.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -111,7 +111,6 @@ void Factory::setBackend(QObject *b) bool FactoryPrivate::createBackend() { -#ifndef QT_NO_LIBRARY Q_ASSERT(m_backendObject == 0); #ifndef QT_NO_PHONON_PLATFORMPLUGIN PlatformPlugin *f = globalFactory->platformPlugin(); @@ -125,39 +124,15 @@ bool FactoryPrivate::createBackend() // could not load a backend through the platform plugin. Falling back to the default // (finding the first loadable backend). const QLatin1String suffix("/phonon_backend/"); - const QStringList paths = QCoreApplication::libraryPaths(); - for (int i = 0; i < paths.count(); ++i) { - const QString libPath = paths.at(i) + suffix; + foreach (QString libPath, QCoreApplication::libraryPaths()) { + libPath += suffix; const QDir dir(libPath); if (!dir.exists()) { pDebug() << Q_FUNC_INFO << dir.absolutePath() << "does not exist"; continue; } - - QStringList plugins(dir.entryList(QDir::Files)); - -#ifdef Q_OS_SYMBIAN - /* On Symbian OS we might have two plugins, one which uses Symbian - * MMF framework("phonon_mmf"), and one which uses Real Networks's - * Helix("hxphonon"). We prefer the latter because it's more - * sophisticated, so we make sure the Helix backend is attempted - * to be loaded first, and the MMF backend is used for backup. */ - { - - const int hxphonon = plugins.indexOf(QLatin1String("hxphonon")); - if (hxphonon != -1) - plugins.move(hxphonon, 0); - - // Code for debugging the MMF backend. - if(hxphonon != -1) { - qDebug() << "Found hxphonon backend and removed it from the lookup list."; - plugins.removeAll(QLatin1String("hxphonon")); - } - } -#endif - - for (int i = 0; i < plugins.count(); ++i) { - QPluginLoader pluginLoader(libPath + plugins.at(i)); + foreach (const QString &pluginName, dir.entryList(QDir::Files)) { + QPluginLoader pluginLoader(libPath + pluginName); if (!pluginLoader.load()) { pDebug() << Q_FUNC_INFO << " load failed:" << pluginLoader.errorString(); @@ -187,20 +162,14 @@ bool FactoryPrivate::createBackend() SLOT(objectDescriptionChanged(ObjectDescriptionType))); return true; -#else //QT_NO_LIBRARY - pWarning() << Q_FUNC_INFO << "Trying to use Phonon with QT_NO_LIBRARY defined. " - "That is currently not supported"; - return false; -#endif } FactoryPrivate::FactoryPrivate() - : #ifndef QT_NO_PHONON_PLATFORMPLUGIN - m_platformPlugin(0), - m_noPlatformPlugin(false), + : m_platformPlugin(0), + m_noPlatformPlugin(false) #endif //QT_NO_PHONON_PLATFORMPLUGIN - m_backendObject(0) + , m_backendObject(0) { // Add the post routine to make sure that all other global statics (especially the ones from Qt) // are still available. If the FactoryPrivate dtor is called too late many bad things can happen @@ -214,8 +183,14 @@ FactoryPrivate::FactoryPrivate() FactoryPrivate::~FactoryPrivate() { - for (int i = 0; i < mediaNodePrivateList.count(); ++i) { - mediaNodePrivateList.at(i)->deleteBackendObject(); + foreach (QObject *o, objects) { + MediaObject *m = qobject_cast(o); + if (m) { + m->stop(); + } + } + foreach (MediaNodePrivate *bp, mediaNodePrivateList) { + bp->deleteBackendObject(); } if (objects.size() > 0) { pError() << "The backend objects are not deleted as was requested."; @@ -283,8 +258,8 @@ void Factory::deregisterFrontendObject(MediaNodePrivate *bp) void FactoryPrivate::phononBackendChanged() { if (m_backendObject) { - for (int i = 0; i < mediaNodePrivateList.count(); ++i) { - mediaNodePrivateList.at(i)->deleteBackendObject(); + foreach (MediaNodePrivate *bp, mediaNodePrivateList) { + bp->deleteBackendObject(); } if (objects.size() > 0) { pDebug() << "WARNING: we were asked to change the backend but the application did\n" @@ -293,8 +268,8 @@ void FactoryPrivate::phononBackendChanged() "backendswitching possible."; // in case there were objects deleted give 'em a chance to recreate // them now - for (int i = 0; i < mediaNodePrivateList.count(); ++i) { - mediaNodePrivateList.at(i)->createBackendObject(); + foreach (MediaNodePrivate *bp, mediaNodePrivateList) { + bp->createBackendObject(); } return; } @@ -302,8 +277,8 @@ void FactoryPrivate::phononBackendChanged() m_backendObject = 0; } createBackend(); - for (int i = 0; i < mediaNodePrivateList.count(); ++i) { - mediaNodePrivateList.at(i)->createBackendObject(); + foreach (MediaNodePrivate *bp, mediaNodePrivateList) { + bp->createBackendObject(); } emit backendChanged(); } @@ -350,6 +325,7 @@ FACTORY_IMPL(AudioOutput) #ifndef QT_NO_PHONON_VIDEO FACTORY_IMPL(VideoWidget) #endif //QT_NO_PHONON_VIDEO +FACTORY_IMPL(AudioDataOutput) #undef FACTORY_IMPL @@ -387,17 +363,15 @@ PlatformPlugin *FactoryPrivate::platformPlugin() QStringList()) ); dir.setFilter(QDir::Files); - const QStringList libPaths = QCoreApplication::libraryPaths(); forever { - for (int i = 0; i < libPaths.count(); ++i) { - const QString libPath = libPaths.at(i) + suffix; + foreach (QString libPath, QCoreApplication::libraryPaths()) { + libPath += suffix; dir.setPath(libPath); if (!dir.exists()) { continue; } - const QStringList files = dir.entryList(QDir::Files); - for (int i = 0; i < files.count(); ++i) { - QPluginLoader pluginLoader(libPath + files.at(i)); + foreach (const QString &pluginName, dir.entryList()) { + QPluginLoader pluginLoader(libPath + pluginName); if (!pluginLoader.load()) { pDebug() << Q_FUNC_INFO << " platform plugin load failed:" << pluginLoader.errorString(); @@ -449,7 +423,6 @@ QObject *Factory::backend(bool createWhenNull) return globalFactory->m_backendObject; } -#ifndef QT_NO_PROPERTIES #define GET_STRING_PROPERTY(name) \ QString Factory::name() \ { \ @@ -465,7 +438,7 @@ GET_STRING_PROPERTY(backendComment) GET_STRING_PROPERTY(backendVersion) GET_STRING_PROPERTY(backendIcon) GET_STRING_PROPERTY(backendWebsite) -#endif //QT_NO_PROPERTIES + QObject *Factory::registerQObject(QObject *o) { if (o) { diff --git a/src/3rdparty/phonon/phonon/factory_p.h b/src/3rdparty/phonon/phonon/factory_p.h index de059f8..41b8c5b 100644 --- a/src/3rdparty/phonon/phonon/factory_p.h +++ b/src/3rdparty/phonon/phonon/factory_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -122,6 +122,13 @@ namespace Factory #endif //QT_NO_PHONON_VIDEO /** + * Create a new backend object for a AudioDataOutput. + * + * \return a pointer to the AudioDataOutput the backend provides. + */ + PHONON_EXPORT QObject *createAudioDataOutput(QObject *parent = 0); + + /** * \return a pointer to the backend interface. */ PHONON_EXPORT QObject *backend(bool createWhenNull = true); diff --git a/src/3rdparty/phonon/phonon/frontendinterface_p.h b/src/3rdparty/phonon/phonon/frontendinterface_p.h index b6c76ce..83ad780 100644 --- a/src/3rdparty/phonon/phonon/frontendinterface_p.h +++ b/src/3rdparty/phonon/phonon/frontendinterface_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/globalconfig.cpp b/src/3rdparty/phonon/phonon/globalconfig.cpp index 3718c6a..44bf49a 100644 --- a/src/3rdparty/phonon/phonon/globalconfig.cpp +++ b/src/3rdparty/phonon/phonon/globalconfig.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -20,6 +20,7 @@ */ +#include "globalconfig.h" #include "globalconfig_p.h" #include "factory_p.h" @@ -29,6 +30,7 @@ #include "backendinterface.h" #include "qsettingsgroup_p.h" #include "phononnamespace_p.h" +#include "pulsesupport.h" #include #include @@ -38,15 +40,18 @@ QT_BEGIN_NAMESPACE namespace Phonon { +GlobalConfigPrivate::GlobalConfigPrivate() : config(QLatin1String("kde.org"), QLatin1String("libphonon")) +{ +} + GlobalConfig::GlobalConfig() -#ifndef QT_NO_SETTINGS - : m_config(QLatin1String("kde.org"), QLatin1String("libphonon")) -#endif //QT_NO_SETTINGS + : k_ptr(new GlobalConfigPrivate) { } GlobalConfig::~GlobalConfig() { + delete k_ptr; } enum WhatToFilter { @@ -85,9 +90,12 @@ static void filter(ObjectDescriptionType type, BackendInterface *backendIface, Q } } -#ifndef QT_NO_PHONON_SETTINGSGROUP -static QList listSortedByConfig(const QSettingsGroup &backendConfig, Phonon::Category category, QList &defaultList) +static QList sortDevicesByCategoryPriority(const GlobalConfig *config, const QSettingsGroup *backendConfig, ObjectDescriptionType type, Phonon::Category category, QList &defaultList) { + Q_ASSERT(config); + Q_ASSERT(backendConfig); + Q_ASSERT(type == AudioOutputDeviceType || type == AudioCaptureDeviceType); + if (defaultList.size() <= 1) { // nothing to sort return defaultList; @@ -104,20 +112,26 @@ static QList listSortedByConfig(const QSettingsGroup &backendConfig, Phonon } } - QString categoryKey = QLatin1String("Category_") + QString::number(static_cast(category)); - if (!backendConfig.hasKey(categoryKey)) { - // no list in config for the given category - categoryKey = QLatin1String("Category_") + QString::number(static_cast(Phonon::NoCategory)); - if (!backendConfig.hasKey(categoryKey)) { - // no list in config for NoCategory - return defaultList; + QList deviceList; + PulseSupport *pulse = PulseSupport::getInstance(); + if (pulse->isActive()) { + deviceList = pulse->objectIndexesByCategory(type, category); + } else { + QString categoryKey = QLatin1String("Category_") + QString::number(static_cast(category)); + if (!backendConfig->hasKey(categoryKey)) { + // no list in config for the given category + categoryKey = QLatin1String("Category_") + QString::number(static_cast(Phonon::NoCategory)); + if (!backendConfig->hasKey(categoryKey)) { + // no list in config for NoCategory + return defaultList; + } } - } - //Now the list from m_config - QList deviceList = backendConfig.value(categoryKey, QList()); + //Now the list from d->config + deviceList = backendConfig->value(categoryKey, QList()); + } - //if there are devices in m_config that the backend doesn't report, remove them from the list + //if there are devices in d->config that the backend doesn't report, remove them from the list QMutableListIterator i(deviceList); while (i.hasNext()) { if (0 == defaultList.removeAll(i.next())) { @@ -125,49 +139,176 @@ static QList listSortedByConfig(const QSettingsGroup &backendConfig, Phonon } } - //if the backend reports more devices that are not in m_config append them to the list + //if the backend reports more devices that are not in d->config append them to the list deviceList += defaultList; return deviceList; } -#endif //QT_NO_PHONON_SETTINGSGROUP -#ifndef QT_NO_PHONON_SETTINGSGROUP -QList GlobalConfig::audioOutputDeviceListFor(Phonon::Category category, int override) const +bool GlobalConfig::hideAdvancedDevices() const { + K_D(const GlobalConfig); //The devices need to be stored independently for every backend - const QSettingsGroup backendConfig(&m_config, QLatin1String("AudioOutputDevice")); // + Factory::identifier()); - const QSettingsGroup generalGroup(&m_config, QLatin1String("General")); - const bool hideAdvancedDevices = ((override & AdvancedDevicesFromSettings) - ? generalGroup.value(QLatin1String("HideAdvancedDevices"), true) + const QSettingsGroup generalGroup(&d->config, QLatin1String("General")); + return generalGroup.value(QLatin1String("HideAdvancedDevices"), true); +} + +void GlobalConfig::setHideAdvancedDevices(bool hide) +{ + K_D(GlobalConfig); + QSettingsGroup generalGroup(&d->config, QLatin1String("General")); + generalGroup.setValue(QLatin1String("HideAdvancedDevices"), hide); +} + +static bool isHiddenAudioOutputDevice(const GlobalConfig *config, int i) +{ + Q_ASSERT(config); + + if (!config->hideAdvancedDevices()) + return false; + + AudioOutputDevice ad = AudioOutputDevice::fromIndex(i); + const QVariant var = ad.property("isAdvanced"); + return (var.isValid() && var.toBool()); +} + +#ifndef QT_NO_PHONON_AUDIOCAPTURE +static bool isHiddenAudioCaptureDevice(const GlobalConfig *config, int i) +{ + Q_ASSERT(config); + + if (!config->hideAdvancedDevices()) + return false; + + AudioCaptureDevice ad = AudioCaptureDevice::fromIndex(i); + const QVariant var = ad.property("isAdvanced"); + return (var.isValid() && var.toBool()); +} +#endif + +static QList reindexList(const GlobalConfig *config, Phonon::Category category, QListnewOrder, bool output) +{ + Q_ASSERT(config); +#ifdef QT_NO_PHONON_AUDIOCAPTURE + Q_ASSERT(output); +#endif + + /*QString sb; + sb = QString("(Size %1)").arg(currentList.size()); + foreach (int i, currentList) + sb += QString("%1, ").arg(i); + fprintf(stderr, "=== Reindex Current: %s\n", sb.toUtf8().constData()); + sb = QString("(Size %1)").arg(newOrder.size()); + foreach (int i, newOrder) + sb += QString("%1, ").arg(i); + fprintf(stderr, "=== Reindex Before : %s\n", sb.toUtf8().constData());*/ + + QList currentList; + if (output) + currentList = config->audioOutputDeviceListFor(category, GlobalConfig::ShowUnavailableDevices|GlobalConfig::ShowAdvancedDevices); +#ifndef QT_NO_PHONON_AUDIOCAPTURE + else + currentList = config->audioCaptureDeviceListFor(category, GlobalConfig::ShowUnavailableDevices|GlobalConfig::ShowAdvancedDevices); +#endif + + QList newList; + + foreach (int i, newOrder) { + int found = currentList.indexOf(i); + if (found < 0) { + // It's not in the list, so something is odd (e.g. client error). Ignore it. + continue; + } + + // Iterate through the list from this point onward. If there are hidden devices + // immediately following, take them too. + newList.append(currentList.takeAt(found)); + while (found < currentList.size()) { + bool hidden = true; + if (output) + hidden = isHiddenAudioOutputDevice(config, currentList.at(found)); +#ifndef QT_NO_PHONON_AUDIOCAPTURE + else + hidden = isHiddenAudioCaptureDevice(config, currentList.at(found)); +#endif + + if (!hidden) + break; + newList.append(currentList.takeAt(found)); + } + } + + // If there are any devices left in.. just tack them on the end. + if (currentList.size() > 0) + newList += currentList; + + /*sb = QString("(Size %1)").arg(newList.size()); + foreach (int i, newList) + sb += QString("%1, ").arg(i); + fprintf(stderr, "=== Reindex After : %s\n", sb.toUtf8().constData());*/ + return newList; +} + + +void GlobalConfig::setAudioOutputDeviceListFor(Phonon::Category category, QList order) +{ + PulseSupport *pulse = PulseSupport::getInstance(); + if (pulse->isActive()) { + pulse->setOutputDevicePriorityForCategory(category, order); + return; + } + + K_D(GlobalConfig); + QSettingsGroup backendConfig(&d->config, QLatin1String("AudioOutputDevice")); // + Factory::identifier()); + + order = reindexList(this, category, order, true); + + const QList noCategoryOrder = audioOutputDeviceListFor(Phonon::NoCategory, ShowUnavailableDevices|ShowAdvancedDevices); + if (category != Phonon::NoCategory && order == noCategoryOrder) { + backendConfig.removeEntry(QLatin1String("Category_") + QString::number(category)); + } else { + backendConfig.setValue(QLatin1String("Category_") + QString::number(category), order); + } +} + +QList GlobalConfig::audioOutputDeviceListFor(Phonon::Category category, int override) const +{ + K_D(const GlobalConfig); + + const bool hide = ((override & AdvancedDevicesFromSettings) + ? hideAdvancedDevices() : static_cast(override & HideAdvancedDevices)); QList defaultList; + BackendInterface *backendIface = qobject_cast(Factory::backend()); + #ifndef QT_NO_PHONON_PLATFORMPLUGIN - if (PlatformPlugin *platformPlugin = Factory::platformPlugin()) { - // the platform plugin lists the audio devices for the platform - // this list already is in default order (as defined by the platform plugin) - defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioOutputDeviceType); - if (hideAdvancedDevices) { - QMutableListIterator it(defaultList); - while (it.hasNext()) { - AudioOutputDevice objDesc = AudioOutputDevice::fromIndex(it.next()); - const QVariant var = objDesc.property("isAdvanced"); - if (var.isValid() && var.toBool()) { - it.remove(); + if (!backendIface || !PulseSupport::getInstance()->isActive()) { + if (PlatformPlugin *platformPlugin = Factory::platformPlugin()) { + // the platform plugin lists the audio devices for the platform + // this list already is in default order (as defined by the platform plugin) + defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioOutputDeviceType); + if (hide) { + QMutableListIterator it(defaultList); + while (it.hasNext()) { + AudioOutputDevice objDesc = AudioOutputDevice::fromIndex(it.next()); + const QVariant var = objDesc.property("isAdvanced"); + if (var.isValid() && var.toBool()) { + it.remove(); + } } } } } #endif //QT_NO_PHONON_PLATFORMPLUGIN - // lookup the available devices directly from the backend (mostly for virtual devices) - if (BackendInterface *backendIface = qobject_cast(Factory::backend())) { + // lookup the available devices directly from the backend + if (backendIface) { // this list already is in default order (as defined by the backend) QList list = backendIface->objectDescriptionIndexes(Phonon::AudioOutputDeviceType); - if (hideAdvancedDevices || !defaultList.isEmpty() || (override & HideUnavailableDevices)) { + if (hide || !defaultList.isEmpty() || (override & HideUnavailableDevices)) { filter(AudioOutputDeviceType, backendIface, &list, - (hideAdvancedDevices ? FilterAdvancedDevices : 0) + (hide ? FilterAdvancedDevices : 0) // the platform plugin already provided the hardware devices | (defaultList.isEmpty() ? 0 : FilterHardwareDevices) | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0) @@ -176,9 +317,10 @@ QList GlobalConfig::audioOutputDeviceListFor(Phonon::Category category, int defaultList += list; } - return listSortedByConfig(backendConfig, category, defaultList); + const QSettingsGroup backendConfig(&d->config, QLatin1String("AudioOutputDevice")); // + Factory::identifier()); + return sortDevicesByCategoryPriority(this, &backendConfig, AudioOutputDeviceType, category, defaultList); } -#endif //QT_NO_SETTINGSGROUPS + int GlobalConfig::audioOutputDeviceFor(Phonon::Category category, int override) const { QList ret = audioOutputDeviceListFor(category, override); @@ -188,42 +330,65 @@ int GlobalConfig::audioOutputDeviceFor(Phonon::Category category, int override) } #ifndef QT_NO_PHONON_AUDIOCAPTURE +void GlobalConfig::setAudioCaptureDeviceListFor(Phonon::Category category, QList order) +{ + PulseSupport *pulse = PulseSupport::getInstance(); + if (pulse->isActive()) { + pulse->setCaptureDevicePriorityForCategory(category, order); + return; + } + + K_D(GlobalConfig); + QSettingsGroup backendConfig(&d->config, QLatin1String("AudioCaptureDevice")); // + Factory::identifier()); + + order = reindexList(this, category, order, false); + + const QList noCategoryOrder = audioCaptureDeviceListFor(Phonon::NoCategory, ShowUnavailableDevices|ShowAdvancedDevices); + if (category != Phonon::NoCategory && order == noCategoryOrder) { + backendConfig.removeEntry(QLatin1String("Category_") + QString::number(category)); + } else { + backendConfig.setValue(QLatin1String("Category_") + QString::number(category), order); + } +} + QList GlobalConfig::audioCaptureDeviceListFor(Phonon::Category category, int override) const { -#ifndef QT_NO_PHONON_SETTINGSGROUP - //The devices need to be stored independently for every backend - const QSettingsGroup backendConfig(&m_config, QLatin1String("AudioCaptureDevice")); // + Factory::identifier()); - const QSettingsGroup generalGroup(&m_config, QLatin1String("General")); - const bool hideAdvancedDevices = ((override & AdvancedDevicesFromSettings) - ? generalGroup.value(QLatin1String("HideAdvancedDevices"), true) + K_D(const GlobalConfig); + + const bool hide = ((override & AdvancedDevicesFromSettings) + ? hideAdvancedDevices() : static_cast(override & HideAdvancedDevices)); QList defaultList; + BackendInterface *backendIface = qobject_cast(Factory::backend()); + #ifndef QT_NO_PHONON_PLATFORMPLUGIN - if (PlatformPlugin *platformPlugin = Factory::platformPlugin()) { - // the platform plugin lists the audio devices for the platform - // this list already is in default order (as defined by the platform plugin) - defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType); - if (hideAdvancedDevices) { - QMutableListIterator it(defaultList); - while (it.hasNext()) { - AudioCaptureDevice objDesc = AudioCaptureDevice::fromIndex(it.next()); - const QVariant var = objDesc.property("isAdvanced"); - if (var.isValid() && var.toBool()) { - it.remove(); + if (!backendIface || !PulseSupport::getInstance()->isActive()) { + if (PlatformPlugin *platformPlugin = Factory::platformPlugin()) { + // the platform plugin lists the audio devices for the platform + // this list already is in default order (as defined by the platform plugin) + defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType); + if (hide) { + QMutableListIterator it(defaultList); + while (it.hasNext()) { + AudioCaptureDevice objDesc = AudioCaptureDevice::fromIndex(it.next()); + const QVariant var = objDesc.property("isAdvanced"); + if (var.isValid() && var.toBool()) { + it.remove(); + } } } } } #endif //QT_NO_PHONON_PLATFORMPLUGIN - // lookup the available devices directly from the backend (mostly for virtual devices) - if (BackendInterface *backendIface = qobject_cast(Factory::backend())) { + // lookup the available devices directly from the backend + if (backendIface) { // this list already is in default order (as defined by the backend) QList list = backendIface->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType); - if (hideAdvancedDevices || !defaultList.isEmpty() || (override & HideUnavailableDevices)) { + if (hide || !defaultList.isEmpty() || (override & HideUnavailableDevices)) { filter(AudioCaptureDeviceType, backendIface, &list, - (hideAdvancedDevices ? FilterAdvancedDevices : 0) + (hide ? FilterAdvancedDevices : 0) // the platform plugin already provided the hardware devices | (defaultList.isEmpty() ? 0 : FilterHardwareDevices) | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0) @@ -232,10 +397,8 @@ QList GlobalConfig::audioCaptureDeviceListFor(Phonon::Category category, in defaultList += list; } - return listSortedByConfig(backendConfig, category, defaultList); -#else //QT_NO_SETTINGSGROUP - return QList(); -#endif //QT_NO_SETTINGSGROUP + const QSettingsGroup backendConfig(&d->config, QLatin1String("AudioCaptureDevice")); // + Factory::identifier()); + return sortDevicesByCategoryPriority(this, &backendConfig, AudioCaptureDeviceType, category, defaultList); } int GlobalConfig::audioCaptureDeviceFor(Phonon::Category category, int override) const diff --git a/src/3rdparty/phonon/phonon/globalconfig.h b/src/3rdparty/phonon/phonon/globalconfig.h new file mode 100644 index 0000000..5233c7b --- /dev/null +++ b/src/3rdparty/phonon/phonon/globalconfig.h @@ -0,0 +1,71 @@ +/* This file is part of the KDE project +Copyright (C) 2006-2008 Matthias Kretz + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_GLOBALCONFIG_H +#define PHONON_GLOBALCONFIG_H + +#include "phonon_export.h" +#include "phononnamespace.h" +#include "phonondefs.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + class GlobalConfigPrivate; + + class PHONON_EXPORT GlobalConfig + { + K_DECLARE_PRIVATE(GlobalConfig) + public: + GlobalConfig(); + virtual ~GlobalConfig(); + + enum DevicesToHideFlag { + ShowUnavailableDevices = 0, + ShowAdvancedDevices = 0, + HideAdvancedDevices = 1, + AdvancedDevicesFromSettings = 2, + HideUnavailableDevices = 4 + }; + bool hideAdvancedDevices() const; + void setHideAdvancedDevices(bool hide = true); + void setAudioOutputDeviceListFor(Phonon::Category category, QList order); + QList audioOutputDeviceListFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const; + int audioOutputDeviceFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const; + +#ifndef QT_NO_PHONON_AUDIOCAPTURE + void setAudioCaptureDeviceListFor(Phonon::Category category, QList order); + QList audioCaptureDeviceListFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const; + int audioCaptureDeviceFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const; +#endif //QT_NO_PHONON_AUDIOCAPTURE + + protected: + GlobalConfigPrivate *const k_ptr; + }; +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_GLOBALCONFIG_H diff --git a/src/3rdparty/phonon/phonon/globalconfig_p.h b/src/3rdparty/phonon/phonon/globalconfig_p.h index 034bce3..090ca6b 100644 --- a/src/3rdparty/phonon/phonon/globalconfig_p.h +++ b/src/3rdparty/phonon/phonon/globalconfig_p.h @@ -6,7 +6,7 @@ Copyright (C) 2006-2008 Matthias Kretz License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -26,40 +26,19 @@ Copyright (C) 2006-2008 Matthias Kretz #include #include "phonon_export.h" -#include "phononnamespace.h" QT_BEGIN_HEADER QT_BEGIN_NAMESPACE namespace Phonon { - class PHONON_EXPORT GlobalConfig + class GlobalConfigPrivate { - public: - GlobalConfig(); - virtual ~GlobalConfig(); + public: + GlobalConfigPrivate(); + virtual ~GlobalConfigPrivate() {} - enum DevicesToHideFlag { - ShowUnavailableDevices = 0, - ShowAdvancedDevices = 0, - HideAdvancedDevices = 1, - AdvancedDevicesFromSettings = 2, - HideUnavailableDevices = 4 - }; -#ifndef QT_NO_PHONON_SETTINGSGROUP - QList audioOutputDeviceListFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const; -#endif //QT_NO_PHONON_SETTINGSGROUP - int audioOutputDeviceFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const; - -#ifndef QT_NO_PHONON_AUDIOCAPTURE - QList audioCaptureDeviceListFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const; - int audioCaptureDeviceFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const; -#endif //QT_NO_PHONON_AUDIOCAPTURE - - protected: -#ifndef QT_NO_SETTINGS - QSettings m_config; -#endif //QT_NO_SETTINGS + QSettings config; }; } // namespace Phonon diff --git a/src/3rdparty/phonon/phonon/globalstatic_p.h b/src/3rdparty/phonon/phonon/globalstatic_p.h index 04f8395..cf80512 100644 --- a/src/3rdparty/phonon/phonon/globalstatic_p.h +++ b/src/3rdparty/phonon/phonon/globalstatic_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/iodevicestream.cpp b/src/3rdparty/phonon/phonon/iodevicestream.cpp index 5376da3..3735f75 100644 --- a/src/3rdparty/phonon/phonon/iodevicestream.cpp +++ b/src/3rdparty/phonon/phonon/iodevicestream.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/iodevicestream_p.h b/src/3rdparty/phonon/phonon/iodevicestream_p.h index 5eb90bc..cca77e3 100644 --- a/src/3rdparty/phonon/phonon/iodevicestream_p.h +++ b/src/3rdparty/phonon/phonon/iodevicestream_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/mediacontroller.cpp b/src/3rdparty/phonon/phonon/mediacontroller.cpp index d094381..59fd5c7 100644 --- a/src/3rdparty/phonon/phonon/mediacontroller.cpp +++ b/src/3rdparty/phonon/phonon/mediacontroller.cpp @@ -7,7 +7,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/mediacontroller.h b/src/3rdparty/phonon/phonon/mediacontroller.h index 19aaf13..109a79e 100644 --- a/src/3rdparty/phonon/phonon/mediacontroller.h +++ b/src/3rdparty/phonon/phonon/mediacontroller.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/medianode.cpp b/src/3rdparty/phonon/phonon/medianode.cpp index 63fa2e3..f855766 100644 --- a/src/3rdparty/phonon/phonon/medianode.cpp +++ b/src/3rdparty/phonon/phonon/medianode.cpp @@ -7,7 +7,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -67,8 +67,8 @@ bool MediaNode::isValid() const MediaNodePrivate::~MediaNodePrivate() { - for (int i = 0 ; i < handlers.count(); ++i) { - handlers.at(i)->phononObjectDestroyed(this); + foreach (MediaNodeDestructionHandler *handler, handlers) { + handler->phononObjectDestroyed(this); } Factory::deregisterFrontendObject(this); delete m_backendObject; diff --git a/src/3rdparty/phonon/phonon/medianode.h b/src/3rdparty/phonon/phonon/medianode.h index 86931ac..6aab189 100644 --- a/src/3rdparty/phonon/phonon/medianode.h +++ b/src/3rdparty/phonon/phonon/medianode.h @@ -7,7 +7,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/medianode_p.h b/src/3rdparty/phonon/phonon/medianode_p.h index d5424b7..e2329a9 100644 --- a/src/3rdparty/phonon/phonon/medianode_p.h +++ b/src/3rdparty/phonon/phonon/medianode_p.h @@ -6,7 +6,7 @@ Copyright (C) 2007 Matthias Kretz License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/medianodedestructionhandler_p.h b/src/3rdparty/phonon/phonon/medianodedestructionhandler_p.h index 38c0907..9c893f4 100644 --- a/src/3rdparty/phonon/phonon/medianodedestructionhandler_p.h +++ b/src/3rdparty/phonon/phonon/medianodedestructionhandler_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/mediaobject.cpp b/src/3rdparty/phonon/phonon/mediaobject.cpp index 10fefbd..0801bd7 100644 --- a/src/3rdparty/phonon/phonon/mediaobject.cpp +++ b/src/3rdparty/phonon/phonon/mediaobject.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -300,15 +300,15 @@ void MediaObject::enqueue(const MediaSource &source) void MediaObject::enqueue(const QList &sources) { - for (int i = 0; i < sources.count(); ++i) { - enqueue(sources.at(i)); + foreach (const MediaSource &m, sources) { + enqueue(m); } } void MediaObject::enqueue(const QList &urls) { - for (int i = 0; i < urls.count(); ++i) { - enqueue(urls.at(i)); + foreach (const QUrl &url, urls) { + enqueue(url); } } @@ -502,8 +502,8 @@ void MediaObjectPrivate::setupBackendObject() } #ifndef QT_NO_PHONON_MEDIACONTROLLER - for (int i = 0 ; i < interfaceList.count(); ++i) { - interfaceList.at(i)->_backendObjectChanged(); + foreach (FrontendInterfacePrivate *f, interfaceList) { + f->_backendObjectChanged(); } #endif //QT_NO_PHONON_MEDIACONTROLLER diff --git a/src/3rdparty/phonon/phonon/mediaobject.h b/src/3rdparty/phonon/phonon/mediaobject.h index c56b6b5..c1fa3c6 100644 --- a/src/3rdparty/phonon/phonon/mediaobject.h +++ b/src/3rdparty/phonon/phonon/mediaobject.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -15,7 +15,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public + You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ @@ -198,18 +198,18 @@ namespace Phonon * Check whether the current media may be seeked. * * \warning This information cannot be known immediately. It is best - * to also listen to the seekableChanged signal. + * to also listen to the hasVideoChanged signal. * * \code - * connect(media, SIGNAL(seekableChanged(bool)), seekableChanged(bool)); + * connect(media, SIGNAL(hasVideoChanged(bool)), hasVideoChanged(bool)); * media->setCurrentSource("somevideo.avi"); - * media->isSeekable(); // returns false; + * media->hasVideo(); // returns false; * } * - * void seekableChanged(bool b) + * void hasVideoChanged(bool b) * { * // b == true - * media->isSeekable(); // returns true; + * media->hasVideo(); // returns true; * } * \endcode * @@ -301,7 +301,7 @@ namespace Phonon void setCurrentSource(const MediaSource &source); /** - * Returns the queued media sources. This list does not include + * Returns the queued media sources. This does list does not include * the current source (returned by currentSource). */ QList queue() const; @@ -456,6 +456,8 @@ namespace Phonon Q_SIGNALS: /** * Emitted when the state of the MediaObject has changed. + * In case you're not interested in the old state you can also + * connect to a slot that only has one State argument. * * @param newstate The state the Player is in now. * @param oldstate The state the Player was in before. @@ -585,7 +587,7 @@ namespace Phonon /** * This signal is emitted as soon as the total time of the media file is * known or has changed. For most non-local media data the total - * time of the media can only be known after some time. Initially the + * time of the media can only be known after some time. At that time the * totalTime function can not return useful information. You have * to wait for this signal to know the real total time. * diff --git a/src/3rdparty/phonon/phonon/mediaobject_p.h b/src/3rdparty/phonon/phonon/mediaobject_p.h index 5419341..c164490 100644 --- a/src/3rdparty/phonon/phonon/mediaobject_p.h +++ b/src/3rdparty/phonon/phonon/mediaobject_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/mediaobjectinterface.h b/src/3rdparty/phonon/phonon/mediaobjectinterface.h index a5e2c51..26c4c8e 100644 --- a/src/3rdparty/phonon/phonon/mediaobjectinterface.h +++ b/src/3rdparty/phonon/phonon/mediaobjectinterface.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/mediasource.cpp b/src/3rdparty/phonon/phonon/mediasource.cpp index c003af9..c8db1e6 100644 --- a/src/3rdparty/phonon/phonon/mediasource.cpp +++ b/src/3rdparty/phonon/phonon/mediasource.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -140,12 +140,8 @@ MediaSourcePrivate::~MediaSourcePrivate() { #ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM if (autoDelete) { - //here we use deleteLater because this object - //might be destroyed from another thread - if (stream) - stream->deleteLater(); - if (ioDevice) - ioDevice->deleteLater(); + delete stream; + delete ioDevice; } #endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM } diff --git a/src/3rdparty/phonon/phonon/mediasource.h b/src/3rdparty/phonon/phonon/mediasource.h index da010d9..4cddbad 100644 --- a/src/3rdparty/phonon/phonon/mediasource.h +++ b/src/3rdparty/phonon/phonon/mediasource.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/mediasource_p.h b/src/3rdparty/phonon/phonon/mediasource_p.h index bfac7ad..46caef3 100644 --- a/src/3rdparty/phonon/phonon/mediasource_p.h +++ b/src/3rdparty/phonon/phonon/mediasource_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/objectdescription.cpp b/src/3rdparty/phonon/phonon/objectdescription.cpp index 3296792..4afd9dd 100644 --- a/src/3rdparty/phonon/phonon/objectdescription.cpp +++ b/src/3rdparty/phonon/phonon/objectdescription.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -29,6 +29,7 @@ #include #include "backendinterface.h" #include "platformplugin.h" +#include "pulsesupport.h" QT_BEGIN_NAMESPACE @@ -108,22 +109,24 @@ bool ObjectDescriptionData::isValid() const ObjectDescriptionData *ObjectDescriptionData::fromIndex(ObjectDescriptionType type, int index) { + BackendInterface *iface = qobject_cast(Factory::backend()); + // prefer to get the ObjectDescriptionData from the platform plugin for audio devices #ifndef QT_NO_PHONON_PLATFORMPLUGIN - if (type == AudioOutputDeviceType || type == AudioCaptureDeviceType) { - PlatformPlugin *platformPlugin = Factory::platformPlugin(); - if (platformPlugin) { - QList indexes = platformPlugin->objectDescriptionIndexes(type); - if (indexes.contains(index)) { - QHash properties = platformPlugin->objectDescriptionProperties(type, index); - return new ObjectDescriptionData(index, properties); + if (!iface || !PulseSupport::getInstance()->isActive()) { + if (type == AudioOutputDeviceType || type == AudioCaptureDeviceType) { + PlatformPlugin *platformPlugin = Factory::platformPlugin(); + if (platformPlugin) { + QList indexes = platformPlugin->objectDescriptionIndexes(type); + if (indexes.contains(index)) { + QHash properties = platformPlugin->objectDescriptionProperties(type, index); + return new ObjectDescriptionData(index, properties); + } } } } #endif //QT_NO_PHONON_PLATFORMPLUGIN - QObject *b = Factory::backend(); - BackendInterface *iface = qobject_cast(b); if (iface) { QList indexes = iface->objectDescriptionIndexes(type); if (indexes.contains(index)) { diff --git a/src/3rdparty/phonon/phonon/objectdescription.h b/src/3rdparty/phonon/phonon/objectdescription.h index 108f02c..985cdcc 100644 --- a/src/3rdparty/phonon/phonon/objectdescription.h +++ b/src/3rdparty/phonon/phonon/objectdescription.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/objectdescription_p.h b/src/3rdparty/phonon/phonon/objectdescription_p.h index 1069f11..bcf56de 100644 --- a/src/3rdparty/phonon/phonon/objectdescription_p.h +++ b/src/3rdparty/phonon/phonon/objectdescription_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp b/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp index b67344f..3d48a46 100644 --- a/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp +++ b/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -67,8 +67,6 @@ static const char qt_meta_stringdata_Phonon__ObjectDescriptionModel_Visualizatio namespace Phonon { -#if !defined(Q_CC_MINGW) || __MINGW32_MAJOR_VERSION >= 4 - template<> const QMetaObject ObjectDescriptionModel::staticMetaObject = { { &QAbstractListModel::staticMetaObject, qt_meta_stringdata_Phonon__ObjectDescriptionModel_AudioOutputDeviceType, qt_meta_data_Phonon__ObjectDescriptionModel, 0 } @@ -139,7 +137,6 @@ int ObjectDescriptionModel::qt_metacall(QMetaObject::Call _c, int _id, voi return QAbstractListModel::qt_metacall(_c, _id, _a); } */ -#endif int ObjectDescriptionModelData::rowCount(const QModelIndex &parent) const { @@ -321,8 +318,8 @@ bool ObjectDescriptionModelData::dropMimeData(ObjectDescriptionType type, const } } d->model->beginInsertRows(QModelIndex(), row, row + toInsert.size() - 1); - for (int i = 0 ; i < toInsert.count(); ++i) { - d->data.insert(row, toInsert.at(i)); + foreach (const QExplicitlySharedDataPointer &obj, toInsert) { + d->data.insert(row, obj); } d->model->endInsertRows(); return true; @@ -365,8 +362,7 @@ QStringList ObjectDescriptionModelData::mimeTypes(ObjectDescriptionType type) co return QStringList(QLatin1String("application/x-phonon-objectdescription") + QString::number(static_cast(type))); } -#if !defined(Q_CC_MINGW) || __MINGW32_MAJOR_VERSION >= 4 -#if !defined(Q_CC_MSVC) || _MSC_VER > 1300 || defined(Q_CC_INTEL) +#if !defined(Q_CC_MSVC) || _MSC_VER > 1300 || defined(Q_CC_INTEL) || defined(Q_CC_MINGW) #define INSTANTIATE_META_FUNCTIONS(type) \ template const QMetaObject *ObjectDescriptionModel::metaObject() const; \ template void *ObjectDescriptionModel::qt_metacast(const char *) @@ -384,7 +380,6 @@ INSTANTIATE_META_FUNCTIONS(VideoCodecType); INSTANTIATE_META_FUNCTIONS(ContainerFormatType); INSTANTIATE_META_FUNCTIONS(VisualizationType); */ -#endif //Q_CC_MINGW } // namespace Phonon #endif //QT_NO_PHONON_OBJECTDESCRIPTIONMODEL diff --git a/src/3rdparty/phonon/phonon/objectdescriptionmodel.h b/src/3rdparty/phonon/phonon/objectdescriptionmodel.h index a3c72b2..495225e 100644 --- a/src/3rdparty/phonon/phonon/objectdescriptionmodel.h +++ b/src/3rdparty/phonon/phonon/objectdescriptionmodel.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -35,6 +35,18 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_PHONON_OBJECTDESCRIPTIONMODEL +/* MinGW 3.4.x gives an ICE when trying to instantiate one of the + ObjectDescriptionModel classes because it can't handle + half exported classes correct. gcc 4.3.x has a fix for this but + we currently there's no official gcc 4.3 on windows available. + Because of this we need this little hack + */ +#if defined(Q_CC_MINGW) +#define PHONON_EXPORT_ODM +#else +#define PHONON_EXPORT_ODM PHONON_EXPORT +#endif + namespace Phonon { class ObjectDescriptionModelDataPrivate; @@ -139,21 +151,6 @@ namespace Phonon ObjectDescriptionModelDataPrivate *const d; }; -/* Required to ensure template class vtables are exported on both symbian -and existing builds. */ -#if defined(Q_OS_SYMBIAN) && defined(Q_CC_RVCT) -// RVCT compiler (2.2.686) requires the export declaration to be on the class to export vtables -// MWC compiler works both ways -// GCCE compiler is unknown (it can't compile QtCore yet) -#define PHONON_TEMPLATE_CLASS_EXPORT PHONON_EXPORT -#define PHONON_TEMPLATE_CLASS_MEMBER_EXPORT -#else -// Windows builds (at least) do not support export declaration on templated class -// But if you export a member function, the vtable is implicitly exported -#define PHONON_TEMPLATE_CLASS_EXPORT -#define PHONON_TEMPLATE_CLASS_MEMBER_EXPORT PHONON_EXPORT -#endif - /** \class ObjectDescriptionModel objectdescriptionmodel.h Phonon/ObjectDescriptionModel * \short The ObjectDescriptionModel class provides a model from * a list of ObjectDescription objects. @@ -190,26 +187,17 @@ and existing builds. */ * \author Matthias Kretz */ template - class PHONON_TEMPLATE_CLASS_EXPORT ObjectDescriptionModel : public QAbstractListModel + class ObjectDescriptionModel : public QAbstractListModel { public: Q_OBJECT_CHECK - -/* MinGW 3.4.x gives an ICE when trying to instantiate one of the - ObjectDescriptionModel classes because it can't handle - half exported classes correct. gcc 4.3.x has a fix for this but - we currently there's no official gcc 4.3 on windows available. - Because of this we need this little hack - */ -#if !defined(Q_CC_MINGW) || __MINGW32_MAJOR_VERSION >= 4 /** \internal */ - static PHONON_TEMPLATE_CLASS_MEMBER_EXPORT const QMetaObject staticMetaObject; + static PHONON_EXPORT const QMetaObject staticMetaObject; /** \internal */ - PHONON_TEMPLATE_CLASS_MEMBER_EXPORT const QMetaObject *metaObject() const; + PHONON_EXPORT_ODM const QMetaObject *metaObject() const; /** \internal */ - PHONON_TEMPLATE_CLASS_MEMBER_EXPORT void *qt_metacast(const char *_clname); + PHONON_EXPORT_ODM void *qt_metacast(const char *_clname); //int qt_metacall(QMetaObject::Call _c, int _id, void **_a); -#endif /** * Returns the number of rows in the model. This value corresponds @@ -307,8 +295,8 @@ and existing builds. */ */ inline void setModelData(const QList > &data) { //krazy:exclude=inline QList > list; - for (int i = 0; i < data.count(); ++i) { - list += data.at(i).d; + Q_FOREACH (const ObjectDescription &desc, data) { + list << desc.d; } d->setModelData(list); } @@ -322,8 +310,8 @@ and existing builds. */ inline QList > modelData() const { //krazy:exclude=inline QList > ret; QList > list = d->modelData(); - for (int i = 0; i < list.count(); ++i) { - ret << ObjectDescription(list.at(i)); + Q_FOREACH (const QExplicitlySharedDataPointer &data, list) { + ret << ObjectDescription(data); } return ret; } diff --git a/src/3rdparty/phonon/phonon/objectdescriptionmodel_p.h b/src/3rdparty/phonon/phonon/objectdescriptionmodel_p.h index f036bc8..2200c8d 100644 --- a/src/3rdparty/phonon/phonon/objectdescriptionmodel_p.h +++ b/src/3rdparty/phonon/phonon/objectdescriptionmodel_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/path.cpp b/src/3rdparty/phonon/phonon/path.cpp index ef3530c..b225697 100644 --- a/src/3rdparty/phonon/phonon/path.cpp +++ b/src/3rdparty/phonon/phonon/path.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -58,8 +58,8 @@ class ConnectionTransaction PathPrivate::~PathPrivate() { #ifndef QT_NO_PHONON_EFFECT - for (int i = 0; i < effects.count(); ++i) { - effects.at(i)->k_ptr->removeDestructionHandler(this); + foreach (Effect *e, effects) { + e->k_ptr->removeDestructionHandler(this); } delete effectsParent; #endif @@ -233,8 +233,8 @@ bool Path::disconnect() if (d->sourceNode) list << d->sourceNode->k_ptr->backendObject(); #ifndef QT_NO_PHONON_EFFECT - for (int i = 0; i < d->effects.count(); ++i) { - list << d->effects.at(i)->k_ptr->backendObject(); + foreach(Effect *e, d->effects) { + list << e->k_ptr->backendObject(); } #endif if (d->sinkNode) { @@ -244,8 +244,8 @@ bool Path::disconnect() //lets build the disconnection list QList disco; if (list.count() >=2 ) { - QObjectList::const_iterator it = list.begin(); - for(;it+1 != list.end();++it) { + QObjectList::const_iterator it = list.constBegin(); + for(;it+1 != list.constEnd();++it) { disco << QObjectPair(*it, *(it+1)); } } @@ -260,8 +260,8 @@ bool Path::disconnect() d->sourceNode = 0; #ifndef QT_NO_PHONON_EFFECT - for (int i = 0; i < d->effects.count(); ++i) { - d->effects.at(i)->k_ptr->removeDestructionHandler(d.data()); + foreach(Effect *e, d->effects) { + e->k_ptr->removeDestructionHandler(d.data()); } d->effects.clear(); #endif @@ -292,13 +292,11 @@ MediaNode *Path::sink() const bool PathPrivate::executeTransaction( const QList &disconnections, const QList &connections) { QSet nodesForTransaction; - for (int i = 0; i < disconnections.count(); ++i) { - const QObjectPair &pair = disconnections.at(i); + foreach(const QObjectPair &pair, disconnections) { nodesForTransaction << pair.first; nodesForTransaction << pair.second; } - for (int i = 0; i < connections.count(); ++i) { - const QObjectPair &pair = connections.at(i); + foreach(const QObjectPair &pair, connections) { nodesForTransaction << pair.first; nodesForTransaction << pair.second; } @@ -310,8 +308,8 @@ bool PathPrivate::executeTransaction( const QList &disconnections, if (!transaction) return false; - QList::const_iterator it = disconnections.constBegin(); - for(;it != disconnections.constEnd();++it) { + QList::const_iterator it = disconnections.begin(); + for(;it != disconnections.end();++it) { const QObjectPair &pair = *it; if (!backend->disconnectNodes(pair.first, pair.second)) { @@ -327,8 +325,8 @@ bool PathPrivate::executeTransaction( const QList &disconnections, } } - for(it = connections.constBegin(); it != connections.constEnd(); ++it) { - const QObjectPair pair = *it; + for(it = connections.begin(); it != connections.end();++it) { + const QObjectPair &pair = *it; if (!backend->connectNodes(pair.first, pair.second)) { //Error: a connection failed QList::const_iterator it2 = connections.begin(); @@ -340,8 +338,7 @@ bool PathPrivate::executeTransaction( const QList &disconnections, } //and now let's reconnect the nodes that were disconnected: rollback - for (int i = 0; i < disconnections.count(); ++i) { - const QObjectPair &pair = disconnections.at(i); + foreach(const QObjectPair &pair, disconnections) { bool success = backend->connectNodes(pair.first, pair.second); Q_ASSERT(success); //a failure here means it is impossible to reestablish the connection Q_UNUSED(success); @@ -420,8 +417,7 @@ void PathPrivate::phononObjectDestroyed(MediaNodePrivate *mediaNodePrivate) sinkNode = 0; } else { #ifndef QT_NO_PHONON_EFFECT - for (int i = 0; i < effects.count(); ++i) { - Effect *e = effects.at(i); + foreach (Effect *e, effects) { if (e->k_ptr == mediaNodePrivate) { removeEffect(e); } diff --git a/src/3rdparty/phonon/phonon/path.h b/src/3rdparty/phonon/phonon/path.h index eeabe82..6193054 100644 --- a/src/3rdparty/phonon/phonon/path.h +++ b/src/3rdparty/phonon/phonon/path.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/path_p.h b/src/3rdparty/phonon/phonon/path_p.h index 1345ad5..51b7e83 100644 --- a/src/3rdparty/phonon/phonon/path_p.h +++ b/src/3rdparty/phonon/phonon/path_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/phonon_export.h b/src/3rdparty/phonon/phonon/phonon_export.h index 5f93ea0..96b5159 100644 --- a/src/3rdparty/phonon/phonon/phonon_export.h +++ b/src/3rdparty/phonon/phonon/phonon_export.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/phonondefs.h b/src/3rdparty/phonon/phonon/phonondefs.h index d1a114a..765eb1c 100644 --- a/src/3rdparty/phonon/phonon/phonondefs.h +++ b/src/3rdparty/phonon/phonon/phonondefs.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -29,6 +29,11 @@ QT_BEGIN_HEADER QT_BEGIN_NAMESPACE +#ifdef PHONON_BACKEND_VERSION_4_4 +# ifndef PHONON_BACKEND_VERSION_4_3 +# define PHONON_BACKEND_VERSION_4_3 +# endif +#endif #ifdef PHONON_BACKEND_VERSION_4_3 # ifndef PHONON_BACKEND_VERSION_4_2 # define PHONON_BACKEND_VERSION_4_2 diff --git a/src/3rdparty/phonon/phonon/phonondefs_p.h b/src/3rdparty/phonon/phonon/phonondefs_p.h index 09037b5..778d7f6 100644 --- a/src/3rdparty/phonon/phonon/phonondefs_p.h +++ b/src/3rdparty/phonon/phonon/phonondefs_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/phononnamespace.cpp b/src/3rdparty/phonon/phonon/phononnamespace.cpp index f594d3c..ba20aa5 100644 --- a/src/3rdparty/phonon/phonon/phononnamespace.cpp +++ b/src/3rdparty/phonon/phonon/phononnamespace.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/phononnamespace.h.in b/src/3rdparty/phonon/phonon/phononnamespace.h.in index 54c5578..c65c121 100644 --- a/src/3rdparty/phonon/phonon/phononnamespace.h.in +++ b/src/3rdparty/phonon/phonon/phononnamespace.h.in @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -90,7 +90,7 @@ namespace Phonon }; /** - * Provided as keys for \ref MediaObject::metaData for convenience, in addition to the strings defined in + * Provided as keys for MediaObject::metaData for convenience, in addition to the strings defined in * the Ogg Vorbis specification. */ enum MetaData { diff --git a/src/3rdparty/phonon/phonon/phononnamespace_p.h b/src/3rdparty/phonon/phonon/phononnamespace_p.h index 4dd0ee8..2fa520a 100644 --- a/src/3rdparty/phonon/phonon/phononnamespace_p.h +++ b/src/3rdparty/phonon/phonon/phononnamespace_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/platform.cpp b/src/3rdparty/phonon/phonon/platform.cpp index ed660dc..49c4561 100644 --- a/src/3rdparty/phonon/phonon/platform.cpp +++ b/src/3rdparty/phonon/phonon/platform.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/platform_p.h b/src/3rdparty/phonon/phonon/platform_p.h index 379c54b..c4edb2f 100644 --- a/src/3rdparty/phonon/phonon/platform_p.h +++ b/src/3rdparty/phonon/phonon/platform_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/platformplugin.h b/src/3rdparty/phonon/phonon/platformplugin.h index e1ab1b7..c75bc96 100644 --- a/src/3rdparty/phonon/phonon/platformplugin.h +++ b/src/3rdparty/phonon/phonon/platformplugin.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/pulsesupport.cpp b/src/3rdparty/phonon/phonon/pulsesupport.cpp new file mode 100644 index 0000000..997df9a --- /dev/null +++ b/src/3rdparty/phonon/phonon/pulsesupport.cpp @@ -0,0 +1,966 @@ +/* This file is part of the KDE project + Copyright (C) 2009 Colin Guthrie + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#include +#include +#include +#include + +#ifdef HAVE_PULSEAUDIO +#include +#include +#include +#include +#include +#endif // HAVE_PULSEAUDIO + +#include "pulsesupport.h" + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + +static PulseSupport* s_instance = NULL; + +#ifdef HAVE_PULSEAUDIO +/*** +* Prints a conditional debug message based on the current debug level +* If obj is provided, classname and objectname will be printed as well +* +* see debugLevel() +*/ + +static int debugLevel() { + static int level = -1; + if (level < 1) { + level = 0; + QString pulseenv = qgetenv("PHONON_PULSEAUDIO_DEBUG"); + int l = pulseenv.toInt(); + if (l > 0) + level = (l > 2 ? 2 : l); + } + return level; +} + +static void logMessage(const QString &message, int priority = 2, QObject *obj=0); +static void logMessage(const QString &message, int priority, QObject *obj) +{ + if (debugLevel() > 0) { + QString output; + if (obj) { + // Strip away namespace from className + QString className(obj->metaObject()->className()); + int nameLength = className.length() - className.lastIndexOf(':') - 1; + className = className.right(nameLength); + output.sprintf("%s %s (%s %p)", message.toLatin1().constData(), + obj->objectName().toLatin1().constData(), + className.toLatin1().constData(), obj); + } + else { + output = message; + } + if (priority <= debugLevel()) { + qDebug() << QString("PulseSupport(%1): %2").arg(priority).arg(output); + } + } +} + + +class AudioDevice +{ + public: + inline + AudioDevice(QString name, QString desc, QString icon, uint32_t index) + : pulseName(name), pulseIndex(index) + { + properties["name"] = desc; + properties["description"] = ""; // We don't have descriptions (well we do, but we use them as the name!) + properties["icon"] = icon; + properties["available"] = (index != PA_INVALID_INDEX); + properties["isAdvanced"] = false; // Nothing is advanced! + } + + // Needed for QMap + inline AudioDevice() {} + + QString pulseName; + uint32_t pulseIndex; + QHash properties; +}; +bool operator!=(const AudioDevice &a, const AudioDevice &b) +{ + return !(a.pulseName == b.pulseName && a.properties == b.properties); +} + +class PulseUserData +{ + public: + inline + PulseUserData() + { + } + + QMap newOutputDevices; + QMap > newOutputDevicePriorities; // prio, device + + QMap newCaptureDevices; + QMap > newCaptureDevicePriorities; // prio, device +}; + +static QMap s_roleCategoryMap; + +static bool s_pulseActive = false; + +static pa_glib_mainloop *s_mainloop = NULL; +static pa_context *s_context = NULL; +static QEventLoop *s_connectionEventloop = NULL; + + + +static int s_deviceIndexCounter = 0; + +static QMap s_outputDeviceIndexes; +static QMap s_outputDevices; +static QMap > s_outputDevicePriorities; // prio, device +static QMap s_outputStreamIndexMap; +static QMap s_outputStreamMoveQueue; + +static QMap s_captureDeviceIndexes; +static QMap s_captureDevices; +static QMap > s_captureDevicePriorities; // prio, device +static QMap s_captureStreamIndexMap; +static QMap s_captureStreamMoveQueue; + + +static void ext_device_manager_subscribe_cb(pa_context *, void *); +static void ext_device_manager_read_cb(pa_context *c, const pa_ext_device_manager_info *info, int eol, void *userdata) { + Q_ASSERT(c); + Q_ASSERT(userdata); + + // If this is our first iteration, set things up properly + if (s_connectionEventloop) { + s_connectionEventloop->exit(0); + s_connectionEventloop = NULL; + s_pulseActive = true; + + pa_operation *o; + pa_ext_device_manager_set_subscribe_cb(c, ext_device_manager_subscribe_cb, NULL); + if ((o = pa_ext_device_manager_subscribe(c, 1, NULL, NULL))) + pa_operation_unref(o); + } + + if (eol < 0) { + logMessage(QString("Failed to initialize device manager extension: %1").arg(pa_strerror(pa_context_errno(c)))); + // OK so we don't have the device manager extension, but we can show a single device and fake it. + int index; + s_outputDeviceIndexes.clear(); + s_outputDevices.clear(); + s_outputDevicePriorities.clear(); + index = s_deviceIndexCounter++; + s_outputDeviceIndexes.insert("sink:default", index); + s_outputDevices.insert(index, AudioDevice("sink:default", QObject::tr("PulseAudio Sound Server").toUtf8(), "audio-backend-pulseaudio", 0)); + for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) { + Phonon::Category cat = static_cast(i); + s_outputDevicePriorities[cat].insert(0, index); + } + + s_captureDeviceIndexes.clear(); + s_captureDevices.clear(); + s_captureDevicePriorities.clear(); + index = s_deviceIndexCounter++; + s_captureDeviceIndexes.insert("source:default", index); + s_captureDevices.insert(index, AudioDevice("source:default", QObject::tr("PulseAudio Sound Server").toUtf8(), "audio-backend-pulseaudio", 0)); + for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) { + Phonon::Category cat = static_cast(i); + s_captureDevicePriorities[cat].insert(0, index); + } + + return; + } + + PulseUserData *u = reinterpret_cast(userdata); + if (eol) { + // We're done reading the data, so order it by priority and copy it into the + // static variables where it can then be accessed by those classes that need it. + + QMap::iterator newdev_it; + + // Check for new output devices or things changing about known output devices. + bool output_changed = false; + for (newdev_it = u->newOutputDevices.begin(); newdev_it != u->newOutputDevices.end(); ++newdev_it) { + QString name = newdev_it.key(); + + // The name + index map is always written when a new device is added. + Q_ASSERT(s_outputDeviceIndexes.contains(name)); + + int index = s_outputDeviceIndexes[name]; + if (!s_outputDevices.contains(index)) { + // This is a totally new device + output_changed = true; + logMessage(QString("Brand New Output Device Found.")); + s_outputDevices.insert(index, *newdev_it); + } else if (s_outputDevices[index] != *newdev_it) { + // We have this device already, but is it different? + output_changed = true; + logMessage(QString("Change to Existing Output Device (may be Added/Removed or something else)")); + s_outputDevices.remove(index); + s_outputDevices.insert(index, *newdev_it); + } + } + // Go through the output devices we know about and see if any are no longer mentioned in the list. + QMutableMapIterator output_existing_it(s_outputDeviceIndexes); + while (output_existing_it.hasNext()) { + output_existing_it.next(); + if (!u->newOutputDevices.contains(output_existing_it.key())) { + output_changed = true; + logMessage(QString("Output Device Completely Removed")); + s_outputDevices.remove(output_existing_it.value()); + output_existing_it.remove(); + } + } + + // Check for new capture devices or things changing about known capture devices. + bool capture_changed = false; + for (newdev_it = u->newCaptureDevices.begin(); newdev_it != u->newCaptureDevices.end(); ++newdev_it) { + QString name = newdev_it.key(); + + // The name + index map is always written when a new device is added. + Q_ASSERT(s_captureDeviceIndexes.contains(name)); + + int index = s_captureDeviceIndexes[name]; + if (!s_captureDevices.contains(index)) { + // This is a totally new device + capture_changed = true; + logMessage(QString("Brand New Capture Device Found.")); + s_captureDevices.insert(index, *newdev_it); + } else if (s_captureDevices[index] != *newdev_it) { + // We have this device already, but is it different? + capture_changed = true; + logMessage(QString("Change to Existing Capture Device (may be Added/Removed or something else)")); + s_captureDevices.remove(index); + s_captureDevices.insert(index, *newdev_it); + } + } + // Go through the capture devices we know about and see if any are no longer mentioned in the list. + QMutableMapIterator capture_existing_it(s_captureDeviceIndexes); + while (capture_existing_it.hasNext()) { + capture_existing_it.next(); + if (!u->newCaptureDevices.contains(capture_existing_it.key())) { + capture_changed = true; + logMessage(QString("Capture Device Completely Removed")); + s_captureDevices.remove(capture_existing_it.value()); + capture_existing_it.remove(); + } + } + + // Just copy accross the new priority lists as we know they are valid + if (s_outputDevicePriorities != u->newOutputDevicePriorities) { + output_changed = true; + s_outputDevicePriorities = u->newOutputDevicePriorities; + } + if (s_captureDevicePriorities != u->newCaptureDevicePriorities) { + capture_changed = true; + s_captureDevicePriorities = u->newCaptureDevicePriorities; + } + + if (s_instance) { + if (output_changed) + s_instance->emitObjectDescriptionChanged(AudioOutputDeviceType); + if (capture_changed) + s_instance->emitObjectDescriptionChanged(AudioCaptureDeviceType); + } + + // We can free the user data as we will not be called again. + delete u; + + // Some debug + logMessage(QString("Output Device Priority List:")); + for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) { + Phonon::Category cat = static_cast(i); + if (s_outputDevicePriorities.contains(cat)) { + logMessage(QString(" Phonon Category %1").arg(cat)); + int count = 0; + foreach (int j, s_outputDevicePriorities[cat]) { + QHash &props = s_outputDevices[j].properties; + logMessage(QString(" %1. %2 (Available: %3)").arg(++count).arg(props["name"].toString()).arg(props["available"].toBool())); + } + } + } + logMessage(QString("Capture Device Priority List:")); + for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) { + Phonon::Category cat = static_cast(i); + if (s_captureDevicePriorities.contains(cat)) { + logMessage(QString(" Phonon Category %1").arg(cat)); + int count = 0; + foreach (int j, s_captureDevicePriorities[cat]) { + QHash &props = s_captureDevices[j].properties; + logMessage(QString(" %1. %2 (Available: %3)").arg(++count).arg(props["name"].toString()).arg(props["available"].toBool())); + } + } + } + } + + if (!info) + return; + + Q_ASSERT(info->name); + Q_ASSERT(info->description); + Q_ASSERT(info->icon); + + // QString wrapper + QString name(info->name); + int index; + QMap > *new_prio_map_cats; // prio, device + QMap *new_devices; + + if (name.startsWith("sink:")) { + new_devices = &u->newOutputDevices; + new_prio_map_cats = &u->newOutputDevicePriorities; + + if (s_outputDeviceIndexes.contains(name)) + index = s_outputDeviceIndexes[name]; + else + index = s_outputDeviceIndexes[name] = s_deviceIndexCounter++; + } else if (name.startsWith("source:")) { + new_devices = &u->newCaptureDevices; + new_prio_map_cats = &u->newCaptureDevicePriorities; + + if (s_captureDeviceIndexes.contains(name)) + index = s_captureDeviceIndexes[name]; + else + index = s_captureDeviceIndexes[name] = s_deviceIndexCounter++; + } else { + // This indicates a bug in pulseaudio. + return; + } + + // Add the new device itself. + new_devices->insert(name, AudioDevice(name, info->description, info->icon, info->index)); + + // For each role in the priority, map it to a phonon category and store the order. + for (uint32_t i = 0; i < info->n_role_priorities; ++i) { + pa_ext_device_manager_role_priority_info* role_prio = &info->role_priorities[i]; + Q_ASSERT(role_prio->role); + + if (s_roleCategoryMap.contains(role_prio->role)) { + Phonon::Category cat = s_roleCategoryMap[role_prio->role]; + + (*new_prio_map_cats)[cat].insert(role_prio->priority, index); + } + } +} + +static void set_output_device(QString streamUuid) +{ + // If we only have one device, bail. This will be true if we are not using module-device-manager + if (s_outputDevices.size() < 2) + return; + + if (!s_outputStreamMoveQueue.contains(streamUuid)) + return; + + if (!s_outputStreamIndexMap.contains(streamUuid)) + return; + + if (s_outputStreamIndexMap[streamUuid] == PA_INVALID_INDEX) + return; + + int device = s_outputStreamMoveQueue[streamUuid]; + if (!s_outputDevices.contains(device)) + return; + + // We don't remove the uuid from the s_captureStreamMoveQueue + // as an application may reuse the phonon AudioOutput object + + uint32_t pulse_device_index = s_outputDevices[device].pulseIndex; + uint32_t pulse_stream_index = s_outputStreamIndexMap[streamUuid]; + + const QVariant var = s_outputDevices[device].properties["name"]; + logMessage(QString("Moving Pulse Sink Input %1 to '%2' (Pulse Sink %3)").arg(pulse_stream_index).arg(var.toString()).arg(pulse_device_index)); + + /// @todo Find a way to move the stream without saving it... We don't want to pollute the stream restore db. + pa_operation* o; + if (!(o = pa_context_move_sink_input_by_index(s_context, pulse_stream_index, pulse_device_index, NULL, NULL))) { + logMessage(QString("pa_context_move_sink_input_by_index() failed")); + return; + } + pa_operation_unref(o); +} + +static void set_capture_device(QString streamUuid) +{ + // If we only have one device, bail. This will be true if we are not using module-device-manager + if (s_captureDevices.size() < 2) + return; + + if (!s_captureStreamMoveQueue.contains(streamUuid)) + return; + + if (!s_captureStreamIndexMap.contains(streamUuid)) + return; + + if (s_captureStreamIndexMap[streamUuid] == PA_INVALID_INDEX) + return; + + int device = s_captureStreamMoveQueue[streamUuid]; + if (!s_captureDevices.contains(device)) + return; + + // We don't remove the uuid from the s_captureStreamMoveQueue + // as an application may reuse the phonon AudioCapture object (when it exists!) + + uint32_t pulse_device_index = s_captureDevices[device].pulseIndex; + uint32_t pulse_stream_index = s_captureStreamIndexMap[streamUuid]; + + const QVariant var = s_captureDevices[device].properties["name"]; + logMessage(QString("Moving Pulse Source Output %1 to '%2' (Pulse Sink %3)").arg(pulse_stream_index).arg(var.toString()).arg(pulse_device_index)); + + /// @todo Find a way to move the stream without saving it... We don't want to pollute the stream restore db. + pa_operation* o; + if (!(o = pa_context_move_source_output_by_index(s_context, pulse_stream_index, pulse_device_index, NULL, NULL))) { + logMessage(QString("pa_context_move_source_output_by_index() failed")); + return; + } + pa_operation_unref(o); +} + +void sink_input_cb(pa_context *c, const pa_sink_input_info *i, int eol, void *userdata) { + Q_UNUSED(userdata); + Q_ASSERT(c); + + if (eol < 0) { + if (pa_context_errno(c) == PA_ERR_NOENTITY) + return; + + logMessage(QString("Sink input callback failure")); + return; + } + + if (eol > 0) + return; + + Q_ASSERT(i); + + // loop through (*i) and extract phonon->streamindex... + const char *t; + if ((t = pa_proplist_gets(i->proplist, "phonon.streamid"))) { + logMessage(QString("Found PulseAudio stream index %1 for Phonon Output Stream %2").arg(i->index).arg(t)); + s_outputStreamIndexMap[QString(t)] = i->index; + // Process any pending moves... + set_output_device(QString(t)); + } +} + +void source_output_cb(pa_context *c, const pa_source_output_info *i, int eol, void *userdata) { + Q_UNUSED(userdata); + Q_ASSERT(c); + + if (eol < 0) { + if (pa_context_errno(c) == PA_ERR_NOENTITY) + return; + + logMessage(QString("Source output callback failure")); + return; + } + + if (eol > 0) + return; + + Q_ASSERT(i); + + // loop through (*i) and extract phonon->streamindex... + const char *t; + if ((t = pa_proplist_gets(i->proplist, "phonon.streamid"))) { + logMessage(QString("Found PulseAudio stream index %1 for Phonon Capture Stream %2").arg(i->index).arg(t)); + s_captureStreamIndexMap[QString(t)] = i->index; + // Process any pending moves... + set_capture_device(QString(t)); + } +} + +static void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata) { + Q_UNUSED(userdata); + + switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) { + case PA_SUBSCRIPTION_EVENT_SINK_INPUT: + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + QString phononid = s_outputStreamIndexMap.key(index); + if (!phononid.isEmpty()) { + if (s_outputStreamIndexMap.contains(phononid)) { + logMessage(QString("Phonon Output Stream %1 is gone at the PA end. Marking it as invalid in our cache as we may reuse it.").arg(phononid)); + s_outputStreamIndexMap[phononid] = PA_INVALID_INDEX; + } else { + logMessage(QString("Removing Phonon Output Stream %1 (it's gone!)").arg(phononid)); + s_outputStreamIndexMap.remove(phononid); + s_outputStreamMoveQueue.remove(phononid); + } + } + } else { + pa_operation *o; + if (!(o = pa_context_get_sink_input_info(c, index, sink_input_cb, NULL))) { + logMessage(QString("pa_context_get_sink_input_info() failed")); + return; + } + pa_operation_unref(o); + } + break; + + case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT: + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) { + QString phononid = s_captureStreamIndexMap.key(index); + if (!phononid.isEmpty()) { + if (s_captureStreamIndexMap.contains(phononid)) { + logMessage(QString("Phonon Capture Stream %1 is gone at the PA end. Marking it as invalid in our cache as we may reuse it.").arg(phononid)); + s_captureStreamIndexMap[phononid] = PA_INVALID_INDEX; + } else { + logMessage(QString("Removing Phonon Capture Stream %1 (it's gone!)").arg(phononid)); + s_captureStreamIndexMap.remove(phononid); + s_captureStreamMoveQueue.remove(phononid); + } + } + } else { + pa_operation *o; + if (!(o = pa_context_get_source_output_info(c, index, source_output_cb, NULL))) { + logMessage(QString("pa_context_get_sink_input_info() failed")); + return; + } + pa_operation_unref(o); + } + break; + } +} + + +static void ext_device_manager_subscribe_cb(pa_context *c, void *) { + Q_ASSERT(c); + + pa_operation *o; + PulseUserData *u = new PulseUserData; /** @todo Make some object to receive the info... */ + if (!(o = pa_ext_device_manager_read(c, ext_device_manager_read_cb, u))) { + // We need to deal with failure on first iteration + if (s_connectionEventloop) { + s_connectionEventloop->exit(0); + s_connectionEventloop = NULL; + } + logMessage(QString("pa_ext_device_manager_read() failed")); + return; + } + pa_operation_unref(o); + + + // Register for the stream changes... + pa_context_set_subscribe_callback(c, subscribe_cb, NULL); + + if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t) + (PA_SUBSCRIPTION_MASK_SINK_INPUT| + PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT), NULL, NULL))) { + logMessage(QString("pa_context_subscribe() failed")); + return; + } + pa_operation_unref(o); +} + +static void context_state_callback(pa_context *c, void *) +{ + Q_ASSERT(c); + + switch (pa_context_get_state(c)) { + case PA_CONTEXT_UNCONNECTED: + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + + case PA_CONTEXT_READY: + // Attempt to load things up + ext_device_manager_subscribe_cb(c, NULL); + break; + + case PA_CONTEXT_FAILED: + s_pulseActive = false; + if (s_connectionEventloop) { + s_connectionEventloop->exit(0); + s_connectionEventloop = NULL; + } + break; + + case PA_CONTEXT_TERMINATED: + default: + s_pulseActive = false; + /// @todo Deal with reconnection... + break; + } +} +#endif // HAVE_PULSEAUDIO + + +PulseSupport* PulseSupport::getInstance() +{ + if (NULL == s_instance) { + s_instance = new PulseSupport(); + } + return s_instance; +} + +void PulseSupport::shutdown() +{ + if (NULL != s_instance) { + delete s_instance; + s_instance = NULL; + } +} + +PulseSupport::PulseSupport() + : QObject() +{ +#ifdef HAVE_PULSEAUDIO + // Initialise our map (is there a better way to do this?) + s_roleCategoryMap["none"] = Phonon::NoCategory; + s_roleCategoryMap["video"] = Phonon::VideoCategory; + s_roleCategoryMap["music"] = Phonon::MusicCategory; + s_roleCategoryMap["game"] = Phonon::GameCategory; + s_roleCategoryMap["event"] = Phonon::NotificationCategory; + s_roleCategoryMap["phone"] = Phonon::CommunicationCategory; + //s_roleCategoryMap["animation"]; // No Mapping + //s_roleCategoryMap["production"]; // No Mapping + s_roleCategoryMap["a11y"] = Phonon::AccessibilityCategory; + + // To allow for easy debugging, give an easy way to disable this pulseaudio check + QString pulseenv = qgetenv("PHONON_PULSEAUDIO_DISABLE"); + if (pulseenv.toInt()) + return; + + s_mainloop = pa_glib_mainloop_new(NULL); + Q_ASSERT(s_mainloop); + pa_mainloop_api *api = pa_glib_mainloop_get_api(s_mainloop); + + // We create a simple event loop to allow the glib loop + // to iterate until we've connected or not to the server. + s_connectionEventloop = new QEventLoop; + + // XXX I don't want to show up in the client list. All I want to know is the list of sources + // and sinks... + s_context = pa_context_new(api, "libphonon"); + // (cg) Convert to PA_CONTEXT_NOFLAGS when PulseAudio 0.9.19 is required + if (pa_context_connect(s_context, NULL, static_cast(0), 0) >= 0) { + pa_context_set_state_callback(s_context, &context_state_callback, s_connectionEventloop); + // Now we block until we connect or otherwise... + s_connectionEventloop->exec(); + } +#endif +} + +PulseSupport::~PulseSupport() +{ +#ifdef HAVE_PULSEAUDIO + if (s_context) { + pa_context_disconnect(s_context); + s_context = NULL; + } + + if (s_mainloop) { + pa_glib_mainloop_free(s_mainloop); + s_mainloop = NULL; + } + + if (s_connectionEventloop) { + delete s_connectionEventloop; + s_connectionEventloop = NULL; + } +#endif +} + +bool PulseSupport::isActive() +{ +#ifdef HAVE_PULSEAUDIO + return s_pulseActive; +#else + return false; +#endif +} + +void PulseSupport::disable() +{ +#ifdef HAVE_PULSEAUDIO + s_pulseActive = false; +#endif +} + +QList PulseSupport::objectDescriptionIndexes(ObjectDescriptionType type) const +{ + QList list; + + if (type != AudioOutputDeviceType && type != AudioCaptureDeviceType) + return list; + +#ifdef HAVE_PULSEAUDIO + if (s_pulseActive) { + switch (type) { + + case AudioOutputDeviceType: { + QMap::iterator it; + for (it = s_outputDeviceIndexes.begin(); it != s_outputDeviceIndexes.end(); ++it) { + list.append(*it); + } + break; + } + case AudioCaptureDeviceType: { + QMap::iterator it; + for (it = s_captureDeviceIndexes.begin(); it != s_captureDeviceIndexes.end(); ++it) { + list.append(*it); + } + break; + } + default: + break; + } + } +#endif + + return list; +} + +QHash PulseSupport::objectDescriptionProperties(ObjectDescriptionType type, int index) const +{ + QHash ret; + + if (type != AudioOutputDeviceType && type != AudioCaptureDeviceType) + return ret; + +#ifndef HAVE_PULSEAUDIO + Q_UNUSED(index); +#else + if (s_pulseActive) { + switch (type) { + + case AudioOutputDeviceType: + Q_ASSERT(s_outputDevices.contains(index)); + ret = s_outputDevices[index].properties; + break; + + case AudioCaptureDeviceType: + Q_ASSERT(s_captureDevices.contains(index)); + ret = s_captureDevices[index].properties; + break; + + default: + break; + } + } +#endif + + return ret; +} + +QList PulseSupport::objectIndexesByCategory(ObjectDescriptionType type, Category category) const +{ + QList ret; + + if (type != AudioOutputDeviceType && type != AudioCaptureDeviceType) + return ret; + +#ifndef HAVE_PULSEAUDIO + Q_UNUSED(category); +#else + if (s_pulseActive) { + switch (type) { + + case AudioOutputDeviceType: + if (s_outputDevicePriorities.contains(category)) + ret = s_outputDevicePriorities[category].values(); + break; + + case AudioCaptureDeviceType: + if (s_captureDevicePriorities.contains(category)) + ret = s_captureDevicePriorities[category].values(); + break; + + default: + break; + } + } +#endif + + return ret; +} + +#ifdef HAVE_PULSEAUDIO +static void setDevicePriority(Category category, QStringList list) +{ + QString role = s_roleCategoryMap.key(category); + if (role.isEmpty()) + return; + + logMessage(QString("Reindexing %1: %2").arg(role).arg(list.join(", "))); + + char **devices; + devices = pa_xnew(char *, list.size()+1); + int i = 0; + foreach (QString str, list) { + devices[i++] = pa_xstrdup(str.toUtf8().constData()); + } + devices[list.size()] = NULL; + + pa_operation *o; + if (!(o = pa_ext_device_manager_reorder_devices_for_role(s_context, role.toUtf8().constData(), (const char**)devices, NULL, NULL))) + logMessage(QString("pa_ext_device_manager_reorder_devices_for_role() failed")); + else + pa_operation_unref(o); + + for (i = 0; i < list.size(); ++i) + pa_xfree(devices[i]); + pa_xfree(devices); +} +#endif + +void PulseSupport::setOutputDevicePriorityForCategory(Category category, QList order) +{ +#ifndef HAVE_PULSEAUDIO + Q_UNUSED(category); + Q_UNUSED(order); +#else + QStringList list; + QList::iterator it; + + for (it = order.begin(); it != order.end(); ++it) { + if (s_outputDevices.contains(*it)) { + list << s_outputDeviceIndexes.key(*it); + } + } + setDevicePriority(category, list); +#endif +} + +void PulseSupport::setCaptureDevicePriorityForCategory(Category category, QList order) +{ +#ifndef HAVE_PULSEAUDIO + Q_UNUSED(category); + Q_UNUSED(order); +#else + QStringList list; + QList::iterator it; + + for (it = order.begin(); it != order.end(); ++it) { + if (s_captureDevices.contains(*it)) { + list << s_captureDeviceIndexes.key(*it); + } + } + setDevicePriority(category, list); +#endif +} + +void PulseSupport::setStreamPropList(Category category, QString streamUuid) +{ +#ifndef HAVE_PULSEAUDIO + Q_UNUSED(category); + Q_UNUSED(streamUuid); +#else + QString role = s_roleCategoryMap.key(category); + if (role.isEmpty()) + return; + + logMessage(QString("Setting role to %1 for streamindex %2").arg(role).arg(streamUuid)); + setenv("PULSE_PROP_media.role", role.toLatin1().constData(), 1); + setenv("PULSE_PROP_phonon.streamid", streamUuid.toLatin1().constData(), 1); +#endif +} + +void PulseSupport::emitObjectDescriptionChanged(ObjectDescriptionType type) +{ + emit objectDescriptionChanged(type); +} + +bool PulseSupport::setOutputDevice(QString streamUuid, int device) { +#ifndef HAVE_PULSEAUDIO + Q_UNUSED(streamUuid); + Q_UNUSED(device); + return false; +#else + if (s_outputDevices.size() < 2) + return true; + + if (!s_outputDevices.contains(device)) { + logMessage(QString("Attempting to set Output Device for invalid device id %1.").arg(device)); + return false; + } + const QVariant var = s_outputDevices[device].properties["name"]; + logMessage(QString("Attempting to set Output Device to '%1' for Output Stream %2").arg(var.toString()).arg(streamUuid)); + + s_outputStreamMoveQueue[streamUuid] = device; + // Attempt to look up the pulse stream index. + if (s_outputStreamIndexMap.contains(streamUuid) && s_outputStreamIndexMap[streamUuid] != PA_INVALID_INDEX) { + logMessage(QString("... Found in map. Moving now")); + set_output_device(streamUuid); + } else { + logMessage(QString("... Not found in map. Saving move for when the stream appears")); + } + return true; +#endif +} + +bool PulseSupport::setCaptureDevice(QString streamUuid, int device) { +#ifndef HAVE_PULSEAUDIO + Q_UNUSED(streamUuid); + Q_UNUSED(device); + return false; +#else + if (s_captureDevices.size() < 2) + return true; + + if (!s_captureDevices.contains(device)) { + logMessage(QString("Attempting to set Capture Device for invalid device id %1.").arg(device)); + return false; + } + const QVariant var = s_captureDevices[device].properties["name"]; + logMessage(QString("Attempting to set Capture Device to '%1' for Capture Stream %2").arg(var.toString()).arg(streamUuid)); + + s_captureStreamMoveQueue[streamUuid] = device; + // Attempt to look up the pulse stream index. + if (s_captureStreamIndexMap.contains(streamUuid) && s_captureStreamIndexMap[streamUuid] == PA_INVALID_INDEX) { + logMessage(QString("... Found in map. Moving now")); + set_capture_device(streamUuid); + } else { + logMessage(QString("... Not found in map. Saving move for when the stream appears")); + } + return true; +#endif +} + +void PulseSupport::clearStreamCache(QString streamUuid) { +#ifndef HAVE_PULSEAUDIO + Q_UNUSED(streamUuid); + return; +#else + logMessage(QString("Clearing stream cache for stream %1").arg(streamUuid)); + s_outputStreamIndexMap.remove(streamUuid); + s_outputStreamMoveQueue.remove(streamUuid); + s_captureStreamIndexMap.remove(streamUuid); + s_captureStreamMoveQueue.remove(streamUuid); +#endif +} + +} // namespace Phonon + +QT_END_NAMESPACE + +// vim: sw=4 ts=4 diff --git a/src/3rdparty/phonon/phonon/pulsesupport.h b/src/3rdparty/phonon/phonon/pulsesupport.h new file mode 100644 index 0000000..434b559 --- /dev/null +++ b/src/3rdparty/phonon/phonon/pulsesupport.h @@ -0,0 +1,74 @@ +/* This file is part of the KDE project + Copyright (C) 2009 Colin Guthrie + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef PHONON_PULSESUPPORT_H +#define PHONON_PULSESUPPORT_H + +#include "phonon_export.h" +#include "phononnamespace.h" +#include "objectdescription.h" + +#include +#include + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace Phonon +{ + class PHONON_EXPORT PulseSupport : public QObject + { + Q_OBJECT + public: + static PulseSupport* getInstance(); + static void shutdown(); + + bool isActive(); + void disable(); + + QList objectDescriptionIndexes(ObjectDescriptionType type) const; + QHash objectDescriptionProperties(ObjectDescriptionType type, int index) const; + QList objectIndexesByCategory(ObjectDescriptionType type, Category category) const; + + void setOutputDevicePriorityForCategory(Category category, QList order); + void setCaptureDevicePriorityForCategory(Category category, QList order); + + void setStreamPropList(Category category, QString streamUuid); + void emitObjectDescriptionChanged(ObjectDescriptionType); + + bool setOutputDevice(QString streamUuid, int device); + bool setCaptureDevice(QString streamUuid, int device); + void clearStreamCache(QString streamUuid); + + signals: + void objectDescriptionChanged(ObjectDescriptionType); + private: + PulseSupport(); + ~PulseSupport(); + }; +} // namespace Phonon + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // PHONON_PULSESUPPORT_H + diff --git a/src/3rdparty/phonon/phonon/qsettingsgroup_p.h b/src/3rdparty/phonon/phonon/qsettingsgroup_p.h index 501fe37..ac7ca8d 100644 --- a/src/3rdparty/phonon/phonon/qsettingsgroup_p.h +++ b/src/3rdparty/phonon/phonon/qsettingsgroup_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -27,8 +27,6 @@ #include #include -#ifndef QT_NO_PHONON_SETTINGSGROUP - QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -89,6 +87,5 @@ class QSettingsGroup QT_END_NAMESPACE QT_END_HEADER -#endif //QT_NO_PHONON_SETTINGSGROUP #endif // PHONON_QSETTINGSGROUP_P_H diff --git a/src/3rdparty/phonon/phonon/seekslider.cpp b/src/3rdparty/phonon/phonon/seekslider.cpp index e1eea54..b5b25f0 100644 --- a/src/3rdparty/phonon/phonon/seekslider.cpp +++ b/src/3rdparty/phonon/phonon/seekslider.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/seekslider.h b/src/3rdparty/phonon/phonon/seekslider.h index 540079e..0005029 100644 --- a/src/3rdparty/phonon/phonon/seekslider.h +++ b/src/3rdparty/phonon/phonon/seekslider.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/seekslider_p.h b/src/3rdparty/phonon/phonon/seekslider_p.h index f4ed616..911ab25 100644 --- a/src/3rdparty/phonon/phonon/seekslider_p.h +++ b/src/3rdparty/phonon/phonon/seekslider_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -24,8 +24,8 @@ #define SEEKSLIDER_P_H #include "seekslider.h" +#include "swiftslider_p.h" #include -#include #include #include #include @@ -84,7 +84,7 @@ class SeekSliderPrivate void _k_currentSourceChanged(); QBoxLayout layout; - QSlider slider; + SwiftSlider slider; QLabel iconLabel; QPointer media; bool ticking; diff --git a/src/3rdparty/phonon/phonon/streaminterface.cpp b/src/3rdparty/phonon/phonon/streaminterface.cpp index 3646fc1..666cb1e 100644 --- a/src/3rdparty/phonon/phonon/streaminterface.cpp +++ b/src/3rdparty/phonon/phonon/streaminterface.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/streaminterface.h b/src/3rdparty/phonon/phonon/streaminterface.h index 10cc061..67df05d 100644 --- a/src/3rdparty/phonon/phonon/streaminterface.h +++ b/src/3rdparty/phonon/phonon/streaminterface.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/streaminterface_p.h b/src/3rdparty/phonon/phonon/streaminterface_p.h index cc41156..426c58d 100644 --- a/src/3rdparty/phonon/phonon/streaminterface_p.h +++ b/src/3rdparty/phonon/phonon/streaminterface_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/swiftslider.cpp b/src/3rdparty/phonon/phonon/swiftslider.cpp new file mode 100644 index 0000000..1e274aa --- /dev/null +++ b/src/3rdparty/phonon/phonon/swiftslider.cpp @@ -0,0 +1,103 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2008 Ricardo Villalba + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#include "swiftslider_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +#if !defined(QT_NO_PHONON_SEEKSLIDER) && !defined(QT_NO_PHONON_VOLUMESLIDER) + +namespace Phonon +{ + +SwiftSlider::SwiftSlider(Qt::Orientation orientation, QWidget * parent) + : QSlider(orientation, parent) +{ +} + +SwiftSlider::~SwiftSlider() +{ +} + +// Function copied from qslider.cpp +inline int SwiftSlider::pick(const QPoint &pt) const +{ + return orientation() == Qt::Horizontal ? pt.x() : pt.y(); +} + +// Function copied from qslider.cpp and modified to make it compile +int SwiftSlider::pixelPosToRangeValue(int pos) const +{ + QStyleOptionSlider opt; + initStyleOption(&opt); + QRect gr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, this); + QRect sr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this); + int sliderMin, sliderMax, sliderLength; + + if (orientation() == Qt::Horizontal) { + sliderLength = sr.width(); + sliderMin = gr.x(); + sliderMax = gr.right() - sliderLength + 1; + } else { + sliderLength = sr.height(); + sliderMin = gr.y(); + sliderMax = gr.bottom() - sliderLength + 1; + } + return QStyle::sliderValueFromPosition(minimum(), maximum(), pos - sliderMin, + sliderMax - sliderMin, opt.upsideDown); +} + +// Based on code from qslider.cpp +void SwiftSlider::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + QStyleOptionSlider opt; + initStyleOption(&opt); + const QRect sliderRect = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this); + const QPoint center = sliderRect.center() - sliderRect.topLeft(); + // to take half of the slider off for the setSliderPosition call we use the center - topLeft + + if (!sliderRect.contains(event->pos())) { + event->accept(); + + setSliderPosition(pixelPosToRangeValue(pick(event->pos() - center))); + triggerAction(SliderMove); + setRepeatAction(SliderNoAction); + } else { + QSlider::mousePressEvent(event); + } + } else { + QSlider::mousePressEvent(event); + } +} + +} // namespace Phonon + +#endif //QT_NO_PHONON_VOLUMESLIDER && QT_NO_PHONON_VOLUMESLIDER + +QT_END_NAMESPACE + +#include "moc_swiftslider_p.cpp" diff --git a/src/3rdparty/phonon/phonon/swiftslider_p.h b/src/3rdparty/phonon/phonon/swiftslider_p.h new file mode 100644 index 0000000..f1e9c88 --- /dev/null +++ b/src/3rdparty/phonon/phonon/swiftslider_p.h @@ -0,0 +1,68 @@ +/* This file is part of the KDE project + Copyright (C) 2006-2008 Ricardo Villalba + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), Nokia Corporation + (or its successors, if any) and the KDE Free Qt Foundation, which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . + +*/ + +#ifndef SWIFTSLIDER_H +#define SWIFTSLIDER_H + +#include + +QT_BEGIN_NAMESPACE + +#if !defined(QT_NO_PHONON_SEEKSLIDER) && !defined(QT_NO_PHONON_VOLUMESLIDER) + +namespace Phonon +{ + +/** \class SwiftSlider swiftslider_p.h Phonon/SwiftSlider + * \short Modified QSlider that allows sudden/quick moves instead of stepped moves ("Click'n'Go" QSlider) + * + * This is an internal class used by SeekSlider and VolumeSlider. + * + * Ricardo Villalba, the original author of MySlider.cpp (from the SMPlayer project) + * gave his permission for the inclusion of this code inside Phonon by + * switching MySlider.cpp to the LGPLv2.1+ license. + * See http://smplayer.svn.sourceforge.net/viewvc/smplayer/smplayer/trunk/src/myslider.cpp?revision=2406&view=markup + * + * The original discussion about a "Click'n'Go QSlider": http://lists.trolltech.com/qt-interest/2006-11/msg00363.html + * + * \ingroup PhononWidgets + */ +class SwiftSlider : public QSlider +{ + Q_OBJECT +public: + SwiftSlider(Qt::Orientation orientation, QWidget * parent); + ~SwiftSlider(); + +private: + void mousePressEvent(QMouseEvent *event); + inline int pick(const QPoint &pt) const; + int pixelPosToRangeValue(int pos) const; +}; + +} // namespace Phonon + +#endif //QT_NO_PHONON_VOLUMESLIDER && QT_NO_PHONON_VOLUMESLIDER + +QT_END_NAMESPACE + +#endif //SWIFTSLIDER_H diff --git a/src/3rdparty/phonon/phonon/videoplayer.cpp b/src/3rdparty/phonon/phonon/videoplayer.cpp index 8f76d4c..8851b05 100644 --- a/src/3rdparty/phonon/phonon/videoplayer.cpp +++ b/src/3rdparty/phonon/phonon/videoplayer.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/videoplayer.h b/src/3rdparty/phonon/phonon/videoplayer.h index 6da1d98..7970f04 100644 --- a/src/3rdparty/phonon/phonon/videoplayer.h +++ b/src/3rdparty/phonon/phonon/videoplayer.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/videowidget.cpp b/src/3rdparty/phonon/phonon/videowidget.cpp index 63f6899..4575dfd 100644 --- a/src/3rdparty/phonon/phonon/videowidget.cpp +++ b/src/3rdparty/phonon/phonon/videowidget.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -28,8 +28,9 @@ #include "phononnamespace_p.h" #include - -#define PHONON_INTERFACENAME VideoWidgetInterface +#define IFACES4 VideoWidgetInterface44 +#define IFACES0 VideoWidgetInterface, IFACES4 +#define PHONON_INTERFACENAME IFACES0 QT_BEGIN_NAMESPACE @@ -48,6 +49,8 @@ VideoWidget::VideoWidget(QWidget *parent) setMouseTracking(true); } + + VideoWidget::VideoWidget(VideoWidgetPrivate &dd, QWidget *parent) : QWidget(parent), Phonon::AbstractVideoOutput(dd) @@ -98,6 +101,15 @@ PHONON_INTERFACE_SETTER(setHue, hue, qreal) PHONON_INTERFACE_GETTER(qreal, saturation, d->saturation) PHONON_INTERFACE_SETTER(setSaturation, saturation, qreal) + +QImage VideoWidget::snapshot() const { + K_D(const VideoWidget); + ConstIface iface(d); + if(iface) return iface->snapshot(); + return QImage(); // TODO not implemented in VideoInterface +} + + void VideoWidget::setFullScreen(bool newFullScreen) { pDebug() << Q_FUNC_INFO << newFullScreen; diff --git a/src/3rdparty/phonon/phonon/videowidget.h b/src/3rdparty/phonon/phonon/videowidget.h index bde7333..804e61a 100644 --- a/src/3rdparty/phonon/phonon/videowidget.h +++ b/src/3rdparty/phonon/phonon/videowidget.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -172,6 +172,7 @@ class AbstractVideoOutput; qreal contrast() const; qreal hue() const; qreal saturation() const; + QImage snapshot() const; //TODO: bar colors property public Q_SLOTS: diff --git a/src/3rdparty/phonon/phonon/videowidget_p.h b/src/3rdparty/phonon/phonon/videowidget_p.h index c2434f2..3335135 100644 --- a/src/3rdparty/phonon/phonon/videowidget_p.h +++ b/src/3rdparty/phonon/phonon/videowidget_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/videowidgetinterface.h b/src/3rdparty/phonon/phonon/videowidgetinterface.h index 7ed8a8a..0c33956 100644 --- a/src/3rdparty/phonon/phonon/videowidgetinterface.h +++ b/src/3rdparty/phonon/phonon/videowidgetinterface.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -53,8 +53,21 @@ class VideoWidgetInterface //X virtual int overlayCapabilities() const = 0; //X virtual bool createOverlay(QWidget *widget, int type) = 0; }; + +class VideoWidgetInterface44 : public VideoWidgetInterface +{ + public: + virtual QImage snapshot() const = 0; +}; } +#ifdef PHONON_BACKEND_VERSION_4_4 +namespace Phonon { typedef VideoWidgetInterface44 VideoWidgetInterfaceLatest; } +#else +namespace Phonon { typedef VideoWidgetInterface VideoWidgetInterfaceLatest; } +#endif + +Q_DECLARE_INTERFACE(Phonon::VideoWidgetInterface44, "VideoWidgetInterface44.phonon.kde.org") Q_DECLARE_INTERFACE(Phonon::VideoWidgetInterface, "VideoWidgetInterface3.phonon.kde.org") #endif //QT_NO_PHONON_VIDEO diff --git a/src/3rdparty/phonon/phonon/volumefadereffect.cpp b/src/3rdparty/phonon/phonon/volumefadereffect.cpp index 066199e..15d34ee 100644 --- a/src/3rdparty/phonon/phonon/volumefadereffect.cpp +++ b/src/3rdparty/phonon/phonon/volumefadereffect.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/volumefadereffect.h b/src/3rdparty/phonon/phonon/volumefadereffect.h index 22f2137..528bffa 100644 --- a/src/3rdparty/phonon/phonon/volumefadereffect.h +++ b/src/3rdparty/phonon/phonon/volumefadereffect.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/volumefadereffect_p.h b/src/3rdparty/phonon/phonon/volumefadereffect_p.h index cdd4e00..7937e63 100644 --- a/src/3rdparty/phonon/phonon/volumefadereffect_p.h +++ b/src/3rdparty/phonon/phonon/volumefadereffect_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/volumefaderinterface.h b/src/3rdparty/phonon/phonon/volumefaderinterface.h index da4262b..8c6e3a4 100644 --- a/src/3rdparty/phonon/phonon/volumefaderinterface.h +++ b/src/3rdparty/phonon/phonon/volumefaderinterface.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/volumeslider.cpp b/src/3rdparty/phonon/phonon/volumeslider.cpp index 1888cb6..923f8d0 100644 --- a/src/3rdparty/phonon/phonon/volumeslider.cpp +++ b/src/3rdparty/phonon/phonon/volumeslider.cpp @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -85,7 +85,7 @@ VolumeSlider::~VolumeSlider() bool VolumeSlider::isMuteVisible() const { - return !k_ptr->muteButton.isHidden(); + return k_ptr->muteButton.isVisible(); } void VolumeSlider::setMuteVisible(bool visible) diff --git a/src/3rdparty/phonon/phonon/volumeslider.h b/src/3rdparty/phonon/phonon/volumeslider.h index 47863a8..f5ef34f 100644 --- a/src/3rdparty/phonon/phonon/volumeslider.h +++ b/src/3rdparty/phonon/phonon/volumeslider.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. diff --git a/src/3rdparty/phonon/phonon/volumeslider_p.h b/src/3rdparty/phonon/phonon/volumeslider_p.h index 6d8009a..623275f 100644 --- a/src/3rdparty/phonon/phonon/volumeslider_p.h +++ b/src/3rdparty/phonon/phonon/volumeslider_p.h @@ -6,7 +6,7 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), Trolltech ASA + successor approved by the membership of KDE e.V.), Nokia Corporation (or its successors, if any) and the KDE Free Qt Foundation, which shall act as a proxy defined in Section 6 of version 3 of the license. @@ -24,8 +24,8 @@ #define VOLUMESLIDER_P_H #include "volumeslider.h" +#include "swiftslider_p.h" #include -#include #include #include #include @@ -83,7 +83,7 @@ class VolumeSliderPrivate private: QBoxLayout layout; - QSlider slider; + SwiftSlider slider; QToolButton muteButton; QIcon volumeIcon; QIcon mutedIcon; diff --git a/src/phonon/phonon.pro b/src/phonon/phonon.pro index 0469839..f62e958 100644 --- a/src/phonon/phonon.pro +++ b/src/phonon/phonon.pro @@ -3,7 +3,7 @@ include(../qbase.pri) PHONON_MAJOR_VERSION = $${QT_MAJOR_VERSION} PHONON_MINOR_VERSION = 3 -PHONON_PATCH_VERSION = 1 +PHONON_PATCH_VERSION = 80 VERSION = $${PHONON_MAJOR_VERSION}.$${PHONON_MINOR_VERSION}.$${PHONON_PATCH_VERSION} DEPENDPATH += . @@ -21,6 +21,9 @@ HEADERS += $$PHONON_DIR/abstractaudiooutput.h \ $$PHONON_DIR/abstractvideooutput.h \ $$PHONON_DIR/abstractvideooutput_p.h \ $$PHONON_DIR/addoninterface.h \ + $$PHONON_DIR/audiodataoutput.h \ + $$PHONON_DIR/audiodataoutput_p.h \ + $$PHONON_DIR/audiodataoutputinterface.h \ $$PHONON_DIR/audiooutput.h \ $$PHONON_DIR/audiooutput_p.h \ $$PHONON_DIR/audiooutputinterface.h \ @@ -36,6 +39,7 @@ HEADERS += $$PHONON_DIR/abstractaudiooutput.h \ $$PHONON_DIR/effectwidget_p.h \ $$PHONON_DIR/factory_p.h \ $$PHONON_DIR/frontendinterface_p.h \ + $$PHONON_DIR/globalconfig.h \ $$PHONON_DIR/globalconfig_p.h \ $$PHONON_DIR/iodevicestream_p.h \ $$PHONON_DIR/mediacontroller.h \ @@ -59,11 +63,13 @@ HEADERS += $$PHONON_DIR/abstractaudiooutput.h \ $$PHONON_DIR/phononnamespace_p.h \ $$PHONON_DIR/platform_p.h \ $$PHONON_DIR/platformplugin.h \ + $$PHONON_DIR/pulsesupport.h \ $$PHONON_DIR/qsettingsgroup_p.h \ $$PHONON_DIR/seekslider.h \ $$PHONON_DIR/seekslider_p.h \ $$PHONON_DIR/streaminterface.h \ $$PHONON_DIR/streaminterface_p.h \ + $$PHONON_DIR/swiftslider_p.h \ $$PHONON_DIR/videoplayer.h \ $$PHONON_DIR/videowidget.h \ $$PHONON_DIR/videowidget_p.h \ @@ -73,35 +79,39 @@ HEADERS += $$PHONON_DIR/abstractaudiooutput.h \ $$PHONON_DIR/volumefaderinterface.h \ $$PHONON_DIR/volumeslider.h \ $$PHONON_DIR/volumeslider_p.h -SOURCES += $$PHONON_DIR/objectdescription.cpp \ - $$PHONON_DIR/objectdescriptionmodel.cpp \ - $$PHONON_DIR/phononnamespace.cpp \ - $$PHONON_DIR/mediasource.cpp \ - $$PHONON_DIR/abstractmediastream.cpp \ - $$PHONON_DIR/streaminterface.cpp \ - $$PHONON_DIR/mediaobject.cpp \ - $$PHONON_DIR/medianode.cpp \ - $$PHONON_DIR/path.cpp \ - $$PHONON_DIR/effectparameter.cpp \ - $$PHONON_DIR/effect.cpp \ - $$PHONON_DIR/volumefadereffect.cpp \ - $$PHONON_DIR/abstractaudiooutput.cpp \ + +SOURCES += $$PHONON_DIR/abstractaudiooutput.cpp \ $$PHONON_DIR/abstractaudiooutput_p.cpp \ - $$PHONON_DIR/audiooutput.cpp \ - $$PHONON_DIR/audiooutputinterface.cpp \ + $$PHONON_DIR/abstractmediastream.cpp \ $$PHONON_DIR/abstractvideooutput.cpp \ $$PHONON_DIR/abstractvideooutput_p.cpp \ + $$PHONON_DIR/audiodataoutput.cpp \ + $$PHONON_DIR/audiooutput.cpp \ + $$PHONON_DIR/audiooutputinterface.cpp \ $$PHONON_DIR/backendcapabilities.cpp \ - $$PHONON_DIR/globalconfig.cpp \ + $$PHONON_DIR/effect.cpp \ + $$PHONON_DIR/effectparameter.cpp \ + $$PHONON_DIR/effectwidget.cpp \ $$PHONON_DIR/factory.cpp \ - $$PHONON_DIR/platform.cpp \ + $$PHONON_DIR/globalconfig.cpp \ + $$PHONON_DIR/iodevicestream.cpp \ $$PHONON_DIR/mediacontroller.cpp \ - $$PHONON_DIR/videowidget.cpp \ - $$PHONON_DIR/videoplayer.cpp \ + $$PHONON_DIR/medianode.cpp \ + $$PHONON_DIR/mediaobject.cpp \ + $$PHONON_DIR/mediasource.cpp \ + $$PHONON_DIR/objectdescription.cpp \ + $$PHONON_DIR/objectdescriptionmodel.cpp \ + $$PHONON_DIR/path.cpp \ + $$PHONON_DIR/phononnamespace.cpp \ + $$PHONON_DIR/platform.cpp \ + $$PHONON_DIR/pulsesupport.cpp \ $$PHONON_DIR/seekslider.cpp \ - $$PHONON_DIR/volumeslider.cpp \ - $$PHONON_DIR/effectwidget.cpp \ - $$PHONON_DIR/iodevicestream.cpp + $$PHONON_DIR/streaminterface.cpp \ + $$PHONON_DIR/swiftslider.cpp \ + $$PHONON_DIR/videoplayer.cpp \ + $$PHONON_DIR/videowidget.cpp \ + $$PHONON_DIR/volumefadereffect.cpp \ + $$PHONON_DIR/volumeslider.cpp contains(QT_CONFIG, dbus) { QT += dbus