1 /* GStreamer Tuner
2 * Copyright (C) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
3 *
4 * tuner.c: tuner design virtual class function wrappers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "tuner.h"
27
28 #include <string.h>
29
30 /**
31 * SECTION:gsttuner
32 * @title: TunEr.h
33 * @short_description: Interface for elements providing tuner operations
34 *
35 * The GstTuner interface is provided by elements that have the ability to
36 * tune into multiple input signals, for example TV or radio capture cards.
37 *
38 * The interpretation of 'tuning into' an input stream depends on the element
39 * implementing the interface. For v4lsrc, it might imply selection of an
40 * input source and/or frequency to be configured on a TV card. Another
41 * GstTuner implementation might be to allow selection of an active input pad
42 * from multiple input pads.
43 *
44 * That said, the GstTuner interface functions are biased toward the
45 * TV capture scenario.
46 *
47 * The general parameters provided are for configuration are:
48 *
49 * * Selection of a current #GstTunerChannel. The current channel
50 * represents the input source (e.g. Composite, S-Video etc for TV capture).
51 * * The #GstTunerNorm for the channel. The norm chooses the
52 * interpretation of the incoming signal for the current channel. For example,
53 * PAL or NTSC, or more specific variants there-of.
54 * * Channel frequency. If the current channel has the ability to tune
55 * between multiple frequencies (if it has the GST_TUNER_CHANNEL_FREQUENCY flag)
56 * then the frequency can be changed/retrieved via the
57 * gst_tuner_set_frequency() and gst_tuner_get_frequency() methods.
58 *
59 * Where applicable, the signal strength can be retrieved and/or monitored
60 * via a signal.
61 *
62 */
63
64 /* FIXME 0.11: check if we need to add API for sometimes-supportedness
65 * (aka making up for GstImplementsInterface removal) */
66
67 /* FIXME 0.11: replace signals with messages (+ make API thread-safe) */
68
69 enum
70 {
71 NORM_CHANGED,
72 CHANNEL_CHANGED,
73 FREQUENCY_CHANGED,
74 SIGNAL_CHANGED,
75 LAST_SIGNAL
76 };
77
78 static guint gst_tuner_signals[LAST_SIGNAL] = { 0 };
79
80 G_DEFINE_INTERFACE (GstTuner, gst_tuner, G_TYPE_INVALID);
81
82 static void
gst_tuner_default_init(GstTunerInterface * iface)83 gst_tuner_default_init (GstTunerInterface * iface)
84 {
85 static gboolean initialized = FALSE;
86
87 if (!initialized) {
88 /**
89 * GstTuner::norm-changed:
90 * @tuner: The element providing the GstTuner interface
91 * @norm: The new configured norm.
92 *
93 * Reports that the current #GstTunerNorm has changed.
94 */
95 gst_tuner_signals[NORM_CHANGED] =
96 g_signal_new ("norm-changed",
97 GST_TYPE_TUNER, G_SIGNAL_RUN_LAST,
98 G_STRUCT_OFFSET (GstTunerInterface, norm_changed),
99 NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_TUNER_NORM);
100 /**
101 * GstTuner::channel-changed:
102 * @tuner: The element providing the GstTuner interface
103 * @channel: The new configured channel.
104 *
105 * Reports that the current #GstTunerChannel has changed.
106 */
107 gst_tuner_signals[CHANNEL_CHANGED] =
108 g_signal_new ("channel-changed",
109 GST_TYPE_TUNER, G_SIGNAL_RUN_LAST,
110 G_STRUCT_OFFSET (GstTunerInterface, channel_changed),
111 NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_TUNER_CHANNEL);
112 /**
113 * GstTuner::frequency-changed:
114 * @tuner: The element providing the GstTuner interface
115 * @frequency: The new frequency (an unsigned long)
116 *
117 * Reports that the current frequency has changed.
118 */
119 gst_tuner_signals[FREQUENCY_CHANGED] =
120 g_signal_new ("frequency-changed",
121 GST_TYPE_TUNER, G_SIGNAL_RUN_LAST,
122 G_STRUCT_OFFSET (GstTunerInterface, frequency_changed),
123 NULL, NULL, NULL, G_TYPE_NONE, 2, GST_TYPE_TUNER_CHANNEL, G_TYPE_ULONG);
124 /**
125 * GstTuner::signal-changed:
126 * @tuner: The element providing the GstTuner interface
127 * @channel: The current #GstTunerChannel
128 * @signal: The new signal strength (an integer)
129 *
130 * Reports that the signal strength has changed.
131 */
132 gst_tuner_signals[SIGNAL_CHANGED] =
133 g_signal_new ("signal-changed",
134 GST_TYPE_TUNER, G_SIGNAL_RUN_LAST,
135 G_STRUCT_OFFSET (GstTunerInterface, signal_changed),
136 NULL, NULL, NULL, G_TYPE_NONE, 2, GST_TYPE_TUNER_CHANNEL, G_TYPE_INT);
137
138 gst_type_mark_as_plugin_api (GST_TYPE_TUNER, 0);
139 gst_type_mark_as_plugin_api (GST_TYPE_TUNER_CHANNEL, 0);
140 gst_type_mark_as_plugin_api (GST_TYPE_TUNER_NORM, 0);
141
142 initialized = TRUE;
143 }
144
145 /* default virtual functions */
146 iface->list_channels = NULL;
147 iface->set_channel = NULL;
148 iface->get_channel = NULL;
149
150 iface->list_norms = NULL;
151 iface->set_norm = NULL;
152 iface->get_norm = NULL;
153
154 iface->set_frequency = NULL;
155 iface->get_frequency = NULL;
156 iface->signal_strength = NULL;
157 }
158
159 /**
160 * gst_tuner_list_channels:
161 * @tuner: the #GstTuner (a #GstElement) to get the channels from.
162 *
163 * Retrieve a #GList of #GstTunerChannels available
164 * (e.g. 'composite', 's-video', ...) from the given tuner object.
165 *
166 * Returns: A list of channels available on this tuner. The list is
167 * owned by the GstTuner and must not be freed.
168 */
169 const GList *
gst_tuner_list_channels(GstTuner * tuner)170 gst_tuner_list_channels (GstTuner * tuner)
171 {
172 GstTunerInterface *iface;
173
174 g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
175
176 iface = GST_TUNER_GET_INTERFACE (tuner);
177 if (iface->list_channels) {
178 return iface->list_channels (tuner);
179 }
180
181 return NULL;
182 }
183
184 /**
185 * gst_tuner_set_channel:
186 * @tuner: the #GstTuner (a #GstElement) that owns the channel.
187 * @channel: the channel to tune to.
188 *
189 * Tunes the object to the given channel, which should be one of the
190 * channels returned by gst_tuner_list_channels().
191 */
192
193 void
gst_tuner_set_channel(GstTuner * tuner,GstTunerChannel * channel)194 gst_tuner_set_channel (GstTuner * tuner, GstTunerChannel * channel)
195 {
196 GstTunerInterface *iface;
197
198 g_return_if_fail (GST_IS_TUNER (tuner));
199
200 iface = GST_TUNER_GET_INTERFACE (tuner);
201 if (iface->set_channel) {
202 iface->set_channel (tuner, channel);
203 }
204 }
205
206 /**
207 * gst_tuner_get_channel:
208 * @tuner: the #GstTuner (a #GstElement) to get the current channel from.
209 *
210 * Retrieve the current channel from the tuner.
211 *
212 * Returns: the current channel of the tuner object.
213 */
214
215 GstTunerChannel *
gst_tuner_get_channel(GstTuner * tuner)216 gst_tuner_get_channel (GstTuner * tuner)
217 {
218 GstTunerInterface *iface;
219
220 g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
221
222 iface = GST_TUNER_GET_INTERFACE (tuner);
223 if (iface->get_channel) {
224 return iface->get_channel (tuner);
225 }
226
227 return NULL;
228 }
229
230 /**
231 * gst_tuner_list_norms:
232 * @tuner: the #GstTuner (*a #GstElement) to get the list of norms from.
233 *
234 * Retrieve a GList of available #GstTunerNorm settings for the currently
235 * tuned channel on the given tuner object.
236 *
237 * Returns: A list of norms available on the current channel for this
238 * tuner object. The list is owned by the GstTuner and must not
239 * be freed.
240 */
241
242 const GList *
gst_tuner_list_norms(GstTuner * tuner)243 gst_tuner_list_norms (GstTuner * tuner)
244 {
245 GstTunerInterface *iface;
246
247 g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
248
249 iface = GST_TUNER_GET_INTERFACE (tuner);
250 if (iface->list_norms) {
251 return iface->list_norms (tuner);
252 }
253
254 return NULL;
255 }
256
257 /**
258 * gst_tuner_set_norm:
259 * @tuner: the #GstTuner (a #GstElement) to set the norm on.
260 * @norm: the norm to use for the current channel.
261 *
262 * Changes the video norm on this tuner to the given norm, which should be
263 * one of the norms returned by gst_tuner_list_norms().
264 */
265
266 void
gst_tuner_set_norm(GstTuner * tuner,GstTunerNorm * norm)267 gst_tuner_set_norm (GstTuner * tuner, GstTunerNorm * norm)
268 {
269 GstTunerInterface *iface;
270
271 g_return_if_fail (GST_IS_TUNER (tuner));
272
273 iface = GST_TUNER_GET_INTERFACE (tuner);
274 if (iface->set_norm) {
275 iface->set_norm (tuner, norm);
276 }
277 }
278
279 /**
280 * gst_tuner_get_norm:
281 * @tuner: the #GstTuner (a #GstElement) to get the current norm from.
282 *
283 * Get the current video norm from the given tuner object for the
284 * currently selected channel.
285 *
286 * Returns: the current norm.
287 */
288
289 GstTunerNorm *
gst_tuner_get_norm(GstTuner * tuner)290 gst_tuner_get_norm (GstTuner * tuner)
291 {
292 GstTunerInterface *iface;
293
294 g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
295
296 iface = GST_TUNER_GET_INTERFACE (tuner);
297 if (iface->get_norm) {
298 return iface->get_norm (tuner);
299 }
300
301 return NULL;
302 }
303
304 /**
305 * gst_tuner_set_frequency:
306 * @tuner: The #GstTuner (a #GstElement) that owns the given channel.
307 * @channel: The #GstTunerChannel to set the frequency on.
308 * @frequency: The frequency to tune in to.
309 *
310 * Sets a tuning frequency on the given tuner/channel. Note that this
311 * requires the given channel to be a "tuning" channel, which can be
312 * checked using GST_TUNER_CHANNEL_HAS_FLAG (), with the proper flag
313 * being GST_TUNER_CHANNEL_FREQUENCY.
314 *
315 * The frequency is in Hz, with minimum steps indicated by the
316 * frequency_multiplicator provided in the #GstTunerChannel. The
317 * valid range is provided in the min_frequency and max_frequency properties
318 * of the #GstTunerChannel.
319 */
320
321 void
gst_tuner_set_frequency(GstTuner * tuner,GstTunerChannel * channel,gulong frequency)322 gst_tuner_set_frequency (GstTuner * tuner,
323 GstTunerChannel * channel, gulong frequency)
324 {
325 GstTunerInterface *iface;
326
327 g_return_if_fail (GST_IS_TUNER (tuner));
328 g_return_if_fail (GST_IS_TUNER_CHANNEL (channel));
329 g_return_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
330 GST_TUNER_CHANNEL_FREQUENCY));
331
332 iface = GST_TUNER_GET_INTERFACE (tuner);
333 if (iface->set_frequency) {
334 iface->set_frequency (tuner, channel, frequency);
335 }
336 }
337
338 /**
339 * gst_tuner_get_frequency:
340 * @tuner: The #GstTuner (a #GstElement) that owns the given channel.
341 * @channel: The #GstTunerChannel to retrieve the frequency from.
342 *
343 * Retrieve the current frequency from the given channel. As for
344 * gst_tuner_set_frequency(), the #GstTunerChannel must support frequency
345 * operations, as indicated by the GST_TUNER_CHANNEL_FREQUENCY flag.
346 *
347 * Returns: The current frequency, or 0 on error.
348 */
349
350 gulong
gst_tuner_get_frequency(GstTuner * tuner,GstTunerChannel * channel)351 gst_tuner_get_frequency (GstTuner * tuner, GstTunerChannel * channel)
352 {
353 GstTunerInterface *iface;
354
355 g_return_val_if_fail (GST_IS_TUNER (tuner), 0);
356 g_return_val_if_fail (GST_IS_TUNER_CHANNEL (channel), 0);
357 g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
358 GST_TUNER_CHANNEL_FREQUENCY), 0);
359
360 iface = GST_TUNER_GET_INTERFACE (tuner);
361
362 if (iface->get_frequency) {
363 return iface->get_frequency (tuner, channel);
364 }
365
366 return 0;
367 }
368
369 /**
370 * gst_tuner_signal_strength:
371 * @tuner: the #GstTuner (a #GstElement) that owns the given channel.
372 * @channel: the #GstTunerChannel to get the signal strength from.
373 *
374 * Get the strength of the signal on this channel. Note that this
375 * requires the current channel to be a "tuning" channel, i.e. a
376 * channel on which frequency can be set. This can be checked using
377 * GST_TUNER_CHANNEL_HAS_FLAG (), and the appropriate flag to check
378 * for is GST_TUNER_CHANNEL_FREQUENCY.
379 *
380 * The valid range of the signal strength is indicated in the
381 * min_signal and max_signal properties of the #GstTunerChannel.
382 *
383 * Returns: Signal strength, or 0 on error.
384 */
385 gint
gst_tuner_signal_strength(GstTuner * tuner,GstTunerChannel * channel)386 gst_tuner_signal_strength (GstTuner * tuner, GstTunerChannel * channel)
387 {
388 GstTunerInterface *iface;
389
390 g_return_val_if_fail (GST_IS_TUNER (tuner), 0);
391 g_return_val_if_fail (GST_IS_TUNER_CHANNEL (channel), 0);
392 g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel,
393 GST_TUNER_CHANNEL_FREQUENCY), 0);
394
395 iface = GST_TUNER_GET_INTERFACE (tuner);
396 if (iface->signal_strength) {
397 return iface->signal_strength (tuner, channel);
398 }
399
400 return 0;
401 }
402
403 /**
404 * gst_tuner_find_norm_by_name:
405 * @tuner: A #GstTuner instance
406 * @norm: A string containing the name of a #GstTunerNorm
407 *
408 * Look up a #GstTunerNorm by name.
409 *
410 * Returns: A #GstTunerNorm, or NULL if no norm with the provided name
411 * is available.
412 */
413 GstTunerNorm *
gst_tuner_find_norm_by_name(GstTuner * tuner,gchar * norm)414 gst_tuner_find_norm_by_name (GstTuner * tuner, gchar * norm)
415 {
416 GList *walk;
417
418 g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
419 g_return_val_if_fail (norm != NULL, NULL);
420
421 walk = (GList *) gst_tuner_list_norms (tuner);
422 while (walk) {
423 if (strcmp (GST_TUNER_NORM (walk->data)->label, norm) == 0)
424 return GST_TUNER_NORM (walk->data);
425 walk = g_list_next (walk);
426 }
427 return NULL;
428 }
429
430 /**
431 * gst_tuner_find_channel_by_name:
432 * @tuner: A #GstTuner instance
433 * @channel: A string containing the name of a #GstTunerChannel
434 *
435 * Look up a #GstTunerChannel by name.
436 *
437 * Returns: A #GstTunerChannel, or NULL if no channel with the provided name
438 * is available.
439 */
440 GstTunerChannel *
gst_tuner_find_channel_by_name(GstTuner * tuner,gchar * channel)441 gst_tuner_find_channel_by_name (GstTuner * tuner, gchar * channel)
442 {
443 GList *walk;
444
445 g_return_val_if_fail (GST_IS_TUNER (tuner), NULL);
446 g_return_val_if_fail (channel != NULL, NULL);
447
448 walk = (GList *) gst_tuner_list_channels (tuner);
449 while (walk) {
450 if (strcmp (GST_TUNER_CHANNEL (walk->data)->label, channel) == 0)
451 return GST_TUNER_CHANNEL (walk->data);
452 walk = g_list_next (walk);
453 }
454 return NULL;
455 }
456
457 /**
458 * gst_tuner_channel_changed:
459 * @tuner: A #GstTuner instance
460 * @channel: A #GstTunerChannel instance
461 *
462 * Called by elements implementing the #GstTuner interface when the
463 * current channel changes. Fires the #GstTuner::channel-changed signal.
464 */
465 void
gst_tuner_channel_changed(GstTuner * tuner,GstTunerChannel * channel)466 gst_tuner_channel_changed (GstTuner * tuner, GstTunerChannel * channel)
467 {
468 g_return_if_fail (GST_IS_TUNER (tuner));
469 g_return_if_fail (GST_IS_TUNER_CHANNEL (channel));
470
471 g_signal_emit (G_OBJECT (tuner),
472 gst_tuner_signals[CHANNEL_CHANGED], 0, channel);
473 }
474
475 /**
476 * gst_tuner_norm_changed:
477 * @tuner: A #GstTuner instance
478 * @norm: A #GstTunerNorm instance
479 *
480 * Called by elements implementing the #GstTuner interface when the
481 * current norm changes. Fires the #GstTuner::norm-changed signal.
482 *
483 */
484 void
gst_tuner_norm_changed(GstTuner * tuner,GstTunerNorm * norm)485 gst_tuner_norm_changed (GstTuner * tuner, GstTunerNorm * norm)
486 {
487 g_return_if_fail (GST_IS_TUNER (tuner));
488 g_return_if_fail (GST_IS_TUNER_NORM (norm));
489
490 g_signal_emit (G_OBJECT (tuner), gst_tuner_signals[NORM_CHANGED], 0, norm);
491 }
492
493 /**
494 * gst_tuner_frequency_changed:
495 * @tuner: A #GstTuner instance
496 * @channel: The current #GstTunerChannel
497 * @frequency: The new frequency setting
498 *
499 * Called by elements implementing the #GstTuner interface when the
500 * configured frequency changes. Fires the #GstTuner::frequency-changed
501 * signal on the tuner, and the #GstTunerChannel::frequency-changed signal
502 * on the channel.
503 */
504 void
gst_tuner_frequency_changed(GstTuner * tuner,GstTunerChannel * channel,gulong frequency)505 gst_tuner_frequency_changed (GstTuner * tuner,
506 GstTunerChannel * channel, gulong frequency)
507 {
508 g_return_if_fail (GST_IS_TUNER (tuner));
509 g_return_if_fail (GST_IS_TUNER_CHANNEL (channel));
510
511 g_signal_emit (G_OBJECT (tuner),
512 gst_tuner_signals[FREQUENCY_CHANGED], 0, channel, frequency);
513
514 g_signal_emit_by_name (G_OBJECT (channel), "frequency_changed", frequency);
515 }
516
517 /**
518 * gst_tuner_signal_changed:
519 * @tuner: A #GstTuner instance
520 * @channel: The current #GstTunerChannel
521 * @signal: The new signal strength
522 *
523 * Called by elements implementing the #GstTuner interface when the
524 * incoming signal strength changes. Fires the #GstTuner::signal-changed
525 * signal on the tuner and the #GstTunerChannel::signal-changed signal on
526 * the channel.
527 */
528 void
gst_tuner_signal_changed(GstTuner * tuner,GstTunerChannel * channel,gint signal)529 gst_tuner_signal_changed (GstTuner * tuner,
530 GstTunerChannel * channel, gint signal)
531 {
532 g_return_if_fail (GST_IS_TUNER (tuner));
533 g_return_if_fail (GST_IS_TUNER_CHANNEL (channel));
534
535 g_signal_emit (G_OBJECT (tuner),
536 gst_tuner_signals[SIGNAL_CHANGED], 0, channel, signal);
537
538 g_signal_emit_by_name (G_OBJECT (channel), "signal_changed", signal);
539 }
540