~ubuntu-branches/debian/stretch/cheese/stretch

« back to all changes in this revision

Viewing changes to libcheese/cheese-camera-device.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Biebl
  • Date: 2010-05-04 17:37:18 UTC
  • mfrom: (1.1.13 upstream)
  • Revision ID: james.westby@ubuntu.com-20100504173718-k2rx3nryi4vd0xyx
Tags: 2.30.1-1
* New upstream release.
  - HAL dependency has been dropped. Use (g)udev for v4l capability probing
    on Linux. Closes: #573774
  - Split code into separate libraries.
* debian/control.in
  - Drop Build-Depends on libhal-dev.
  - Drop Build-Depends on libebook1.2-dev.
  - Bump Build-Depends on libgtk2.0-dev to (>= 2.19.1).
  - Bump Build-Depends on libgstreamer*-dev to (>= 0.10.23).
  - Add Build-Depends on libcanberra-gtk-dev.
  - Add Build-Depends on libxtst-dev.
  - Add Build-Depends on libgudev-1.0-dev on Linux.
  - Bump Standards-Version to 3.8.4. No further changes.
* Switch to source format 3.0 (quilt)
  - Add debian/source/format.
* debian/rules
  - Drop lpia specific configure flags, lpia is dead.
* Update package layout (based on work by Ubuntu)
  - Move data files into new cheese-common package.
  - Keep binary along with its desktop and dbus service file in the cheese
    package.
  - Add libcheese-gtk18 and libcheese-gtk-dev package for the new
    libcheese-gtk library. Use a symbols file for improved shlibs
    dependencies.
  - Add Conflicts/Replaces to cheese-common to ensure proper upgrades from
    previous versions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2009 Filippo Argiolas <filippo.argiolas@gmail.com>
 
3
 * Copyright © 2007,2008 Jaap Haitsma <jaap@haitsma.org>
 
4
 * Copyright © 2007-2009 daniel g. siegel <dgsiegel@gnome.org>
 
5
 * Copyright © 2008 Ryan Zeigler <zeiglerr@gmail.com>
 
6
 *
 
7
 * Licensed under the GNU General Public License Version 2
 
8
 *
 
9
 * This program is free software; you can redistribute it and/or modify
 
10
 * it under the terms of the GNU General Public License as published by
 
11
 * the Free Software Foundation; either version 2 of the License, or
 
12
 * (at your option) any later version.
 
13
 *
 
14
 * This program is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 * GNU General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU General Public License
 
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
21
 */
 
22
 
 
23
#ifdef HAVE_CONFIG_H
 
24
  #include <cheese-config.h>
 
25
#endif
 
26
 
 
27
#include <glib.h>
 
28
#include <glib/gi18n.h>
 
29
#include <gio/gio.h>
 
30
 
 
31
#include "cheese-camera-device.h"
 
32
 
 
33
static void     cheese_camera_device_initable_iface_init (GInitableIface  *iface);
 
34
static gboolean cheese_camera_device_initable_init       (GInitable       *initable,
 
35
                                                          GCancellable    *cancellable,
 
36
                                                          GError         **error);
 
37
 
 
38
G_DEFINE_TYPE_WITH_CODE (CheeseCameraDevice, cheese_camera_device, G_TYPE_OBJECT,
 
39
                         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
 
40
                                                cheese_camera_device_initable_iface_init))
 
41
 
 
42
#define CHEESE_CAMERA_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CHEESE_TYPE_CAMERA_DEVICE, \
 
43
                                                                          CheeseCameraDevicePrivate))
 
44
 
 
45
#define CHEESE_CAMERA_DEVICE_ERROR cheese_camera_device_error_quark ()
 
46
 
 
47
enum CheeseCameraDeviceError
 
48
{
 
49
  CHEESE_CAMERA_DEVICE_ERROR_UNKNOWN,
 
50
  CHEESE_CAMERA_DEVICE_ERROR_NOT_SUPPORTED,
 
51
  CHEESE_CAMERA_DEVICE_ERROR_UNSUPPORTED_CAPS
 
52
};
 
53
 
 
54
GST_DEBUG_CATEGORY (cheese_camera_device_cat);
 
55
#define GST_CAT_DEFAULT cheese_camera_device_cat
 
56
 
 
57
static gchar *supported_formats[] = {
 
58
  "video/x-raw-rgb",
 
59
  "video/x-raw-yuv",
 
60
  NULL
 
61
};
 
62
 
 
63
/* FIXME: make this configurable */
 
64
#define CHEESE_MAXIMUM_RATE 30 /* fps */
 
65
 
 
66
enum
 
67
{
 
68
  PROP_0,
 
69
  PROP_NAME,
 
70
  PROP_FILE,
 
71
  PROP_ID,
 
72
  PROP_API
 
73
};
 
74
 
 
75
typedef struct
 
76
{
 
77
  gchar *device;
 
78
  gchar *id;
 
79
  const gchar *src;
 
80
  gchar *name;
 
81
  gint api;
 
82
  GstCaps *caps;
 
83
  GList *formats;
 
84
 
 
85
  GError *construct_error;
 
86
} CheeseCameraDevicePrivate;
 
87
 
 
88
GQuark
 
89
cheese_camera_device_error_quark (void)
 
90
{
 
91
  return g_quark_from_static_string ("cheese-camera-device-error-quark");
 
92
}
 
93
 
 
94
/* CheeseVideoFormat */
 
95
 
 
96
static CheeseVideoFormat *
 
97
cheese_video_format_copy (const CheeseVideoFormat *format)
 
98
{
 
99
  return g_slice_dup (CheeseVideoFormat, format);
 
100
}
 
101
 
 
102
static void
 
103
cheese_video_format_free (CheeseVideoFormat *format)
 
104
{
 
105
  if (G_LIKELY (format != NULL))
 
106
    g_slice_free (CheeseVideoFormat, format);
 
107
}
 
108
 
 
109
GType
 
110
cheese_video_format_get_type (void)
 
111
{
 
112
  static GType our_type = 0;
 
113
 
 
114
  if (G_UNLIKELY (our_type == 0))
 
115
    our_type =
 
116
      g_boxed_type_register_static ("CheeseVideoFormat",
 
117
                                    (GBoxedCopyFunc) cheese_video_format_copy,
 
118
                                    (GBoxedFreeFunc) cheese_video_format_free);
 
119
  return our_type;
 
120
}
 
121
 
 
122
/* the rest */
 
123
 
 
124
static gint
 
125
compare_formats (gconstpointer a, gconstpointer b)
 
126
{
 
127
  const CheeseVideoFormat *c = a;
 
128
  const CheeseVideoFormat *d = b;
 
129
 
 
130
  /* descending sort for rectangle area */
 
131
  return (d->width * d->height - c->width * c->height);
 
132
}
 
133
 
 
134
static
 
135
GstCaps *
 
136
cheese_webcam_device_filter_caps (CheeseCameraDevice *device, const GstCaps *caps, GStrv formats)
 
137
{
 
138
/*  CheeseCameraDevicePrivate *priv =
 
139
 *  CHEESE_CAMERA_DEVICE_GET_PRIVATE (device); */
 
140
  GstCaps *filter;
 
141
  GstCaps *allowed;
 
142
  gint i;
 
143
 
 
144
  filter = gst_caps_new_simple (formats[0],
 
145
                                "framerate", GST_TYPE_FRACTION_RANGE,
 
146
                                0, 1, CHEESE_MAXIMUM_RATE, 1,
 
147
                                NULL);
 
148
 
 
149
  for (i = 1; i < g_strv_length (formats); i++)
 
150
  {
 
151
    gst_caps_append (filter,
 
152
                     gst_caps_new_simple (formats[i],
 
153
                                          "framerate", GST_TYPE_FRACTION_RANGE,
 
154
                                          0, 1, CHEESE_MAXIMUM_RATE, 1,
 
155
                                          NULL));
 
156
  }
 
157
 
 
158
  allowed = gst_caps_intersect (caps, filter);
 
159
 
 
160
  GST_DEBUG ("Supported caps %" GST_PTR_FORMAT, caps);
 
161
  GST_DEBUG ("Filter caps %" GST_PTR_FORMAT, filter);
 
162
  GST_DEBUG ("Filtered caps %" GST_PTR_FORMAT, allowed);
 
163
 
 
164
  gst_caps_unref (filter);
 
165
 
 
166
  return allowed;
 
167
}
 
168
 
 
169
static void
 
170
cheese_camera_device_add_format (CheeseCameraDevice *device, CheeseVideoFormat *format)
 
171
{
 
172
  CheeseCameraDevicePrivate *priv =
 
173
    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
 
174
  GList *l;
 
175
 
 
176
  for (l = priv->formats; l != NULL; l = l->next)
 
177
  {
 
178
    CheeseVideoFormat *item = l->data;
 
179
    if ((item != NULL) &&
 
180
        (item->width == format->width) &&
 
181
        (item->height == format->height)) return;
 
182
  }
 
183
 
 
184
  GST_INFO ("%dx%d", format->width, format->height);
 
185
 
 
186
  priv->formats = g_list_append (priv->formats, format);
 
187
}
 
188
 
 
189
static void
 
190
free_format_list (CheeseCameraDevice *device)
 
191
{
 
192
  CheeseCameraDevicePrivate *priv =
 
193
    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
 
194
 
 
195
  GList *l;
 
196
 
 
197
  for (l = priv->formats; l != NULL; l = l->next)
 
198
    g_free (l->data);
 
199
  g_list_free (priv->formats);
 
200
  priv->formats = NULL;
 
201
}
 
202
 
 
203
static void
 
204
cheese_webcam_device_update_format_table (CheeseCameraDevice *device)
 
205
{
 
206
  CheeseCameraDevicePrivate *priv =
 
207
    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
 
208
 
 
209
  int i;
 
210
  int num_structures;
 
211
 
 
212
  free_format_list (device);
 
213
 
 
214
  num_structures = gst_caps_get_size (priv->caps);
 
215
  for (i = 0; i < num_structures; i++)
 
216
  {
 
217
    GstStructure *structure;
 
218
    const GValue *width, *height;
 
219
    structure = gst_caps_get_structure (priv->caps, i);
 
220
 
 
221
    width  = gst_structure_get_value (structure, "width");
 
222
    height = gst_structure_get_value (structure, "height");
 
223
 
 
224
    if (G_VALUE_HOLDS_INT (width))
 
225
    {
 
226
      CheeseVideoFormat *format = g_new0 (CheeseVideoFormat, 1);
 
227
 
 
228
      gst_structure_get_int (structure, "width", &(format->width));
 
229
      gst_structure_get_int (structure, "height", &(format->height));
 
230
      cheese_camera_device_add_format (device, format);
 
231
    }
 
232
    else if (GST_VALUE_HOLDS_INT_RANGE (width))
 
233
    {
 
234
      int min_width, max_width, min_height, max_height;
 
235
      int cur_width, cur_height;
 
236
 
 
237
      min_width  = gst_value_get_int_range_min (width);
 
238
      max_width  = gst_value_get_int_range_max (width);
 
239
      min_height = gst_value_get_int_range_min (height);
 
240
      max_height = gst_value_get_int_range_max (height);
 
241
 
 
242
      cur_width  = min_width;
 
243
      cur_height = min_height;
 
244
 
 
245
      /* Gstreamer will sometimes give us a range with min_xxx == max_xxx,
 
246
       * we use <= here (and not below) to make this work */
 
247
      while (cur_width <= max_width && cur_height <= max_height)
 
248
      {
 
249
        CheeseVideoFormat *format = g_new0 (CheeseVideoFormat, 1);
 
250
 
 
251
        format->width  = cur_width;
 
252
        format->height = cur_height;
 
253
 
 
254
        cheese_camera_device_add_format (device, format);
 
255
 
 
256
        cur_width  *= 2;
 
257
        cur_height *= 2;
 
258
      }
 
259
 
 
260
      cur_width  = max_width;
 
261
      cur_height = max_height;
 
262
      while (cur_width > min_width && cur_height > min_height)
 
263
      {
 
264
        CheeseVideoFormat *format = g_new0 (CheeseVideoFormat, 1);
 
265
 
 
266
        format->width  = cur_width;
 
267
        format->height = cur_height;
 
268
 
 
269
        cheese_camera_device_add_format (device, format);
 
270
 
 
271
        cur_width  /= 2;
 
272
        cur_height /= 2;
 
273
      }
 
274
    }
 
275
    else
 
276
    {
 
277
      g_critical ("GValue type %s, cannot be handled for resolution width", G_VALUE_TYPE_NAME (width));
 
278
    }
 
279
  }
 
280
}
 
281
 
 
282
static void
 
283
cheese_camera_device_get_caps (CheeseCameraDevice *device)
 
284
{
 
285
  CheeseCameraDevicePrivate *priv =
 
286
    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
 
287
 
 
288
  gchar               *pipeline_desc;
 
289
  GstElement          *pipeline;
 
290
  GstStateChangeReturn ret;
 
291
  GstMessage          *msg;
 
292
  GstBus              *bus;
 
293
  GError              *err = NULL;
 
294
 
 
295
  pipeline_desc = g_strdup_printf ("%s name=source device=%s ! fakesink",
 
296
                                   priv->src, priv->device);
 
297
  pipeline = gst_parse_launch (pipeline_desc, &err);
 
298
  if ((pipeline != NULL) && (err == NULL))
 
299
  {
 
300
    /* Start the pipeline and wait for max. 10 seconds for it to start up */
 
301
    gst_element_set_state (pipeline, GST_STATE_READY);
 
302
    ret = gst_element_get_state (pipeline, NULL, NULL, 10 * GST_SECOND);
 
303
 
 
304
    /* Check if any error messages were posted on the bus */
 
305
    bus = gst_element_get_bus (pipeline);
 
306
    msg = gst_bus_pop_filtered (bus, GST_MESSAGE_ERROR);
 
307
    gst_object_unref (bus);
 
308
 
 
309
    if ((msg == NULL) && (ret == GST_STATE_CHANGE_SUCCESS))
 
310
    {
 
311
      GstElement *src;
 
312
      GstPad     *pad;
 
313
      GstCaps    *caps;
 
314
 
 
315
      src = gst_bin_get_by_name (GST_BIN (pipeline), "source");
 
316
 
 
317
      GST_LOG ("Device: %s (%s)\n", priv->name, priv->device);
 
318
      pad        = gst_element_get_pad (src, "src");
 
319
      caps       = gst_pad_get_caps (pad);
 
320
      priv->caps = cheese_webcam_device_filter_caps (device, caps, supported_formats);
 
321
      if (!gst_caps_is_empty (priv->caps))
 
322
        cheese_webcam_device_update_format_table (device);
 
323
      else {
 
324
        g_set_error_literal (&priv->construct_error,
 
325
                             CHEESE_CAMERA_DEVICE_ERROR,
 
326
                             CHEESE_CAMERA_DEVICE_ERROR_UNSUPPORTED_CAPS,
 
327
                             _("Device capabilities not supported"));
 
328
 
 
329
      }
 
330
 
 
331
      gst_object_unref (pad);
 
332
      gst_caps_unref (caps);
 
333
    }
 
334
    gst_element_set_state (pipeline, GST_STATE_NULL);
 
335
    gst_object_unref (pipeline);
 
336
  }
 
337
 
 
338
  if (err)
 
339
    g_error_free (err);
 
340
 
 
341
  g_free (pipeline_desc);
 
342
}
 
343
 
 
344
static void
 
345
cheese_camera_device_constructed (GObject *object)
 
346
{
 
347
  CheeseCameraDevice *device = CHEESE_CAMERA_DEVICE (object);
 
348
  CheeseCameraDevicePrivate *priv   =
 
349
    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
 
350
 
 
351
  priv->src = (priv->api == 2) ? "v4l2src" : "v4lsrc";
 
352
 
 
353
  cheese_camera_device_get_caps (device);
 
354
 
 
355
  if (G_OBJECT_CLASS (cheese_camera_device_parent_class)->constructed)
 
356
    G_OBJECT_CLASS (cheese_camera_device_parent_class)->constructed (object);
 
357
}
 
358
 
 
359
static void
 
360
cheese_camera_device_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 
361
{
 
362
  CheeseCameraDevice        *device = CHEESE_CAMERA_DEVICE (object);
 
363
  CheeseCameraDevicePrivate *priv   =
 
364
    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
 
365
 
 
366
  switch (prop_id)
 
367
  {
 
368
    case PROP_NAME:
 
369
      g_value_set_string (value, priv->name);
 
370
      break;
 
371
    case PROP_FILE:
 
372
      g_value_set_string (value, priv->device);
 
373
      break;
 
374
    case PROP_ID:
 
375
      g_value_set_string (value, priv->id);
 
376
      break;
 
377
    case PROP_API:
 
378
      g_value_set_int (value, priv->api);
 
379
      break;
 
380
    default:
 
381
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
382
      break;
 
383
  }
 
384
}
 
385
 
 
386
static void
 
387
cheese_camera_device_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
 
388
{
 
389
  CheeseCameraDevice        *device = CHEESE_CAMERA_DEVICE (object);
 
390
  CheeseCameraDevicePrivate *priv   =
 
391
    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
 
392
 
 
393
  switch (prop_id)
 
394
  {
 
395
    case PROP_NAME:
 
396
      if (priv->name)
 
397
        g_free (priv->name);
 
398
      priv->name = g_value_dup_string (value);
 
399
      break;
 
400
    case PROP_ID:
 
401
      if (priv->id)
 
402
        g_free (priv->id);
 
403
      priv->id = g_value_dup_string (value);
 
404
      break;
 
405
    case PROP_FILE:
 
406
      if (priv->device)
 
407
        g_free (priv->device);
 
408
      priv->device = g_value_dup_string (value);
 
409
      break;
 
410
    case PROP_API:
 
411
      priv->api = g_value_get_int (value);
 
412
      break;
 
413
    default:
 
414
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
415
      break;
 
416
  }
 
417
}
 
418
 
 
419
static void
 
420
cheese_camera_device_finalize (GObject *object)
 
421
{
 
422
  CheeseCameraDevice        *device = CHEESE_CAMERA_DEVICE (object);
 
423
  CheeseCameraDevicePrivate *priv   =
 
424
    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
 
425
 
 
426
  g_free (priv->device);
 
427
  g_free (priv->id);
 
428
  g_free (priv->name);
 
429
 
 
430
  gst_caps_unref (priv->caps);
 
431
  free_format_list (device);
 
432
 
 
433
  G_OBJECT_CLASS (cheese_camera_device_parent_class)->finalize (object);
 
434
}
 
435
 
 
436
static void
 
437
cheese_camera_device_class_init (CheeseCameraDeviceClass *klass)
 
438
{
 
439
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
440
 
 
441
  if (cheese_camera_device_cat == NULL)
 
442
    GST_DEBUG_CATEGORY_INIT (cheese_camera_device_cat,
 
443
                             "cheese-camera-device",
 
444
                             0, "Cheese Camera Device");
 
445
 
 
446
  object_class->finalize     = cheese_camera_device_finalize;
 
447
  object_class->get_property = cheese_camera_device_get_property;
 
448
  object_class->set_property = cheese_camera_device_set_property;
 
449
  object_class->constructed  = cheese_camera_device_constructed;
 
450
 
 
451
  g_object_class_install_property (object_class, PROP_NAME,
 
452
                                   g_param_spec_string ("name",
 
453
                                                        NULL, NULL, NULL,
 
454
                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
455
 
 
456
  g_object_class_install_property (object_class, PROP_FILE,
 
457
                                   g_param_spec_string ("device-file",
 
458
                                                        NULL, NULL, NULL,
 
459
                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
460
 
 
461
  g_object_class_install_property (object_class, PROP_ID,
 
462
                                   g_param_spec_string ("device-id",
 
463
                                                        NULL, NULL, NULL,
 
464
                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
465
 
 
466
  g_object_class_install_property (object_class, PROP_API,
 
467
                                   g_param_spec_int ("api", NULL, NULL,
 
468
                                                     1, 2, 2,
 
469
                                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
470
  g_type_class_add_private (klass, sizeof (CheeseCameraDevicePrivate));
 
471
}
 
472
 
 
473
static void
 
474
cheese_camera_device_initable_iface_init (GInitableIface *iface)
 
475
{
 
476
  iface->init = cheese_camera_device_initable_init;
 
477
}
 
478
 
 
479
static void
 
480
cheese_camera_device_init (CheeseCameraDevice *device)
 
481
{
 
482
  CheeseCameraDevicePrivate *priv =
 
483
    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
 
484
 
 
485
  priv->device = NULL;
 
486
  priv->id     = NULL;
 
487
  priv->src    = NULL;
 
488
  priv->name   = g_strdup (_("Unknown device"));
 
489
  priv->caps   = gst_caps_new_empty ();
 
490
 
 
491
  priv->formats = NULL;
 
492
 
 
493
  priv->construct_error = NULL;
 
494
}
 
495
 
 
496
static gboolean
 
497
cheese_camera_device_initable_init (GInitable *initable,
 
498
                                    GCancellable *cancellable,
 
499
                                    GError **error)
 
500
{
 
501
  CheeseCameraDevice *device = CHEESE_CAMERA_DEVICE (initable);
 
502
  CheeseCameraDevicePrivate *priv =
 
503
    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
 
504
 
 
505
  g_return_val_if_fail (CHEESE_IS_CAMERA_DEVICE (initable), FALSE);
 
506
 
 
507
  if (cancellable != NULL)
 
508
  {
 
509
    g_set_error_literal (error,
 
510
                         CHEESE_CAMERA_DEVICE_ERROR,
 
511
                         CHEESE_CAMERA_DEVICE_ERROR_NOT_SUPPORTED,
 
512
                         _("Cancellable initialization not supported"));
 
513
    return FALSE;
 
514
  }
 
515
 
 
516
  if (priv->construct_error)
 
517
  {
 
518
    if (error)
 
519
      *error = g_error_copy (priv->construct_error);
 
520
    return FALSE;
 
521
  }
 
522
 
 
523
  return TRUE;
 
524
}
 
525
 
 
526
CheeseCameraDevice *
 
527
cheese_camera_device_new (const gchar *device_id,
 
528
                          const gchar *device_file,
 
529
                          const gchar *product_name,
 
530
                          gint         api_version,
 
531
                          GError **error)
 
532
{
 
533
  return CHEESE_CAMERA_DEVICE (g_initable_new (CHEESE_TYPE_CAMERA_DEVICE,
 
534
                                               NULL, error,
 
535
                                               "device-id", device_id,
 
536
                                               "device-file", device_file,
 
537
                                               "name", product_name,
 
538
                                               "api", api_version,
 
539
                                               NULL));
 
540
}
 
541
 
 
542
/* public methods */
 
543
 
 
544
GList *
 
545
cheese_camera_device_get_format_list (CheeseCameraDevice *device)
 
546
{
 
547
  CheeseCameraDevicePrivate *priv =
 
548
    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
 
549
 
 
550
  return g_list_sort (g_list_copy (priv->formats), compare_formats);
 
551
}
 
552
 
 
553
const gchar *
 
554
cheese_camera_device_get_name (CheeseCameraDevice *device)
 
555
{
 
556
  CheeseCameraDevicePrivate *priv =
 
557
    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
 
558
 
 
559
  return priv->name;
 
560
}
 
561
 
 
562
const gchar *
 
563
cheese_camera_device_get_id (CheeseCameraDevice *device)
 
564
{
 
565
  CheeseCameraDevicePrivate *priv =
 
566
    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
 
567
 
 
568
  return priv->id;
 
569
}
 
570
 
 
571
const gchar *
 
572
cheese_camera_device_get_src (CheeseCameraDevice *device)
 
573
{
 
574
  CheeseCameraDevicePrivate *priv =
 
575
    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
 
576
 
 
577
  return priv->src;
 
578
}
 
579
 
 
580
const gchar *
 
581
cheese_camera_device_get_device_file (CheeseCameraDevice *device)
 
582
{
 
583
  CheeseCameraDevicePrivate *priv =
 
584
    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
 
585
 
 
586
  return priv->device;
 
587
}
 
588
 
 
589
CheeseVideoFormat *
 
590
cheese_camera_device_get_best_format (CheeseCameraDevice *device)
 
591
{
 
592
  CheeseVideoFormat *format = g_boxed_copy (CHEESE_TYPE_VIDEO_FORMAT,
 
593
                                            cheese_camera_device_get_format_list (device)->data);
 
594
 
 
595
  GST_INFO ("%dx%d", format->width, format->height);
 
596
  return format;
 
597
}
 
598
 
 
599
GstCaps *
 
600
cheese_camera_device_get_caps_for_format (CheeseCameraDevice *device,
 
601
                                          CheeseVideoFormat  *format)
 
602
{
 
603
  CheeseCameraDevicePrivate *priv =
 
604
    CHEESE_CAMERA_DEVICE_GET_PRIVATE (device);
 
605
  GstCaps *desired_caps;
 
606
  GstCaps *subset_caps;
 
607
  gint     i;
 
608
 
 
609
  GST_INFO ("Getting caps for %dx%d", format->width, format->height);
 
610
 
 
611
  desired_caps = gst_caps_new_simple (supported_formats[0],
 
612
                                      "width", G_TYPE_INT,
 
613
                                      format->width,
 
614
                                      "height", G_TYPE_INT,
 
615
                                      format->height,
 
616
                                      NULL);
 
617
 
 
618
  for (i = 1; i < g_strv_length (supported_formats); i++)
 
619
  {
 
620
    gst_caps_append (desired_caps,
 
621
                     gst_caps_new_simple (supported_formats[i],
 
622
                                          "width", G_TYPE_INT,
 
623
                                          format->width,
 
624
                                          "height", G_TYPE_INT,
 
625
                                          format->height,
 
626
                                          NULL));
 
627
  }
 
628
 
 
629
  subset_caps = gst_caps_intersect (desired_caps, priv->caps);
 
630
  gst_caps_unref (desired_caps);
 
631
 
 
632
  GST_INFO ("Got %" GST_PTR_FORMAT, subset_caps);
 
633
 
 
634
  return subset_caps;
 
635
}