4 * @file gmyth/gmyth_livetv.c
6 * @brief <p> GMythLiveTV starts a remote TV session with the MythTV backend.
8 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
9 * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "gmyth_remote_util.h"
29 #include "gmyth_tvchain.h"
30 #include "gmyth_socket.h"
31 #include "gmyth_debug.h"
33 #include "gmyth_livetv.h"
34 #include "gmyth_file_transfer.h"
36 static void gmyth_livetv_class_init (GMythLiveTVClass *klass);
37 static void gmyth_livetv_init (GMythLiveTV *object);
39 static void gmyth_livetv_dispose (GObject *object);
40 static void gmyth_livetv_finalize (GObject *object);
42 static gint tvchain_curr_index = -1;
44 #define GMYTHTV_RECORDER_HEADER "QUERY_RECORDER"
47 G_DEFINE_TYPE(GMythLiveTV, gmyth_livetv, G_TYPE_OBJECT)
50 gmyth_livetv_class_init (GMythLiveTVClass *klass)
52 GObjectClass *gobject_class;
54 gobject_class = (GObjectClass *) klass;
56 gobject_class->dispose = gmyth_livetv_dispose;
57 gobject_class->finalize = gmyth_livetv_finalize;
61 gmyth_livetv_init (GMythLiveTV *livetv)
63 livetv->backend_hostname = NULL;
64 livetv->backend_port = 0;
65 livetv->local_hostname = NULL;
67 livetv->recorder = NULL;
68 livetv->tvchain = NULL;
69 livetv->proginfo = NULL;
73 gmyth_livetv_dispose (GObject *object)
76 G_OBJECT_CLASS (gmyth_livetv_parent_class)->dispose (object);
80 gmyth_livetv_finalize (GObject *object)
82 g_signal_handlers_destroy (object);
84 GMythLiveTV *livetv = GMYTH_LIVETV (object);
86 gmyth_debug ("[%s] Finalizing livetv", __FUNCTION__);
88 if ( livetv->recorder != NULL ) {
89 g_object_unref (livetv->recorder);
90 livetv->recorder = NULL;
93 if ( livetv->tvchain != NULL ) {
94 g_object_unref (livetv->tvchain);
95 livetv->tvchain = NULL;
98 if ( livetv->proginfo != NULL ) {
99 g_object_unref (livetv->proginfo);
100 livetv->proginfo = NULL;
103 G_OBJECT_CLASS ( gmyth_livetv_parent_class )->finalize ( object );
109 GMythLiveTV *livetv = GMYTH_LIVETV ( g_object_new( GMYTH_LIVETV_TYPE, NULL ) );
115 gmyth_livetv_setup ( GMythLiveTV *livetv, GMythBackendInfo *backend_info )
120 GMythSocket *socket = gmyth_socket_new ();
122 // FIME: Implement this at gmyth_socket
123 res = gmyth_socket_connect_to_backend (socket, backend_info->hostname,
124 backend_info->port, TRUE);
126 g_warning ("[%s] LiveTV can not connect to backend", __FUNCTION__);
131 livetv->is_livetv = TRUE;
133 hostname = gmyth_backend_info_get_hostname(backend_info);
134 livetv->backend_hostname = g_string_new (hostname);
135 livetv->backend_port = gmyth_backend_info_get_port (backend_info);
137 livetv->local_hostname = gmyth_socket_get_local_hostname ( );
139 if ( livetv->local_hostname == NULL ) {
144 // Gets the recorder num
145 livetv->recorder = remote_request_next_free_recorder (socket, -1);
146 gmyth_socket_close_connection (socket);
148 if ( livetv->recorder == NULL ) {
149 g_warning ("[%s] None remote encoder available", __FUNCTION__);
154 // Creates livetv chain handler
155 livetv->tvchain = GMYTH_TVCHAIN ( g_object_new(GMYTH_TVCHAIN_TYPE, NULL) );
156 gmyth_tvchain_initialize ( livetv->tvchain, backend_info );
158 if ( livetv->tvchain == NULL || livetv->tvchain->tvchain_id == NULL ) {
163 // Init remote encoder. Opens its control socket.
164 res = gmyth_recorder_setup(livetv->recorder);
166 g_warning ("[%s] Fail while setting remote encoder\n", __FUNCTION__);
174 for ( ; idx < 5; idx++ ) {
175 if ( gmyth_recorder_check_channel( livetv->recorder, ch ) ) {
176 if ( gmyth_recorder_set_channel( livetv->recorder, ch ) ) {
177 g_print( "[%s] Channel changed!!! [%d].\n", __FUNCTION__, ch );
185 // Spawn live tv. Uses the socket to send mythprotocol data to start livetv in the backend (remotelly)
186 res = gmyth_recorder_spawntv ( livetv->recorder,
187 gmyth_tvchain_get_id(livetv->tvchain) );
189 g_warning ("[%s] Fail while spawn tv\n", __FUNCTION__);
194 // Reload all TV chain from Mysql database.
195 gmyth_tvchain_reload_all (livetv->tvchain);
197 if ( livetv->tvchain == NULL ) {
202 // Get program info from database using chanid and starttime
203 livetv->proginfo = gmyth_tvchain_get_program_at (livetv->tvchain, tvchain_curr_index++ );
204 if ( livetv->proginfo == NULL ) {
205 g_warning ("[%s] LiveTV not successfully started.\n", __FUNCTION__ );
209 gmyth_debug ("[%s] GMythLiveTV: All requests to backend to start TV were OK.\n", __FUNCTION__ );
215 g_print( "[%s] ERROR running LiveTV setup.\n", __FUNCTION__ );
216 if ( livetv->backend_hostname != NULL ) {
217 g_string_free( livetv->backend_hostname, TRUE );
221 if ( livetv->local_hostname != NULL ) {
222 g_string_free( livetv->local_hostname, TRUE );
226 if ( livetv->recorder != NULL ) {
227 g_object_unref (livetv->recorder);
228 livetv->recorder = NULL;
231 if ( livetv->tvchain != NULL ) {
232 g_object_unref (livetv->tvchain);
233 livetv->tvchain = NULL;
236 if ( livetv->proginfo != NULL ) {
237 g_object_unref (livetv->proginfo);
238 livetv->proginfo = NULL;
246 gmyth_livetv_next_program_chain ( GMythLiveTV *livetv )
250 // Reload all TV chain from Mysql database.
251 gmyth_tvchain_reload_all (livetv->tvchain);
253 if ( livetv->tvchain == NULL ) {
258 // Get program info from database using chanid and starttime
259 livetv->proginfo = gmyth_tvchain_get_program_at (livetv->tvchain, -1 );
260 if ( livetv->proginfo == NULL ) {
261 g_warning ("[%s] LiveTV not successfully started on the next program chain.\n", __FUNCTION__ );
265 gmyth_debug ("[%s] GMythLiveTV: All requests to backend to start TV were OK, TV chain changed.\n", __FUNCTION__ );
271 g_print( "[%s] ERROR running LiveTV setup.\n", __FUNCTION__ );
272 if ( livetv->backend_hostname != NULL ) {
273 g_string_free( livetv->backend_hostname, TRUE );
277 if ( livetv->local_hostname != NULL ) {
278 g_string_free( livetv->local_hostname, TRUE );
282 if ( livetv->recorder != NULL ) {
283 g_object_unref (livetv->recorder);
284 livetv->recorder = NULL;
287 if ( livetv->tvchain != NULL ) {
288 g_object_unref (livetv->tvchain);
289 livetv->tvchain = NULL;
292 if ( livetv->proginfo != NULL ) {
293 g_object_unref (livetv->proginfo);
294 livetv->proginfo = NULL;
301 // FIXME: How to proceed differently between livetv and recorded content
303 gmyth_livetv_stop_playing (GMythLiveTV *livetv)
305 gmyth_debug ("[%s] Stopping the LiveTV...\n", __FUNCTION__);
307 if (livetv->is_livetv) {
308 if (!gmyth_recorder_stop_livetv (livetv->recorder)) {
309 g_warning ("[%s] Error while stoping remote encoder", __FUNCTION__);
314 // FIXME: put here just a wrapper function to call gmyth_recorder_is_recording()...
316 gmyth_livetv_is_recording ( GMythLiveTV *livetv )
320 GMythStringList *str_list = gmyth_string_list_new ();
321 GString *message = g_string_new ("");
323 gmyth_debug ( "[%s]\n", __FUNCTION__ );
324 //g_static_mutex_lock (&mutex);
326 g_string_printf( message, "%s %d", GMYTHTV_RECORDER_HEADER,
327 /* FIXME file_transfer->rec_id >= 0 ? file_transfer->rec_id : file_transfer->card_id );*/
328 livetv->recorder->recorder_num);
329 gmyth_string_list_append_string (str_list, message);
330 gmyth_string_list_append_string (str_list, g_string_new ("IS_RECORDING"));
332 gmyth_socket_sendreceive_stringlist ( livetv->recorder->myth_socket, str_list );
334 if ( str_list != NULL && gmyth_string_list_length(str_list) > 0 )
337 if ( ( str = gmyth_string_list_get_string( str_list, 0 ) ) != NULL && strcmp( str->str, "bad" )!= 0 ) {
338 gint is_rec = gmyth_string_list_get_int( str_list, 0 );
345 g_print( "[%s] %s, stream is %s being recorded!\n", __FUNCTION__, ret ? "YES" : "NO", ret ? "" : "NOT" );
346 //g_static_mutex_unlock (&mutex);
348 if ( str_list != NULL )
349 g_object_unref (str_list);
357 gmyth_livetv_is_playing (GMythLiveTV *livetv)
363 gmyth_livetv_start_playing (GMythLiveTV *livetv)