gmyth/src/gmyth_livetv.c
author renatofilho
Tue Jun 19 22:01:13 2007 +0100 (2007-06-19)
branchtrunk
changeset 755 4b5efa290285
parent 750 312d6bc514f3
child 817 888b9724f601
permissions -rwxr-xr-x
[svn r761] create function to get recorded inf; fixe some headers indent
     1 /**
     2  * GMyth Library
     3  *
     4  * @file gmyth/gmyth_livetv.c
     5  * 
     6  * @brief <p> GMythLiveTV starts a remote TV session with the MythTV backend.
     7  *
     8  * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
     9  * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
    10  *
    11  * 
    12  * This program is free software; you can redistribute it and/or modify
    13  * it under the terms of the GNU Lesser General Public License as published by
    14  * the Free Software Foundation; either version 2 of the License, or
    15  * (at your option) any later version.
    16  *
    17  * This program is distributed in the hope that it will be useful,
    18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    20  * GNU General Public License for more details.
    21  *
    22  * You should have received a copy of the GNU Lesser General Public License
    23  * along with this program; if not, write to the Free Software
    24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    25  */
    26 
    27 #ifdef HAVE_CONFIG_H
    28 #include "config.h"
    29 #endif
    30 
    31 #include "gmyth_livetv.h"
    32 #include "gmyth_remote_util.h"
    33 #include "gmyth_tvchain.h"
    34 #include "gmyth_socket.h"
    35 #include "gmyth_backendinfo.h"
    36 #include "gmyth_debug.h"
    37 
    38 #include "gmyth_file.h"
    39 #include "gmyth_file_transfer.h"
    40 #include "gmyth_file_local.h"
    41 #include "gmyth_monitor_handler.h"
    42 
    43 #include "gmyth_common.h"
    44 #include "gmyth_util.h"
    45 
    46 static void     gmyth_livetv_class_init(GMythLiveTVClass * klass);
    47 static void     gmyth_livetv_init(GMythLiveTV * object);
    48 
    49 static void     gmyth_livetv_dispose(GObject * object);
    50 static void     gmyth_livetv_finalize(GObject * object);
    51 
    52 static gint     tvchain_curr_index = -1;
    53 
    54 /*
    55  * static GStaticMutex lock = G_STATIC_MUTEX_INIT;
    56  */
    57 
    58 #define GMYTHTV_TRANSFER_MAX_WAITS	    100
    59 
    60 G_DEFINE_TYPE(GMythLiveTV, gmyth_livetv, G_TYPE_OBJECT)
    61     static void     gmyth_livetv_class_init(GMythLiveTVClass * klass)
    62 {
    63     GObjectClass   *gobject_class;
    64 
    65     gobject_class = (GObjectClass *) klass;
    66 
    67     gobject_class->dispose = gmyth_livetv_dispose;
    68     gobject_class->finalize = gmyth_livetv_finalize;
    69 }
    70 
    71 static void
    72 gmyth_livetv_init(GMythLiveTV * livetv)
    73 {
    74     livetv->monitor = NULL;
    75     livetv->backend_info = NULL;
    76     livetv->local_hostname = NULL;
    77     livetv->file = NULL;
    78     livetv->setup_done = FALSE;
    79 
    80     livetv->socket = NULL;
    81     livetv->recorder = NULL;
    82     livetv->tvchain = NULL;
    83     livetv->proginfo = NULL;
    84     livetv->uri = NULL;
    85 
    86     livetv->mutex = g_mutex_new();
    87 }
    88 
    89 static void
    90 gmyth_livetv_dispose(GObject * object)
    91 {
    92     GMythLiveTV    *livetv = GMYTH_LIVETV(object);
    93 
    94 
    95     if (livetv->disposed) {
    96         /*
    97          * If dispose did already run, return. 
    98          */
    99         return;
   100     }
   101 
   102     /*
   103      * Make sure dispose does not run twice. 
   104      */
   105     livetv->disposed = TRUE;
   106 
   107     if (livetv->monitor != NULL) {
   108         g_object_unref(livetv->monitor);
   109         livetv->monitor = NULL;
   110     }
   111 
   112     if (livetv->file != NULL) {
   113         g_object_unref(livetv->file);
   114         livetv->file = NULL;
   115     }
   116 
   117 
   118     if (livetv->recorder != NULL) {
   119         // gmyth_recorder_close(livetv->recorder);
   120         g_object_unref(livetv->recorder);
   121         livetv->recorder = NULL;
   122     }
   123 
   124     if (livetv->socket != NULL) {
   125         g_object_unref(livetv->socket);
   126         livetv->socket = NULL;
   127     }
   128 
   129     if (livetv->tvchain != NULL) {
   130         g_object_unref(livetv->tvchain);
   131         livetv->tvchain = NULL;
   132     }
   133 
   134 
   135     if (livetv->proginfo != NULL) {
   136         g_object_unref(livetv->proginfo);
   137         livetv->proginfo = NULL;
   138     }
   139 
   140     if (livetv->backend_info != NULL) {
   141         g_object_unref(livetv->backend_info);
   142         livetv->backend_info = NULL;
   143     }
   144 
   145 
   146     if (livetv->uri != NULL) {
   147         g_object_unref(livetv->uri);
   148         livetv->uri = NULL;
   149     }
   150 
   151     if (livetv->mutex != NULL) {
   152         g_mutex_free(livetv->mutex);
   153         livetv->mutex = NULL;
   154     }
   155 
   156 
   157     if (livetv->local_hostname != NULL) {
   158         g_string_free(livetv->local_hostname, TRUE);
   159         livetv->local_hostname = NULL;
   160     }
   161 
   162     G_OBJECT_CLASS(gmyth_livetv_parent_class)->dispose(object);
   163 }
   164 
   165 static void
   166 gmyth_livetv_finalize(GObject * object)
   167 {
   168     g_signal_handlers_destroy(object);
   169 
   170     G_OBJECT_CLASS(gmyth_livetv_parent_class)->finalize(object);
   171 }
   172 
   173 /**
   174  * Creates a new GMythLiveTV instance
   175  * 
   176  * @return a newly allocated GMythLiveTV instance
   177  */
   178 GMythLiveTV    *
   179 gmyth_livetv_new(GMythBackendInfo * backend_info)
   180 {
   181     GMythLiveTV    *livetv =
   182         GMYTH_LIVETV(g_object_new(GMYTH_LIVETV_TYPE, NULL));
   183 
   184     livetv->backend_info = backend_info;
   185     g_object_ref(livetv->backend_info);
   186 
   187     return livetv;
   188 }
   189 
   190 /**
   191  * The GObject signal handler function, from which all status messages 
   192  * from the Monitor Handler will be advertized, all time it receives
   193  * LiveTV status messages from the MythTV backend
   194  * 
   195  * @param monitor a GMythMonitorHandler instance
   196  * @param msg_code the MythTV's server numeric status code
   197  * @param message the message's string description
   198  * @param user_data pointer to the GMythLiveTV instance
   199  */
   200 static void
   201 gmyth_livetv_monitor_signal_handler(GMythMonitorHandler * monitor,
   202                                     gint msg_code, gchar * message,
   203                                     gpointer user_data)
   204 {
   205     GMythLiveTV    *live_tv = GMYTH_LIVETV(user_data);
   206 
   207     gmyth_debug
   208         ("LIVETV Signal handler ( msg = %s, code = %d, live_tv param = %s, user_data = %s )\n",
   209          message, msg_code, live_tv != NULL ? "" : "NULL",
   210          user_data != NULL ? "" : "NULL");
   211 
   212     if (NULL == live_tv || !IS_GMYTH_FILE_TRANSFER(live_tv->file)) {
   213         gmyth_debug("LiveTV_obj is equals to NULL!!!");
   214         return;
   215     }
   216 
   217     switch (msg_code) {
   218 
   219     case GMYTH_BACKEND_PROGRAM_INFO_CHANGED:
   220         {
   221             gmyth_debug
   222                 ("LIVETV Program Changed request received [ msg = %s ]. Watching if the new "
   223                  "TV Chain ID is the same as the old one...\n", message);
   224             if (g_ascii_strcasecmp
   225                 (message,
   226                  (gmyth_tvchain_get_id(live_tv->tvchain))->str) != 0) {
   227                 gmyth_debug
   228                     ("OK!!! MOVED to the next program chain [actual == %s]!",
   229                      (gmyth_tvchain_get_id(live_tv->tvchain))->str);
   230                 /*
   231                  * advertises the FileTransfer about the program info
   232                  * changed 
   233                  */
   234                 if (live_tv->file != NULL) {
   235                     gmyth_debug
   236                         ("Emitting signal to the FileTransfer... [ \"program-info-changed \" ]");
   237 
   238                     gmyth_file_transfer_emit_program_info_changed_signal
   239                         (GMYTH_FILE_TRANSFER(live_tv->file), msg_code,
   240                          (gpointer) (live_tv->recorder));
   241 
   242                     /*
   243                      * gmyth_livetv_monitor_handler_stop( live_tv ); 
   244                      */
   245                 } else
   246                     gmyth_debug
   247                         ("LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n");
   248             }
   249             break;
   250         }
   251     case GMYTH_BACKEND_DONE_RECORDING:
   252         {
   253             gmyth_debug
   254                 ("LIVETV Program Changed request received [ msg = %s ]. Watching if the new "
   255                  "TV Chain ID is the same as the old one...\n", message);
   256             if (g_ascii_strcasecmp
   257                 (message,
   258                  (gmyth_tvchain_get_id(live_tv->tvchain))->str) != 0) {
   259                 gmyth_debug
   260                     ("OK!!! MOVED to the next program chain [actual == %s]!",
   261                      (gmyth_tvchain_get_id(live_tv->tvchain))->str);
   262                 /*
   263                  * advertises the FileTransfer about the program info
   264                  * changed 
   265                  */
   266                 if (live_tv->file != NULL) {
   267                     gmyth_debug
   268                         ("Emitting signal to the FileTransfer... [ \"backend-done-recording\" ]");
   269 
   270                     gmyth_file_transfer_emit_program_info_changed_signal
   271                         (GMYTH_FILE_TRANSFER(live_tv->file), msg_code,
   272                          (gpointer) (live_tv->recorder));
   273 
   274                 } else
   275                     gmyth_debug
   276                         ("LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n");
   277             }
   278             break;
   279         }
   280     case GMYTH_BACKEND_STOP_LIVETV:
   281         {
   282             gmyth_debug
   283                 ("LIVETV Stop LiveTV request received [ msg = %s ]. Going out the "
   284                  "LiveTV...\n", message);
   285             /*
   286              * stops the LiveTV 
   287              */
   288             if (live_tv != NULL) {
   289                 gmyth_debug("Going out the LiveTV... [ \"quit-livetv\" ]");
   290 
   291                 g_object_unref(live_tv);
   292             } else
   293                 gmyth_debug
   294                     ("LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n");
   295 
   296             break;
   297         }
   298     default:
   299         break;
   300     }                           /* switch (Monitor Handler messages) */
   301 
   302 }
   303 
   304 /**
   305  * Starts the Monitor Handler to this GMythLiveTV session, in order
   306  * to receive the status messages from the MythTV's backend server 
   307  * 
   308  * @param live_tv the GMythLiveTV instance
   309  * 
   310  * @return <code>true</code> if the Monitor Handler start-up process
   311  * 	   had been concluded succcesfully 
   312  */
   313 gboolean
   314 gmyth_livetv_monitor_handler_start(GMythLiveTV * livetv)
   315 {
   316     gboolean        res = TRUE;
   317 
   318     if (livetv->monitor != NULL) {
   319         g_object_unref(livetv->monitor);
   320         livetv->monitor = NULL;
   321     }
   322 
   323     livetv->monitor = gmyth_monitor_handler_new();
   324 
   325     res =
   326         gmyth_monitor_handler_open(livetv->monitor,
   327                                    livetv->backend_info->hostname,
   328                                    livetv->backend_info->port);
   329 
   330     if (res == TRUE) {
   331         gmyth_debug
   332             ("Connect MythTV Monitor event socket! Trying to start the message handler...");
   333 
   334         res = gmyth_monitor_handler_start(livetv->monitor);
   335 
   336         if (res) {
   337             gmyth_debug
   338                 ("MythTV Monitor event socket connected and listening!");
   339             g_signal_connect(G_OBJECT(livetv->monitor),
   340                              "backend-events-handler", (GCallback)
   341                              gmyth_livetv_monitor_signal_handler, livetv);
   342         } else {
   343             gmyth_debug
   344                 ("Problems when trying to start MythTV Monitor event socket!");
   345             goto error;
   346         }
   347     }
   348 
   349   error:
   350     return res;
   351 
   352 }
   353 
   354 /**
   355  * Stops the Monitor Handler to this GMythLiveTV session, in order
   356  * to stop receiving the status messages from the MythTV's backend server 
   357  * 
   358  * @param live_tv the GMythLiveTV instance
   359  * 
   360  * @return <code>true</code> if the Monitor Handler shutdown process
   361  * 	   had been concluded succcesfully 
   362  */
   363 void
   364 gmyth_livetv_monitor_handler_stop(GMythLiveTV * livetv)
   365 {
   366 
   367     if (livetv->monitor != NULL) {
   368         g_object_unref(livetv->monitor);
   369         livetv->monitor = NULL;
   370     }
   371 
   372 }
   373 
   374 #if 0
   375 static gchar   *
   376 gmyth_livetv_create_remote_url(GMythLiveTV * livetv)
   377 {
   378     gchar          *uri = g_strdup("");
   379 
   380     gmyth_backend_info_get_remote_h
   381         // gmyth_backend(livetv->backend_info)
   382         return uri;
   383 }
   384 #endif
   385 
   386 /**
   387  * Configures the GMythLiveTV session, sends SPAWN_LIVETV message, 
   388  * sets the channel name, and gets the first program info about the
   389  * actual recording 
   390  * 
   391  * @param live_tv the GMythLiveTV instance
   392  * @param channel the channel name (the chan_name field, from the tvchain table)
   393  * @param backend_info the GMythBackendInfo describing the remote server
   394  * 
   395  * @return <code>true</code> if the LiveTV's recorder instance configuration 
   396  * 				had been concluded succcesfully 
   397  */
   398 static          gboolean
   399 gmyth_livetv_setup_recorder_channel_name(GMythLiveTV * livetv,
   400                                          gchar * channel)
   401 {
   402     gboolean        res = TRUE;
   403 
   404     g_return_val_if_fail(livetv != NULL, FALSE);
   405 
   406     if (NULL == livetv->socket) {
   407         livetv->socket = gmyth_socket_new();
   408 
   409         /*
   410          * FIME: Implement this at gmyth_socket 
   411          */
   412         res =
   413             gmyth_socket_connect_to_backend(livetv->socket,
   414                                             livetv->backend_info->hostname,
   415                                             livetv->backend_info->port,
   416                                             TRUE);
   417         if (!res) {
   418             gmyth_debug("[%s] LiveTV can not connect to backend",
   419                         __FUNCTION__);
   420             res = FALSE;
   421             goto error;
   422         }
   423     }
   424 
   425     g_mutex_lock(livetv->mutex);
   426 
   427     livetv->is_livetv = TRUE;
   428 
   429     livetv->local_hostname = gmyth_socket_get_local_hostname();
   430 
   431     if (livetv->local_hostname == NULL) {
   432         g_warning("livetv could not retrieve the local hostname");
   433         res = FALSE;
   434         goto error;
   435     } else {
   436         gmyth_debug("Local hostname: %s", livetv->local_hostname->str);
   437     }
   438 
   439     if (livetv->recorder != NULL) {
   440         g_object_unref(livetv->recorder);
   441         livetv->recorder = NULL;
   442     }
   443 
   444     if (gmyth_remote_util_get_free_recorder_count(livetv->socket) <= 0) {
   445         gmyth_debug("No free remote encoder available.");
   446         res = FALSE;
   447         goto error;
   448     }
   449 
   450     /*
   451      * Gets the recorder num 
   452      */
   453     livetv->recorder =
   454         remote_request_next_free_recorder(livetv->socket, -1);
   455     gmyth_socket_close_connection(livetv->socket);
   456 
   457     if (NULL == livetv->recorder) {
   458         gmyth_debug("[%s] None remote encoder available", __FUNCTION__);
   459         res = FALSE;
   460         goto error;
   461     }
   462 
   463     /*
   464      * Init remote encoder. Opens its control socket. 
   465      */
   466     res = gmyth_recorder_setup(livetv->recorder);
   467     if (!res) {
   468         gmyth_debug("[%s] Fail while setting remote encoder\n",
   469                     __FUNCTION__);
   470         res = FALSE;
   471         goto error;
   472     }
   473 
   474     /*
   475      * Creates livetv chain handler 
   476      */
   477     livetv->tvchain = gmyth_tvchain_new();
   478     gmyth_tvchain_initialize(livetv->tvchain, livetv->backend_info);
   479 
   480     if (livetv->tvchain == NULL || livetv->tvchain->tvchain_id == NULL) {
   481         res = FALSE;
   482         goto error;
   483     }
   484     // Spawn live tv. Uses the socket to send mythprotocol data to start
   485     // livetv in the backend (remotelly)
   486     res = gmyth_recorder_spawntv(livetv->recorder,
   487                                  gmyth_tvchain_get_id(livetv->tvchain));
   488     if (!res) {
   489         gmyth_debug("[%s] Fail while spawn tv\n", __FUNCTION__);
   490         res = FALSE;
   491         goto error;
   492     }
   493 
   494     if (res == TRUE) {
   495         /*
   496          * loop finished, set the max tries variable to zero again... 
   497          */
   498         gint            wait_to_transfer = 0;
   499 
   500         while (wait_to_transfer++ < GMYTHTV_TRANSFER_MAX_WAITS &&
   501                (gmyth_recorder_is_recording(livetv->recorder) == FALSE))
   502             g_usleep(300);
   503 
   504         if (channel != NULL) {
   505             /*
   506              * Pauses remote encoder. 
   507              */
   508             res = gmyth_recorder_pause_recording(livetv->recorder);
   509             if (!res) {
   510                 gmyth_debug("[%s] Fail while pausing remote encoder\n",
   511                             __FUNCTION__);
   512                 res = FALSE;
   513                 goto error;
   514             }
   515 
   516             if (gmyth_recorder_check_channel_name
   517                 (livetv->recorder, channel)) {
   518                 if (gmyth_recorder_set_channel_name
   519                     (livetv->recorder, channel)) {
   520                     gmyth_debug("Channel changed!!! [%s].\n", channel);
   521                 }
   522             }
   523 
   524         }
   525         /*
   526          * if - changes the channel number 
   527          */
   528         /*
   529          * sleep (5); 
   530          */
   531         /*
   532          * FIXME: this is evil (tpm) 
   533          */
   534     }
   535 
   536     /*
   537      * DEBUG message 
   538      */
   539     GMythProgramInfo *prog_info =
   540         gmyth_recorder_get_current_program_info(livetv->recorder);
   541 
   542     if (NULL == prog_info) {
   543         gmyth_debug("ProgramInfo is equals to NULL!!!");
   544 
   545         gint            i;
   546         gchar          *channame = NULL;
   547 
   548         gmyth_debug("Problem getting current proginfo!\n");
   549 
   550         /*
   551          * mythbackend must not be tuned in to a channel, so keep
   552          * changing channels until we find a valid one, or until
   553          * we decide to give up.
   554          */
   555         for (i = 1; i < 1000; i++) {
   556             if (channame != NULL)
   557                 g_free(channame);
   558             channame = g_strdup_printf("%d", i);
   559             if (gmyth_recorder_set_channel_name(livetv->recorder, channame)
   560                 < 0) {
   561                 continue;
   562             }
   563             prog_info =
   564                 gmyth_recorder_get_next_program_info(livetv->recorder,
   565                                                      BROWSE_DIRECTION_UP);
   566             gmyth_program_info_print(prog_info);
   567             if (prog_info != NULL)
   568                 break;
   569         }
   570 
   571     }
   572 
   573     /*
   574      * if - Program Info 
   575      */
   576     /*
   577      * prints program info data text 
   578      */
   579     gmyth_debug("New ProgramInfo...\n");
   580     gmyth_program_info_print(prog_info);
   581 
   582     /*
   583      * check if the program chain could be obtained from the MythTV
   584      * protocol message 
   585      */
   586     if (prog_info != NULL) {
   587         gmyth_backend_info_set_username(livetv->tvchain->backend_info,
   588                                         "mythtv");
   589         gmyth_backend_info_set_password(livetv->tvchain->backend_info,
   590                                         "mythtv");
   591         gmyth_backend_info_set_db_name(livetv->tvchain->backend_info,
   592                                        "mythconverg");
   593         GList          *prog_list =
   594             gmyth_tvchain_get_program_info_from_channel(livetv->tvchain,
   595                                                         channel);
   596         GMythProgramInfo *ch_prog = NULL;
   597 
   598         if (prog_list != NULL && g_list_length(prog_list) > 0) {
   599             ch_prog = (GMythProgramInfo *) g_list_nth_data(prog_list, 0);
   600             gmyth_debug
   601                 ("Channel program info (from a list with size = %d)!",
   602                  g_list_length(prog_list));
   603             gmyth_program_info_print(ch_prog);
   604         }
   605 
   606         gmyth_debug("Program Info: %s\n",
   607                     gmyth_program_info_to_string(prog_info));
   608         livetv->proginfo = prog_info;
   609         /*
   610          * testing change channel 
   611          */
   612         // gmyth_recorder_spawntv_no_tvchain( livetv->recorder );
   613     } else {
   614 
   615         /*
   616          * check for the program info in the TV program chain could be
   617          * obtained from the MythTV MySQL database 
   618          */
   619 
   620         /*
   621          * Reload all TV chain from Mysql database. 
   622          */
   623         gmyth_tvchain_reload_all(livetv->tvchain);
   624 
   625         if (livetv->tvchain == NULL) {
   626             res = FALSE;
   627             goto error;
   628         }
   629 
   630         /*
   631          * Get program info from database using chanid and starttime 
   632          */
   633         livetv->proginfo =
   634             gmyth_tvchain_get_program_at(livetv->tvchain,
   635                                          tvchain_curr_index++);
   636         if (livetv->proginfo == NULL) {
   637             gmyth_debug("LiveTV not successfully started.\n");
   638             res = FALSE;
   639             goto error;
   640         } else {
   641             res = TRUE;
   642             gmyth_debug
   643                 ("GMythLiveTV: All requests to backend to start TV were OK. [%s]\n",
   644                  livetv->proginfo->pathname->str);
   645         }
   646 
   647     }
   648 
   649     livetv->uri =
   650         (GMythURI *) gmyth_backend_info_get_uri(livetv->backend_info);
   651 
   652     g_mutex_unlock(livetv->mutex);
   653 
   654     if (!gmyth_livetv_monitor_handler_start(livetv)) {
   655         res = FALSE;
   656         gmyth_debug("LiveTV MONITOR handler error on setup!");
   657         goto error;
   658     }
   659 
   660     livetv->setup_done = TRUE;
   661 
   662     return res;
   663 
   664   error:
   665     g_mutex_unlock(livetv->mutex);
   666 
   667     gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
   668 
   669     res = FALSE;
   670 
   671     if (livetv->local_hostname != NULL) {
   672         g_string_free(livetv->local_hostname, TRUE);
   673         livetv->local_hostname = NULL;
   674     }
   675 
   676     gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
   677 
   678     if (livetv->recorder != NULL) {
   679         g_object_unref(livetv->recorder);
   680         livetv->recorder = NULL;
   681     }
   682 
   683     gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
   684 
   685     if (livetv->tvchain != NULL) {
   686         g_object_unref(livetv->tvchain);
   687         livetv->tvchain = NULL;
   688     }
   689 
   690     gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
   691 
   692     if (livetv->proginfo != NULL) {
   693         g_object_unref(livetv->proginfo);
   694         livetv->proginfo = NULL;
   695     }
   696 
   697     gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
   698 
   699     if (livetv->monitor != NULL) {
   700         g_object_unref(livetv->monitor);
   701         livetv->monitor = NULL;
   702     }
   703 
   704 
   705     gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
   706 
   707     return res;
   708 
   709 }
   710 
   711 /**
   712  * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, 
   713  * sets the channel name, and gets the first program info about the
   714  * actual recording 
   715  * 
   716  * @param live_tv the GMythLiveTV instance
   717  * @param channel the channel name, in numerical format
   718  * @param backend_info the GMythBackendInfo describing the remote server
   719  * 
   720  * @return <code>true</code> if the LiveTV's recorder instance configuration 
   721  * 				had been concluded succcesfully 
   722  */
   723 static          gboolean
   724 gmyth_livetv_setup_recorder(GMythLiveTV * livetv, gint channel)
   725 {
   726     return gmyth_livetv_setup_recorder_channel_name(livetv,
   727                                                     (channel !=
   728                                                      -1) ?
   729                                                     g_strdup_printf("%d",
   730                                                                     channel)
   731                                                     : NULL);
   732 }
   733 
   734 /**
   735  * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, 
   736  * sets the channel name (numerical format), and gets the first program info about the
   737  * actual recording 
   738  * 
   739  * @param live_tv the GMythLiveTV instance
   740  * @param channel the channel name, in numerical format
   741  * @param backend_info the GMythBackendInfo describing the remote server
   742  * 
   743  * @return <code>true</code> if the LiveTV's recorder instance configuration 
   744  * 				had been concluded succcesfully 
   745  */
   746 gboolean
   747 gmyth_livetv_channel_setup(GMythLiveTV * livetv, gint channel)
   748 {
   749     return gmyth_livetv_setup_recorder(livetv, channel);
   750 }
   751 
   752 /**
   753  * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, 
   754  * sets the channel name (string format), and gets the first program info about the
   755  * actual recording 
   756  * 
   757  * @param live_tv the GMythLiveTV instance
   758  * @param channel the channel name, in numerical format
   759  * @param backend_info the GMythBackendInfo describing the remote server
   760  * 
   761  * @return <code>true</code> if the LiveTV's recorder instance configuration 
   762  * 				had been concluded succcesfully 
   763  */
   764 gboolean
   765 gmyth_livetv_channel_name_setup(GMythLiveTV * livetv, gchar * channel)
   766 {
   767     return gmyth_livetv_setup_recorder_channel_name(livetv, channel);
   768 }
   769 
   770 /**
   771  * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, 
   772  * and gets the first program info about the actual recording
   773  * (doesn't changes the channel). 
   774  * 
   775  * @param live_tv the GMythLiveTV instance
   776  * @param backend_info the GMythBackendInfo describing the remote server
   777  * 
   778  * @return <code>true</code> if the LiveTV's recorder instance configuration 
   779  * 				had been concluded succcesfully 
   780  */
   781 gboolean
   782 gmyth_livetv_setup(GMythLiveTV * livetv)
   783 {
   784     return gmyth_livetv_setup_recorder(livetv, -1);
   785 }
   786 
   787 /**
   788  * Gets the next program info from this GMythLiveTV session.
   789  * 
   790  * @param live_tv the GMythLiveTV instance
   791  * 
   792  * @return <code>true</code> if the next program info could be got 
   793  */
   794 gboolean
   795 gmyth_livetv_next_program_chain(GMythLiveTV * livetv)
   796 {
   797     gboolean        res = TRUE;
   798     GMythProgramInfo *prog_info = NULL;
   799 
   800     if (!livetv->setup_done) {
   801         gmyth_debug("Call the setup function first!");
   802         goto error;
   803     }
   804 
   805     gmyth_debug("Current ProgramInfo...\n");
   806     prog_info = gmyth_recorder_get_current_program_info(livetv->recorder);
   807 
   808     if (prog_info != NULL) {
   809         livetv->proginfo = prog_info;
   810     } else {
   811         gmyth_debug
   812             ("ProgramInfo equals to NULL!!! Getting the next program info...");
   813         prog_info =
   814             gmyth_recorder_get_next_program_info(livetv->recorder,
   815                                                  BROWSE_DIRECTION_RIGHT);
   816         livetv->proginfo = prog_info;
   817     }
   818     /*
   819      * prints program info data text 
   820      */
   821     gmyth_program_info_print(prog_info);
   822 
   823     if (prog_info != NULL) {
   824         res = TRUE;
   825         livetv->proginfo = prog_info;
   826         gmyth_debug
   827             ("GMythLiveTV: All requests to backend to start TV were OK, program info changed.");
   828     } else {
   829         gmyth_debug
   830             ("[%s] LiveTV not successfully started on the next program chain.\n",
   831              __FUNCTION__);
   832         goto error;
   833     }
   834 
   835     livetv->setup_done = TRUE;
   836 
   837     return res;
   838 
   839   error:
   840     gmyth_debug("ERROR running LiveTV setup.\n");
   841 
   842     res = FALSE;
   843 
   844     g_string_free(livetv->local_hostname, TRUE);
   845 
   846     if (livetv->recorder != NULL) {
   847         g_object_unref(livetv->recorder);
   848         livetv->recorder = NULL;
   849     }
   850 
   851     if (livetv->tvchain != NULL) {
   852         g_object_unref(livetv->tvchain);
   853         livetv->tvchain = NULL;
   854     }
   855 
   856     if (livetv->proginfo != NULL) {
   857         g_object_unref(livetv->proginfo);
   858         livetv->proginfo = NULL;
   859     }
   860 
   861     return res;
   862 }
   863 
   864 /**
   865  * Creates a File Transfer session, using all configuration information
   866  * got from the actual program info.
   867  * 
   868  * @param live_tv the GMythLiveTV instance
   869  * 
   870  * @return the actual GMythFileTransfer instance, generated using the
   871  * 		data got from the actual program info.
   872  */
   873 GMythFile      *
   874 gmyth_livetv_create_file_transfer(GMythLiveTV * livetv)
   875 {
   876     // GMythURI* uri = NULL;
   877 
   878     if (NULL == livetv)
   879         goto done;
   880 
   881     if (!livetv->setup_done) {
   882         gmyth_debug
   883             ("Error: You must do the LiveTV setup, just before generating the FileTransfer from LiveTV source!");
   884         goto done;
   885     }
   886 
   887     if (livetv->proginfo != NULL)
   888         gmyth_debug("URI path (from program info) = %s.\n",
   889                     livetv->proginfo->pathname->str);
   890     else
   891         gmyth_debug("URI path (from URI) = %s.\n", livetv->uri->uri->str);
   892 
   893     g_mutex_lock(livetv->mutex);
   894 
   895     if (livetv->file != NULL) {
   896         /*
   897          * gmyth_file_transfer_close( livetv->file ); 
   898          */
   899         g_object_unref(livetv->file);
   900         livetv->file = NULL;
   901     }
   902 
   903     if (livetv->uri != NULL) {
   904         gmyth_debug
   905             ("URI is not NULL, creating from the ProgramInfo pathname... (%s)",
   906              livetv->proginfo->pathname->str);
   907         livetv->uri->path = g_string_erase(livetv->uri->path, 0, -1);
   908         livetv->uri->path =
   909             g_string_new(g_strrstr(livetv->proginfo->pathname->str, "/"));
   910     } else {
   911         gmyth_debug
   912             ("URI is NULL, creating from the ProgramInfo pathname... (%s)",
   913              livetv->proginfo->pathname->str);
   914         livetv->uri =
   915             gmyth_uri_new_with_value(livetv->proginfo->pathname->str);
   916     }
   917 
   918     if (NULL == livetv->uri) {
   919         gmyth_debug("Couldn't parse the URI to start LiveTV! [ uri = %s ]",
   920                     livetv->proginfo->pathname->str);
   921         goto done;
   922     }
   923 
   924     if (gmyth_uri_is_local_file(livetv->uri))
   925         livetv->file =
   926             GMYTH_FILE(gmyth_file_local_new(livetv->backend_info));
   927     else {
   928         livetv->file =
   929             GMYTH_FILE(gmyth_file_transfer_new(livetv->backend_info));
   930         /*
   931          * gmyth_file_transfer_settimeout(
   932          * GMYTH_FILE_TRANSFER(livetv->file), TRUE ); 
   933          */
   934     }
   935 
   936     if (NULL == livetv->file) {
   937         gmyth_debug
   938             ("Error: couldn't create the FileTransfer from LiveTV source!");
   939         goto done;
   940     }
   941 
   942     g_object_ref(livetv->file);
   943 
   944     g_mutex_unlock(livetv->mutex);
   945 
   946     /*
   947      * Do some locking procedure with the Monitor Handler messages... 
   948      */
   949 
   950   done:
   951     /*
   952      * if ( uri != NULL ) { g_object_unref( uri ); uri = NULL; } 
   953      */
   954 
   955     return livetv->file;
   956 
   957 }
   958 
   959 /**
   960  * Stops this LiveTV session.
   961  * 
   962  * @param live_tv the GMythLiveTV instance
   963  */
   964 void
   965 gmyth_livetv_stop_playing(GMythLiveTV * livetv)
   966 {
   967     gmyth_debug("Stopping the LiveTV...\n");
   968 
   969     if (livetv->is_livetv) {
   970         if (!gmyth_recorder_stop_livetv(livetv->recorder)) {
   971             gmyth_debug("[%s] Error while stoping remote encoder",
   972                         __FUNCTION__);
   973         }
   974 
   975         if (!gmyth_recorder_finish_recording(livetv->recorder)) {
   976             gmyth_debug
   977                 ("[%s] Error while finishing recording on remote encoder",
   978                  __FUNCTION__);
   979         }
   980     }
   981 }
   982 
   983 gboolean
   984 gmyth_livetv_is_playing(GMythLiveTV * livetv)
   985 {
   986     return TRUE;
   987 }
   988 
   989 void
   990 gmyth_livetv_start_playing(GMythLiveTV * livetv)
   991 {
   992 
   993     // TODO
   994 
   995 }