Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
18 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/3rdparty/phonon/gstreamer/CMakeLists.txt

    r561 r846  
    2020   include_directories(
    2121          ${CMAKE_CURRENT_BINARY_DIR}
    22           ${GSTREAMER_INCLUDE_DIR} 
     22          ${GSTREAMER_INCLUDE_DIR}
    2323          ${GLIB2_INCLUDE_DIR}
    2424      ${LIBXML2_INCLUDE_DIR}
     
    3535   set(phonon_gstreamer_SRCS
    3636      audiooutput.cpp
    37       artssink.cpp
    3837      backend.cpp
    3938      devicemanager.cpp
     
    5150      audioeffect.cpp
    5251      abstractrenderer.cpp
    53       x11renderer.cpp
    5452      widgetrenderer.cpp
    5553      glrenderer.cpp
    5654      volumefadereffect.cpp
     55      audiodataoutput.cpp
    5756      )
    5857
    59    find_package(Alsa)
    60    macro_ensure_version("0.10.22" ${GSTREAMER_VERSION} GSTREAMER_HAS_NONBLOCKING_ALSASINK)
     58   if(NOT WIN32)
     59      set(phonon_gstreamer_SRCS
     60          ${phonon_gstreamer_SRCS}
     61          artssink.cpp
     62          x11renderer.cpp)
     63      macro_optional_find_package(Alsa)
     64      macro_ensure_version("0.10.22" ${GSTREAMER_VERSION} GSTREAMER_HAS_NONBLOCKING_ALSASINK)
     65   endif(NOT WIN32)
    6166   if(ALSA_FOUND AND NOT GSTREAMER_HAS_NONBLOCKING_ALSASINK)
    6267      add_definitions(-DUSE_ALSASINK2)
     
    7984      target_link_libraries(phonon_gstreamer ${ASOUND_LIBRARY})
    8085   endif(ALSA_FOUND)
     86   if(USE_INSTALL_PLUGIN)
     87       target_link_libraries(phonon_gstreamer ${GSTREAMER_PLUGIN_PBUTILS_LIBRARIES})
     88   endif(USE_INSTALL_PLUGIN)
    8189
    8290   install(TARGETS phonon_gstreamer DESTINATION ${PLUGIN_INSTALL_DIR}/plugins/phonon_backend)
  • trunk/src/3rdparty/phonon/gstreamer/ConfigureChecks.cmake

    r2 r846  
    1818macro_optional_find_package(GStreamerPlugins)
    1919macro_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")
     20macro_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")
    2021
    2122macro_optional_find_package(GLIB2)
     
    3132macro_log_feature(OPENGL_FOUND "OpenGL" "OpenGL support is required to compile the gstreamer backend for Phonon" "" FALSE)
    3233
    33 if (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND)
     34if (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GSTREAMER_PLUGIN_AUDIO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND)
    3435   set(BUILD_PHONON_GSTREAMER TRUE)
    35 else (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND)
     36else (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GSTREAMER_PLUGIN_AUDIO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND)
    3637   set(BUILD_PHONON_GSTREAMER FALSE)
    37 endif (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND)
     38endif (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GSTREAMER_PLUGIN_AUDIO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND)
  • trunk/src/3rdparty/phonon/gstreamer/audiooutput.cpp

    r561 r846  
    126126{
    127127    m_backend->logMessage(Q_FUNC_INFO + QString::number(newDevice), Backend::Info, this);
     128
    128129    if (newDevice == m_device)
    129130        return true;
     
    136137
    137138    bool success = false;
    138     const QList<AudioDevice> deviceList = m_backend->deviceManager()->audioOutputDevices();
    139     int deviceIdx = -1;
    140     for (int i=0; i<deviceList.size(); i++) {
    141         if (deviceList.at(i).id == newDevice) {
    142             deviceIdx = i;
    143             break;
    144         }
    145     }
    146 
    147     if (m_audioSink && deviceIdx >= 0) {
     139    if (m_audioSink &&  newDevice >= 0) {
    148140        // Save previous state
    149141        GstState oldState = GST_STATE(m_audioSink);
    150142        const QByteArray oldDeviceValue = GstHelper::property(m_audioSink, "device");
    151         const QByteArray deviceId = deviceList.at(deviceIdx).gstId;
     143        const QByteArray deviceId = m_backend->deviceManager()->gstId(newDevice);
    152144        m_device = newDevice;
    153145
     
    171163        }
    172164
    173         // Note the stopped state should not really be neccessary, but seems to be required to
     165        // Note the stopped state should not really be necessary, but seems to be required to
    174166        // properly reset after changing the audio state
    175167        if (root()) {
  • trunk/src/3rdparty/phonon/gstreamer/backend.cpp

    r561 r846  
    1919#include "backend.h"
    2020#include "audiooutput.h"
     21#include "audiodataoutput.h"
    2122#include "audioeffect.h"
    2223#include "mediaobject.h"
     
    2728#include "volumefadereffect.h"
    2829#include <gst/interfaces/propertyprobe.h>
     30#include <phonon/pulsesupport.h>
    2931
    3032#include <QtCore/QSet>
     
    5052        , m_isValid(false)
    5153{
     54    // Initialise PulseAudio support
     55    PulseSupport *pulse = PulseSupport::getInstance();
     56    pulse->enable();
     57    connect(pulse, SIGNAL(objectDescriptionChanged(ObjectDescriptionType)), SIGNAL(objectDescriptionChanged(ObjectDescriptionType)));
     58
    5259    // In order to support reloading, we only set the app name once...
    5360    static bool first = true;
     
    5663        g_set_application_name(qApp->applicationName().toUtf8());
    5764    }
    58 
    5965    GError *err = 0;
    6066    bool wasInit = gst_init_check(0, 0, &err);  //init gstreamer: must be called before any gst-related functions
     
    9399Backend::~Backend()
    94100{
     101    delete m_effectManager;
     102    delete m_deviceManager;
     103    PulseSupport::shutdown();
    95104}
    96105
     
    120129        return new MediaObject(this, parent);
    121130
    122     case AudioOutputClass: {
    123             AudioOutput *ao = new AudioOutput(this, parent);
    124             m_audioOutputs.append(ao);
    125             return ao;
    126         }
     131    case AudioOutputClass:
     132        return new AudioOutput(this, parent);
     133
    127134#ifndef QT_NO_PHONON_EFFECT
    128135    case EffectClass:
     
    130137#endif //QT_NO_PHONON_EFFECT
    131138    case AudioDataOutputClass:
    132         logMessage("createObject() : AudioDataOutput not implemented");
    133         break;
     139        return new AudioDataOutput(this, parent);
    134140
    135141#ifndef QT_NO_PHONON_VIDEO
     
    215221        QString klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature));
    216222
    217         if (klass == QLatin1String("Codec/Decoder") ||
    218             klass == QLatin1String("Codec/Decoder/Audio") ||
    219             klass == QLatin1String("Codec/Decoder/Video") ||
    220             klass == QLatin1String("Codec/Demuxer") ||
    221             klass == QLatin1String("Codec/Demuxer/Audio") ||
    222             klass == QLatin1String("Codec/Demuxer/Video") ||
    223             klass == QLatin1String("Codec/Parser") ||
    224             klass == QLatin1String("Codec/Parser/Audio") ||
     223        if (klass == QLatin1String("Codec/Decoder") || 
     224            klass == QLatin1String("Codec/Decoder/Audio") || 
     225            klass == QLatin1String("Codec/Decoder/Video") || 
     226            klass == QLatin1String("Codec/Demuxer") || 
     227            klass == QLatin1String("Codec/Demuxer/Audio") || 
     228            klass == QLatin1String("Codec/Demuxer/Video") || 
     229            klass == QLatin1String("Codec/Parser") || 
     230            klass == QLatin1String("Codec/Parser/Audio") || 
    225231            klass == QLatin1String("Codec/Parser/Video")) {
    226232
     
    235241
    236242                    if (caps) {
    237                         const GstStructure* capsStruct = gst_caps_get_structure (caps, 0);
    238                         QString mime = QString::fromUtf8(gst_structure_get_name (capsStruct));
    239                         if (!availableMimeTypes.contains(mime))
    240                               availableMimeTypes.append(mime);
     243                        for (unsigned int struct_idx = 0; struct_idx < gst_caps_get_size (caps); struct_idx++) {
     244
     245                            const GstStructure* capsStruct = gst_caps_get_structure (caps, struct_idx);
     246                            QString mime = QString::fromUtf8(gst_structure_get_name (capsStruct));
     247                            if (!availableMimeTypes.contains(mime))
     248                                availableMimeTypes.append(mime);
     249                        }
    241250                    }
    242251                }
     
    245254    }
    246255    g_list_free(factoryList);
     256    if (availableMimeTypes.contains("audio/x-vorbis")
     257        && availableMimeTypes.contains("application/x-ogm-audio")) {
     258        if (!availableMimeTypes.contains("audio/x-vorbis+ogg"))
     259            availableMimeTypes.append("audio/x-vorbis+ogg");
     260        if (!availableMimeTypes.contains("application/ogg"))  /* *.ogg */
     261            availableMimeTypes.append("application/ogg");
     262        if (!availableMimeTypes.contains("audio/ogg")) /* *.oga */
     263            availableMimeTypes.append("audio/ogg");
     264    }
    247265    availableMimeTypes.sort();
    248266    return availableMimeTypes;
     
    294312    switch (type) {
    295313    case Phonon::AudioOutputDeviceType: {
    296             QList<AudioDevice> audioDevices = deviceManager()->audioOutputDevices();
    297             foreach(const AudioDevice &device, audioDevices) {
    298                 if (device.id == index) {
    299                     ret.insert("name", device.gstId);
    300                     ret.insert("description", device.description);
    301                     ret.insert("icon", QLatin1String("audio-card"));
    302                     break;
    303                 }
     314            AudioDevice* ad;
     315            if ((ad = deviceManager()->audioDevice(index))) {
     316                ret.insert("name", ad->gstId);
     317                ret.insert("description", ad->description);
     318                ret.insert("icon", ad->icon);
    304319            }
    305320        }
     
    430445/**
    431446 * Returns a debuglevel that is determined by the
    432  * PHONON_GSTREAMER_DEBUG environment variable.
     447 * PHONON_GST_DEBUG environment variable.
    433448 *
    434449 *  Warning - important warnings
  • trunk/src/3rdparty/phonon/gstreamer/backend.h

    r2 r846  
    8787private:
    8888    static gboolean busCall(GstBus *bus, GstMessage *msg, gpointer data);
    89     QList<QPointer<AudioOutput> > m_audioOutputs;
    9089
    9190    DeviceManager *m_deviceManager;
  • trunk/src/3rdparty/phonon/gstreamer/devicemanager.cpp

    r561 r846  
    2525#include "x11renderer.h"
    2626#include "artssink.h"
     27#include "pulsesupport.h"
    2728
    2829#ifdef USE_ALSASINK2
     
    4546        : gstId(gstId)
    4647{
    47     //get an id
    48     static int counter = 0;
    49     id = counter++;
     48    // This should never be called when PulseAudio is active.
     49    Q_ASSERT(!PulseSupport::getInstance()->isActive());
     50
     51    id = manager->allocateDeviceId();
     52    icon = "audio-card";
     53
    5054    //get name from device
    5155    if (gstId == "default") {
     
    7276        : QObject(backend)
    7377        , m_backend(backend)
    74 {
    75     m_audioSink = qgetenv("PHONON_GST_AUDIOSINK");
    76     m_videoSinkWidget = qgetenv("PHONON_GST_VIDEOMODE");
    77 
    78 #ifndef QT_NO_SETTINGS
     78        , m_audioDeviceCounter(0)
     79{
    7980    QSettings settings(QLatin1String("Trolltech"));
    8081    settings.beginGroup(QLatin1String("Qt"));
    8182
     83    PulseSupport *pulse = PulseSupport::getInstance();
     84    m_audioSink = qgetenv("PHONON_GST_AUDIOSINK");
    8285    if (m_audioSink.isEmpty()) {
    8386        m_audioSink = settings.value(QLatin1String("audiosink"), "Auto").toByteArray().toLower();
    84     }
    85 
     87        if (m_audioSink == "auto" && pulse->isActive())
     88            m_audioSink = "pulsesink";
     89    }
     90    if ("pulsesink" != m_audioSink)
     91        pulse->enable(false);
     92
     93    m_videoSinkWidget = qgetenv("PHONON_GST_VIDEOMODE");
    8694    if (m_videoSinkWidget.isEmpty()) {
    8795        m_videoSinkWidget = settings.value(QLatin1String("videomode"), "Auto").toByteArray().toLower();
    8896    }
    89 #endif //QT_NO_SETTINGS
    9097
    9198    if (m_backend->isValid())
     
    272279#endif //QT_NO_PHONON_VIDEO
    273280
    274 /*
    275  * Returns a positive device id or -1 if device
    276  * does not exist
     281/**
     282 * Allocate a device id for a new audio device
     283 */
     284int DeviceManager::allocateDeviceId()
     285{
     286    return m_audioDeviceCounter++;
     287}
     288
     289
     290/**
     291 * Returns a positive device id or -1 if device does not exist
    277292 *
    278293 * The gstId is typically in the format hw:1,0
     
    289304
    290305/**
    291  * Get a human-readable description from a device id
    292  */
    293 QByteArray DeviceManager::deviceDescription(int id) const
     306 * Returns a gstId or "default" if device does not exist
     307 *
     308 * The gstId is typically in the format hw:1,0
     309 */
     310const QByteArray DeviceManager::gstId(int deviceId)
     311{
     312    if (!PulseSupport::getInstance()->isActive()) {
     313        AudioDevice *ad = audioDevice(deviceId);
     314        if (ad)
     315            return QByteArray(ad->gstId);
     316    }
     317    return QByteArray("default");
     318}
     319
     320/**
     321* Get the AudioDevice for a given device id
     322*/
     323AudioDevice* DeviceManager::audioDevice(int id)
    294324{
    295325    for (int i = 0 ; i < m_audioDeviceList.size() ; ++i) {
    296         if (m_audioDeviceList[i].id == id) {
    297             return m_audioDeviceList[i].description;
    298         }
    299     }
    300     return QByteArray();
     326        if (m_audioDeviceList[i].id == id)
     327            return &m_audioDeviceList[i];
     328    }
     329    return NULL;
    301330}
    302331
     
    312341
    313342    if (audioSink) {
    314         list = GstHelper::extractProperties(audioSink, "device");
    315         list.prepend("default");
     343        if (!PulseSupport::getInstance()->isActive()) {
     344            // If we're using pulse, the PulseSupport class takes care of things for us.
     345            list = GstHelper::extractProperties(audioSink, "device");
     346            list.prepend("default");
     347        }
    316348
    317349        for (int i = 0 ; i < list.size() ; ++i) {
  • trunk/src/3rdparty/phonon/gstreamer/devicemanager.h

    r2 r846  
    4343    QByteArray gstId;
    4444    QByteArray description;
     45    QString icon;
    4546};
    4647
     
    5253    const QList<AudioDevice> audioOutputDevices() const;
    5354    GstPad *requestPad(int device) const;
     55    int allocateDeviceId();
    5456    int deviceId(const QByteArray &gstId) const;
    55     QByteArray deviceDescription(int id) const;
     57    const QByteArray gstId(int id);
     58    AudioDevice* audioDevice(int id);
    5659    GstElement *createGNOMEAudioSink(Category category);
    5760    GstElement *createAudioSink(Category category = NoCategory);
     
    6972    Backend *m_backend;
    7073    QList <AudioDevice> m_audioDeviceList;
     74    int m_audioDeviceCounter;
    7175    QTimer m_devicePollTimer;
    7276    QByteArray m_audioSink;
  • trunk/src/3rdparty/phonon/gstreamer/effectmanager.cpp

    r2 r846  
    5555            // "equalizer-nbands" not really useful at the moment
    5656
    57             // These plugins simply dont work or have major stability issues:
     57            // These plugins simply don't work or have major stability issues:
    5858            // "iir" Does not seem to do much at the moment
    5959            // "audioinvert" Only works for some streams, should be invesigated
  • trunk/src/3rdparty/phonon/gstreamer/glrenderer.cpp

    r2 r846  
    267267    setPalette(palette);
    268268    setAutoFillBackground(true);
    269     // Videowidget allways have this property to allow hiding the mouse cursor
     269    // Videowidget always have this property to allow hiding the mouse cursor
    270270    setMouseTracking(true);
    271271}
     
    305305        const QRectF r = drawFrameRect();
    306306
    307         const float v_array[] = { r.left(), r.top(), r.right(), r.top(), r.right(), r.bottom(), r.left(), r.bottom() };
     307        const float v_array[] = { float(r.left()), float(r.top()), float(r.right()), float(r.top()), float(r.right()), float(r.bottom()), float(r.left()), float(r.bottom()) };
    308308
    309309        glActiveTexture(GL_TEXTURE0);
  • trunk/src/3rdparty/phonon/gstreamer/gsthelper.cpp

    r2 r846  
    122122    GstElement *playbin = 0;
    123123    //init playbin and add to our pipeline
    124     playbin = gst_element_factory_make("playbin", NULL);
     124    playbin = gst_element_factory_make("playbin2", NULL);
    125125
    126126    //Create an identity element to redirect sound
  • trunk/src/3rdparty/phonon/gstreamer/gstreamer.desktop

    r2 r846  
    1111
    1212Name=GStreamer
     13Name[bg]=GStreamer
     14Name[ca]=GStreamer
     15Name[ca@valencia]=GStreamer
     16Name[cs]=GStreamer
     17Name[da]=GStreamer
     18Name[de]=GStreamer
     19Name[el]=GStreamer
     20Name[en_GB]=GStreamer
     21Name[es]=GStreamer
     22Name[et]=GStreamer
     23Name[eu]=GStreamer
     24Name[fi]=GStreamer
     25Name[fr]=GStreamer
     26Name[ga]=GStreamer
     27Name[gl]=GStreamer
     28Name[hsb]=GStreamer
     29Name[hu]=GStreamer
     30Name[id]=GStreamer
     31Name[is]=GStreamer
     32Name[it]=GStreamer
     33Name[ja]=GStreamer
     34Name[ko]=GStreamer
     35Name[ku]=GStreamer
     36Name[lt]=GStreamer
     37Name[lv]=GStreamer
     38Name[nb]=GStreamer
     39Name[nds]=GStreamer
     40Name[nl]=GStreamer
     41Name[nn]=GStreamer
    1342Name[pa]=àšœà©€àšžàšŸà©€àš°àš®àš°
     43Name[pl]=GStreamer
     44Name[pt]=GStreamer
     45Name[pt_BR]=GStreamer
     46Name[ru]=GStreamer
     47Name[se]=GStreamer
     48Name[sk]=GStreamer
     49Name[sl]=GStreamer
    1450Name[sr]=ГстрОЌер
     51Name[sr@ijekavian]=ГстрОЌер
     52Name[sr@ijekavianlatin]=GStreamer
     53Name[sr@latin]=GStreamer
    1554Name[sv]=Gstreamer
     55Name[tr]=GStreamer
     56Name[uk]=GStreamer
    1657Name[x-test]=xxGStreamerxx
     58Name[zh_CN]=GStreamer
     59Name[zh_TW]=GStreamer
    1760
    1861Comment=Phonon GStreamer backend
    1962Comment[bg]=Phonon GStreamer
    2063Comment[ca]=Dorsal GStreamer del Phonon
     64Comment[ca@valencia]=Dorsal GStreamer del Phonon
     65Comment[cs]=Phonon GStreamer backend
    2166Comment[da]=GStreamer-backend til Phonon
    2267Comment[de]=Phonon-Treiber fÃŒr GStreamer
     
    2469ποστήριΟης GStreamer τοÏ
    2570 Phonon
     71Comment[en_GB]=Phonon GStreamer backend
    2672Comment[es]=Motor GStreamer para Phonon
    2773Comment[et]=Phononi GStreameri taustaprogramm
     74Comment[eu]=Phonon GStreamer backend
     75Comment[fi]=Phonon GStreamer-taustaohjelma
    2876Comment[fr]=SystÚme de gestion GStreamer pour Phonon
    2977Comment[ga]=Inneall GStreamer le haghaidh Phonon
    3078Comment[gl]=Infraestrutura de GStreamer para Phonon
     79Comment[hsb]=Phonon GStreamer backend
     80Comment[hu]=Phonon GStreamer modul
     81Comment[id]=Phonon GStreamer backend
    3182Comment[is]=Phonon GStreamer bakendi
    3283Comment[it]=Motore Gstreamer di Phonon
     
    3485Comment[ko]=Phonon GStreamer 백엔드
    3586Comment[ku]=Binesaza Phonon GStreamer
     87Comment[lt]=Phonon GStreamer galinė sÄ
     88saja
    3689Comment[lv]=Phonon GStreamer aizmugure
     90Comment[nb]=Phonon-motor for GStreamer
    3791Comment[nds]=Phonon-HÃŒlpprogramm GStreamer
    3892Comment[nl]=GStreamer-backend (Phonon)
     
    4296Comment[pt]=Infra-estrutura do GStreamer para o Phonon
    4397Comment[pt_BR]=Infraestrutura Phonon GStreamer
     98Comment[ru]=МеÑ
     99аМОзЌ GStreamer Ўля Phonon
     100Comment[se]=Phonon GStreamer duogášmohtor
    44101Comment[sk]=GStreamer podsystém
    45102Comment[sl]=Phononova hrbtenica GStreamer
    46103Comment[sr]=ГстрОЌер каП пПзаЎОМа ЀПМПМа
     104Comment[sr@ijekavian]=ГстрОЌер каП пПзаЎОМа ЀПМПМа
     105Comment[sr@ijekavianlatin]=GStreamer kao pozadina Phonona
    47106Comment[sr@latin]=GStreamer kao pozadina Phonona
    48107Comment[sv]=Phonon Gstreamer-grÀnssnitt
  • trunk/src/3rdparty/phonon/gstreamer/medianode.cpp

    r2 r846  
    199199        // potential deadlock. Hence we force the pipeline into ready state
    200200        // before any nodes are disconnected.
    201         gst_element_set_state(root()->pipeline(), GST_STATE_READY);   
    202 
    203         Q_ASSERT(sink->root()); //sink has to have a root since it is onnected
     201        gst_element_set_state(root()->pipeline(), GST_STATE_READY);
     202
     203        Q_ASSERT(sink->root()); //sink has to have a root since it is connected
    204204
    205205        if (sink->description() & (AudioSink)) {
  • trunk/src/3rdparty/phonon/gstreamer/mediaobject.cpp

    r561 r846  
    1717#include <cmath>
    1818#include <gst/interfaces/propertyprobe.h>
     19#include <gst/pbutils/install-plugins.h>
    1920#include "common.h"
    2021#include "mediaobject.h"
     
    5455        , m_prefinishMark(0)
    5556        , m_transitionTime(0)
     57        , m_isStream(false)
    5658        , m_posAtSeek(-1)
    5759        , m_prefinishMarkReachedNotEmitted(true)
     
    8082        , m_availableTitles(0)
    8183        , m_currentTitle(1)
     84        , m_pendingTitle(1)
    8285{
    8386    qRegisterMetaType<GstCaps*>("GstCaps*");
     
    9699        connect(m_tickTimer, SIGNAL(timeout()), SLOT(emitTick()));
    97100    }
    98     connect(this, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
    99             this, SLOT(notifyStateChange(Phonon::State,Phonon::State)));
     101    connect(this, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
     102            this, SLOT(notifyStateChange(Phonon::State, Phonon::State)));
    100103
    101104}
     
    137140}
    138141
     142void
     143pluginInstallationDone( GstInstallPluginsReturn res, gpointer userData )
     144{
     145    // Nothing inside yet
     146    Q_UNUSED(res);
     147    Q_UNUSED(userData);
     148}
     149
    139150void MediaObject::saveState()
    140151{
     
    196207        bool canPlay = (m_hasAudio || m_videoStreamFound);
    197208        Phonon::ErrorType error = canPlay ? Phonon::NormalError : Phonon::FatalError;
     209#ifdef PLUGIN_INSTALL_API
     210        GstInstallPluginsContext *ctx = gst_install_plugins_context_new ();
     211        gchar *details[2];
     212        details[0] = m_missingCodecs[0].toLocal8Bit().data();
     213        details[1] = NULL;
     214        GstInstallPluginsReturn status;
     215
     216        status = gst_install_plugins_async( details, ctx, pluginInstallationDone, NULL );
     217        gst_install_plugins_context_free ( ctx );
     218
     219        if ( status != GST_INSTALL_PLUGINS_STARTED_OK )
     220        {
     221            if( status == GST_INSTALL_PLUGINS_HELPER_MISSING )
     222                setError(tr("Missing codec helper script assistant."), Phonon::FatalError );
     223            else
     224                setError(tr("Plugin codec installation failed for codec: %0")
     225                        .arg(m_missingCodecs[0].split("|")[3]), error);
     226        }
     227        m_missingCodecs.clear();
     228#else
     229        QString codecs = m_missingCodecs.join(", ");
     230
    198231        if (error == Phonon::NormalError && m_hasVideo && !m_videoStreamFound) {
    199232            m_hasVideo = false;
    200233            emit hasVideoChanged(false);
    201234        }
    202         QString codecs = m_missingCodecs.join(", ");
    203         setError(QString(tr("A required codec is missing. You need to install the following codec(s) to play this content: %0")).arg(codecs), error);
     235        setError(tr("A required codec is missing. You need to install the following codec(s) to play this content: %0").arg(codecs), error);
    204236        m_missingCodecs.clear();
     237#endif
    205238    }
    206239}
     
    249282
    250283    }
    251     media->addMissingCodecName(value);
     284
     285#ifdef PLUGIN_INSTALL_API
     286    QString plugins = QString("gstreamer|0.10|%0|%1|decoder-%2")
     287        .arg( qApp->applicationName() )
     288        .arg( value )
     289        .arg( QString::fromUtf8(gst_caps_to_string (caps) ) );
     290    media->addMissingCodecName( plugins );
     291#else
     292    media->addMissingCodecName( value );
     293#endif
    252294}
    253295
     
    310352            // Note that the notify::caps _must_ be installed after linking to work with Dapper
    311353            m_capsHandler = g_signal_connect(pad, "notify::caps", G_CALLBACK(notifyVideoCaps), this);
    312  
     354
    313355            if (!m_loading && !m_hasVideo) {
    314356                m_hasVideo = m_videoStreamFound;
     
    369411
    370412    // Create a new datasource based on the input URL
    371     QByteArray encoded_cstr_url = url.toEncoded();
     413    // add the 'file' scheme if it's missing; the double '/' is needed!
     414    QByteArray encoded_cstr_url = (url.scheme() == QLatin1String("") ?
     415                    "file://" + url.toEncoded() :
     416                    url.toEncoded());
    372417    m_datasource = gst_element_make_from_uri(GST_URI_SRC, encoded_cstr_url.constData(), (const char*)NULL);
    373418    if (!m_datasource)
     
    389434            m_backend->logMessage(QString("new device speed : 2X"), Backend::Info, this);
    390435        }
     436  }
     437
     438    /* make HTTP sources send extra headers so we get icecast
     439     * metadata in case the stream is an icecast stream */
     440    if (encoded_cstr_url.startsWith("http://")
     441        && g_object_class_find_property (G_OBJECT_GET_CLASS (m_datasource), "iradio-mode")) {
     442        g_object_set (m_datasource, "iradio-mode", TRUE, NULL);
     443        m_isStream = true;
    391444    }
    392445
     
    443496    gst_object_sink (GST_OBJECT (m_pipeline));
    444497
    445     m_decodebin = gst_element_factory_make ("decodebin", NULL);
     498    m_decodebin = gst_element_factory_make ("decodebin2", NULL);
    446499    g_signal_connect (m_decodebin, "new-decoded-pad", G_CALLBACK (&cb_newpad), this);
    447500    g_signal_connect (m_decodebin, "unknown-type", G_CALLBACK (&cb_unknown_type), this);
     
    647700        } else if (currentState == GST_STATE_PLAYING) {
    648701            changeState(Phonon::PlayingState);
    649         } else if (!m_atEndOfStream && gst_element_set_state(m_pipeline, GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE) {
     702        } else if (gst_element_set_state(m_pipeline, GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE) {
    650703            m_pendingState = Phonon::PlayingState;
    651704        } else {
     
    677730
    678731    Phonon::State oldState = m_state;
    679     m_state = newstate; // m_state must be set before emitting, since 
     732    m_state = newstate; // m_state must be set before emitting, since
    680733                        // Error state requires that state() will return the new value
    681734    m_pendingState = newstate;
     
    697750    case Phonon::StoppedState:
    698751        m_backend->logMessage("phonon state changed: Stopped", Backend::Info, this);
     752        // We must reset the pipeline when playing again
     753        m_resetNeeded = true;
    699754        m_tickTimer->stop();
    700755        break;
     
    862917    GstState state;
    863918    gst_element_set_state(m_pipeline, GST_STATE_NULL);
    864     gst_element_get_state (m_pipeline, &state, NULL, 2000);
     919    gst_element_get_state(m_pipeline, &state, NULL, 2000);
    865920
    866921    m_source = source;
     
    872927    changeState(Phonon::LoadingState);
    873928    m_loading = true;
    874     m_resetNeeded = false;
     929    // IMPORTANT: Honor the m_resetNeeded flag as it currently stands.
     930    // See https://qa.mandriva.com/show_bug.cgi?id=56807
     931    //m_resetNeeded = false;
    875932    m_resumeState = false;
    876933    m_pendingState = Phonon::StoppedState;
     
    885942    m_aboutToFinishEmitted = false;
    886943    m_error = NoError;
    887     m_errorString = QString();
    888    
     944    m_errorString.clear();
     945
    889946    m_bufferPercent = 0;
    890947    m_prefinishMarkReachedNotEmitted = true;
     
    895952    m_atEndOfStream = false;
    896953
    897     // Clear exising meta tags
     954    m_availableTitles = 0;
     955    m_pendingTitle = 1;
     956    m_currentTitle = 1;
     957
     958    // Clear existing meta tags
    898959    m_metaData.clear();
     960    m_isStream = false;
    899961
    900962    switch (source.type()) {
    901     case MediaSource::Url: {           
    902             if (createPipefromURL(source.url()))
    903                 m_loading = true;
    904             else
     963    case MediaSource::Url: {
     964            if (!createPipefromURL(source.url()))
    905965                setError(tr("Could not open media source."));
    906966        }
     
    908968
    909969    case MediaSource::LocalFile: {
    910             if (createPipefromURL(QUrl::fromLocalFile(source.fileName())))
    911                 m_loading = true;
    912             else
     970            if (!createPipefromURL(QUrl::fromLocalFile(source.fileName())))
    913971                setError(tr("Could not open media source."));
    914972        }
     
    923981
    924982    case MediaSource::Stream:
    925         if (createPipefromStream(source))
    926             m_loading = true;
    927         else
     983        if (!createPipefromStream(source))
    928984            setError(tr("Could not open media source."));
    929985        break;
     
    931987    case MediaSource::Disc:
    932988        {
    933             QString mediaUrl;
    934             switch (source.discType()) {
    935             case Phonon::NoDisc:
     989       QString mediaUrl;
     990       switch (source.discType()) {
     991       case Phonon::NoDisc:
    936992                qWarning() << "I should never get to see a MediaSource that is a disc but doesn't specify which one";
    937993                return;
     
    9491005                return;
    9501006            }
    951             if (!mediaUrl.isEmpty() && createPipefromURL(QUrl(mediaUrl)))
    952                 m_loading = true;
    953             else
     1007            if (mediaUrl.isEmpty() || !createPipefromURL(QUrl(mediaUrl)))
    9541008                setError(tr("Could not open media source."));
    9551009        }
     
    9671021    // We need to link this node to ensure that fake sinks are connected
    9681022    // before loading, otherwise the stream will be blocked
    969     if (m_loading)
    970         link();
     1023    link();
    9711024    beginLoad();
    9721025}
     
    10051058    }
    10061059
    1007     m_availableTitles = 1;
    1008     gint64 titleCount;
    1009     GstFormat format = gst_format_get_by_nick("track");
    1010     if (gst_element_query_duration (m_pipeline, &format, &titleCount)) {
     1060    if (m_source.discType() == Phonon::Cd) {
     1061        gint64 titleCount;
     1062        GstFormat format = gst_format_get_by_nick("track");
     1063        if (gst_element_query_duration (m_pipeline, &format, &titleCount)) {
    10111064        //check if returned format is still "track",
    10121065        //gstreamer sometimes returns the total time, if tracks information is not available.
    1013         if (qstrcmp(gst_format_get_name(format), "track") == 0)  {
    1014             int oldAvailableTitles = m_availableTitles;
    1015             m_availableTitles = (int)titleCount;
    1016             if (m_availableTitles != oldAvailableTitles) {
    1017                 emit availableTitlesChanged(m_availableTitles);
    1018                 m_backend->logMessage(QString("Available titles changed: %0").arg(m_availableTitles), Backend::Info, this);
     1066            if (qstrcmp(gst_format_get_name(format), "track") == 0)  {
     1067                int oldAvailableTitles = m_availableTitles;
     1068                m_availableTitles = (int)titleCount;
     1069                if (m_availableTitles != oldAvailableTitles) {
     1070                    emit availableTitlesChanged(m_availableTitles);
     1071                    m_backend->logMessage(QString("Available titles changed: %0").arg(m_availableTitles), Backend::Info, this);
     1072                }
    10191073            }
    10201074        }
    10211075    }
    1022 
    10231076}
    10241077
     
    10781131
    10791132        quint64 current = currentTime();
    1080         quint64 total = totalTime(); 
     1133        quint64 total = totalTime();
    10811134
    10821135        if (current < total - m_prefinishMark)
     
    10991152    if (m_tickInterval > 0 && currentTime != m_previousTickTime) {
    11001153        emit tick(currentTime);
    1101         m_previousTickTime = currentTime;       
     1154        m_previousTickTime = currentTime;
    11021155    }
    11031156    if (m_state == Phonon::PlayingState) {
     
    11101163        // Prepare load of next source
    11111164        if (currentTime >= totalTime - ABOUT_TO_FINNISH_TIME) {
    1112             if (!m_aboutToFinishEmitted) {
     1165            if (m_source.type() == MediaSource::Disc &&
     1166                m_autoplayTitles &&
     1167                m_availableTitles > 1 &&
     1168                m_currentTitle < m_availableTitles) {
     1169                m_aboutToFinishEmitted = false;
     1170            } else if (!m_aboutToFinishEmitted) {
    11131171                m_aboutToFinishEmitted = true; // track is about to finish
    11141172                emit aboutToFinish();
     
    12141272    switch (GST_MESSAGE_TYPE (gstMessage)) {
    12151273
    1216     case GST_MESSAGE_EOS: 
    1217         m_backend->logMessage("EOS recieved", Backend::Info, this);
     1274    case GST_MESSAGE_EOS:
     1275        m_backend->logMessage("EOS received", Backend::Info, this);
    12181276        handleEndOfStream();
    12191277        break;
     
    12231281            gst_message_parse_tag(gstMessage, &tag_list);
    12241282            if (tag_list) {
     1283                TagMap newTags;
     1284                gst_tag_list_foreach (tag_list, &foreach_tag_function, &newTags);
     1285                gst_tag_list_free(tag_list);
     1286
     1287                // Determine if we should no fake the album/artist tags.
     1288                // This is a little confusing as we want to fake it on initial
     1289                // connection where title, album and artist are all missing.
     1290                // There are however times when we get just other information,
     1291                // e.g. codec, and so we want to only do clever stuff if we
     1292                // have a commonly available tag (ORGANIZATION) or we have a
     1293                // change in title
     1294                bool fake_it =
     1295                   (m_isStream
     1296                    && ((!newTags.contains("TITLE")
     1297                         && newTags.contains("ORGANIZATION"))
     1298                        || (newTags.contains("TITLE")
     1299                            && m_metaData.value("TITLE") != newTags.value("TITLE")))
     1300                    && !newTags.contains("ALBUM")
     1301                    && !newTags.contains("ARTIST"));
     1302
    12251303                TagMap oldMap = m_metaData; // Keep a copy of the old one for reference
    1226                 // Append any new meta tags to the existing tag list
    1227                 gst_tag_list_foreach (tag_list, &foreach_tag_function, &m_metaData);
     1304
     1305                // Now we've checked the new data, append any new meta tags to the existing tag list
     1306                // We cannot use TagMap::iterator as this is a multimap and when streaming data
     1307                // could in theory be lost.
     1308                QList<QString> keys = newTags.keys();
     1309                for (QList<QString>::iterator i = keys.begin(); i != keys.end(); ++i) {
     1310                    QString key = *i;
     1311                    if (m_isStream) {
     1312                        // If we're streaming, we need to remove data in m_metaData
     1313                        // in order to stop it filling up indefinitely (as it's a multimap)
     1314                        m_metaData.remove(key);
     1315                    }
     1316                    QList<QString> values = newTags.values(key);
     1317                    for (QList<QString>::iterator j = values.begin(); j != values.end(); ++j) {
     1318                        QString value = *j;
     1319                        QString currVal = m_metaData.value(key);
     1320                        if (!m_metaData.contains(key) || currVal != value) {
     1321                            m_metaData.insert(key, value);
     1322                        }
     1323                    }
     1324                }
     1325
    12281326                m_backend->logMessage("Meta tags found", Backend::Info, this);
    1229                 if (oldMap != m_metaData && !m_loading)
    1230                     emit metaDataChanged(m_metaData);
    1231                 gst_tag_list_free(tag_list);
    1232             }
     1327                if (oldMap != m_metaData) {
     1328                    // This is a bit of a hack to ensure that stream metadata is
     1329                    // returned. We get as much as we can from the Shoutcast server's
     1330                    // StreamTitle= header. If further info is decoded from the stream
     1331                    // itself later, then it will overwrite this info.
     1332                    if (m_isStream && fake_it) {
     1333                        m_metaData.remove("ALBUM");
     1334                        m_metaData.remove("ARTIST");
     1335
     1336                        // Detect whether we want to "fill in the blanks"
     1337                        QString str;
     1338                        if (m_metaData.contains("TITLE"))
     1339                        {
     1340                            str = m_metaData.value("TITLE");
     1341                            int splitpoint;
     1342                            // Check to see if our title matches "%s - %s"
     1343                            // Where neither %s are empty...
     1344                            if ((splitpoint = str.indexOf(" - ")) > 0
     1345                                && str.size() > (splitpoint+3)) {
     1346                                m_metaData.insert("ARTIST", str.left(splitpoint));
     1347                                m_metaData.replace("TITLE", str.mid(splitpoint+3));
     1348                            }
     1349                        } else {
     1350                            str = m_metaData.value("GENRE");
     1351                            if (!str.isEmpty())
     1352                                m_metaData.insert("TITLE", str);
     1353                            else
     1354                                m_metaData.insert("TITLE", "Streaming Data");
     1355                        }
     1356                        if (!m_metaData.contains("ARTIST")) {
     1357                            str = m_metaData.value("LOCATION");
     1358                            if (!str.isEmpty())
     1359                                m_metaData.insert("ARTIST", str);
     1360                            else
     1361                                m_metaData.insert("ARTIST", "Streaming Data");
     1362                        }
     1363                        str = m_metaData.value("ORGANIZATION");
     1364                        if (!str.isEmpty())
     1365                            m_metaData.insert("ALBUM", str);
     1366                        else
     1367                            m_metaData.insert("ALBUM", "Streaming Data");
     1368                    }
     1369                    // As we manipulate the title, we need to recompare
     1370                    // oldMap and m_metaData here...
     1371                    if (oldMap != m_metaData && !m_loading)
     1372                        emit metaDataChanged(m_metaData);
     1373                }
     1374                        }
    12331375        }
    12341376        break;
     
    12561398                m_tickTimer->start();
    12571399                changeState(Phonon::PlayingState);
     1400                if ((m_source.type() == MediaSource::Disc) && (m_currentTitle != m_pendingTitle)) {
     1401                    setTrack(m_pendingTitle);
     1402                }
    12581403                if (m_resumeState && m_oldState == Phonon::PlayingState) {
    12591404                    seek(m_oldPos);
     
    12911436                m_backend->logMessage("gstreamer: pipeline state set to ready", Backend::Debug, this);
    12921437                m_tickTimer->stop();
     1438                if ((m_source.type() == MediaSource::Disc) && (m_currentTitle != m_pendingTitle)) {
     1439                    setTrack(m_pendingTitle);
     1440                }
    12931441                break;
    12941442
     
    13291477                        gst_caps_unref (caps);
    13301478                        gst_object_unref (sinkPad);
    1331                    } 
     1479                   }
    13321480               } else {
    13331481                    setError(QString(err->message), Phonon::FatalError);
     
    14011549        //case GST_MESSAGE_LATENCY: only from 0.10.12
    14021550        //case GST_MESSAGE_ASYNC_DONE: only from 0.10.13
    1403     default: 
    1404         break; 
     1551    default:
     1552        break;
    14051553    }
    14061554}
     
    14181566        m_atEndOfStream = true;
    14191567
    1420     if (m_autoplayTitles &&
     1568    if (m_source.type() == MediaSource::Disc &&
     1569        m_autoplayTitles &&
    14211570        m_availableTitles > 1 &&
    14221571        m_currentTitle < m_availableTitles) {
     
    14421591                setState(m_pendingState);
    14431592        }
     1593    }
     1594}
     1595
     1596void MediaObject::invalidateGraph()
     1597{
     1598    m_resetNeeded = true;
     1599    if (m_state == Phonon::PlayingState || m_state == Phonon::PausedState) {
     1600        changeState(Phonon::StoppedState);
    14441601    }
    14451602}
     
    15031660void MediaObject::_iface_setCurrentTitle(int title)
    15041661{
     1662    m_backend->logMessage(QString("setCurrentTitle %0").arg(title), Backend::Info, this);
     1663    if ((title == m_currentTitle) || (title == m_pendingTitle))
     1664        return;
     1665
     1666    m_pendingTitle = title;
     1667
     1668    if (m_state == Phonon::PlayingState || m_state == Phonon::StoppedState) {
     1669        setTrack(m_pendingTitle);
     1670    } else {
     1671        setState(Phonon::StoppedState);
     1672    }
     1673}
     1674
     1675void MediaObject::setTrack(int title)
     1676{
     1677    if (((m_state != Phonon::PlayingState) && (m_state != Phonon::StoppedState)) || (title < 1) || (title > m_availableTitles))
     1678        return;
     1679
     1680
     1681    //let's seek to the beginning of the song
    15051682    GstFormat trackFormat = gst_format_get_by_nick("track");
    1506     m_backend->logMessage(QString("setCurrentTitle %0").arg(title), Backend::Info, this);
    1507     if ((title == m_currentTitle) || (title < 1) || (title > m_availableTitles))
    1508         return;
    1509 
    1510     m_currentTitle = title;
    1511 
    1512     //let's seek to the beginning of the song
    1513     if (gst_element_seek_simple(m_pipeline, trackFormat, GST_SEEK_FLAG_FLUSH, m_currentTitle - 1)) {
     1683    m_backend->logMessage(QString("setTrack %0").arg(title), Backend::Info, this);
     1684    if (gst_element_seek_simple(m_pipeline, trackFormat, GST_SEEK_FLAG_FLUSH, title - 1)) {
     1685        m_currentTitle = title;
    15141686        updateTotalTime();
    15151687        m_atEndOfStream = false;
  • trunk/src/3rdparty/phonon/gstreamer/mediaobject.h

    r2 r846  
    5656{
    5757    friend class Stream;
     58    friend class AudioDataOutput;
    5859    Q_OBJECT
    5960    Q_INTERFACES(Phonon::MediaObjectInterface
     
    145146    void handleEndOfStream();
    146147    void addMissingCodecName(const QString &codec) { m_missingCodecs.append(codec); }
    147     void invalidateGraph() {
    148         m_resetNeeded = true;
    149         if (m_state == Phonon::PlayingState || m_state == Phonon::PausedState) {
    150             changeState(Phonon::StoppedState);
    151         }
    152     }
     148    void invalidateGraph();
     149
    153150    static void cb_newpad (GstElement *decodebin, GstPad *pad, gboolean last, gpointer data);
    154151    static void cb_pad_added (GstElement *decodebin, GstPad *pad, gpointer data);
     
    237234    int _iface_currentTitle() const;
    238235    void _iface_setCurrentTitle(int title);
     236    void setTrack(int title);
    239237
    240238    bool m_resumeState;
     
    251249    qint32 m_prefinishMark;
    252250    qint32 m_transitionTime;
     251        bool m_isStream;
    253252
    254253    qint64 m_posAtSeek;
     
    286285    int m_availableTitles;
    287286    int m_currentTitle;
     287    int m_pendingTitle;
    288288};
    289289}
  • trunk/src/3rdparty/phonon/gstreamer/qwidgetvideosink.h

    r2 r846  
    2020
    2121#include "common.h"
     22#include "qwidgetvideosink.h"
    2223
    2324#include <QtCore/QByteArray>
  • trunk/src/3rdparty/phonon/gstreamer/videowidget.h

    r561 r846  
    2626#include "medianode.h"
    2727#include "abstractrenderer.h"
     28#include "videowidget.h"
    2829
    2930#include <gst/gst.h>
  • trunk/src/3rdparty/phonon/gstreamer/x11renderer.cpp

    r2 r846  
    9191            videoSink = 0;
    9292        } else {
    93             // Note that this should not really be neccessary as these are
     93            // Note that this should not really be necessary as these are
    9494            // default values, though under certain conditions values are retained
    9595            // even between application instances. (reproducible on 0.10.16/Gutsy)
     
    139139{
    140140    Q_UNUSED(movieSize);
     141
    141142    if (m_renderWidget) {
    142143        m_renderWidget->setGeometry(m_videoWidget->calculateDrawFrameRect());
Note: See TracChangeset for help on using the changeset viewer.