[svn r310] Added new function to recorder: CHANGE_CHANNEL, which try to move to the next valid channel, instead of passing a valid channel name.
4 * @file gmyth/gmyth_remote_encoder.c
6 * @brief <p> GMythRecorder class defines functions for playing live tv.
8 * The remote encoder is used by gmyth_tvplayer to setup livetv.
10 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
11 * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU Lesser General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 #include "gmyth_recorder.h"
38 #include "gmyth_stringlist.h"
39 #include "gmyth_util.h"
40 #include "gmyth_debug.h"
42 #define GMYTHTV_RECORDER_HEADER "QUERY_RECORDER"
44 static void gmyth_recorder_class_init (GMythRecorderClass *klass);
45 static void gmyth_recorder_init (GMythRecorder *object);
47 static void gmyth_recorder_dispose (GObject *object);
48 static void gmyth_recorder_finalize (GObject *object);
50 G_DEFINE_TYPE(GMythRecorder, gmyth_recorder, G_TYPE_OBJECT)
53 gmyth_recorder_class_init (GMythRecorderClass *klass)
55 GObjectClass *gobject_class;
57 gobject_class = (GObjectClass *) klass;
59 gobject_class->dispose = gmyth_recorder_dispose;
60 gobject_class->finalize = gmyth_recorder_finalize;
64 gmyth_recorder_init (GMythRecorder *gmyth_remote_encoder)
69 gmyth_recorder_dispose (GObject *object)
71 // GMythRecorder *gmyth_remote_encoder = GMYTH_RECORDER(object);
73 G_OBJECT_CLASS (gmyth_recorder_parent_class)->dispose (object);
78 gmyth_recorder_finalize (GObject *object)
80 g_signal_handlers_destroy (object);
82 GMythRecorder *recorder = GMYTH_RECORDER(object);
84 gmyth_debug ("[%s] Closing control socket", __FUNCTION__);
85 gmyth_socket_close_connection(recorder->myth_socket);
86 g_object_unref (recorder->myth_socket);
88 G_OBJECT_CLASS (gmyth_recorder_parent_class)->finalize (object);
91 /** Creates a new instance of GMythRecorder.
93 * @return a new instance of GMythRecorder.
96 gmyth_recorder_new (int num, GString *hostname, gshort port)
98 GMythRecorder *encoder = GMYTH_RECORDER ( g_object_new (
99 GMYTH_RECORDER_TYPE, FALSE ));
101 encoder->recorder_num = num;
102 encoder->hostname = g_string_new (hostname->str);
103 encoder->port = port;
108 /** Configures the remote encoder instance connecting it to Mythtv backend.
110 * @param recorder the GMythRecorder instance.
111 * @return TRUE if successfull, FALSE if any error happens.
114 gmyth_recorder_setup (GMythRecorder *recorder)
117 gmyth_debug ("[%s] Creating socket and connecting to backend", __FUNCTION__);
119 if (recorder->myth_socket == NULL) {
121 recorder->myth_socket = gmyth_socket_new ();
123 if (!gmyth_socket_connect_to_backend ( recorder->myth_socket, recorder->hostname->str,
124 recorder->port, TRUE ) ) {
125 g_warning ("GMythRemoteEncoder: Connection to backend failed");
130 g_warning("Remote encoder socket already created\n");
136 /** Sends the SPAWN_LIVETV command through Mythtv protocol. This command
137 * requests the backend to start capturing TV content.
139 * @param recorder The GMythRecorder instance.
140 * @param tvchain_id The tvchain unique id.
141 * @return true if success, false if any error happens.
144 gmyth_recorder_spawntv (GMythRecorder *recorder, GString *tvchain_id)
146 GMythStringList *str_list;
147 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
149 gmyth_debug ("[%s] Spawntv with tvchain_id = %s", __FUNCTION__, tvchain_id->str);
151 str_list = gmyth_string_list_new ();
153 g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
155 gmyth_string_list_append_string (str_list, tmp_str);
156 gmyth_string_list_append_string (str_list, g_string_new ("SPAWN_LIVETV"));
157 gmyth_string_list_append_string (str_list, tvchain_id);
158 gmyth_string_list_append_int (str_list, 0); // PIP = FALSE (0)
160 gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
162 g_string_free (tmp_str, TRUE);
164 tmp_str = gmyth_string_list_get_string (str_list, 0);
165 if (tmp_str == NULL) {
166 g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str);
170 if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
171 g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str);
172 g_object_unref (str_list);
176 g_object_unref (str_list);
181 /** Sends the command STOP_LIVETV to Mythtv backend.
183 * @param recorder the GMythRecorder instance.
184 * @return true if success, false if any error happens.
187 gmyth_recorder_stop_livetv (GMythRecorder *recorder)
189 GMythStringList *str_list;
190 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
192 gmyth_debug ("[%s]", __FUNCTION__);
194 str_list = gmyth_string_list_new ();
196 g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
197 gmyth_string_list_append_char_array( str_list, "STOP_LIVETV" );
199 gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
201 g_string_free (tmp_str, TRUE);
203 tmp_str = gmyth_string_list_get_string (str_list, 0);
204 if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
205 g_warning ("[%s] Stop livetv request returned %s", __FUNCTION__, tmp_str->str);
206 g_object_unref (str_list);
210 g_object_unref (str_list);
215 /** Sends the FRONTEND_READY command through Mythtv protocol. This command
216 * advertises the backend to start capturing TV content.
218 * @param recorder The GMythRecorder instance.
219 * @return TRUE if success, FALSE if any error happens.
222 gmyth_recorder_send_frontend_ready_command (GMythRecorder *recorder)
224 GMythStringList *str_list;
225 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
227 gmyth_debug ( "[%s] FRONTEND_READY with recorder id = %d", __FUNCTION__, recorder->recorder_num );
229 str_list = gmyth_string_list_new ();
231 g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
233 gmyth_string_list_append_string (str_list, tmp_str);
234 gmyth_string_list_append_string (str_list, g_string_new ("FRONTEND_READY"));
236 gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
238 g_string_free (tmp_str, TRUE);
240 tmp_str = gmyth_string_list_get_string (str_list, 0);
241 if (tmp_str == NULL) {
242 g_warning ("[%s] FRONTEND_READY command request couldn't returns, reason: %s", __FUNCTION__, tmp_str->str);
246 if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
247 g_warning ("[%s] FRONTEND_READY request returned %s", __FUNCTION__, tmp_str->str);
248 g_object_unref (str_list);
252 g_object_unref (str_list);
257 /** Send a CHECK_CHANNEL command request to the backend, in order to find if a
258 * certain channel actually exists.
260 * @param recorder The GMythRecorder instance.
261 * @param channel The new channel to be checked (string format).
262 * @return true if success, false if any error happens.
265 gmyth_recorder_check_channel_name (GMythRecorder *recorder, gchar* channel)
267 GMythStringList *str_list;
268 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
270 gmyth_debug ("[%s] CHECK_CHANNEL with channel = %s", __FUNCTION__, channel);
272 str_list = gmyth_string_list_new ();
274 g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
276 gmyth_string_list_append_string (str_list, tmp_str);
277 gmyth_string_list_append_string (str_list, g_string_new ("CHECK_CHANNEL"));
278 gmyth_string_list_append_char_array (str_list, channel);
280 gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
282 g_string_free (tmp_str, TRUE);
284 tmp_str = gmyth_string_list_get_string (str_list, 0);
285 if (tmp_str == NULL) {
286 g_warning ("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__, tmp_str->str);
290 if (g_ascii_strncasecmp (tmp_str->str, "ok", 2) == 0 || g_ascii_strncasecmp (tmp_str->str, "0", 1) == 0 ) {
291 g_warning ("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__, tmp_str->str);
292 g_object_unref (str_list);
296 g_object_unref (str_list);
301 /** Send a CHECK_CHANNEL command request to the backend, in order to find if a
302 * certain channel actually exists.
304 * @param recorder The GMythRecorder instance.
305 * @param channel The new channel to be checked (decimal integer value).
306 * @return true if success, false if any error happens.
309 gmyth_recorder_check_channel (GMythRecorder *recorder, gint channel)
311 return gmyth_recorder_check_channel_name( recorder, g_strdup_printf( "%d", channel ) );
314 /** Send a SET_CHANNEL command request to the backend, to start streaming on another
315 * TV content channel.
317 * @param recorder The GMythRecorder instance.
318 * @param channel The new channel to be loaded.
319 * @return true if success, false if any error happens.
322 gmyth_recorder_set_channel (GMythRecorder *recorder, gint channel)
324 GMythStringList *str_list;
325 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
327 gmyth_debug ("[%s] SET_CHANNEL with channel = %d", __FUNCTION__, channel);
329 str_list = gmyth_string_list_new ();
331 g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
333 gmyth_string_list_append_string (str_list, tmp_str);
334 gmyth_string_list_append_string (str_list, g_string_new ("SET_CHANNEL"));
335 gmyth_string_list_append_int (str_list, channel);
337 gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
339 g_string_free (tmp_str, TRUE);
341 tmp_str = gmyth_string_list_get_string (str_list, 0);
342 if (tmp_str == NULL) {
343 g_warning ("[%s] SET_CHANNEL request returned %s", __FUNCTION__, tmp_str->str);
347 if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
348 g_warning ("[%s] SET_CHANNEL request returned %s", __FUNCTION__, tmp_str->str);
349 g_object_unref (str_list);
353 g_object_unref (str_list);
358 /** Send a SET_CHANNEL command request to the backend, to start streaming on another
359 * TV content channel.
361 * @param recorder The GMythRecorder instance.
362 * @param channel The new channel to be loaded.
363 * @return true if success, false if any error happens.
366 gmyth_recorder_set_channel_name (GMythRecorder *recorder, const gchar* channel)
368 GMythStringList *str_list;
369 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
371 gmyth_debug ("[%s] SET_CHANNEL with channel name = %s", __FUNCTION__, channel);
373 str_list = gmyth_string_list_new ();
375 g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
377 gmyth_string_list_append_string (str_list, tmp_str);
378 gmyth_string_list_append_string (str_list, g_string_new ("SET_CHANNEL"));
379 gmyth_string_list_append_char_array (str_list, channel);
381 gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
383 g_string_free (tmp_str, TRUE);
385 tmp_str = gmyth_string_list_get_string (str_list, 0);
386 if (tmp_str == NULL) {
387 g_warning ("[%s] SET_CHANNEL name request returned %s", __FUNCTION__, tmp_str->str );
391 if (g_ascii_strncasecmp (tmp_str->str, "ok", 2) || g_ascii_strtoull( tmp_str->str, NULL, 10 ) == 0 ) {
392 g_warning ("[%s] SET_CHANNEL name request returned %s", __FUNCTION__, tmp_str->str);
393 g_object_unref (str_list);
397 g_object_unref (str_list);
403 * Changes the channel of the actual Recorder.
405 * CHANNEL_DIRECTION_UP - Go up one channel in the listing
407 * CHANNEL_DIRECTION_DOWN - Go down one channel in the listing
409 * CHANNEL_DIRECTION_FAVORITE - Go to the next favorite channel
411 * CHANNEL_DIRECTION_SAME - Stay
413 * @param recorder The GMythRecorder instance.
414 * @param direction The new channel direction where to move to.
415 * @return true if success, false if any error happens.
418 gmyth_recorder_change_channel (GMythRecorder *recorder, const GMythRecorderChannelChangeDirection direction)
420 GMythStringList *str_list;
421 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
423 gmyth_debug ("[%s] CHANGE_CHANNEL to the channel direction = %u", __FUNCTION__, direction);
425 str_list = gmyth_string_list_new ();
427 g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
429 gmyth_string_list_append_string (str_list, tmp_str);
430 gmyth_string_list_append_string (str_list, g_string_new ("CHANGE_CHANNEL"));
431 gmyth_string_list_append_int (str_list, direction);
433 gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
435 g_string_free (tmp_str, TRUE);
437 tmp_str = gmyth_string_list_get_string (str_list, 0);
438 if (tmp_str == NULL) {
439 g_warning ("[%s] CHANGE_CHANNEL name request returned %s", __FUNCTION__, tmp_str->str );
443 if (g_ascii_strncasecmp (tmp_str->str, "ok", 2) || g_ascii_strtoull( tmp_str->str, NULL, 10 ) == 0 ) {
444 g_warning ("[%s] CHANGE_CHANNEL name request returned %s", __FUNCTION__, tmp_str->str);
445 g_object_unref (str_list);
449 g_object_unref (str_list);
454 /** Send a PAUSE command request to the backend, to pause streaming on another
455 * TV content channel.
457 * @param recorder The GMythRecorder instance.
458 * @return true if success, false if any error happens.
461 gmyth_recorder_pause_recording ( GMythRecorder *recorder )
463 GMythStringList *str_list;
464 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
466 gmyth_debug ("[%s] PAUSE", __FUNCTION__);
468 str_list = gmyth_string_list_new ();
470 g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
472 gmyth_string_list_append_string (str_list, tmp_str);
473 gmyth_string_list_append_string (str_list, g_string_new ("PAUSE"));
475 gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
477 g_string_free (tmp_str, TRUE);
479 tmp_str = gmyth_string_list_get_string (str_list, 0);
480 if (tmp_str == NULL) {
481 g_warning ("[%s] PAUSE name request returned %s", __FUNCTION__, tmp_str->str);
485 if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
486 g_warning ("[%s] PAUSE name request returned %s", __FUNCTION__, tmp_str->str);
487 g_object_unref (str_list);
491 g_object_unref (str_list);
497 * Requests the actual program info from the MythTV backend server.
499 * @param recorder The GMythRecorder instance.
500 * @return The actual program info.
503 gmyth_recorder_get_current_program_info ( GMythRecorder *recorder )
505 GMythStringList *str_list;
506 GMythProgramInfo *program_info = gmyth_program_info_new();
507 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
509 str_list = gmyth_string_list_new ();
511 g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
513 gmyth_string_list_append_string (str_list, tmp_str);
515 if ( recorder->myth_socket->mythtv_version >= 26 )
516 gmyth_string_list_append_string (str_list, g_string_new ("GET_CURRENT_RECORDING"));
518 gmyth_string_list_append_string (str_list, g_string_new ("GET_PROGRAM_INFO"));
520 gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
522 g_string_free (tmp_str, TRUE);
524 if (str_list == NULL) {
525 g_warning ("[%s] GET_PROGRAM_INFO request returned. Error getting program info, string list equals to NULL!", __FUNCTION__);
529 program_info = gmyth_program_info_from_string_list( str_list );
531 if ( NULL == program_info ) {
532 g_warning ("[%s] GET_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!", __FUNCTION__);
533 g_object_unref (program_info);
537 g_object_unref (str_list);
543 gmyth_recorder_get_file_position ( GMythRecorder *recorder )
546 GString *query = g_string_new( GMYTHTV_RECORDER_HEADER );
548 GMythStringList *str_list = gmyth_string_list_new ();
550 g_string_append_printf( query, " %d", recorder->recorder_num );
552 gmyth_string_list_append_string (str_list, query);
553 gmyth_string_list_append_char_array( str_list, "GET_FILE_POSITION" );
555 gmyth_socket_sendreceive_stringlist ( recorder->myth_socket, str_list );
557 if ( str_list != NULL && gmyth_string_list_length(str_list) > 0 )
560 if ( ( str = gmyth_string_list_get_string( str_list, 0 ) ) != NULL && strstr ( str->str, "bad" ) == NULL )
561 pos = gmyth_util_decode_long_long( str_list, 0 );
564 #ifndef GMYTHTV_ENABLE_DEBUG
565 g_print( "[%s] Got file position = %lld\n", __FUNCTION__, pos );
568 g_object_unref (str_list);
575 gmyth_recorder_is_recording ( GMythRecorder *recorder )
579 g_return_val_if_fail( recorder != NULL, FALSE );
581 GMythStringList *str_list = gmyth_string_list_new ();
582 GString *message = g_string_new ("");
584 g_string_printf( message, "%s %d", GMYTHTV_RECORDER_HEADER, recorder->recorder_num);
585 gmyth_string_list_append_string (str_list, message);
586 gmyth_string_list_append_string (str_list, g_string_new ("IS_RECORDING"));
588 gmyth_socket_sendreceive_stringlist ( recorder->myth_socket, str_list );
590 if ( str_list != NULL && gmyth_string_list_length(str_list) > 0 )
593 if ( ( str = gmyth_string_list_get_string( str_list, 0 ) ) != NULL && strcmp( str->str, "bad" )!= 0 )
595 gint is_rec = gmyth_string_list_get_int( str_list, 0 );
602 gmyth_debug( "%s, stream is %s being recorded!\n", ret ? "YES" : "NO", ret ? "" : "NOT" );
603 //g_static_mutex_unlock (&mutex);
605 if ( str_list != NULL )
606 g_object_unref (str_list);