gmyth/src/gmyth_recorder.c
author renatofilho
Tue Jun 19 22:01:13 2007 +0100 (2007-06-19)
branchtrunk
changeset 755 4b5efa290285
parent 750 312d6bc514f3
child 890 6b565181036e
permissions -rw-r--r--
[svn r761] create function to get recorded inf; fixe some headers indent
     1 /**
     2  * GMyth Library
     3  *
     4  * @file gmyth/gmyth_recorder.c
     5  * 
     6  * @brief <p> GMythRecorder defines functions for playing live tv.
     7  *
     8  * The remote encoder is used by gmyth_tvplayer to setup livetv. 
     9  *
    10  * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
    11  * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
    12  * @author Rosfran Borges <rosfran.borges@indt.org.br>
    13  *
    14  * 
    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.
    19  *
    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.
    24  *
    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
    28  */
    29 
    30 #ifdef HAVE_CONFIG_H
    31 #include "config.h"
    32 #endif
    33 
    34 #include "gmyth_recorder.h"
    35 
    36 #include <assert.h>
    37 
    38 #include "gmyth_stringlist.h"
    39 #include "gmyth_util.h"
    40 #include "gmyth_common.h"
    41 #include "gmyth_debug.h"
    42 
    43 #define	 GMYTHTV_RECORDER_HEADER			"QUERY_RECORDER"
    44 
    45 static void     gmyth_recorder_class_init(GMythRecorderClass * klass);
    46 static void     gmyth_recorder_init(GMythRecorder * object);
    47 
    48 static void     gmyth_recorder_dispose(GObject * object);
    49 static void     gmyth_recorder_finalize(GObject * object);
    50 
    51 G_DEFINE_TYPE(GMythRecorder, gmyth_recorder, G_TYPE_OBJECT)
    52     static void     gmyth_recorder_class_init(GMythRecorderClass * klass)
    53 {
    54     GObjectClass   *gobject_class;
    55 
    56     gobject_class = (GObjectClass *) klass;
    57 
    58     gobject_class->dispose = gmyth_recorder_dispose;
    59     gobject_class->finalize = gmyth_recorder_finalize;
    60 }
    61 
    62 static void
    63 gmyth_recorder_init(GMythRecorder * gmyth_remote_encoder)
    64 {
    65 }
    66 
    67 static void
    68 gmyth_recorder_dispose(GObject * object)
    69 {
    70     GMythRecorder  *recorder = GMYTH_RECORDER(object);
    71 
    72     gmyth_recorder_close(recorder);
    73 
    74     if (recorder->mutex != NULL) {
    75         g_mutex_free(recorder->mutex);
    76         recorder->mutex = NULL;
    77     }
    78 
    79     if (recorder->myth_socket != NULL) {
    80         g_object_unref(recorder->myth_socket);
    81         recorder->myth_socket = NULL;
    82     }
    83 
    84     if (recorder->progs_info_list != NULL)
    85         gmyth_free_program_list(recorder->progs_info_list);
    86 
    87     if (recorder->hostname != NULL)
    88         g_string_free(recorder->hostname, TRUE);
    89 
    90     G_OBJECT_CLASS(gmyth_recorder_parent_class)->dispose(object);
    91 }
    92 
    93 static void
    94 gmyth_recorder_finalize(GObject * object)
    95 {
    96     g_signal_handlers_destroy(object);
    97 
    98     G_OBJECT_CLASS(gmyth_recorder_parent_class)->finalize(object);
    99 }
   100 
   101 void
   102 gmyth_recorder_close(GMythRecorder * recorder)
   103 {
   104     if (recorder != NULL && recorder->recorder_num != -1) {
   105         g_mutex_lock(recorder->mutex);
   106 
   107         gmyth_recorder_stop_playing(recorder);
   108         gmyth_recorder_stop_livetv(recorder);
   109         gmyth_recorder_finish_recording(recorder);
   110         gmyth_recorder_free_tuner(recorder);
   111 
   112         g_mutex_unlock(recorder->mutex);
   113     }
   114 }
   115 
   116 /** Creates a new instance of GMythRecorder.
   117  * 
   118  * @return a new instance of GMythRecorder.
   119  */
   120 GMythRecorder  *
   121 gmyth_recorder_new(int num, GString * hostname, gshort port)
   122 {
   123     GMythRecorder  *encoder =
   124         GMYTH_RECORDER(g_object_new(GMYTH_RECORDER_TYPE, FALSE));
   125 
   126     encoder->recorder_num = num;
   127     encoder->hostname = g_string_new(hostname->str);
   128     encoder->port = port;
   129 
   130     encoder->mutex = g_mutex_new();
   131 
   132     encoder->progs_info_list = NULL;
   133 
   134     return encoder;
   135 }
   136 
   137 /** Configures the remote encoder instance connecting it to Mythtv backend.
   138  * 
   139  * @param recorder the GMythRecorder instance.
   140  * 
   141  * @return TRUE if successfull, FALSE if any error happens.
   142  */
   143 gboolean
   144 gmyth_recorder_setup(GMythRecorder * recorder)
   145 {
   146     assert(recorder);
   147     gmyth_debug("[%s] Creating socket and connecting to backend",
   148                 __FUNCTION__);
   149 
   150     if (recorder->myth_socket == NULL) {
   151         recorder->myth_socket = gmyth_socket_new();
   152 
   153         if (!gmyth_socket_connect_to_backend(recorder->myth_socket,
   154                                              recorder->hostname->str,
   155                                              recorder->port, TRUE)) {
   156             gmyth_debug
   157                 ("GMythRemoteEncoder: Connection to backend failed");
   158             return FALSE;
   159         }
   160     } else {
   161         gmyth_debug("Remote encoder socket already created\n");
   162     }
   163 
   164     return TRUE;
   165 }
   166 
   167 /** Sends the SPAWN_LIVETV command through Mythtv protocol. This command
   168  * requests the backend to start capturing TV content.
   169  * 
   170  * @param recorder The GMythRecorder instance.
   171  * @param tvchain_id The tvchain unique id.
   172  * @return true if success, false if any error happens.
   173  */
   174 gboolean
   175 gmyth_recorder_spawntv(GMythRecorder * recorder, GString * tvchain_id)
   176 {
   177     GMythStringList *str_list;
   178     GString        *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
   179     gboolean        ret = TRUE;
   180 
   181     gmyth_debug("[%s] Spawntv with tvchain_id = %s", __FUNCTION__,
   182                 tvchain_id->str);
   183 
   184     str_list = gmyth_string_list_new();
   185 
   186     g_mutex_lock(recorder->mutex);
   187 
   188     g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
   189 
   190     gmyth_string_list_append_string(str_list, tmp_str);
   191     g_string_free(tmp_str, TRUE);
   192 
   193     gmyth_string_list_append_char_array(str_list, "SPAWN_LIVETV");
   194 
   195     gmyth_string_list_append_string(str_list, tvchain_id);
   196     gmyth_string_list_append_int(str_list, 0);  // PIP = FALSE (0)
   197 
   198     gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
   199 
   200     tmp_str = gmyth_string_list_get_string(str_list, 0);
   201 
   202     if (tmp_str == NULL) {
   203         gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__,
   204                     tmp_str->str);
   205         ret = FALSE;
   206         goto cleanup;
   207     }
   208 
   209     if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
   210         gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__,
   211                     tmp_str->str);
   212         ret = FALSE;
   213         goto cleanup;
   214     }
   215 
   216   cleanup:
   217     g_mutex_unlock(recorder->mutex);
   218 
   219     g_string_free(tmp_str, TRUE);
   220     g_object_unref(str_list);
   221 
   222     return ret;
   223 }
   224 
   225 /** 
   226  * Sends the SPAWN_LIVETV command through Mythtv protocol. This command
   227  * requests the backend to start capturing TV content, but it doesn't need
   228  * the TV chain ID.
   229  * 
   230  * @param recorder The GMythRecorder instance.
   231  * @return true if success, false if any error happens.
   232  */
   233 gboolean
   234 gmyth_recorder_spawntv_no_tvchain(GMythRecorder * recorder)
   235 {
   236     GMythStringList *str_list;
   237     GString        *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
   238     gboolean        ret = TRUE;
   239 
   240     gmyth_debug("[%s] Spawntv, no TV chain!", __FUNCTION__);
   241 
   242     str_list = gmyth_string_list_new();
   243 
   244     g_mutex_lock(recorder->mutex);
   245 
   246     g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
   247 
   248     gmyth_string_list_append_string(str_list, tmp_str);
   249     g_string_free(tmp_str, TRUE);
   250 
   251     gmyth_string_list_append_char_array(str_list, "SPAWN_LIVETV");
   252 
   253     gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
   254 
   255     tmp_str = gmyth_string_list_get_string(str_list, 0);
   256 
   257     if (tmp_str == NULL) {
   258         gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__,
   259                     tmp_str->str);
   260         ret = FALSE;
   261         goto cleanup;
   262     }
   263 
   264     if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
   265         gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__,
   266                     tmp_str->str);
   267         ret = FALSE;
   268         goto cleanup;
   269     }
   270 
   271   cleanup:
   272     g_mutex_unlock(recorder->mutex);
   273 
   274     g_string_free(tmp_str, TRUE);
   275     g_object_unref(str_list);
   276 
   277     return ret;
   278 }
   279 
   280 /** Sends the command STOP_LIVETV to Mythtv backend.
   281  * 
   282  * @param recorder the GMythRecorder instance.
   283  * @return true if success, false if any error happens.
   284  */
   285 gboolean
   286 gmyth_recorder_stop_livetv(GMythRecorder * recorder)
   287 {
   288     GMythStringList *str_list;
   289     GString        *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
   290     gboolean        ret = TRUE;
   291 
   292     gmyth_debug("[%s]", __FUNCTION__);
   293 
   294     str_list = gmyth_string_list_new();
   295 
   296     g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
   297 
   298     gmyth_string_list_append_string(str_list, tmp_str);
   299     g_string_free(tmp_str, TRUE);
   300 
   301     gmyth_string_list_append_char_array(str_list, "STOP_LIVETV");
   302 
   303     gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
   304 
   305     tmp_str = gmyth_string_list_get_string(str_list, 0);
   306 
   307     if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
   308         gmyth_debug("[%s] Stop livetv request returned %s", __FUNCTION__,
   309                     tmp_str->str);
   310         ret = FALSE;
   311         goto cleanup;
   312     }
   313 
   314   cleanup:
   315     g_string_free(tmp_str, TRUE);
   316     g_object_unref(str_list);
   317 
   318     return ret;
   319 }
   320 
   321 /** Sends the FRONTEND_READY command through Mythtv protocol. This command
   322  * advertises the backend to start capturing TV content.
   323  * 
   324  * @param recorder The GMythRecorder instance.
   325  * @return TRUE if success, FALSE if any error happens.
   326  */
   327 gboolean
   328 gmyth_recorder_send_frontend_ready_command(GMythRecorder * recorder)
   329 {
   330     GMythStringList *str_list;
   331     GString        *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
   332     gboolean        ret = TRUE;
   333 
   334     gmyth_debug("[%s] FRONTEND_READY with recorder id = %d", __FUNCTION__,
   335                 recorder->recorder_num);
   336 
   337     str_list = gmyth_string_list_new();
   338 
   339     g_mutex_lock(recorder->mutex);
   340 
   341     g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
   342 
   343     gmyth_string_list_append_string(str_list, tmp_str);
   344     g_string_free(tmp_str, TRUE);
   345 
   346     gmyth_string_list_append_char_array(str_list, "FRONTEND_READY");
   347 
   348     gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
   349 
   350     tmp_str = gmyth_string_list_get_string(str_list, 0);
   351 
   352     if (tmp_str == NULL) {
   353         gmyth_debug
   354             ("[%s] FRONTEND_READY command request couldn't returns, reason: %s",
   355              __FUNCTION__, tmp_str->str);
   356         ret = FALSE;
   357         goto cleanup;
   358     }
   359 
   360     if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
   361         gmyth_debug("[%s] FRONTEND_READY request returned %s",
   362                     __FUNCTION__, tmp_str->str);
   363         ret = FALSE;
   364         goto cleanup;
   365     }
   366 
   367   cleanup:
   368     g_mutex_unlock(recorder->mutex);
   369     g_string_free(tmp_str, TRUE);
   370     g_object_unref(str_list);
   371 
   372     return ret;
   373 }
   374 
   375 /** Send a CHECK_CHANNEL command request to the backend, in order to find if a 
   376  * certain channel actually exists.
   377  * 
   378  * @param recorder The GMythRecorder instance.
   379  * @param channel	 The new channel to be checked (string format).
   380  * @return true if success, false if any error happens.
   381  */
   382 gboolean
   383 gmyth_recorder_check_channel_name(GMythRecorder * recorder,
   384                                   gchar * channel)
   385 {
   386     GMythStringList *str_list;
   387     GString        *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
   388     gboolean        ret = TRUE;
   389 
   390     gmyth_debug("[%s] CHECK_CHANNEL with channel = %s", __FUNCTION__,
   391                 channel);
   392 
   393     str_list = gmyth_string_list_new();
   394 
   395     g_mutex_lock(recorder->mutex);
   396 
   397     g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
   398 
   399     gmyth_string_list_append_string(str_list, tmp_str);
   400     g_string_free(tmp_str, TRUE);
   401 
   402     gmyth_string_list_append_char_array(str_list, "CHECK_CHANNEL");
   403 
   404     gmyth_string_list_append_char_array(str_list, channel);
   405 
   406     gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
   407 
   408     tmp_str = gmyth_string_list_get_string(str_list, 0);
   409 
   410     if (tmp_str == NULL) {
   411         gmyth_debug("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__,
   412                     tmp_str->str);
   413         ret = FALSE;
   414         goto cleanup;
   415     }
   416 
   417     if (g_ascii_strncasecmp(tmp_str->str, "ok", 2) == 0
   418         || g_ascii_strncasecmp(tmp_str->str, "0", 1) == 0) {
   419         gmyth_debug("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__,
   420                     tmp_str->str);
   421         ret = FALSE;
   422         goto cleanup;
   423     }
   424 
   425   cleanup:
   426     g_mutex_unlock(recorder->mutex);
   427     g_string_free(tmp_str, TRUE);
   428     g_object_unref(str_list);
   429 
   430     return ret;
   431 }
   432 
   433 /** Send a CHECK_CHANNEL command request to the backend, in order to find if a 
   434  * certain channel actually exists.
   435  * 
   436  * @param recorder The GMythRecorder instance.
   437  * @param channel	 The new channel to be checked (decimal integer value).
   438  * @return true if success, false if any error happens.
   439  */
   440 gboolean
   441 gmyth_recorder_check_channel(GMythRecorder * recorder, gint channel)
   442 {
   443     return gmyth_recorder_check_channel_name(recorder,
   444                                              g_strdup_printf("%d",
   445                                                              channel));
   446 }
   447 
   448 /** Send a SET_CHANNEL command request to the backend, to start streaming on another 
   449  * TV content channel.
   450  * 
   451  * @param recorder The GMythRecorder instance.
   452  * @param channel	 The new channel to be loaded.
   453  * @return true if success, false if any error happens.
   454  */
   455 gboolean
   456 gmyth_recorder_set_channel(GMythRecorder * recorder, gint channel)
   457 {
   458     GMythStringList *str_list;
   459     GString        *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
   460     gboolean        ret = TRUE;
   461 
   462     gmyth_debug("[%s] SET_CHANNEL with channel = %d", __FUNCTION__,
   463                 channel);
   464 
   465     str_list = gmyth_string_list_new();
   466 
   467     g_mutex_lock(recorder->mutex);
   468 
   469     g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
   470 
   471     gmyth_string_list_append_string(str_list, tmp_str);
   472     g_string_free(tmp_str, TRUE);
   473 
   474     gmyth_string_list_append_char_array(str_list, "SET_CHANNEL");
   475 
   476     gmyth_string_list_append_int(str_list, channel);
   477 
   478     gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
   479 
   480     tmp_str = gmyth_string_list_get_string(str_list, 0);
   481 
   482     if (tmp_str == NULL) {
   483         gmyth_debug("[%s] SET_CHANNEL request returned %s", __FUNCTION__,
   484                     tmp_str->str);
   485         ret = FALSE;
   486         goto cleanup;
   487     }
   488 
   489     if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
   490         gmyth_debug("[%s] SET_CHANNEL request returned %s", __FUNCTION__,
   491                     tmp_str->str);
   492         ret = FALSE;
   493         goto cleanup;
   494     }
   495 
   496   cleanup:
   497     g_mutex_unlock(recorder->mutex);
   498     g_string_free(tmp_str, TRUE);
   499     g_object_unref(str_list);
   500 
   501     return ret;
   502 }
   503 
   504 /** Send a SET_CHANNEL command request to the backend, to start streaming on another 
   505  * TV content channel.
   506  * 
   507  * @param recorder The GMythRecorder instance.
   508  * @param channel	 The new channel to be loaded.
   509  * @return true if success, false if any error happens.
   510  */
   511 gboolean
   512 gmyth_recorder_set_channel_name(GMythRecorder * recorder,
   513                                 const gchar * channel)
   514 {
   515     GMythStringList *str_list;
   516     GString        *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
   517     gboolean        ret = TRUE;
   518 
   519     gmyth_debug("[%s] SET_CHANNEL with channel name = %s", __FUNCTION__,
   520                 channel);
   521 
   522     str_list = gmyth_string_list_new();
   523 
   524     g_mutex_lock(recorder->mutex);
   525 
   526     g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
   527 
   528     gmyth_string_list_append_string(str_list, tmp_str);
   529     g_string_free(tmp_str, TRUE);
   530 
   531     gmyth_string_list_append_char_array(str_list, "SET_CHANNEL");
   532     gmyth_string_list_append_char_array(str_list, channel);
   533 
   534     gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
   535 
   536     tmp_str = gmyth_string_list_get_string(str_list, 0);
   537 
   538     if (tmp_str == NULL) {
   539         gmyth_debug("[%s] SET_CHANNEL name request returned NULL!",
   540                     __FUNCTION__);
   541         ret = FALSE;
   542         goto cleanup;
   543     }
   544 
   545     if (tmp_str != NULL && g_ascii_strncasecmp(tmp_str->str, "ok", 2)
   546         /*
   547          * || g_ascii_strtoull( tmp_str->str, NULL, 10 ) == 0 
   548          */
   549         ) {
   550         g_warning("[%s] SET_CHANNEL name request returned not ok",
   551                   __FUNCTION__);
   552         ret = FALSE;
   553         goto cleanup;
   554     }
   555 
   556   cleanup:
   557     g_mutex_unlock(recorder->mutex);
   558     g_string_free(tmp_str, TRUE);
   559     g_object_unref(str_list);
   560 
   561     return ret;
   562 }
   563 
   564 /**
   565  * Changes the channel of the actual Recorder.
   566  * 
   567  * CHANNEL_DIRECTION_UP       - Go up one channel in the listing
   568  *
   569  * CHANNEL_DIRECTION_DOWN     - Go down one channel in the listing
   570  *
   571  * CHANNEL_DIRECTION_FAVORITE - Go to the next favorite channel
   572  *
   573  * CHANNEL_DIRECTION_SAME     - Stay
   574  * 
   575  * @param recorder 	 The GMythRecorder instance.
   576  * @param direction	 The new channel direction where to move to.
   577  * @return true if success, false if any error happens.
   578  */
   579 gboolean
   580 gmyth_recorder_change_channel(GMythRecorder * recorder,
   581                               const GMythRecorderChannelChangeDirection
   582                               direction)
   583 {
   584     GMythStringList *str_list;
   585     GString        *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
   586     gboolean        ret = TRUE;
   587 
   588     gmyth_debug("[%s] CHANGE_CHANNEL to the channel direction = %u",
   589                 __FUNCTION__, direction);
   590 
   591     str_list = gmyth_string_list_new();
   592 
   593     g_mutex_lock(recorder->mutex);
   594 
   595     g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
   596 
   597     gmyth_string_list_append_string(str_list, tmp_str);
   598     g_string_free(tmp_str, TRUE);
   599 
   600     gmyth_string_list_append_char_array(str_list, "CHANGE_CHANNEL");
   601     gmyth_string_list_append_int(str_list, direction);
   602 
   603     gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
   604 
   605     tmp_str = gmyth_string_list_get_string(str_list, 0);
   606 
   607     if (tmp_str == NULL) {
   608         gmyth_debug("[%s] CHANGE_CHANNEL name request returned %s",
   609                     __FUNCTION__, tmp_str->str);
   610         ret = FALSE;
   611         goto cleanup;
   612     }
   613 
   614     if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)
   615         || g_ascii_strtoull(tmp_str->str, NULL, 10) == 0) {
   616         gmyth_debug("[%s] CHANGE_CHANNEL name request returned %s",
   617                     __FUNCTION__, tmp_str->str);
   618         ret = FALSE;
   619         goto cleanup;
   620     }
   621 
   622   cleanup:
   623     g_mutex_unlock(recorder->mutex);
   624     g_string_free(tmp_str, TRUE);
   625     g_object_unref(str_list);
   626 
   627     return ret;
   628 }
   629 
   630 /** 
   631  * Gets the channel's list from the MythTV backend server.
   632  * 
   633  * @param recorder The GMythRecorder instance.
   634  * 
   635  * @return a GList* instance with all the channel names.
   636  */
   637 GList          *
   638 gmyth_recorder_get_channel_list(GMythRecorder * recorder)
   639 {
   640 
   641     GList          *channel_list = NULL;
   642     gchar          *channel = NULL;
   643     guint           i;
   644 
   645     for (i = 0; i < 1000; i++) {
   646         channel = g_strdup_printf("%u", i);
   647 
   648         if (gmyth_recorder_check_channel_name(recorder, channel)) {
   649             channel_list = g_list_append(channel_list, g_strdup(channel));
   650         }
   651 
   652     }                           /* for - channel list */
   653 
   654     g_free(channel);
   655 
   656     return channel_list;
   657 
   658 }
   659 
   660 /** Send a PAUSE command request to the backend, to pause streaming on another 
   661  * TV content channel.
   662  * 
   663  * @param recorder The GMythRecorder instance.
   664  * @return true if success, false if any error happens.
   665  */
   666 gboolean
   667 gmyth_recorder_pause_recording(GMythRecorder * recorder)
   668 {
   669     GMythStringList *str_list;
   670     GString        *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
   671     gboolean        ret = TRUE;
   672 
   673     gmyth_debug("[%s] PAUSE", __FUNCTION__);
   674 
   675     str_list = gmyth_string_list_new();
   676 
   677     g_mutex_lock(recorder->mutex);
   678 
   679     g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
   680 
   681     gmyth_string_list_append_string(str_list, tmp_str);
   682     g_string_free(tmp_str, TRUE);
   683 
   684     gmyth_string_list_append_char_array(str_list, "PAUSE");
   685 
   686     gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
   687 
   688     tmp_str = gmyth_string_list_get_string(str_list, 0);
   689 
   690     if (tmp_str == NULL) {
   691         gmyth_debug("[%s] PAUSE name request returned %s", __FUNCTION__,
   692                     tmp_str->str);
   693         ret = FALSE;
   694         goto cleanup;
   695     }
   696 
   697     if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
   698         gmyth_debug("[%s] PAUSE name request returned %s", __FUNCTION__,
   699                     tmp_str->str);
   700         ret = FALSE;
   701         goto cleanup;
   702     }
   703 
   704   cleanup:
   705     g_mutex_unlock(recorder->mutex);
   706     g_string_free(tmp_str, TRUE);
   707     g_object_unref(str_list);
   708 
   709     return ret;
   710 }
   711 
   712 static          gboolean
   713 gmyth_recorder_find_if_program_exists(GMythRecorder * recorder,
   714                                       GMythProgramInfo * prog)
   715 {
   716     GList          *lst = NULL;
   717 
   718     g_return_val_if_fail(recorder != NULL
   719                          && recorder->progs_info_list != NULL, FALSE);
   720 
   721     for (lst = recorder->progs_info_list; lst != NULL;
   722          lst = g_list_next(lst)) {
   723         gmyth_debug("Got program info from list = [%s]",
   724                     gmyth_program_info_to_string((GMythProgramInfo *)
   725                                                  lst->data));
   726         if (gmyth_program_info_is_equals
   727             (prog, (GMythProgramInfo *) lst->data))
   728             return TRUE;
   729     }
   730 
   731     return FALSE;
   732 }
   733 
   734 /**
   735  * Requests the actual program info from the MythTV backend server.
   736  * 
   737  * @param recorder The GMythRecorder instance.
   738  * @return The actual program info.
   739  */
   740 GMythProgramInfo *
   741 gmyth_recorder_get_current_program_info(GMythRecorder * recorder)
   742 {
   743     GMythStringList *str_list = NULL;
   744     GMythProgramInfo *program_info = NULL;
   745     GString        *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
   746 
   747     str_list = gmyth_string_list_new();
   748 
   749     g_mutex_lock(recorder->mutex);
   750 
   751     g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
   752 
   753     gmyth_string_list_append_string(str_list, tmp_str);
   754 
   755     if (recorder->myth_socket->mythtv_version >= 26)
   756         gmyth_string_list_append_char_array(str_list,
   757                                             "GET_CURRENT_RECORDING");
   758     else
   759         gmyth_string_list_append_char_array(str_list, "GET_PROGRAM_INFO");
   760 
   761     gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
   762 
   763     if (str_list == NULL) {
   764         gmyth_debug
   765             ("[%s] GET_PROGRAM_INFO request returned. Error getting program info, string list equals to NULL!",
   766              __FUNCTION__);
   767         goto cleanup;
   768     }
   769 
   770     program_info = gmyth_program_info_from_string_list(str_list);
   771 
   772     if (NULL == program_info || NULL == program_info->pathname
   773         || program_info->pathname->len <= 0) {
   774         gmyth_debug
   775             ("GET_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!");
   776 
   777         if (program_info)
   778             g_object_unref(program_info);
   779 
   780         program_info = NULL;
   781 
   782         goto cleanup;
   783     }
   784 
   785     if (!gmyth_recorder_find_if_program_exists(recorder, program_info))
   786         recorder->progs_info_list =
   787             g_list_append(recorder->progs_info_list,
   788                           g_object_ref(program_info));
   789   cleanup:
   790     g_mutex_unlock(recorder->mutex);
   791     g_string_free(tmp_str, TRUE);
   792     g_object_unref(str_list);
   793 
   794     return program_info;
   795 }
   796 
   797 /**
   798  * Requests the actual program info from the MythTV backend server.
   799  * 
   800  * @param rec_id The GMythRecorder record number.
   801  * @return The GMythRecorder instance.
   802  */
   803 GMythRecorder  *
   804 gmyth_recorder_get_recorder_from_num(gint rec_id)
   805 {
   806     GMythRecorder  *recorder = NULL;
   807     GMythStringList *str_list;
   808     GString        *tmp_str = g_string_new("GET_RECORDER_FROM_NUM");
   809     gint            command_size = 0;
   810 
   811     gchar          *recorder_host = NULL;
   812     gint            recorder_port;
   813 
   814     str_list = gmyth_string_list_new();
   815 
   816     /*
   817      * g_string_append_printf ( tmp_str, " %d", recorder->recorder_num ); 
   818      */
   819 
   820     g_mutex_lock(recorder->mutex);
   821 
   822     gmyth_string_list_append_string(str_list, tmp_str);
   823 
   824     gmyth_string_list_append_int(str_list, rec_id);
   825 
   826     command_size =
   827         gmyth_socket_sendreceive_stringlist(recorder->myth_socket,
   828                                             str_list);
   829 
   830     if (str_list == NULL) {
   831         gmyth_debug
   832             ("[%s] GET_RECORDER_FROM_NUM request returned. Error getting recorder number %d, it is equals to NULL!!!",
   833              __FUNCTION__, rec_id);
   834         return NULL;
   835     }
   836 
   837     if (command_size > 0) {
   838         recorder_host = gmyth_string_list_get_char_array(str_list, 0);
   839         recorder_port = gmyth_string_list_get_int(str_list, 1);
   840 
   841         if (g_strstr_len(recorder_host, strlen(recorder_host), "nohost")
   842             != NULL) {
   843             gmyth_debug
   844                 ("No available recorder with the recorder ID number %d!",
   845                  rec_id);
   846         } else {
   847 
   848             recorder = gmyth_recorder_new(rec_id,
   849                                           g_string_new(recorder_host),
   850                                           (gshort) recorder_port);
   851 
   852             if (NULL == recorder) {
   853                 gmyth_debug
   854                     ("[%s] GET_RECORDER_FROM_NUM request returned. Error getting recorder number %d, it is equals to NULL!!!",
   855                      __FUNCTION__, rec_id);
   856                 g_object_unref(recorder);
   857                 return NULL;
   858             }
   859 
   860         }
   861 
   862     } else {
   863         gmyth_debug
   864             ("Cannot find a valuable recorder with the recorder ID number %d, backend server error!",
   865              rec_id);
   866     }
   867 
   868     g_mutex_unlock(recorder->mutex);
   869 
   870     g_object_unref(str_list);
   871 
   872     g_string_free(tmp_str, TRUE);
   873 
   874     g_free(recorder_host);
   875 
   876     return recorder;
   877 
   878 }
   879 
   880 /**
   881  * Requests the actual program info from the MythTV backend server.
   882  * 
   883  * @param recorder The GMythRecorder instance.
   884  * @param direction The direction to move based on the current channel (forward, backward,
   885  *            up, down).
   886  * 
   887  * @return The GMythProgramInfo next program info instance.
   888  */
   889 GMythProgramInfo *
   890 gmyth_recorder_get_next_program_info(GMythRecorder * recorder,
   891                                      const GMythRecorderBrowseDirection
   892                                      direction)
   893 {
   894     GMythProgramInfo *actual_proginfo = NULL;
   895     GMythProgramInfo *program_info = NULL;
   896     GMythStringList *str_list;
   897     GString        *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
   898 
   899     gchar          *date = NULL;
   900     struct tm      *tm = NULL;
   901     time_t          t;
   902 
   903     actual_proginfo = gmyth_recorder_get_current_program_info(recorder);
   904 
   905     str_list = gmyth_string_list_new();
   906 
   907     g_mutex_lock(recorder->mutex);
   908 
   909     g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
   910 
   911     t = time(NULL);
   912     tm = localtime(&t);
   913     date = g_strdup_printf("%.4d%.2d%.2d%.2d%.2d%.2d", tm->tm_year + 1900,
   914                            tm->tm_mon + 1, tm->tm_mday, tm->tm_hour,
   915                            tm->tm_min, tm->tm_sec);
   916 
   917     gmyth_string_list_append_string(str_list, tmp_str);
   918     gmyth_string_list_append_char_array(str_list, "GET_NEXT_PROGRAM_INFO");
   919     gmyth_string_list_append_string(str_list, actual_proginfo->channame);
   920     gmyth_string_list_append_string(str_list, actual_proginfo->chanid);
   921     gmyth_string_list_append_int(str_list, direction);
   922     gmyth_string_list_append_char_array(str_list, date);
   923 
   924     if (gmyth_socket_sendreceive_stringlist
   925         (recorder->myth_socket, str_list)
   926         > 0) {
   927 
   928         if (str_list == NULL) {
   929             gmyth_debug
   930                 ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!",
   931                  __FUNCTION__);
   932             goto done;
   933         }
   934         program_info =
   935             gmyth_program_info_from_string_list_next_prog(str_list);
   936 
   937         if (NULL == program_info) {
   938             gmyth_debug
   939                 ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting next program info, it is equals to NULL!!!",
   940                  __FUNCTION__);
   941             g_object_unref(program_info);
   942             goto done;
   943         }
   944 
   945         if (                    /* ( program_info->chanid != NULL &&
   946                                  * strlen( program_info->chanid->str ) > 0 
   947                                  * * * * * * ) && */
   948                (program_info->chansign != NULL
   949                 && strlen(program_info->chansign->str) > 0)) {
   950             gmyth_debug("OK!!! Got the next program info... [%s].",
   951                         program_info->chansign->str);
   952         } else {
   953             gmyth_debug
   954                 ("GET_NEXT_PROGRAM_INFO request returned. Error getting next program info, it is equals to NULL!!!");
   955             g_object_unref(program_info);
   956             program_info = NULL;
   957         }
   958 
   959     }
   960     /*
   961      * if 
   962      */
   963   done:
   964 
   965     g_mutex_unlock(recorder->mutex);
   966 
   967     if (actual_proginfo != NULL)
   968         g_object_unref(actual_proginfo);
   969 
   970     if (str_list != NULL)
   971         g_object_unref(str_list);
   972 
   973     if (tmp_str != NULL)
   974         g_string_free(tmp_str, TRUE);
   975 
   976     if (date != NULL)
   977         g_free(date);
   978     // if ( tm != NULL)
   979     // g_free (tm);
   980 
   981     return program_info;
   982 }
   983 
   984 /**
   985  * Requests the program info from the MythTV backend server, based on its 
   986  * channel name.
   987  * 
   988  * @param recorder The GMythRecorder instance.
   989  * @return The GMythProgramInfo next program info instance.
   990  */
   991 GMythProgramInfo *
   992 gmyth_recorder_get_program_info_from_channel_name(GMythRecorder * recorder,
   993                                                   const gchar * channel)
   994 {
   995     // GMythProgramInfo* actual_proginfo= NULL;
   996     GMythProgramInfo *program_info = NULL;
   997     GMythStringList *str_list;
   998     GString        *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
   999 
  1000     /*
  1001      * gchar *date = NULL; struct tm *tm = NULL; time_t t;
  1002      * 
  1003      * actual_proginfo =
  1004      * gmyth_recorder_get_current_program_info(recorder); 
  1005      */
  1006 
  1007     str_list = gmyth_string_list_new();
  1008 
  1009     g_mutex_lock(recorder->mutex);
  1010 
  1011     g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
  1012 
  1013     /*
  1014      * t = time(NULL); tm = localtime(&t); date =
  1015      * g_strdup_printf("%.4d%.2d%.2d%.2d%.2d%.2d", tm->tm_year + 1900,
  1016      * tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); 
  1017      */
  1018 
  1019     gmyth_string_list_append_string(str_list, tmp_str);
  1020     gmyth_string_list_append_char_array(str_list, "GET_NEXT_PROGRAM_INFO");
  1021     gmyth_string_list_append_char_array(str_list, channel);
  1022     gmyth_string_list_append_char_array(str_list, "0");
  1023     gmyth_string_list_append_int(str_list, BROWSE_DIRECTION_UP);
  1024     gmyth_string_list_append_char_array(str_list, "0");
  1025 
  1026     do {
  1027 
  1028         if (str_list != NULL &&
  1029             gmyth_socket_sendreceive_stringlist(recorder->myth_socket,
  1030                                                 str_list) > 0) {
  1031 
  1032             if (str_list == NULL) {
  1033                 gmyth_debug
  1034                     ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!",
  1035                      __FUNCTION__);
  1036                 goto done;
  1037             }
  1038             program_info =
  1039                 gmyth_program_info_from_string_list_next_prog(str_list);
  1040 
  1041             if (NULL == program_info) {
  1042                 gmyth_debug
  1043                     ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting next program info, it is equals to NULL!!!",
  1044                      __FUNCTION__);
  1045                 g_object_unref(program_info);
  1046                 goto done;
  1047             }
  1048 
  1049             if (                /* ( program_info->chanid != NULL &&
  1050                                  * strlen( program_info->chanid->str ) > 0 
  1051                                  * * * * * * ) && */
  1052                    (program_info->chansign != NULL
  1053                     && strlen(program_info->chansign->str) > 0)) {
  1054                 gmyth_debug("OK!!! Got the next program info... [%s].",
  1055                             program_info->chansign->str);
  1056             } else {
  1057                 gmyth_debug
  1058                     ("GET_NEXT_PROGRAM_INFO request returned. Error getting "
  1059                      "next program info, it is equals to NULL!!!");
  1060                 g_object_unref(program_info);
  1061                 program_info = NULL;
  1062             }
  1063 
  1064         }
  1065         /*
  1066          * if 
  1067          */
  1068     }
  1069     while (str_list != NULL);
  1070 
  1071   done:
  1072 
  1073     g_mutex_unlock(recorder->mutex);
  1074 
  1075     if (str_list != NULL)
  1076         g_object_unref(str_list);
  1077 
  1078     if (tmp_str != NULL)
  1079         g_string_free(tmp_str, TRUE);
  1080 
  1081     return program_info;
  1082 }
  1083 
  1084 /**
  1085  * Requests the actual remote file position on a LiveTV instance.
  1086  * 
  1087  * @param recorder The GMythRecorder instance.
  1088  * 
  1089  * @return The position, in bytes, of the offset to the read header.
  1090  */
  1091 gint64
  1092 gmyth_recorder_get_file_position(GMythRecorder * recorder)
  1093 {
  1094     gint64          pos = 0;
  1095     GString        *query = g_string_new(GMYTHTV_RECORDER_HEADER);
  1096 
  1097     GMythStringList *str_list = gmyth_string_list_new();
  1098 
  1099     g_mutex_lock(recorder->mutex);
  1100 
  1101     g_string_append_printf(query, " %d", recorder->recorder_num);
  1102 
  1103     gmyth_string_list_append_string(str_list, query);
  1104     gmyth_string_list_append_char_array(str_list, "GET_FILE_POSITION");
  1105 
  1106     gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
  1107 
  1108     if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
  1109         GString        *str = NULL;
  1110 
  1111         if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL
  1112             && strstr(str->str, "bad") == NULL)
  1113             pos = gmyth_string_list_get_int64(str_list, 0);
  1114         g_string_free(str, TRUE);
  1115     }
  1116 #ifndef GMYTHTV_ENABLE_DEBUG
  1117     gmyth_debug("[%s] Got file position = %lld\n", __FUNCTION__, pos);
  1118 #endif
  1119 
  1120     g_mutex_unlock(recorder->mutex);
  1121 
  1122     if (str_list != NULL)
  1123         g_object_unref(str_list);
  1124 
  1125     g_string_free(query, TRUE);
  1126 
  1127     return pos;
  1128 }
  1129 
  1130 /**
  1131  * Asks MythTV backend server about if it started to record the remote file.
  1132  * 
  1133  * @param recorder The GMythRecorder instance.
  1134  * 
  1135  * @return <code>true</code>, if the actual remote file is bein recorded.
  1136  */
  1137 gboolean
  1138 gmyth_recorder_is_recording(GMythRecorder * recorder)
  1139 {
  1140     gboolean        ret = TRUE;
  1141 
  1142     g_return_val_if_fail(recorder != NULL, FALSE);
  1143 
  1144     GMythStringList *str_list = gmyth_string_list_new();
  1145     GString        *message = g_string_new("");
  1146 
  1147     g_mutex_lock(recorder->mutex);
  1148 
  1149     g_string_printf(message, "%s %d", GMYTHTV_RECORDER_HEADER,
  1150                     recorder->recorder_num);
  1151     gmyth_string_list_append_string(str_list, message);
  1152     gmyth_string_list_append_char_array(str_list, "IS_RECORDING");
  1153 
  1154     gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
  1155 
  1156     if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
  1157         GString        *str = NULL;
  1158 
  1159         if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL
  1160             && strcmp(str->str, "bad") != 0) {
  1161             gint            is_rec =
  1162                 gmyth_string_list_get_int(str_list, 0);
  1163 
  1164             if (is_rec != 0)
  1165                 ret = TRUE;
  1166             else
  1167                 ret = FALSE;
  1168         }
  1169         g_string_free(str, TRUE);
  1170     }
  1171 
  1172     gmyth_debug("%s, stream is %s being recorded!\n", ret ? "YES" : "NO",
  1173                 ret ? "" : "NOT");
  1174     // g_static_mutex_unlock (&mutex);
  1175 
  1176     g_mutex_unlock(recorder->mutex);
  1177 
  1178     if (str_list != NULL)
  1179         g_object_unref(str_list);
  1180 
  1181     g_string_free(message, TRUE);
  1182 
  1183     return ret;
  1184 
  1185 }
  1186 
  1187 /**
  1188  * Finish remote file recording process.
  1189  * 
  1190  * @param recorder The GMythRecorder instance.
  1191  * 
  1192  * @return <code>true</code>, if the recording had been actually closed.
  1193  */
  1194 gboolean
  1195 gmyth_recorder_finish_recording(GMythRecorder * recorder)
  1196 {
  1197     gboolean        ret = TRUE;
  1198 
  1199     g_return_val_if_fail(recorder != NULL, FALSE);
  1200 
  1201     GMythStringList *str_list = gmyth_string_list_new();
  1202     GString        *message = g_string_new("");
  1203 
  1204     g_string_printf(message, "%s %d", GMYTHTV_RECORDER_HEADER,
  1205                     recorder->recorder_num);
  1206     gmyth_string_list_append_string(str_list, message);
  1207     gmyth_string_list_append_char_array(str_list, "FINISH_RECORDING");
  1208 
  1209     gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
  1210 
  1211     if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
  1212         GString        *str = NULL;
  1213 
  1214         if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL &&
  1215             strcmp(str->str, "ok") != 0) {
  1216             gint            is_rec =
  1217                 gmyth_string_list_get_int(str_list, 0);
  1218 
  1219             if (is_rec != 0)
  1220                 ret = TRUE;
  1221             else
  1222                 ret = FALSE;
  1223         }
  1224         g_string_free(str, TRUE);
  1225     }
  1226 
  1227     gmyth_debug("%s, stream is %s finished!\n", ret ? "YES" : "NO",
  1228                 ret ? "" : "NOT");
  1229     // g_static_mutex_unlock (&mutex);
  1230 
  1231     if (str_list != NULL)
  1232         g_object_unref(str_list);
  1233 
  1234     g_string_free(message, TRUE);
  1235 
  1236     return ret;
  1237 }
  1238 
  1239 
  1240 /**
  1241  * Stops playing the remote file.
  1242  * 
  1243  * @param recorder The GMythRecorder instance.
  1244  * 
  1245  * @return <code>true</code>, if the recording had been actually stopped.
  1246  */
  1247 gboolean
  1248 gmyth_recorder_stop_playing(GMythRecorder * recorder)
  1249 {
  1250     gboolean        ret = TRUE;
  1251 
  1252     g_return_val_if_fail(recorder != NULL, FALSE);
  1253 
  1254     GMythStringList *str_list = gmyth_string_list_new();
  1255     GString        *message = g_string_new("");
  1256 
  1257     g_string_printf(message, "%s %d", GMYTHTV_RECORDER_HEADER,
  1258                     recorder->recorder_num);
  1259     gmyth_string_list_append_string(str_list, message);
  1260     gmyth_string_list_append_char_array(str_list, "STOP_PLAYING");
  1261 
  1262     gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
  1263 
  1264     if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
  1265         GString        *str = NULL;
  1266 
  1267         if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL &&
  1268             strcmp(str->str, "ok") != 0) {
  1269             gint            is_rec =
  1270                 gmyth_string_list_get_int(str_list, 0);
  1271 
  1272             if (is_rec != 0)
  1273                 ret = TRUE;
  1274             else
  1275                 ret = FALSE;
  1276         }
  1277         g_string_free(str, TRUE);
  1278     }
  1279 
  1280     gmyth_debug("%s, stream is %s stopped!\n", ret ? "YES" : "NO",
  1281                 ret ? "" : "NOT");
  1282 
  1283     if (str_list != NULL)
  1284         g_object_unref(str_list);
  1285 
  1286     g_string_free(message, TRUE);
  1287 
  1288     return ret;
  1289 }
  1290 
  1291 /**
  1292  * Free the tuner responsible for recording this channel.
  1293  * 
  1294  * @param recorder The GMythRecorder instance.
  1295  * 
  1296  * @return <code>true</code>, if the tuner had been freed.
  1297  */
  1298 gboolean
  1299 gmyth_recorder_free_tuner(GMythRecorder * recorder)
  1300 {
  1301     gboolean        ret = TRUE;
  1302 
  1303     g_return_val_if_fail(recorder != NULL, FALSE);
  1304 
  1305     GMythStringList *str_list = gmyth_string_list_new();
  1306     GString        *message = g_string_new("");
  1307 
  1308     g_string_printf(message, "%s %d", "FREE_TUNER",
  1309                     recorder->recorder_num);
  1310     gmyth_string_list_append_string(str_list, message);
  1311 
  1312     gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
  1313 
  1314     if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
  1315         GString        *str = NULL;
  1316 
  1317         if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL &&
  1318             g_ascii_strncasecmp(str->str, "ok", 2) != 0) {
  1319             gint            is_rec =
  1320                 gmyth_string_list_get_int(str_list, 0);
  1321 
  1322             if (is_rec != 0)
  1323                 ret = TRUE;
  1324             else
  1325                 ret = FALSE;
  1326         }
  1327         g_string_free(str, TRUE);
  1328     }
  1329 
  1330     gmyth_debug("%s, tuner is %s freed!\n", ret ? "YES" : "NO",
  1331                 ret ? "" : "NOT");
  1332 
  1333     if (str_list != NULL)
  1334         g_object_unref(str_list);
  1335 
  1336     g_string_free(message, TRUE);
  1337 
  1338     return ret;
  1339 }
  1340 
  1341 /**
  1342  * Asks the MythTV backend server about the frame rate 
  1343  * of this LiveTV instance.
  1344  * 
  1345  * @param recorder The GMythRecorder instance.
  1346  * 
  1347  * @return The framerate (double value) of the current video.
  1348  */
  1349 gdouble
  1350 gmyth_recorder_get_framerate(GMythRecorder * recorder)
  1351 {
  1352     gdouble         fr = 0.0f;
  1353     GString        *query = g_string_new(GMYTHTV_RECORDER_HEADER);
  1354 
  1355     GMythStringList *str_list = gmyth_string_list_new();
  1356 
  1357     g_mutex_lock(recorder->mutex);
  1358 
  1359     g_string_append_printf(query, " %d", recorder->recorder_num);
  1360 
  1361     gmyth_string_list_append_string(str_list, query);
  1362     gmyth_string_list_append_char_array(str_list, "GET_FRAMERATE");
  1363 
  1364     gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
  1365 
  1366     if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
  1367         GString        *str = NULL;
  1368 
  1369         if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL
  1370             && strstr(str->str, "bad") == NULL)
  1371             fr = g_ascii_strtod(str->str, NULL);
  1372 
  1373         g_string_free(str, TRUE);
  1374     }
  1375 #ifndef GMYTHTV_ENABLE_DEBUG
  1376     gmyth_debug("[%s] Got file position = %f\n", __FUNCTION__, fr);
  1377 #endif
  1378 
  1379     g_mutex_unlock(recorder->mutex);
  1380 
  1381     if (str_list != NULL)
  1382         g_object_unref(str_list);
  1383 
  1384     g_string_free(query, TRUE);
  1385 
  1386     return fr;
  1387 
  1388 }