src/3rdparty/phonon/gstreamer/phononsrc.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /*  This file is part of the KDE project.
       
     2 
       
     3 Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 
       
     5 This library is free software: you can redistribute it and/or modify
       
     6 it under the terms of the GNU Lesser General Public License as published by
       
     7 the Free Software Foundation, either version 2.1 or 3 of the License.
       
     8 
       
     9 This library is distributed in the hope that it will be useful,
       
    10 but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12 GNU Lesser General Public License for more details.
       
    13 
       
    14 You should have received a copy of the GNU Lesser General Public License
       
    15 along with this library.  If not, see <http://www.gnu.org/licenses/>.
       
    16 */
       
    17 
       
    18 #include <gst/gst.h>
       
    19 #include <gst/base/gstbasesrc.h>
       
    20 #include "phononsrc.h"
       
    21 #include "streamreader.h"
       
    22 
       
    23 QT_BEGIN_NAMESPACE
       
    24 
       
    25 namespace Phonon
       
    26 {
       
    27 namespace Gstreamer
       
    28 {
       
    29 
       
    30 static GstStaticPadTemplate srctemplate =
       
    31        GST_STATIC_PAD_TEMPLATE ("src",
       
    32                                 GST_PAD_SRC,
       
    33                                 GST_PAD_ALWAYS,
       
    34                                 GST_STATIC_CAPS_ANY);
       
    35 
       
    36 GST_DEBUG_CATEGORY_STATIC (phonon_src_debug);
       
    37 
       
    38 // PhononSrc args
       
    39 enum
       
    40 {
       
    41     ARG_0,
       
    42     ARG_PHONONSRC
       
    43 };
       
    44 
       
    45 static void phonon_src_finalize (GObject * object);
       
    46 
       
    47 static void phonon_src_set_property (GObject * object, guint prop_id,
       
    48                                         const GValue * value, GParamSpec * pspec);
       
    49 static void phonon_src_get_property (GObject * object, guint prop_id,
       
    50                                         GValue * value, GParamSpec * pspec);
       
    51 
       
    52 static gboolean phonon_src_start (GstBaseSrc * basesrc);
       
    53 static gboolean phonon_src_stop (GstBaseSrc * basesrc);
       
    54 
       
    55 static gboolean phonon_src_is_seekable (GstBaseSrc * src);
       
    56 static gboolean phonon_src_get_size (GstBaseSrc * src, guint64 * size);
       
    57 static GstFlowReturn phonon_src_create (GstBaseSrc * src, guint64 offset,
       
    58                                            guint length, GstBuffer ** buffer);
       
    59 
       
    60 static void _do_init (GType filesrc_type)
       
    61 {
       
    62     Q_UNUSED(filesrc_type);
       
    63     GST_DEBUG_CATEGORY_INIT (phonon_src_debug, "phononsrc", 0, "QIODevice element");
       
    64 }
       
    65 
       
    66 GST_BOILERPLATE_FULL (PhononSrc, phonon_src, GstBaseSrc, GST_TYPE_BASE_SRC, _do_init)
       
    67 
       
    68 // Register element details
       
    69 static void phonon_src_base_init (gpointer g_class) {
       
    70     GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
       
    71     static gchar longname[] = "Phonon Stream Source",
       
    72                     klass[] = "Source/File",
       
    73               description[] = "Read from a Phonon StreamInterface",
       
    74                    author[] = "Nokia Corporation and/or its subsidiary(-ies) <qt-info@nokia.com>";
       
    75     GstElementDetails details = GST_ELEMENT_DETAILS (longname,
       
    76                                           klass,
       
    77                                           description,
       
    78                                           author);
       
    79     gst_element_class_set_details (gstelement_class, &details);
       
    80     gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&srctemplate));
       
    81 }
       
    82 
       
    83 static void phonon_src_class_init (PhononSrcClass * klass)
       
    84 {
       
    85     GObjectClass *gobject_class;
       
    86     GstElementClass *gstelement_class;
       
    87     GstBaseSrcClass *gstbasesrc_class;
       
    88 
       
    89     gobject_class = G_OBJECT_CLASS (klass);
       
    90     gstelement_class = GST_ELEMENT_CLASS (klass);
       
    91     gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
       
    92 
       
    93     gobject_class->set_property = phonon_src_set_property;
       
    94     gobject_class->get_property = phonon_src_get_property;
       
    95 
       
    96     g_object_class_install_property (gobject_class, ARG_PHONONSRC,
       
    97                                      g_param_spec_pointer ("iodevice", "A Phonon StreamReader",
       
    98                                      "A Phonon::GStreamer::StreamReader to read from", GParamFlags(G_PARAM_READWRITE)));
       
    99 
       
   100     gobject_class->finalize = GST_DEBUG_FUNCPTR (phonon_src_finalize);
       
   101 
       
   102     gstbasesrc_class->start = GST_DEBUG_FUNCPTR (phonon_src_start);
       
   103     gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (phonon_src_stop);
       
   104     gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (phonon_src_is_seekable);
       
   105     gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (phonon_src_get_size);
       
   106     gstbasesrc_class->create = GST_DEBUG_FUNCPTR (phonon_src_create);
       
   107 }
       
   108 
       
   109 static void phonon_src_init (PhononSrc * src, PhononSrcClass * g_class)
       
   110 {
       
   111     Q_UNUSED(g_class);
       
   112     src->device = 0;
       
   113 }
       
   114 
       
   115 static void phonon_src_finalize (GObject * object)
       
   116 {
       
   117     PhononSrc *src;
       
   118     src = GST_PHONON_SRC (object);
       
   119     delete src->device;
       
   120     src->device = 0;
       
   121     G_OBJECT_CLASS (parent_class)->finalize (object);
       
   122 }
       
   123 
       
   124 static gboolean phonon_src_set_device(PhononSrc * src, StreamReader* device)
       
   125 {
       
   126     GstState state;
       
   127     // The element must be stopped in order to do this
       
   128     GST_OBJECT_LOCK (src);
       
   129     state = GST_STATE (src);
       
   130 
       
   131     if (state != GST_STATE_READY && state != GST_STATE_NULL)
       
   132         goto wrong_state;
       
   133 
       
   134     GST_OBJECT_UNLOCK (src);
       
   135 
       
   136     src->device = device;
       
   137     g_object_notify (G_OBJECT (src), "iodevice");
       
   138     return TRUE;
       
   139 
       
   140     // Error
       
   141 wrong_state:
       
   142     {
       
   143         //GST_DEBUG_OBJECT (src, "setting location in wrong state");
       
   144         GST_OBJECT_UNLOCK (src);
       
   145         return FALSE;
       
   146     }
       
   147 }
       
   148 
       
   149 static void phonon_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
       
   150 {
       
   151     PhononSrc *src;
       
   152     g_return_if_fail (GST_IS_PHONON_SRC (object));
       
   153     src = GST_PHONON_SRC (object);
       
   154 
       
   155     switch (prop_id) {
       
   156     case ARG_PHONONSRC:
       
   157     {
       
   158         StreamReader *dev = (StreamReader*)(g_value_get_pointer(value));
       
   159         if (dev)
       
   160             phonon_src_set_device(src, dev);
       
   161         break;
       
   162     }
       
   163    default:
       
   164        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
   165        break;
       
   166    }
       
   167 }
       
   168 
       
   169 static void phonon_src_get_property (GObject * object, guint prop_id, GValue * value,
       
   170                                         GParamSpec * pspec)
       
   171 {
       
   172     PhononSrc *src;
       
   173     g_return_if_fail (GST_IS_PHONON_SRC (object));
       
   174     src = GST_PHONON_SRC (object);
       
   175 
       
   176     switch (prop_id) {
       
   177     case ARG_PHONONSRC:
       
   178         g_value_set_pointer(value, src->device);
       
   179         break;
       
   180     default:
       
   181         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
   182         break;
       
   183     }
       
   184 }
       
   185 
       
   186 static GstFlowReturn phonon_src_create_read (PhononSrc * src, guint64 offset, guint length, GstBuffer ** buffer)
       
   187 {
       
   188     Q_ASSERT(src->device);
       
   189     if (!src->device)
       
   190         return GST_FLOW_ERROR;
       
   191 
       
   192     GstBuffer *buf = gst_buffer_new_and_alloc (length);
       
   193     GST_BUFFER_SIZE (buf) = length;
       
   194     GST_BUFFER_OFFSET (buf) = offset;
       
   195     GST_BUFFER_OFFSET_END (buf) = offset + length;
       
   196 
       
   197     bool success = src->device->read(offset, length, (char*)GST_BUFFER_DATA (buf));
       
   198     //GST_LOG_OBJECT (src, "Reading %d bytes", length);
       
   199 
       
   200     if (success) {
       
   201         *buffer = buf;
       
   202         return GST_FLOW_OK;
       
   203     }
       
   204 
       
   205     gst_mini_object_unref(GST_MINI_OBJECT(buf));
       
   206     return GST_FLOW_ERROR;
       
   207 }
       
   208 
       
   209 static GstFlowReturn phonon_src_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBuffer ** buffer)
       
   210 {
       
   211     PhononSrc *src;
       
   212     GstFlowReturn ret;
       
   213     src = GST_PHONON_SRC (basesrc);
       
   214     ret = phonon_src_create_read (src, offset, length, buffer);
       
   215     return ret;
       
   216 }
       
   217 
       
   218 static gboolean phonon_src_is_seekable (GstBaseSrc * basesrc)
       
   219 {
       
   220     PhononSrc *src = GST_PHONON_SRC (basesrc);
       
   221     if (src->device)
       
   222         return src->device->streamSeekable();
       
   223     return false;
       
   224 }
       
   225 
       
   226 static gboolean phonon_src_get_size (GstBaseSrc * basesrc, guint64 * size)
       
   227 {
       
   228     PhononSrc *src;
       
   229     src = GST_PHONON_SRC (basesrc);
       
   230     if (src->device && src->device->streamSeekable()) {
       
   231         *size = src->device->streamSize();
       
   232         return TRUE;
       
   233     }
       
   234     *size = 0;
       
   235     return FALSE;
       
   236 }
       
   237 
       
   238 // Necessary to go to READY state
       
   239 static gboolean phonon_src_start (GstBaseSrc * basesrc)
       
   240 {
       
   241     Q_UNUSED(basesrc);
       
   242     // Opening the device is handled by the frontend
       
   243     // We can only assume it is already open
       
   244     return TRUE;
       
   245 }
       
   246 
       
   247 static gboolean phonon_src_stop (GstBaseSrc * basesrc)
       
   248 {
       
   249     Q_UNUSED(basesrc);
       
   250     // Closing the device is handled by the frontend
       
   251     return TRUE;
       
   252 }
       
   253 
       
   254 }
       
   255 } //namespace Phonon::Gstreamer
       
   256 
       
   257 QT_END_NAMESPACE