gst-gmyth/playbinmaemo/gstplaybinmaemo.c
author renatofilho
Tue Sep 18 18:20:50 2007 +0100 (2007-09-18)
branchtrunk
changeset 852 2498e4f8c758
parent 811 69aba3b6b7b3
child 853 c738c2ac1968
permissions -rw-r--r--
[svn r858] fixed debian scripts
renatofilho@787
     1
/* GStreamer
renatofilho@797
     2
 * Copyright (C) <2007> Renato Araujo Oliveira Filho <renato.filho@indt.org.br>
renatofilho@787
     3
 *
renatofilho@787
     4
 * This library is free software; you can redistribute it and/or
renatofilho@787
     5
 * modify it under the terms of the GNU Library General Public
renatofilho@787
     6
 * License as published by the Free Software Foundation; either
renatofilho@787
     7
 * version 2 of the License, or (at your option) any later version.
renatofilho@787
     8
 *
renatofilho@787
     9
 * This library is distributed in the hope that it will be useful,
renatofilho@787
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
renatofilho@787
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
renatofilho@787
    12
 * Library General Public License for more details.
renatofilho@787
    13
 *
renatofilho@787
    14
 * You should have received a copy of the GNU Library General Public
renatofilho@787
    15
 * License along with this library; if not, write to the
renatofilho@787
    16
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
renatofilho@787
    17
 * Boston, MA 02111-1307, USA.
renatofilho@787
    18
 */
renatofilho@787
    19
renatofilho@787
    20
#ifdef HAVE_CONFIG_H
renatofilho@787
    21
#include "config.h"
renatofilho@787
    22
#endif
renatofilho@787
    23
renatofilho@787
    24
#include <glib/gi18n.h>
renatofilho@787
    25
#include <string.h>
renatofilho@787
    26
#include <gst/gst.h>
renatofilho@787
    27
#include <gst/gsterror.h>
renatofilho@787
    28
#include <gst/gstplugin.h>
renatofilho@787
    29
#include <gst/interfaces/xoverlay.h>
renatofilho@787
    30
#include <X11/Xlib.h>
renatofilho@787
    31
//#include <gst/pbutils/pbutils.h>
renatofilho@787
    32
#include "gstplaybinmaemo.h"
renatofilho@787
    33
renatofilho@787
    34
renatofilho@787
    35
GST_DEBUG_CATEGORY_STATIC (gst_play_bin_maemo_debug);
renatofilho@787
    36
#define GST_CAT_DEFAULT gst_play_bin_maemo_debug
renatofilho@787
    37
leo_sobral@811
    38
#define DEFAULT_VOLUME               1.0
renatofilho@787
    39
#define DEFAULT_XID                 -1
renatofilho@787
    40
renatofilho@787
    41
/* props */
renatofilho@787
    42
enum
renatofilho@787
    43
{
renatofilho@787
    44
  ARG_0,
renatofilho@787
    45
  ARG_URI,
renatofilho@787
    46
  ARG_QUEUE_SIZE,
renatofilho@787
    47
  ARG_QUEUE_MIN_THRESHOLD,
renatofilho@787
    48
  ARG_SOURCE,
renatofilho@787
    49
  ARG_VOLUME,
renatofilho@788
    50
  ARG_PARSE_METADATA,
renatofilho@787
    51
  ARG_XID
renatofilho@787
    52
};
renatofilho@787
    53
renatofilho@787
    54
static const GstElementDetails gst_play_bin_maemo_details =
leo_sobral@796
    55
        GST_ELEMENT_DETAILS("playbinmaemo",
renatofilho@787
    56
                            "Generic/Bin/Player",
renatofilho@787
    57
                            "Autoplug and play media from an uri used on maemo plataform",
renatofilho@787
    58
                            "Renato Araujo Oliveira Filho <renato.filho@indt.org.br>");
renatofilho@787
    59
renatofilho@787
    60
static void     gst_play_bin_maemo_dispose          (GObject * object);
renatofilho@787
    61
static void     gst_play_bin_maemo_finalize         (GObject * object);
renatofilho@787
    62
static void     gst_play_bin_maemo_set_property     (GObject * object, guint prop_id,
renatofilho@787
    63
                                                    const GValue * value, GParamSpec * spec);
renatofilho@787
    64
static void     gst_play_bin_maemo_get_property     (GObject * object, guint prop_id,
renatofilho@787
    65
                                                    GValue * value, GParamSpec * spec);
renatofilho@787
    66
static GstStateChangeReturn
renatofilho@787
    67
                gst_play_bin_maemo_change_state     (GstElement *element,
renatofilho@787
    68
                                                    GstStateChange transition);
renatofilho@787
    69
static gboolean factory_filter_sinks                (GstPluginFeature *feature,
renatofilho@787
    70
                                                    GstPlayBinMaemo *pbm);
renatofilho@787
    71
static gint     compare_ranks                       (GstPluginFeature * f1,
renatofilho@787
    72
                                                    GstPluginFeature * f2);
renatofilho@787
    73
static GList    *find_compatibles                   (GstPlayBinMaemo *pbm,
renatofilho@787
    74
                                                     const GstCaps *caps);
renatofilho@787
    75
static GstPad   *find_sink_pad                      (GstElement * element);
leo_sobral@811
    76
static void     update_volume                       (GstPlayBinMaemo *pbm,
renatofilho@852
    77
                                                     gdouble volume);
renatofilho@787
    78
static void     update_xid                          (GstPlayBinMaemo *pbm);
renatofilho@787
    79
static void     new_decoded_pad_cb                  (GstElement *object,
renatofilho@787
    80
                                                     GstPad* pad,
renatofilho@787
    81
                                                     gboolean arg,
renatofilho@787
    82
                                                     gpointer user_data);
leo_sobral@811
    83
static void     removed_decoded_pad_cb              (GstElement *object,
leo_sobral@811
    84
                                                     GstPad* pad,
leo_sobral@811
    85
                                                     gpointer user_data);
renatofilho@787
    86
static void     unknown_type_cb                     (GstElement *object,
renatofilho@787
    87
                                                     GstPad *pad,
renatofilho@787
    88
                                                     GstCaps *casp,
renatofilho@787
    89
                                                     gpointer user_data);
renatofilho@852
    90
#if 0
renatofilho@787
    91
static gboolean autoplug_continue_cb                (GstElement* object,
renatofilho@787
    92
                                                     GstCaps* caps,
renatofilho@787
    93
                                                     gpointer user_data);
renatofilho@852
    94
#endif 
renatofilho@792
    95
static gboolean add_element                         (GstPlayBinMaemo *pbm,
renatofilho@792
    96
                                                     GstElement *child);
renatofilho@792
    97
static void     clear_elements                      (GstPlayBinMaemo *pbm);
leo_sobral@808
    98
static int      x_error_handler                     (Display *display,
leo_sobral@808
    99
                                                     XErrorEvent *event);
renatofilho@787
   100
renatofilho@787
   101
GST_BOILERPLATE(GstPlayBinMaemo, gst_play_bin_maemo, GstPipeline, GST_TYPE_PIPELINE)
renatofilho@787
   102
renatofilho@787
   103
renatofilho@787
   104
static void
renatofilho@787
   105
gst_play_bin_maemo_base_init (gpointer klass)
renatofilho@787
   106
{
renatofilho@787
   107
    GstElementClass *element_class = GST_ELEMENT_CLASS(klass);
renatofilho@787
   108
renatofilho@787
   109
    gst_element_class_set_details (element_class, &gst_play_bin_maemo_details);
renatofilho@787
   110
}
renatofilho@787
   111
renatofilho@787
   112
static void
renatofilho@787
   113
gst_play_bin_maemo_class_init (GstPlayBinMaemoClass * klass)
renatofilho@787
   114
{
renatofilho@787
   115
  GObjectClass *gobject_klass;
renatofilho@787
   116
  GstElementClass *gstelement_klass;
renatofilho@787
   117
  GstBinClass *gstbin_klass;
renatofilho@787
   118
renatofilho@787
   119
  gobject_klass = (GObjectClass *) klass;
renatofilho@787
   120
  gstelement_klass = (GstElementClass *) klass;
renatofilho@787
   121
  gstbin_klass = (GstBinClass *) klass;
renatofilho@787
   122
renatofilho@787
   123
  parent_class = g_type_class_peek_parent (klass);
renatofilho@787
   124
renatofilho@787
   125
  gobject_klass->set_property = gst_play_bin_maemo_set_property;
renatofilho@787
   126
  gobject_klass->get_property = gst_play_bin_maemo_get_property;
renatofilho@787
   127
renatofilho@787
   128
  g_object_class_install_property (gobject_klass, ARG_URI,
renatofilho@787
   129
      g_param_spec_string ("uri", "URI", "URI of the media to play",
renatofilho@787
   130
          NULL, G_PARAM_READWRITE));
renatofilho@787
   131
renatofilho@787
   132
  g_object_class_install_property (gobject_klass, ARG_VOLUME,
renatofilho@793
   133
      g_param_spec_double ("volume", "Audio volume", "volume",
leo_sobral@811
   134
                            0.0, 10.0, DEFAULT_VOLUME, G_PARAM_READWRITE));
renatofilho@787
   135
renatofilho@787
   136
  g_object_class_install_property (gobject_klass, ARG_XID,
renatofilho@787
   137
      g_param_spec_long ("xid", "xid", "X windown ID",
renatofilho@787
   138
                         -1, G_MAXLONG, DEFAULT_XID, G_PARAM_READWRITE));
renatofilho@787
   139
renatofilho@787
   140
  g_object_class_install_property (gobject_klass, ARG_SOURCE,
renatofilho@787
   141
      g_param_spec_object ("source", "Source", "Source element",
renatofilho@787
   142
          GST_TYPE_ELEMENT, G_PARAM_READABLE));
renatofilho@787
   143
renatofilho@788
   144
  g_object_class_install_property (gobject_klass, ARG_PARSE_METADATA,
renatofilho@788
   145
      g_param_spec_boolean ("parse-metadata", "Parse Metadata", "Parse metadata info",
renatofilho@788
   146
          TRUE, G_PARAM_READWRITE));
renatofilho@788
   147
renatofilho@788
   148
renatofilho@787
   149
  GST_DEBUG_CATEGORY_INIT (gst_play_bin_maemo_debug, "playbinmaemo", 0,
renatofilho@787
   150
      "playbinmaemo");
renatofilho@787
   151
renatofilho@787
   152
  gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_play_bin_maemo_dispose);
renatofilho@787
   153
  gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_bin_maemo_finalize);
renatofilho@787
   154
renatofilho@787
   155
  gstelement_klass->change_state =
renatofilho@787
   156
      GST_DEBUG_FUNCPTR (gst_play_bin_maemo_change_state);
renatofilho@787
   157
}
renatofilho@787
   158
renatofilho@787
   159
static void
renatofilho@787
   160
gst_play_bin_maemo_init (GstPlayBinMaemo * play_bin_maemo, GstPlayBinMaemoClass *class)
renatofilho@787
   161
{
renatofilho@787
   162
  GList *factories;
renatofilho@787
   163
renatofilho@787
   164
  play_bin_maemo->uri = NULL;
renatofilho@787
   165
  play_bin_maemo->source = NULL;
renatofilho@787
   166
leo_sobral@811
   167
  play_bin_maemo->volume = DEFAULT_VOLUME;
renatofilho@787
   168
  play_bin_maemo->xid = DEFAULT_XID;
renatofilho@788
   169
  play_bin_maemo->parse_metadata = TRUE;
renatofilho@787
   170
leo_sobral@811
   171
  factories = gst_default_registry_feature_filter (
leo_sobral@811
   172
                (GstPluginFeatureFilter) factory_filter_sinks,
leo_sobral@811
   173
                 FALSE, play_bin_maemo);
renatofilho@787
   174
leo_sobral@811
   175
  play_bin_maemo->factories = g_list_sort (factories,
leo_sobral@811
   176
                                           (GCompareFunc) compare_ranks);
renatofilho@787
   177
}
renatofilho@787
   178
renatofilho@787
   179
static void
renatofilho@787
   180
gst_play_bin_maemo_dispose (GObject * object)
renatofilho@787
   181
{
renatofilho@787
   182
  GstPlayBinMaemo *play_bin_maemo;
renatofilho@787
   183
renatofilho@787
   184
  play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
renatofilho@787
   185
  g_free (play_bin_maemo->uri);
renatofilho@787
   186
  play_bin_maemo->uri = NULL;
renatofilho@852
   187
  clear_elements (GST_PLAY_BIN_MAEMO (object));
renatofilho@787
   188
renatofilho@787
   189
  G_OBJECT_CLASS (parent_class)->dispose (object);
renatofilho@787
   190
}
renatofilho@787
   191
renatofilho@787
   192
static void
renatofilho@787
   193
gst_play_bin_maemo_finalize (GObject * object)
renatofilho@787
   194
{
renatofilho@787
   195
  G_OBJECT_CLASS (parent_class)->finalize (object);
renatofilho@787
   196
}
renatofilho@787
   197
renatofilho@787
   198
static gboolean
renatofilho@787
   199
array_has_value (const gchar * values[], const gchar * value)
renatofilho@787
   200
{
renatofilho@787
   201
  gint i;
renatofilho@787
   202
renatofilho@787
   203
  for (i = 0; values[i]; i++) {
renatofilho@787
   204
    if (g_str_has_prefix (value, values[i]))
renatofilho@787
   205
      return TRUE;
renatofilho@787
   206
  }
renatofilho@787
   207
  return FALSE;
renatofilho@787
   208
}
renatofilho@787
   209
renatofilho@787
   210
/* list of URIs that we consider to be streams and that need buffering.
renatofilho@787
   211
 * We have no mechanism yet to figure this out with a query. */
renatofilho@787
   212
static const gchar *stream_uris[] = { "http://", "mms://", "mmsh://",
renatofilho@787
   213
  "mmsu://", "mmst://", NULL
renatofilho@787
   214
};
renatofilho@787
   215
renatofilho@787
   216
/* blacklisted URIs, we know they will always fail. */
renatofilho@787
   217
static const gchar *blacklisted_uris[] = { NULL };
renatofilho@787
   218
renatofilho@787
   219
/* mime types that we don't consider to be media types */
renatofilho@793
   220
/*
renatofilho@787
   221
static const gchar *no_media_mimes[] = {
renatofilho@787
   222
  "application/x-executable", "application/x-bzip", "application/x-gzip",
renatofilho@787
   223
  "application/zip", "application/x-compress", NULL
renatofilho@787
   224
};
renatofilho@793
   225
*/
renatofilho@787
   226
renatofilho@787
   227
/* mime types we consider raw media */
renatofilho@787
   228
static const gchar *raw_mimes[] = {
renatofilho@787
   229
  "audio/x-raw", "video/x-raw", NULL
renatofilho@787
   230
};
renatofilho@787
   231
renatofilho@787
   232
#define IS_STREAM_URI(uri)          (array_has_value (stream_uris, uri))
renatofilho@787
   233
#define IS_BLACKLISTED_URI(uri)     (array_has_value (blacklisted_uris, uri))
renatofilho@787
   234
#define IS_NO_MEDIA_MIME(mime)      (array_has_value (no_media_mimes, mime))
renatofilho@787
   235
#define IS_RAW_MIME(mime)           (array_has_value (raw_mimes, mime))
renatofilho@787
   236
renatofilho@787
   237
/*
renatofilho@787
   238
 * Generate and configure a source element.
renatofilho@787
   239
 */
renatofilho@787
   240
static GstElement *
renatofilho@787
   241
gen_source_element (GstPlayBinMaemo * play_bin_maemo)
renatofilho@787
   242
{
renatofilho@787
   243
  GstElement *source;
renatofilho@787
   244
renatofilho@787
   245
  if (!play_bin_maemo->uri)
renatofilho@787
   246
    goto no_uri;
renatofilho@787
   247
renatofilho@787
   248
  if (!gst_uri_is_valid (play_bin_maemo->uri))
renatofilho@787
   249
    goto invalid_uri;
renatofilho@787
   250
renatofilho@787
   251
  if (IS_BLACKLISTED_URI (play_bin_maemo->uri))
renatofilho@787
   252
    goto uri_blacklisted;
renatofilho@787
   253
renatofilho@792
   254
  source = gst_element_make_from_uri (GST_URI_SRC, play_bin_maemo->uri, "source");
renatofilho@787
   255
  if (!source)
renatofilho@787
   256
    goto no_source;
renatofilho@787
   257
renatofilho@787
   258
  play_bin_maemo->is_stream = IS_STREAM_URI (play_bin_maemo->uri);
renatofilho@787
   259
renatofilho@787
   260
  /* make HTTP sources send extra headers so we get icecast
renatofilho@787
   261
   * metadata in case the stream is an icecast stream */
renatofilho@787
   262
  if (!strncmp (play_bin_maemo->uri, "http://", 7) &&
renatofilho@787
   263
      g_object_class_find_property (G_OBJECT_GET_CLASS (source),
renatofilho@787
   264
          "iradio-mode")) {
renatofilho@787
   265
    g_object_set (source, "iradio-mode", TRUE, NULL);
renatofilho@787
   266
  }
renatofilho@787
   267
  return source;
renatofilho@787
   268
renatofilho@787
   269
  /* ERRORS */
renatofilho@787
   270
no_uri:
renatofilho@787
   271
  {
renatofilho@787
   272
    GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, NOT_FOUND,
renatofilho@787
   273
        (_("No URI specified to play from.")), (NULL));
renatofilho@787
   274
    return NULL;
renatofilho@787
   275
  }
renatofilho@787
   276
invalid_uri:
renatofilho@787
   277
  {
renatofilho@787
   278
    GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, NOT_FOUND,
renatofilho@787
   279
        (_("Invalid URI \"%s\"."), play_bin_maemo->uri), (NULL));
renatofilho@787
   280
    return NULL;
renatofilho@787
   281
  }
renatofilho@787
   282
uri_blacklisted:
renatofilho@787
   283
  {
renatofilho@787
   284
    GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, FAILED,
renatofilho@787
   285
        (_("RTSP streams cannot be played yet.")), (NULL));
renatofilho@787
   286
    return NULL;
renatofilho@787
   287
  }
renatofilho@787
   288
no_source:
renatofilho@787
   289
  {
renatofilho@787
   290
    gchar *prot = gst_uri_get_protocol (play_bin_maemo->uri);
renatofilho@787
   291
renatofilho@787
   292
    /* whoops, could not create the source element, dig a little deeper to
renatofilho@787
   293
     * figure out what might be wrong. */
renatofilho@787
   294
    if (prot) {
renatofilho@793
   295
       /*
renatofilho@787
   296
      gchar *desc;
renatofilho@787
   297
renatofilho@787
   298
      gst_element_post_message (GST_ELEMENT (play_bin_maemo),
renatofilho@787
   299
          gst_missing_uri_source_message_new (GST_ELEMENT (play_bin_maemo),
renatofilho@787
   300
              prot));
renatofilho@787
   301
renatofilho@787
   302
      desc = gst_pb_utils_get_source_description (prot);
renatofilho@787
   303
      GST_ELEMENT_ERROR (play_bin_maemo, CORE, MISSING_PLUGIN,
renatofilho@787
   304
          (_("A %s plugin is required to play this stream, but not installed."),
renatofilho@787
   305
              desc), ("No URI handler for %s", prot));
renatofilho@787
   306
      g_free (desc);
renatofilho@793
   307
      */
renatofilho@787
   308
      g_free (prot);
renatofilho@787
   309
    } else
renatofilho@787
   310
      goto invalid_uri;
renatofilho@787
   311
renatofilho@787
   312
    return NULL;
renatofilho@787
   313
  }
renatofilho@787
   314
}
renatofilho@787
   315
renatofilho@787
   316
static void
renatofilho@852
   317
_setup_decoder (GstPlayBinMaemo *pbm, GstElement *element)
renatofilho@852
   318
{
renatofilho@852
   319
  GList *factories;
renatofilho@852
   320
  GstCaps *all_caps;
renatofilho@852
   321
  //GstCaps *decode_caps;
renatofilho@852
   322
renatofilho@852
   323
renatofilho@852
   324
//  all_caps = gst_caps_new_empty ();
renatofilho@852
   325
  g_object_get (element, "caps", &all_caps, NULL);
renatofilho@852
   326
  all_caps = gst_caps_copy (all_caps);
renatofilho@852
   327
//  gst_caps_append (all_caps, decode_caps);
renatofilho@852
   328
renatofilho@852
   329
  /* loop over all the factories */
renatofilho@852
   330
  for (factories = pbm->factories; factories; factories = g_list_next (factories)) {
renatofilho@852
   331
    GstElementFactory *factory = GST_ELEMENT_FACTORY (factories->data);
renatofilho@852
   332
    const GList *templates;
renatofilho@852
   333
    GList *walk;
renatofilho@852
   334
renatofilho@852
   335
    /* get the templates from the element factory */
renatofilho@852
   336
    templates = gst_element_factory_get_static_pad_templates (factory);
renatofilho@852
   337
    for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
renatofilho@852
   338
      GstStaticPadTemplate *templ = walk->data;
renatofilho@852
   339
renatofilho@852
   340
      /* we only care about the sink templates */
renatofilho@852
   341
      if (templ->direction == GST_PAD_SINK) {
renatofilho@852
   342
        GstCaps *tmpl_caps;
renatofilho@852
   343
renatofilho@852
   344
        /* try to intersect the caps with the caps of the template */
renatofilho@852
   345
        tmpl_caps = gst_static_caps_get (&templ->static_caps);
renatofilho@852
   346
        gst_caps_append (all_caps, gst_caps_copy (tmpl_caps));
renatofilho@852
   347
        gst_caps_ref (tmpl_caps);
renatofilho@852
   348
      }
renatofilho@852
   349
    }
renatofilho@852
   350
  }
renatofilho@852
   351
renatofilho@852
   352
  g_object_set (element, "caps", all_caps, NULL);
renatofilho@852
   353
}
renatofilho@852
   354
renatofilho@852
   355
static void
renatofilho@787
   356
prepare_elements (GstPlayBinMaemo *pbm)
renatofilho@787
   357
{
leo_sobral@805
   358
  GstElement *decoder;
leo_sobral@805
   359
  GstElement *queue;
renatofilho@787
   360
renatofilho@852
   361
  queue = gst_element_factory_make ("queue", NULL);
renatofilho@852
   362
  add_element (pbm, queue);
renatofilho@852
   363
leo_sobral@805
   364
  decoder = gst_element_factory_make ("decodebin2", "decode");
renatofilho@852
   365
  _setup_decoder (pbm, decoder);
leo_sobral@805
   366
  add_element (pbm, decoder);
renatofilho@852
   367
  /*
leo_sobral@805
   368
  g_signal_connect (G_OBJECT (decoder),
leo_sobral@805
   369
                    "autoplug-continue",
leo_sobral@805
   370
                    G_CALLBACK (autoplug_continue_cb),
leo_sobral@805
   371
                    pbm);
renatofilho@852
   372
                    */
renatofilho@787
   373
leo_sobral@805
   374
  g_signal_connect (G_OBJECT (decoder),
leo_sobral@805
   375
                    "unknown-type",
leo_sobral@805
   376
                    G_CALLBACK (unknown_type_cb),
leo_sobral@805
   377
                    pbm);
renatofilho@792
   378
leo_sobral@805
   379
  g_signal_connect (G_OBJECT (decoder),
leo_sobral@805
   380
                    "new-decoded-pad",
leo_sobral@805
   381
                    G_CALLBACK (new_decoded_pad_cb),
leo_sobral@805
   382
                    pbm);
renatofilho@792
   383
leo_sobral@811
   384
  g_signal_connect (G_OBJECT (decoder),
leo_sobral@811
   385
                    "removed-decoded-pad",
leo_sobral@811
   386
                    G_CALLBACK (removed_decoded_pad_cb),
leo_sobral@811
   387
                    pbm);
leo_sobral@811
   388
leo_sobral@811
   389
leo_sobral@805
   390
  if (gst_element_link_many (pbm->source, queue, decoder, NULL) == FALSE) {
leo_sobral@811
   391
    GST_WARNING ("FAIL TO LINK SRC WITH DECODEBIN2");
leo_sobral@805
   392
  }
renatofilho@787
   393
}
renatofilho@787
   394
renatofilho@787
   395
static gboolean
renatofilho@787
   396
setup_source (GstPlayBinMaemo *pbm)
renatofilho@787
   397
{
leo_sobral@805
   398
  if (!pbm->need_rebuild)
leo_sobral@805
   399
    return TRUE;
renatofilho@787
   400
leo_sobral@805
   401
  clear_elements (pbm);
renatofilho@792
   402
leo_sobral@805
   403
  GST_DEBUG_OBJECT (pbm, "setup source");
renatofilho@787
   404
leo_sobral@805
   405
  pbm->has_metadata = FALSE;
renatofilho@788
   406
leo_sobral@805
   407
  /* create and configure an element that can handle the uri */
leo_sobral@805
   408
  if (!(pbm->source = gen_source_element (pbm)))
leo_sobral@805
   409
    goto no_source;
renatofilho@787
   410
leo_sobral@805
   411
  add_element (pbm, pbm->source);
renatofilho@787
   412
renatofilho@787
   413
renatofilho@787
   414
#if 0
renatofilho@787
   415
    if (verify_src_have_sink (pbm)) {
renatofilho@787
   416
        /* source can be linked with sinks directly */
renatofilho@787
   417
        return TRUE;
renatofilho@787
   418
    }
renatofilho@787
   419
#endif
renatofilho@787
   420
leo_sobral@805
   421
  prepare_elements (pbm);
renatofilho@787
   422
leo_sobral@805
   423
  return TRUE;
renatofilho@787
   424
renatofilho@787
   425
no_source:
leo_sobral@805
   426
  return FALSE;
renatofilho@787
   427
}
renatofilho@787
   428
renatofilho@787
   429
static void
renatofilho@787
   430
gst_play_bin_maemo_set_property (GObject *object,
renatofilho@787
   431
                                 guint prop_id,
renatofilho@787
   432
                                 const GValue *value,
renatofilho@787
   433
                                 GParamSpec *pspec)
renatofilho@787
   434
{
renatofilho@787
   435
  GstPlayBinMaemo *play_bin_maemo;
renatofilho@787
   436
renatofilho@787
   437
  g_return_if_fail (GST_IS_PLAY_BIN_MAEMO (object));
renatofilho@787
   438
renatofilho@787
   439
  play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
renatofilho@787
   440
renatofilho@787
   441
  switch (prop_id) {
renatofilho@787
   442
    case ARG_URI:
renatofilho@787
   443
    {
renatofilho@787
   444
      const gchar *uri = g_value_get_string (value);
renatofilho@787
   445
renatofilho@787
   446
      if (uri == NULL) {
leo_sobral@811
   447
        GST_WARNING ("cannot set NULL uri");
renatofilho@787
   448
        return;
renatofilho@787
   449
      }
renatofilho@787
   450
      /* if we have no previous uri, or the new uri is different from the
renatofilho@787
   451
       * old one, replug */
renatofilho@787
   452
      if (play_bin_maemo->uri == NULL || strcmp (play_bin_maemo->uri, uri) != 0) {
renatofilho@787
   453
        g_free (play_bin_maemo->uri);
renatofilho@787
   454
        play_bin_maemo->uri = g_strdup (uri);
renatofilho@787
   455
renatofilho@787
   456
        GST_DEBUG ("setting new uri to %s", uri);
renatofilho@787
   457
renatofilho@787
   458
        play_bin_maemo->need_rebuild = TRUE;
renatofilho@787
   459
      }
renatofilho@787
   460
      break;
renatofilho@787
   461
    }
renatofilho@787
   462
    case ARG_VOLUME:
leo_sobral@811
   463
      update_volume(play_bin_maemo, g_value_get_double (value));
renatofilho@787
   464
      break;
renatofilho@787
   465
    case ARG_XID:
renatofilho@787
   466
    {
renatofilho@787
   467
      long xid;
renatofilho@787
   468
      xid = g_value_get_long (value);
renatofilho@792
   469
      if (play_bin_maemo->xid != xid)
renatofilho@792
   470
      {
renatofilho@787
   471
          play_bin_maemo->xid = xid;
renatofilho@787
   472
          update_xid (play_bin_maemo);
renatofilho@787
   473
      }
renatofilho@787
   474
      break;
renatofilho@787
   475
    }
renatofilho@788
   476
    case ARG_PARSE_METADATA:
renatofilho@788
   477
        play_bin_maemo->parse_metadata = g_value_get_boolean (value);
renatofilho@788
   478
        break;
renatofilho@787
   479
    default:
renatofilho@787
   480
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
renatofilho@787
   481
      break;
renatofilho@787
   482
  }
renatofilho@787
   483
}
renatofilho@787
   484
renatofilho@787
   485
static void
leo_sobral@811
   486
gst_play_bin_maemo_get_property (GObject * object,
leo_sobral@811
   487
                                 guint prop_id,
leo_sobral@811
   488
                                 GValue * value,
leo_sobral@811
   489
                                 GParamSpec * pspec)
renatofilho@787
   490
{
renatofilho@787
   491
  GstPlayBinMaemo *play_bin_maemo;
renatofilho@787
   492
renatofilho@787
   493
  g_return_if_fail (GST_IS_PLAY_BIN_MAEMO (object));
renatofilho@787
   494
renatofilho@787
   495
  play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
renatofilho@787
   496
renatofilho@787
   497
  switch (prop_id) {
renatofilho@787
   498
    case ARG_URI:
renatofilho@787
   499
      g_value_set_string (value, play_bin_maemo->uri);
renatofilho@787
   500
      break;
renatofilho@787
   501
    case ARG_SOURCE:
renatofilho@787
   502
      g_value_set_object (value, play_bin_maemo->source);
renatofilho@787
   503
      break;
renatofilho@787
   504
    case ARG_VOLUME:
leo_sobral@811
   505
      g_value_set_double (value, play_bin_maemo->volume);
renatofilho@787
   506
      break;
renatofilho@787
   507
    case ARG_XID:
renatofilho@787
   508
      g_value_set_long (value, play_bin_maemo->xid);
renatofilho@787
   509
      break;
renatofilho@788
   510
    case ARG_PARSE_METADATA:
renatofilho@788
   511
      g_value_set_boolean (value, play_bin_maemo->parse_metadata);
renatofilho@788
   512
      break;
renatofilho@787
   513
    default:
renatofilho@787
   514
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
renatofilho@787
   515
      break;
renatofilho@787
   516
  }
renatofilho@787
   517
}
renatofilho@787
   518
renatofilho@787
   519
static GstStateChangeReturn
leo_sobral@811
   520
gst_play_bin_maemo_change_state (GstElement * element,
leo_sobral@811
   521
                                 GstStateChange transition)
renatofilho@787
   522
{
renatofilho@787
   523
  GstStateChangeReturn ret;
renatofilho@787
   524
  GstPlayBinMaemo *play_bin_maemo;
renatofilho@787
   525
renatofilho@787
   526
  play_bin_maemo = GST_PLAY_BIN_MAEMO (element);
renatofilho@787
   527
renatofilho@787
   528
  switch (transition) {
renatofilho@787
   529
    case GST_STATE_CHANGE_READY_TO_PAUSED:
renatofilho@787
   530
      if (!setup_source (play_bin_maemo))
renatofilho@787
   531
        goto source_failed;
renatofilho@787
   532
      break;
renatofilho@787
   533
    default:
renatofilho@787
   534
      break;
renatofilho@787
   535
  }
renatofilho@787
   536
renatofilho@787
   537
  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
renatofilho@787
   538
renatofilho@787
   539
  switch (transition) {
renatofilho@787
   540
    case GST_STATE_CHANGE_READY_TO_PAUSED:
renatofilho@787
   541
      if (ret == GST_STATE_CHANGE_FAILURE) {
renatofilho@787
   542
        play_bin_maemo->need_rebuild = TRUE;
renatofilho@787
   543
        return GST_STATE_CHANGE_FAILURE;
renatofilho@787
   544
      }
renatofilho@787
   545
      break;
renatofilho@787
   546
      /* clean-up in both cases, READY=>NULL clean-up is if there was an error */
renatofilho@787
   547
    case GST_STATE_CHANGE_PAUSED_TO_READY:
renatofilho@787
   548
    case GST_STATE_CHANGE_READY_TO_NULL:
renatofilho@787
   549
      play_bin_maemo->need_rebuild = TRUE;
renatofilho@792
   550
      clear_elements (play_bin_maemo);
renatofilho@787
   551
      break;
renatofilho@787
   552
    default:
renatofilho@787
   553
      break;
renatofilho@787
   554
  }
renatofilho@787
   555
  return ret;
renatofilho@787
   556
renatofilho@787
   557
  /* ERRORS */
renatofilho@787
   558
source_failed:
renatofilho@787
   559
  {
renatofilho@787
   560
    play_bin_maemo->need_rebuild = TRUE;
renatofilho@787
   561
renatofilho@787
   562
    return GST_STATE_CHANGE_FAILURE;
renatofilho@787
   563
  }
renatofilho@787
   564
}
renatofilho@787
   565
renatofilho@787
   566
static gboolean
renatofilho@787
   567
factory_filter_sinks (GstPluginFeature *feature,
renatofilho@787
   568
                      GstPlayBinMaemo *pbm)
renatofilho@787
   569
{
leo_sobral@805
   570
  guint rank;
leo_sobral@805
   571
  const gchar *klass;
renatofilho@787
   572
leo_sobral@805
   573
  if (!GST_IS_ELEMENT_FACTORY (feature))
leo_sobral@805
   574
    return FALSE;
renatofilho@787
   575
leo_sobral@805
   576
  klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
renatofilho@787
   577
leo_sobral@805
   578
  if ((strstr (klass, "Sink/Video") == NULL) && (strstr (klass, "Sink/Audio") == NULL))
leo_sobral@805
   579
    return FALSE;
renatofilho@787
   580
leo_sobral@811
   581
  GST_DEBUG_OBJECT (pbm, "Filtered: %s",
leo_sobral@811
   582
        gst_element_factory_get_longname ((GST_ELEMENT_FACTORY (feature))));
leo_sobral@805
   583
  rank = gst_plugin_feature_get_rank (feature);
leo_sobral@805
   584
  if (rank < GST_RANK_MARGINAL)
leo_sobral@805
   585
    return FALSE;
renatofilho@787
   586
leo_sobral@805
   587
  return TRUE;
renatofilho@787
   588
}
renatofilho@787
   589
renatofilho@787
   590
static gint
leo_sobral@811
   591
compare_ranks (GstPluginFeature * f1,
leo_sobral@811
   592
               GstPluginFeature * f2)
renatofilho@787
   593
{
renatofilho@787
   594
  gint diff;
renatofilho@787
   595
  const gchar *rname1, *rname2;
renatofilho@787
   596
renatofilho@787
   597
  diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1);
renatofilho@787
   598
  if (diff != 0)
renatofilho@787
   599
    return diff;
renatofilho@787
   600
renatofilho@787
   601
  rname1 = gst_plugin_feature_get_name (f1);
renatofilho@787
   602
  rname2 = gst_plugin_feature_get_name (f2);
renatofilho@787
   603
renatofilho@787
   604
  diff = strcmp (rname2, rname1);
renatofilho@787
   605
renatofilho@787
   606
  return diff;
renatofilho@787
   607
}
renatofilho@787
   608
renatofilho@787
   609
renatofilho@787
   610
static GList *
leo_sobral@811
   611
find_compatibles (GstPlayBinMaemo *pbm,
leo_sobral@811
   612
                  const GstCaps *caps)
renatofilho@787
   613
{
renatofilho@787
   614
  GList *factories;
renatofilho@787
   615
  GList *to_try = NULL;
renatofilho@787
   616
renatofilho@787
   617
  /* loop over all the factories */
renatofilho@787
   618
  for (factories = pbm->factories; factories; factories = g_list_next (factories)) {
renatofilho@787
   619
    GstElementFactory *factory = GST_ELEMENT_FACTORY (factories->data);
renatofilho@787
   620
    const GList *templates;
renatofilho@787
   621
    GList *walk;
renatofilho@787
   622
renatofilho@787
   623
    /* get the templates from the element factory */
renatofilho@787
   624
    templates = gst_element_factory_get_static_pad_templates (factory);
renatofilho@787
   625
    for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
renatofilho@787
   626
      GstStaticPadTemplate *templ = walk->data;
renatofilho@787
   627
renatofilho@787
   628
      /* we only care about the sink templates */
renatofilho@787
   629
      if (templ->direction == GST_PAD_SINK) {
renatofilho@787
   630
        GstCaps *intersect;
renatofilho@787
   631
        GstCaps *tmpl_caps;
renatofilho@787
   632
renatofilho@787
   633
        /* try to intersect the caps with the caps of the template */
renatofilho@787
   634
        tmpl_caps = gst_static_caps_get (&templ->static_caps);
renatofilho@787
   635
renatofilho@787
   636
        intersect = gst_caps_intersect (caps, tmpl_caps);
leo_sobral@811
   637
renatofilho@787
   638
        gst_caps_unref (tmpl_caps);
renatofilho@787
   639
renatofilho@787
   640
        /* check if the intersection is empty */
renatofilho@787
   641
        if (!gst_caps_is_empty (intersect)) {
renatofilho@787
   642
          /* non empty intersection, we can use this element */
renatofilho@787
   643
          to_try = g_list_prepend (to_try, factory);
renatofilho@787
   644
          gst_caps_unref (intersect);
renatofilho@787
   645
          break;
renatofilho@787
   646
        }
renatofilho@787
   647
        gst_caps_unref (intersect);
renatofilho@787
   648
      }
renatofilho@787
   649
    }
renatofilho@787
   650
  }
renatofilho@787
   651
  to_try = g_list_reverse (to_try);
renatofilho@787
   652
renatofilho@787
   653
  return to_try;
renatofilho@787
   654
}
renatofilho@787
   655
renatofilho@852
   656
#if 0
renatofilho@787
   657
static gboolean
renatofilho@787
   658
autoplug_continue_cb (GstElement* object,
renatofilho@787
   659
                      GstCaps* caps,
renatofilho@787
   660
                      gpointer user_data)
renatofilho@787
   661
{
renatofilho@787
   662
    GList *comp = NULL;
renatofilho@787
   663
    gboolean ret = TRUE;
renatofilho@788
   664
    GstPlayBinMaemo *pbm;
renatofilho@788
   665
renatofilho@788
   666
    pbm = GST_PLAY_BIN_MAEMO (user_data);
renatofilho@788
   667
leo_sobral@811
   668
    //TODO: fix this to work with all metadata elements
renatofilho@788
   669
    if (pbm->parse_metadata) {
renatofilho@788
   670
        gchar *caps_str = gst_caps_to_string (caps);
renatofilho@788
   671
        if ((strstr (caps_str, "id3") != NULL) &&
renatofilho@788
   672
            (pbm->has_metadata == FALSE)) {
renatofilho@788
   673
renatofilho@788
   674
            g_free (caps_str);
renatofilho@788
   675
            pbm->has_metadata = TRUE;
renatofilho@788
   676
            return ret;
renatofilho@788
   677
        }
renatofilho@788
   678
        g_free (caps_str);
renatofilho@788
   679
    }
renatofilho@787
   680
renatofilho@787
   681
    comp = find_compatibles (GST_PLAY_BIN_MAEMO (user_data), caps);
renatofilho@787
   682
    if (comp != NULL) {
renatofilho@787
   683
        g_list_free (comp);
renatofilho@787
   684
        ret = FALSE;
renatofilho@787
   685
    }
renatofilho@787
   686
renatofilho@787
   687
    return ret;
renatofilho@787
   688
}
renatofilho@852
   689
#endif
renatofilho@787
   690
renatofilho@787
   691
static void
renatofilho@787
   692
unknown_type_cb (GstElement *object,
renatofilho@787
   693
                 GstPad *pad,
renatofilho@787
   694
                 GstCaps *caps,
renatofilho@787
   695
                 gpointer user_data)
renatofilho@787
   696
{
leo_sobral@811
   697
  GST_DEBUG ("unknown_type_cb: %s", gst_caps_to_string (caps));
renatofilho@787
   698
}
renatofilho@787
   699
leo_sobral@811
   700
static GstPad*
renatofilho@787
   701
find_sink_pad (GstElement * element)
renatofilho@787
   702
{
renatofilho@787
   703
  GstIterator *it;
renatofilho@787
   704
  GstPad *pad = NULL;
renatofilho@787
   705
  gpointer point;
renatofilho@787
   706
renatofilho@787
   707
  it = gst_element_iterate_sink_pads (element);
renatofilho@787
   708
renatofilho@787
   709
  if ((gst_iterator_next (it, &point)) == GST_ITERATOR_OK)
renatofilho@787
   710
    pad = (GstPad *) point;
renatofilho@787
   711
renatofilho@787
   712
  gst_iterator_free (it);
renatofilho@787
   713
renatofilho@787
   714
  return pad;
renatofilho@787
   715
}
renatofilho@787
   716
renatofilho@788
   717
static GstElement*
leo_sobral@811
   718
create_element (GstPlayBinMaemo *pbm,
leo_sobral@811
   719
                GstElementFactory *factory)
renatofilho@788
   720
{
leo_sobral@805
   721
  GstElement *queue;
leo_sobral@805
   722
  GstElement *bin = NULL;
leo_sobral@805
   723
  GstElement *element;
leo_sobral@805
   724
  GstPad *pad;
renatofilho@788
   725
leo_sobral@805
   726
  element = gst_element_factory_create (factory, NULL);
leo_sobral@805
   727
  if (element == NULL)
leo_sobral@811
   728
    goto error;
renatofilho@792
   729
leo_sobral@805
   730
  bin = gst_bin_new (NULL);
leo_sobral@811
   731
  if (bin == NULL)
leo_sobral@811
   732
    goto error;
renatofilho@792
   733
leo_sobral@805
   734
  queue = gst_element_factory_make ("queue", NULL);
leo_sobral@805
   735
  gst_bin_add (GST_BIN (bin), queue);
renatofilho@792
   736
leo_sobral@805
   737
  if (strstr (gst_element_factory_get_klass (factory), "Sink/Video") != NULL) {
leo_sobral@805
   738
    GstElement *colorspace;
renatofilho@792
   739
leo_sobral@805
   740
    colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
leo_sobral@811
   741
    if (colorspace == NULL)
leo_sobral@811
   742
      goto error;
renatofilho@792
   743
leo_sobral@805
   744
    gst_bin_add (GST_BIN (bin), colorspace);
leo_sobral@805
   745
    if (gst_element_link (queue, colorspace) == FALSE) {
leo_sobral@811
   746
      GST_WARNING_OBJECT (pbm, "Failed to link queue and colorspace");
leo_sobral@805
   747
      gst_element_set_state (colorspace, GST_STATE_NULL);
leo_sobral@805
   748
      gst_object_unref (colorspace);
leo_sobral@805
   749
      goto error;
renatofilho@788
   750
    }
renatofilho@788
   751
leo_sobral@805
   752
    gst_bin_add (GST_BIN (bin), element);
leo_sobral@805
   753
    if (gst_element_link (colorspace, element) == FALSE) {
leo_sobral@811
   754
      GST_WARNING_OBJECT (pbm, "Failed to link colorspace and sink video: %s",
leo_sobral@811
   755
                          GST_ELEMENT_NAME (element));
leo_sobral@805
   756
      gst_element_set_state (colorspace, GST_STATE_NULL);
leo_sobral@805
   757
      gst_object_unref (colorspace);
leo_sobral@805
   758
      goto error;
leo_sobral@805
   759
    }
renatofilho@792
   760
leo_sobral@805
   761
    pbm->video_sink = element;
leo_sobral@805
   762
    update_xid (pbm);
leo_sobral@805
   763
leo_sobral@805
   764
  } else if (strstr (gst_element_factory_get_klass (factory), "Sink/Audio") != NULL) {
leo_sobral@805
   765
    GParamSpec *vol_spec;
renatofilho@852
   766
    GstElement *prev = NULL;
leo_sobral@805
   767
leo_sobral@805
   768
    prev = queue;
leo_sobral@805
   769
    vol_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), "volume");
leo_sobral@811
   770
leo_sobral@805
   771
    if (vol_spec == NULL) {
leo_sobral@811
   772
      GstElement *conv;
leo_sobral@805
   773
      GstElement *volume;
leo_sobral@805
   774
leo_sobral@811
   775
      conv = gst_element_factory_make ("audioconvert", "aconv");
leo_sobral@811
   776
      if (conv == NULL)
leo_sobral@811
   777
        goto error;
leo_sobral@811
   778
leo_sobral@811
   779
      gst_bin_add (GST_BIN_CAST (bin), conv);
leo_sobral@811
   780
leo_sobral@811
   781
      gst_element_link (queue, conv);
leo_sobral@811
   782
leo_sobral@805
   783
      volume = gst_element_factory_make ("volume", "volume");
leo_sobral@811
   784
      if (volume == NULL)
leo_sobral@811
   785
        goto error;
leo_sobral@811
   786
leo_sobral@805
   787
      gst_bin_add (GST_BIN (bin), volume);
leo_sobral@811
   788
      if (gst_element_link (conv, volume) == FALSE) {
leo_sobral@811
   789
        GST_WARNING_OBJECT (pbm, "Failed to link queue and volume");
leo_sobral@805
   790
        gst_element_set_state (volume, GST_STATE_NULL);
leo_sobral@805
   791
        gst_object_unref (volume);
leo_sobral@805
   792
        goto error;
leo_sobral@805
   793
      }
leo_sobral@805
   794
leo_sobral@805
   795
      prev = volume;
leo_sobral@805
   796
    }
leo_sobral@805
   797
leo_sobral@805
   798
    gst_bin_add (GST_BIN (bin), element);
leo_sobral@805
   799
    if (gst_element_link (prev, element) == FALSE) {
leo_sobral@811
   800
      GST_WARNING_OBJECT (pbm, "Failed to link volume and sink audio: %s", GST_ELEMENT_NAME (element));
leo_sobral@805
   801
      if (prev != queue) {
leo_sobral@805
   802
        gst_element_set_state (prev, GST_STATE_NULL);
leo_sobral@805
   803
        gst_object_unref (prev);
leo_sobral@805
   804
      }
leo_sobral@805
   805
      goto error;
leo_sobral@805
   806
    }
leo_sobral@805
   807
    pbm->volume_element = (prev != queue) ? prev : element;
leo_sobral@811
   808
    update_volume (pbm, pbm->volume);
leo_sobral@805
   809
  }
leo_sobral@805
   810
leo_sobral@805
   811
  pad = gst_element_get_pad (queue, "sink");
leo_sobral@805
   812
  gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));
leo_sobral@805
   813
  gst_object_unref (pad);
leo_sobral@805
   814
renatofilho@852
   815
leo_sobral@805
   816
  return bin;
leo_sobral@811
   817
renatofilho@792
   818
error:
leo_sobral@811
   819
  GST_WARNING_OBJECT (pbm, "Error creating pipeline");
renatofilho@792
   820
leo_sobral@805
   821
  gst_element_set_state (bin, GST_STATE_NULL);
leo_sobral@805
   822
  gst_object_unref (bin);
renatofilho@792
   823
leo_sobral@805
   824
  return NULL;
renatofilho@788
   825
}
renatofilho@788
   826
renatofilho@787
   827
static void
renatofilho@787
   828
new_decoded_pad_cb (GstElement *object,
renatofilho@787
   829
                    GstPad* pad,
renatofilho@787
   830
                    gboolean arg,
renatofilho@787
   831
                    gpointer user_data)
renatofilho@787
   832
{
leo_sobral@805
   833
  GList *comp = NULL;
leo_sobral@805
   834
  GList *walk;
leo_sobral@805
   835
  GstCaps *caps;
leo_sobral@805
   836
  gboolean linked;
leo_sobral@805
   837
  GstPlayBinMaemo *pbm;
renatofilho@787
   838
leo_sobral@805
   839
  pbm = GST_PLAY_BIN_MAEMO (user_data);
leo_sobral@805
   840
  caps = gst_pad_get_caps (pad);
renatofilho@787
   841
leo_sobral@811
   842
  GST_DEBUG_OBJECT (pbm, "new_decoded_pad_cb: %s", gst_caps_to_string (caps));
renatofilho@787
   843
leo_sobral@805
   844
  comp = find_compatibles (GST_PLAY_BIN_MAEMO (user_data), caps);
renatofilho@787
   845
leo_sobral@805
   846
  if (comp == NULL) {
leo_sobral@811
   847
    GST_WARNING ("flow error: dont find comaptible");
leo_sobral@805
   848
    return;
leo_sobral@805
   849
  }
leo_sobral@805
   850
leo_sobral@805
   851
  GST_PAD_STREAM_LOCK (pad);
leo_sobral@805
   852
leo_sobral@805
   853
  linked = FALSE;
leo_sobral@805
   854
  for (walk=comp; walk != NULL; walk = walk->next) {
leo_sobral@805
   855
    GstElementFactory *factory = (GstElementFactory *) walk->data;
leo_sobral@805
   856
    GstElement *element;
leo_sobral@805
   857
    GstPad *sinkpad = NULL;
renatofilho@852
   858
leo_sobral@805
   859
leo_sobral@805
   860
    if ((element = create_element (pbm, factory)) == NULL) {
leo_sobral@805
   861
      GST_WARNING_OBJECT (pbm, "Could not create an element from %s",
leo_sobral@805
   862
          gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
leo_sobral@811
   863
      continue;
leo_sobral@811
   864
    }
leo_sobral@805
   865
leo_sobral@811
   866
    if (!(sinkpad = find_sink_pad (element))) {
leo_sobral@811
   867
      GST_WARNING_OBJECT (pbm, "Element %s doesn't have a sink pad", GST_ELEMENT_NAME (element));
leo_sobral@811
   868
      gst_object_unref (element);
leo_sobral@805
   869
      continue;
renatofilho@787
   870
    }
renatofilho@787
   871
leo_sobral@805
   872
    if (!(add_element (GST_PLAY_BIN_MAEMO (user_data), element))) {
leo_sobral@811
   873
      GST_WARNING_OBJECT (pbm, "Couldn't add element %s to bin", GST_ELEMENT_NAME (element));
leo_sobral@811
   874
      gst_object_unref (sinkpad);
leo_sobral@805
   875
      gst_object_unref (element);
leo_sobral@805
   876
      continue;
renatofilho@787
   877
    }
renatofilho@787
   878
leo_sobral@805
   879
    if ((gst_element_set_state (element, GST_STATE_READY))
leo_sobral@805
   880
                   == GST_STATE_CHANGE_FAILURE) {
leo_sobral@811
   881
      GST_WARNING_OBJECT (pbm, "Couldn't set %s to READY", GST_ELEMENT_NAME (element));
leo_sobral@811
   882
      gst_object_unref (sinkpad);
leo_sobral@811
   883
      gst_bin_remove (GST_BIN (user_data), element);
leo_sobral@811
   884
      continue;
leo_sobral@811
   885
    }
leo_sobral@811
   886
leo_sobral@811
   887
    if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK) {
leo_sobral@811
   888
      GST_WARNING_OBJECT (pbm, "Link failed on pad %s:%s", GST_DEBUG_PAD_NAME (sinkpad));
leo_sobral@805
   889
      gst_element_set_state (element, GST_STATE_NULL);
leo_sobral@805
   890
      gst_object_unref (sinkpad);
leo_sobral@805
   891
      gst_bin_remove (GST_BIN (user_data), element);
leo_sobral@805
   892
      continue;
renatofilho@787
   893
    }
leo_sobral@805
   894
leo_sobral@805
   895
    gst_object_unref (sinkpad);
leo_sobral@805
   896
leo_sobral@805
   897
    if ((gst_element_set_state (element, GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) {
leo_sobral@811
   898
      gst_element_set_state (element, GST_STATE_NULL);
leo_sobral@811
   899
      gst_bin_remove (GST_BIN (user_data), element);
leo_sobral@805
   900
      continue;
leo_sobral@805
   901
    }
leo_sobral@805
   902
leo_sobral@805
   903
    linked = TRUE;
leo_sobral@805
   904
    break;
leo_sobral@805
   905
  }
leo_sobral@805
   906
leo_sobral@805
   907
  g_list_free (comp);
leo_sobral@805
   908
  if (linked == FALSE) {
leo_sobral@811
   909
    GST_WARNING ("GstFlow ERROR");
leo_sobral@805
   910
  }
leo_sobral@805
   911
  GST_PAD_STREAM_UNLOCK (pad);
renatofilho@787
   912
}
renatofilho@787
   913
renatofilho@787
   914
static void
leo_sobral@811
   915
removed_decoded_pad_cb (GstElement *object,
leo_sobral@811
   916
                        GstPad* pad,
leo_sobral@811
   917
                        gpointer user_data)
renatofilho@787
   918
{
leo_sobral@811
   919
  GstElement *sink;
leo_sobral@811
   920
leo_sobral@811
   921
  GST_DEBUG("removed_decoded_pad_cb");
leo_sobral@811
   922
leo_sobral@811
   923
  sink = gst_pad_get_parent_element (pad);
leo_sobral@811
   924
leo_sobral@811
   925
  if (sink)
leo_sobral@811
   926
    gst_bin_remove (GST_BIN (user_data), sink);
leo_sobral@811
   927
}
leo_sobral@811
   928
leo_sobral@811
   929
static GValue*
leo_sobral@811
   930
convert_volume_base (GstPlayBinMaemo *pbm, gfloat volume)
leo_sobral@811
   931
{
leo_sobral@811
   932
  GValue value = { 0, };
leo_sobral@811
   933
  GValue *converted_vol = g_new0(GValue, 1);
leo_sobral@811
   934
leo_sobral@811
   935
  GParamSpec* vol_spec = g_object_class_find_property (
leo_sobral@811
   936
    G_OBJECT_GET_CLASS (pbm->volume_element), "volume");
leo_sobral@811
   937
leo_sobral@811
   938
  g_value_init (&value, vol_spec->value_type);
leo_sobral@811
   939
  g_value_init (converted_vol, vol_spec->value_type);
leo_sobral@811
   940
leo_sobral@811
   941
  g_object_get_property (G_OBJECT (pbm->volume_element), "volume", &value);
leo_sobral@811
   942
leo_sobral@811
   943
  /* convert volume from double to int range if needed */
leo_sobral@811
   944
  switch (G_VALUE_TYPE (&value)) {
leo_sobral@811
   945
    case G_TYPE_UINT:
leo_sobral@811
   946
    {
leo_sobral@811
   947
      GParamSpecUInt *puint = G_PARAM_SPEC_UINT (vol_spec);
leo_sobral@811
   948
      guint scale = puint->maximum - puint->minimum;
leo_sobral@811
   949
      guint vol_guint = (guint) ((scale * volume) + puint->minimum);
leo_sobral@811
   950
leo_sobral@811
   951
      GST_WARNING ("Range: %u - %u, Converted: %u",
leo_sobral@811
   952
          puint->minimum, puint->maximum, vol_guint);
leo_sobral@811
   953
      g_value_set_uint (converted_vol, vol_guint);
leo_sobral@811
   954
      break;
renatofilho@787
   955
    }
leo_sobral@811
   956
    case G_TYPE_INT:
leo_sobral@811
   957
    {
leo_sobral@811
   958
      GParamSpecInt *pint = G_PARAM_SPEC_INT (vol_spec);
leo_sobral@811
   959
      gint scale = pint->maximum - pint->minimum;
leo_sobral@811
   960
      gint vol_gint = (gint) ((scale * volume) + pint->minimum);
leo_sobral@811
   961
leo_sobral@811
   962
      GST_WARNING ("Range: %d - %d, Converted: %d",
leo_sobral@811
   963
          pint->minimum, pint->maximum, vol_gint);
leo_sobral@811
   964
      g_value_set_int (converted_vol, vol_gint);
leo_sobral@811
   965
      break;
leo_sobral@811
   966
    }
leo_sobral@811
   967
    case G_TYPE_DOUBLE:
leo_sobral@811
   968
    case G_TYPE_FLOAT:
leo_sobral@811
   969
    {
leo_sobral@811
   970
      GST_WARNING ("Default converted to float: %f", volume);
leo_sobral@811
   971
      g_value_set_double (converted_vol, volume);
leo_sobral@811
   972
      break;
leo_sobral@811
   973
    }
leo_sobral@811
   974
    default:
leo_sobral@811
   975
      GST_WARNING ("Dont know how to convert volume");
leo_sobral@811
   976
  }
leo_sobral@811
   977
leo_sobral@811
   978
  return converted_vol;
leo_sobral@811
   979
}
leo_sobral@811
   980
leo_sobral@811
   981
static void
renatofilho@852
   982
update_volume (GstPlayBinMaemo *pbm, gdouble volume)
leo_sobral@811
   983
{
leo_sobral@811
   984
  pbm->volume = volume;
leo_sobral@811
   985
  if (pbm->volume_element) {
leo_sobral@811
   986
    GValue *converted_vol = convert_volume_base (pbm, volume);
leo_sobral@811
   987
    g_object_set_property (G_OBJECT (pbm->volume_element), "volume",
leo_sobral@811
   988
                           converted_vol);
leo_sobral@811
   989
    g_value_unset (converted_vol);
leo_sobral@805
   990
  }
renatofilho@787
   991
}
renatofilho@787
   992
renatofilho@787
   993
static void
renatofilho@787
   994
update_xid (GstPlayBinMaemo *pbm)
renatofilho@787
   995
{
leo_sobral@811
   996
  if ((pbm->video_sink != NULL) && (pbm->xid != -1) &&
leo_sobral@811
   997
      (GST_IS_X_OVERLAY (pbm->video_sink))) {
leo_sobral@805
   998
    Display *display;
leo_sobral@805
   999
    g_object_set (G_OBJECT (pbm->video_sink),
leo_sobral@805
  1000
                  "force-aspect-ratio", TRUE, NULL);
leo_sobral@811
  1001
leo_sobral@805
  1002
    display = XOpenDisplay(NULL);
leo_sobral@811
  1003
leo_sobral@805
  1004
    XMapRaised(display, pbm->xid);
leo_sobral@811
  1005
    XSync (display, FALSE);
leo_sobral@811
  1006
leo_sobral@808
  1007
    XSetErrorHandler(x_error_handler);
renatofilho@792
  1008
leo_sobral@805
  1009
    gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (pbm->video_sink),
leo_sobral@805
  1010
                                  pbm->xid);
leo_sobral@805
  1011
  }
renatofilho@787
  1012
}
renatofilho@787
  1013
leo_sobral@808
  1014
static int
leo_sobral@811
  1015
x_error_handler(Display *display,
leo_sobral@811
  1016
                XErrorEvent *event)
leo_sobral@808
  1017
{
leo_sobral@811
  1018
    GST_DEBUG ("In x error handler:");
leo_sobral@808
  1019
leo_sobral@808
  1020
    switch (event->error_code) {
leo_sobral@808
  1021
        case BadWindow:
leo_sobral@811
  1022
            GST_DEBUG ("got bad window");
leo_sobral@808
  1023
            break;
leo_sobral@808
  1024
        case BadDrawable:
leo_sobral@811
  1025
            GST_DEBUG ("got bad drawable");
leo_sobral@808
  1026
            break;
leo_sobral@808
  1027
        case BadGC:
leo_sobral@811
  1028
            GST_DEBUG ("got bad gc");
leo_sobral@808
  1029
            break;
leo_sobral@808
  1030
        default:
leo_sobral@811
  1031
            GST_DEBUG ("unhandled x error = %d", event->error_code);
leo_sobral@808
  1032
    }
leo_sobral@808
  1033
leo_sobral@808
  1034
    return 0;
leo_sobral@808
  1035
}
leo_sobral@808
  1036
renatofilho@787
  1037
static gboolean
renatofilho@792
  1038
add_element (GstPlayBinMaemo *pbm,
renatofilho@792
  1039
             GstElement *child)
renatofilho@792
  1040
{
leo_sobral@805
  1041
  if (gst_bin_add (GST_BIN (pbm), child)) {
leo_sobral@805
  1042
    pbm->elements = g_list_append (pbm->elements, child);
leo_sobral@805
  1043
    return TRUE;
leo_sobral@805
  1044
  }
leo_sobral@805
  1045
  return FALSE;
renatofilho@792
  1046
}
renatofilho@792
  1047
renatofilho@792
  1048
static void
renatofilho@792
  1049
clear_elements (GstPlayBinMaemo *pbm)
renatofilho@792
  1050
{
leo_sobral@805
  1051
  GList *walk;
renatofilho@792
  1052
leo_sobral@805
  1053
  walk = pbm->elements;
renatofilho@792
  1054
leo_sobral@805
  1055
  for (; walk != NULL; walk = walk->next) {
leo_sobral@805
  1056
    GstElement *e = GST_ELEMENT (walk->data);
renatofilho@792
  1057
leo_sobral@805
  1058
    gst_element_set_state (e, GST_STATE_NULL);
leo_sobral@805
  1059
    gst_bin_remove (GST_BIN (pbm), e);
leo_sobral@805
  1060
  }
renatofilho@792
  1061
leo_sobral@805
  1062
  g_list_free (pbm->elements);
leo_sobral@805
  1063
  pbm->elements = NULL;
leo_sobral@805
  1064
  pbm->source = NULL;
leo_sobral@805
  1065
  pbm->volume_element = NULL;
leo_sobral@805
  1066
  pbm->video_sink = NULL;
renatofilho@792
  1067
}
renatofilho@792
  1068
renatofilho@792
  1069
static gboolean
renatofilho@787
  1070
plugin_init(GstPlugin * plugin)
renatofilho@787
  1071
{
renatofilho@787
  1072
#ifdef ENABLE_NLS
leo_sobral@805
  1073
  setlocale(LC_ALL, "");
leo_sobral@805
  1074
  bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
renatofilho@787
  1075
#endif                          /* ENABLE_NLS */
renatofilho@787
  1076
leo_sobral@805
  1077
  if (!gst_element_register(plugin, "playbinmaemo", GST_RANK_SECONDARY,
leo_sobral@805
  1078
                          GST_TYPE_PLAY_BIN_MAEMO)) {
leo_sobral@805
  1079
    return FALSE;
leo_sobral@805
  1080
  }
renatofilho@787
  1081
leo_sobral@805
  1082
  return TRUE;
renatofilho@787
  1083
}
renatofilho@787
  1084
renatofilho@787
  1085
GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
renatofilho@787
  1086
                  GST_VERSION_MINOR,
renatofilho@787
  1087
                  "playbinmaemo",
leo_sobral@796
  1088
                  "A playbin element that uses decodebin2 for automatic playback of audio and video",
renatofilho@787
  1089
                  plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME,
renatofilho@787
  1090
                  GST_PACKAGE_ORIGIN)