[svn r328] Some fixes on program info, and some memory clean ups.
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);
182 * Sends the SPAWN_LIVETV command through Mythtv protocol. This command
183 * requests the backend to start capturing TV content, but it doesn't need
186 * @param recorder The GMythRecorder instance.
187 * @return true if success, false if any error happens.
190 gmyth_recorder_spawntv_no_tvchain (GMythRecorder *recorder)
192 GMythStringList *str_list;
193 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
195 gmyth_debug ("[%s] Spawntv, no TV chain!", __FUNCTION__);
197 str_list = gmyth_string_list_new ();
199 g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
201 gmyth_string_list_append_string (str_list, tmp_str);
202 gmyth_string_list_append_string (str_list, g_string_new ("SPAWN_LIVETV"));
204 gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
206 g_string_free (tmp_str, TRUE);
208 tmp_str = gmyth_string_list_get_string (str_list, 0);
209 if (tmp_str == NULL) {
210 g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str);
214 if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
215 g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str);
216 g_object_unref (str_list);
220 g_object_unref (str_list);
225 /** Sends the command STOP_LIVETV to Mythtv backend.
227 * @param recorder the GMythRecorder instance.
228 * @return true if success, false if any error happens.
231 gmyth_recorder_stop_livetv (GMythRecorder *recorder)
233 GMythStringList *str_list;
234 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
236 gmyth_debug ("[%s]", __FUNCTION__);
238 str_list = gmyth_string_list_new ();
240 g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
241 gmyth_string_list_append_char_array( str_list, "STOP_LIVETV" );
243 gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
245 g_string_free (tmp_str, TRUE);
247 tmp_str = gmyth_string_list_get_string (str_list, 0);
248 if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
249 g_warning ("[%s] Stop livetv request returned %s", __FUNCTION__, tmp_str->str);
250 g_object_unref (str_list);
254 g_object_unref (str_list);
259 /** Sends the FRONTEND_READY command through Mythtv protocol. This command
260 * advertises the backend to start capturing TV content.
262 * @param recorder The GMythRecorder instance.
263 * @return TRUE if success, FALSE if any error happens.
266 gmyth_recorder_send_frontend_ready_command (GMythRecorder *recorder)
268 GMythStringList *str_list;
269 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
271 gmyth_debug ( "[%s] FRONTEND_READY with recorder id = %d", __FUNCTION__, recorder->recorder_num );
273 str_list = gmyth_string_list_new ();
275 g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
277 gmyth_string_list_append_string (str_list, tmp_str);
278 gmyth_string_list_append_string (str_list, g_string_new ("FRONTEND_READY"));
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] FRONTEND_READY command request couldn't returns, reason: %s", __FUNCTION__, tmp_str->str);
290 if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
291 g_warning ("[%s] FRONTEND_READY 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 (string format).
306 * @return true if success, false if any error happens.
309 gmyth_recorder_check_channel_name (GMythRecorder *recorder, gchar* channel)
311 GMythStringList *str_list;
312 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
314 gmyth_debug ("[%s] CHECK_CHANNEL with channel = %s", __FUNCTION__, channel);
316 str_list = gmyth_string_list_new ();
318 g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
320 gmyth_string_list_append_string (str_list, tmp_str);
321 gmyth_string_list_append_string (str_list, g_string_new ("CHECK_CHANNEL"));
322 gmyth_string_list_append_char_array (str_list, channel);
324 gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
326 g_string_free (tmp_str, TRUE);
328 tmp_str = gmyth_string_list_get_string (str_list, 0);
329 if (tmp_str == NULL) {
330 g_warning ("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__, tmp_str->str);
334 if (g_ascii_strncasecmp (tmp_str->str, "ok", 2) == 0 || g_ascii_strncasecmp (tmp_str->str, "0", 1) == 0 ) {
335 g_warning ("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__, tmp_str->str);
336 g_object_unref (str_list);
340 g_object_unref (str_list);
345 /** Send a CHECK_CHANNEL command request to the backend, in order to find if a
346 * certain channel actually exists.
348 * @param recorder The GMythRecorder instance.
349 * @param channel The new channel to be checked (decimal integer value).
350 * @return true if success, false if any error happens.
353 gmyth_recorder_check_channel (GMythRecorder *recorder, gint channel)
355 return gmyth_recorder_check_channel_name( recorder, g_strdup_printf( "%d", channel ) );
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 (GMythRecorder *recorder, gint channel)
368 GMythStringList *str_list;
369 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
371 gmyth_debug ("[%s] SET_CHANNEL with channel = %d", __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_int (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 request returned %s", __FUNCTION__, tmp_str->str);
391 if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
392 g_warning ("[%s] SET_CHANNEL request returned %s", __FUNCTION__, tmp_str->str);
393 g_object_unref (str_list);
397 g_object_unref (str_list);
402 /** Send a SET_CHANNEL command request to the backend, to start streaming on another
403 * TV content channel.
405 * @param recorder The GMythRecorder instance.
406 * @param channel The new channel to be loaded.
407 * @return true if success, false if any error happens.
410 gmyth_recorder_set_channel_name (GMythRecorder *recorder, const gchar* channel)
412 GMythStringList *str_list;
413 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
415 gmyth_debug ("[%s] SET_CHANNEL with channel name = %s", __FUNCTION__, channel);
417 str_list = gmyth_string_list_new ();
419 g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
421 gmyth_string_list_append_string (str_list, tmp_str);
422 gmyth_string_list_append_string (str_list, g_string_new ("SET_CHANNEL"));
423 gmyth_string_list_append_char_array (str_list, channel);
425 gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
427 g_string_free (tmp_str, TRUE);
429 tmp_str = gmyth_string_list_get_string (str_list, 0);
430 if (tmp_str == NULL) {
431 g_warning ("[%s] SET_CHANNEL name request returned %s", __FUNCTION__, tmp_str->str );
435 if (g_ascii_strncasecmp (tmp_str->str, "ok", 2) || g_ascii_strtoull( tmp_str->str, NULL, 10 ) == 0 ) {
436 g_warning ("[%s] SET_CHANNEL name request returned %s", __FUNCTION__, tmp_str->str);
437 g_object_unref (str_list);
441 g_object_unref (str_list);
447 * Changes the channel of the actual Recorder.
449 * CHANNEL_DIRECTION_UP - Go up one channel in the listing
451 * CHANNEL_DIRECTION_DOWN - Go down one channel in the listing
453 * CHANNEL_DIRECTION_FAVORITE - Go to the next favorite channel
455 * CHANNEL_DIRECTION_SAME - Stay
457 * @param recorder The GMythRecorder instance.
458 * @param direction The new channel direction where to move to.
459 * @return true if success, false if any error happens.
462 gmyth_recorder_change_channel (GMythRecorder *recorder, const GMythRecorderChannelChangeDirection direction)
464 GMythStringList *str_list;
465 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
467 gmyth_debug ("[%s] CHANGE_CHANNEL to the channel direction = %u", __FUNCTION__, direction);
469 str_list = gmyth_string_list_new ();
471 g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
473 gmyth_string_list_append_string (str_list, tmp_str);
474 gmyth_string_list_append_string (str_list, g_string_new ("CHANGE_CHANNEL"));
475 gmyth_string_list_append_int (str_list, direction);
477 gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
479 g_string_free (tmp_str, TRUE);
481 tmp_str = gmyth_string_list_get_string (str_list, 0);
482 if (tmp_str == NULL) {
483 g_warning ("[%s] CHANGE_CHANNEL name request returned %s", __FUNCTION__, tmp_str->str );
487 if (g_ascii_strncasecmp (tmp_str->str, "ok", 2) || g_ascii_strtoull( tmp_str->str, NULL, 10 ) == 0 ) {
488 g_warning ("[%s] CHANGE_CHANNEL name request returned %s", __FUNCTION__, tmp_str->str);
489 g_object_unref (str_list);
493 g_object_unref (str_list);
498 /** Send a PAUSE command request to the backend, to pause streaming on another
499 * TV content channel.
501 * @param recorder The GMythRecorder instance.
502 * @return true if success, false if any error happens.
505 gmyth_recorder_pause_recording ( GMythRecorder *recorder )
507 GMythStringList *str_list;
508 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
510 gmyth_debug ("[%s] PAUSE", __FUNCTION__);
512 str_list = gmyth_string_list_new ();
514 g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
516 gmyth_string_list_append_string (str_list, tmp_str);
517 gmyth_string_list_append_string (str_list, g_string_new ("PAUSE"));
519 gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
521 g_string_free (tmp_str, TRUE);
523 tmp_str = gmyth_string_list_get_string (str_list, 0);
524 if (tmp_str == NULL) {
525 g_warning ("[%s] PAUSE name request returned %s", __FUNCTION__, tmp_str->str);
529 if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
530 g_warning ("[%s] PAUSE name request returned %s", __FUNCTION__, tmp_str->str);
531 g_object_unref (str_list);
535 g_object_unref (str_list);
541 * Requests the actual program info from the MythTV backend server.
543 * @param recorder The GMythRecorder instance.
544 * @return The actual program info.
547 gmyth_recorder_get_current_program_info ( GMythRecorder *recorder )
549 GMythStringList *str_list;
550 GMythProgramInfo *program_info = gmyth_program_info_new();
551 GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
553 str_list = gmyth_string_list_new ();
555 g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
557 gmyth_string_list_append_string (str_list, tmp_str);
559 if ( recorder->myth_socket->mythtv_version >= 26 )
560 gmyth_string_list_append_string (str_list, g_string_new ("GET_CURRENT_RECORDING"));
562 gmyth_string_list_append_string (str_list, g_string_new ("GET_PROGRAM_INFO"));
564 gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
566 g_string_free (tmp_str, TRUE);
568 if (str_list == NULL) {
569 g_warning ("[%s] GET_PROGRAM_INFO request returned. Error getting program info, string list equals to NULL!", __FUNCTION__);
573 program_info = gmyth_program_info_from_string_list( str_list );
575 if ( NULL == program_info ) {
576 g_warning ("[%s] GET_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!", __FUNCTION__);
577 g_object_unref (program_info);
581 g_object_unref (str_list);
587 gmyth_recorder_get_file_position ( GMythRecorder *recorder )
590 GString *query = g_string_new( GMYTHTV_RECORDER_HEADER );
592 GMythStringList *str_list = gmyth_string_list_new ();
594 g_string_append_printf( query, " %d", recorder->recorder_num );
596 gmyth_string_list_append_string (str_list, query);
597 gmyth_string_list_append_char_array( str_list, "GET_FILE_POSITION" );
599 gmyth_socket_sendreceive_stringlist ( recorder->myth_socket, str_list );
601 if ( str_list != NULL && gmyth_string_list_length(str_list) > 0 )
604 if ( ( str = gmyth_string_list_get_string( str_list, 0 ) ) != NULL && strstr ( str->str, "bad" ) == NULL )
605 pos = gmyth_util_decode_long_long( str_list, 0 );
608 #ifndef GMYTHTV_ENABLE_DEBUG
609 g_print( "[%s] Got file position = %lld\n", __FUNCTION__, pos );
612 g_object_unref (str_list);
619 gmyth_recorder_is_recording ( GMythRecorder *recorder )
623 g_return_val_if_fail( recorder != NULL, FALSE );
625 GMythStringList *str_list = gmyth_string_list_new ();
626 GString *message = g_string_new ("");
628 g_string_printf( message, "%s %d", GMYTHTV_RECORDER_HEADER, recorder->recorder_num);
629 gmyth_string_list_append_string (str_list, message);
630 gmyth_string_list_append_string (str_list, g_string_new ("IS_RECORDING"));
632 gmyth_socket_sendreceive_stringlist ( recorder->myth_socket, str_list );
634 if ( str_list != NULL && gmyth_string_list_length(str_list) > 0 )
637 if ( ( str = gmyth_string_list_get_string( str_list, 0 ) ) != NULL && strcmp( str->str, "bad" )!= 0 )
639 gint is_rec = gmyth_string_list_get_int( str_list, 0 );
646 gmyth_debug( "%s, stream is %s being recorded!\n", ret ? "YES" : "NO", ret ? "" : "NOT" );
647 //g_static_mutex_unlock (&mutex);
649 if ( str_list != NULL )
650 g_object_unref (str_list);