# HG changeset patch # User renatofilho # Date 1203961903 0 # Node ID 4a8d56080089e4b53fc4a53058538940e49b597e # Parent c39c60fcfec806235d1794a311239d6b3b780658 [svn r934] renamed src dir to gmyth diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/Makefile.am --- a/gmyth/Makefile.am Mon Feb 25 17:45:36 2008 +0000 +++ b/gmyth/Makefile.am Mon Feb 25 17:51:43 2008 +0000 @@ -1,4 +1,4 @@ -SUBDIRS= src samples tests +SUBDIRS= gmyth samples tests pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = gmyth.pc diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/configure.ac --- a/gmyth/configure.ac Mon Feb 25 17:45:36 2008 +0000 +++ b/gmyth/configure.ac Mon Feb 25 17:51:43 2008 +0000 @@ -121,7 +121,7 @@ AC_OUTPUT( Makefile -src/Makefile +gmyth/Makefile samples/Makefile tests/Makefile gmyth.pc) diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/Makefile.am Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,98 @@ +lib_LTLIBRARIES = libgmyth.la + +INCLUDES = -I$(top_srcdir) -I$(top_builddir)/gmyth @GLIB_CFLAGS@ @GOBJECT_CFLAGS@ + +BUILT_SOURCES = \ + gmyth_marshal.c \ + gmyth_marshal.h + +libgmyth_la_SOURCES = \ + gmyth_common.c \ + gmyth_debug.c \ + gmyth_epg.c \ + gmyth_recorder.c \ + gmyth_remote_util.c \ + gmyth_tvchain.c \ + gmyth_scheduler.c \ + gmyth_util.c \ + gmyth_query.c \ + gmyth_socket.c \ + gmyth_stringlist.c \ + gmyth_monitor_handler.c \ + gmyth_file_transfer.c \ + gmyth_livetv.c \ + gmyth_backendinfo.c \ + gmyth_programinfo.c \ + gmyth_uri.c \ + gmyth_http.c \ + gmyth_vlc.c \ + gmyth_jobqueue.c \ + gmyth_transcoder.c \ + gmyth_recprofile.c \ + gmyth_file.c \ + gmyth_file_local.c \ + $(BUILT_SOURCES) + +EXTRA_libgmyth_la_SOURCES = gmyth_marshal.list + +gmyth_marshal.h: gmyth_marshal.list + glib-genmarshal --header --prefix=gmyth_marshal gmyth_marshal.list > gmyth_marshal.h.tmp + mv gmyth_marshal.h.tmp gmyth_marshal.h + +gmyth_marshal.c: gmyth_marshal.list gmyth_marshal.h + echo "#include \"glib-object.h\"" > gmyth_marshal.c.tmp + echo "#include \"gmyth_marshal.h\"" >> gmyth_marshal.c.tmp + glib-genmarshal --body --prefix=gmyth_marshal $(srcdir)/gmyth_marshal.list >> gmyth_marshal.c.tmp + mv gmyth_marshal.c.tmp gmyth_marshal.c + +libgmyth_la_CFLAGS = \ + -DDATADIR=\"$(pkgdatadir)\" \ + $(GLIB_CFLAGS) \ + $(GOBJECT_CFLAGS) \ + $(GST_CFLAGS) \ + $(GSTBASE_CFLAGS) \ + $(GSTPLUGINSBASE_CFLAGS) \ + $(MYSQL_CFLAGS) \ + $(LIBXML_CFLAGS) + +libgmyth_la_LDFLAGS = \ + -export-dynamic \ + $(GLIB_CFLAGS) \ + $(GOBJECT_CFLAGS) \ + $(MYSQL_LIBS) \ + $(GST_LIBS) \ + $(GSTBASE_LIBS) \ + $(GSTPLUGINS_LIBS) \ + $(LIBXML_LIBS) + +libgmyth_includedir = \ + $(pkgincludedir) + +libgmyth_include_HEADERS = \ + gmyth.h \ + gmyth_common.h \ + gmyth_debug.h \ + gmyth_epg.h \ + gmyth_recorder.h \ + gmyth_scheduler.h \ + gmyth_tvchain.h \ + gmyth_util.h \ + gmyth_query.h \ + gmyth_socket.h \ + gmyth_remote_util.h \ + gmyth_stringlist.h \ + gmyth_monitor_handler.h \ + gmyth_file_transfer.h \ + gmyth_livetv.h \ + gmyth_backendinfo.h \ + gmyth_programinfo.h \ + gmyth_uri.h \ + gmyth_http.h \ + gmyth_vlc.h \ + gmyth_jobqueue.h \ + gmyth_transcoder.h \ + gmyth_recprofile.h \ + gmyth_file.h \ + gmyth_file_local.h + +CLEANFILES = $(BUILT_SOURCES) diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth-indent.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth-indent.sh Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,25 @@ +#!/bin/sh +indent \ + -gnu \ + -i4 \ + -l80 \ + -bfda \ + -nut \ + -pcs \ + -psl \ + -bli0 \ + -cs \ + -cli0 \ + -nbfda \ + -sai \ + -saw \ + -saf \ + -sbi4 \ + -npro \ + -nfca \ + -nsc \ + -ts4 \ + -prs \ + -bap \ + $* + diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,57 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth.h + * + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Renato Filho + * + *//* + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + +#ifndef _GMYTH_H_ +#define _GMYTH_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif /* _GMYTH_H_ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_backendinfo.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_backendinfo.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,395 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_backend_info.c + * + * @brief

This component represents all the MythTV backend server + * configuration information. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Melo + * @author Rosfran Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_backendinfo.h" +#include "gmyth_uri.h" +#include "gmyth_debug.h" + +static void gmyth_backend_info_class_init(GMythBackendInfoClass * + klass); +static void gmyth_backend_info_init(GMythBackendInfo * object); + +static void gmyth_backend_info_dispose(GObject * object); +static void gmyth_backend_info_finalize(GObject * object); + +G_DEFINE_TYPE(GMythBackendInfo, gmyth_backend_info, G_TYPE_OBJECT); +static void gmyth_backend_info_class_init(GMythBackendInfoClass * + klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_backend_info_dispose; + gobject_class->finalize = gmyth_backend_info_finalize; +} + +static void +gmyth_backend_info_init(GMythBackendInfo * backend_info) +{ + backend_info->hostname = NULL; + backend_info->port = -1; + backend_info->username = NULL; + backend_info->password = NULL; + backend_info->db_name = NULL; + backend_info->db_port = 0; + backend_info->status_port = -1; +} + +static void +gmyth_backend_info_dispose(GObject * object) +{ + GMythBackendInfo *backend_info = GMYTH_BACKEND_INFO(object); + + g_free(backend_info->hostname); + g_free(backend_info->username); + g_free(backend_info->password); + g_free(backend_info->db_name); + + if (backend_info->sock) + g_object_unref (backend_info->sock); + + backend_info->hostname = NULL; + backend_info->port = -1; + backend_info->username = NULL; + backend_info->password = NULL; + backend_info->db_name = NULL; + backend_info->db_port = 0; + backend_info->status_port = -1; + backend_info->sock = NULL; + + G_OBJECT_CLASS(gmyth_backend_info_parent_class)->dispose(object); +} + +static void +gmyth_backend_info_finalize(GObject * object) +{ + g_signal_handlers_destroy(object); + + G_OBJECT_CLASS(gmyth_backend_info_parent_class)->finalize(object); +} + +/** + * Creates a new instance of GMythBackendInfo. + * + * @return a new instance of GMythBackendInfo. + */ +GMythBackendInfo * +gmyth_backend_info_new() +{ + GMythBackendInfo *backend_info = + GMYTH_BACKEND_INFO(g_object_new(GMYTH_BACKEND_INFO_TYPE, NULL)); + + return backend_info; +} + +/** + * Creates a new instance of GMythBackendInfo, based on a given set of + * configuration parameters. + * + * @param hostname The hostname to the MythTV backend server. + * @param username The user name to the MythTV backend MySQL server. + * @param password The password to the user of the MythTV backend MySQL server. + * @param db_name The database name of the MythTV backend, stored on the MySQL server. + * @param port The port number of the MythTV backend server (commonly is 6543). + * + * @return a new instance of GMythBackendInfo. + */ +GMythBackendInfo * +gmyth_backend_info_new_full(const gchar * hostname, const gchar * username, + const gchar * password, const gchar * db_name, + gint port) +{ + GMythBackendInfo *backend_info = + GMYTH_BACKEND_INFO(g_object_new(GMYTH_BACKEND_INFO_TYPE, NULL)); + + gmyth_backend_info_set_hostname(backend_info, hostname); + gmyth_backend_info_set_username(backend_info, username); + gmyth_backend_info_set_password(backend_info, password); + gmyth_backend_info_set_db_name(backend_info, db_name); + gmyth_backend_info_set_port(backend_info, port); + + return backend_info; +} + +/** + * Creates a new instance of GMythBackendInfo, based on the + * MythTV's backend server URI string. + * + * @param uri_str The URI string pointing to the MythTV backend server. + * + * @return a new instance of GMythBackendInfo. + */ +GMythBackendInfo * +gmyth_backend_info_new_with_uri(const gchar * uri_str) +{ + GMythBackendInfo *backend_info; + GMythURI *uri; + gchar **path_parts; + gchar *db; + + backend_info = GMYTH_BACKEND_INFO(g_object_new(GMYTH_BACKEND_INFO_TYPE, NULL)); + uri = gmyth_uri_new_with_value (uri_str); + path_parts = g_strsplit(gmyth_uri_get_path(uri), "&", -1); + gmyth_backend_info_set_hostname(backend_info, gmyth_uri_get_host(uri)); + gmyth_backend_info_set_username(backend_info, gmyth_uri_get_user(uri)); + gmyth_backend_info_set_password(backend_info, + gmyth_uri_get_password(uri)); + + /* + * gets the path info to database name, from the URI, and removes the + * trash chars + */ + if ((path_parts != NULL) && (strlen (path_parts[0]) > 0)) + { + db = path_parts[0]+2; + } + else + { + db = gmyth_uri_get_path(uri); + } + + gmyth_backend_info_set_db_name(backend_info, db); + + gmyth_backend_info_set_port(backend_info, gmyth_uri_get_port(uri)); + + g_object_unref(uri); + g_strfreev(path_parts); + + return backend_info; +} + +void +gmyth_backend_info_set_hostname(GMythBackendInfo * backend_info, + const gchar * hostname) +{ + g_return_if_fail(backend_info != NULL); + + if (NULL == hostname || strlen(hostname) <= 0) { + gmyth_debug("Error trying to set a hostname equals to NULL."); + } else { + backend_info->hostname = g_strdup(hostname); + } +} + +void +gmyth_backend_info_set_username(GMythBackendInfo * backend_info, + const gchar * username) +{ + g_return_if_fail(backend_info != NULL); + + backend_info->username = g_strdup(username); +} + +void +gmyth_backend_info_set_password(GMythBackendInfo * backend_info, + const gchar * password) +{ + g_return_if_fail(backend_info != NULL); + + backend_info->password = g_strdup(password); +} + +void +gmyth_backend_info_set_db_name(GMythBackendInfo * backend_info, + const gchar * db_name) +{ + g_return_if_fail(backend_info != NULL); + + backend_info->db_name = g_strdup(db_name); +} + +void +gmyth_backend_info_set_db_port(GMythBackendInfo * backend_info, gint db_port) +{ + g_return_if_fail(backend_info != NULL); + + if (db_port <= 0) { + gmyth_debug("Error trying to set a port less than 0."); + } else { + backend_info->db_port = db_port; + } +} + +void +gmyth_backend_info_set_port(GMythBackendInfo * backend_info, gint port) +{ + g_return_if_fail(backend_info != NULL); + + if (port <= 0) { + gmyth_debug("Error trying to set a port less than 0."); + } else { + backend_info->port = port; + } +} + +void +gmyth_backend_info_set_status_port(GMythBackendInfo * backend_info, + gint port) +{ + g_return_if_fail(backend_info != NULL); + + if (port <= 0) { + gmyth_debug + ("Error trying to set the status port to less than zero."); + } else { + backend_info->status_port = port; + } +} + +const gchar * +gmyth_backend_info_get_hostname(GMythBackendInfo * backend_info) +{ + g_return_val_if_fail(backend_info != NULL, NULL); + + return backend_info->hostname; +} + +const gchar * +gmyth_backend_info_get_username(GMythBackendInfo * backend_info) +{ + g_return_val_if_fail(backend_info != NULL, NULL); + + return backend_info->username; +} + +const gchar * +gmyth_backend_info_get_password(GMythBackendInfo * backend_info) +{ + g_return_val_if_fail(backend_info != NULL, NULL); + + return backend_info->password; +} + +const gchar * +gmyth_backend_info_get_db_name(GMythBackendInfo * backend_info) +{ + g_return_val_if_fail(backend_info != NULL, NULL); + + return backend_info->db_name; +} + +gint +gmyth_backend_info_get_idb_port(GMythBackendInfo * backend_info) +{ + g_return_val_if_fail(backend_info != NULL, -1); + + return backend_info->db_port; +} + + +gint +gmyth_backend_info_get_port(GMythBackendInfo * backend_info) +{ + g_return_val_if_fail(backend_info != NULL, -1); + + return backend_info->port; +} + +/** + * Creates a new instance of GMythURI, based on the GMythBackendInfo instance to the + * MythTV's backend server. + * + * @param backend_info The GMythBackendInfo instance. + * + * @return an instance of GMythURI, created from a GMythBackendInfo. + */ +GMythURI * +gmyth_backend_info_get_uri(GMythBackendInfo * backend_info) +{ + GMythURI *uri = NULL; + gchar *uri_str = NULL; + gchar *user_info = NULL; + gchar *db_data = NULL; + + if ((backend_info->username != NULL + && strlen(backend_info->username) > 0)) + user_info = + g_strdup_printf("%s:%s@", backend_info->username, + backend_info->password); + + if (backend_info->db_name != NULL && strlen(backend_info->db_name) > 0) { + if ((g_strrstr(backend_info->db_name, "_") != NULL)) + db_data = g_strdup(backend_info->db_name); + else + db_data = g_strdup_printf("?%s&", backend_info->db_name); + } + // else if ( ( ( g_strrstr( backend_info->path, "livetv" ) != NULL ) + // || + // ( g_strrstr( backend_info->path, "/?" ) != NULL ) ) + + uri_str = g_strdup_printf("myth://%s%s:%d/%s", user_info != NULL + && strlen(user_info) > 0 ? user_info : "", + backend_info->hostname, backend_info->port, + db_data != NULL + && strlen(db_data) > 0 ? db_data : ""); + uri = gmyth_uri_new_with_value(uri_str); + + if (user_info != NULL) + g_free(user_info); + + if (db_data != NULL) + g_free(db_data); + + g_free(uri_str); + + return uri; +} + +gboolean +gmyth_backend_info_is_local_file(GMythBackendInfo * backend_info) +{ + g_return_val_if_fail(backend_info != NULL, FALSE); + + return + gmyth_uri_is_local_file(gmyth_backend_info_get_uri(backend_info)); +} + +GMythSocket* +gmyth_backend_info_get_connected_socket (GMythBackendInfo *backend_info) +{ + if (backend_info->sock == NULL) { + gboolean res; + backend_info->sock = gmyth_socket_new (); + res = gmyth_socket_connect_to_backend (backend_info->sock, + backend_info->hostname, + backend_info->port, + TRUE); + if (res == FALSE) { + g_object_unref (backend_info->sock); + backend_info->sock = NULL; + return NULL; + } + } + + return g_object_ref (backend_info->sock); +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_backendinfo.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_backendinfo.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,121 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_backend_info.h + * + * @brief

This component represents all the MythTV backend server + * configuration information. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Melo + * @author Rosfran Borges + * +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_BACKEND_INFO_H__ +#define __GMYTH_BACKEND_INFO_H__ + +#include + +#include "gmyth_uri.h" +#include "gmyth_socket.h" + +G_BEGIN_DECLS +#define GMYTH_BACKEND_INFO_TYPE \ + (gmyth_backend_info_get_type ()) +#define GMYTH_BACKEND_INFO(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_BACKEND_INFO_TYPE, GMythBackendInfo)) +#define GMYTH_BACKEND_INFO_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_BACKEND_INFO_TYPE, GMythBackendInfoClass)) +#define IS_GMYTH_BACKEND_INFO(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_BACKEND_INFO_TYPE)) +#define IS_GMYTH_BACKEND_INFO_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_BACKEND_INFO_TYPE)) +#define GMYTH_BACKEND_INFO_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_BACKEND_INFO_TYPE, GMythBackendInfoClass)) + +typedef struct _GMythBackendInfo GMythBackendInfo; +typedef struct _GMythBackendInfoClass GMythBackendInfoClass; + +struct _GMythBackendInfoClass { + GObjectClass parent_class; + + /* + * callbacks + */ + /* + * no one for now + */ +}; + +struct _GMythBackendInfo { + GObject parent; + /** The backend hostname or ip address. */ + gchar *hostname; + /** The backend port. */ + gint port; + /** The username to connect to the mysql server. */ + gchar *username; + /** The password to connect to the mysql server. */ + gchar *password; + /** The mythtv's mysql database name. */ + gchar *db_name; + /** The mysql database port */ + gint db_port; + /** The backend status port for http connection */ + gint status_port; + + /* Private */ + GMythSocket *sock; +}; + + +GType gmyth_backend_info_get_type (void) G_GNUC_CONST; +GMythBackendInfo* gmyth_backend_info_new (void); +GMythBackendInfo* gmyth_backend_info_new_full (const gchar *hostname, + const gchar *username, + const gchar *password, + const gchar *db_name, + gint port); +GMythBackendInfo* gmyth_backend_info_new_with_uri (const gchar *uri_str); +void gmyth_backend_info_set_hostname (GMythBackendInfo *backend_info, + const gchar *hostname); +void gmyth_backend_info_set_username (GMythBackendInfo *backend_info, + const gchar *username); +void gmyth_backend_info_set_password (GMythBackendInfo *backend_info, + const gchar *password); +void gmyth_backend_info_set_db_name (GMythBackendInfo *backend_info, + const gchar *db_name); +void gmyth_backend_info_set_db_port (GMythBackendInfo *backend_info, + gint db_port); +void gmyth_backend_info_set_port (GMythBackendInfo *backend_info, + gint port); +void gmyth_backend_info_set_status_port (GMythBackendInfo *backend_info, + gint port); +const gchar* gmyth_backend_info_get_hostname (GMythBackendInfo *backend_info); +const gchar* gmyth_backend_info_get_username (GMythBackendInfo *backend_info); +const gchar* gmyth_backend_info_get_password (GMythBackendInfo *backend_info); +const gchar* gmyth_backend_info_get_db_name (GMythBackendInfo *backend_info); +gint gmyth_backend_info_get_db_port (GMythBackendInfo *backend_info); +gint gmyth_backend_info_get_port (GMythBackendInfo *backend_info); +GMythURI* gmyth_backend_info_get_uri (GMythBackendInfo *backend_info); +gboolean gmyth_backend_info_is_local_file (GMythBackendInfo *backend_info); +GMythSocket* gmyth_backend_info_get_connected_socket + (GMythBackendInfo *backend_info); + +G_END_DECLS +#endif /* __GMYTH_BACKEND_INFO_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_common.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_common.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,154 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_common.c + * + * @brief

This file contains basic common functions for the gmyth library. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Leonardo Sobral Cunha + * @author Rosfran Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_common.h" +#include "gmyth_debug.h" +#include "gmyth_util.h" + +static void free_channel_data(gpointer data, gpointer user_data); +static void free_program_data(gpointer data, gpointer user_data); + +/** +* Frees the memory allocated to the GMythChannelInfo objects inside list. +* The list memory is also released by g_list_free(). If LIST is NULL it +* simply returns. +* +* @param list the GList containing a list of GMythChannelInfo to free. +*/ +void +gmyth_free_channel_list(GList * list) +{ + g_return_if_fail(list != NULL); + + g_list_foreach(list, free_channel_data, NULL); + g_list_free(list); +} + +/** + * Frees the memory allocated to the GMythProgramInfo objects inside list. + * The list memory is also released by g_list_free(). If list is NULL it + * simply returns. + * + * @param list the GList containing a list of GMythProgramInfo to free. + */ +void +gmyth_free_program_list(GList * list) +{ + g_return_if_fail(list != NULL); + + g_list_foreach(list, free_program_data, NULL); + g_list_free(list); +} + +void +gmyth_channel_info_free(GMythChannelInfo * channel) +{ + g_return_if_fail(channel != NULL); + + if (channel->channel_num) + g_string_free(channel->channel_num, TRUE); + + if (channel->channel_name) + g_string_free(channel->channel_name, TRUE); + + if (channel->channel_icon) + g_string_free(channel->channel_icon, TRUE); + + g_free(channel); +} + +/** + * Prints the channel info to the standard output. The gmyth debug must be enabled. + * @param channel_info the GMythChannelInfo instance + */ +void +gmyth_channel_info_print(GMythChannelInfo * channel_info) +{ +#ifdef GMYTH_USE_DEBUG + if (channel_info != NULL) { + g_return_if_fail(channel_info->channel_name != NULL); + g_return_if_fail(channel_info->channel_num != NULL); + + gmyth_debug("ChannelInfo (Name, Num, ID) = (%s, %s, %d)", + channel_info->channel_name->str, + channel_info->channel_num->str, + channel_info->channel_ID); + + } +#endif +} + +/** + * Prints the program info to the standard output. The gmyth debug must be enabled. + * @param channel_info the GMythProgramInfo instance + */ +void +gmyth_program_info_print(GMythProgramInfo * program_info) +{ +#ifdef GMYTH_USE_DEBUG + g_return_if_fail(program_info); + + gmyth_debug("ProgramInfo\n\tTitle = %s\n\t" + "Description = %s\n\t" + "Start time= %s\t" + "End time = %s\n" + "Path name = %s\n" + "File size = %lld\n", + program_info->title ? program_info->title->str : "NULL", + program_info->description ? program_info->description-> + str : "NULL", + gmyth_util_time_to_string_from_time_val(program_info-> + startts), + gmyth_util_time_to_string_from_time_val(program_info-> + endts), + program_info->pathname ? program_info->pathname-> + str : "NULL", program_info->filesize); +#endif +} + +static void +free_channel_data(gpointer data, gpointer user_data) +{ + /* + * Frees the GMythChannelInfo structure + */ + GMythChannelInfo *channel = (GMythChannelInfo *) data; + + gmyth_channel_info_free(channel); +} + +static void +free_program_data(gpointer data, gpointer user_data) +{ + g_return_if_fail(data != NULL); + + g_object_unref((GMythProgramInfo *) data); +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_common.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_common.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,62 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_common.h + * + * @brief

This file contains basic common functions for the gmyth library. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Leonardo Sobral Cunha + * @author Rosfran Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef GMYTH_COMMON_H_ +#define GMYTH_COMMON_H_ + +#include +#include + +#include "gmyth_programinfo.h" + +G_BEGIN_DECLS + /** + * The GMythChannelInfo structure represents the channel information + * stored in the backend database. + */ + typedef struct { + /** The channel ID in backend database */ + gint channel_ID; + + /** The channel number */ + GString *channel_num; + + /** The channel name in backend database */ + GString *channel_name; + + /** The channel icon path in the backend database */ + GString *channel_icon; +} GMythChannelInfo; + +void gmyth_free_channel_list (GList *list); +void gmyth_free_program_list (GList *list); +void gmyth_channel_info_free (GMythChannelInfo *channel_info); +void gmyth_channel_info_print (GMythChannelInfo *channel_info); +void gmyth_program_info_print (GMythProgramInfo *program_info); + +G_END_DECLS +#endif /* GMYTH_COMMON_H_ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_debug.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_debug.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,54 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_debug.c + * + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Renato Filho + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_debug.h" + +void +gmyth_debug_real(const char *func, + const char *file, const int line, gboolean newline, + const char *format, ...) +{ + va_list args; + char buffer[1025]; + char str_time[255]; + time_t the_time; + + va_start(args, format); + + g_vsnprintf(buffer, 1024, format, args); + + va_end(args); + + time(&the_time); + strftime(str_time, 254, "%H:%M:%S", localtime(&the_time)); + + g_printerr(newline ? "(%s) [%p] [%s] %s:%d: %s\n" : + "(%s) [%p] [%s] %s:%d: %s", str_time, g_thread_self(), func, + file, line, buffer); +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_debug.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_debug.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,46 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_debug.h + * + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Renato Filho + * +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_DEBUG_H__ +#define __GMYTH_DEBUG_H__ + +#include +#include +#include + +G_BEGIN_DECLS +#ifdef GMYTH_USE_DEBUG +#define gmyth_debug(...) gmyth_debug_real (__FUNCTION__, __FILE__, __LINE__, TRUE, __VA_ARGS__) +#else +#define gmyth_debug(...) +#endif + void +gmyth_debug_real(const char *func, + const char *file, int line, gboolean newline, + const char *format, ...) +G_GNUC_PRINTF(5, 6); + +G_END_DECLS +#endif diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_epg.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_epg.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,446 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_epg.c + * + * @brief

GMythEPG class provides access to the program and channel data + * from the Electronic Program Guide (EPG) of the Mythtv backend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Leonardo Sobral Cunha + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include "gmyth_epg.h" +#include "gmyth_programinfo.h" +#include "gmyth_util.h" +#include "gmyth_file_transfer.h" +#include "gmyth_debug.h" + +#define CONNECT_TIMEOUT 6 + +static void gmyth_epg_class_init(GMythEPGClass * klass); +static void gmyth_epg_init(GMythEPG * object); + +static void gmyth_epg_dispose(GObject * object); +static void gmyth_epg_finalize(GObject * object); + +G_DEFINE_TYPE(GMythEPG, gmyth_epg, G_TYPE_OBJECT) + static void gmyth_epg_class_init(GMythEPGClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->dispose = gmyth_epg_dispose; + gobject_class->finalize = gmyth_epg_finalize; +} + +static void +gmyth_epg_init(GMythEPG * gmyth_epg) +{ + +} + +static void +gmyth_epg_dispose(GObject * object) +{ + GMythEPG *gmyth_epg = GMYTH_EPG(object); + + if (gmyth_epg->sqlquery != NULL) { + g_object_unref(gmyth_epg->sqlquery); + gmyth_epg->sqlquery = NULL; + } + + G_OBJECT_CLASS(gmyth_epg_parent_class)->dispose(object); +} + +static void +gmyth_epg_finalize(GObject * object) +{ + g_signal_handlers_destroy(object); + + G_OBJECT_CLASS(gmyth_epg_parent_class)->finalize(object); +} + +/** + * Creates a new instance of GMythEPG. + * + * @return a new instance of GMythEPG. + */ +GMythEPG * +gmyth_epg_new(void) +{ + GMythEPG *epg = GMYTH_EPG(g_object_new(GMYTH_EPG_TYPE, NULL)); + + return epg; +} + +/** Connects to the Mysql database in the backend. The backend address + * is loaded from the GMythSettings instance. + * + * @param gmyth_epg the GMythEPG instance to be connected. + * @return true if connection was success, false if failed. + */ +gboolean +gmyth_epg_connect(GMythEPG * gmyth_epg, GMythBackendInfo * backend_info) +{ + g_return_val_if_fail(gmyth_epg != NULL, FALSE); + + if (gmyth_epg->sqlquery == NULL) { + gmyth_debug("[%s] Creating gmyth_query", __FUNCTION__); + gmyth_epg->sqlquery = gmyth_query_new(); + } + + if (!gmyth_query_connect_with_timeout(gmyth_epg->sqlquery, + backend_info, CONNECT_TIMEOUT)) { + gmyth_debug("[%s] Error while connecting to db", __FUNCTION__); + return FALSE; + } + + gmyth_epg->backend_info = backend_info; + g_object_ref(backend_info); + + return TRUE; +} + +/** Disconnects from the Mysql database in the backend. + * + * @param gmyth_epg the GMythEPG instance to be disconnected + * @return true if disconnection was success, false if failed. + */ +gboolean +gmyth_epg_disconnect(GMythEPG * gmyth_epg) +{ + g_return_val_if_fail(gmyth_epg != NULL, FALSE); + + if (gmyth_epg->sqlquery != NULL) { + gmyth_query_disconnect(gmyth_epg->sqlquery); + g_object_unref(gmyth_epg->sqlquery); + gmyth_epg->sqlquery = NULL; + } + + if (gmyth_epg->backend_info != NULL) { + g_object_unref(gmyth_epg->backend_info); + gmyth_epg->backend_info = NULL; + } + + return TRUE; +} + +/** Retrieves the available list of channels from the backend Mysql database. + * + * @param gmyth_epg the GMythEPG instance. + * @param glist_ptr the GSList pointer to be filled with the loaded list address. + * @return The amount of channels retrieved from database, or -1 if error. + */ +gint +gmyth_epg_get_channel_list(GMythEPG * gmyth_epg, GList ** glist_ptr) +{ + MYSQL_RES *msql_res; + + g_return_val_if_fail(gmyth_epg != NULL, -1); + + msql_res = gmyth_query_process_statement(gmyth_epg->sqlquery, + "SELECT chanid, channum, name, icon FROM channel;"); + + (*glist_ptr) = NULL; + + if (msql_res == NULL) { + gmyth_debug("[%s] msql query returned NULL MYSQL_RES", + __FUNCTION__); + return -1; + } else { + MYSQL_ROW row; + GMythChannelInfo *channel_info; + + while ((row = mysql_fetch_row(msql_res)) != NULL) { + + channel_info = g_new0(GMythChannelInfo, 1); + channel_info->channel_ID = + (gint) g_ascii_strtoull(row[0], NULL, 10); + channel_info->channel_num = g_string_new(row[1]); + channel_info->channel_name = g_string_new(row[2]); + channel_info->channel_icon = g_string_new(row[3]); +#ifdef GMYTH_USE_DEBUG + gmyth_channel_info_print(channel_info); +#endif + (*glist_ptr) = g_list_append((*glist_ptr), channel_info); + } + } + mysql_free_result(msql_res); + + return (!(*glist_ptr)) ? 0 : g_list_length(*glist_ptr); +} + +GMythChannelInfo * +gmyth_epg_get_channel_info(GMythEPG * gmyth_epg, gint channel_id) +{ + GMythChannelInfo *channel_info = NULL; + MYSQL_RES *msql_res; + gchar *query_str; + + g_return_val_if_fail(gmyth_epg != NULL, NULL); + + query_str = + g_strdup_printf + ("SELECT channum, name, icon FROM channel WHERE chanid=%d;", + channel_id); + msql_res = + gmyth_query_process_statement(gmyth_epg->sqlquery, query_str); + + if (msql_res == NULL) { + gmyth_debug("[%s] msql query returned NULL MYSQL_RES", + __FUNCTION__); + return NULL; + } else { + MYSQL_ROW row; + + if ((row = mysql_fetch_row(msql_res)) != NULL) { + + channel_info = g_new0(GMythChannelInfo, 1); + channel_info->channel_ID = channel_id; + channel_info->channel_num = g_string_new(row[0]); + channel_info->channel_name = g_string_new(row[1]); + channel_info->channel_icon = g_string_new(row[2]); +#ifdef GMYTH_USE_DEBUG + gmyth_channel_info_print(channel_info); +#endif + } + } + mysql_free_result(msql_res); + + return channel_info; +} + +/** + * Retrieves the available list of channels from the backend Mysql database. + * + * @param gmyth_epg the GMythEPG instance. + * @param proglist the GSList pointer to be filled with the loaded list. + * @param chan_num the channel num on which to search for program. + * @param starttime the start time to search for programs. + * @param endtime the end time to search for programs. + * @return The amount of channels retrieved from database, or -1 if error. + */ +gint +gmyth_epg_get_program_list(GMythEPG * gmyth_epg, GList ** proglist, + const gint chan_num, GTimeVal * starttime, + GTimeVal * endtime) +{ + + gchar *startts = + gmyth_util_time_to_string_from_time_val(starttime); + gchar *endts = + gmyth_util_time_to_string_from_time_val(endtime); + MYSQL_ROW row; + GString *querystr; + + assert(gmyth_epg); + + querystr = + g_string_new + ("SELECT DISTINCT program.chanid, program.starttime, program.endtime, " + " program.title, program.subtitle, program.description, " + " program.category, channel.channum, channel.callsign, " + " channel.name, program.previouslyshown, channel.commfree, " + " channel.outputfilters, program.seriesid, program.programid, " + " program.airdate, program.stars, program.originalairdate, " + " program.category_type, record.recordid, " + " oldrecstatus.rectype, oldrecstatus.recstatus, " + " oldrecstatus.findid " + "FROM program " + "LEFT JOIN channel ON program.chanid = channel.chanid " + "LEFT JOIN record ON " + " program.chanid = record.chanid AND " + " DATE (program.starttime) = record.startdate AND " + " TIME (program.starttime) = record.starttime AND " + " DATE (program.endtime) = record.enddate AND " + " TIME (program.endtime) = record.endtime " + "LEFT JOIN oldrecorded AS oldrecstatus ON " + " program.title = oldrecstatus.title AND " + " channel.callsign = oldrecstatus.station AND " + " program.starttime = oldrecstatus.starttime "); + + g_string_append_printf(querystr, + "WHERE program.chanid = %d " + " AND program.endtime >= '%s' " + " AND program.starttime <= '%s' " + " AND program.manualid = 0 ", chan_num, + startts, endts); + + if (!g_strrstr(querystr->str, " GROUP BY ")) + querystr = g_string_append(querystr, + " GROUP BY program.starttime, channel.channum, " + " channel.callsign, program.title "); + + if (!g_strrstr(querystr->str, " LIMIT ")) + querystr = g_string_append(querystr, " LIMIT 1000 "); + + MYSQL_RES *res_set = + gmyth_query_process_statement(gmyth_epg->sqlquery, querystr->str); + + if (res_set == NULL) { + gmyth_debug("[%s] msql query returned NULL MYSQL_RES", + __FUNCTION__); + return -1; + } + + *proglist = NULL; + while ((row = mysql_fetch_row(res_set)) != NULL) { + + GMythProgramInfo *p = gmyth_program_info_new(); + + p->channel_id = (int) g_ascii_strtoull (row[0], NULL, 10); + + p->startts = gmyth_util_string_to_time_val(row[1]); + p->endts = gmyth_util_string_to_time_val(row[2]); + + p->recstartts = g_new0(GTimeVal, 1); + p->recstartts->tv_sec = p->startts->tv_sec; + p->recstartts->tv_usec = p->startts->tv_usec; + + p->recendts = g_new0(GTimeVal, 1); + p->recendts->tv_sec = p->endts->tv_sec; + p->recendts->tv_usec = p->endts->tv_usec; + + p->lastmodified = g_new0(GTimeVal, 1); + p->lastmodified->tv_sec = p->startts->tv_sec; + p->lastmodified->tv_usec = p->startts->tv_usec; + + + p->title = g_string_new(row[3]); + p->subtitle = g_string_new(row[4]); + p->description = g_string_new(row[5]); + p->category = g_string_new(row[6]); + p->chanstr = g_string_new(row[7]); + p->chansign = g_string_new(row[8]); + p->channame = g_string_new(row[9]); + p->repeat = g_ascii_strtoull(row[10], NULL, 10); + p->chancommfree = g_ascii_strtoull(row[11], NULL, 10); + p->chanOutputFilters = g_string_new(row[12]); + p->seriesid = g_string_new(row[13]); + p->program_id = g_string_new(row[14]); + p->year = g_string_new(row[15]); + p->stars = g_ascii_strtod(row[16], NULL); + + if (!row[17] || !strcmp(row[17], "")) { + p->originalAirDate = 0; + p->hasAirDate = FALSE; + } else { + p->originalAirDate = gmyth_util_string_to_time_val(row[17]); + p->hasAirDate = TRUE; + } + + p->catType = g_string_new(row[18]); + if (row[19] != NULL) + p->recordid = g_ascii_strtoull(row[19], NULL, 10); + + *proglist = g_list_append(*proglist, p); + +#ifdef GMYTH_USE_DEBUG + gmyth_program_info_print(p); +#endif + } + + /* + * deallocate + */ + mysql_free_result(res_set); + g_string_free(querystr, TRUE); + + return g_list_length (*proglist); +} + +gboolean +gmyth_epg_channel_has_icon(GMythEPG * gmyth_epg, + GMythChannelInfo * channel_info) +{ + gboolean res = FALSE; + + g_return_val_if_fail(gmyth_epg != NULL, FALSE); + g_return_val_if_fail(channel_info != NULL, FALSE); + + if (channel_info->channel_icon != NULL) { + res = gmyth_util_file_exists(gmyth_epg->backend_info, + channel_info->channel_icon->str); + } + + return res; + +} + +/** + * + * @param data the data pointer to be filled with icon binary data. It must be freed by the calling function. + * @return TRUE if success, FALSE if any error happens. + */ +gboolean +gmyth_epg_channel_get_icon(GMythEPG * gmyth_epg, + GMythChannelInfo * channel_info, guint8 ** data, + guint * length) +{ + gboolean res = FALSE; + + g_return_val_if_fail(gmyth_epg != NULL, FALSE); + g_return_val_if_fail(channel_info != NULL, FALSE); + + if (gmyth_epg_channel_has_icon(gmyth_epg, channel_info)) { + GMythFileTransfer *transfer = + gmyth_file_transfer_new(gmyth_epg->backend_info); + + GMythFileReadResult gmyth_res; + GByteArray *icon_data; + guint64 icon_length = 0; + + res = gmyth_file_transfer_open(transfer, + channel_info->channel_icon->str); + if (!res) { + gmyth_debug("Channel icon could not be opened"); + return FALSE; + } + + icon_length = gmyth_file_transfer_get_filesize(transfer); + if (icon_length <= 0) { + gmyth_debug("Channel icon file size is zero or negative"); + return FALSE; + } + + icon_data = g_byte_array_new(); + gmyth_res = gmyth_file_transfer_read(transfer, + icon_data, + icon_length, FALSE); + if (gmyth_res == GMYTH_FILE_READ_EOF) { + *length = icon_length; + *data = icon_data->data; + g_byte_array_free(icon_data, FALSE); + res = TRUE; + } else { + *length = 0; + *data = NULL; + g_byte_array_free(icon_data, TRUE); + } + } + + return res; +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_epg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_epg.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,85 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_epg.h + * + * @brief

GMythEPG class provides access to the program and channel data + * from the Electronic Program Guide (EPG) of the Mythtv backend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Leonardo Sobral Cunha + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef GMYTH_EPG_H_ +#define GMYTH_EPG_H_ + +#include + +#include "gmyth_query.h" +#include "gmyth_common.h" + +G_BEGIN_DECLS +#define GMYTH_EPG_TYPE (gmyth_epg_get_type ()) +#define GMYTH_EPG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_EPG_TYPE, GMythEPG)) +#define GMYTH_EPG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_EPG_TYPE, GMythEPGClass)) +#define IS_GMYTH_EPG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_EPG_TYPE)) +#define IS_GMYTH_EPG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_EPG_TYPE)) +#define GMYTH_EPG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_EPG_TYPE, GMythEPGClass)) +typedef struct _GMythEPG GMythEPG; +typedef struct _GMythEPGClass GMythEPGClass; + +struct _GMythEPGClass { + GObjectClass parent_class; + + /* + * callbacks + */ + /* + * no one for now + */ +}; + +struct _GMythEPG { + GObject parent; + + GMythQuery *sqlquery; + GMythBackendInfo *backend_info; +}; + +GType gmyth_epg_get_type (void) G_GNUC_CONST;; +GMythEPG* gmyth_epg_new (void); +gboolean gmyth_epg_connect (GMythEPG *gmyth_epg, + GMythBackendInfo *backend_info); +gboolean gmyth_epg_disconnect (GMythEPG *gmyth_epg); +gint gmyth_epg_get_channel_list (GMythEPG *gmyth_epg, + GList **glist_ptr); +gint gmyth_epg_get_program_list (GMythEPG *gmyth_epg, + GList **proglist, + gint chanNum, + GTimeVal *starttime, + GTimeVal *endtime); +GMythChannelInfo*gmyth_epg_get_channel_info (GMythEPG *gmyth_epg, + gint channel_id); +gboolean gmyth_epg_channel_has_icon (GMythEPG *gmyth_epg, + GMythChannelInfo *channel); +gboolean gmyth_epg_channel_get_icon (GMythEPG *gmyth_epg, + GMythChannelInfo *channel, + guint8 **data, + guint *length); + +G_END_DECLS +#endif /* GMYTH_EPG_H_ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_file.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_file.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,515 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_file.c + * + * @brief

GMythFile deals with the file streaming media remote/local + * transfering to the MythTV frontend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_file.h" +#include "gmyth_recorder.h" +#include "gmyth_util.h" +#include "gmyth_socket.h" +#include "gmyth_stringlist.h" +#include "gmyth_debug.h" +#include "gmyth_uri.h" +#include "gmyth_marshal.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define GMYTH_FILE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_TYPE, GMythFilePrivate)) + +struct _GMythFilePrivate { + gboolean disposed; + gint64 offset; + guint64 filesize; + + GMythBackendInfo *backend_info; + + /* + * Myth URI structure + */ + gchar *filename; + + gint file_id; +}; + +enum { + PROP_GMYTH_FILE_DUMMY, + PROP_GMYTH_FILE_FILENAME, + PROP_GMYTH_FILE_OFFSET, + PROP_GMYTH_FILE_FILESIZE, + PROP_GMYTH_FILE_BACKEND_INFO, + PROP_GMYTH_FILE_FILEID +}; + +static void gmyth_file_set_property(GObject * object, guint prop_id, + const GValue * value, + GParamSpec * pspec); +static void gmyth_file_get_property(GObject * object, guint prop_id, + GValue * value, + GParamSpec * pspec); + +static void gmyth_file_class_init(GMythFileClass * klass); +static void gmyth_file_init(GMythFile * object); +static void gmyth_file_dispose(GObject * object); +static void gmyth_file_finalize(GObject * object); + +G_DEFINE_TYPE(GMythFile, gmyth_file, G_TYPE_OBJECT) + static void gmyth_file_class_init(GMythFileClass * klass) +{ + GObjectClass *gobject_class; + GMythFileClass *gtransfer_class; + + gobject_class = (GObjectClass *) klass; + gtransfer_class = (GMythFileClass *) gobject_class; + + gobject_class->dispose = gmyth_file_dispose; + gobject_class->finalize = gmyth_file_finalize; + + gobject_class->set_property = gmyth_file_set_property; + gobject_class->get_property = gmyth_file_get_property; + + g_object_class_install_property + (gobject_class, PROP_GMYTH_FILE_FILENAME, + g_param_spec_string("filename", "filename", + "The file name.", + "", + G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB | G_PARAM_READABLE | + G_PARAM_WRITABLE)); + + g_object_class_install_property + (gobject_class, PROP_GMYTH_FILE_OFFSET, + g_param_spec_int64("file-offset", "file-offset", + "The offset (position) of this file", 0, + G_MAXINT64, 0, + G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB | G_PARAM_READABLE | + G_PARAM_WRITABLE)); + + g_object_class_install_property + (gobject_class, PROP_GMYTH_FILE_FILESIZE, + g_param_spec_uint64("file-size", "file-size", + "The file size in bytes", + 0, G_MAXUINT64, 0, + G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB | G_PARAM_READABLE | + G_PARAM_WRITABLE)); + + g_object_class_install_property + (gobject_class, PROP_GMYTH_FILE_BACKEND_INFO, + g_param_spec_object("backend-info", "backend-info", + "The Backend Information about the remote server", + G_TYPE_OBJECT, + G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB | G_PARAM_READABLE | + G_PARAM_WRITABLE)); + + g_object_class_install_property + (gobject_class, PROP_GMYTH_FILE_FILEID, + g_param_spec_int("file-id", "file-id", + "The file ID", 0, G_MAXINT, 0, + G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB | G_PARAM_READABLE | + G_PARAM_WRITABLE)); + + g_type_class_add_private(gobject_class, sizeof(GMythFilePrivate)); + +} + +static void +gmyth_file_init(GMythFile * file) +{ + g_return_if_fail(file != NULL); + + file->priv = GMYTH_FILE_GET_PRIVATE(file); +} + +static void +gmyth_file_dispose(GObject * object) +{ + GMythFilePrivate *priv; + GMythFile *file = GMYTH_FILE(object); + + g_return_if_fail(file != NULL); + + priv = GMYTH_FILE_GET_PRIVATE(file); + + if (priv->disposed) { + /* + * If dispose did already run, return. + */ + return; + } + + /* + * Make sure dispose does not run twice. + */ + priv->disposed = TRUE; + + if (priv->backend_info != NULL) { + g_object_unref(priv->backend_info); + priv->backend_info = NULL; + } + + if (priv->filename != NULL) { + g_free(priv->filename); + priv->filename = NULL; + } + + G_OBJECT_CLASS(gmyth_file_parent_class)->dispose(object); +} + +static void +gmyth_file_finalize(GObject * object) +{ + g_signal_handlers_destroy(object); + + G_OBJECT_CLASS(gmyth_file_parent_class)->finalize(object); +} + +/** + * Creates a new instance of GMythFile. + * + * @param backend_info The BackendInfo instance, with all the MythTV network + * configuration data. + * + * @return a new instance of the File Transfer. + */ +GMythFile * +gmyth_file_new(GMythBackendInfo * backend_info) +{ + GMythFile *file = NULL; + + g_return_val_if_fail(backend_info != NULL, NULL); + + GParameter *__params = g_new0(GParameter, 1); + GParameter *__params_it = __params; + + (__params_it->name = + "backend-info", g_value_init(&__params_it->value, G_TYPE_OBJECT), + g_value_set_object(&__params_it->value, backend_info), __params_it++); + file = + g_object_newv(GMYTH_FILE_TYPE, __params_it - __params, __params); + + return file; +} + +gchar * +gmyth_file_get_file_name(GMythFile * file) +{ + GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(file); + + g_return_val_if_fail(file != NULL, NULL); + + return priv->filename; +} + +void +gmyth_file_set_file_name(GMythFile * file, const gchar * filename) +{ + g_return_if_fail(file != NULL); + g_return_if_fail(filename != NULL); + + gchar *__temp2 = NULL; + const gchar *__temp1 = NULL; + + file->priv->filename = (__temp2 = + (__temp1 = + filename, + (__temp1 == NULL ? NULL : g_strdup(__temp1))), + (file->priv->filename == + NULL ? NULL : (file->priv->filename = + (g_free(file->priv->filename), + NULL))), __temp2); +} + +/** + * Creates a new instance of GMythFile. + * + * @param uri_str The URI poiting to the MythTV backend server. + * + * @return a new instance of the File Transfer. + */ +GMythFile * +gmyth_file_new_with_uri(const gchar * uri_str) +{ + GMythFile *file = GMYTH_FILE(g_object_new(GMYTH_FILE_TYPE, NULL)); + GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(file); + + priv->backend_info = gmyth_backend_info_new_with_uri(uri_str); + return file; +} + +/** + * Open a File Transfer connection in order to get a remote file. + * + * @param file The actual File Transfer instance. + * @param filename The file name of the remote file to be transfered to the client. + * + * @return true, if the connection opening had been done successfully. + */ +gboolean +gmyth_file_setup(GMythFile * file, const gchar * filename) +{ + gboolean ret = TRUE; + GMythFilePrivate *priv; + + g_return_val_if_fail(file != NULL, FALSE); + g_return_val_if_fail(filename != NULL && strlen(filename) > 0, FALSE); + + priv = GMYTH_FILE_GET_PRIVATE(file); + + if (priv->filename != NULL) { + gmyth_file_close(file); + } + + priv->filename = g_strdup(filename); + + return ret; +} + +/** + * Closes a remote File Transfer connection. + * + * @param file The actual File Transfer instance. + */ +void +gmyth_file_close(GMythFile * file) +{ + GMythFilePrivate *priv; + + priv = GMYTH_FILE_GET_PRIVATE(file); + + if (priv->filename) { + g_free(priv->filename); + priv->filename = NULL; + } + +} + +/** + * Gets the actual file size of the binary content. + * + * @param file The actual File Transfer instance. + * + * @return The actual file size in bytes. + */ +guint64 +gmyth_file_get_filesize(GMythFile * file) +{ + GMythFilePrivate *priv; + + g_return_val_if_fail(file != NULL, 0); + + priv = GMYTH_FILE_GET_PRIVATE(file); + return priv->filesize; +} + +/** + * Sets the actual file size. + * + * @param file The actual File Transfer instance. + * @param filesize The actual File Transfer size, in bytes. + */ +void +gmyth_file_set_filesize(GMythFile * file, guint64 filesize) +{ + GMythFilePrivate *priv; + + priv = GMYTH_FILE_GET_PRIVATE(file); + + priv->filesize = filesize; +} + +/** + * Gets the actual offset of the binary content. + * + * @param file The actual File Transfer instance. + * + * @return The actual file offset in bytes. + */ +gint64 +gmyth_file_get_offset(GMythFile * file) +{ + g_return_val_if_fail(file != NULL, 0); + + return file->priv->offset; +} + +/** + * Sets the actual file offset. + * + * @param file The actual File instance. + * @param filesize The actual File offset, in bytes. + */ +void +gmyth_file_set_offset(GMythFile * file, gint64 offset) +{ + GMythFilePrivate *priv; + + priv = GMYTH_FILE_GET_PRIVATE(file); + + priv->offset = offset; +} + +gchar * +gmyth_file_get_uri(GMythFile * file) +{ + GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(file); + gchar *uri = NULL; + + g_return_val_if_fail(file != NULL, NULL); + + if (g_strstr_len(priv->filename, strlen(priv->filename), "://") != + NULL) + uri = g_strdup(priv->filename); + else + uri = + g_strdup_printf("myth://%s:%d/%s", + gmyth_backend_info_get_hostname(priv-> + backend_info), + gmyth_backend_info_get_port(priv-> + backend_info), + priv->filename); + + return uri; +} + +static void +gmyth_file_set_property(GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(GMYTH_FILE(object)); + + switch (prop_id) { + case PROP_GMYTH_FILE_FILENAME: + { + if (!g_value_get_string(value)) { + break; + } + + if (priv->filename != NULL) { + g_free(priv->filename); + priv->filename = NULL; + } + + priv->filename = g_value_dup_string(value); + gmyth_debug("Changed the filename to [%s]!", priv->filename); + break; + } + case PROP_GMYTH_FILE_OFFSET: + { + priv->offset = g_value_get_int64(value); + break; + } + case PROP_GMYTH_FILE_FILESIZE: + { + priv->filesize = g_value_get_uint64(value); + break; + } + case PROP_GMYTH_FILE_BACKEND_INFO: + { + if (!g_value_get_object(value)) { + break; + } + + if (priv->backend_info != NULL) { + g_object_unref(priv->backend_info); + priv->backend_info = NULL; + } + + priv->backend_info = g_value_get_object(value); + gmyth_debug("Changed the backend info to [%s]!", + gmyth_backend_info_get_hostname(priv-> + backend_info)); + break; + } + case PROP_GMYTH_FILE_FILEID: + { + priv->file_id = g_value_get_int(value); + break; + } + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } + +} + +static void +gmyth_file_get_property(GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(GMYTH_FILE(object)); + + switch (prop_id) { + case PROP_GMYTH_FILE_FILENAME: + { + gmyth_debug("Got the filename to [%s]!", priv->filename); + g_value_set_string(value, priv->filename); + break; + } + case PROP_GMYTH_FILE_OFFSET: + { + g_value_set_int64(value, priv->offset); + break; + } + case PROP_GMYTH_FILE_FILESIZE: + { + g_value_set_uint64(value, priv->filesize); + break; + } + case PROP_GMYTH_FILE_BACKEND_INFO: + { + g_value_set_object(value, priv->backend_info); + break; + } + case PROP_GMYTH_FILE_FILEID: + { + g_value_set_int(value, priv->file_id); + break; + } + default: + { + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } + } + +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_file.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_file.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,90 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_file.h + * + * @brief

GMythFile is the parent GMObject that deals with the file streaming + * media remote/local transfering to the MythTV frontend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_FILE_H__ +#define __GMYTH_FILE_H__ + +#include +#include + +#include "gmyth_uri.h" +#include "gmyth_backendinfo.h" + +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS +#define GMYTH_FILE_TYPE (gmyth_file_get_type ()) +#define GMYTH_FILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_FILE_TYPE, GMythFile)) +#define GMYTH_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TYPE, GMythFileClass)) +#define IS_GMYTH_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_FILE_TYPE)) +#define IS_GMYTH_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TYPE)) +#define GMYTH_FILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_FILE_TYPE, GMythFileClass)) + +typedef enum { + GMYTH_FILE_READ_OK = 0, + GMYTH_FILE_READ_NEXT_PROG_CHAIN = 1, + GMYTH_FILE_READ_ERROR = 2, + GMYTH_FILE_READ_EOF = 3 +} GMythFileReadResult; + +typedef struct _GMythFile GMythFile; +typedef struct _GMythFileClass GMythFileClass; +typedef struct _GMythFilePrivate GMythFilePrivate; + +struct _GMythFile { + GObject parent; + GMythFilePrivate *priv; +}; + +struct _GMythFileClass { + GObjectClass parent_class; +}; + +GType gmyth_file_get_type (void); +GMythFile *gmyth_file_new (GMythBackendInfo *backend_info); +gchar *gmyth_file_get_file_name (GMythFile *file); +void gmyth_file_set_file_name (GMythFile *file, + const gchar *filename); +gboolean gmyth_file_setup (GMythFile *file, + const gchar *filename); +void gmyth_file_close (GMythFile *file); +gboolean gmyth_file_is_open (GMythFile *file); +guint64 gmyth_file_get_filesize (GMythFile *file); +void gmyth_file_set_filesize (GMythFile *file, + guint64 filesize); +gint64 gmyth_file_get_offset (GMythFile *file); +void gmyth_file_set_offset (GMythFile *file, + gint64 offset); +gchar *gmyth_file_get_uri (GMythFile *file); + +G_END_DECLS +#endif /* __GMYTH_FILE_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_file_local.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_file_local.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,464 @@ +/** + * GMyth Library + * + * @file_local gmyth/gmyth_file_local.c + * + * @brief

GMythFileLocal deals with the file_local streaming media remote/local + * transfering to the MythTV frontend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_file_local.h" +#include "gmyth_recorder.h" +#include "gmyth_util.h" +#include "gmyth_socket.h" +#include "gmyth_stringlist.h" +#include "gmyth_debug.h" +#include "gmyth_uri.h" +#include "gmyth_marshal.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define GMYTH_FILE_LOCAL_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_LOCAL_TYPE, GMythFileLocalPrivate)) + +struct _GMythFileLocalPrivate { + + gboolean disposed; + + GMutex *mutex; + + gint fd; + + GIOChannel *file_io; + +}; + +static void gmyth_file_local_class_init(GMythFileLocalClass * klass); +static void gmyth_file_local_init(GMythFileLocal * object); +static void gmyth_file_local_dispose(GObject * object); +static void gmyth_file_local_finalize(GObject * object); + +static gboolean _control_acquire_context(GMythFileLocal * file_local, + gboolean do_wait); + +static gboolean _control_release_context(GMythFileLocal * file_local); + +G_DEFINE_TYPE(GMythFileLocal, gmyth_file_local, GMYTH_FILE_TYPE) + static void gmyth_file_local_class_init(GMythFileLocalClass * + klass) +{ + GObjectClass *gobject_class; + GMythFileLocalClass *gtransfer_class; + + gobject_class = (GObjectClass *) klass; + gtransfer_class = (GMythFileLocalClass *) gobject_class; + + gobject_class->dispose = gmyth_file_local_dispose; + gobject_class->finalize = gmyth_file_local_finalize; + + g_type_class_add_private(gobject_class, sizeof(GMythFileLocalPrivate)); + +} + +static void +gmyth_file_local_init(GMythFileLocal * file_local) +{ + GMythFileLocalPrivate *priv; + + g_return_if_fail(file_local != NULL); + + priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local); + + priv->mutex = g_mutex_new(); +} + +static void +gmyth_file_local_dispose(GObject * object) +{ + GMythFileLocalPrivate *priv; + GMythFileLocal *file_local = GMYTH_FILE_LOCAL(object); + + g_return_if_fail(file_local != NULL); + + priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local); + + if (priv->disposed) { + /* + * If dispose did already run, return. + */ + return; + } + + /* + * Make sure dispose does not run twice. + */ + priv->disposed = TRUE; + + if (priv->mutex != NULL) { + g_mutex_free(priv->mutex); + priv->mutex = NULL; + } + + if (priv->file_io != NULL) { + g_io_channel_unref(priv->file_io); + priv->file_io = NULL; + } + + G_OBJECT_CLASS(gmyth_file_local_parent_class)->dispose(object); +} + +static void +gmyth_file_local_finalize(GObject * object) +{ + g_signal_handlers_destroy(object); + + G_OBJECT_CLASS(gmyth_file_local_parent_class)->finalize(object); +} + +/** + * Creates a new instance of GMythFileLocal. + * + * @param backend_info The BackendInfo instance, with all the MythTV network + * configuration data. + * + * @return a new instance of the File Transfer. + */ +GMythFileLocal * +gmyth_file_local_new(GMythBackendInfo * backend_info) +{ + GMythFileLocal *file_local = + GMYTH_FILE_LOCAL(g_object_new(GMYTH_FILE_LOCAL_TYPE, NULL)); + + g_object_set(GMYTH_FILE(file_local), "backend-info", &backend_info, + NULL); + + return file_local; +} + +/** + * Creates a new instance of GMythFileLocal. + * + * @param uri_str The URI poiting to the MythTV backend server. + * + * @return a new instance of the File Transfer. + */ +GMythFileLocal * +gmyth_file_local_new_with_uri(const gchar * uri_str) +{ + GMythFileLocal *file_local = + GMYTH_FILE_LOCAL(g_object_new(GMYTH_FILE_LOCAL_TYPE, NULL)); + GMythURI *uri = gmyth_uri_new_with_value(uri_str); + + gmyth_debug("GMythURI path segment = %s", gmyth_uri_get_path(uri)); + + g_object_set(GMYTH_FILE(file_local), + "backend-info", gmyth_backend_info_new_with_uri(uri_str), + "filename", g_strdup(gmyth_uri_get_path(uri)), NULL); + + g_object_unref(uri); + + return file_local; +} + +gchar * +gmyth_file_local_get_file_name(GMythFileLocal * file_local) +{ + return gmyth_file_get_file_name(GMYTH_FILE(file_local)); +} + +void +gmyth_file_local_set_file_name(GMythFileLocal * file_local, + const gchar * filename) +{ + gmyth_file_set_file_name(GMYTH_FILE(file_local), filename); +} + +/** + * Open a File in order to get a local file. + * + * @param file_local The actual File Transfer instance. + * + * @return true, if the connection opening had been done successfully. + */ +gboolean +gmyth_file_local_open(GMythFileLocal * file_local) +{ + gboolean ret = TRUE; + GMythFileLocalPrivate *priv; + gchar *file_name_uri = NULL; + + g_return_val_if_fail(file_local != NULL, FALSE); + + priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local); + file_name_uri = gmyth_file_local_get_file_name(file_local); + + if (file_name_uri != NULL) { + priv->file_io = + g_io_channel_new_file(g_strdup(file_name_uri), "r+", NULL); + g_free(file_name_uri); + } + + if (priv->file_io < 0) + ret = FALSE; + + return ret; +} + +/** + * Closes a remote File Transfer connection. + * + * @param file_local The actual File Transfer instance. + */ +void +gmyth_file_local_close(GMythFileLocal * file_local) +{ + g_return_if_fail(file_local != NULL); +} + +/** + * Acquire access to a local file read/write pointer. + * + * @param transfer The actual File Local instance. + * @param do_wait Waits or not on a GCond, when trying to read from the remote socket. + * + * @return true, if the acquire had been got. + */ +static gboolean +_control_acquire_context(GMythFileLocal * file_local, gboolean do_wait) +{ + gboolean ret = TRUE; + GMythFileLocalPrivate *priv; + + g_return_val_if_fail(file_local != NULL, FALSE); + priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local); + + g_mutex_lock(priv->mutex); + return ret; +} + +/** + * Release access to a local file read/write pointer. + * + * @param transfer The actual File Transfer instance. + * + * @return true, if the local file read/write permissions had been releaseds. + */ +static gboolean +_control_release_context(GMythFileLocal * file_local) +{ + gboolean ret = TRUE; + GMythFileLocalPrivate *priv; + + g_return_val_if_fail(file_local != NULL, FALSE); + priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local); + + g_mutex_unlock(priv->mutex); + + return ret; +} + +/** + * Reads a block from a remote file. + * + * @param transfer The actual File Transfer instance. + * @param data A GByteArray instance, where all the binary data representing + * the remote file will be stored. + * @param size The block size, in bytes, to be requested from a remote file. + * @param read_unlimited Tells the backend to read indefinitely (LiveTV), or only + * gets the actual size + * + * @return The actual block size (in bytes) returned by REQUEST_BLOCK message, + * or the error code. + */ +GMythFileReadResult +gmyth_file_local_read(GMythFileLocal * file_local, GByteArray * data, + gint size, gboolean read_unlimited) +{ + gsize bytes_read = 0; + gint64 total_read = 0; + GMythFileReadResult retval = GMYTH_FILE_READ_OK; + GMythFileLocalPrivate *priv; + + GError *error = NULL; + + GIOCondition io_cond; + GIOStatus io_status = G_IO_STATUS_NORMAL; + + g_return_val_if_fail(file_local != NULL, FALSE); + g_return_val_if_fail(data != NULL, GMYTH_FILE_READ_ERROR); + + priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local); + + io_status = g_io_channel_set_encoding(priv->file_io, NULL, &error); + if (io_status == G_IO_STATUS_NORMAL) + gmyth_debug("Setting encoding to binary file data stream.\n"); + + io_cond = g_io_channel_get_buffer_condition(priv->file_io); + + _control_acquire_context(file_local, TRUE); + + if (size > 0) { + gchar *data_buffer = g_new0(gchar, size); + + io_status = g_io_channel_read_chars(priv->file_io, + data_buffer, (gsize) size, + &bytes_read, &error); + + if (io_status != G_IO_STATUS_NORMAL) { + gmyth_debug("Error on io_channel"); + g_free(data_buffer); + retval = GMYTH_FILE_READ_ERROR; + goto error; + } + + /* + * append new data to the increasing byte array + */ + data = + g_byte_array_append(data, (const guint8 *) data_buffer, + bytes_read); + total_read += bytes_read; + + if (!read_unlimited + && (gmyth_file_local_get_filesize(file_local) > 0) + && (gmyth_file_local_get_offset(file_local) == + gmyth_file_local_get_filesize(file_local))) { + retval = GMYTH_FILE_READ_EOF; + goto error; + } + + g_free(data_buffer); + } else { + retval = GMYTH_FILE_READ_ERROR; + } + + error: + _control_release_context(file_local); + + if (error != NULL) { + gmyth_debug("Cleaning-up ERROR: [msg = %s, code = %d]\n", + error->message, error->code); + g_error_free(error); + } + + if (total_read > 0) + gmyth_file_local_set_offset(file_local, + (gmyth_file_local_get_offset + (file_local) + total_read)); + + return retval; +} + +gint64 +gmyth_file_local_seek(GMythFileLocal * file_local, gint64 pos, + GSeekType whence) +{ + GMythFileLocalPrivate *priv; + + GError *error; + + GIOStatus io_status = G_IO_STATUS_NORMAL; + + g_return_val_if_fail(file_local != NULL, -1); + + priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local); + + io_status = + g_io_channel_seek_position(priv->file_io, pos, whence, &error); + + if (io_status == G_IO_STATUS_ERROR) + pos = -1; + + return pos; + +} + +/** + * Gets the actual file_local size of the binary content. + * + * @param file_local The actual File Transfer instance. + * + * @return The actual file_local size in bytes. + */ +guint64 +gmyth_file_local_get_filesize(GMythFileLocal * file_local) +{ + g_return_val_if_fail(file_local != NULL, 0); + + return gmyth_file_get_filesize(GMYTH_FILE(file_local)); +} + +/** + * Sets the actual file_local size. + * + * @param file_local The actual File Transfer instance. + * @param filesize The actual File Transfer size, in bytes. + */ +void +gmyth_file_local_set_filesize(GMythFileLocal * file_local, + guint64 filesize) +{ + g_return_if_fail(file_local != NULL); + + gmyth_file_set_filesize(GMYTH_FILE(file_local), filesize); +} + +/** + * Gets the actual file offset of the binary content. + * + * @param file_local The actual File Transfer instance. + * + * @return The actual file offset in bytes. + */ +gint64 +gmyth_file_local_get_offset(GMythFileLocal * file_local) +{ + g_return_val_if_fail(file_local != NULL, 0); + + return gmyth_file_get_offset(GMYTH_FILE(file_local)); +} + +/** + * Sets the actual file offset. + * + * @param file_local The actual File Local instance. + * @param offset The actual File Local offset, in bytes. + */ +void +gmyth_file_local_set_offset(GMythFileLocal * file_local, gint64 offset) +{ + g_return_if_fail(file_local != NULL); + + gmyth_file_set_offset(GMYTH_FILE(file_local), offset); +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_file_local.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_file_local.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,93 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_file_local_local.h + * + * @brief

GMythFileLocal is the parent GMythFile that deals with the file streaming + * media local transfering from the MythTV backend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_FILE_LOCAL_H__ +#define __GMYTH_FILE_LOCAL_H__ + +#include +#include + +#include "gmyth_file.h" +#include "gmyth_uri.h" +#include "gmyth_backendinfo.h" + +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS +#define GMYTH_FILE_LOCAL_TYPE (gmyth_file_local_get_type ()) +#define GMYTH_FILE_LOCAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_FILE_LOCAL_TYPE, GMythFileLocal)) +#define GMYTH_FILE_LOCAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_LOCAL_TYPE, GMythFileLocalClass)) +#define IS_GMYTH_FILE_LOCAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_FILE_LOCAL_TYPE)) +#define IS_GMYTH_FILE_LOCAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_LOCAL_TYPE)) +#define GMYTH_FILE_LOCAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_FILE_LOCAL_TYPE, GMythFileLocalClass)) +typedef struct _GMythFileLocal GMythFileLocal; +typedef struct _GMythFileLocalClass GMythFileLocalClass; +typedef struct _GMythFileLocalPrivate GMythFileLocalPrivate; + +struct _GMythFileLocal { + GMythFile parent; +}; + +struct _GMythFileLocalClass { + GMythFileClass parent_class; +}; + + +GType gmyth_file_local_get_type(void); +GMythFileLocal *gmyth_file_local_new(GMythBackendInfo * backend_info); +GMythFileLocal *gmyth_file_local_new_with_uri(const gchar * uri); +gchar *gmyth_file_local_get_file_name(GMythFileLocal * + file_local); +void gmyth_file_local_set_file_name(GMythFileLocal * file_local, + const gchar * filename); +gboolean gmyth_file_local_open(GMythFileLocal * file_local); +void gmyth_file_local_close(GMythFileLocal * file_local); +gboolean gmyth_file_local_is_open(GMythFileLocal * file_local); + +GMythFileReadResult +gmyth_file_local_read(GMythFileLocal * file_local, + GByteArray * data, gint size, + gboolean read_unlimited); + +gint64 gmyth_file_local_seek(GMythFileLocal * file_local, + gint64 pos, GSeekType whence); + +guint64 gmyth_file_local_get_filesize(GMythFileLocal * file_local); +void gmyth_file_local_set_filesize(GMythFileLocal * file, + guint64 filesize); + +gint64 gmyth_file_local_get_offset(GMythFileLocal * file_local); +void gmyth_file_local_set_offset(GMythFileLocal * file_local, + gint64 offset); + +G_END_DECLS +#endif /* __GMYTH_FILE_LOCAL_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_file_transfer.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_file_transfer.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,1014 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_file_transfer.c + * + * @brief

GMythFileTransfer deals with the file streaming media remote/local + * transfering to the MythTV frontend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * GStreamer MythTV plug-in properties: + * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv] + * - path (qurl - remote file to be opened) + * - port number * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_file_transfer.h" +#include "gmyth_recorder.h" +#include "gmyth_util.h" +#include "gmyth_socket.h" +#include "gmyth_stringlist.h" +#include "gmyth_debug.h" +#include "gmyth_uri.h" +#include "gmyth_marshal.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER " + + +#define GMYTH_FILE_TRANSFER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferPrivate)) + +enum myth_sock_types { + GMYTH_PLAYBACK_TYPE = 0, + GMYTH_MONITOR_TYPE, + GMYTH_FILETRANSFER_TYPE, + GMYTH_RINGBUFFER_TYPE +}; + +struct _GMythFileTransferPrivate { + GMythRecorder *recorder; + + gboolean do_next_program_chain; + gboolean disposed; + gboolean livetv_wait; + + /* + * MythTV version number + */ + gint mythtv_version; + + /* + * socket descriptors + */ + GMythSocket *control_sock; + GMythSocket *sock; + GMutex *mutex; + gint file_id; +}; + +static void gmyth_file_transfer_class_init(GMythFileTransferClass * + klass); +static void gmyth_file_transfer_init(GMythFileTransfer * object); +static void gmyth_file_transfer_dispose(GObject * object); +static void gmyth_file_transfer_finalize(GObject * object); +static void _file_transfer_program_info_changed(GMythFileTransfer * + transfer, + gint msg_code, + gpointer + livetv_recorder); +static gboolean _connect_to_backend(GMythFileTransfer * transfer); +static gboolean _control_acquire_context(GMythFileTransfer * transfer, + gboolean do_wait); +static gboolean _control_release_context(GMythFileTransfer * transfer); + +G_DEFINE_TYPE(GMythFileTransfer, gmyth_file_transfer, GMYTH_FILE_TYPE) + static void gmyth_file_transfer_class_init(GMythFileTransferClass * + klass) +{ + GObjectClass *gobject_class; + GMythFileTransferClass *gtransfer_class; + + gobject_class = (GObjectClass *) klass; + gtransfer_class = (GMythFileTransferClass *) gobject_class; + + gobject_class->dispose = gmyth_file_transfer_dispose; + gobject_class->finalize = gmyth_file_transfer_finalize; + + g_type_class_add_private(gobject_class, + sizeof(GMythFileTransferPrivate)); + + gtransfer_class->program_info_changed_handler = + _file_transfer_program_info_changed; + + gtransfer_class->program_info_changed_handler_signal_id = + g_signal_new("program-info-changed", + G_TYPE_FROM_CLASS(gtransfer_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | + G_SIGNAL_NO_HOOKS, 0, NULL, NULL, + gmyth_marshal_VOID__INT_POINTER, G_TYPE_NONE, 2, + G_TYPE_INT, G_TYPE_POINTER); + +} + +static void +gmyth_file_transfer_init(GMythFileTransfer * transfer) +{ + g_return_if_fail(transfer != NULL); + + transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + transfer->priv->mutex = g_mutex_new(); + + g_signal_connect(G_OBJECT(transfer), "program-info-changed", + (GCallback) (GMYTH_FILE_TRANSFER_GET_CLASS + (transfer)->program_info_changed_handler), + NULL); +} + +static void +gmyth_file_transfer_dispose(GObject * object) +{ + GMythFileTransferPrivate *priv; + GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER(object); + + g_return_if_fail(transfer != NULL); + + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + + if (priv->disposed) { + /* + * If dispose did already run, return. + */ + return; + } + + /* + * Make sure dispose does not run twice. + */ + priv->disposed = TRUE; + + if (priv->mutex != NULL) { + g_mutex_free(priv->mutex); + priv->mutex = NULL; + } + + if (priv->control_sock != NULL) { + g_object_unref(priv->control_sock); + priv->control_sock = NULL; + } + + if (priv->sock != NULL) { + g_object_unref(priv->sock); + priv->sock = NULL; + } + + if (priv->recorder != NULL) { + g_object_unref(priv->recorder); + priv->recorder = NULL; + } + + G_OBJECT_CLASS(gmyth_file_transfer_parent_class)->dispose(object); +} + +static void +gmyth_file_transfer_finalize(GObject * object) +{ + g_signal_handlers_destroy(object); + + G_OBJECT_CLASS(gmyth_file_transfer_parent_class)->finalize(object); +} + +/** + * Creates a new instance of GMythFileTransfer. + * + * @param backend_info The BackendInfo instance, with all the MythTV network + * configuration data. + * + * @return a new instance of the File Transfer. + */ +GMythFileTransfer * +gmyth_file_transfer_new(GMythBackendInfo * backend_info) +{ + GMythFileTransfer *transfer = g_object_new(GMYTH_FILE_TRANSFER_TYPE, + "backend-info", + backend_info, + NULL); + + // GValue val = {0,}; + // backend_info = g_object_ref( backend_info ); + gmyth_debug("Creating FileTransfer BackendInfo hostname = %s", + gmyth_backend_info_get_hostname(backend_info)); + // GMythBackendInfo *backend_info = gmyth_backend_info_new_with_uri + // (uri_str); + // g_value_init (&val, G_TYPE_OBJECT); + // g_value_set_object (&val, backend_info); + // g_object_set (G_OBJECT (transfer), "backend-info", &val, NULL); + + return transfer; +} + +gchar * +gmyth_file_transfer_get_file_name(GMythFileTransfer * transfer) +{ + gchar *filename; + + g_object_get(G_OBJECT(transfer), "filename", &filename, NULL); + + return filename; +} + +/** + * Creates a new instance of GMythFileTransfer. + * + * @param uri_str The URI poiting to the MythTV backend server. + * + * @return a new instance of the File Transfer. + */ +GMythFileTransfer * +gmyth_file_transfer_new_with_uri(const gchar * uri_str) +{ + GMythFileTransfer *transfer = + GMYTH_FILE_TRANSFER(g_object_new(GMYTH_FILE_TRANSFER_TYPE, NULL)); + gmyth_debug("URI str = %s", uri_str); + // GMythBackendInfo *backend_info = gmyth_backend_info_new_with_uri + // (uri_str); + GValue val = { 0, }; + g_value_init(&val, G_TYPE_OBJECT); + g_value_set_object(&val, gmyth_backend_info_new_with_uri(uri_str)); + g_object_set(G_OBJECT(transfer), "backend-info", &val, NULL); + + return transfer; +} + +/** + * Open a File Transfer connection in order to get a remote file. + * + * @param transfer The actual File Transfer instance. + * @param filename The file name of the remote file to be transferred to the client. + * + * @return true, if the connection opening had been done successfully. + */ +gboolean +gmyth_file_transfer_open(GMythFileTransfer * transfer, + const gchar * filename) +{ + gboolean ret = TRUE; + GMythFileTransferPrivate *priv; + + g_return_val_if_fail(transfer != NULL, FALSE); + g_return_val_if_fail(filename != NULL && strlen(filename) > 0, FALSE); + + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + + gmyth_debug("Opening the FileTransfer... (%s)", filename); + + g_object_set(GMYTH_FILE(transfer), "filename", filename, NULL); + + /* + * configure the control socket + */ + if (TRUE /* priv->control_sock == NULL */ ) { + if (!_connect_to_backend(transfer)) { + gmyth_debug("Connection to backend failed (Control Socket)."); + ret = FALSE; + } + + if (priv->do_next_program_chain) { + priv->do_next_program_chain = FALSE; // fixme + gmyth_debug + ("New file available before the current file was opened"); + GMythProgramInfo *prog_info = + gmyth_recorder_get_current_program_info(priv->recorder); + + if (prog_info != NULL && prog_info->pathname != NULL + && strlen(prog_info->pathname->str) > 0 + && g_ascii_strcasecmp(prog_info->pathname->str, + gmyth_file_get_file_name(GMYTH_FILE + (transfer))) + != 0) + ret = + gmyth_file_transfer_open(transfer, + g_strrstr(prog_info-> + pathname->str, + "/")); + + if (prog_info != NULL) + g_object_unref(prog_info); + + if (!ret) + gmyth_debug("Cannot change to the next program info!"); + else + gmyth_debug("OK!!! MOVED to the next program info [%s]!", + gmyth_file_get_file_name(GMYTH_FILE + (transfer))); + + } else { + gmyth_debug + ("None new file found. We continue with the same file opened before"); + } + + } else { + gmyth_debug("Remote transfer control socket already created."); + } + + gmyth_debug("Got file with size = %lld.\n", + gmyth_file_get_filesize(GMYTH_FILE(transfer))); + + return ret; +} + +/** + * Connect a File Transfer binary client socket to a remote file. + * + * @param transfer The actual File Transfer instance. + * + * @return true, if the connection had been configured successfully. + */ +static gboolean +_connect_to_backend(GMythFileTransfer * transfer) +{ + GString *base_str = NULL; + GString *hostname = NULL; + GMythStringList *strlist = NULL; + gboolean ret = TRUE; + GMythFileTransferPrivate *priv; + GMythBackendInfo *backend_info; + + g_return_val_if_fail(transfer != NULL, FALSE); + + g_object_get(GMYTH_FILE(transfer), "backend-info", &backend_info, + NULL); + + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + _control_acquire_context(transfer, TRUE); + + /* + * Creates the control socket + */ + + if (priv->control_sock != NULL) { + g_object_unref(priv->control_sock); + priv->control_sock = NULL; + } + + base_str = g_string_new(""); + + priv->control_sock = gmyth_socket_new(); + // Connects the socket, send Mythtv ANN command and verify Mythtv + // protocol version + if (!gmyth_socket_connect_to_backend(priv->control_sock, + backend_info->hostname, + backend_info->port, TRUE)) { + + _control_release_context(transfer); + g_object_unref(priv->control_sock); + priv->control_sock = NULL; + return FALSE; + } + + /* + * Creates the data socket + */ + if (priv->sock != NULL) { + g_object_unref(priv->sock); + priv->sock = NULL; + } + + priv->sock = gmyth_socket_new(); + gmyth_socket_connect(priv->sock, backend_info->hostname, + backend_info->port); + gmyth_debug("Connecting file transfer... (%s, %d)", + backend_info->hostname, backend_info->port); + + strlist = gmyth_string_list_new(); + hostname = gmyth_socket_get_local_hostname(); + gmyth_debug("[%s] MythTV version (from backend) = %d.\n", __FUNCTION__, + priv->control_sock->mythtv_version); + if (priv->control_sock->mythtv_version > 26) + g_string_printf(base_str, "ANN FileTransfer %s 1 -1", + hostname->str); + else + g_string_printf(base_str, "ANN FileTransfer %s", hostname->str); + + gmyth_string_list_append_string(strlist, base_str); + gmyth_string_list_append_char_array(strlist, + gmyth_file_get_file_name(GMYTH_FILE + (transfer))); + + gmyth_socket_write_stringlist(priv->sock, strlist); + + /* + * MONITOR Handler - DVB TV Chain update messages!!! + */ + + gmyth_socket_read_stringlist(priv->sock, strlist); + + /* + * file identification used in future file transfer requests to + * backend + */ + priv->file_id = gmyth_string_list_get_int(strlist, 1); + + /* + * Myth URI stream file size - decoded using two 8-bytes sequences (64 + * bits/long long types) + */ + gmyth_file_set_filesize(GMYTH_FILE(transfer), + gmyth_string_list_get_int64(strlist, 2)); + + gmyth_debug("***** Received: recordernum = %d, filesize = %" + G_GUINT64_FORMAT "\n", priv->file_id, + gmyth_file_get_filesize(GMYTH_FILE(transfer))); + + if (gmyth_file_get_filesize(GMYTH_FILE(transfer)) < 0) { + gmyth_debug + ("Got filesize equals to %llu is lesser than 0 [invalid stream file]\n", + gmyth_file_get_filesize(GMYTH_FILE(transfer))); + g_object_unref(priv->sock); + priv->sock = NULL; + ret = FALSE; + } + + _control_release_context(transfer); + + if (strlist != NULL) + g_object_unref(strlist); + + if (base_str != NULL) + g_string_free(base_str, TRUE); + + if (hostname != NULL) + g_string_free(hostname, TRUE); + + return ret; +} + +/** + * Receives a GObject signal coming from a LiveTV instance, all the time a + * program info changes. + * + * @param transfer The actual File Transfer instance. + * @param msg_code The MythTV backend message status code. + * @param live_tv A pointer to the LiveTV instance. * + */ +void +gmyth_file_transfer_emit_program_info_changed_signal(GMythFileTransfer * + transfer, + gint msg_code, + gpointer + live_tv_recorder) +{ + gmyth_debug("Calling signal handler... [FILE_TRANSFER]"); + + g_signal_emit(transfer, GMYTH_FILE_TRANSFER_GET_CLASS(transfer)->program_info_changed_handler_signal_id, 0, /* details + */ + msg_code, live_tv_recorder); + +} + +/** + * Checks if the actual File Transfer connection is open. + * + * @param transfer The actual File Transfer instance. + * + * @return true, if the File Transfer connection is opened. + */ +gboolean +gmyth_file_transfer_is_open(GMythFileTransfer * transfer) +{ + GMythStringList *strlist; + GMythFileTransferPrivate *priv; + GString *query; + + g_return_val_if_fail(transfer != NULL, FALSE); + + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + g_return_val_if_fail(priv->control_sock != NULL, FALSE); + g_return_val_if_fail(priv->sock != NULL, FALSE); + + _control_acquire_context(transfer, TRUE); + + strlist = gmyth_string_list_new(); + query = g_string_new(GMYTHTV_QUERY_HEADER); + g_string_append_printf(query, "%d", priv->file_id); + + gmyth_string_list_append_string(strlist, query); + gmyth_string_list_append_char_array(strlist, "IS_OPEN"); + + gmyth_socket_write_stringlist(priv->control_sock, strlist); + gmyth_socket_read_stringlist(priv->control_sock, strlist); + + _control_release_context(transfer); + + g_string_free(query, TRUE); + g_object_unref(strlist); + + return (strlist != NULL && gmyth_string_list_get_int(strlist, 0) == 1); +} + +/** + * Closes a remote File Transfer connection. + * + * @param transfer The actual File Transfer instance. + */ +void +gmyth_file_transfer_close(GMythFileTransfer * transfer) +{ + GMythStringList *strlist; + GMythFileTransferPrivate *priv; + GString *query; + + g_return_if_fail(transfer != NULL); + + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + + if (priv->control_sock == NULL) + return; + + _control_acquire_context(transfer, TRUE); + + strlist = gmyth_string_list_new(); + query = g_string_new(GMYTHTV_QUERY_HEADER); + g_string_append_printf(query, "%d", priv->file_id); + + gmyth_string_list_append_string(strlist, query); + gmyth_string_list_append_char_array(strlist, "DONE"); + + if (gmyth_socket_sendreceive_stringlist(priv->control_sock, strlist) <= + 0) { + // fixme: time out??? + gmyth_debug("Remote file timeout.\n"); + } + + g_string_free(query, TRUE); + g_object_unref(strlist); + + if (priv->sock) { + g_object_unref(priv->sock); + priv->sock = NULL; + } + + if (priv->control_sock) { + g_object_unref(priv->control_sock); + priv->control_sock = NULL; + } + + _control_release_context(transfer); +} + +/** + * Do a seek operation (moves the read/write file pointer) on a remote file. + * + * @param transfer The actual File Transfer instance. + * @param pos The position to be moved in the remote file. + * @param whence Tells to what direction seek movement should be done. + * + * @return The actual position on the remote file (after seek has been done). + */ +gint64 +gmyth_file_transfer_seek(GMythFileTransfer * transfer, guint64 pos, + gint whence) +{ + GMythStringList *strlist = gmyth_string_list_new(); + GMythFileTransferPrivate *priv; + GString *query; + + g_return_val_if_fail(transfer != NULL, FALSE); + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + + g_return_val_if_fail(priv->sock != NULL, -1); + g_return_val_if_fail(priv->control_sock != NULL, -1); + + strlist = gmyth_string_list_new(); + query = g_string_new(GMYTHTV_QUERY_HEADER); + g_string_append_printf(query, "%d", priv->file_id); + + /* + * myth_control_acquire_context( transfer, TRUE ); + */ + + gmyth_string_list_append_string(strlist, query); + gmyth_string_list_append_char_array(strlist, "SEEK"); + gmyth_string_list_append_uint64(strlist, pos); + + gmyth_string_list_append_int(strlist, whence); + + if (pos > 0) + gmyth_string_list_append_uint64(strlist, pos); + else + gmyth_string_list_append_uint64(strlist, + gmyth_file_get_offset(GMYTH_FILE + (transfer))); + + gmyth_socket_sendreceive_stringlist(priv->control_sock, strlist); + + gint64 retval = gmyth_string_list_get_int64(strlist, 0); + + gmyth_file_set_offset(GMYTH_FILE(transfer), retval); + gmyth_debug("Got reading position pointer from the streaming = %lld\n", + retval); + + g_object_unref(strlist); + g_string_free(query, TRUE); + + /* + * myth_control_release_context( transfer ); + */ + + return retval; +} + +/** + * Acquire access to a remote file socket read/write pointer. + * + * @param transfer The actual File Transfer instance. + * @param do_wait Waits or not on a GCond, when trying to read from the remote socket. + * + * @return true, if the acquire had been got. + */ +static gboolean +_control_acquire_context(GMythFileTransfer * transfer, gboolean do_wait) +{ + gboolean ret = TRUE; + GMythFileTransferPrivate *priv; + + g_return_val_if_fail(transfer != NULL, FALSE); + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + + g_mutex_lock(priv->mutex); + return ret; +} + +/** + * Release access to a remote file socket read/write pointer. + * + * @param transfer The actual File Transfer instance. + * + * @return true, if the socket read/write permissions had been releaseds. + */ +static gboolean +_control_release_context(GMythFileTransfer * transfer) +{ + gboolean ret = TRUE; + GMythFileTransferPrivate *priv; + + g_return_val_if_fail(transfer != NULL, FALSE); + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + + g_mutex_unlock(priv->mutex); + + return ret; +} + +/** + * Reads a block from a remote file. + * + * @param transfer The actual File Transfer instance. + * @param data A GByteArray instance, where all the binary data representing + * the remote file will be stored. + * @param size The block size, in bytes, to be requested from a remote file. + * @param read_unlimited Tells the backend to read indefinitely (LiveTV), or only + * gets the actual size + * + * @return The actual block size (in bytes) returned by REQUEST_BLOCK message, + * or the error code. + */ +GMythFileReadResult +gmyth_file_transfer_read(GMythFileTransfer * transfer, GByteArray * data, + gint size, gboolean read_unlimited) +{ + gint bytes_sent = 0; + gsize bytes_read = 0; + gint64 total_read = 0; + GMythFileReadResult retval = GMYTH_FILE_READ_OK; + GMythFileTransferPrivate *priv; + + GError *error = NULL; + + GIOChannel *io_channel; + GIOChannel *io_channel_control; + + GIOCondition io_cond; + GIOCondition io_cond_control; + GIOStatus io_status = G_IO_STATUS_NORMAL; + GIOStatus io_status_control = G_IO_STATUS_NORMAL; + + GMythStringList *strlist; + GMythStringList *ret_strlist = NULL; + gboolean ret = TRUE; + GString *query; + + g_return_val_if_fail(transfer != NULL, FALSE); + g_return_val_if_fail(data != NULL, GMYTH_FILE_READ_ERROR); + + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + + strlist = gmyth_string_list_new(); + + io_channel = priv->sock->sd_io_ch; + io_channel_control = priv->control_sock->sd_io_ch; + + io_status = g_io_channel_set_encoding(io_channel, NULL, &error); + if (io_status == G_IO_STATUS_NORMAL) + gmyth_debug("[%s] Setting encoding to binary data socket).\n", + __FUNCTION__); + + io_cond = g_io_channel_get_buffer_condition(io_channel); + + io_cond_control = g_io_channel_get_buffer_condition(io_channel); + if (priv->sock == NULL || (io_status == G_IO_STATUS_ERROR)) { + g_printerr + ("gmyth_file_transfer_read(): Called with no raw socket.\n"); + return GMYTH_FILE_READ_ERROR; + } + + if (priv->control_sock == NULL + || (io_status_control == G_IO_STATUS_ERROR)) { + g_printerr + ("gmyth_file_transfer_read(): Called with no control socket.\n"); + return GMYTH_FILE_READ_ERROR; + } + + query = g_string_new(GMYTHTV_QUERY_HEADER); + g_string_append_printf(query, "%d", priv->file_id); + gmyth_debug("[%s] Transfer_query = %s\n", __FUNCTION__, query->str); + + _control_acquire_context(transfer, TRUE); + // Do Read + gmyth_string_list_append_char_array(strlist, query->str); + gmyth_string_list_append_char_array(strlist, "REQUEST_BLOCK"); + gmyth_string_list_append_int(strlist, size - total_read); + + guint iter_count = 3; + + do { + bytes_sent = 0; + + // Request the block to the backend + gmyth_socket_write_stringlist(priv->control_sock, strlist); + + if (ret_strlist != NULL) + g_object_unref(ret_strlist); + + ret_strlist = gmyth_string_list_new(); + // Receives the backand answer + gmyth_socket_read_stringlist(priv->control_sock, ret_strlist); + + if (ret_strlist != NULL + && gmyth_string_list_length(ret_strlist) > 0) { + bytes_sent = gmyth_string_list_get_int(ret_strlist, 0); // -1 + // on + // backend + // error + gmyth_debug("[%s] got SENT buffer message = %d\n", + __FUNCTION__, bytes_sent); + } + + if (read_unlimited && (bytes_sent == 0)) { + g_usleep(300); + } + + --iter_count; + + } + while (read_unlimited && (bytes_sent == 0) && iter_count > 0); + + if (bytes_sent > 0) { + gchar *data_buffer = g_new0(gchar, bytes_sent); + + io_status = g_io_channel_read_chars(io_channel, + data_buffer, + (gsize) bytes_sent, + &bytes_read, &error); + + if (io_status != G_IO_STATUS_NORMAL) { + gmyth_debug("Error on io_channel"); + g_free(data_buffer); + g_object_unref(strlist); + retval = GMYTH_FILE_READ_ERROR; + goto error; + } + + /* + * append new data to the increasing byte array + */ + data = + g_byte_array_append(data, (const guint8 *) data_buffer, + bytes_read); + gmyth_file_set_offset(GMYTH_FILE(transfer), + gmyth_file_get_offset(GMYTH_FILE(transfer)) + + bytes_read); + + if (!read_unlimited + && (gmyth_file_get_filesize(GMYTH_FILE(transfer)) > 0) + && (gmyth_file_get_offset(GMYTH_FILE(transfer)) == + gmyth_file_get_filesize(GMYTH_FILE(transfer)))) { + retval = GMYTH_FILE_READ_EOF; + goto error; + } + + g_free(data_buffer); + } else { + retval = GMYTH_FILE_READ_ERROR; + } + + if (strlist != NULL) { + g_object_unref(strlist); + strlist = NULL; + } + + if (ret_strlist != NULL) { + g_object_unref(ret_strlist); + ret_strlist = NULL; + } + + if (read_unlimited && (bytes_sent == 0)) { + gmyth_debug("Trying to move to the next program chain..."); + if (priv->recorder != NULL && priv->do_next_program_chain) { + priv->do_next_program_chain = FALSE; + retval = GMYTH_FILE_READ_NEXT_PROG_CHAIN; + GMythProgramInfo *prog_info = + gmyth_recorder_get_current_program_info(priv->recorder); + + gmyth_debug + ("Comparing if the current prog. info = %s [strlen == %d] is equals to " + " %s [strlen == %d]...", prog_info->pathname->str, + strlen(prog_info->pathname->str), + gmyth_file_get_file_name(GMYTH_FILE(transfer)), + strlen(gmyth_file_get_file_name(GMYTH_FILE(transfer)))); + + if (prog_info != NULL && prog_info->pathname != NULL + && strlen(prog_info->pathname->str) > 0 + && (NULL == + g_strstr_len(prog_info->pathname->str, + strlen(prog_info->pathname->str), + gmyth_file_get_file_name(GMYTH_FILE + (transfer))))) { + /* + * releasing context got at this function starting... + */ + _control_release_context(transfer); + ret = + gmyth_file_transfer_open(transfer, + g_strrstr(prog_info-> + pathname->str, + "/")); + _control_acquire_context(transfer, TRUE); + /* + * acquiring context released at this function stopping... + */ + + if (prog_info != NULL) + g_object_unref(prog_info); + + if (!ret) + gmyth_debug("Cannot change to the next program info!"); + else + gmyth_debug + ("OK!!! MOVED to the next program info [%s]!", + gmyth_file_get_file_name(GMYTH_FILE(transfer))); + } + + } + + } + /* + * if + */ + error: + + _control_release_context(transfer); + g_string_free(query, TRUE); + + if (error != NULL) { + gmyth_debug("Cleaning-up ERROR: %s [msg = %s, code = %d]\n", + __FUNCTION__, error->message, error->code); + g_error_free(error); + } + + if (total_read > 0) + gmyth_file_set_offset(GMYTH_FILE(transfer), + gmyth_file_get_offset(GMYTH_FILE + (transfer)) + + total_read); + + return retval; +} + +static void +_file_transfer_program_info_changed(GMythFileTransfer * transfer, + gint msg_code, + gpointer livetv_recorder) +{ + GMythRecorder *recorder; + GMythFileTransferPrivate *priv; + + g_return_if_fail(transfer != NULL); + + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + + recorder = GMYTH_RECORDER(livetv_recorder); + gmyth_debug + ("Program info changed! ( file transfer orig. = %p, ptr. = [%s] )", + transfer, livetv_recorder != NULL ? "[NOT NULL]" : "[NULL]"); + + if (NULL != recorder) { + gmyth_debug + ("YES, the requested program info movement on the LiveTV transfer is authentical!"); + } + + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + g_object_ref(recorder); + priv->recorder = recorder; + priv->do_next_program_chain = TRUE; +} + +/** + * Sets the timeout flag of a file being transfered. + * + * @param transfer The actual File Transfer instance. + * @param fast If this is true, sets the remote timeout to be as fast + * as possible. + * + * @return true, if the acquire had been got. + */ +gboolean +gmyth_file_transfer_settimeout(GMythFileTransfer * transfer, gboolean fast) +{ + GMythFileTransferPrivate *priv; + GMythStringList *strlist = NULL; + + g_return_val_if_fail(transfer != NULL, FALSE); + + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + + g_return_val_if_fail(priv->sock != NULL, FALSE); + g_return_val_if_fail(priv->control_sock != NULL, FALSE); + + _control_acquire_context(transfer, TRUE); + + strlist = gmyth_string_list_new(); + gmyth_string_list_append_char_array(strlist, GMYTHTV_QUERY_HEADER); + gmyth_string_list_append_char_array(strlist, "SET_TIMEOUT"); + gmyth_string_list_append_int(strlist, fast); + + gint strlist_len = + gmyth_socket_sendreceive_stringlist(priv->control_sock, + strlist); + + if (strlist_len > 0) + gmyth_debug("Yes, timeout was changed: %s.", + gmyth_string_list_get_char_array(strlist, 0)); + else + gmyth_debug("Timeout cannot be changed!"); + + _control_release_context(transfer); + + gmyth_debug("%s setting timeout flag of this file transfer = %s\n", + strlist_len > 0 ? "Yes," : "NOT", + fast ? "FAST" : "NOT FAST"); + + g_object_unref(strlist); + + return TRUE; +} + +/** + * Gets the actual file size of the binary content. + * + * @param transfer The actual File Transfer instance. + * + * @return The actual file size in bytes. + */ +guint64 +gmyth_file_transfer_get_filesize(GMythFileTransfer * transfer) +{ + guint64 filesize; + + g_return_val_if_fail(transfer != NULL, 0); + + g_object_get(GMYTH_FILE(transfer), "file-size", &filesize, NULL); + + return filesize; +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_file_transfer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_file_transfer.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,111 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_file_transfer.h + * + * @brief

GMythFileTransfer deals with the file streaming media remote/local + * transfering to the MythTV frontend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_FILE_TRANSFER_H__ +#define __GMYTH_FILE_TRANSFER_H__ + +#include +#include + +#include "gmyth_file.h" +#include "gmyth_socket.h" +#include "gmyth_uri.h" +#include "gmyth_backendinfo.h" + +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS +#define GMYTH_FILE_TRANSFER_TYPE (gmyth_file_transfer_get_type ()) +#define GMYTH_FILE_TRANSFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransfer)) +#define GMYTH_FILE_TRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferClass)) +#define IS_GMYTH_FILE_TRANSFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_FILE_TRANSFER_TYPE)) +#define IS_GMYTH_FILE_TRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TRANSFER_TYPE)) +#define GMYTH_FILE_TRANSFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferClass)) +typedef struct _GMythFileTransfer GMythFileTransfer; +typedef struct _GMythFileTransferClass GMythFileTransferClass; +typedef struct _GMythFileTransferPrivate GMythFileTransferPrivate; + +struct _GMythFileTransfer { + GMythFile parent; + GMythFileTransferPrivate *priv; +}; + +struct _GMythFileTransferClass { + GMythFileClass parent_class; + + /* + * callbacks + */ + guint program_info_changed_handler_signal_id; + + /* + * signal default handlers + */ + void (*program_info_changed_handler) (GMythFileTransfer * + transfer, + gint msg_code, + gpointer + livetv_recorder); +}; + + +GType gmyth_file_transfer_get_type(void); +GMythFileTransfer *gmyth_file_transfer_new(GMythBackendInfo * + backend_info); +gchar *gmyth_file_transfer_get_file_name(GMythFileTransfer * + transfer); +gboolean gmyth_file_transfer_open(GMythFileTransfer * transfer, + const gchar * filename); +void gmyth_file_transfer_close(GMythFileTransfer * transfer); +gboolean gmyth_file_transfer_is_open(GMythFileTransfer * transfer); + +GMythFileReadResult +gmyth_file_transfer_read(GMythFileTransfer * transfer, + GByteArray * data, gint size, + gboolean read_unlimited); +gint64 gmyth_file_transfer_seek(GMythFileTransfer * transfer, + guint64 pos, gint whence); +gboolean gmyth_file_transfer_settimeout(GMythFileTransfer * + transfer, gboolean fast); +guint64 gmyth_file_transfer_get_filesize(GMythFileTransfer * + transfer); + +void + gmyth_file_transfer_emit_program_info_changed_signal(GMythFileTransfer * + transfer, + gint + msg_code, + gpointer + live_tv_recorder); + +G_END_DECLS +#endif /* __GMYTH_FILE_TRANSFER_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_http.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_http.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,1037 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_http.c + * + * @brief

GMythHttp library provides a wrapper to access + * data from the database using http+xml + * + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. + * @author Artur Duque de Souza + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +#include "gmyth_http.h" +#include "gmyth_debug.h" +#include "gmyth_socket.h" + +xmlXPathObjectPtr +getnodeset(xmlDocPtr doc, xmlChar * xpath) +{ + + xmlXPathContextPtr context; + xmlXPathObjectPtr result; + + context = xmlXPathNewContext(doc); + result = xmlXPathEvalExpression(xpath, context); + + if (xmlXPathNodeSetIsEmpty(result->nodesetval)) { + g_fprintf(stderr, "Error: No result at XPath\n"); + return NULL; + } + + xmlXPathFreeContext(context); + return result; +} + + +xmlDocPtr +XMLParse(const char *content, int length) +{ + xmlDocPtr doc; /* the resulting document tree */ + + doc = xmlReadMemory(content, length, NULL, NULL, 0); + if (doc == NULL) { + g_fprintf(stderr, "Error: Failed to parse XML document\n"); + return NULL; + } + + return doc; +} + +xmlXPathObjectPtr +getXPath(xmlChar * xpath, xmlDocPtr doc) +{ + xmlXPathObjectPtr result; + + result = getnodeset(doc, xpath); + return result; +} + + +/** Retrieves the Progam List from the Channel + * + * @param nodeTab A pointer to a node inside the XML + * @return A GSList containing a list of all the programs + */ +GSList * +get_Program_List(xmlNodePtr node) +{ + GSList *program_list = NULL; + + while (node != NULL) { + if (g_ascii_strcasecmp((char *) node->name, "text") != 0) { + GMythProgram *program = (GMythProgram *) + g_malloc(sizeof(struct _GMythProgram)); + + program->title = g_strdup((char *) + xmlGetProp(node, + (xmlChar *) "title")); + + program->subtitle = g_strdup((char *) + xmlGetProp(node, (xmlChar *) + "subtitle")); + + program->catType = g_strdup((char *) + xmlGetProp(node, (xmlChar *) + "catType")); + + program->category = g_strdup((char *) + xmlGetProp(node, (xmlChar *) + "category")); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "repeat"), + "%d", &(program->repeat)); + + program->startTime = gmyth_util_string_to_time_val + ((char *) xmlGetProp(node, (xmlChar *) "startTime")); + + program->endTime = gmyth_util_string_to_time_val + ((char *) xmlGetProp(node, (xmlChar *) "endTime")); + + program_list = g_slist_append(program_list, program); + } + + node = node->next; + } + + return program_list; +} + +/** Retrieves the Channel List from the ProgramGuide + * + * @param node A pointer to a node inside the XML + * @param epg The struct where is the current epg + * @return The epg from "param" updated + */ +void +get_Channel_List(xmlNodePtr node, GMythEpg * epg) +{ + epg->channelList = NULL; + + while (node != NULL) { + + if (g_ascii_strcasecmp((char *) node->name, "text") != 0) { + GMythChannel *channel = (GMythChannel *) g_malloc + (sizeof(struct _GMythChannel)); + + channel->channelName = g_strdup((char *) + xmlGetProp(node, (xmlChar *) + "channelName")); + + channel->chanNum = g_strdup((char *) + xmlGetProp(node, (xmlChar *) + "chanNum")); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "chanId"), + "%d", &(channel->chanId)); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "callSign"), + "%d", &(channel->callSign)); + + channel->programList = get_Program_List(node->children); + + epg->channelList = g_slist_append(epg->channelList, channel); + + } + + node = node->next; + } +} + +/** Retrieves the properties from the ProgramGuide + * + * @param nodeTab A pointer to a node inside the XML + * @param epg The struct where is the current epg + * @return The epg from "param" updated + */ +void +get_ProgramGuide_Properties(xmlNodePtr nodeTab, GMythEpg * epg) +{ + + xmlNode *ptr = nodeTab->children->next->children; + + epg->startTime = gmyth_util_string_to_time_val((char *) ptr->content); + + ptr = ptr->parent->next->next->children; + epg->endTime = gmyth_util_string_to_time_val((char *) ptr->content); + + ptr = ptr->parent->next->next->children; + sscanf((char *) ptr->content, "%d", &(epg->startChanId)); + + ptr = ptr->parent->next->next->children; + sscanf((char *) ptr->content, "%d", &(epg->endChanId)); + + ptr = ptr->parent->next->next->children; + sscanf((char *) ptr->content, "%d", &(epg->numOfChannels)); + + ptr = ptr->parent->next->next->children; + sscanf((char *) ptr->content, "%d", &(epg->details)); + + ptr = ptr->parent->next->next->children; + sscanf((char *) ptr->content, "%d", &(epg->totalCount)); + + ptr = ptr->parent->next->next->children; + epg->asOf = gmyth_util_string_to_time_val((char *) ptr->content); + + ptr = ptr->parent->next->next->children; + epg->version = g_strdup((char *) ptr->content); + + ptr = ptr->parent->next->next->children; + sscanf((char *) ptr->content, "%d", &(epg->protoVer)); + + ptr = ptr->parent->next->next->children; + // go to Channel section and retrieve Channels and Programs + if (epg->numOfChannels > 0) + get_Channel_List(ptr, epg); + else + epg->channelList = NULL; +} + +/** Aux function to retrieve the Eletronic Program Guide + * + * @param doc An XML document (xmlDocPtr) + * @return The epg + */ +void +getEpg(xmlDocPtr doc, GMythEpg * epg) +{ + xmlXPathObjectPtr result; + xmlNodeSetPtr nodeset; + xmlChar *keyword; + + int i; + + result = getXPath((xmlChar *) "/*", doc); + + if (result) { + nodeset = result->nodesetval; + for (i = 0; i < nodeset->nodeNr; i++) { + keyword = (xmlChar *) nodeset->nodeTab[i]->name; + if (g_ascii_strcasecmp + ((char *) keyword, "GetProgramGuideResponse") == 0) { + get_ProgramGuide_Properties(nodeset->nodeTab[i], epg); + break; + } + } + xmlXPathFreeObject(result); + } + +} + + + +/** Retrieves the Eletronic Program Guide from the backend + * + * @param doc An XML document (xmlDocPtr) + * @return The epg + */ +GMythEpg +gmyth_http_retrieve_epg(GMythBackendInfo * backend_info, + GTimeVal * StartTime, GTimeVal * EndTime, + gint StartChanId, gint NumOfChannels, + gchar * Details) +{ + GMythEpg epg; + MemoryStruct chunk; + + chunk.memory = NULL; /* we expect realloc(NULL, size) to work */ + chunk.size = 0; /* no data at this point */ + + gchar *starttime; + + starttime = (gchar *) xmlURIEscapeStr((const xmlChar *) + gmyth_util_time_to_mythformat_from_time_val + (StartTime), NULL); + + gchar *endtime; + + endtime = (gchar *) xmlURIEscapeStr((const xmlChar *) + gmyth_util_time_to_mythformat_from_time_val + (EndTime), NULL); + + GString *command = g_string_new(""); + + g_string_printf(command, + "GetProgramGuide?StartTime=%s&EndTime=%s&StartChanId=%d" + "&NumOfChannels=%d&Details=%s", starttime, endtime, + StartChanId, NumOfChannels, Details); + gmyth_debug("HTTP Request command = %s\n", command->str); + + chunk = gmyth_http_request(backend_info, command); + if (chunk.memory != NULL) { + xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory)); + + getEpg(doc, &epg); + free(chunk.memory); + } + + return epg; +} + + +GMythRecorded_Recording +retrieve_recorded_recording(xmlNodePtr node) +{ + GMythRecorded_Recording recording; + + if (g_ascii_strcasecmp((char *) node->name, "text") != 0) { + + sscanf((char *) xmlGetProp(node, (xmlChar *) "dupInType"), + "%d", &(recording.dupInType)); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "dupMethod"), + "%d", &(recording.dupMethod)); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "recStatus"), + "%d", &(recording.recStatus)); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "encoderId"), + "%d", &(recording.encoderId)); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "recordId"), + "%d", &(recording.recordId)); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "recType"), + "%d", &(recording.recType)); + + recording.playGroup = g_strdup((char *) + xmlGetProp(node, (xmlChar *) + "playGroup")); + + recording.recGroup = g_strdup((char *) + xmlGetProp(node, + (xmlChar *) "recGroup")); + + recording.recProfile = g_strdup((char *) + xmlGetProp(node, (xmlChar *) + "recProfile")); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "recPriority"), + "%d", &(recording.recPriority)); + + recording.recStartTs = gmyth_util_string_to_time_val + ((char *) xmlGetProp(node, (xmlChar *) "recStartTs")); + + recording.recEndTs = gmyth_util_string_to_time_val + ((char *) xmlGetProp(node, (xmlChar *) "recEndTs")); + } + + return recording; +} + + +GMythRecorded_Channel +retrieve_recorded_channel(xmlNodePtr node) +{ + GMythRecorded_Channel channel; + + if (g_ascii_strcasecmp((char *) node->name, "text") != 0) { + + channel.chanFilters = g_strdup((char *) + xmlGetProp(node, (xmlChar *) + "chanFilters")); + + channel.channelName = g_strdup((char *) + xmlGetProp(node, (xmlChar *) + "channelName")); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "chanNum"), + "%d", &(channel.chanNum)); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "sourceId"), + "%d", &(channel.sourceId)); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "commFree"), + "%d", &(channel.commFree)); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "inputId"), + "%d", &(channel.inputId)); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "chanId"), + "%d", &(channel.chanId)); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "callSign"), + "%d", &(channel.callSign)); + } + + return channel; +} + + + +/** Retrieves all the programs from Recorded XML + * + * @param nodeTab A pointer to a node inside the XML + * @param recorded The struct where is the current epg + * @return list with all the recorded programs + */ +GSList * +get_Recorded_Programs(xmlNodePtr node) +{ + GSList *programList = NULL; + + while (node != NULL) { + + if (g_ascii_strcasecmp((char *) node->name, "text") != 0) { + + GMythRecorded_Program *program = (GMythRecorded_Program *) + g_malloc(sizeof(struct _GMythRecorded_Program)); + + sscanf((char *) + xmlGetProp(node, (xmlChar *) "programFlags"), "%d", + &(program->programFlags)); + + program->title = g_strdup((char *) + xmlGetProp(node, + (xmlChar *) "title")); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "programId"), + "%d", &(program->programId)); + + program->catType = g_strdup((char *) + xmlGetProp(node, (xmlChar *) + "catType")); + + program->category = g_strdup((char *) + xmlGetProp(node, (xmlChar *) + "category")); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "seriesId"), + "%d", &(program->seriesId)); + + + program->startTime = gmyth_util_string_to_time_val + ((char *) xmlGetProp(node, (xmlChar *) "startTime")); + + program->endTime = gmyth_util_string_to_time_val + ((char *) xmlGetProp(node, (xmlChar *) "endTime")); + + program->lastModified = gmyth_util_string_to_time_val((char *) + xmlGetProp + (node, + (xmlChar + *) + "lastModified")); + + /* + * TODO: FIX ME at gmyth_util program->asOf = + * gmyth_util_string_to_time_val\ ((char *)xmlGetProp(node, + * (xmlChar *)"airdate")); + */ + + program->subTitle = g_strdup((char *) + xmlGetProp(node, (xmlChar *) + "subTitle")); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "stars"), + "%d", &(program->stars)); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "repeat"), + "%d", &(program->repeat)); + + sscanf((char *) xmlGetProp(node, (xmlChar *) "fileSize"), + "%d", &(program->repeat)); + + program->hostname = g_strdup((char *) + xmlGetProp(node, (xmlChar *) + "hostname")); + + program->channel = retrieve_recorded_channel(node->children); + + // Skip the \n + program->recording = + retrieve_recorded_recording(node->children->next->next); + + // add to the list + programList = g_slist_append(programList, program); + } + + node = node->next; + } + + return programList; +} + +/** Retrieves the properties from Recorded XML + * + * @param nodeTab A pointer to a node inside the XML + * @param recorded The struct where is the current epg + * @return "recorded" from "param" updated + */ +void +get_Recorded_Properties(xmlNodePtr nodeTab, GMythRecorded * recorded) +{ + xmlNode *ptr = nodeTab->children->next->children; + + sscanf((char *) ptr->content, "%d", &(recorded->totalCount)); + + + ptr = ptr->parent->next->next->children; + recorded->asOf = gmyth_util_string_to_time_val((char *) ptr->content); + + ptr = ptr->parent->next->next->children; + recorded->version = g_strdup((char *) ptr->content); + + ptr = ptr->parent->next->next->children; + sscanf((char *) ptr->content, "%d", &(recorded->protoVer)); + + ptr = ptr->parent->next->next->children; + if (recorded->totalCount > 0) + recorded->programList = get_Recorded_Programs(ptr->children); + +} + + +/** Aux function to retrieve Recorded programs + * + * @param doc An XML document (xmlDocPtr) + * @return The recorded var updated + */ +void +getRecorded(xmlDocPtr doc, GMythRecorded * recorded) +{ + xmlXPathObjectPtr result; + xmlNodeSetPtr nodeset; + xmlChar *keyword; + + int i; + + result = getXPath((xmlChar *) "/*", doc); + + if (result) { + nodeset = result->nodesetval; + for (i = 0; i < nodeset->nodeNr; i++) { + keyword = (xmlChar *) nodeset->nodeTab[i]->name; + if (g_ascii_strcasecmp + ((char *) keyword, "GetRecordedResponse") == 0) { + get_Recorded_Properties(nodeset->nodeTab[i], recorded); + break; + } + } + xmlXPathFreeObject(result); + } + +} + + +/** Function to retrieve the files that are recorded + * + */ +GMythRecorded +gmyth_http_retrieve_recorded(GMythBackendInfo * backend_info) +{ + GMythRecorded recorded; + MemoryStruct chunk; + + chunk.memory = NULL; + chunk.size = 0; + + GString *command = g_string_new(""); + + g_string_printf(command, "GetRecorded"); + + chunk = gmyth_http_request(backend_info, command); + if (chunk.memory != NULL) { + xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory)); + + getRecorded(doc, &recorded); + free(chunk.memory); + } + + return recorded; +} + + + +/** Function to retrieve jobqueue status + * + */ +gint +gmyth_http_retrieve_job_status(GMythBackendInfo * backend_info, + gint chanid, GTimeVal * start) +{ + gint status = 0; + gint count = 0; + gint temp_chanid = 0; + GTimeVal *temp_start = NULL; + int i; + + xmlXPathObjectPtr result; + xmlNodeSetPtr nodeset; + xmlNodePtr node; + MemoryStruct chunk; + + chunk.memory = NULL; + chunk.size = 0; + + GString *command = g_string_new(""); + + g_string_printf(command, "GetStatus"); + + chunk = gmyth_http_request(backend_info, command); + + if (chunk.memory != NULL) { + xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory)); + + result = getXPath((xmlChar *) "/Status/JobQueue", doc); + if (result) { + nodeset = result->nodesetval; + node = nodeset->nodeTab[0]; + sscanf((char *) xmlGetProp(node, (xmlChar *) "count"), + "%d", &count); + + if (count > 0) { + + // Get the first child + node = node->children->next; + + for (i = 0; i < count; i++) { + + sscanf((char *) + xmlGetProp(node, (xmlChar *) "chanId"), "%d", + &temp_chanid); + + if (chanid == temp_chanid) { + temp_start = gmyth_util_string_to_time_val((char *) + xmlGetProp + (node, + (xmlChar + *) + "startTime")); + + if ((temp_start->tv_sec == start->tv_sec) && + (temp_start->tv_usec == start->tv_usec)) + sscanf((char *) + xmlGetProp(node, + (xmlChar *) "status"), + "%d", &status); + } + // Escape "text" node + node = node->next->next; + } + } + + } + + xmlXPathFreeObject(result); + free(chunk.memory); + + } + + return status; +} + + + +/** Function to retrieve settings on the backend + * + * @param backend_info infos about the backend + * @param key the key you want to retrieve + * @param hostname the hostname that the key is set up + * @return the value of the key + */ +gchar * +gmyth_http_retrieve_setting(GMythBackendInfo * backend_info, + gchar * key, gchar * hostname) +{ + xmlXPathObjectPtr result; + xmlNodeSetPtr nodeset; + xmlChar *keyword; + MemoryStruct chunk; + gchar *value = NULL; + + chunk.memory = NULL; + chunk.size = 0; + + GString *command = g_string_new(""); + + g_string_printf(command, "GetSetting?Key=%s&HostName=%s&Default=NULL", + key, hostname); + + chunk = gmyth_http_request(backend_info, command); + + if (chunk.memory != NULL) { + xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory)); + + result = getXPath((xmlChar *) "/GetSettingResponse/Values/*", doc); + + if (result) { + nodeset = result->nodesetval; + keyword = (xmlChar *) nodeset->nodeTab[0]->name; + if (g_ascii_strcasecmp((char *) keyword, "Value") == 0) { + // Here we have the value + value = (gchar *) nodeset->nodeTab[0]->children->content; + } + xmlXPathFreeObject(result); + } + + free(chunk.memory); + } + + return value; +} + +/** Common steps for rec_profile's functions + * + * @param backend_info infos about the backend + * @param id the profile's id that you want to delete + * @return 0 if OK + */ +gint +rec_profile_common(GMythBackendInfo * backend_info, GString * command) +{ + xmlXPathObjectPtr result; + xmlNodeSetPtr nodeset; + xmlChar *keyword; + MemoryStruct chunk; + + chunk.memory = NULL; + chunk.size = 0; + + int ret = -1; + + chunk = gmyth_http_request(backend_info, command); + + if (chunk.memory != NULL) { + xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory)); + + result = getXPath((xmlChar *) "/*", doc); + + if (result) { + nodeset = result->nodesetval; + keyword = (xmlChar *) nodeset->nodeTab[0]->name; + + if (g_ascii_strcasecmp((char *) keyword, "Success") == 0) + ret = 0; + + xmlXPathFreeObject(result); + } + + free(chunk.memory); + } + + return ret; +} + + +/** Function to delete recording profiles + * + * @param backend_info infos about the backend + * @param id the profile's id that you want to delete + * @return 0 if OK + */ +gint +gmyth_http_del_rec_profile(GMythBackendInfo * backend_info, gint id) +{ + + GString *command = g_string_new(""); + + g_string_printf(command, "delRecProfiles?id=%d", id); + + + return rec_profile_common(backend_info, command); +} + +/** Function to create recording profiles + * + * @param backend_info infos about the backend + * @param profilename the name of profile you want to use + * @param groupname the name of groupname you want to use + * @param vcodec the name of the video codec you want to use + * @param acodec the name of the audo codec you want to use + * @return 0 if OK + */ +gint +gmyth_http_create_rec_profile(GMythBackendInfo * backend_info, + GMythRecProfile * profile) +{ + + if (profile->name != NULL && profile->group != NULL && + profile->vcodec && profile->acodec && profile->options != NULL) { + GString *command = g_string_new(""); + + g_string_printf(command, "createRecProfiles?profilename=%s&" + "groupname=%s&vcodec=%s&acodec=%s&" + "transcodelossless=%d&transcoderesize=%d&" + "width=%d&height=%d&rtjpegquality=%d&" + "rtjpeglumafilter=%d&rtjpegchromafilter=%d&" + "mpeg4bitrate=%d&mpeg4maxquality=%d&" + "mpeg4minquality=%d&mpeg4qualdiff=%d&" + "mpeg4scalebitrate=%d&mpeg4optionvhq=%d&" + "mpeg4option4mv=%d&mpeg4optionidct=%d&" + "mpeg4optionime=%d&hardwaremjpegquality=%d&" + "hardwaremjpeghdecimation=%d&hardwaremjpegvdecimation=%d&" + "mpeg2streamtype=%s&mpeg2aspectratio=%s&" + "mpeg2bitrate=%d&mpeg2maxbitrate=%d&" + "samplerate=%d&mp3quality=%d&" + "volume=%d&mpeg2audtype=%s&" + "mpeg2audbitratel1=%d&mpeg2audbitratel2=%d&" + "mpeg2audvolume=%d", + profile->name, profile->group, + profile->vcodec, profile->acodec, + profile->options->transcodelossless, + profile->options->transcoderesize, + profile->options->width, + profile->options->height, + profile->options->rtjpegquality, + profile->options->rtjpeglumafilter, + profile->options->rtjpegchromafilter, + profile->options->mpeg4bitrate, + profile->options->mpeg4maxquality, + profile->options->mpeg4minquality, + profile->options->mpeg4qualdiff, + profile->options->mpeg4scalebitrate, + profile->options->mpeg4optionvhq, + profile->options->mpeg4option4mv, + profile->options->mpeg4optionidct, + profile->options->mpeg4optionime, + profile->options->hardwaremjpegquality, + profile->options->hardwaremjpeghdecimation, + profile->options->hardwaremjpegvdecimation, + profile->options->mpeg2streamtype, + profile->options->mpeg2aspectratio, + profile->options->mpeg2bitrate, + profile->options->mpeg2maxbitrate, + profile->options->samplerate, + profile->options->mp3quality, + profile->options->volume, + profile->options->mpeg2audtype, + profile->options->mpeg2audbitratel1, + profile->options->mpeg2audbitratel2, + profile->options->mpeg2audvolume); + + + return rec_profile_common(backend_info, command); + } else + return -1; +} + +/** Function to retrieve recording profiles + * + * @param backend_info infos about the backend + * @param groupname the name of group you want to retrieve + * @return the list of profiles + */ +GSList * +gmyth_http_retrieve_rec_profiles(GMythBackendInfo * backend_info, + gchar * groupname) +{ + xmlXPathObjectPtr result; + xmlNodeSetPtr nodeset; + xmlChar *keyword; + MemoryStruct chunk; + GSList *profiles = NULL; + + chunk.memory = NULL; + chunk.size = 0; + + GString *command = g_string_new(""); + + g_string_printf(command, "GetRecProfiles?groupname=%s", groupname); + + chunk = gmyth_http_request(backend_info, command); + + if (chunk.memory != NULL) { + xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory)); + + result = getXPath((xmlChar *) "/*", doc); + + if (result) { + nodeset = result->nodesetval; + keyword = (xmlChar *) nodeset->nodeTab[0]->name; + + if (g_ascii_strcasecmp((char *) keyword, "Profiles") == 0) { + xmlNodePtr node = nodeset->nodeTab[0]->children->next; + GMythRecProfile *profile; + + while (node != NULL) { + if (g_ascii_strcasecmp((char *) node->name, "text") != + 0) { + profile = gmyth_recprofile_new(); + + sscanf((char *) xmlGetProp(node, (xmlChar *) + "id"), "%d", + &(profile->id)); + + profile->name = g_strdup((char *) + xmlGetProp(node, + (xmlChar *) + "name")); + + profile->vcodec = g_strdup((char *) + xmlGetProp(node, + (xmlChar *) + "vcodec")); + + profile->acodec = g_strdup((char *) + xmlGetProp(node, + (xmlChar *) + "acodec")); + + profile->group = g_strdup(groupname); + + profiles = g_slist_append(profiles, profile); + } + node = node->next; + } + + } + xmlXPathFreeObject(result); + } + + free(chunk.memory); + } + + return profiles; +} + + + +/* + * Aux functions got from libcurl + */ +void * +myrealloc(void *ptr, size_t size) +{ + /* + * There might be a realloc() out there that doesn't like reallocing + * NULL pointers, so we take care of it here + */ + if (ptr) + return realloc(ptr, size); + else + return malloc(size); +} + +size_t +WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) +{ + size_t realsize = size * nmemb; + MemoryStruct *mem = (struct _MemoryStruct *) data; + + mem->memory = + (char *) myrealloc(mem->memory, mem->size + realsize + 1); + if (mem->memory) { + memcpy(&(mem->memory[mem->size]), ptr, realsize); + mem->size += realsize; + mem->memory[mem->size] = 0; + } + + return realsize; +} + + +/** Send HTTP Command and receives the result of it + * + * @return A string with the response from the server + * NULL if there is no response. + */ +MemoryStruct +gmyth_http_request(GMythBackendInfo * backend_info, GString * command) +{ + LIBXML_TEST_VERSION + size_t size = + strlen(backend_info->hostname) + strlen(command->str) + 20; + + gchar *URL = (gchar *) g_malloc(sizeof(gchar) * size); + gchar *mid = (gchar *) g_malloc(sizeof(gchar) * 6); + + mid = ""; + + if (g_ascii_strcasecmp(command->str, "GetStatus") && + g_ascii_strcasecmp(command->str, "GetStatusHTML")) { + mid = "Myth/"; + } + + g_snprintf(URL, size, "http://%s:%d/%s%s", + backend_info->hostname, backend_info->status_port, mid, + command->str); + + CURL *curl_handle; + + MemoryStruct chunk; + + chunk.memory = NULL; /* we expect realloc(NULL, size) to work */ + chunk.size = 0; /* no data at this point */ + + curl_global_init(CURL_GLOBAL_ALL); + + /* + * init the curl session + */ + curl_handle = curl_easy_init(); + + /* + * specify URL to get + */ + curl_easy_setopt(curl_handle, CURLOPT_URL, URL); + + /* + * send all data to this function + */ + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, + WriteMemoryCallback); + + /* + * we pass our 'chunk' struct to the callback function + */ + curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &chunk); + + /* + * some servers don't like requests that are made without a user-agent + * field, so we provide one + */ + curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); + + /* + * set timeout + */ + curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 20); + + /* + * get it! + */ + curl_easy_perform(curl_handle); + + /* + * cleanup curl stuff + */ + curl_easy_cleanup(curl_handle); + + return chunk; +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_http.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_http.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,204 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_http.h + * + * @brief

GMythHttp library provides a wrapper to access + * data from the database using http+xml + * + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. + * @author Artur Duque de Souza + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_HTTP_H__ +#define __GMYTH_HTTP_H__ + +#include + +#include +#include +#include +#include +#include +#include + +#include "gmyth_backendinfo.h" +#include "gmyth_util.h" +#include "gmyth_recprofile.h" + +#include +#include +#include + +G_BEGIN_DECLS +#define MYTH_PORT_STATUS 6544 +#define JOB_UNKNOWN 0x0000 +#define JOB_QUEUED 0x0001 +#define JOB_PENDING 0x0002 +#define JOB_STARTING 0x0003 +#define JOB_RUNNING 0x0004 +#define JOB_STOPPING 0x0005 +#define JOB_PAUSED 0x0006 +#define JOB_RETRY 0x0007 +#define JOB_ERRORING 0x0008 +#define JOB_ABORTING 0x0009 + // JOB_DONE is a mask to indicate the job is done + // whatever the status is +#define JOB_DONE 0x0100 +#define JOB_FINISHED 0x0110 +#define JOB_ABORTED 0x0120 +#define JOB_ERRORED 0x0130 +#define JOB_CANCELLED 0x0140 +typedef struct _GMythRecorded_Recording GMythRecorded_Recording; +typedef struct _GMythRecorded_Channel GMythRecorded_Channel; +typedef struct _GMythRecorded_Program GMythRecorded_Program; +typedef struct _GMythRecorded GMythRecorded; +typedef struct _GMythProgram GMythProgram; +typedef struct _GMythChannel GMythChannel; +typedef struct _GMythEpg GMythEpg; +typedef struct _MemoryStruct MemoryStruct; + +struct _MemoryStruct { + char *memory; + size_t size; +}; + +struct _GMythProgram { + gchar *title; + gchar *subtitle; + gchar *catType; + gchar *category; + gint repeat; + GTimeVal *startTime; + GTimeVal *endTime; +}; + +struct _GMythChannel { + gchar *channelName; + gchar *chanNum; + gint chanId; + gint callSign; + GSList *programList; +}; + +struct _GMythEpg { + gint startChanId; + gint endChanId; + gchar *version; + gint protoVer; + gint totalCount; + gint numOfChannels; + GTimeVal *asOf; + GTimeVal *startTime; + GTimeVal *endTime; + gint details; + GSList *channelList; +}; + + +struct _GMythRecorded_Recording { + gint dupInType; + gint dupMethod; + gchar *playGroup; + gchar *recGroup; + gchar *recProfile; + gint recPriority; + gint recStatus; + gint encoderId; + gint recordId; + gint recType; + GTimeVal *recStartTs; + GTimeVal *recEndTs; +}; + + +struct _GMythRecorded_Channel { + gchar *chanFilters; + gchar *channelName; + gint chanNum; + gint sourceId; + gint commFree; + gint inputId; + gint chanId; + gint callSign; +}; + + +struct _GMythRecorded_Program { + gint programFlags; + gchar *title; + gint programId; + gchar *catType; + gchar *category; + gint seriesId; + GTimeVal *startTime; + GTimeVal *endTime; + GTimeVal *airdate; // ? + GTimeVal *lastModified; + gchar *subTitle; + gint stars; + gint repeat; + gint fileSize; + gchar *hostname; + GMythRecorded_Channel channel; + GMythRecorded_Recording recording; +}; + +struct _GMythRecorded { + gchar *version; + gint protoVer; + gint totalCount; + GTimeVal *asOf; + GSList *programList; +}; + + +gint gmyth_http_retrieve_job_status(GMythBackendInfo * + backend_info, gint chanid, + GTimeVal * start); + +gchar *gmyth_http_retrieve_setting(GMythBackendInfo * + backend_info, gchar * key, + gchar * hostname); + +GMythEpg gmyth_http_retrieve_epg(GMythBackendInfo * backend_info, + GTimeVal * StartTime, + GTimeVal * EndTime, + gint StartChanId, + gint NumOfChannels, + gchar * Details); + +GMythRecorded gmyth_http_retrieve_recorded(GMythBackendInfo * + backend_info); + +GSList *gmyth_http_retrieve_rec_profiles(GMythBackendInfo * + backend_info, + gchar * groupname); + +gint gmyth_http_create_rec_profile(GMythBackendInfo * + backend_info, + GMythRecProfile * profile); + +gint gmyth_http_del_rec_profile(GMythBackendInfo * backend_info, + gint id); + +MemoryStruct gmyth_http_request(GMythBackendInfo * backend_info, + GString * command); + +G_END_DECLS +#endif /* __GMYTH_HTTP_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_jobqueue.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_jobqueue.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,200 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_jobqueue.c + * + * @brief

Library to use JobQueue from mythbackend + * + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. + * @author Artur Duque de Souza + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_jobqueue.h" +#include "gmyth_http.h" +#include "gmyth_debug.h" +#include "gmyth_socket.h" + +/** Function to connect + * + * @param backend_info the backendinfo + * @return gboolean - result of connection + * + */ +static GMythSocket * +backend_connect(GMythBackendInfo * backend_info) +{ + GMythSocket *socket = gmyth_socket_new(); + + if (gmyth_socket_connect_to_backend(socket, + gmyth_backend_info_get_hostname + (backend_info), + gmyth_backend_info_get_port + (backend_info), TRUE) == TRUE) { + gmyth_debug("Backend socket connection success"); + return socket; + } else { + gmyth_debug("Connection failed"); + return NULL; + } +} + + +/** Function to send a command to the backend + * + * @param socket pointer to a socket + * @param action the action itself + * @param job the action itself + * @param chanid the action itself + * @param starttime the action itself + * @param options the action itself + * @return the value returned by the backend + * + */ +static gchar * +send_command(GMythSocket * socket, gchar * action, + gchar * job, gint chanid, gchar * starttime, gchar * options) +{ + GString *command = g_string_new(""); + GString *ret_str; + gchar *ret; + + GMythStringList *retlist = gmyth_string_list_new(); + + g_string_printf(command, "JOBQUEUE %s %s %d %s %s", action, job, + chanid, starttime, options); + + gmyth_string_list_append_string(retlist, command); + gmyth_socket_write_stringlist(socket, retlist); + + // receive answer + gmyth_socket_read_stringlist(socket, retlist); + ret_str = gmyth_string_list_get_string(retlist, 0); + + // ret = ret_str->str; + ret = g_string_free(ret_str, FALSE); + g_string_free(command, TRUE); + + gmyth_string_list_clear_all(retlist); + g_object_unref(retlist); + + return ret; +} + + +/** Function to analyze the response from the backend + * + * @param ret the msg returned by the backend + * @param value the expected value + * @return 0 if success and -1 if error + * + */ +static gboolean +test_result(gchar * ret, gchar * value) +{ + if (g_ascii_strcasecmp(ret, value) == 0) { + return TRUE; + } else { + gmyth_debug("JobQueue Error: %s", ret); + return FALSE; + } +} + +/** Function to add a job inside JOBQUEUE + * + * @param transcode object holding all the info about the transcoding + * @param job the job you want to add the action + * @return TRUE if the job was added, FALSE if not + * + */ +gboolean +gmyth_jobqueue_add_job(GMythTranscoder * transcode, gchar * job) +{ + GMythSocket *socket = backend_connect(transcode->backend_info); + gboolean res = FALSE; + + if (socket != NULL) { + GString *options = g_string_new(""); + gchar *ret = NULL; + + if (g_ascii_strcasecmp(job, "JOB_TRANSCODE") == 0) { + if (transcode->cutlist) + g_string_append(options, " JOB_USE_CUTLIST"); + + if (transcode->output) + g_string_append_printf(options, " JOB_OUTPUT %s", + transcode->output_filename); + + if (transcode->profile != NULL) + g_string_append_printf(options, " %s", transcode->profile); + } + ret = send_command(socket, "ADD", job, transcode->chanid, + transcode->starttime, options->str); + res = test_result(ret, "JOBQUEUE_OK"); + gmyth_socket_close_connection(socket); + + g_object_unref(socket); + + g_string_free(options, TRUE); + + if (ret) + g_free(ret); + + } else { + gmyth_debug("JobQueue Connection Failed"); + } + + return res; +} + +/** Function to change a job cmd inside JOBQUEUE + * + * @param transcode object holding all the info about the transcoding + * @param action the action (ADD) + * @param job the job you want to add the action + * @return the value of the key + * + */ +gboolean +gmyth_jobqueue_change_cmd(GMythTranscoder * transcode, gchar * action, + gchar * job) +{ + GMythSocket *socket = backend_connect(transcode->backend_info); + gboolean res = FALSE; + + if (socket != NULL) { + gchar *ret = send_command(socket, action, job, + transcode->chanid, + transcode->starttime, ""); + + res = test_result(ret, "JOBQUEUE_CHANGED_CMD_OK"); + + gmyth_socket_close_connection(socket); + g_object_unref(socket); + + g_free(ret); + + } else { + gmyth_debug("JobQueue Connection Failed"); + } + + return res; +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_jobqueue.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_jobqueue.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,52 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_jobqueue.h + * + * @brief

Library to use JobQueue from mythbackend + * + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. + * @author Artur Duque de Souza + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_JOBQUEUE_H__ +#define __GMYTH_JOBQUEUE_H__ + +#include + +#include +#include +#include +#include +#include +#include + +#include "gmyth_stringlist.h" +#include "gmyth_backendinfo.h" +#include "gmyth_transcoder.h" +#include "gmyth_socket.h" +#include "gmyth_util.h" + +G_BEGIN_DECLS + gboolean gmyth_jobqueue_add_job(GMythTranscoder * transcoder, + gchar * job); +gboolean gmyth_jobqueue_change_cmd(GMythTranscoder * transcoder, + gchar * action, gchar * job); + +G_END_DECLS +#endif /* __GMYTH_JOBQUEUE_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_livetv.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_livetv.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,980 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_livetv.c + * + * @brief

GMythLiveTV starts a remote TV session with the MythTV backend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_livetv.h" +#include "gmyth_remote_util.h" +#include "gmyth_tvchain.h" +#include "gmyth_socket.h" +#include "gmyth_backendinfo.h" +#include "gmyth_debug.h" + +#include "gmyth_file.h" +#include "gmyth_file_transfer.h" +#include "gmyth_file_local.h" +#include "gmyth_monitor_handler.h" + +#include "gmyth_common.h" +#include "gmyth_util.h" + +static void gmyth_livetv_class_init(GMythLiveTVClass * klass); +static void gmyth_livetv_init(GMythLiveTV * object); + +static void gmyth_livetv_dispose(GObject * object); +static void gmyth_livetv_finalize(GObject * object); + +static gint tvchain_curr_index = -1; + +/* + * static GStaticMutex lock = G_STATIC_MUTEX_INIT; + */ + +#define GMYTHTV_TRANSFER_MAX_WAITS 100 + +G_DEFINE_TYPE(GMythLiveTV, gmyth_livetv, G_TYPE_OBJECT) + static void gmyth_livetv_class_init(GMythLiveTVClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_livetv_dispose; + gobject_class->finalize = gmyth_livetv_finalize; +} + +static void +gmyth_livetv_init(GMythLiveTV * livetv) +{ + livetv->monitor = NULL; + livetv->backend_info = NULL; + livetv->local_hostname = NULL; + livetv->file = NULL; + livetv->setup_done = FALSE; + + livetv->socket = NULL; + livetv->recorder = NULL; + livetv->tvchain = NULL; + livetv->proginfo = NULL; + livetv->uri = NULL; + + livetv->mutex = g_mutex_new(); +} + +static void +gmyth_livetv_dispose(GObject * object) +{ + GMythLiveTV *livetv = GMYTH_LIVETV(object); + + + if (livetv->disposed) { + /* + * If dispose did already run, return. + */ + return; + } + + /* + * Make sure dispose does not run twice. + */ + livetv->disposed = TRUE; + + if (livetv->monitor != NULL) { + g_object_unref(livetv->monitor); + livetv->monitor = NULL; + } + + + if (livetv->file != NULL) { + g_object_unref(livetv->file); + livetv->file = NULL; + } + + if (livetv->recorder != NULL) { + // gmyth_recorder_close(livetv->recorder); + g_object_unref(livetv->recorder); + livetv->recorder = NULL; + } + + if (livetv->socket != NULL) { + g_object_unref(livetv->socket); + livetv->socket = NULL; + } + + if (livetv->tvchain != NULL) { + g_object_unref(livetv->tvchain); + livetv->tvchain = NULL; + } + + if (livetv->proginfo != NULL) { + g_object_unref(livetv->proginfo); + livetv->proginfo = NULL; + } + + if (livetv->backend_info != NULL) { + g_object_unref(livetv->backend_info); + livetv->backend_info = NULL; + } + + if (livetv->uri != NULL) { + g_object_unref(livetv->uri); + livetv->uri = NULL; + } + + if (livetv->mutex != NULL) { + g_mutex_free(livetv->mutex); + livetv->mutex = NULL; + } + + if (livetv->local_hostname != NULL) { + g_string_free(livetv->local_hostname, TRUE); + livetv->local_hostname = NULL; + } + + G_OBJECT_CLASS(gmyth_livetv_parent_class)->dispose(object); +} + +static void +gmyth_livetv_finalize(GObject * object) +{ + g_signal_handlers_destroy(object); + + G_OBJECT_CLASS(gmyth_livetv_parent_class)->finalize(object); +} + +/** + * Creates a new GMythLiveTV instance + * + * @return a newly allocated GMythLiveTV instance + */ +GMythLiveTV * +gmyth_livetv_new(GMythBackendInfo * backend_info) +{ + GMythLiveTV *livetv = + GMYTH_LIVETV(g_object_new(GMYTH_LIVETV_TYPE, NULL)); + + livetv->backend_info = backend_info; + g_object_ref(livetv->backend_info); + + return livetv; +} + +/** + * The GObject signal handler function, from which all status messages + * from the Monitor Handler will be advertized, all time it receives + * LiveTV status messages from the MythTV backend + * + * @param monitor a GMythMonitorHandler instance + * @param msg_code the MythTV's server numeric status code + * @param message the message's string description + * @param user_data pointer to the GMythLiveTV instance + */ +static void +gmyth_livetv_monitor_signal_handler(GMythMonitorHandler * monitor, + gint msg_code, gchar * message, + gpointer user_data) +{ + GMythLiveTV *live_tv = GMYTH_LIVETV(user_data); + + gmyth_debug + ("LIVETV Signal handler ( msg = %s, code = %d, live_tv param = %s, user_data = %s )\n", + message, msg_code, live_tv != NULL ? "" : "NULL", + user_data != NULL ? "" : "NULL"); + + if (NULL == live_tv || !IS_GMYTH_FILE_TRANSFER(live_tv->file)) { + gmyth_debug("LiveTV_obj is equals to NULL!!!"); + return; + } + + switch (msg_code) { + + case GMYTH_BACKEND_PROGRAM_INFO_CHANGED: + { + gmyth_debug + ("LIVETV Program Changed request received [ msg = %s ]. Watching if the new " + "TV Chain ID is the same as the old one...\n", message); + if (g_ascii_strcasecmp + (message, + (gmyth_tvchain_get_id(live_tv->tvchain))->str) != 0) { + gmyth_debug + ("OK!!! MOVED to the next program chain [actual == %s]!", + (gmyth_tvchain_get_id(live_tv->tvchain))->str); + /* + * advertises the FileTransfer about the program info + * changed + */ + if (live_tv->file != NULL) { + gmyth_debug + ("Emitting signal to the FileTransfer... [ \"program-info-changed \" ]"); + + gmyth_file_transfer_emit_program_info_changed_signal + (GMYTH_FILE_TRANSFER(live_tv->file), msg_code, + (gpointer) (live_tv->recorder)); + + /* + * gmyth_livetv_monitor_handler_stop( live_tv ); + */ + } else + gmyth_debug + ("LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n"); + } + break; + } + case GMYTH_BACKEND_DONE_RECORDING: + { + gmyth_debug + ("LIVETV Program Changed request received [ msg = %s ]. Watching if the new " + "TV Chain ID is the same as the old one...\n", message); + if (g_ascii_strcasecmp + (message, + (gmyth_tvchain_get_id(live_tv->tvchain))->str) != 0) { + gmyth_debug + ("OK!!! MOVED to the next program chain [actual == %s]!", + (gmyth_tvchain_get_id(live_tv->tvchain))->str); + /* + * advertises the FileTransfer about the program info + * changed + */ + if (live_tv->file != NULL) { + gmyth_debug + ("Emitting signal to the FileTransfer... [ \"backend-done-recording\" ]"); + + gmyth_file_transfer_emit_program_info_changed_signal + (GMYTH_FILE_TRANSFER(live_tv->file), msg_code, + (gpointer) (live_tv->recorder)); + + } else + gmyth_debug + ("LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n"); + } + break; + } + case GMYTH_BACKEND_STOP_LIVETV: + { + gmyth_debug + ("LIVETV Stop LiveTV request received [ msg = %s ]. Going out the " + "LiveTV...\n", message); + /* + * stops the LiveTV + */ + if (live_tv != NULL) { + gmyth_debug("Going out the LiveTV... [ \"quit-livetv\" ]"); + + g_object_unref(live_tv); + } else + gmyth_debug + ("LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n"); + + break; + } + default: + break; + } /* switch (Monitor Handler messages) */ + +} + +/** + * Starts the Monitor Handler to this GMythLiveTV session, in order + * to receive the status messages from the MythTV's backend server + * + * @param live_tv the GMythLiveTV instance + * + * @return true if the Monitor Handler start-up process + * had been concluded succcesfully + */ +gboolean +gmyth_livetv_monitor_handler_start(GMythLiveTV * livetv) +{ + gboolean res = TRUE; + + if (livetv->monitor != NULL) { + g_object_unref(livetv->monitor); + livetv->monitor = NULL; + } + + livetv->monitor = gmyth_monitor_handler_new(); + res = + gmyth_monitor_handler_open(livetv->monitor, + livetv->backend_info->hostname, + livetv->backend_info->port); + + if (res == TRUE) { + gmyth_debug + ("Connect MythTV Monitor event socket! Trying to start the message handler..."); + + res = gmyth_monitor_handler_start(livetv->monitor); + + if (res) { + gmyth_debug + ("MythTV Monitor event socket connected and listening!"); + g_signal_connect(G_OBJECT(livetv->monitor), + "backend-events-handler", (GCallback) + gmyth_livetv_monitor_signal_handler, livetv); + } else { + gmyth_debug + ("Problems when trying to start MythTV Monitor event socket!"); + goto error; + } + } + + error: + return res; + +} + +/** + * Stops the Monitor Handler to this GMythLiveTV session, in order + * to stop receiving the status messages from the MythTV's backend server + * + * @param live_tv the GMythLiveTV instance + * + * @return true if the Monitor Handler shutdown process + * had been concluded succcesfully + */ +void +gmyth_livetv_monitor_handler_stop(GMythLiveTV * livetv) +{ + + if (livetv->monitor != NULL) { + g_object_unref(livetv->monitor); + livetv->monitor = NULL; + } + +} + +#if 0 +static gchar * +gmyth_livetv_create_remote_url(GMythLiveTV * livetv) +{ + gchar *uri = g_strdup(""); + + gmyth_backend_info_get_remote_h + // gmyth_backend(livetv->backend_info) + return uri; +} +#endif + +/** + * Configures the GMythLiveTV session, sends SPAWN_LIVETV message, + * sets the channel name, and gets the first program info about the + * actual recording + * + * @param live_tv the GMythLiveTV instance + * @param channel the channel name (the chan_name field, from the tvchain table) + * @param backend_info the GMythBackendInfo describing the remote server + * + * @return true if the LiveTV's recorder instance configuration + * had been concluded succcesfully + */ +static gboolean +gmyth_livetv_setup_recorder_channel_name(GMythLiveTV * livetv, + gchar * channel) +{ + gboolean res = TRUE; + + g_return_val_if_fail(livetv != NULL, FALSE); + + g_mutex_lock(livetv->mutex); + + if (livetv->socket == NULL) { + livetv->socket = gmyth_socket_new(); + /* + * FIME: Implement this at gmyth_socket + */ + res = + gmyth_socket_connect_to_backend(livetv->socket, + livetv->backend_info->hostname, + livetv->backend_info->port, + TRUE); + if (!res) { + gmyth_debug("[%s] LiveTV can not connect to backend", + __FUNCTION__); + res = FALSE; + goto error; + } + } + + livetv->is_livetv = TRUE; + + livetv->local_hostname = gmyth_socket_get_local_hostname(); + + if (livetv->local_hostname == NULL) { + g_warning("livetv could not retrieve the local hostname"); + res = FALSE; + goto error; + } else { + gmyth_debug("Local hostname: %s", livetv->local_hostname->str); + } + + if (livetv->recorder != NULL) { + g_object_unref(livetv->recorder); + livetv->recorder = NULL; + } + + if (gmyth_remote_util_get_free_recorder_count(livetv->socket) <= 0) { + gmyth_debug("No free remote encoder available."); + res = FALSE; + goto error; + } + + /* + * Gets the recorder num + */ + livetv->recorder = + remote_request_next_free_recorder(livetv->socket, -1); + gmyth_socket_close_connection(livetv->socket); + + if (NULL == livetv->recorder) { + gmyth_debug("[%s] None remote encoder available", __FUNCTION__); + res = FALSE; + goto error; + } + + /* + * Init remote encoder. Opens its control socket. + */ + res = gmyth_recorder_setup(livetv->recorder); + if (!res) { + gmyth_debug("[%s] Fail while setting remote encoder\n", + __FUNCTION__); + res = FALSE; + goto error; + } + + /* + * Creates livetv chain handler + */ + livetv->tvchain = gmyth_tvchain_new(); + gmyth_tvchain_initialize(livetv->tvchain, livetv->backend_info); + + if (livetv->tvchain == NULL || livetv->tvchain->tvchain_id == NULL) { + res = FALSE; + goto error; + } + // Spawn live tv. Uses the socket to send mythprotocol data to start + // livetv in the backend (remotelly) + res = gmyth_recorder_spawntv(livetv->recorder, + gmyth_tvchain_get_id(livetv->tvchain)); + if (!res) { + gmyth_debug("[%s] Fail while spawn tv\n", __FUNCTION__); + res = FALSE; + goto error; + } + + if (res == TRUE) { + /* + * loop finished, set the max tries variable to zero again... + */ + gint wait_to_transfer = 0; + + while (wait_to_transfer++ < GMYTHTV_TRANSFER_MAX_WAITS && + (gmyth_recorder_is_recording(livetv->recorder) == FALSE)) + g_usleep(300); + + if (channel != NULL) { + /* + * Pauses remote encoder. + */ + res = gmyth_recorder_pause_recording(livetv->recorder); + if (!res) { + gmyth_debug("[%s] Fail while pausing remote encoder\n", + __FUNCTION__); + res = FALSE; + goto error; + } + + if (gmyth_recorder_check_channel_name + (livetv->recorder, channel)) { + if (gmyth_recorder_set_channel_name + (livetv->recorder, channel)) { + gmyth_debug("Channel changed!!! [%s].\n", channel); + } + } + + } + /* + * if - changes the channel number + */ + /* + * sleep (5); + */ + /* + * FIXME: this is evil (tpm) + */ + } + + /* + * DEBUG message + */ + GMythProgramInfo *prog_info = + gmyth_recorder_get_current_program_info(livetv->recorder); + + if (NULL == prog_info) { + gmyth_debug("ProgramInfo is equals to NULL!!!"); + + gint i; + gchar *channame = NULL; + + gmyth_debug("Problem getting current proginfo!\n"); + + /* + * mythbackend must not be tuned in to a channel, so keep + * changing channels until we find a valid one, or until + * we decide to give up. + */ + for (i = 1; i < 1000; i++) { + if (channame != NULL) + g_free(channame); + channame = g_strdup_printf("%d", i); + if (gmyth_recorder_set_channel_name(livetv->recorder, channame) + < 0) { + continue; + } + prog_info = + gmyth_recorder_get_next_program_info(livetv->recorder, + BROWSE_DIRECTION_UP); + gmyth_program_info_print(prog_info); + if (prog_info != NULL) + break; + } + + } + + /* + * if - Program Info + */ + /* + * prints program info data text + */ + gmyth_debug("New ProgramInfo...\n"); + gmyth_program_info_print(prog_info); + + /* + * check if the program chain could be obtained from the MythTV + * protocol message + */ + if (prog_info != NULL) { + gmyth_backend_info_set_username(livetv->tvchain->backend_info, + "mythtv"); + gmyth_backend_info_set_password(livetv->tvchain->backend_info, + "mythtv"); + gmyth_backend_info_set_db_name(livetv->tvchain->backend_info, + "mythconverg"); + GList *prog_list = + gmyth_tvchain_get_program_info_from_channel(livetv->tvchain, + channel); + GMythProgramInfo *ch_prog = NULL; + + if (prog_list != NULL && g_list_length(prog_list) > 0) { + ch_prog = (GMythProgramInfo *) g_list_nth_data(prog_list, 0); + gmyth_debug + ("Channel program info (from a list with size = %d)!", + g_list_length(prog_list)); + gmyth_program_info_print(ch_prog); + } + + gmyth_debug("Program Info: %s\n", + gmyth_program_info_to_string(prog_info)); + livetv->proginfo = prog_info; + /* + * testing change channel + */ + // gmyth_recorder_spawntv_no_tvchain( livetv->recorder ); + } else { + + /* + * check for the program info in the TV program chain could be + * obtained from the MythTV MySQL database + */ + + /* + * Reload all TV chain from Mysql database. + */ + gmyth_tvchain_reload_all(livetv->tvchain); + + if (livetv->tvchain == NULL) { + res = FALSE; + goto error; + } + + /* + * Get program info from database using chanid and starttime + */ + livetv->proginfo = + gmyth_tvchain_get_program_at(livetv->tvchain, + tvchain_curr_index++); + if (livetv->proginfo == NULL) { + gmyth_debug("LiveTV not successfully started.\n"); + res = FALSE; + goto error; + } else { + res = TRUE; + gmyth_debug + ("GMythLiveTV: All requests to backend to start TV were OK. [%s]\n", + livetv->proginfo->pathname->str); + } + + } + + livetv->uri = + (GMythURI *) gmyth_backend_info_get_uri(livetv->backend_info); + + g_mutex_unlock(livetv->mutex); + + if (!gmyth_livetv_monitor_handler_start(livetv)) { + res = FALSE; + gmyth_debug("LiveTV MONITOR handler error on setup!"); + goto error; + } + + livetv->setup_done = TRUE; + + return res; + + error: + g_mutex_unlock(livetv->mutex); + + gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__); + + res = FALSE; + + if (livetv->local_hostname != NULL) { + g_string_free(livetv->local_hostname, TRUE); + livetv->local_hostname = NULL; + } + + gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__); + + if (livetv->recorder != NULL) { + g_object_unref(livetv->recorder); + livetv->recorder = NULL; + } + + gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__); + + if (livetv->tvchain != NULL) { + g_object_unref(livetv->tvchain); + livetv->tvchain = NULL; + } + + gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__); + + if (livetv->proginfo != NULL) { + g_object_unref(livetv->proginfo); + livetv->proginfo = NULL; + } + + gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__); + + if (livetv->monitor != NULL) { + g_object_unref(livetv->monitor); + livetv->monitor = NULL; + } + + + gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__); + + return res; + +} + +/** + * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, + * sets the channel name, and gets the first program info about the + * actual recording + * + * @param live_tv the GMythLiveTV instance + * @param channel the channel name, in numerical format + * @param backend_info the GMythBackendInfo describing the remote server + * + * @return true if the LiveTV's recorder instance configuration + * had been concluded succcesfully + */ +static gboolean +gmyth_livetv_setup_recorder(GMythLiveTV * livetv, gint channel) +{ + return gmyth_livetv_setup_recorder_channel_name(livetv, + (channel != + -1) ? + g_strdup_printf("%d", + channel) + : NULL); +} + +/** + * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, + * sets the channel name (numerical format), and gets the first program info about the + * actual recording + * + * @param live_tv the GMythLiveTV instance + * @param channel the channel name, in numerical format + * @param backend_info the GMythBackendInfo describing the remote server + * + * @return true if the LiveTV's recorder instance configuration + * had been concluded succcesfully + */ +gboolean +gmyth_livetv_channel_setup(GMythLiveTV * livetv, gint channel) +{ + return gmyth_livetv_setup_recorder(livetv, channel); +} + +/** + * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, + * sets the channel name (string format), and gets the first program info about the + * actual recording + * + * @param live_tv the GMythLiveTV instance + * @param channel the channel name, in numerical format + * @param backend_info the GMythBackendInfo describing the remote server + * + * @return true if the LiveTV's recorder instance configuration + * had been concluded succcesfully + */ +gboolean +gmyth_livetv_channel_name_setup(GMythLiveTV * livetv, gchar * channel) +{ + return gmyth_livetv_setup_recorder_channel_name(livetv, channel); +} + +/** + * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, + * and gets the first program info about the actual recording + * (doesn't changes the channel). + * + * @param live_tv the GMythLiveTV instance + * @param backend_info the GMythBackendInfo describing the remote server + * + * @return true if the LiveTV's recorder instance configuration + * had been concluded succcesfully + */ +gboolean +gmyth_livetv_setup(GMythLiveTV * livetv) +{ + return gmyth_livetv_setup_recorder(livetv, -1); +} + +/** + * Gets the next program info from this GMythLiveTV session. + * + * @param live_tv the GMythLiveTV instance + * + * @return true if the next program info could be got + */ +gboolean +gmyth_livetv_next_program_chain(GMythLiveTV * livetv) +{ + gboolean res = TRUE; + GMythProgramInfo *prog_info = NULL; + + if (!livetv->setup_done) { + gmyth_debug("Call the setup function first!"); + goto error; + } + + gmyth_debug("Current ProgramInfo...\n"); + prog_info = gmyth_recorder_get_current_program_info(livetv->recorder); + + if (prog_info != NULL) { + livetv->proginfo = prog_info; + } else { + gmyth_debug + ("ProgramInfo equals to NULL!!! Getting the next program info..."); + prog_info = + gmyth_recorder_get_next_program_info(livetv->recorder, + BROWSE_DIRECTION_RIGHT); + livetv->proginfo = prog_info; + } + /* + * prints program info data text + */ + gmyth_program_info_print(prog_info); + + if (prog_info != NULL) { + res = TRUE; + livetv->proginfo = prog_info; + gmyth_debug + ("GMythLiveTV: All requests to backend to start TV were OK, program info changed."); + } else { + gmyth_debug + ("[%s] LiveTV not successfully started on the next program chain.\n", + __FUNCTION__); + goto error; + } + + livetv->setup_done = TRUE; + + return res; + + error: + gmyth_debug("ERROR running LiveTV setup.\n"); + + res = FALSE; + + g_string_free(livetv->local_hostname, TRUE); + + if (livetv->recorder != NULL) { + g_object_unref(livetv->recorder); + livetv->recorder = NULL; + } + + if (livetv->tvchain != NULL) { + g_object_unref(livetv->tvchain); + livetv->tvchain = NULL; + } + + if (livetv->proginfo != NULL) { + g_object_unref(livetv->proginfo); + livetv->proginfo = NULL; + } + + return res; +} + +/** + * Creates a File Transfer session, using all configuration information + * got from the actual program info. + * + * @param live_tv the GMythLiveTV instance + * + * @return the actual GMythFileTransfer instance, generated using the + * data got from the actual program info. + */ +GMythFile* +gmyth_livetv_create_file_transfer(GMythLiveTV * livetv) +{ + // GMythURI* uri = NULL; + + if (NULL == livetv) + return NULL; + + if (!livetv->setup_done) { + gmyth_debug + ("Error: You must do the LiveTV setup, just before generating the FileTransfer from LiveTV source!"); + return NULL; + } + + if (livetv->proginfo != NULL) + gmyth_debug("URI path (from program info) = %s.\n", + livetv->proginfo->pathname->str); + else + gmyth_debug("URI path (from URI) = %s.\n", livetv->uri->uri->str); + + g_mutex_lock(livetv->mutex); + + if (livetv->file != NULL) { + /* + * gmyth_file_transfer_close( livetv->file ); + */ + g_object_unref(livetv->file); + livetv->file = NULL; + } + + if (livetv->uri != NULL) { + gmyth_debug + ("URI is not NULL, creating from the ProgramInfo pathname... (%s)", + livetv->proginfo->pathname->str); + livetv->uri->path = g_string_erase(livetv->uri->path, 0, -1); + livetv->uri->path = + g_string_new(g_strrstr(livetv->proginfo->pathname->str, "/")); + } else { + gmyth_debug + ("URI is NULL, creating from the ProgramInfo pathname... (%s)", + livetv->proginfo->pathname->str); + livetv->uri = + gmyth_uri_new_with_value(livetv->proginfo->pathname->str); + } + + if (NULL == livetv->uri) { + gmyth_debug("Couldn't parse the URI to start LiveTV! [ uri = %s ]", + livetv->proginfo->pathname->str); + goto done; + } + + if (gmyth_uri_is_local_file(livetv->uri)) + livetv->file = + GMYTH_FILE(gmyth_file_local_new(livetv->backend_info)); + else { + livetv->file = + GMYTH_FILE(gmyth_file_transfer_new(livetv->backend_info)); + /* + * gmyth_file_transfer_settimeout( + * GMYTH_FILE_TRANSFER(livetv->file), TRUE ); + */ + } + + if (NULL == livetv->file) { + gmyth_debug + ("Error: couldn't create the FileTransfer from LiveTV source!"); + goto done; + } + + g_object_ref(livetv->file); + +done: + g_mutex_unlock(livetv->mutex); + return livetv->file; +} + +/** + * Stops this LiveTV session. + * + * @param live_tv the GMythLiveTV instance + */ +void +gmyth_livetv_stop_playing(GMythLiveTV * livetv) +{ + gmyth_debug("Stopping the LiveTV...\n"); + + if (livetv->is_livetv) { + if (!gmyth_recorder_stop_livetv(livetv->recorder)) { + gmyth_debug("[%s] Error while stoping remote encoder", + __FUNCTION__); + } + + if (!gmyth_recorder_finish_recording(livetv->recorder)) { + gmyth_debug + ("[%s] Error while finishing recording on remote encoder", + __FUNCTION__); + } + } +} + +gboolean +gmyth_livetv_is_playing(GMythLiveTV * livetv) +{ + return TRUE; +} + +void +gmyth_livetv_start_playing(GMythLiveTV * livetv) +{ + + // TODO + +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_livetv.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_livetv.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,103 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_livetv.h + * + * @brief

GMythLiveTV starts a remote TV session with the MythTV backend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef GMYTH_LIVETV_H_ +#define GMYTH_LIVETV_H_ + +#include +#include + +#include "gmyth_recorder.h" +#include "gmyth_tvchain.h" +#include "gmyth_monitor_handler.h" +#include "gmyth_file.h" +#include "gmyth_programinfo.h" +#include "gmyth_backendinfo.h" + +G_BEGIN_DECLS +#define GMYTH_LIVETV_TYPE (gmyth_livetv_get_type ()) +#define GMYTH_LIVETV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_LIVETV_TYPE, GMythLiveTV)) +#define GMYTH_LIVETV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_LIVETV_TYPE, GMythLiveTVClass)) +#define IS_GMYTH_LIVETV(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_LIVETV_TYPE)) +#define IS_GMYTH_LIVETV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_LIVETV_TYPE)) +#define GMYTH_LIVETV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_LIVETV_TYPE, GMythLiveTVClass)) +typedef struct _GMythLiveTV GMythLiveTV; +typedef struct _GMythLiveTVClass GMythLiveTVClass; + +struct _GMythLiveTVClass { + GObjectClass parent_class; + + /* + * callbacks + */ +}; + +struct _GMythLiveTV { + GObject parent; + + GMythSocket *socket; + + GString *local_hostname; + + GMythBackendInfo *backend_info; + + GMythRecorder *recorder; + GMythTVChain *tvchain; + GMythProgramInfo *proginfo; + + GMythFile *file; + + GMythMonitorHandler *monitor; + GMythURI *uri; + + gboolean is_livetv; + gboolean setup_done; + + GMutex *mutex; + gboolean disposed; +}; + +GType gmyth_livetv_get_type(void); + +GMythLiveTV *gmyth_livetv_new(GMythBackendInfo * backend_info); + +void gmyth_livetv_start_playing(GMythLiveTV * livetv); +void gmyth_livetv_stop_playing(GMythLiveTV * livetv); + +gboolean gmyth_livetv_setup(GMythLiveTV * livetv); +gboolean gmyth_livetv_channel_setup(GMythLiveTV * livetv, + gint channel); +gboolean gmyth_livetv_channel_name_setup(GMythLiveTV * livetv, + gchar * channel); +gboolean gmyth_livetv_next_program_chain(GMythLiveTV * livetv); + +GMythFile *gmyth_livetv_create_file_transfer(GMythLiveTV * livetv); + +gboolean gmyth_livetv_monitor_handler_start(GMythLiveTV * livetv); +void gmyth_livetv_monitor_handler_stop(GMythLiveTV * livetv); + +G_END_DECLS +#endif /* GMYTH_LIVETV_H_ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_marshal.list --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_marshal.list Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,2 @@ +VOID:INT,STRING +VOID:INT,POINTER diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_monitor_handler.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_monitor_handler.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,593 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_monitor_handler.c + * + * @brief

GMythMonitorHandler deals with the streaming media events remote/local + * that are sent to the MythTV frontend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * GStreamer MythTV plug-in properties: + * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv] + * - path (qurl - remote file to be opened) + * - port number * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gmyth_marshal.h" + +#include "gmyth_monitor_handler.h" +#include "gmyth_debug.h" + +#define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER " + +#define GMYTHTV_VERSION 30 + +#define GMYTHTV_TRANSFER_MAX_WAITS 700 + +#define GMYTHTV_BUFFER_SIZE 8*1024 + +#ifdef GMYTHTV_ENABLE_DEBUG +#define GMYTHTV_ENABLE_DEBUG 1 +#else +#undef GMYTHTV_ENABLE_DEBUG +#endif + +/* + * this NDEBUG is to maintain compatibility with GMyth library + */ +#ifndef NDEBUG +#define GMYTHTV_ENABLE_DEBUG 1 +#endif + +static gboolean gmyth_monitor_handler_listener (GIOChannel *io_channel, + GIOCondition condition, + gpointer data); + +static void gmyth_monitor_handler_default_listener(GMythMonitorHandler + * monitor, + gint msg_code, + gchar * message); + +static void gmyth_monitor_handler_class_init(GMythMonitorHandlerClass * + klass); +static void gmyth_monitor_handler_init(GMythMonitorHandler * object); + +static void gmyth_monitor_handler_dispose(GObject * object); +static void gmyth_monitor_handler_finalize(GObject * object); + +static gboolean gmyth_connect_to_backend_monitor(GMythMonitorHandler * + monitor); + +static gboolean gmyth_monitor_handler_setup(GMythMonitorHandler * monitor, + GIOChannel * channel); + +void gmyth_monitor_handler_close(GMythMonitorHandler * monitor); + +G_DEFINE_TYPE(GMythMonitorHandler, gmyth_monitor_handler, G_TYPE_OBJECT); + +static void +gmyth_monitor_handler_class_init(GMythMonitorHandlerClass * klass) +{ + GObjectClass *gobject_class; + GMythMonitorHandlerClass *gmonitor_class; + + gobject_class = (GObjectClass *) klass; + gmonitor_class = (GMythMonitorHandlerClass *) gobject_class; + + gobject_class->dispose = gmyth_monitor_handler_dispose; + gobject_class->finalize = gmyth_monitor_handler_finalize; + + gmonitor_class->backend_events_handler_signal_id = + g_signal_new("backend-events-handler", + G_TYPE_FROM_CLASS(gmonitor_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | + G_SIGNAL_NO_HOOKS, 0, NULL, NULL, + gmyth_marshal_VOID__INT_STRING, G_TYPE_NONE, 2, + G_TYPE_INT, G_TYPE_STRING); + + gmonitor_class->backend_events_handler = + gmyth_monitor_handler_default_listener; + +} + +static void +gmyth_monitor_handler_init(GMythMonitorHandler * monitor) +{ + g_return_if_fail(monitor != NULL); + + monitor->event_sock = NULL; + monitor->hostname = NULL; + monitor->port = 0; + monitor->actual_index = 0; + monitor->allow_msgs_listener = FALSE; + /* + * it is used for signalizing the event socket consumer thread + */ + monitor->mutex = g_mutex_new(); +} + +static void +gmyth_monitor_handler_dispose(GObject * object) +{ + GMythMonitorHandler *monitor = GMYTH_MONITOR_HANDLER(object); + + gmyth_monitor_handler_close(monitor); + + monitor->allow_msgs_listener = FALSE; + + if (monitor->io_source != 0) { + g_source_remove (monitor->io_source); + monitor->io_source = 0; + } + + /* + * mutex to control access to the event socket consumer thread + */ + if (monitor->mutex != NULL) { + // g_mutex_unlock( monitor->mutex ); + g_mutex_free(monitor->mutex); + monitor->mutex = NULL; + } + + if (monitor->event_sock != NULL) { + g_object_unref(monitor->event_sock); + monitor->event_sock = NULL; + } + + if (monitor->hostname != NULL) { + g_free(monitor->hostname); + monitor->hostname = NULL; + } + + + if (monitor->backend_msgs != NULL) { + g_hash_table_destroy(monitor->backend_msgs); + monitor->backend_msgs = NULL; + } + + /* + * if ( io_watcher_cond != NULL ) { g_cond_free( io_watcher_cond ); + * io_watcher_cond = NULL; } + */ + + + G_OBJECT_CLASS(gmyth_monitor_handler_parent_class)->dispose(object); +} + +static void +gmyth_monitor_handler_finalize(GObject * object) +{ + g_signal_handlers_destroy(object); + + G_OBJECT_CLASS(gmyth_monitor_handler_parent_class)->finalize(object); +} + +/** + * Creates a new instance of GMyth Monitor Handler. + * + * @return a new instance of the Monitor Handler. + */ +GMythMonitorHandler * +gmyth_monitor_handler_new(void) +{ + GMythMonitorHandler *monitor = + GMYTH_MONITOR_HANDLER(g_object_new + (GMYTH_MONITOR_HANDLER_TYPE, FALSE)); + + return monitor; +} + +/** + * Acquire the mutex to have access to the IO Watcher listener. + * + * @param monitor The GMythMonitorHandler instance. + * @param do_wait Tells the IO Watcher to wait on the GCond. (obsolete) + * + * @return true, if the access to IO Watcher was acquired. + */ +static gboolean +myth_control_acquire_context(GMythMonitorHandler * monitor, + gboolean do_wait) +{ + + gboolean ret = TRUE; + + g_mutex_lock(monitor->mutex); + + return ret; + +} + +/** + * Release the mutex to have access to the IO Watcher listener. + * + * @param monitor The GMythMonitorHandler instance. + * + * @return true, if the access to IO Watcher was released. + */ +static gboolean +myth_control_release_context(GMythMonitorHandler * monitor) +{ + + gboolean ret = TRUE; + + g_mutex_unlock(monitor->mutex); + + return ret; +} + +void +gmyth_monitor_handler_close(GMythMonitorHandler * monitor) +{ + monitor->allow_msgs_listener = FALSE; + +#if 0 + if (monitor->monitor_th != NULL) { + g_thread_pool_free(monitor->monitor_th, TRUE, FALSE); + // g_thread_exit( monitor->monitor_th ); + /* + * if ( monitor->monitor_th != NULL ) g_object_unref( + * monitor->monitor_th ); + */ + monitor->monitor_th = NULL; + } + + if (monitor->event_sock != NULL) { + gmyth_socket_close_connection(monitor->event_sock); + } +#endif + +} + +/** + * Opens connection the the Monitor socket on MythTV backend server, + * where all status messages are notified to the client. + * + * @param monitor The GMythMonitorHandler instance. + * @param hostname The remote host name of the MythTV backend server. + * @param port The remote port number of the MythTV backend server. + * + * @return true, if the connection was successfully opened. + */ +gboolean +gmyth_monitor_handler_open(GMythMonitorHandler * monitor, + const gchar * hostname, gint port) +{ + gboolean ret = TRUE; + + g_return_val_if_fail(hostname != NULL, FALSE); + + if (monitor->hostname != NULL) { + g_free(monitor->hostname); + monitor->hostname = NULL; + } + + monitor->hostname = g_strdup(hostname); + monitor->port = port; + + gmyth_debug("Monitor event socket --- hostname: %s, port %d\n", + monitor->hostname, monitor->port); + + if (monitor->event_sock != NULL) { + g_object_unref(monitor->event_sock); + monitor->event_sock = NULL; + } + + /* + * configure the event socket + */ + if (!gmyth_connect_to_backend_monitor(monitor)) { + gmyth_debug("Connection to backend failed (Event Socket)!"); + ret = FALSE; + } else { + gmyth_debug ("Remote monitor event socket had been succesfully create"); + } + + return ret; +} + +/** + * Reads the data got from the connection to the Monitor socket, + * and looks for some important status messages. + * + * @param monitor The GMythMonitorHandler instance. + * @param strlist The GMythStringList instance got from the Monitor remote socket. + * @param back_msg_action A string pointer to the status message detailed description. + * + * @return The backend status message code ID. + */ +static gint +gmyth_monitor_handler_is_backend_message(GMythMonitorHandler * monitor, + GMythStringList * strlist, + gchar ** back_msg_action) +{ + gint msg_type = GMYTH_BACKEND_NO_MESSAGE; + GString *back_msg = NULL; + + if (gmyth_string_list_length(strlist) > 0) { + + back_msg = gmyth_string_list_get_string(strlist, 0); + if (back_msg != NULL && back_msg->str != NULL && + strstr(back_msg->str, "BACKEND") != NULL) { + gmyth_debug("MONITOR HANDLER - Received backend message = %s", + back_msg->str); + *back_msg_action = + gmyth_string_list_get_char_array(strlist, 1); + + if (back_msg_action != NULL) { + + if (g_strstr_len + (*back_msg_action, strlen(*back_msg_action), + "LIVETV_CHAIN") + || g_strstr_len(*back_msg_action, + strlen(*back_msg_action), + "RECORDING_LIST_CHANGE") + || g_strstr_len(*back_msg_action, + strlen(*back_msg_action), + "SCHEDULE_CHANGE") + || g_strstr_len(*back_msg_action, + strlen(*back_msg_action), + "LIVETV_WATCH")) { + gmyth_debug + ("MONITOR: message type == GMYTH_BACKEND_PROGRAM_INFO_CHANGED, msg = %s", + *back_msg_action); + msg_type = GMYTH_BACKEND_PROGRAM_INFO_CHANGED; + } else if (g_strstr_len + (*back_msg_action, strlen(*back_msg_action), + "DONE_RECORDING")) { + gmyth_debug + ("MONITOR: message type == GMYTH_BACKEND_DONE_RECORDING, msg = %s", + *back_msg_action); + msg_type = GMYTH_BACKEND_DONE_RECORDING; + } else if (g_strstr_len + (*back_msg_action, strlen(*back_msg_action), + "QUIT")) { + gmyth_debug + ("MONITOR: message type == GMYTH_BACKEND_STOP_LIVETV, msg = %s", + *back_msg_action); + msg_type = GMYTH_BACKEND_STOP_LIVETV; + } + + /* + * g_hash_table_insert ( monitor->backend_msgs, + * &(monitor->actual_index), *back_msg_action ); + */ + + } + /* + * if + */ + } + /* + * if + */ + if (back_msg != NULL) { + g_string_free(back_msg, TRUE); + back_msg = NULL; + } + + } /* if - Does Monitor got any message from + * * * backend? */ + else { + *back_msg_action = g_strdup(""); + } + + return msg_type; + +} + +static void +gmyth_monitor_handler_default_listener(GMythMonitorHandler * monitor, + gint msg_code, gchar * message) +{ + // assert( message!= NULL ); + gmyth_debug("DEFAULT Signal handler ( msg = %s, code = %d )\n", + message, msg_code); +} + +static void +gmyth_monitor_handler_print(GString * str, gpointer ptr) +{ + gmyth_debug("Backend message event: %s --- ", str->str); +} + +/** + * Opens connection the the Monitor socket on MythTV backend server, + * where all status messages are notified to the client. + * + * @param data Pointer to the GMythMonitorHandler. + * + * @return Pointer to a gboolean true value, if the data was + * successfully read. + */ +static gboolean +gmyth_monitor_handler_listener (GIOChannel *io_channel, + GIOCondition io_cond, + gpointer data) +{ + GMythMonitorHandler *monitor; + guint recv = 0; + gsize len = 0; + GMythStringList *strlist = NULL; + gint bytes_sent = 0; + + monitor = (GMythMonitorHandler *) data; + + gmyth_debug("Entering MONITOR handler listener..."); + + myth_control_acquire_context(monitor, TRUE); + + if (((io_cond & G_IO_HUP) != 0) || + ((io_cond & G_IO_ERR) != 0)) { + goto clean_up; + } + + + gmyth_debug("Listening on Monitor socket...!\n"); + strlist = gmyth_string_list_new(); + + len = gmyth_socket_read_stringlist(monitor->event_sock, strlist); + if ((len > 0) && strlist != NULL && gmyth_string_list_length(strlist) > 0) { + gchar *back_msg_action; + gint msg_type; + + bytes_sent = gmyth_string_list_get_int(strlist, 0); + // on backend error + gmyth_debug ("received data buffer from IO event channel... %d strings gone!\n", len); + recv += len; + + /* + * debug purpose: prints out all the string list + * elements + */ + g_list_foreach(strlist->glist, + (GFunc) gmyth_monitor_handler_print, + NULL); + + back_msg_action = g_new0(gchar, 1); + msg_type = gmyth_monitor_handler_is_backend_message(monitor, + strlist, + &back_msg_action); + + if (msg_type != GMYTH_BACKEND_NO_MESSAGE) { + g_signal_emit(monitor, + GMYTH_MONITOR_HANDLER_GET_CLASS(monitor)->backend_events_handler_signal_id, + 0, msg_type, back_msg_action); + } + + if (back_msg_action != NULL) + g_free(back_msg_action); + + g_object_unref(strlist); + } + +clean_up: + myth_control_release_context(monitor); + return TRUE; +} + +/** + * Opens connection events' socket the the Monitor socket on + * MythTV backend server. + * + * @param monitor The GMythMonitorHandler instance. + * + * @return true, if the socket was successfully opened. + */ +static gboolean +gmyth_connect_to_backend_monitor(GMythMonitorHandler * monitor) +{ + gboolean ret = TRUE; + + monitor->event_sock = gmyth_socket_new(); + + /* + * Connects the socket, send Mythtv ANN Monitor and verify Mythtv + * protocol version + */ + if (!gmyth_socket_connect_to_backend_events(monitor->event_sock, + monitor->hostname, + monitor->port, FALSE)) { + g_object_unref(monitor->event_sock); + monitor->event_sock = NULL; + ret = FALSE; + } + + return ret; +} + +/** + * Opens connection the the Monitor socket on MythTV backend server, + * where all status messages are notified to the client. + * + * @param monitor The GMythMonitorHandler instance. + * @param channel The GIOChannel instance to the Monitor socket. + * + * @return Pointer to the boolean value, and it is true only if the + * GMythMonitorHandler could be configured. + */ +static gboolean +gmyth_monitor_handler_setup(GMythMonitorHandler * monitor, + GIOChannel * channel) +{ + gboolean ret = TRUE; + + if (channel != NULL) { + monitor->allow_msgs_listener = TRUE; + monitor->io_source = g_io_add_watch (channel, G_IO_IN | G_IO_ERR | G_IO_HUP, + gmyth_monitor_handler_listener, + monitor); + } else { + ret = FALSE; + } + return ret; +} + +/** + * Starts the MonitorHandler thread to the GIOWatcher. + * + * @param monitor The GMythMonitorHandler instance. + * + * @return true, if the MonitorHandler was started. + */ +gboolean +gmyth_monitor_handler_start(GMythMonitorHandler * monitor) +{ + gboolean ret = TRUE; + + if (!(ret = g_thread_supported())) { + gmyth_debug("Thread system wasn't initialized, starting NOW!!!"); + g_thread_init(NULL); + } + + ret = + gmyth_monitor_handler_setup(monitor, + monitor->event_sock->sd_io_ch); + if (ret) { + gmyth_debug + ("\n[%s]\tOK! Starting listener on the MONITOR event socket...[thread location = %p]\n", + __FUNCTION__, g_thread_self()); + } else { + gmyth_debug + ("\n[%s]\tERROR! Coudn't start listener on the MONITOR event socket...[thread location = %p]\n", + __FUNCTION__, g_thread_self()); + ret = FALSE; + } + + gmyth_debug + ("[%s] Watch listener function over the IO control channel? %s!!!\n", + __FUNCTION__, (ret == TRUE ? "YES" : "NO")); + + return ret; +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_monitor_handler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_monitor_handler.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,122 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_monitor_handler.h + * + * @brief

GMythMonitorHandler deals with the streaming media events remote/local + * that are sent to the MythTV frontend. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_MONITOR_HANDLER_H__ +#define __GMYTH_MONITOR_HANDLER_H__ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "gmyth_socket.h" +#include "gmyth_uri.h" + +G_BEGIN_DECLS +#define GMYTH_MONITOR_HANDLER_TYPE (gmyth_monitor_handler_get_type ()) +#define GMYTH_MONITOR_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_MONITOR_HANDLER_TYPE, GMythMonitorHandler)) +#define GMYTH_MONITOR_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_MONITOR_HANDLER_TYPE, GMythMonitorHandlerClass)) +#define IS_GMYTH_MONITOR_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_MONITOR_HANDLER_TYPE)) +#define IS_GMYTH_MONITOR_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_MONITOR_HANDLER_TYPE)) +#define GMYTH_MONITOR_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_MONITOR_HANDLER_TYPE, GMythMonitorHandlerClass)) +#define GMYTHTV_MONITOR_HANDLER_READ_ERROR -314 + enum { + GMYTH_BACKEND_NO_MESSAGE = 0, + GMYTH_BACKEND_PROGRAM_INFO_CHANGED, + GMYTH_BACKEND_DONE_RECORDING, + GMYTH_BACKEND_STOP_LIVETV +}; + +typedef struct _GMythMonitorHandler GMythMonitorHandler; +typedef struct _GMythMonitorHandlerClass GMythMonitorHandlerClass; + +struct _GMythMonitorHandlerClass { + GObjectClass parent_class; + + /* + * callbacks + */ + guint backend_events_handler_signal_id; + + /* + * signal default handlers + */ + void (*backend_events_handler) (GMythMonitorHandler * + monitor, gint msg_code, + gchar * message); +}; + +struct _GMythMonitorHandler { + GObject parent; + + /* + * MythTV version number + */ + gint mythtv_version; + + /* + * socket descriptors + */ + GMythSocket *event_sock; + + //gpointer(*gmyth_monitor_handler_listener) (gpointer data); + + gchar *hostname; + gint port; + + gint64 actual_index; + + gboolean allow_msgs_listener; + + /* + * stores the messages coming from the backend + */ + GHashTable *backend_msgs; + + GMutex *mutex; + guint io_source; +}; + +GType gmyth_monitor_handler_get_type(void); + +GMythMonitorHandler *gmyth_monitor_handler_new(void); + +gboolean gmyth_monitor_handler_open(GMythMonitorHandler * monitor, + const gchar * hostname, + gint port); + +gboolean gmyth_monitor_handler_start(GMythMonitorHandler * monitor); + +void gmyth_monitor_handler_close(GMythMonitorHandler * monitor); + +G_END_DECLS +#endif /* __GMYTH_MONITOR_HANDLER_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_programinfo.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_programinfo.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,582 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_programinfo.c + * + * @brief

GMythProgramInfo representing the program info, with the + * configuration data to the actual remote file in the TV chain. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Borges + * @author Leonardo Sobral Cunha + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "gmyth_programinfo.h" +#include "gmyth_util.h" +#include "gmyth_debug.h" + +static void gmyth_program_info_class_init(GMythProgramInfoClass * + klass); +static void gmyth_program_info_init(GMythProgramInfo * object); + +static void gmyth_program_info_dispose(GObject * object); +static void gmyth_program_info_finalize(GObject * object); + +G_DEFINE_TYPE(GMythProgramInfo, gmyth_program_info, G_TYPE_OBJECT) + static const gchar *gmyth_program_info_non_null_value(const GString * + str); + + static void gmyth_program_info_class_init(GMythProgramInfoClass * + klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->dispose = gmyth_program_info_dispose; + gobject_class->finalize = gmyth_program_info_finalize; +} + +static void +gmyth_program_info_init(GMythProgramInfo * gmyth_program_info) +{ + gmyth_program_info->chancommfree = 0; + + /** A flag informing if the program has video or not. */ + gmyth_program_info->isVideo = FALSE; + gmyth_program_info->lenMins = 0; + + gmyth_program_info->stars = 0.0f; + gmyth_program_info->repeat = 0; + + gmyth_program_info->hasAirDate = FALSE; + + gmyth_program_info->spread = 0; + gmyth_program_info->startCol = 0; + + gmyth_program_info->recpriority2 = 0; + gmyth_program_info->reactivate = 0; + + gmyth_program_info->recordid = 0; + gmyth_program_info->parentid = 0; + + /** The backend video source id associated to this program.*/ + gmyth_program_info->sourceid = 0; + /** the backend input id associated to this program.*/ + gmyth_program_info->inputid = 0; + /** The backend card id associated to this program.*/ + gmyth_program_info->cardid = 0; + gmyth_program_info->shareable = FALSE; + gmyth_program_info->duplicate = FALSE; + + gmyth_program_info->findid = 0; + + gmyth_program_info->programflags = 0; + gmyth_program_info->transcoder = 0; + + gmyth_program_info->recpriority = 0; + + /** The file size of the recorded program.*/ + gmyth_program_info->filesize = -1; +} + +static void +gmyth_program_info_dispose(GObject * object) +{ + GMythProgramInfo *gmyth_program_info = GMYTH_PROGRAM_INFO(object); + + /** The program start time. */ + g_free(gmyth_program_info->startts); + + /** The program end time. */ + g_free(gmyth_program_info->endts); + + /** The recording schedule start time. */ + g_free(gmyth_program_info->recstartts); + + /** The recording schedule end time */ + g_free(gmyth_program_info->recendts); + + /** The program title. */ + if (gmyth_program_info->title != NULL) { + g_string_free(gmyth_program_info->title, TRUE); + gmyth_program_info->title = NULL; + } + + /** The program subtitle. */ + if (gmyth_program_info->subtitle != NULL) { + g_string_free(gmyth_program_info->subtitle, TRUE); + gmyth_program_info->subtitle = NULL; + } + + /** The program description. */ + if (gmyth_program_info->description != NULL) { + g_string_free(gmyth_program_info->description, TRUE); + gmyth_program_info->description = NULL; + } + + /** The program category. */ + if (gmyth_program_info->category != NULL) { + g_string_free(gmyth_program_info->category, TRUE); + gmyth_program_info->category = NULL; + } + + if (gmyth_program_info->chanstr != NULL) { + g_string_free(gmyth_program_info->chanstr, TRUE); + gmyth_program_info->chanstr = NULL; + } + + if (gmyth_program_info->chansign != NULL) { + g_string_free(gmyth_program_info->chansign, TRUE); + gmyth_program_info->chansign = NULL; + } + + /** The associated channel name. */ + if (gmyth_program_info->channame != NULL) { + g_string_free(gmyth_program_info->channame, TRUE); + gmyth_program_info->channame = NULL; + } + + if (gmyth_program_info->chanOutputFilters != NULL) { + g_string_free(gmyth_program_info->chanOutputFilters, TRUE); + gmyth_program_info->chanOutputFilters = NULL; + } + + if (gmyth_program_info->seriesid != NULL) { + g_string_free(gmyth_program_info->seriesid, TRUE); + gmyth_program_info->chanOutputFilters = NULL; + } + + /** The program unique id. */ + if (gmyth_program_info->program_id != NULL) { + g_string_free (gmyth_program_info->program_id, TRUE); + gmyth_program_info->program_id = NULL; + } + + if (gmyth_program_info->catType != NULL) { + g_string_free(gmyth_program_info->catType, TRUE); + gmyth_program_info->catType = NULL; + } + + if (gmyth_program_info->sortTitle != NULL) { + g_string_free(gmyth_program_info->sortTitle, TRUE); + gmyth_program_info->sortTitle = NULL; + } + + if (gmyth_program_info->year != NULL) { + g_string_free(gmyth_program_info->year, TRUE); + gmyth_program_info->year = NULL; + } + + g_free(gmyth_program_info->originalAirDate); + + g_free(gmyth_program_info->lastmodified); + + g_free(gmyth_program_info->lastInUseTime); + + if (gmyth_program_info->schedulerid != NULL) { + g_string_free(gmyth_program_info->schedulerid, TRUE); + gmyth_program_info->schedulerid = NULL; + } + + if (gmyth_program_info->recgroup != NULL) { + g_string_free(gmyth_program_info->recgroup, TRUE); + gmyth_program_info->recgroup = NULL; + } + + if (gmyth_program_info->playgroup != NULL) { + g_string_free(gmyth_program_info->playgroup, TRUE); + gmyth_program_info->playgroup = NULL; + } + + /** The file name of the recorded program.*/ + if (gmyth_program_info->pathname != NULL) { + g_string_free(gmyth_program_info->pathname, TRUE); + gmyth_program_info->pathname = NULL; + } + + if (gmyth_program_info->hostname != NULL) { + g_string_free(gmyth_program_info->hostname, TRUE); + gmyth_program_info->hostname = NULL; + } + + G_OBJECT_CLASS(gmyth_program_info_parent_class)->dispose(object); +} + +static void +gmyth_program_info_finalize(GObject * object) +{ + g_signal_handlers_destroy(object); + + G_OBJECT_CLASS(gmyth_program_info_parent_class)->finalize(object); +} + +/** + * Creates a new instance of GMythProgramInfo. + * + * @return a new instance of GMythProgramInfo. + */ +GMythProgramInfo * +gmyth_program_info_new(void) +{ + GMythProgramInfo *program_info = + GMYTH_PROGRAM_INFO(g_object_new(GMYTH_PROGRAM_INFO_TYPE, NULL)); + + return program_info; +} + +/** + * Converts an instance of a GMythProgramInfo, to a GMythStringList. + * + * @param prog A GMythProgramInfo instance. + * @param slist The GMythStringList to be passed to this function, in order to + * give the responsibility of the string list creation to the + * API user. + * + * @return a GMythStringList with the program info fields. + */ +GMythStringList * +gmyth_program_info_to_string_list(GMythProgramInfo * prog, + GMythStringList * slist) +{ + g_return_val_if_fail(prog != NULL, NULL); + g_return_val_if_fail(slist != NULL, NULL); + + gmyth_string_list_append_string(slist, prog->title); /* 0 */ + gmyth_string_list_append_string(slist, prog->subtitle); /* 1 */ + gmyth_string_list_append_string(slist, prog->description); /* 2 */ + gmyth_string_list_append_string(slist, prog->category); /* 3 */ + gmyth_string_list_append_int (slist, prog->channel_id); /* 4 */ + gmyth_string_list_append_string(slist, prog->chanstr); /* 5 */ + gmyth_string_list_append_string(slist, prog->chansign); /* 6 */ + gmyth_string_list_append_string(slist, prog->channame); /* 7 */ + gmyth_string_list_append_string(slist, prog->pathname); /* 8 */ + gmyth_string_list_append_int64(slist, 0); /* 9 */ + + // fixme + // gmyth_string_list_append_int64 (slist, 100/*prog->filesize*/); /* 9 + // + // + // */ + // gmyth_string_list_append_int (slist, 0); /* 10 */ + + if (prog->startts) + gmyth_string_list_append_int(slist, prog->startts->tv_sec); /* 11 */// DATETIME_TO_LIST(startts) + else + gmyth_string_list_append_int(slist, 0); + + if (prog->endts) + gmyth_string_list_append_int(slist, prog->endts->tv_sec); /* 12 */// DATETIME_TO_LIST(endts) + else + gmyth_string_list_append_int(slist, 0); + + gmyth_string_list_append_int(slist, prog->duplicate); /* 13 */ + gmyth_string_list_append_int(slist, prog->shareable); /* 14 */ + gmyth_string_list_append_int(slist, prog->findid); /* 15 */ + gmyth_string_list_append_string(slist, prog->hostname); /* 16 */ + gmyth_string_list_append_int(slist, prog->sourceid); /* 17 */ + gmyth_string_list_append_int(slist, prog->cardid); /* 18 */ + gmyth_string_list_append_int(slist, prog->inputid); /* 19 */ + gmyth_string_list_append_int(slist, prog->recpriority); /* 20 */ + gmyth_string_list_append_int(slist, 0 /* prog->recstatus */ ); /* 21 */ + gmyth_string_list_append_int(slist, prog->recordid); /* 22 */ + gmyth_string_list_append_int(slist, 0 /* prog->rectype */ ); /* 23 */ + gmyth_string_list_append_int(slist, 0 /* prog->dupin */ ); /* 24 */ + gmyth_string_list_append_int(slist, 0 /* prog->dupmethod */ ); /* 25 */ + gmyth_string_list_append_int(slist, prog->recstartts != NULL ? prog->recstartts->tv_sec : 0); /* 26 + */// DATETIME_TO_LIST(recstartts) + gmyth_string_list_append_int(slist, prog->recendts != NULL ? prog->recendts->tv_sec : 0); /* 27 + */// DATETIME_TO_LIST(recendts) + gmyth_string_list_append_int(slist, prog->repeat); /* 28 */ + gmyth_string_list_append_int(slist, prog->programflags); /* 29 */ + gmyth_string_list_append_char_array(slist, "Default"); /* 30 */// prog->(recgroup + // + // + // != "") ? + // recgroup : + // "Default") + gmyth_string_list_append_int(slist, prog->chancommfree); /* 31 */ + gmyth_string_list_append_string(slist, prog->chanOutputFilters); /* 32 + */ + gmyth_string_list_append_string(slist, prog->seriesid); /* 33 */ + gmyth_string_list_append_string(slist, prog->program_id); /* 34 */ + gmyth_string_list_append_char_array(slist, ""); /* 35 */ + gmyth_string_list_append_int(slist, prog->lastmodified != NULL ? prog->lastmodified->tv_sec : 0); /* 36 + */// DATETIME_TO_LIST(lastmodified) + gmyth_string_list_append_int(slist, 0); /* 37 */// FLOAT_TO_LIST(stars) + gmyth_string_list_append_int(slist, prog->originalAirDate != NULL ? prog->originalAirDate->tv_sec : 0); /* 38 + */// DATETIME_TO_LIST(QDateTime(originalAirDate)) + gmyth_string_list_append_int(slist, prog->hasAirDate); /* 39 */ + gmyth_string_list_append_char_array(slist, "Default"); /* 40 */// prog->(playgroup + // + // + // != "") ? + // playgroup : + // "Default") + gmyth_string_list_append_int(slist, prog->recpriority2); /* 41 */ + + return slist; +} + +/** + * Converts an instance of a GMythStringList, to a GMythProgramInfo. + * + * @param slist The GMythStringList got from the MythTV backend server. + * @param pos The position in the GMythStringList to start getting the fields. + * + * @return a GMythProgramInfo representing the string list got from network. + */ +GMythProgramInfo * +gmyth_program_info_from_string_list_from_pos(GMythStringList * slist, + guint pos) +{ + GMythProgramInfo *prog = gmyth_program_info_new(); + + g_return_val_if_fail(slist != NULL && + gmyth_string_list_get_string(slist, pos) != NULL, + NULL); + + prog->title = gmyth_string_list_get_string(slist, pos); + prog->subtitle = gmyth_string_list_get_string(slist, pos + 1); + prog->description = gmyth_string_list_get_string(slist, pos + 2); + prog->category = gmyth_string_list_get_string(slist, pos + 3); + prog->channel_id = gmyth_string_list_get_int (slist, pos + 4); + prog->channame = gmyth_string_list_get_string(slist, pos + 5); + prog->chanstr = gmyth_string_list_get_string(slist, pos + 6); + prog->chansign = gmyth_string_list_get_string(slist, pos + 7); + prog->pathname = gmyth_string_list_get_string(slist, pos + 8); + + prog->filesize = gmyth_string_list_get_int64(slist, pos + 9); + + gmyth_debug("Prog info: [ %s, %s, %s, %s, %s, %s, %s, %s, %d ]\n", + gmyth_program_info_non_null_value(prog->title), + gmyth_program_info_non_null_value(prog->subtitle), + gmyth_program_info_non_null_value(prog->description), + gmyth_program_info_non_null_value(prog->category), + gmyth_program_info_non_null_value(prog->channame), + gmyth_program_info_non_null_value(prog->chanstr), + gmyth_program_info_non_null_value(prog->chansign), + gmyth_program_info_non_null_value(prog->pathname), + gmyth_string_list_get_int(slist, pos + 11)); + + prog->startts = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 11)))->str); // DATETIME_TO_LIST(startts) + prog->endts = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 12)))->str); // DATETIME_TO_LIST(endts) + prog->duplicate = gmyth_string_list_get_int(slist, pos + 13); + prog->shareable = gmyth_string_list_get_int(slist, pos + 14); + prog->findid = gmyth_string_list_get_int(slist, pos + 15); + prog->hostname = gmyth_string_list_get_string(slist, pos + 16); + prog->sourceid = gmyth_string_list_get_int(slist, pos + 17); + prog->cardid = gmyth_string_list_get_int(slist, pos + 18); + prog->inputid = gmyth_string_list_get_int(slist, pos + 19); + prog->recpriority = gmyth_string_list_get_int(slist, pos + 20); + prog->reactivate = gmyth_string_list_get_int(slist, pos + 21); + prog->recordid = gmyth_string_list_get_int(slist, pos + 22); + gmyth_string_list_get_int(slist, pos + 23); + gmyth_string_list_get_int(slist, pos + 24); + gmyth_string_list_get_int(slist, pos + 25); + prog->recstartts = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 26)))->str); // DATETIME_TO_LIST(recstartts) + prog->recendts = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 27)))->str); // DATETIME_TO_LIST(recendts) + prog->repeat = gmyth_string_list_get_int(slist, pos + 28); + prog->programflags = gmyth_string_list_get_int(slist, pos + 29); + prog->recgroup = gmyth_string_list_get_string(slist, pos + 30); // prog->(recgroup + // + // + // != + // "") + // ? + // recgroup + // : + // "Default") + prog->chancommfree = gmyth_string_list_get_int(slist, pos + 31); + prog->chanOutputFilters = + gmyth_string_list_get_string(slist, pos + 32); + prog->seriesid = gmyth_string_list_get_string(slist, pos + 33); + prog->program_id = gmyth_string_list_get_string(slist, pos + 34); + gmyth_string_list_get_string(slist, pos + 35); + prog->lastmodified = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 36)))->str); // DATETIME_TO_LIST(lastmodified) + gmyth_string_list_get_int(slist, pos + 37); // FLOAT_TO_LIST(stars) + prog->originalAirDate = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 38)))->str); // DATETIME_TO_LIST(QDateTime(originalAirDate)) + prog->hasAirDate = gmyth_string_list_get_int(slist, pos + 39); + prog->playgroup = gmyth_string_list_get_string(slist, pos + 40); // prog->(playgroup + // + // + // != + // "") + // ? + // playgroup + // : + // "Default") + prog->recpriority2 = gmyth_string_list_get_int(slist, pos + 41); + + return prog; +} + +/** + * Converts an instance of a GMythStringList, to a GMythProgramInfo. + * + * @param slist The GMythStringList got from the MythTV backend server. + * + * @return a GMythProgramInfo representing the string list got from network. + */ +GMythProgramInfo * +gmyth_program_info_from_string_list(GMythStringList * slist) +{ + GMythProgramInfo *prog = NULL; + + g_return_val_if_fail(slist != NULL, NULL); + + prog = gmyth_program_info_from_string_list_from_pos(slist, 0); + + return prog; +} + +/** + * Converts an instance of a GMythStringList, to a GMythProgramInfo ( NEXT_PROGRAM_INFO ). + * + * @param slist The GMythStringList got from the MythTV backend server. + * + * @return a GMythProgramInfo representing the string list got from network. + */ +GMythProgramInfo * +gmyth_program_info_from_string_list_next_prog(GMythStringList * slist) +{ + GMythProgramInfo *prog = gmyth_program_info_new(); + + g_return_val_if_fail(slist != NULL, NULL); + + /* + * {Home Improvement[]:[]No, No, Godot[]:[] US sitcom about a + * DIY-obsessed father of three. When Tim tries to sell off his extra + * ticket for an ice hockey game, he is arrested as a tout.[]:[] + * Sitcom[]:[]2007-04-18T15:30:00[]:[]2007-04-18T16:00:00[]:[]ABC1[]:[] + * /home/hmelo/.mythtv/channels/abc1.jpg[]:[]abc1[]:[]2000[]:[]25725844[]:[] + * } + */ + + prog->title = gmyth_string_list_get_string(slist, 0); + prog->subtitle = gmyth_string_list_get_string(slist, 1); + prog->description = gmyth_string_list_get_string(slist, 2); + prog->category = gmyth_string_list_get_string(slist, 3); + prog->startts = gmyth_util_string_to_time_val(gmyth_string_list_get_char_array(slist, 4)); // DATETIME_TO_LIST(startts) + prog->endts = gmyth_util_string_to_time_val(gmyth_string_list_get_char_array(slist, 5)); // DATETIME_TO_LIST(endts) + prog->channame = gmyth_string_list_get_string(slist, 6); + prog->chansign = gmyth_string_list_get_string(slist, 7); + prog->chanstr = gmyth_string_list_get_string(slist, 8); + prog->channel_id = gmyth_string_list_get_int (slist, 9); + prog->filesize = gmyth_string_list_get_int64(slist, 10); + + gmyth_debug + ("NEXT program info: [ %s, %s, %s, %s, %s, %s, %s, %s ]\n", + gmyth_program_info_non_null_value(prog->title), + gmyth_program_info_non_null_value(prog->subtitle), + gmyth_program_info_non_null_value(prog->description), + gmyth_program_info_non_null_value(prog->category), + gmyth_program_info_non_null_value(prog->channame), + gmyth_program_info_non_null_value(prog->chanstr), + gmyth_program_info_non_null_value(prog->chansign), + gmyth_program_info_non_null_value(prog->pathname)); + + return prog; +} + +static const gchar * +gmyth_program_info_non_null_value(const GString * str) +{ + return (str != NULL && str->str != NULL + && strlen(str->str) > 0 ? str->str : " "); +} + +/** + * Prints out an instance of a GMythProgramInfo. + * + * @param prog A GMythProgramInfo instance. + * + * @return a string representing the program info. + */ +const gchar * +gmyth_program_info_to_string(const GMythProgramInfo * prog) +{ + return + g_strdup_printf + ("Title: %s, Subtitle: %s, Description: %s, Category: %s, Channel ID: %d, " + "Channel Name: %s, Chan str: %s, Channel Sign: %s, Path Name: %s, File Size: %lld, \n" + "Start TS: %s, End TS: %s, Duplicate: %d, Shareable: %d, Find ID: %d, Hostname: %s, " + "Source ID: %d, Vard ID: %d, Input ID: %d, Rec Priority: %d, Reactivate: %d, \n" + "Record ID: %d, Rec Start TS: %s, Rec End TS: %s, Repeat: %d, Program Flags: %d, " + "Rec Group: %s, Channel Comm Free: %d, Channel Output Filters: %s, Series ID: %s, \n" + "Program ID: %s, Last Modified Date: %s, Original Air Date: %s, Has Air Date: %d, " + "Play Group: %s.\n", + gmyth_program_info_non_null_value(prog->title), + gmyth_program_info_non_null_value(prog->subtitle), + gmyth_program_info_non_null_value(prog->description), + gmyth_program_info_non_null_value(prog->category), + prog->channel_id, + gmyth_program_info_non_null_value(prog->channame), + gmyth_program_info_non_null_value(prog->chanstr), + gmyth_program_info_non_null_value(prog->chansign), + gmyth_program_info_non_null_value(prog->pathname), prog->filesize, + gmyth_util_time_to_string_from_time_val(prog->startts), + gmyth_util_time_to_string_from_time_val(prog->endts), + prog->duplicate, prog->shareable, prog->findid, + gmyth_program_info_non_null_value(prog->hostname), prog->sourceid, + prog->cardid, prog->inputid, prog->recpriority, prog->reactivate, + prog->recordid, + gmyth_util_time_to_string_from_time_val(prog->recstartts), + gmyth_util_time_to_string_from_time_val(prog->recendts), + prog->repeat, prog->programflags, + gmyth_program_info_non_null_value(prog->recgroup), + prog->chancommfree, + gmyth_program_info_non_null_value(prog->chanOutputFilters), + gmyth_program_info_non_null_value(prog->seriesid), + gmyth_program_info_non_null_value(prog->program_id), + gmyth_util_time_to_string_from_time_val(prog->lastmodified), + gmyth_util_time_to_string_from_time_val(prog->originalAirDate), + prog->hasAirDate, + gmyth_program_info_non_null_value(prog->playgroup)); +} + +/** + * Say if an instance of a GMythProgramInfo is equals to another one. + * + * @param prog The first GMythProgramInfo instance. + * @param prog The second GMythProgramInfo instance. + * + * @return true, if the program infos are equals. + */ +gboolean +gmyth_program_info_is_equals(const GMythProgramInfo * prog1, + const GMythProgramInfo * prog2) +{ + if ((strcmp(gmyth_program_info_non_null_value(prog1->title), + gmyth_program_info_non_null_value(prog2->title)) == 0) + || + (strcmp + (gmyth_program_info_non_null_value(prog1->pathname), + gmyth_program_info_non_null_value(prog2->pathname)) == 0)) + return TRUE; + else + return FALSE; + +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_programinfo.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_programinfo.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,180 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_programinfo.h + * + * @brief

GMythProgramInfo representing the program info, with the + * configuration data to the actual remote file in the TV chain. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Borges + * @author Leonardo Sobral Cunha + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef _GMYTH_PROGRAMINFO_H +#define _GMYTH_PROGRAMINFO_H + +#include +#include + +#include "gmyth_stringlist.h" + +G_BEGIN_DECLS +#define GMYTH_PROGRAM_INFO_TYPE (gmyth_program_info_get_type ()) +#define GMYTH_PROGRAM_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_PROGRAM_INFO_TYPE, GMythProgramInfo)) +#define GMYTH_PROGRAM_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_PROGRAM_INFO_TYPE, GMythProgramInfoClass)) +#define IS_GMYTH_PROGRAM_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_PROGRAM_INFO_TYPE)) +#define IS_GMYTH_PROGRAM_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_PROGRAM_INFO_TYPE)) +#define GMYTH_PROGRAM_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_PROGRAM_INFO_TYPE, GMythProgramInfoClass)) +typedef struct _GMythProgramInfo GMythProgramInfo; +typedef struct _GMythProgramInfoClass GMythProgramInfoClass; + +struct _GMythProgramInfoClass { + GObjectClass parent_class; + + /* + * callbacks + */ +}; + +/** + * The GMythProgramInfo structure represents a program information + * stored in the database. It could be a program from the EPG data, + * a program scheduled to be recorded, or a program already recorded. + */ +struct _GMythProgramInfo { + GObject parent; + + /** The channel unique ID. */ + gint channel_id; + /** The program start time. */ + GTimeVal *startts; + /** The program end time. */ + GTimeVal *endts; + /** The recording schedule start time. */ + GTimeVal *recstartts; + /** The recording schedule end time */ + GTimeVal *recendts; + + /** The program title. */ + GString *title; + /** The program subtitle. */ + GString *subtitle; + /** The program description. */ + GString *description; + /** The program category. */ + GString *category; + + GString *chanstr; + GString *chansign; + /** The associated channel name. */ + GString *channame; + gint chancommfree; + GString *chanOutputFilters; + + GString *seriesid; + /** The program unique id. */ + GString *program_id; + GString *catType; + + GString *sortTitle; + + /** A flag informing if the program has video or not. */ + gboolean isVideo; + gint lenMins; + + GString *year; + gdouble stars; + gint repeat; + + GTimeVal *originalAirDate; + GTimeVal *lastmodified; + GTimeVal *lastInUseTime; + + gboolean hasAirDate; + + gint spread; + gint startCol; + + gint recpriority2; + gint reactivate; + + gint recordid; + gint parentid; + + /** The backend video source id associated to this program.*/ + gint sourceid; + /** the backend input id associated to this program.*/ + gint inputid; + /** The backend card id associated to this program.*/ + gint cardid; + gboolean shareable; + gboolean duplicate; + + GString *schedulerid; + gint findid; + + gint programflags; + gint transcoder; + + GString *recgroup; + GString *playgroup; + gint rectype; + gint recstatus; + gint recpriority; + gint dupin; + gint dupmethod; + + /** The file size of the recorded program.*/ + gint64 filesize; + + /** The file name of the recorded program.*/ + GString *pathname; + GString *hostname; +}; + +GType gmyth_program_info_get_type(void); + +GMythProgramInfo *gmyth_program_info_new(void); + +GMythStringList *gmyth_program_info_to_string_list(GMythProgramInfo * prog, + GMythStringList * + slist); + +GMythProgramInfo + * gmyth_program_info_from_string_list_from_pos(GMythStringList * slist, + guint pos); + +GMythProgramInfo *gmyth_program_info_from_string_list(GMythStringList * + slist); + +GMythProgramInfo + * gmyth_program_info_from_string_list_next_prog(GMythStringList * + slist); + +const gchar *gmyth_program_info_to_string(const GMythProgramInfo * + prog); + +gboolean gmyth_program_info_is_equals(const GMythProgramInfo * + prog1, + const GMythProgramInfo * + prog2); + +G_END_DECLS +#endif /*_GMYTH_PROGRAMINFO_H*/ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_query.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_query.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,280 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_query.c + * + * @brief

GMythQuery class provides a wrapper for accessing + * the libmysqlclient funtions. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Leonardo Sobral Cunha + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "gmyth_query.h" +#include "gmyth_debug.h" + +static void gmyth_query_class_init(GMythQueryClass * klass); +static void gmyth_query_init(GMythQuery * object); + +static void gmyth_query_dispose(GObject * object); +static void gmyth_query_finalize(GObject * object); + +static void gmyth_query_print_error(MYSQL * conn, char *message); + +G_DEFINE_TYPE(GMythQuery, gmyth_query, G_TYPE_OBJECT) + static void gmyth_query_class_init(GMythQueryClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_query_dispose; + gobject_class->finalize = gmyth_query_finalize; +} + +static void +gmyth_query_init(GMythQuery * gmyth_query) +{ + gmyth_query->backend_info = NULL; + + /* + * initialize connection handler + */ + gmyth_query->conn = mysql_init(NULL); + + if (!(gmyth_query->conn)) + g_warning("[%s] MSQL structure not initialized", __FUNCTION__); +} + +static void +gmyth_query_dispose(GObject * object) +{ + GMythQuery *gmyth_query = GMYTH_QUERY(object); + + if (gmyth_query->conn != NULL) { + gmyth_query_disconnect(gmyth_query); + } + + if (gmyth_query->backend_info) { + g_object_unref(gmyth_query->backend_info); + gmyth_query->backend_info = NULL; + } + + G_OBJECT_CLASS(gmyth_query_parent_class)->dispose(object); +} + +static void +gmyth_query_finalize(GObject * object) +{ + g_signal_handlers_destroy(object); + + G_OBJECT_CLASS(gmyth_query_parent_class)->finalize(object); +} + +/** Creates a new instance of GMythQuery. + * + * @return a new instance of GMythQuery. + */ +GMythQuery * +gmyth_query_new() +{ + GMythQuery *sql_query = + GMYTH_QUERY(g_object_new(GMYTH_QUERY_TYPE, NULL)); + + return sql_query; +} + +gboolean +gmyth_query_connect_with_timeout(GMythQuery * gmyth_query, + GMythBackendInfo * backend_info, + guint timeout) +{ + assert(gmyth_query); + + if (gmyth_query->conn == NULL) + gmyth_query->conn = mysql_init(NULL); + + if (timeout != 0) { + /* + * sets connection timeout + */ + mysql_options(gmyth_query->conn, MYSQL_OPT_CONNECT_TIMEOUT, + (gchar *) & timeout); + } + + return gmyth_query_connect(gmyth_query, backend_info); +} + +/** Connects to the Mysql database in the backend. The backend address + * is loaded from the GMythBackendInfo instance. + * + * @param gmyth_query the GMythEPG instance to be connected. + * @return true if connection was success, false if failed. + */ +gboolean +gmyth_query_connect(GMythQuery * gmyth_query, + GMythBackendInfo * backend_info) +{ + assert(gmyth_query); + g_return_val_if_fail(backend_info != NULL, FALSE); + g_return_val_if_fail(backend_info->hostname != NULL, FALSE); + g_return_val_if_fail(backend_info->username != NULL, FALSE); + g_return_val_if_fail(backend_info->password != NULL, FALSE); + g_return_val_if_fail(backend_info->db_name != NULL, FALSE); + + if (gmyth_query->backend_info != NULL) { + g_object_unref(gmyth_query->backend_info); + } + gmyth_query->backend_info = g_object_ref(backend_info); + + if (gmyth_query->conn == NULL) { + gmyth_query->conn = mysql_init(NULL); + } + + /* + * connect to server + */ + if (mysql_real_connect(gmyth_query->conn, + gmyth_query->backend_info->hostname, + gmyth_query->backend_info->username, + gmyth_query->backend_info->password, + gmyth_query->backend_info->db_name, + gmyth_query->backend_info->db_port, + NULL, + 0) == NULL) { + gmyth_query_print_error(gmyth_query->conn, + "mysql_real_connect() failed"); + return FALSE; + } + + gmyth_debug + ("[%s] Connection to Mysql server succeeded! (host = %s, user = %s, " + "password = %s, db name = %s)", __FUNCTION__, + gmyth_query->backend_info->hostname, + gmyth_query->backend_info->username, + gmyth_query->backend_info->password, + gmyth_query->backend_info->db_name); + + return TRUE; +} + +/** Disconnects from the Mysql database in the backend. + * + * @param gmyth_query the GMythQuery instance to be disconnected + * @return true if disconnection was success, false if failed. + */ +gboolean +gmyth_query_disconnect(GMythQuery * gmyth_query) +{ + g_return_val_if_fail(gmyth_query != NULL, FALSE); + g_return_val_if_fail(gmyth_query->conn != NULL, FALSE); + + /* + * TODO: Check how to return error + */ + gmyth_debug("[%s] Closing gmyth_query->conn", __FUNCTION__); + + mysql_close(gmyth_query->conn); + gmyth_query->conn = NULL; + + return TRUE; +} + +static void +gmyth_query_print_error(MYSQL * conn, char *message) +{ + gmyth_debug("%s", message); + + if (conn != NULL) { +#if MYSQL_VERSION_ID >= 40101 + gmyth_debug("Error %u (%s): %s\n", + mysql_errno(conn), mysql_sqlstate(conn), + mysql_error(conn)); +#else + gmyth_debug("Error %u: %s\n", mysql_errno(conn), + mysql_error(conn)); +#endif + } +} + +/** Sends the given query to the backend returning the query result as + * MYSQL_RES pointer. + * + * FIXME: this function is returning NULL whether any error happens + * or no rows are returned (e.g. UPDATE or REPLACE). + * + * @param gmyth_query the GMythQuery instance. + * @param stmt_str the query text. + * @return the MYSQL_RES result pointer or NULL if any error happens. + */ +MYSQL_RES* +gmyth_query_process_statement(GMythQuery * gmyth_query, char *stmt_str) +{ + assert(gmyth_query); + + gmyth_debug("[%s] Running mysql query %s", __FUNCTION__, stmt_str); + + if (gmyth_query == NULL) + return NULL; + + //the statement failed + if (mysql_query(gmyth_query->conn, stmt_str) != 0) { + gmyth_query_print_error(gmyth_query->conn, + "Could not execute statement"); + return NULL; + } + + //the statement succeeded; determine whether it returned data + return mysql_store_result(gmyth_query->conn); +} + +MYSQL_RES* +gmyth_query_process_statement_with_increment(GMythQuery * gmyth_query, + char *stmt_str, gulong * id) +{ + assert(gmyth_query); + + gmyth_debug("[%s] Running mysql query %s", __FUNCTION__, stmt_str); + + if (gmyth_query == NULL) + return NULL; + + /* + * the statement failed + */ + if (mysql_query(gmyth_query->conn, stmt_str) != 0) { + gmyth_query_print_error(gmyth_query->conn, + "Could not execute statement"); + return NULL; + } + + *id = (my_ulonglong) mysql_insert_id(gmyth_query->conn); + + /* + * the statement succeeded; determine whether it returned data + */ + return mysql_store_result(gmyth_query->conn); +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_query.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_query.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,93 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_query.h + * + * @brief

GMythQuery class provides a wrapper for accessing + * the libmysqlclient funtions. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Leonardo Sobral Cunha + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_QUERY_H__ +#define __GMYTH_QUERY_H__ + +#include + +/* + * MYSQL includes + */ +#include + +#include "gmyth_backendinfo.h" + +G_BEGIN_DECLS +#define GMYTH_QUERY_TYPE (gmyth_query_get_type ()) +#define GMYTH_QUERY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_QUERY_TYPE, GMythQuery)) +#define GMYTH_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_QUERY_TYPE, GMythQueryClass)) +#define IS_GMYTH_QUERY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_QUERY_TYPE)) +#define IS_GMYTH_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_QUERY_TYPE)) +#define GMYTH_QUERY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_QUERY_TYPE, GMythQueryClass)) +typedef struct _GMythQuery GMythQuery; +typedef struct _GMythQueryClass GMythQueryClass; + +struct _GMythQueryClass { + GObjectClass parent_class; + + /* + * callbacks + */ + /* + * no one for now + */ +}; + +struct _GMythQuery { + GObject parent; + + GMythBackendInfo *backend_info; + + /* + * pointer to connection handler + */ + MYSQL *conn; +}; + + +GType gmyth_query_get_type(void); + +GMythQuery *gmyth_query_new(void); +MYSQL_RES *gmyth_query_process_statement(GMythQuery * gmyth_query, + gchar * stmt_str); +MYSQL_RES *gmyth_query_process_statement_with_increment(GMythQuery * + gmyth_query, + char + *stmt_str, + gulong * id); + +gboolean gmyth_query_connect(GMythQuery * gmyth_query, + GMythBackendInfo * backend_info); +gboolean gmyth_query_connect_with_timeout(GMythQuery * gmyth_query, + GMythBackendInfo * + backend_info, + guint timeout); +gboolean gmyth_query_disconnect(GMythQuery * gmyth_query); + +G_END_DECLS +#endif /* __GMYTH_QUERY_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_recorder.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_recorder.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,1388 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_recorder.c + * + * @brief

GMythRecorder defines functions for playing live tv. + * + * The remote encoder is used by gmyth_tvplayer to setup livetv. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * @author Rosfran Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_recorder.h" + +#include + +#include "gmyth_stringlist.h" +#include "gmyth_util.h" +#include "gmyth_common.h" +#include "gmyth_debug.h" + +#define GMYTHTV_RECORDER_HEADER "QUERY_RECORDER" + +static void gmyth_recorder_class_init(GMythRecorderClass * klass); +static void gmyth_recorder_init(GMythRecorder * object); + +static void gmyth_recorder_dispose(GObject * object); +static void gmyth_recorder_finalize(GObject * object); + +G_DEFINE_TYPE(GMythRecorder, gmyth_recorder, G_TYPE_OBJECT) + static void gmyth_recorder_class_init(GMythRecorderClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_recorder_dispose; + gobject_class->finalize = gmyth_recorder_finalize; +} + +static void +gmyth_recorder_init(GMythRecorder * gmyth_remote_encoder) +{ +} + +static void +gmyth_recorder_dispose(GObject * object) +{ + GMythRecorder *recorder = GMYTH_RECORDER(object); + + gmyth_recorder_close(recorder); + + if (recorder->mutex != NULL) { + g_mutex_free(recorder->mutex); + recorder->mutex = NULL; + } + + if (recorder->myth_socket != NULL) { + g_object_unref(recorder->myth_socket); + recorder->myth_socket = NULL; + } + + if (recorder->progs_info_list != NULL) + gmyth_free_program_list(recorder->progs_info_list); + + if (recorder->hostname != NULL) + g_string_free(recorder->hostname, TRUE); + + G_OBJECT_CLASS(gmyth_recorder_parent_class)->dispose(object); +} + +static void +gmyth_recorder_finalize(GObject * object) +{ + g_signal_handlers_destroy(object); + + G_OBJECT_CLASS(gmyth_recorder_parent_class)->finalize(object); +} + +void +gmyth_recorder_close(GMythRecorder * recorder) +{ + if (recorder != NULL && recorder->recorder_num != -1) { + g_mutex_lock(recorder->mutex); + + gmyth_recorder_stop_playing(recorder); + gmyth_recorder_stop_livetv(recorder); + gmyth_recorder_finish_recording(recorder); + gmyth_recorder_free_tuner(recorder); + + g_mutex_unlock(recorder->mutex); + } +} + +/** Creates a new instance of GMythRecorder. + * + * @return a new instance of GMythRecorder. + */ +GMythRecorder * +gmyth_recorder_new(int num, GString * hostname, gshort port) +{ + GMythRecorder *encoder = + GMYTH_RECORDER(g_object_new(GMYTH_RECORDER_TYPE, FALSE)); + + encoder->recorder_num = num; + encoder->hostname = g_string_new(hostname->str); + encoder->port = port; + + encoder->mutex = g_mutex_new(); + + encoder->progs_info_list = NULL; + + return encoder; +} + +/** Configures the remote encoder instance connecting it to Mythtv backend. + * + * @param recorder the GMythRecorder instance. + * + * @return TRUE if successfull, FALSE if any error happens. + */ +gboolean +gmyth_recorder_setup(GMythRecorder * recorder) +{ + assert(recorder); + gmyth_debug("[%s] Creating socket and connecting to backend", + __FUNCTION__); + + if (recorder->myth_socket == NULL) { + recorder->myth_socket = gmyth_socket_new(); + + if (!gmyth_socket_connect_to_backend(recorder->myth_socket, + recorder->hostname->str, + recorder->port, TRUE)) { + gmyth_debug + ("GMythRemoteEncoder: Connection to backend failed"); + return FALSE; + } + } else { + gmyth_debug("Remote encoder socket already created\n"); + } + + return TRUE; +} + +/** Sends the SPAWN_LIVETV command through Mythtv protocol. This command + * requests the backend to start capturing TV content. + * + * @param recorder The GMythRecorder instance. + * @param tvchain_id The tvchain unique id. + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_spawntv(GMythRecorder * recorder, GString * tvchain_id) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); + gboolean ret = TRUE; + + gmyth_debug("[%s] Spawntv with tvchain_id = %s", __FUNCTION__, + tvchain_id->str); + + str_list = gmyth_string_list_new(); + + g_mutex_lock(recorder->mutex); + + g_string_append_printf(tmp_str, " %d", recorder->recorder_num); + + gmyth_string_list_append_string(str_list, tmp_str); + g_string_free(tmp_str, TRUE); + + gmyth_string_list_append_char_array(str_list, "SPAWN_LIVETV"); + + gmyth_string_list_append_string(str_list, tvchain_id); + gmyth_string_list_append_int(str_list, 0); // PIP = FALSE (0) + + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); + + tmp_str = gmyth_string_list_get_string(str_list, 0); + + if (tmp_str == NULL) { + gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__, + tmp_str->str); + ret = FALSE; + goto cleanup; + } + + if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) { + gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__, + tmp_str->str); + ret = FALSE; + goto cleanup; + } + + cleanup: + g_mutex_unlock(recorder->mutex); + + g_string_free(tmp_str, TRUE); + g_object_unref(str_list); + + return ret; +} + +/** + * Sends the SPAWN_LIVETV command through Mythtv protocol. This command + * requests the backend to start capturing TV content, but it doesn't need + * the TV chain ID. + * + * @param recorder The GMythRecorder instance. + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_spawntv_no_tvchain(GMythRecorder * recorder) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); + gboolean ret = TRUE; + + gmyth_debug("[%s] Spawntv, no TV chain!", __FUNCTION__); + + str_list = gmyth_string_list_new(); + + g_mutex_lock(recorder->mutex); + + g_string_append_printf(tmp_str, " %d", recorder->recorder_num); + + gmyth_string_list_append_string(str_list, tmp_str); + g_string_free(tmp_str, TRUE); + + gmyth_string_list_append_char_array(str_list, "SPAWN_LIVETV"); + + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); + + tmp_str = gmyth_string_list_get_string(str_list, 0); + + if (tmp_str == NULL) { + gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__, + tmp_str->str); + ret = FALSE; + goto cleanup; + } + + if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) { + gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__, + tmp_str->str); + ret = FALSE; + goto cleanup; + } + + cleanup: + g_mutex_unlock(recorder->mutex); + + g_string_free(tmp_str, TRUE); + g_object_unref(str_list); + + return ret; +} + +/** Sends the command STOP_LIVETV to Mythtv backend. + * + * @param recorder the GMythRecorder instance. + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_stop_livetv(GMythRecorder * recorder) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); + gboolean ret = TRUE; + + gmyth_debug("[%s]", __FUNCTION__); + + str_list = gmyth_string_list_new(); + + g_string_append_printf(tmp_str, " %d", recorder->recorder_num); + + gmyth_string_list_append_string(str_list, tmp_str); + g_string_free(tmp_str, TRUE); + + gmyth_string_list_append_char_array(str_list, "STOP_LIVETV"); + + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); + + tmp_str = gmyth_string_list_get_string(str_list, 0); + + if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) { + gmyth_debug("[%s] Stop livetv request returned %s", __FUNCTION__, + tmp_str->str); + ret = FALSE; + goto cleanup; + } + + cleanup: + g_string_free(tmp_str, TRUE); + g_object_unref(str_list); + + return ret; +} + +/** Sends the FRONTEND_READY command through Mythtv protocol. This command + * advertises the backend to start capturing TV content. + * + * @param recorder The GMythRecorder instance. + * @return TRUE if success, FALSE if any error happens. + */ +gboolean +gmyth_recorder_send_frontend_ready_command(GMythRecorder * recorder) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); + gboolean ret = TRUE; + + gmyth_debug("[%s] FRONTEND_READY with recorder id = %d", __FUNCTION__, + recorder->recorder_num); + + str_list = gmyth_string_list_new(); + + g_mutex_lock(recorder->mutex); + + g_string_append_printf(tmp_str, " %d", recorder->recorder_num); + + gmyth_string_list_append_string(str_list, tmp_str); + g_string_free(tmp_str, TRUE); + + gmyth_string_list_append_char_array(str_list, "FRONTEND_READY"); + + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); + + tmp_str = gmyth_string_list_get_string(str_list, 0); + + if (tmp_str == NULL) { + gmyth_debug + ("[%s] FRONTEND_READY command request couldn't returns, reason: %s", + __FUNCTION__, tmp_str->str); + ret = FALSE; + goto cleanup; + } + + if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) { + gmyth_debug("[%s] FRONTEND_READY request returned %s", + __FUNCTION__, tmp_str->str); + ret = FALSE; + goto cleanup; + } + + cleanup: + g_mutex_unlock(recorder->mutex); + g_string_free(tmp_str, TRUE); + g_object_unref(str_list); + + return ret; +} + +/** Send a CHECK_CHANNEL command request to the backend, in order to find if a + * certain channel actually exists. + * + * @param recorder The GMythRecorder instance. + * @param channel The new channel to be checked (string format). + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_check_channel_name(GMythRecorder * recorder, + gchar * channel) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); + gboolean ret = TRUE; + + gmyth_debug("[%s] CHECK_CHANNEL with channel = %s", __FUNCTION__, + channel); + + str_list = gmyth_string_list_new(); + + g_mutex_lock(recorder->mutex); + + g_string_append_printf(tmp_str, " %d", recorder->recorder_num); + + gmyth_string_list_append_string(str_list, tmp_str); + g_string_free(tmp_str, TRUE); + + gmyth_string_list_append_char_array(str_list, "CHECK_CHANNEL"); + + gmyth_string_list_append_char_array(str_list, channel); + + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); + + tmp_str = gmyth_string_list_get_string(str_list, 0); + + if (tmp_str == NULL) { + gmyth_debug("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__, + tmp_str->str); + ret = FALSE; + goto cleanup; + } + + if (g_ascii_strncasecmp(tmp_str->str, "ok", 2) == 0 + || g_ascii_strncasecmp(tmp_str->str, "0", 1) == 0) { + gmyth_debug("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__, + tmp_str->str); + ret = FALSE; + goto cleanup; + } + + cleanup: + g_mutex_unlock(recorder->mutex); + g_string_free(tmp_str, TRUE); + g_object_unref(str_list); + + return ret; +} + +/** Send a CHECK_CHANNEL command request to the backend, in order to find if a + * certain channel actually exists. + * + * @param recorder The GMythRecorder instance. + * @param channel The new channel to be checked (decimal integer value). + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_check_channel(GMythRecorder * recorder, gint channel) +{ + return gmyth_recorder_check_channel_name(recorder, + g_strdup_printf("%d", + channel)); +} + +/** Send a SET_CHANNEL command request to the backend, to start streaming on another + * TV content channel. + * + * @param recorder The GMythRecorder instance. + * @param channel The new channel to be loaded. + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_set_channel(GMythRecorder * recorder, gint channel) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); + gboolean ret = TRUE; + + gmyth_debug("[%s] SET_CHANNEL with channel = %d", __FUNCTION__, + channel); + + str_list = gmyth_string_list_new(); + + g_mutex_lock(recorder->mutex); + + g_string_append_printf(tmp_str, " %d", recorder->recorder_num); + + gmyth_string_list_append_string(str_list, tmp_str); + g_string_free(tmp_str, TRUE); + + gmyth_string_list_append_char_array(str_list, "SET_CHANNEL"); + + gmyth_string_list_append_int(str_list, channel); + + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); + + tmp_str = gmyth_string_list_get_string(str_list, 0); + + if (tmp_str == NULL) { + gmyth_debug("[%s] SET_CHANNEL request returned %s", __FUNCTION__, + tmp_str->str); + ret = FALSE; + goto cleanup; + } + + if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) { + gmyth_debug("[%s] SET_CHANNEL request returned %s", __FUNCTION__, + tmp_str->str); + ret = FALSE; + goto cleanup; + } + + cleanup: + g_mutex_unlock(recorder->mutex); + g_string_free(tmp_str, TRUE); + g_object_unref(str_list); + + return ret; +} + +/** Send a SET_CHANNEL command request to the backend, to start streaming on another + * TV content channel. + * + * @param recorder The GMythRecorder instance. + * @param channel The new channel to be loaded. + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_set_channel_name(GMythRecorder * recorder, + const gchar * channel) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); + gboolean ret = TRUE; + + gmyth_debug("[%s] SET_CHANNEL with channel name = %s", __FUNCTION__, + channel); + + str_list = gmyth_string_list_new(); + + g_mutex_lock(recorder->mutex); + + g_string_append_printf(tmp_str, " %d", recorder->recorder_num); + + gmyth_string_list_append_string(str_list, tmp_str); + g_string_free(tmp_str, TRUE); + + gmyth_string_list_append_char_array(str_list, "SET_CHANNEL"); + gmyth_string_list_append_char_array(str_list, channel); + + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); + + tmp_str = gmyth_string_list_get_string(str_list, 0); + + if (tmp_str == NULL) { + gmyth_debug("[%s] SET_CHANNEL name request returned NULL!", + __FUNCTION__); + ret = FALSE; + goto cleanup; + } + + if (tmp_str != NULL && g_ascii_strncasecmp(tmp_str->str, "ok", 2) + /* + * || g_ascii_strtoull( tmp_str->str, NULL, 10 ) == 0 + */ + ) { + g_warning("[%s] SET_CHANNEL name request returned not ok", + __FUNCTION__); + ret = FALSE; + goto cleanup; + } + + cleanup: + g_mutex_unlock(recorder->mutex); + g_string_free(tmp_str, TRUE); + g_object_unref(str_list); + + return ret; +} + +/** + * Changes the channel of the actual Recorder. + * + * CHANNEL_DIRECTION_UP - Go up one channel in the listing + * + * CHANNEL_DIRECTION_DOWN - Go down one channel in the listing + * + * CHANNEL_DIRECTION_FAVORITE - Go to the next favorite channel + * + * CHANNEL_DIRECTION_SAME - Stay + * + * @param recorder The GMythRecorder instance. + * @param direction The new channel direction where to move to. + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_change_channel(GMythRecorder * recorder, + const GMythRecorderChannelChangeDirection + direction) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); + gboolean ret = TRUE; + + gmyth_debug("[%s] CHANGE_CHANNEL to the channel direction = %u", + __FUNCTION__, direction); + + str_list = gmyth_string_list_new(); + + g_mutex_lock(recorder->mutex); + + g_string_append_printf(tmp_str, " %d", recorder->recorder_num); + + gmyth_string_list_append_string(str_list, tmp_str); + g_string_free(tmp_str, TRUE); + + gmyth_string_list_append_char_array(str_list, "CHANGE_CHANNEL"); + gmyth_string_list_append_int(str_list, direction); + + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); + + tmp_str = gmyth_string_list_get_string(str_list, 0); + + if (tmp_str == NULL) { + gmyth_debug("[%s] CHANGE_CHANNEL name request returned %s", + __FUNCTION__, tmp_str->str); + ret = FALSE; + goto cleanup; + } + + if (g_ascii_strncasecmp(tmp_str->str, "ok", 2) + || g_ascii_strtoull(tmp_str->str, NULL, 10) == 0) { + gmyth_debug("[%s] CHANGE_CHANNEL name request returned %s", + __FUNCTION__, tmp_str->str); + ret = FALSE; + goto cleanup; + } + + cleanup: + g_mutex_unlock(recorder->mutex); + g_string_free(tmp_str, TRUE); + g_object_unref(str_list); + + return ret; +} + +/** + * Gets the channel's list from the MythTV backend server. + * + * @param recorder The GMythRecorder instance. + * + * @return a GList* instance with all the channel names. + */ +GList * +gmyth_recorder_get_channel_list(GMythRecorder * recorder) +{ + + GList *channel_list = NULL; + gchar *channel = NULL; + guint i; + + for (i = 0; i < 1000; i++) { + channel = g_strdup_printf("%u", i); + + if (gmyth_recorder_check_channel_name(recorder, channel)) { + channel_list = g_list_append(channel_list, g_strdup(channel)); + } + + } /* for - channel list */ + + g_free(channel); + + return channel_list; + +} + +/** Send a PAUSE command request to the backend, to pause streaming on another + * TV content channel. + * + * @param recorder The GMythRecorder instance. + * @return true if success, false if any error happens. + */ +gboolean +gmyth_recorder_pause_recording(GMythRecorder * recorder) +{ + GMythStringList *str_list; + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); + gboolean ret = TRUE; + + gmyth_debug("[%s] PAUSE", __FUNCTION__); + + str_list = gmyth_string_list_new(); + + g_mutex_lock(recorder->mutex); + + g_string_append_printf(tmp_str, " %d", recorder->recorder_num); + + gmyth_string_list_append_string(str_list, tmp_str); + g_string_free(tmp_str, TRUE); + + gmyth_string_list_append_char_array(str_list, "PAUSE"); + + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); + + tmp_str = gmyth_string_list_get_string(str_list, 0); + + if (tmp_str == NULL) { + gmyth_debug("[%s] PAUSE name request returned %s", __FUNCTION__, + tmp_str->str); + ret = FALSE; + goto cleanup; + } + + if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) { + gmyth_debug("[%s] PAUSE name request returned %s", __FUNCTION__, + tmp_str->str); + ret = FALSE; + goto cleanup; + } + + cleanup: + g_mutex_unlock(recorder->mutex); + g_string_free(tmp_str, TRUE); + g_object_unref(str_list); + + return ret; +} + +static gboolean +gmyth_recorder_find_if_program_exists(GMythRecorder * recorder, + GMythProgramInfo * prog) +{ + GList *lst = NULL; + + g_return_val_if_fail(recorder != NULL + && recorder->progs_info_list != NULL, FALSE); + + for (lst = recorder->progs_info_list; lst != NULL; + lst = g_list_next(lst)) { + gmyth_debug("Got program info from list = [%s]", + gmyth_program_info_to_string((GMythProgramInfo *) + lst->data)); + if (gmyth_program_info_is_equals + (prog, (GMythProgramInfo *) lst->data)) + return TRUE; + } + + return FALSE; +} + +/** + * Requests the actual program info from the MythTV backend server. + * + * @param recorder The GMythRecorder instance. + * @return The actual program info. + */ +GMythProgramInfo * +gmyth_recorder_get_current_program_info(GMythRecorder * recorder) +{ + GMythStringList *str_list = NULL; + GMythProgramInfo *program_info = NULL; + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); + + str_list = gmyth_string_list_new(); + + g_mutex_lock(recorder->mutex); + + g_string_append_printf(tmp_str, " %d", recorder->recorder_num); + + gmyth_string_list_append_string(str_list, tmp_str); + + if (recorder->myth_socket->mythtv_version >= 26) + gmyth_string_list_append_char_array(str_list, + "GET_CURRENT_RECORDING"); + else + gmyth_string_list_append_char_array(str_list, "GET_PROGRAM_INFO"); + + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); + + if (str_list == NULL) { + gmyth_debug + ("[%s] GET_PROGRAM_INFO request returned. Error getting program info, string list equals to NULL!", + __FUNCTION__); + goto cleanup; + } + + program_info = gmyth_program_info_from_string_list(str_list); + + if (NULL == program_info || NULL == program_info->pathname + || program_info->pathname->len <= 0) { + gmyth_debug + ("GET_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!"); + + if (program_info) + g_object_unref(program_info); + + program_info = NULL; + + goto cleanup; + } + + if (!gmyth_recorder_find_if_program_exists(recorder, program_info)) + recorder->progs_info_list = + g_list_append(recorder->progs_info_list, + g_object_ref(program_info)); + cleanup: + g_mutex_unlock(recorder->mutex); + g_string_free(tmp_str, TRUE); + g_object_unref(str_list); + + return program_info; +} + +/** + * Requests the actual program info from the MythTV backend server. + * + * @param rec_id The GMythRecorder record number. + * @return The GMythRecorder instance. + */ +GMythRecorder * +gmyth_recorder_get_recorder_from_num(gint rec_id) +{ + GMythRecorder *recorder = NULL; + GMythStringList *str_list; + GString *tmp_str = g_string_new("GET_RECORDER_FROM_NUM"); + gint command_size = 0; + + gchar *recorder_host = NULL; + gint recorder_port; + + str_list = gmyth_string_list_new(); + + /* + * g_string_append_printf ( tmp_str, " %d", recorder->recorder_num ); + */ + + g_mutex_lock(recorder->mutex); + + gmyth_string_list_append_string(str_list, tmp_str); + + gmyth_string_list_append_int(str_list, rec_id); + + command_size = + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, + str_list); + + if (str_list == NULL) { + gmyth_debug + ("[%s] GET_RECORDER_FROM_NUM request returned. Error getting recorder number %d, it is equals to NULL!!!", + __FUNCTION__, rec_id); + return NULL; + } + + if (command_size > 0) { + recorder_host = gmyth_string_list_get_char_array(str_list, 0); + recorder_port = gmyth_string_list_get_int(str_list, 1); + + if (g_strstr_len(recorder_host, strlen(recorder_host), "nohost") + != NULL) { + gmyth_debug + ("No available recorder with the recorder ID number %d!", + rec_id); + } else { + + recorder = gmyth_recorder_new(rec_id, + g_string_new(recorder_host), + (gshort) recorder_port); + + if (NULL == recorder) { + gmyth_debug + ("[%s] GET_RECORDER_FROM_NUM request returned. Error getting recorder number %d, it is equals to NULL!!!", + __FUNCTION__, rec_id); + g_object_unref(recorder); + return NULL; + } + + } + + } else { + gmyth_debug + ("Cannot find a valuable recorder with the recorder ID number %d, backend server error!", + rec_id); + } + + g_mutex_unlock(recorder->mutex); + + g_object_unref(str_list); + + g_string_free(tmp_str, TRUE); + + g_free(recorder_host); + + return recorder; + +} + +/** + * Requests the actual program info from the MythTV backend server. + * + * @param recorder The GMythRecorder instance. + * @param direction The direction to move based on the current channel (forward, backward, + * up, down). + * + * @return The GMythProgramInfo next program info instance. + */ +GMythProgramInfo * +gmyth_recorder_get_next_program_info(GMythRecorder * recorder, + const GMythRecorderBrowseDirection + direction) +{ + GMythProgramInfo *actual_proginfo = NULL; + GMythProgramInfo *program_info = NULL; + GMythStringList *str_list; + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); + + gchar *date = NULL; + struct tm *tm = NULL; + time_t t; + + actual_proginfo = gmyth_recorder_get_current_program_info(recorder); + + str_list = gmyth_string_list_new(); + + g_mutex_lock(recorder->mutex); + + g_string_append_printf(tmp_str, " %d", recorder->recorder_num); + + t = time(NULL); + tm = localtime(&t); + date = g_strdup_printf("%.4d%.2d%.2d%.2d%.2d%.2d", tm->tm_year + 1900, + tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, + tm->tm_min, tm->tm_sec); + + gmyth_string_list_append_string(str_list, tmp_str); + gmyth_string_list_append_char_array(str_list, "GET_NEXT_PROGRAM_INFO"); + gmyth_string_list_append_string(str_list, actual_proginfo->channame); + gmyth_string_list_append_int(str_list, actual_proginfo->channel_id); + gmyth_string_list_append_int(str_list, direction); + gmyth_string_list_append_char_array(str_list, date); + + if (gmyth_socket_sendreceive_stringlist + (recorder->myth_socket, str_list) + > 0) { + + if (str_list == NULL) { + gmyth_debug + ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!", + __FUNCTION__); + goto done; + } + program_info = + gmyth_program_info_from_string_list_next_prog(str_list); + + if (NULL == program_info) { + gmyth_debug + ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting next program info, it is equals to NULL!!!", + __FUNCTION__); + g_object_unref(program_info); + goto done; + } + + if ( /* ( program_info->chanid != NULL && + * strlen( program_info->chanid->str ) > 0 + * * * * * * ) && */ + (program_info->chansign != NULL + && strlen(program_info->chansign->str) > 0)) { + gmyth_debug("OK!!! Got the next program info... [%s].", + program_info->chansign->str); + } else { + gmyth_debug + ("GET_NEXT_PROGRAM_INFO request returned. Error getting next program info, it is equals to NULL!!!"); + g_object_unref(program_info); + program_info = NULL; + } + + } + /* + * if + */ + done: + + g_mutex_unlock(recorder->mutex); + + if (actual_proginfo != NULL) + g_object_unref(actual_proginfo); + + if (str_list != NULL) + g_object_unref(str_list); + + if (tmp_str != NULL) + g_string_free(tmp_str, TRUE); + + if (date != NULL) + g_free(date); + // if ( tm != NULL) + // g_free (tm); + + return program_info; +} + +/** + * Requests the program info from the MythTV backend server, based on its + * channel name. + * + * @param recorder The GMythRecorder instance. + * @return The GMythProgramInfo next program info instance. + */ +GMythProgramInfo * +gmyth_recorder_get_program_info_from_channel_name(GMythRecorder * recorder, + const gchar * channel) +{ + // GMythProgramInfo* actual_proginfo= NULL; + GMythProgramInfo *program_info = NULL; + GMythStringList *str_list; + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); + + /* + * gchar *date = NULL; struct tm *tm = NULL; time_t t; + * + * actual_proginfo = + * gmyth_recorder_get_current_program_info(recorder); + */ + + str_list = gmyth_string_list_new(); + + g_mutex_lock(recorder->mutex); + + g_string_append_printf(tmp_str, " %d", recorder->recorder_num); + + /* + * t = time(NULL); tm = localtime(&t); date = + * g_strdup_printf("%.4d%.2d%.2d%.2d%.2d%.2d", tm->tm_year + 1900, + * tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); + */ + + gmyth_string_list_append_string(str_list, tmp_str); + gmyth_string_list_append_char_array(str_list, "GET_NEXT_PROGRAM_INFO"); + gmyth_string_list_append_char_array(str_list, channel); + gmyth_string_list_append_char_array(str_list, "0"); + gmyth_string_list_append_int(str_list, BROWSE_DIRECTION_UP); + gmyth_string_list_append_char_array(str_list, "0"); + + do { + + if (str_list != NULL && + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, + str_list) > 0) { + + if (str_list == NULL) { + gmyth_debug + ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!", + __FUNCTION__); + goto done; + } + program_info = + gmyth_program_info_from_string_list_next_prog(str_list); + + if (NULL == program_info) { + gmyth_debug + ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting next program info, it is equals to NULL!!!", + __FUNCTION__); + g_object_unref(program_info); + goto done; + } + + if ( /* ( program_info->chanid != NULL && + * strlen( program_info->chanid->str ) > 0 + * * * * * * ) && */ + (program_info->chansign != NULL + && strlen(program_info->chansign->str) > 0)) { + gmyth_debug("OK!!! Got the next program info... [%s].", + program_info->chansign->str); + } else { + gmyth_debug + ("GET_NEXT_PROGRAM_INFO request returned. Error getting " + "next program info, it is equals to NULL!!!"); + g_object_unref(program_info); + program_info = NULL; + } + + } + /* + * if + */ + } + while (str_list != NULL); + + done: + + g_mutex_unlock(recorder->mutex); + + if (str_list != NULL) + g_object_unref(str_list); + + if (tmp_str != NULL) + g_string_free(tmp_str, TRUE); + + return program_info; +} + +/** + * Requests the actual remote file position on a LiveTV instance. + * + * @param recorder The GMythRecorder instance. + * + * @return The position, in bytes, of the offset to the read header. + */ +gint64 +gmyth_recorder_get_file_position(GMythRecorder * recorder) +{ + gint64 pos = 0; + GString *query = g_string_new(GMYTHTV_RECORDER_HEADER); + + GMythStringList *str_list = gmyth_string_list_new(); + + g_mutex_lock(recorder->mutex); + + g_string_append_printf(query, " %d", recorder->recorder_num); + + gmyth_string_list_append_string(str_list, query); + gmyth_string_list_append_char_array(str_list, "GET_FILE_POSITION"); + + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); + + if (str_list != NULL && gmyth_string_list_length(str_list) > 0) { + GString *str = NULL; + + if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL + && strstr(str->str, "bad") == NULL) + pos = gmyth_string_list_get_int64(str_list, 0); + g_string_free(str, TRUE); + } +#ifndef GMYTHTV_ENABLE_DEBUG + gmyth_debug("[%s] Got file position = %lld\n", __FUNCTION__, pos); +#endif + + g_mutex_unlock(recorder->mutex); + + if (str_list != NULL) + g_object_unref(str_list); + + g_string_free(query, TRUE); + + return pos; +} + +/** + * Asks MythTV backend server about if it started to record the remote file. + * + * @param recorder The GMythRecorder instance. + * + * @return true, if the actual remote file is bein recorded. + */ +gboolean +gmyth_recorder_is_recording(GMythRecorder * recorder) +{ + gboolean ret = TRUE; + + g_return_val_if_fail(recorder != NULL, FALSE); + + GMythStringList *str_list = gmyth_string_list_new(); + GString *message = g_string_new(""); + + g_mutex_lock(recorder->mutex); + + g_string_printf(message, "%s %d", GMYTHTV_RECORDER_HEADER, + recorder->recorder_num); + gmyth_string_list_append_string(str_list, message); + gmyth_string_list_append_char_array(str_list, "IS_RECORDING"); + + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); + + if (str_list != NULL && gmyth_string_list_length(str_list) > 0) { + GString *str = NULL; + + if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL + && strcmp(str->str, "bad") != 0) { + gint is_rec = + gmyth_string_list_get_int(str_list, 0); + + if (is_rec != 0) + ret = TRUE; + else + ret = FALSE; + } + g_string_free(str, TRUE); + } + + gmyth_debug("%s, stream is %s being recorded!\n", ret ? "YES" : "NO", + ret ? "" : "NOT"); + // g_static_mutex_unlock (&mutex); + + g_mutex_unlock(recorder->mutex); + + if (str_list != NULL) + g_object_unref(str_list); + + g_string_free(message, TRUE); + + return ret; + +} + +/** + * Finish remote file recording process. + * + * @param recorder The GMythRecorder instance. + * + * @return true, if the recording had been actually closed. + */ +gboolean +gmyth_recorder_finish_recording(GMythRecorder * recorder) +{ + gboolean ret = TRUE; + + g_return_val_if_fail(recorder != NULL, FALSE); + + GMythStringList *str_list = gmyth_string_list_new(); + GString *message = g_string_new(""); + + g_string_printf(message, "%s %d", GMYTHTV_RECORDER_HEADER, + recorder->recorder_num); + gmyth_string_list_append_string(str_list, message); + gmyth_string_list_append_char_array(str_list, "FINISH_RECORDING"); + + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); + + if (str_list != NULL && gmyth_string_list_length(str_list) > 0) { + GString *str = NULL; + + if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL && + strcmp(str->str, "ok") != 0) { + gint is_rec = + gmyth_string_list_get_int(str_list, 0); + + if (is_rec != 0) + ret = TRUE; + else + ret = FALSE; + } + g_string_free(str, TRUE); + } + + gmyth_debug("%s, stream is %s finished!\n", ret ? "YES" : "NO", + ret ? "" : "NOT"); + // g_static_mutex_unlock (&mutex); + + if (str_list != NULL) + g_object_unref(str_list); + + g_string_free(message, TRUE); + + return ret; +} + + +/** + * Stops playing the remote file. + * + * @param recorder The GMythRecorder instance. + * + * @return true, if the recording had been actually stopped. + */ +gboolean +gmyth_recorder_stop_playing(GMythRecorder * recorder) +{ + gboolean ret = TRUE; + + g_return_val_if_fail(recorder != NULL, FALSE); + + GMythStringList *str_list = gmyth_string_list_new(); + GString *message = g_string_new(""); + + g_string_printf(message, "%s %d", GMYTHTV_RECORDER_HEADER, + recorder->recorder_num); + gmyth_string_list_append_string(str_list, message); + gmyth_string_list_append_char_array(str_list, "STOP_PLAYING"); + + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); + + if (str_list != NULL && gmyth_string_list_length(str_list) > 0) { + GString *str = NULL; + + if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL && + strcmp(str->str, "ok") != 0) { + gint is_rec = + gmyth_string_list_get_int(str_list, 0); + + if (is_rec != 0) + ret = TRUE; + else + ret = FALSE; + } + g_string_free(str, TRUE); + } + + gmyth_debug("%s, stream is %s stopped!\n", ret ? "YES" : "NO", + ret ? "" : "NOT"); + + if (str_list != NULL) + g_object_unref(str_list); + + g_string_free(message, TRUE); + + return ret; +} + +/** + * Free the tuner responsible for recording this channel. + * + * @param recorder The GMythRecorder instance. + * + * @return true, if the tuner had been freed. + */ +gboolean +gmyth_recorder_free_tuner(GMythRecorder * recorder) +{ + gboolean ret = TRUE; + + g_return_val_if_fail(recorder != NULL, FALSE); + + GMythStringList *str_list = gmyth_string_list_new(); + GString *message = g_string_new(""); + + g_string_printf(message, "%s %d", "FREE_TUNER", + recorder->recorder_num); + gmyth_string_list_append_string(str_list, message); + + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); + + if (str_list != NULL && gmyth_string_list_length(str_list) > 0) { + GString *str = NULL; + + if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL && + g_ascii_strncasecmp(str->str, "ok", 2) != 0) { + gint is_rec = + gmyth_string_list_get_int(str_list, 0); + + if (is_rec != 0) + ret = TRUE; + else + ret = FALSE; + } + g_string_free(str, TRUE); + } + + gmyth_debug("%s, tuner is %s freed!\n", ret ? "YES" : "NO", + ret ? "" : "NOT"); + + if (str_list != NULL) + g_object_unref(str_list); + + g_string_free(message, TRUE); + + return ret; +} + +/** + * Asks the MythTV backend server about the frame rate + * of this LiveTV instance. + * + * @param recorder The GMythRecorder instance. + * + * @return The framerate (double value) of the current video. + */ +gdouble +gmyth_recorder_get_framerate(GMythRecorder * recorder) +{ + gdouble fr = 0.0f; + GString *query = g_string_new(GMYTHTV_RECORDER_HEADER); + + GMythStringList *str_list = gmyth_string_list_new(); + + g_mutex_lock(recorder->mutex); + + g_string_append_printf(query, " %d", recorder->recorder_num); + + gmyth_string_list_append_string(str_list, query); + gmyth_string_list_append_char_array(str_list, "GET_FRAMERATE"); + + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); + + if (str_list != NULL && gmyth_string_list_length(str_list) > 0) { + GString *str = NULL; + + if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL + && strstr(str->str, "bad") == NULL) + fr = g_ascii_strtod(str->str, NULL); + + g_string_free(str, TRUE); + } +#ifndef GMYTHTV_ENABLE_DEBUG + gmyth_debug("[%s] Got file position = %f\n", __FUNCTION__, fr); +#endif + + g_mutex_unlock(recorder->mutex); + + if (str_list != NULL) + g_object_unref(str_list); + + g_string_free(query, TRUE); + + return fr; + +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_recorder.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_recorder.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,162 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_recorder.h + * + * @brief

GMythRecorder defines functions for playing live tv. + * + * The remote encoder is used by gmyth_tvplayer to setup livetv. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * @author Rosfran Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_RECORDER_H__ +#define __GMYTH_RECORDER_H__ + +#include + +#include "gmyth_socket.h" +#include "gmyth_programinfo.h" + +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS +#define GMYTH_RECORDER_TYPE (gmyth_recorder_get_type ()) +#define GMYTH_RECORDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_RECORDER_TYPE, GMythRecorder)) +#define GMYTH_RECORDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECORDER_TYPE, GMythRecorderClass)) +#define IS_GMYTH_RECORDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_RECORDER_TYPE)) +#define IS_GMYTH_RECORDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECORDER_TYPE)) +#define GMYTH_RECORDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_RECORDER_TYPE, GMythRecorderClass)) +typedef struct _GMythRecorder GMythRecorder; +typedef struct _GMythRecorderClass GMythRecorderClass; + +struct _GMythRecorderClass { + GObjectClass parent_class; + + /* + * callbacks + */ + /* + * no one for now + */ +}; + +struct _GMythRecorder { + GObject parent; + + /* + * socket descriptor + */ + GMythSocket *myth_socket; + + gint recorder_num; + GString *hostname; + gint port; + + GList *progs_info_list; + + GMutex *mutex; +}; + +typedef enum _GMythRecorderChannelChangeDirection { + CHANNEL_DIRECTION_UP = 0, + CHANNEL_DIRECTION_DOWN, + CHANNEL_DIRECTION_FAVORITE, + CHANNEL_DIRECTION_SAME +} GMythRecorderChannelChangeDirection; + +typedef enum _GMythRecorderBrowseDirection { + BROWSE_DIRECTION_SAME = 0, /* Stay in the same place */ + BROWSE_DIRECTION_UP, /* Move up one slot (down one channel) */ + BROWSE_DIRECTION_DOWN, /* Move down one slot (up one channel) */ + BROWSE_DIRECTION_LEFT, /* Move left one slot (down one time slot) + */ + BROWSE_DIRECTION_RIGHT, /* Move right one slot (up one time slot) */ + BROWSE_DIRECTION_FAVORITE /* Move to the next favorite slot */ +} GMythRecorderBrowseDirection; + +GType gmyth_recorder_get_type(void); + +GMythRecorder *gmyth_recorder_new(int num, GString * hostname, + gshort port); + +void gmyth_recorder_close(GMythRecorder * recorder); + +gboolean gmyth_recorder_setup(GMythRecorder * recorder); +gboolean gmyth_recorder_spawntv(GMythRecorder * recorder, + GString * tvchain_id); + +gboolean gmyth_recorder_spawntv_no_tvchain(GMythRecorder * + recorder); + +gboolean gmyth_recorder_stop_livetv(GMythRecorder * recorder); + +gboolean gmyth_recorder_send_frontend_ready_command(GMythRecorder * + recorder); + +gboolean gmyth_recorder_check_channel(GMythRecorder * recorder, + gint channel); + +gboolean gmyth_recorder_check_channel_name(GMythRecorder * recorder, + gchar * channel); + +gboolean gmyth_recorder_set_channel(GMythRecorder * recorder, + gint channel); + +gboolean gmyth_recorder_set_channel_name(GMythRecorder * recorder, + const gchar * channel); + +gboolean gmyth_recorder_change_channel(GMythRecorder * recorder, const + GMythRecorderChannelChangeDirection + direction); + +GList *gmyth_recorder_get_channel_list(GMythRecorder * recorder); + +gboolean gmyth_recorder_pause_recording(GMythRecorder * recorder); + +GMythProgramInfo *gmyth_recorder_get_current_program_info(GMythRecorder * + recorder); + +GMythProgramInfo *gmyth_recorder_get_next_program_info(GMythRecorder * + recorder, const + GMythRecorderBrowseDirection + direction); + +GMythRecorder *gmyth_recorder_get_recorder_from_num(gint rec_id); + +gint64 gmyth_recorder_get_file_position(GMythRecorder * recorder); + +gboolean gmyth_recorder_is_recording(GMythRecorder * recorder); + +gboolean gmyth_recorder_finish_recording(GMythRecorder * recorder); + +gboolean gmyth_recorder_stop_playing(GMythRecorder * recorder); + +gboolean gmyth_recorder_free_tuner(GMythRecorder * recorder); + +gdouble gmyth_recorder_get_framerate(GMythRecorder * recorder); + +G_END_DECLS +#endif /* __GMYTH_REMOTE_ENCODER_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_recprofile.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_recprofile.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,264 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_recprofile.c + * + * @brief

This file contains the recprofile class. + * + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. + * @author Artur Duque de Souza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "gmyth_recprofile.h" +#include "gmyth_util.h" +#include "gmyth_debug.h" +#include "gmyth_http.h" + +static void gmyth_recprofile_class_init(GMythRecProfileClass * klass); +static void gmyth_recprofile_init(GMythRecProfile * object); + +static void gmyth_recprofile_dispose(GObject * object); +static void gmyth_recprofile_finalize(GObject * object); + +G_DEFINE_TYPE(GMythRecProfile, gmyth_recprofile, G_TYPE_OBJECT) + static void gmyth_recprofile_class_init(GMythRecProfileClass * + klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->dispose = gmyth_recprofile_dispose; + gobject_class->finalize = gmyth_recprofile_finalize; +} + +static void +gmyth_recprofile_init(GMythRecProfile * recprofile) +{ +} + +static void +gmyth_recprofile_dispose(GObject * object) +{ + GMythRecProfile *recprofile = GMYTH_RECPROFILE(object); + + if (recprofile->name) + g_free(recprofile->name); + + if (recprofile->group) + g_free(recprofile->group); + + if (recprofile->vcodec) + g_free(recprofile->vcodec); + + if (recprofile->acodec) + g_free(recprofile->acodec); + + if (recprofile->options) + g_free(recprofile->options); + + G_OBJECT_CLASS(gmyth_recprofile_parent_class)->dispose(object); +} + +static void +gmyth_recprofile_finalize(GObject * object) +{ + g_signal_handlers_destroy(object); + G_OBJECT_CLASS(gmyth_recprofile_parent_class)->finalize(object); +} + +/** + * Creates a new instance of GMythRecProfile. + * + * @return a new instance of GMythRecProfile. + **/ +GMythRecProfile * +gmyth_recprofile_new(void) +{ + GMythRecProfile *recprofile = GMYTH_RECPROFILE + (g_object_new(GMYTH_RECPROFILE_TYPE, NULL)); + + recprofile->id = 0; + recprofile->name = NULL; + recprofile->group = NULL; + recprofile->vcodec = NULL; + recprofile->acodec = NULL; + recprofile->options = NULL; + + return recprofile; +} + + +/** + * + * gmyth_recprofile_get_profile_list + * @brief get profile list from the backend + * @param backend_info GMythBackendInfo* + * @return GSList + * + **/ +GSList * +gmyth_recprofile_get_profile_list(GMythBackendInfo * backend_info) +{ + return gmyth_http_retrieve_rec_profiles(backend_info, "Transcoders"); +} + +/** + * + * gmyth_recprofile_create_profile + * @brief get profile list from the backend + * @param backend_info GMythBackendInfo* + * @param profile GMythRecProfile* + * @return gint representing the result + * + **/ +gint +gmyth_recprofile_create_profile(GMythBackendInfo * backend_info, + GMythRecProfile * profile) +{ + return gmyth_http_create_rec_profile(backend_info, profile); +} + +/** + * + * gmyth_recprofile_del_profile + * @brief del profile from the backend + * @param backend_info GMythBackendInfo* + * @param id profile's id + * @return gint representing the result + * + **/ +gint +gmyth_recprofile_del_profile_list(GMythBackendInfo * backend_info, gint id) +{ + return gmyth_http_del_rec_profile(backend_info, id); +} + +/** + * + * gmyth_recprofile_set_id + * @brief set recprofile's id + * @param rec GMythRecProfile* + * @param id profile's id + * @return gint representing the result + * + **/ +gint +gmyth_recprofile_set_id(GMythRecProfile * rec, gint id) +{ + rec->id = id; + return 0; +} + +/** + * + * gmyth_recprofile_set + * @brief set recprofile's property + * @param rec GMythRecProfile* + * @param member the member you want to modify + * @param value the value + * @return gint representing the result + * + **/ +gint +gmyth_recprofile_set(GMythRecProfile * rec, gchar * member, gchar * value) +{ + int ret = 0; + + if (value != NULL) { + if (g_ascii_strcasecmp(member, "name") == 0) + rec->name = g_strndup(value, strlen(value)); + else if (g_ascii_strcasecmp(member, "group") == 0) + rec->group = g_strndup(value, strlen(value)); + else if (g_ascii_strcasecmp(member, "vcodec") == 0) + rec->vcodec = g_strndup(value, strlen(value)); + else if (g_ascii_strcasecmp(member, "acodec") == 0) + rec->acodec = g_strndup(value, strlen(value)); + else + ret = -1; + } else + ret = -1; + + return ret; +} + +/** + * + * gmyth_recprofile_set_name + * @brief set recprofile's name + * @param rec GMythRecProfile* + * @param name profile's name + * @return gint representing the result + * + **/ +gint +gmyth_recprofile_set_name(GMythRecProfile * rec, gchar * name) +{ + return gmyth_recprofile_set(rec, "name", name); +} + +/** + * + * gmyth_recprofile_set_group + * @brief set recprofile's group + * @param rec GMythRecProfile* + * @param group profile's group + * @return gint representing the result + * + **/ +gint +gmyth_recprofile_set_group(GMythRecProfile * rec, gchar * group) +{ + return gmyth_recprofile_set(rec, "group", group); +} + +/** + * + * gmyth_recprofile_set_vcodec + * @brief set recprofile's vcodec + * @param rec GMythRecProfile* + * @param vcodec profile's vcodec + * @return gint representing the result + * + **/ +gint +gmyth_recprofile_set_vcodec(GMythRecProfile * rec, gchar * vcodec) +{ + return gmyth_recprofile_set(rec, "vcodec", vcodec); +} + +/** + * + * gmyth_recprofile_set_acodec + * @brief set recprofile's acodec + * @param rec GMythRecProfile* + * @param acodec profile's acodec + * @return gint representing the result + * + **/ +gint +gmyth_recprofile_set_acodec(GMythRecProfile * rec, gchar * acodec) +{ + return gmyth_recprofile_set(rec, "acodec", acodec); +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_recprofile.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_recprofile.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,123 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_recprofile.h + * + * @brief

This file contains the recprofile class. + * + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. + * @author Artur Duque de Souza + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _GMYTH_RECPROFILE_H +#define _GMYTH_RECPROFILE_H + +#include +#include + +#include "gmyth_stringlist.h" +#include "gmyth_backendinfo.h" +#include "gmyth_socket.h" + +G_BEGIN_DECLS +#define GMYTH_RECPROFILE_TYPE (gmyth_recprofile_get_type ()) +#define GMYTH_RECPROFILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_RECPROFILE_TYPE, GMythRecProfile)) +#define GMYTH_RECPROFILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECPROFILE_TYPE, GMythRecProfileClass)) +#define IS_GMYTH_RECPROFILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_RECPROFILE_TYPE)) +#define IS_GMYTH_RECPROFILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECPROFILE_TYPE)) +#define GMYTH_RECPROFILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_RECPROFILE_TYPE, GMythRecProfileClass)) +typedef struct _Options Options; +typedef struct _GMythRecProfile GMythRecProfile; +typedef struct _GMythRecProfileClass GMythRecProfileClass; + +struct _GMythRecProfileClass { + GObjectClass parent_class; + gint teste; + /* + * callbacks + */ +}; + +struct _GMythRecProfile { + gint id; + gchar *name; + gchar *group; + gchar *vcodec; + gchar *acodec; + Options *options; +}; + +struct _Options { + gint transcodelossless; + gint transcoderesize; + gint width; + gint height; + gint rtjpegquality; + gint rtjpeglumafilter; + gint rtjpegchromafilter; + gint mpeg4bitrate; + gint mpeg4maxquality; + gint mpeg4minquality; + gint mpeg4qualdiff; + gint mpeg4scalebitrate; + gint mpeg4optionvhq; + gint mpeg4option4mv; + gint mpeg4optionidct; + gint mpeg4optionime; + gint hardwaremjpegquality; + gint hardwaremjpeghdecimation; + gint hardwaremjpegvdecimation; + gchar *mpeg2streamtype; + gchar *mpeg2aspectratio; + gint mpeg2bitrate; + gint mpeg2maxbitrate; + gint samplerate; + gint mp3quality; + gint volume; + gchar *mpeg2audtype; + gint mpeg2audbitratel1; + gint mpeg2audbitratel2; + gint mpeg2audvolume; +}; + +GType gmyth_recprofile_type(void); + +GMythRecProfile *gmyth_recprofile_new(void); + +GSList *gmyth_recprofile_get_profile_list(GMythBackendInfo * + backend_info); + +gint gmyth_recprofile_create_profile(GMythBackendInfo * + backend_info, + GMythRecProfile * profile); + +gint gmyth_recprofile_del_profile_list(GMythBackendInfo * + backend_info, gint id); + +gint gmyth_recprofile_set_acodec(GMythRecProfile * rec, + gchar * acodec); +gint gmyth_recprofile_set_vcodec(GMythRecProfile * rec, + gchar * vcodec); +gint gmyth_recprofile_set_group(GMythRecProfile * rec, + gchar * group); +gint gmyth_recprofile_set_name(GMythRecProfile * rec, + gchar * name); +gint gmyth_recprofile_set_id(GMythRecProfile * rec, gint id); + +G_END_DECLS +#endif /*_GMYTH_RECPROFILE_H*/ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_remote_util.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_remote_util.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,126 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_remote_util.c + * + * @brief

This component provides utility functions for accessing remote data. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * @author Rosfran Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_remote_util.h" + +#include "gmyth_recorder.h" +#include "gmyth_stringlist.h" +#include "gmyth_debug.h" + +/** + * Requests the Mythtv backend for a free remote recorder. + * + * @param socket The socket instance where to send the command. + * @param curr The recorder index, or -1 to consider the first one. + * + * @return the remote encoder instance available, or NULL if any error happens. + */ +GMythRecorder * +remote_request_next_free_recorder(GMythSocket * socket, gint curr) +{ + GMythRecorder *recorder = NULL; + GString *hostname; + gint num, + port; + + GMythStringList *strlist = gmyth_string_list_new(); + + gmyth_debug("[%s] Request next free recorder in the backend", + __FUNCTION__); + + gmyth_string_list_append_char_array(strlist, "GET_NEXT_FREE_RECORDER"); + gmyth_string_list_append_int(strlist, curr); + + if (!gmyth_socket_sendreceive_stringlist(socket, strlist)) { + g_warning("GET_NEXT_FREE_RECORDER request error!\n"); + return NULL; + } + + num = gmyth_string_list_get_int(strlist, 0); + hostname = gmyth_string_list_get_string(strlist, 1); + port = gmyth_string_list_get_int(strlist, 2); + + if (num < 0 || port < 0) + goto clean_up; + + gmyth_debug + ("[%s] Free recorder info received: num: %d, hostname: %s, port: %d", + __FUNCTION__, num, hostname->str, port); + + recorder = gmyth_recorder_new(num, hostname, port); + + clean_up: + + g_string_free(hostname, TRUE); + g_object_unref(strlist); + + return recorder; +} + +/** + * Requests the Mythtv backend for the number of free remote recorders. + * + * @param socket The socket instance where to send the command. + * + * @return the number of remote encoders instance available, or 0 if no one is actually free.. + */ +gint +gmyth_remote_util_get_free_recorder_count(GMythSocket * socket) +{ + gint num_recs = 0; + + GMythStringList *strlist = gmyth_string_list_new(); + + gmyth_debug("[%s] Request next free recorder in the backend", + __FUNCTION__); + + gmyth_string_list_append_char_array(strlist, + "GET_FREE_RECORDER_COUNT"); + + if (!gmyth_socket_sendreceive_stringlist(socket, strlist)) { + gmyth_debug("GET_FREE_RECORDER_COUNT request error!"); + return 0; + } + + num_recs = gmyth_string_list_get_int(strlist, 0); + + if (num_recs < 0) + goto clean_up; + + gmyth_debug("[%s] Free recorder info received: num recorders: %d", + __FUNCTION__, num_recs); + + clean_up: + + g_object_unref(strlist); + + return num_recs; +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_remote_util.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_remote_util.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,41 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_remote_util.h + * + * @brief

This component provides utility functions for accessing remote data. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __REMOTE_UTIL_H__ +#define __REMOTE_UTIL_H__ + +#include +#include "gmyth_recorder.h" +#include "gmyth_socket.h" + +G_BEGIN_DECLS + GMythRecorder * remote_request_next_free_recorder(GMythSocket * socket, + gint curr); +gint gmyth_remote_util_get_free_recorder_count(GMythSocket * + socket); + +G_END_DECLS +#endif diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_scheduler.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_scheduler.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,1266 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_scheduler.c + * + * @brief

The scheduler encapsulates all functions for browsing, scheduling + * and modifying the recorded content. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Alexsandro Jose Virginio dos Santos + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include + +#include "gmyth_scheduler.h" +#include "gmyth_util.h" +#include "gmyth_query.h" +#include "gmyth_socket.h" +#include "gmyth_debug.h" + +static void gmyth_scheduler_class_init(GMythSchedulerClass * klass); +static void gmyth_scheduler_init(GMythScheduler * object); + +static void gmyth_scheduler_dispose(GObject * object); +static void gmyth_scheduler_finalize(GObject * object); + +static gboolean update_backend(GMythScheduler * scheduler, gint record_id); + +G_DEFINE_TYPE(GMythScheduler, gmyth_scheduler, G_TYPE_OBJECT) + static void gmyth_scheduler_class_init(GMythSchedulerClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_scheduler_dispose; + gobject_class->finalize = gmyth_scheduler_finalize; +} + +static void +gmyth_scheduler_init(GMythScheduler * sched) +{ + sched->recordid = 0; + sched->type = 0; + sched->search = 0; + sched->profile = g_string_new(""); + + sched->dupin = 0; + sched->dupmethod = 0; + sched->autoexpire = 0; + sched->autotranscode = 0; + sched->transcoder = 0; + + sched->autocommflag = 0; + sched->autouserjob1 = 0; + sched->autouserjob2 = 0; + sched->autouserjob3 = 0; + sched->autouserjob4 = 0; + + sched->startoffset = 0; + sched->endoffset = 0; + sched->maxepisodes = 0; + sched->maxnewest = 0; + + sched->recpriority = 0; + sched->recgroup = g_string_new(""); + sched->playgroup = g_string_new(""); + + sched->prefinput = 0; + sched->inactive = 0; + + sched->search_type = g_string_new(""); + sched->search_what = g_string_new(""); + + sched->msqlquery = gmyth_query_new(); +} + +static void +gmyth_scheduler_dispose(GObject * object) +{ + GMythScheduler *scheduler = GMYTH_SCHEDULER(object); + + if (scheduler->backend_info) { + g_object_unref(scheduler->backend_info); + scheduler->backend_info = NULL; + } + + if (scheduler->msqlquery) { + g_object_unref(scheduler->msqlquery); + scheduler->msqlquery = NULL; + } + + g_string_free(scheduler->profile, TRUE); + g_string_free(scheduler->recgroup, TRUE); + g_string_free(scheduler->playgroup, TRUE); + g_string_free(scheduler->search_type, TRUE); + g_string_free(scheduler->search_what, TRUE); + + G_OBJECT_CLASS(gmyth_scheduler_parent_class)->dispose(object); +} + +static void +gmyth_scheduler_finalize(GObject * object) +{ + g_signal_handlers_destroy(object); + + G_OBJECT_CLASS(gmyth_scheduler_parent_class)->finalize(object); +} + +/** Creates a new instance of GMythScheduler. + * + * @return a new instance of GMythScheduler. + */ +GMythScheduler * +gmyth_scheduler_new() +{ + GMythScheduler *scheduler = + GMYTH_SCHEDULER(g_object_new(GMYTH_SCHEDULER_TYPE, NULL)); + + return scheduler; +} + +gboolean +gmyth_scheduler_connect(GMythScheduler * scheduler, + GMythBackendInfo * backend_info) +{ + return gmyth_scheduler_connect_with_timeout(scheduler, backend_info, + 0); +} + +/** Connects to the Mysql database in the backend. The backend address + * is loaded from the GMythSettings instance. + * + * @param scheduler the GMythScheduler instance to be connected. + * @return true if connection was success, false if failed. + */ +gboolean +gmyth_scheduler_connect_with_timeout(GMythScheduler * scheduler, + GMythBackendInfo * backend_info, + guint timeout) +{ + assert(scheduler); + g_return_val_if_fail(backend_info != NULL, FALSE); + + if (scheduler->backend_info) + g_object_unref(scheduler->backend_info); + + scheduler->backend_info = g_object_ref(backend_info); + + if (scheduler->msqlquery == NULL) { + g_warning("[%s] GMythScheduler db initializing", __FUNCTION__); + scheduler->msqlquery = gmyth_query_new(); + } + + if (!gmyth_query_connect_with_timeout(scheduler->msqlquery, + scheduler->backend_info, + timeout)) { + g_warning("[%s] Error while connecting to db", __FUNCTION__); + return FALSE; + } + + return TRUE; +} + +/** Disconnects from the Mysql database in the backend. + * + * @param scheduler the GMythScheduler instance to be disconnected + * @return true if disconnection was success, false if failed. + */ +gboolean +gmyth_scheduler_disconnect(GMythScheduler * scheduler) +{ + assert(scheduler); + + if (scheduler->msqlquery != NULL) { + gmyth_query_disconnect(scheduler->msqlquery); + } + + return TRUE; +} + +/** Retrieves from the backend Mysql database the list of recording schedules. + * + * @param scheduler The GMythScheduler instance. + * @param schedule_list the GList pointer to be filled with the loaded list of ScheduleInfo items. + * @return The amount of schedules retrieved from database, or -1 if error. + */ +gint +gmyth_scheduler_get_schedule_list(GMythScheduler * scheduler, + GList ** schedule_list) +{ + ScheduleInfo *schedule; + MYSQL_RES *msql_res; + GString *query_str = g_string_new(""); + gchar *date_time = NULL; + + assert(scheduler); + + g_string_printf(query_str, + "SELECT recordid,programid,chanid,starttime,startdate," + "endtime,enddate,title,subtitle,description,category,type,parentid,seriesid FROM record;"); + + if (scheduler->msqlquery == NULL) { + g_warning("[%s] Scheduler db connection not initialized", + __FUNCTION__); + return -1; + } + msql_res = + gmyth_query_process_statement(scheduler->msqlquery, + query_str->str); + + if (msql_res == NULL) { + g_warning("DB retrieval of schedule list failed"); + return -1; + } else { + MYSQL_ROW row; + + *schedule_list = NULL; + + while ((row = mysql_fetch_row(msql_res)) != NULL) { + schedule = g_new0(ScheduleInfo, 1); + gint type = 0; + + schedule->schedule_id = + (guint) g_ascii_strtoull(row[0], NULL, 10); + schedule->program_id = g_string_new (row[1]); + schedule->channel_id = (gint) g_ascii_strtoull (row[2], NULL, 10); + + /* + * generate a time_t from a time and a date db field + */ + date_time = g_strdup_printf("%sT%s", row[4], row[3]); + schedule->start_time = + gmyth_util_string_to_time_val(date_time); + g_free(date_time); + + /* + * generate a time_t from a time and a date db field + */ + date_time = g_strdup_printf("%sT%s", row[6], row[5]); + schedule->end_time = gmyth_util_string_to_time_val(date_time); + g_free(date_time); + + schedule->title = g_string_new(row[7]); + schedule->subtitle = g_string_new(row[8]); + schedule->description = g_string_new(row[9]); + schedule->category = g_string_new(row[10]); + type = g_ascii_strtoull (row[11], NULL, 10); + if (type == 4) { + schedule->type = GMYTH_SCHEDULE_ALL_OCCURRENCES; + } else if (type == 1) { + schedule->type = GMYTH_SCHEDULE_ONE_OCCURRENCE; + } else if (type == 8) { + schedule->type = GMYTH_SCHEDULE_EXCEPTION; + schedule->parentid = (gint) g_ascii_strtoull (row[12], NULL, 10); + } + + schedule->seriesid = g_string_new (row[13]); + + (*schedule_list) = g_list_append(*(schedule_list), schedule); + } + } + + mysql_free_result(msql_res); + g_string_free(query_str, TRUE); + + return (*schedule_list == NULL) ? 0 : g_list_length(*schedule_list); +} + +/** Retrieves from the backend Mysql database the list of recorded programs. + * + * @param scheduler The GMythScheduler instance. + * @param recorded_list the GList pointer to be filled with the loaded RecordInfo items. + * @return The amount of recorded retrieved from database, or -1 if error. + */ +gint +gmyth_scheduler_get_recorded_list(GMythScheduler * scheduler, + GList ** recorded_list) +{ + RecordedInfo *record; + MYSQL_RES *msql_res; + GString *query_str = g_string_new(""); + + assert(scheduler); + + g_string_printf(query_str, + "SELECT recordid,programid,chanid,starttime,progstart," + "endtime,progend,title,subtitle,description,category," + "filesize,basename,seriesid FROM recorded WHERE recgroup != 'LiveTV'"); + + if (scheduler->msqlquery == NULL) { + g_warning("[%s] Scheduler db connection not initialized", + __FUNCTION__); + return -1; + } + + msql_res = + gmyth_query_process_statement(scheduler->msqlquery, + query_str->str); + + if (msql_res == NULL) { + g_warning("DB retrieval of recording list failed"); + return -1; + } else { + MYSQL_ROW row; + + (*recorded_list) = NULL; + + while ((row = mysql_fetch_row(msql_res)) != NULL) { + record = g_new0(RecordedInfo, 1); + + record->record_id = (guint) g_ascii_strtoull(row[0], NULL, 10); + record->program_id = g_string_new (row[1]); + record->channel_id = (gint) g_ascii_strtoull(row[2], NULL, 10); + record->start_time = gmyth_util_string_to_time_val(row[3]); + record->end_time = gmyth_util_string_to_time_val(row[5]); + + record->title = g_string_new(row[7]); + record->subtitle = g_string_new(row[8]); + record->description = g_string_new(row[9]); + record->category = g_string_new(row[10]); + record->filesize = g_ascii_strtoull(row[11], NULL, 10); + record->basename = g_string_new(row[12]); + record->seriesid = g_string_new(row[13]); + + (*recorded_list) = g_list_append((*recorded_list), record); + } + } + + mysql_free_result(msql_res); + g_string_free(query_str, TRUE); + + return (*recorded_list == NULL) ? 0 : g_list_length(*recorded_list); +} + +RecordedInfo* +gmyth_scheduler_get_recorded_info (GMythScheduler *scheduler, + const gchar* basename) +{ + RecordedInfo *record = NULL; + MYSQL_RES *msql_res; + GString *query_str = g_string_new(""); + + assert(scheduler); + + g_string_printf(query_str, + "SELECT recordid,programid,chanid,starttime,progstart," + "endtime,progend,title,subtitle,description,category," + "filesize,basename,seriesid FROM recorded " + "WHERE recgroup != 'LiveTV' AND basename = '%s'", basename); + + if (scheduler->msqlquery == NULL) { + g_warning("[%s] Scheduler db connection not initialized", + __FUNCTION__); + return NULL; + } + + msql_res = + gmyth_query_process_statement(scheduler->msqlquery, + query_str->str); + + if (msql_res == NULL) { + g_warning("DB retrieval of recording list failed"); + return NULL; + } else { + MYSQL_ROW row; + row = mysql_fetch_row(msql_res); + if (row != NULL) { + record = g_new0(RecordedInfo, 1); + record->record_id = (guint) g_ascii_strtoull(row[0], NULL, 10); + record->program_id = g_string_new (row[1]); + record->channel_id = (gint) g_ascii_strtoull(row[2], NULL, 10); + record->start_time = gmyth_util_string_to_time_val(row[3]); + record->end_time = gmyth_util_string_to_time_val(row[5]); + record->title = g_string_new(row[7]); + record->subtitle = g_string_new(row[8]); + record->description = g_string_new(row[9]); + record->category = g_string_new(row[10]); + record->filesize = g_ascii_strtoull(row[11], NULL, 10); + record->basename = g_string_new(row[12]); + record->seriesid = g_string_new(row[13]); + } + } + + mysql_free_result(msql_res); + g_string_free(query_str, TRUE); + + return record; +} + + +static void +_set_value(GMythQuery * myth_query, char *field, gchar * value, + gint rec_id) +{ + gchar *query = + g_strdup_printf + ("UPDATE record SET recordid = %d, %s = \"%s\" WHERE recordid = %d;", + rec_id, field, value, rec_id); + + gmyth_query_process_statement(myth_query, query); + g_free(query); +} + +static void +_set_int_value(GMythQuery * myth_query, char *field, gint value, + gint rec_id) +{ + gchar *str_value = g_strdup_printf("%d", value); + + _set_value(myth_query, field, str_value, rec_id); + g_free(str_value); +} + +ScheduleInfo* +gmyth_scheduler_add_schedule_program (GMythScheduler * scheduler, + GMythProgramInfo *program, + GMythScheduleType type) +{ + ScheduleInfo *info; + + info = g_new0 (ScheduleInfo, 1); + info->program_id = g_string_new (program->program_id->str); + info->channel_id = program->channel_id; + info->start_time = g_new0 (GTimeVal, 1); + *info->start_time = *program->startts; + info->end_time = g_new0 (GTimeVal, 1); + *info->end_time = *program->endts; + info->seriesid = g_string_new (program->seriesid->str); + info->title = g_string_new (program->title->str); + info->subtitle = g_string_new (program->subtitle->str); + info->description = g_string_new (program->description->str); + info->category = g_string_new (program->category->str); + info->type = type; + + if (gmyth_scheduler_add_schedule_full (scheduler, info, type)) + { + if (!program->recstartts) + program->recstartts = g_new0 (GTimeVal, 1); + *program->recstartts = *info->start_time; + + if (!program->recendts) + program->recendts = g_new0 (GTimeVal, 1); + *program->recendts = *info->end_time; + + program->recordid = info->schedule_id; + return info; + } + + gmyth_schedule_info_free (info); + return NULL; +} + + +gboolean +gmyth_scheduler_add_schedule_full (GMythScheduler * scheduler, + ScheduleInfo * schedule_info, GMythScheduleType type) +{ + MYSQL_RES *msql_res; + gchar *query_str = "INSERT record (recordid) VALUE (0);"; + gchar *station = NULL; + gulong rec_id; + + g_return_val_if_fail (IS_GMYTH_SCHEDULER (scheduler), FALSE); + + if (scheduler->msqlquery == NULL) { + g_warning("[%s] Scheduler db connection not initialized", + __FUNCTION__); + return FALSE; + } + + msql_res = + gmyth_query_process_statement_with_increment(scheduler->msqlquery, + query_str, &rec_id); + mysql_free_result(msql_res); + + // Retrieves the station info + query_str = + g_strdup_printf + ("SELECT callsign FROM channel WHERE chanid = %d;", + schedule_info->channel_id); + msql_res = + gmyth_query_process_statement(scheduler->msqlquery, query_str); + if (msql_res == NULL) { + g_warning("[%s] msql query returned NULL MYSQL_RES", __FUNCTION__); + return FALSE; + } else { + MYSQL_ROW row; + + if ((row = mysql_fetch_row(msql_res)) != NULL) { + station = g_strdup(row[0]); + } + } + mysql_free_result(msql_res); + g_free(query_str); + + // _set_value (field, value, id); + _set_int_value(scheduler->msqlquery, "chanid", + schedule_info->channel_id, rec_id); + _set_value(scheduler->msqlquery, "station", station, rec_id); + _set_value(scheduler->msqlquery, "title", schedule_info->title->str, + rec_id); + // / subtitle, description + _set_value(scheduler->msqlquery, "starttime", + gmyth_util_time_to_string_only_time(schedule_info-> + start_time), rec_id); + _set_value(scheduler->msqlquery, "startdate", + gmyth_util_time_to_string_only_date(schedule_info-> + start_time), rec_id); + _set_value(scheduler->msqlquery, "endtime", + gmyth_util_time_to_string_only_time(schedule_info-> + end_time), rec_id); + _set_value(scheduler->msqlquery, "enddate", + gmyth_util_time_to_string_only_date(schedule_info-> + end_time), rec_id); + // / category, series id, program id + // _set_value (scheduler->msqlquery, "findday", + // (gmyth_util_time_val_to_date( schedule_info->start_time + // ))->tm_wday, rec_id); + // _set_value (scheduler->msqlquery, "findtime", + // gmyth_util_time_to_string_only_time( schedule_info->start_time), + // rec_id); + // _set_int_value (scheduler->msqlquery, "findid", + // (gint)(schedule_info->start_time->tv_sec/60/60/24 + 719528), + // rec_id); + + if (schedule_info->seriesid) + _set_value(scheduler->msqlquery, "seriesid", + schedule_info->seriesid->str, rec_id); + + _set_value(scheduler->msqlquery, "parentid", "0", rec_id); + _set_value(scheduler->msqlquery, "search", "0", rec_id); + + if (type == GMYTH_SCHEDULE_ALL_OCCURRENCES) { + _set_int_value(scheduler->msqlquery, "type", 3, rec_id); + } else if (type == GMYTH_SCHEDULE_ONE_OCCURRENCE) { + _set_int_value(scheduler->msqlquery, "type", 1, rec_id); + } else if (type == GMYTH_SCHEDULE_EXCEPTION) { + _set_int_value(scheduler->msqlquery, "type", 8, rec_id); + _set_int_value(scheduler->msqlquery, "parentid", schedule_info->parentid, + rec_id); + } + + _set_value(scheduler->msqlquery, "recpriority", "0", rec_id); + _set_value(scheduler->msqlquery, "startoffset", "0", rec_id); + _set_value(scheduler->msqlquery, "endoffset", "0", rec_id); + _set_value(scheduler->msqlquery, "dupmethod", "6", rec_id); // ? + _set_value(scheduler->msqlquery, "dupin", "15", rec_id); // ? + + _set_value(scheduler->msqlquery, "prefinput", "0", rec_id); + _set_value(scheduler->msqlquery, "inactive", "0", rec_id); + _set_value(scheduler->msqlquery, "profile", "Default", rec_id); + _set_value(scheduler->msqlquery, "recgroup", "Default", rec_id); + _set_value(scheduler->msqlquery, "storagegroup", "Default", rec_id); + _set_value(scheduler->msqlquery, "playgroup", "Default", rec_id); + _set_value(scheduler->msqlquery, "autoexpire", "1", rec_id); + _set_value(scheduler->msqlquery, "maxepisodes", "0", rec_id); + _set_value(scheduler->msqlquery, "maxnewest", "0", rec_id); + _set_value(scheduler->msqlquery, "autocommflag", "1", rec_id); + _set_value(scheduler->msqlquery, "autotranscode", "0", rec_id); + _set_value(scheduler->msqlquery, "transcoder", "0", rec_id); + + _set_value(scheduler->msqlquery, "autouserjob1", "0", rec_id); + _set_value(scheduler->msqlquery, "autouserjob2", "0", rec_id); + _set_value(scheduler->msqlquery, "autouserjob3", "0", rec_id); + _set_value(scheduler->msqlquery, "autouserjob4", "0", rec_id); + + schedule_info->schedule_id = rec_id; + + /* Notify the backend of changes */ + return update_backend(scheduler, rec_id); +} + +/** Requests the Mysql database in the backend to add a new schedule. + * + * @param scheduler the GMythScheduler instance. + * @param schedule_info the ScheduleInfo with recording schedule information + * to be added. record_id = -1 to add a new schedule, otherwise this + * function will update the schedule in the db + * @return gboolean returns FALSE if some error occurs, TRUE otherwise + */ +gboolean +gmyth_scheduler_add_schedule (GMythScheduler * scheduler, + ScheduleInfo * schedule_info) +{ + return gmyth_scheduler_add_schedule_full (scheduler, schedule_info, + GMYTH_SCHEDULE_ONE_OCCURRENCE); +} + +/** Requests the Mysql database in the backend to remove an existing schedule. + * + * @param scheduler the GMythScheduler instance. + * @param schedule_id The schedule's record id to be removed + * @return gboolean TRUE if success, FALSE if error + */ +gboolean +gmyth_scheduler_delete_schedule(GMythScheduler * scheduler, gint schedule_id) +{ + + MYSQL_RES *msql_res; + GString *query_str = NULL; + + g_return_val_if_fail (scheduler != NULL, FALSE); + + + if (scheduler->msqlquery == NULL) { + g_warning("[%s] Scheduler db connection not initialized", + __FUNCTION__); + return FALSE; + } + + query_str = g_string_new(""); + g_string_printf(query_str, + "DELETE FROM record WHERE recordid=%d", schedule_id); + + msql_res = + gmyth_query_process_statement(scheduler->msqlquery, + query_str->str); + + + mysql_free_result(msql_res); + g_string_free(query_str, TRUE); + + // Notify the backend of the changes + return update_backend(scheduler, schedule_id); +} + +/* + * Add an exception program to be removed from the schedule list, when programs + * where scheduled with the GMYTH_SCHEDULE_ALL_OCCURRENCES option. + * @param scheduler the GMythScheduler instance. + * @param schedule_id the schedule id of the all occurrence schedule to be changed + * @param exception_info the ScheduleInfo to be removed from all schedule occurrences + * @return TRUE if success, FALSE if any error happens + */ +gboolean +gmyth_scheduler_add_exception (GMythScheduler *scheduler, gint schedule_id, + ScheduleInfo *exception_info) +{ + gboolean res; + + g_return_val_if_fail (scheduler != NULL, FALSE); + g_return_val_if_fail (exception_info != NULL, FALSE); + + exception_info->parentid = schedule_id; + res = gmyth_scheduler_add_schedule_full (scheduler, exception_info, GMYTH_SCHEDULE_EXCEPTION); + + return res; +} + +/** Requests the Mysql database in the backend to remove an existing recorded item. + * + * @param scheduler the GMythScheduler instance. + * @param record_id The recorded item id to be removed + * @return gboolean TRUE if success, FALSE if error + */ +gboolean +gmyth_scheduler_delete_recorded(GMythScheduler * scheduler, gint record_id) +{ + + MYSQL_RES *msql_res; + + GString *query_str = g_string_new(""); + + assert(scheduler); + + if (scheduler->msqlquery == NULL) { + g_warning("[%s] Scheduler db connection not initialized", + __FUNCTION__); + return FALSE; + } + // ======================================== + g_string_printf(query_str, + "DELETE FROM recorded WHERE recordid=%d", record_id); + + // FIXME: Mythtv implementation runs also: DELETE FROM oldfind WHERE + // recordid = x + + msql_res = + gmyth_query_process_statement(scheduler->msqlquery, + query_str->str); + + mysql_free_result(msql_res); + g_string_free(query_str, TRUE); + + // Notify the backend of the changes + return update_backend(scheduler, record_id); +} + + +gboolean gmyth_scheduler_was_recorded_before(GMythScheduler* scheduler, gint channel_id, + time_t start_time) +{ + MYSQL_RES *msql_res; + GString *query_str = g_string_new(""); + + assert(scheduler); + g_string_printf(query_str, "SELECT callsign FROM channel " + "WHERE chanid = \"%d\"", channel_id); + + msql_res = gmyth_query_process_statement(scheduler->msqlquery, query_str->str); + + if (msql_res) { + MYSQL_ROW msql_row = mysql_fetch_row(msql_res); + if (msql_row) { + GString* callsign = g_string_new(msql_row[0]); + GString* startts = gmyth_util_time_to_string(start_time); + g_string_printf(query_str, "SELECT * FROM oldrecorded " + "WHERE station = \"%s\" AND starttime = \"%s\"", + callsign->str, startts->str); + msql_res = gmyth_query_process_statement(scheduler->msqlquery, query_str->str); + g_string_free(callsign, TRUE); + g_string_free(startts, TRUE); + g_string_free(query_str, TRUE); + if (mysql_fetch_row(msql_res)) return TRUE; + } + } + return FALSE; +} + + +gboolean gmyth_scheduler_reactivate_schedule(GMythScheduler* scheduler, gint channel_id, + time_t start_time) + +{ + MYSQL_RES *msql_res; + GString *query_str = g_string_new(""); + + assert(scheduler); + g_string_printf(query_str, "SELECT callsign FROM channel " + "WHERE chanid = \"%d\"", channel_id); + + msql_res = gmyth_query_process_statement(scheduler->msqlquery, query_str->str); + if (msql_res) { + MYSQL_ROW msql_row = mysql_fetch_row(msql_res); + if (msql_row) { + GString* callsign = g_string_new(msql_row[0]); + GString* startts = gmyth_util_time_to_string(start_time); + g_string_printf(query_str, "UPDATE oldrecorded SET reactivate = 1 " + "WHERE station = \"%s\" AND starttime = \"%s\"", + callsign->str, startts->str); + gmyth_query_process_statement(scheduler->msqlquery, query_str->str); + g_string_free(callsign, TRUE); + g_string_free(startts, TRUE); + g_string_free(query_str, TRUE); + return TRUE; + } + + } + + return FALSE; +} + + +/* + * This should only be used in special situations. We do not know the time that + * the recording was set. We just know that it is an "ongoing" record and then + * we have to use this to get it's info. It's always the oldest one -> first on list + * + */ +GMythProgramInfo* +gmyth_scheduler_get_recorded_on_time(GMythScheduler* scheduler, + guint channel_id) +{ + MYSQL_RES *msql_res; + GMythProgramInfo *proginfo = NULL; + GString *query_str = g_string_new(""); + + assert(scheduler); + + g_string_printf(query_str, + "SELECT recorded.chanid,starttime,endtime,title," + "subtitle,description,channel.channum," + "channel.callsign,channel.name,channel.commfree," + "channel.outputfilters,seriesid,programid,filesize," + "lastmodified,stars,previouslyshown,originalairdate," + "hostname,recordid,transcoder,playgroup," + "recorded.recpriority,progstart,progend,basename,recgroup," + "category,findid,duplicate " + "FROM recorded " "LEFT JOIN channel " + "ON recorded.chanid = channel.chanid " + "WHERE recorded.chanid = %d " + "ORDER BY starttime DESC", channel_id); + + msql_res = + gmyth_query_process_statement(scheduler->msqlquery, query_str->str); + + if (msql_res) { + MYSQL_ROW msql_row = mysql_fetch_row(msql_res); + + if (msql_row) { + proginfo = gmyth_program_info_new(); + + proginfo->channel_id = (gint) g_ascii_strtoull (msql_row[0], NULL, 10); + proginfo->recstartts = gmyth_util_string_to_time_val(msql_row[1]); + proginfo->recendts = gmyth_util_string_to_time_val(msql_row[2]); + + proginfo->title = g_string_new(msql_row[3]); + proginfo->subtitle = g_string_new(msql_row[4]); + proginfo->description = g_string_new(msql_row[5]); + + proginfo->chanstr = g_string_new(msql_row[6]); + proginfo->chansign = g_string_new(msql_row[7]); + proginfo->channame = g_string_new(msql_row[8]); + proginfo->chancommfree = (gint) g_ascii_strtoull(msql_row[9], NULL, 10); + proginfo->chanOutputFilters = g_string_new(msql_row[10]); + proginfo->seriesid = g_string_new(msql_row[11]); + proginfo->program_id = g_string_new(msql_row[12]); + proginfo->filesize = g_ascii_strtoull(msql_row[13], NULL, 10); + + proginfo->lastmodified = gmyth_util_string_to_time_val(msql_row[14]); + proginfo->stars = g_ascii_strtod(msql_row[15], NULL); + proginfo->repeat = (gint)g_ascii_strtoull(msql_row[16], NULL, 10); + + if (msql_row[17] == NULL) { + proginfo->originalAirDate = 0; + proginfo->hasAirDate = FALSE; + } else { + proginfo->originalAirDate = gmyth_util_string_to_time_val(msql_row[17]); + proginfo->hasAirDate = TRUE; + } + + proginfo->hostname = g_string_new(msql_row[18]); + proginfo->recordid = (gint) g_ascii_strtoull(msql_row[19], NULL, 10); + proginfo->transcoder = (gint) g_ascii_strtoull(msql_row[20], NULL, 10); + + proginfo->playgroup = g_string_new(msql_row[21]); + proginfo->recpriority = (gint) g_ascii_strtoull(msql_row[22], NULL, 10); + + proginfo->startts = gmyth_util_string_to_time_val(msql_row[23]); + proginfo->endts = gmyth_util_string_to_time_val(msql_row[24]); + proginfo->pathname = g_string_new(g_strdup(msql_row[25])); + proginfo->recgroup = g_string_new(msql_row[26]); + proginfo->category = g_string_new(msql_row[27]); + proginfo->findid = (gint) g_ascii_strtoull(msql_row[28], NULL, 10); + + proginfo->recpriority2 = 0; + + g_string_printf(query_str, + "SELECT dupmethod,dupin,parentid,type " + "FROM record WHERE recordid = \"%d\"", proginfo->recordid); + + msql_res = + gmyth_query_process_statement(scheduler->msqlquery, + query_str->str); + + if (msql_res) { + MYSQL_ROW msql_row = mysql_fetch_row(msql_res); + + if (msql_row) { + proginfo->dupmethod = (gint) g_ascii_strtoull(msql_row[0], NULL, 10); + proginfo->dupin = (gint) g_ascii_strtoull(msql_row[1], NULL, 10); + proginfo->parentid = (gint) g_ascii_strtoull(msql_row[2], NULL, 10); + proginfo->rectype = 0; + } + } + + + g_string_printf(query_str, + "SELECT sourceid,cardid,cardinputid,shareable " + "FROM cardinput"); + + msql_res = + gmyth_query_process_statement(scheduler->msqlquery, + query_str->str); + + if (msql_res) { + MYSQL_ROW msql_row = mysql_fetch_row(msql_res); + + if (msql_row) { + proginfo->sourceid = 0; + proginfo->cardid = 0; + proginfo->inputid = 0; + if (msql_row[3] != NULL && g_ascii_strcasecmp("Y", msql_row[3]) == 0) + proginfo->shareable = 1; + else + proginfo->shareable = 0; + } + } + + + + } + } + + g_string_free(query_str, TRUE); + return proginfo; +} + +/** Retrieves an existing recorded item information from database. The information + * is used to fill the returned GMythProgramInfo. + * + * @param scheduler The GMythScheduler instance. + * @param channel The channel associated to the record + * @param starttime The record start time + * @return A GMythProgramInfo struct with the requested record item + * information, or NULL if error. + */ +GMythProgramInfo * +gmyth_scheduler_get_recorded(GMythScheduler * scheduler, + GString * channel, GTimeVal * starttime) +{ + MYSQL_RES *msql_res; + GMythProgramInfo *proginfo = NULL; + GString *query_str = g_string_new(""); + gchar *time_str = + gmyth_util_time_to_string_from_time_val(starttime); + + assert(scheduler); + + gmyth_debug("[%s] channel: %s", __FUNCTION__, channel->str); + + if (scheduler->msqlquery == NULL) { + g_warning("[%s] Scheduler db connection not initialized", + __FUNCTION__); + return NULL; + } + + g_string_printf(query_str, + "SELECT recorded.chanid,starttime,endtime,title, " + "subtitle,description,channel.channum, " + "channel.callsign,channel.name,channel.commfree, " + "channel.outputfilters,seriesid,programid,filesize, " + "lastmodified,stars,previouslyshown,originalairdate, " + "hostname,recordid,transcoder,playgroup, " + "recorded.recpriority,progstart,progend,basename,recgroup " + "FROM recorded " "LEFT JOIN channel " + "ON recorded.chanid = channel.chanid " + "WHERE recorded.chanid = \"%s\" " + "AND starttime = \"%s\" ;", channel->str, time_str); + + msql_res = + gmyth_query_process_statement(scheduler->msqlquery, + query_str->str); + + if (msql_res /* && query.size() > 0 */ ) { + MYSQL_ROW msql_row = mysql_fetch_row(msql_res); + + if (msql_row) { + proginfo = gmyth_program_info_new(); + + proginfo->channel_id = (gint) g_ascii_strtoull (msql_row[0], NULL, 10); + proginfo->startts = + gmyth_util_string_to_time_val(msql_row[23]); + proginfo->endts = gmyth_util_string_to_time_val(msql_row[24]); + proginfo->recstartts = + gmyth_util_string_to_time_val(msql_row[1]); + proginfo->recendts = + gmyth_util_string_to_time_val(msql_row[2]); + proginfo->title = g_string_new(msql_row[3]); + proginfo->subtitle = g_string_new(msql_row[4]); + proginfo->description = g_string_new(msql_row[5]); + + proginfo->chanstr = g_string_new(msql_row[6]); + proginfo->chansign = g_string_new(msql_row[7]); + proginfo->channame = g_string_new(msql_row[0]); + proginfo->chancommfree = + (gint) g_ascii_strtoull(msql_row[9], NULL, 10); + proginfo->chanOutputFilters = g_string_new(msql_row[10]); + proginfo->seriesid = g_string_new(msql_row[11]); + proginfo->program_id = g_string_new(msql_row[12]); + proginfo->filesize = g_ascii_strtoull(msql_row[13], NULL, 10); + + proginfo->lastmodified = + gmyth_util_string_to_time_val(msql_row[14]); + proginfo->stars = g_ascii_strtod(msql_row[15], NULL); + proginfo->repeat = + (gint) g_ascii_strtoull(msql_row[16], NULL, 10); + + if (msql_row[17] == NULL) { + proginfo->originalAirDate = 0; + proginfo->hasAirDate = FALSE; + } else { + proginfo->originalAirDate = + gmyth_util_string_to_time_val(msql_row[17]); + proginfo->hasAirDate = TRUE; + } + + proginfo->hostname = g_string_new(msql_row[18]); + proginfo->recordid = + (gint) g_ascii_strtoull(msql_row[19], NULL, 10); + proginfo->transcoder = + (gint) g_ascii_strtoull(msql_row[20], NULL, 10); + // proginfo->spread = -1; + // proginfo->programflags = proginfo->getProgramFlags(); + + proginfo->recgroup = g_string_new(msql_row[26]); + proginfo->playgroup = g_string_new(msql_row[21]); + proginfo->recpriority = + (gint) g_ascii_strtoull(msql_row[22], NULL, 10); + + proginfo->pathname = g_string_new(g_strdup(msql_row[25])); + + gmyth_debug("One program info loaded from mysql database\n"); + } + } + + mysql_free_result(msql_res); + g_string_free(query_str, TRUE); + g_free(time_str); + + return proginfo; +} + +gboolean +gmyth_scheduler_stop_recording (GMythScheduler * scheduler, + gint channel_id) +{ + GMythProgramInfo *program; + GMythSocket *socket; + gboolean res = FALSE; + GMythStringList *slist; + + socket = gmyth_backend_info_get_connected_socket (scheduler->backend_info); + program = gmyth_scheduler_get_recorded_on_time (scheduler, channel_id); + + if (program) { + slist = gmyth_string_list_new(); + gmyth_string_list_append_char_array(slist, "STOP_RECORDING"); + + gmyth_string_list_append_string(slist, program->title); /* 0 */ + gmyth_string_list_append_string(slist, program->subtitle); /* 1 */ + gmyth_string_list_append_string(slist, program->description); /* 2 */ + gmyth_string_list_append_string(slist, program->category); /* 3 */ + gmyth_string_list_append_int(slist, program->channel_id); /* 4 */ + gmyth_string_list_append_string(slist, program->chanstr); /* 5 */ + gmyth_string_list_append_string(slist, program->chansign); /* 6 */ + gmyth_string_list_append_string(slist, program->channame); /* 7 */ + gmyth_string_list_append_string(slist, program->pathname); /* 8 */ + gmyth_string_list_append_int64(slist, program->filesize); /* 9 */ + + if (program->startts) + gmyth_string_list_append_int(slist, program->startts->tv_sec); /* 10 */ + else + gmyth_string_list_append_int(slist, 0); + + if (program->endts) + gmyth_string_list_append_int(slist, program->endts->tv_sec); /* 11 */ + else + gmyth_string_list_append_int(slist, 0); + + gmyth_string_list_append_int(slist, program->duplicate); /* 12 */ + gmyth_string_list_append_int(slist, program->shareable); /* 13 */ + gmyth_string_list_append_int(slist, program->findid); /* 14 */ + gmyth_string_list_append_string(slist, program->hostname); /* 15 */ + gmyth_string_list_append_int(slist, program->sourceid); /* 16 */ + gmyth_string_list_append_int(slist, program->cardid); /* 17 */ + gmyth_string_list_append_int(slist, program->inputid); /* 18 */ + gmyth_string_list_append_int(slist, program->recpriority); /* 19 */ + + // recstatus == recording + gmyth_string_list_append_int(slist, -3); /* 20 */ + + gmyth_string_list_append_int(slist, program->recordid); /* 21 */ + gmyth_string_list_append_int(slist, program->rectype); /* 22 */ + gmyth_string_list_append_int(slist, program->dupin); /* 23 */ + gmyth_string_list_append_int(slist, program->dupmethod); /* 24 */ + + + //fixme + program->recstartts->tv_sec -= (60*60); + + gmyth_string_list_append_int(slist, + program->recstartts != NULL ? + program->recstartts->tv_sec : 0); /* 26 */ + + gmyth_string_list_append_int(slist, + program->recendts != NULL ? + program->recendts->tv_sec : 0); /* 27 */ + + gmyth_string_list_append_int(slist, program->repeat); /* 28 */ + gmyth_string_list_append_int(slist, program->programflags); /* 29 */ + + gmyth_string_list_append_char_array(slist, + program->recgroup != NULL ? + program->recgroup->str : "Default"); /* 30 */ + + gmyth_string_list_append_int(slist, program->chancommfree); /* 31 */ + gmyth_string_list_append_string(slist, program->chanOutputFilters); /* 32 */ + gmyth_string_list_append_string(slist, program->seriesid); /* 33 */ + gmyth_string_list_append_string(slist, program->program_id); /* 34 */ + + gmyth_string_list_append_int(slist, + program->lastmodified != NULL ? + program->lastmodified->tv_sec : 0); /* 35 */ + + gmyth_string_list_append_float(slist, program->stars); /* 36 */ + + gmyth_string_list_append_int(slist, + program->originalAirDate != NULL ? + program->originalAirDate->tv_sec : 0); /* 37 */ + + gmyth_string_list_append_int(slist, program->hasAirDate); /* 38 */ + + gmyth_string_list_append_char_array(slist, + program->playgroup != NULL ? + program->playgroup->str : "Default"); /* 39 */ + + gmyth_string_list_append_int(slist, program->recpriority2); /* 40 */ + gmyth_string_list_append_int(slist, program->recpriority2); /* 40 */ + + gmyth_socket_sendreceive_stringlist(socket, slist); + res = (gmyth_string_list_get_int(slist, 0) == 1); + + g_object_unref (program); + g_object_unref (slist); + } + + g_object_unref (socket); + return res; +} + + +/** Notifies the backend of an update in the db. + * + * @param record_id the id of the modified recording. + */ +// fixme: put void and discovery record_id inside +static gboolean +update_backend (GMythScheduler * scheduler, + gint record_id) +{ + GMythSocket *socket; + GMythStringList *strlist = gmyth_string_list_new(); + GString *datastr = g_string_new("RESCHEDULE_RECORDINGS "); + gboolean ret = FALSE; + + g_string_append_printf(datastr, "%d", record_id); + gmyth_string_list_append_string(strlist, datastr); + + socket = gmyth_backend_info_get_connected_socket (scheduler->backend_info); + if (socket != NULL) { + ret = (gmyth_socket_sendreceive_stringlist(socket, strlist) > 0); + g_object_unref (socket); + } else { + g_warning("[%s] Connection to backend failed!", __FUNCTION__); + } + + g_string_free(datastr, TRUE); + g_object_unref(strlist); + return ret; +} + +void +gmyth_scheduler_recorded_info_get_preview(RecordedInfo * info, + GByteArray * data) +{ +} + +void +gmyth_recorded_info_free(RecordedInfo * info) +{ + g_return_if_fail (info != NULL); + + if (info->program_id) + g_string_free (info->program_id, TRUE); + + if (info->title != NULL) + g_string_free(info->title, TRUE); + + if (info->subtitle != NULL) + g_string_free(info->subtitle, TRUE); + + if (info->description != NULL) + g_string_free(info->description, TRUE); + + if (info->category != NULL) + g_string_free(info->category, TRUE); + + if (info->basename != NULL) + g_string_free(info->basename, TRUE); + + if (info != NULL) + g_free(info->start_time); + + if (info != NULL) + g_free(info->end_time); + + g_free(info); +} + +static void +free_recorded_info_item(gpointer data, gpointer user_data) +{ + RecordedInfo *info = (RecordedInfo *) data; + + gmyth_recorded_info_free(info); +} + +void +gmyth_recorded_info_list_free(GList * list) +{ + g_return_if_fail(list != NULL); + + g_list_foreach(list, free_recorded_info_item, NULL); + g_list_free(list); +} + +void +gmyth_schedule_info_free(ScheduleInfo * info) +{ + + g_return_if_fail(info != NULL); + + if (info->program_id) + g_string_free (info->program_id, TRUE); + + if (info->title != NULL) + g_string_free(info->title, TRUE); + + if (info->subtitle != NULL) + g_string_free(info->subtitle, TRUE); + + if (info->description != NULL) + g_string_free(info->description, TRUE); + + if (info->category != NULL) + g_string_free(info->category, TRUE); + + if (info != NULL) + g_free(info->start_time); + + if (info != NULL) + g_free(info->end_time); + + g_free(info); +} + +static void +free_schedule_info_item(gpointer data, gpointer user_data) +{ + ScheduleInfo *info = (ScheduleInfo *) data; + + gmyth_schedule_info_free(info); +} + +void +gmyth_schedule_info_list_free(GList * list) +{ + g_return_if_fail(list != NULL); + + g_list_foreach(list, free_schedule_info_item, NULL); + g_list_free(list); +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_scheduler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_scheduler.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,194 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_scheduler.h + * + * @brief

The scheduler encapsulates all functions for browsing, scheduling + * and modifying the recorded content. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Alexsandro Jose Virginio dos Santos + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_SCHEDULER_H__ +#define __GMYTH_SCHEDULER_H__ + +#include +#include + +#include "gmyth_common.h" +#include "gmyth_query.h" +#include "gmyth_backendinfo.h" + +G_BEGIN_DECLS + +typedef enum { + GMYTH_SCHEDULE_ONE_OCCURRENCE, + GMYTH_SCHEDULE_ALL_OCCURRENCES, + GMYTH_SCHEDULE_EXCEPTION +} GMythScheduleType; + + +#define GMYTH_SCHEDULER_TYPE (gmyth_scheduler_get_type ()) +#define GMYTH_SCHEDULER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SCHEDULER_TYPE, GMythScheduler)) +#define GMYTH_SCHEDULER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SCHEDULER_TYPE, GMythSchedulerClass)) +#define IS_GMYTH_SCHEDULER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_SCHEDULER_TYPE)) +#define IS_GMYTH_SCHEDULER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SCHEDULER_TYPE)) +#define GMYTH_SCHEDULER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_SCHEDULER_TYPE, GMythSchedulerClass)) + +typedef struct _GMythScheduler GMythScheduler; +typedef struct _GMythSchedulerClass GMythSchedulerClass; + +struct _GMythSchedulerClass { + GObjectClass parent_class; +}; + +struct _GMythScheduler { + GObject parent; + + unsigned long recordid; + unsigned long type; + unsigned long search; + GString *profile; + + long dupin; + long dupmethod; + long autoexpire; + short int autotranscode; + long transcoder; + + short int autocommflag; + short int autouserjob1; + short int autouserjob2; + short int autouserjob3; + short int autouserjob4; + + long startoffset; + long endoffset; + long maxepisodes; + long maxnewest; + + long recpriority; + GString *recgroup; + GString *playgroup; + + long prefinput; + short int inactive; + + GString *search_type; + GString *search_what; + + GMythQuery *msqlquery; + GMythBackendInfo *backend_info; +}; + +typedef struct { + guint schedule_id; + gint channel_id; + GString *program_id; + + GTimeVal *start_time; + GTimeVal *end_time; + + GString *seriesid; + GString *title; + GString *subtitle; + GString *description; + GString *category; + + GMythScheduleType type; + + gint parentid; + +} ScheduleInfo; + +typedef struct { + guint record_id; + gint channel_id; + GString *program_id; + + GTimeVal *start_time; + GTimeVal *end_time; + + GString *seriesid; + GString *title; + GString *subtitle; + GString *description; + GString *category; + + GString *basename; + + guint64 filesize; + +} RecordedInfo; + + +GType gmyth_scheduler_get_type (void); + +GMythScheduler* gmyth_scheduler_new (void); +gboolean gmyth_scheduler_connect (GMythScheduler * scheduler, + GMythBackendInfo * backend_info); +gboolean gmyth_scheduler_connect_with_timeout (GMythScheduler * scheduler, + GMythBackendInfo * backend_info, + guint timeout); +gboolean gmyth_scheduler_disconnect (GMythScheduler * scheduler); +gint gmyth_scheduler_get_schedule_list (GMythScheduler * scheduler, + GList ** sched_list); +gint gmyth_scheduler_get_recorded_list (GMythScheduler * scheduler, + GList ** rec_list); +RecordedInfo* gmyth_scheduler_get_recorded_info (GMythScheduler *scheduler, + const char *basename); +gboolean gmyth_scheduler_was_recorded_before (GMythScheduler* scheduler, + gint channel_id, + time_t start_time); +gboolean gmyth_scheduler_reactivate_schedule (GMythScheduler* scheduler, + gint channel_id, + time_t start_time); +GMythProgramInfo* gmyth_scheduler_get_recorded_on_time (GMythScheduler* scheduler, + guint channel_id); +GMythProgramInfo* gmyth_scheduler_get_recorded (GMythScheduler * scheduler, + GString * channel, + GTimeVal * starttime); +ScheduleInfo* gmyth_scheduler_add_schedule_program (GMythScheduler * scheduler, + GMythProgramInfo *program, + GMythScheduleType type); +gint gmyth_scheduler_add_schedule (GMythScheduler * scheduler, + ScheduleInfo * schedule_info); +gboolean gmyth_scheduler_add_schedule_full (GMythScheduler * scheduler, + ScheduleInfo * schedule_info, + GMythScheduleType type); +gboolean gmyth_scheduler_add_exception (GMythScheduler *scheduler, + gint schedule_id, + ScheduleInfo *exception_info); +gboolean gmyth_scheduler_delete_schedule (GMythScheduler * scheduler, + gint record_id); +gint gmyth_scheduler_delete_recorded (GMythScheduler * scheduler, + gint record_id); +gboolean gmyth_scheduler_stop_recording (GMythScheduler * scheduler, + gint channel_id); +void gmyth_scheduler_recorded_info_get_preview(RecordedInfo * info, + GByteArray * data); + + +void gmyth_recorded_info_free (RecordedInfo * info); +void gmyth_schedule_info_free (ScheduleInfo * info); +void gmyth_recorded_info_list_free (GList * list); +void gmyth_schedule_info_list_free (GList * list); + +G_END_DECLS +#endif /* __GMYTH_SCHEDULER_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_socket.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_socket.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,1295 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_socket.c + * + * @brief

MythTV socket implementation, according to the MythTV Project + * (www.mythtv.org). + * + * This component provides basic socket functionalities to interact with + * the Mythtv backend. + *

+ * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_socket.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "gmyth_stringlist.h" +#include "gmyth_uri.h" +#include "gmyth_debug.h" + +#define BUFLEN 512 +#define MYTH_SEPARATOR "[]:[]" +#define MYTH_PROTOCOL_FIELD_SIZE 8 + +/* + * max number of iterations + */ +#define MYTHTV_MAX_VERSION_CHECKS 40 + +// FIXME: put this in the right place +#define MYTHTV_VERSION_DEFAULT 31 + +/* + * static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + */ + +/* + * static GStaticRWLock rwlock = G_STATIC_RW_LOCK_INIT; + */ + +static gchar *local_hostname = NULL; + +static void gmyth_socket_class_init(GMythSocketClass * klass); +static void gmyth_socket_init(GMythSocket * object); + +static void gmyth_socket_dispose(GObject * object); +static void gmyth_socket_finalize(GObject * object); + +G_DEFINE_TYPE(GMythSocket, gmyth_socket, G_TYPE_OBJECT) + static void gmyth_socket_class_init(GMythSocketClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_socket_dispose; + gobject_class->finalize = gmyth_socket_finalize; +} + +static void +gmyth_socket_init(GMythSocket * gmyth_socket) +{ + + /* + * gmyth_socket->local_hostname = NULL; + */ + +} + +/** Gets the some important address translation info, from the client socket + * that will open a connection. + * + * @return gint that represents the error number from getaddrinfo(). + */ +static gint +gmyth_socket_toaddrinfo(const gchar * addr, gint port, + struct addrinfo **addrInfo) +{ + struct addrinfo hints; + gchar *portStr = NULL; + gint errorn = EADDRNOTAVAIL; + + g_return_val_if_fail(addr != NULL, -1); + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + /* + * hints.ai_flags = AI_NUMERICHOST; + */ + + if (port != -1) + portStr = g_strdup_printf("%d", port); + else + portStr = NULL; + + gmyth_debug("Getting name resolution for: %s, %d\n", addr, port); + + if ((errorn = getaddrinfo(addr, portStr, &hints, addrInfo)) != 0) { + gmyth_debug("[%s] Socket ERROR: %s\n", __FUNCTION__, + gai_strerror(errorn)); + } + + g_free(portStr); + + return errorn; +} + +/* + * static gint gmyth_socket_find_match_address_uri( GMythURI* uri, gchar + * *address ) { if ( g_ascii_strcasecmp( gmyth_uri_get_host( uri ), + * address ) == 0 ) { //gmyth_debug( "Found URI: %s !!!\n", + * rui_uri_getvalue(uri) ); return 0; } else { return -1; } } + */ + +const gchar *PATH_PROC_NET_DEV = "/proc/net/dev"; + +/** Gets the list of all local network interfaces (using the /proc/net/dev directory). + * + * @param current_connections A list with all the network interfaces are valid, + * to be applied just like a filter. + * @return List with all the local net interfaces. + */ +GList * +gmyth_socket_get_local_addrs(GList * current_connections) +{ + + GList *local_addrs = NULL; + FILE *fd; + gint s; + gchar buffer[256 + 1]; + gchar ifaddr[20 + 1]; + gchar *ifname; + gchar *sep; + + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) + return 0; + fd = fopen(PATH_PROC_NET_DEV, "r"); + fgets(buffer, sizeof(buffer) - 1, fd); + fgets(buffer, sizeof(buffer) - 1, fd); + while (!feof(fd)) { + ifname = buffer; + + if (fgets(buffer, sizeof(buffer) - 1, fd) == NULL) + break; + sep = strrchr(buffer, ':'); + if (sep) + *sep = 0; + while (*ifname == ' ') + ifname++; + struct ifreq req; + + strcpy(req.ifr_name, ifname); + if (ioctl(s, SIOCGIFFLAGS, &req) < 0) + continue; + if (!(req.ifr_flags & IFF_UP)) + continue; + if (req.ifr_flags & IFF_LOOPBACK) + continue; + if (ioctl(s, SIOCGIFADDR, &req) < 0) + continue; + g_strlcpy(ifaddr, + inet_ntoa(((struct sockaddr_in *) &req.ifr_addr)-> + sin_addr), sizeof(struct ifaddr) - 1); + local_addrs = g_list_append(local_addrs, g_strdup(ifaddr)); + + gmyth_debug + ("( from the /proc/net/dev) Interface name: %s, address: %s\n", + ifname, ifaddr); + } + fclose(fd); + close(s); + return local_addrs; +} + +/** + * Get only the local addresses from the primary interface + */ +gchar * +gmyth_socket_get_primary_addr(void) +{ + gchar *if_eth0 = g_new0(gchar, sizeof(struct ifaddr) - 1); + GList *if_tmp = NULL; + + GList *interfs = gmyth_socket_get_local_addrs(NULL); + + if (interfs != NULL && (g_list_length(interfs) > 0)) { + // get the first occurrence (primary interface) + if_tmp = g_list_first(interfs); + + if (if_tmp != NULL) + g_strlcpy(if_eth0, (gchar *) if_tmp->data, + sizeof(struct ifaddr) - 1); + + } + + if (interfs != NULL) + g_list_free(interfs); + + return if_eth0; +} + +/** This function retrieves the local hostname of the + * client machine. + * + * @return GString* get local hostname. + */ +GString * +gmyth_socket_get_local_hostname(void) +{ + char hname[50]; + gint res = gethostname(hname, 50); + + if (res == -1) { + gmyth_debug("Error while getting hostname"); + return g_string_new("default"); + } + + return g_string_new(hname); + +#if 0 + GString *str = NULL; + + if (local_hostname != NULL && strlen(local_hostname) > 0) + return g_string_new(local_hostname); + + gchar *localaddr = NULL; + gboolean found_addr = FALSE; + struct addrinfo *addr_info_data = NULL, + *addr_info0 = NULL; + struct sockaddr_in *sa = NULL; + gchar localhostname[MAXHOSTNAMELEN]; + + + if (gethostname(localhostname, MAXHOSTNAMELEN) != 0) { + gmyth_debug("Error on gethostname"); + } + localhostname[MAXHOSTNAMELEN - 1] = 0; + + gint err = + gmyth_socket_toaddrinfo(localhostname, -1, &addr_info_data); + + if (err == EADDRNOTAVAIL) { + gmyth_debug("[%s] Address (%s) not available. (reason = %d)\n", + __FUNCTION__, localhostname, err); + return str; + } + + g_mutex_lock(gmyth_socket->mutex); + + addr_info0 = addr_info_data; + + while (addr_info0 != NULL && addr_info0->ai_addr != NULL && + (sa = (struct sockaddr_in *) addr_info0->ai_addr) != NULL + && !found_addr) { + localaddr = inet_ntoa(sa->sin_addr); + + if (localaddr != NULL && (g_strrstr(localaddr, "127") == NULL)) { + str = g_string_new(localaddr); + found_addr = TRUE; + g_free(localaddr); + break; + } + /* + * if (localaddr != NULL) { g_free (localaddr); localaddr = NULL; + * } + */ + + addr_info0 = addr_info0->ai_next; + }; + + freeaddrinfo(addr_info_data); + addr_info_data = NULL; + + if (found_addr == FALSE) { + gchar *prim_addr = gmyth_socket_get_primary_addr(); + + if (prim_addr != NULL) { + gmyth_debug + ("[%s] Could not determine the local alphanumerical hostname. Setting to %s\n", + __FUNCTION__, prim_addr); + + str = g_string_new(prim_addr); + g_free(prim_addr); + } else { + str = g_string_new(localhostname); + } + } + + g_mutex_unlock(gmyth_socket->mutex); + + if (str != NULL && str->str != NULL) + local_hostname = g_strdup(str->str); + + return str; +#endif +} + +static void +gmyth_socket_dispose(GObject * object) +{ + GMythSocket *gmyth_socket = GMYTH_SOCKET(object); + + /* + * disconnect socket + */ + gmyth_socket_close_connection(gmyth_socket); + + g_free(gmyth_socket->hostname); + + g_free(local_hostname); + + local_hostname = NULL; + + if (gmyth_socket->mutex != NULL) { + g_mutex_free(gmyth_socket->mutex); + gmyth_socket->mutex = NULL; + } + + G_OBJECT_CLASS(gmyth_socket_parent_class)->dispose(object); +} + +static void +gmyth_socket_finalize(GObject * object) +{ + g_signal_handlers_destroy(object); + + G_OBJECT_CLASS(gmyth_socket_parent_class)->finalize(object); +} + +/** Creates a new instance of GMythSocket. + * + * @return a new instance of GMythSocket. + */ +GMythSocket * +gmyth_socket_new() +{ + GMythSocket *gmyth_socket = + GMYTH_SOCKET(g_object_new(GMYTH_SOCKET_TYPE, NULL)); + + gmyth_socket->mythtv_version = MYTHTV_VERSION_DEFAULT; + + gmyth_socket->mutex = g_mutex_new(); + + return gmyth_socket; +} + +/** Try to open an asynchronous connection to the MythTV backend. + * + * @param fd Socket descriptor. + * @param remote Remote address. + * @param len Newly created socket length field. + * @param timeout Timeval argument with the time interval to timeout before closing. + * @param err Error message number. + * @return Any numerical value below 0, if an error had been found. + */ +static gint +gmyth_socket_try_connect(gint fd, struct sockaddr *remote, gint len, + struct timeval *timeout, gint * err) +{ + /* + * g_return_val_if_fail( timeout != NULL, 0 ); + */ + gint saveflags, + ret, + back_err; + + fd_set fd_w; + + saveflags = fcntl(fd, F_GETFL, 0); + if (saveflags < 0) { + gmyth_debug("[%s] Problems when getting socket flags on fcntl.\n", + __FUNCTION__); + *err = errno; + return -1; + } + + /* + * Set non blocking + */ + if (fcntl(fd, F_SETFL, saveflags | O_NONBLOCK) < 0) { + gmyth_debug + ("[%s] Problems when setting non-blocking using fcntl.\n", + __FUNCTION__); + *err = errno; + return -1; + } + + /* + * This will return immediately + */ + *err = connect(fd, remote, len); + back_err = errno; + + /* + * restore flags + */ + if (fcntl(fd, F_SETFL, saveflags) < 0) { + gmyth_debug + ("[%s] Problems when trying to restore flags with fcntl.\n", + __FUNCTION__); + *err = errno; + return -1; + } + + /* + * return unless the connection was successful or the connect is still + * in progress. + */ + if (*err < 0 && back_err != EINPROGRESS) { + gmyth_debug + ("[%s] Connection unsucessfully (it is not in progress).\n", + __FUNCTION__); + *err = errno; + return -1; + } + + FD_ZERO(&fd_w); + FD_SET(fd, &fd_w); + + *err = select(FD_SETSIZE, NULL, &fd_w, NULL, timeout); + if (*err < 0) { + gmyth_debug("[%s] Connection unsucessfull (timed out).\n", + __FUNCTION__); + *err = errno; + return -1; + } + + /* + * 0 means it timeout out & no fds changed + */ + if (*err == 0) { + gmyth_debug + ("[%s] Connection unsucessfull [%d] - 0 means it timeout out & no fds changed\n", + __FUNCTION__, *err); + close(fd); + *err = ETIMEDOUT; + return -1; + } + + /* + * Get the return code from the connect + */ + len = sizeof(ret); + *err = getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, (socklen_t *) & len); + + if (*err < 0) { + gmyth_debug("[%s] Connection unsucessfull.\n", __FUNCTION__); + *err = errno; + return -1; + } + + /* + * ret=0 means success, otherwise it contains the errno + */ + if (ret) { + gmyth_debug + ("[%s] Connection unsucessfull - Couldn't connect to remote host!!!\n", + __FUNCTION__); + *err = ret; + return -1; + } + + *err = 0; + return 0; +} + +/** Connects to the backend. + * + * @param gmyth_socket The GMythSocket instance. + * @param hostname The backend hostname or IP address. + * @param port The backend port. + * @return TRUE if success, FALSE if error. + */ + + +gboolean +gmyth_socket_connect(GMythSocket * gmyth_socket, + const gchar * hostname, gint port) +{ + return gmyth_socket_connect_with_timeout(gmyth_socket, hostname, port, + 30); +} + +gboolean +gmyth_socket_connect_with_timeout(GMythSocket * gmyth_socket, + const gchar * hostname, gint port, + guint timeout) +{ + struct addrinfo *addr_info_data = NULL, + *addr_info0 = NULL; + struct linger ling; + gchar *tmp_str; + gint ret_code = 0; /* -1 */ + + /* + * FIXME: add as function parameter + */ + gint err; + gint errno; + gboolean ret = TRUE; + + gmyth_debug("CONNECTING %s:%d", hostname, port); + + if (hostname == NULL) + gmyth_debug("Invalid hostname parameter!\n"); + + /* + * store hostname and port number + */ + gmyth_debug("CONNECTING %s:%d", hostname, port); + + errno = gmyth_socket_toaddrinfo(hostname, port, &addr_info_data); + + g_return_val_if_fail(addr_info_data != NULL + && hostname != NULL, FALSE); + + /* + * hack to avoid deleting the hostname when gmyth_socket->hostname == + * hostname + */ + tmp_str = gmyth_socket->hostname; + + gmyth_socket->hostname = g_strdup(hostname); + gmyth_socket->port = port; + + g_free(tmp_str); + + for (addr_info0 = addr_info_data; addr_info0; + addr_info0 = addr_info_data->ai_next) { + /* + * init socket descriptor + */ + + g_debug ("FAMILY: %d, TYPE: %d, PROTOCOL: %d", + addr_info0->ai_family, + addr_info0->ai_socktype, + addr_info0->ai_protocol); + gmyth_socket->sd = + socket(addr_info0->ai_family, addr_info0->ai_socktype, + addr_info0->ai_protocol); + + if (gmyth_socket->sd < 0) + continue; + + struct timeval *timeout_val = g_new0(struct timeval, 1); + + if (timeout != 0) { + timeout_val->tv_sec = timeout; + timeout_val->tv_usec = 0; + } else { + timeout_val->tv_sec = 5; + timeout_val->tv_usec = 100; + } + + if (gmyth_socket_try_connect + (gmyth_socket->sd, (struct sockaddr *) addr_info0->ai_addr, + addr_info0->ai_addrlen, timeout_val, &ret_code) < 0) { + gmyth_debug("[%s] Error connecting to backend!\n", + __FUNCTION__); + if (ret_code == ETIMEDOUT) + gmyth_debug("[%s]\tBackend host unreachable!\n", + __FUNCTION__); + + close(gmyth_socket->sd); + gmyth_socket->sd = -1; + gmyth_debug("ERROR: %s\n", gai_strerror(ret_code)); + g_free(timeout_val); + continue; + } + + g_free(timeout_val); + + /* + * only will be reached if none of the error above occurred + */ + break; + } + + freeaddrinfo(addr_info_data); + addr_info_data = NULL; + + if (gmyth_socket->sd_io_ch != NULL) { + g_io_channel_unref(gmyth_socket->sd_io_ch); + gmyth_socket->sd_io_ch = NULL; + } + + + memset(&ling, 0, sizeof(struct linger)); + ling.l_onoff = TRUE; + ling.l_linger = 1; + + err = + setsockopt(gmyth_socket->sd, SOL_SOCKET, SO_LINGER, &ling, + sizeof(struct linger)); + + if (err < 0) { + gmyth_debug("[%s] Setting connection unsucessfull.\n", + __FUNCTION__); + err = errno; + ret = FALSE; + goto cleanup; + } + + gmyth_socket->sd_io_ch = g_io_channel_unix_new(gmyth_socket->sd); + + g_io_channel_set_close_on_unref(gmyth_socket->sd_io_ch, TRUE); + // g_io_channel_set_encoding (gmyth_socket->sd_io_ch, NULL, NULL ); + + GIOFlags flags = g_io_channel_get_flags(gmyth_socket->sd_io_ch); + + /* + * unset the nonblock flag + */ + flags &= ~G_IO_FLAG_NONBLOCK; + /* + * unset the nonblocking stuff for some time, because GNUTLS doesn't + * like that + */ + g_io_channel_set_flags(gmyth_socket->sd_io_ch, flags, NULL); + + ret = (ret_code == 0) ? TRUE : FALSE; + + cleanup: + if (!ret) + gmyth_debug("GMythSocket error - return code error!"); + + return ret; +} + +/** Gets the GIOChannel associated to the given GMythSocket. + * + * @param gmyth_socket The GMythSocket instance. + */ +GIOChannel * +gmyth_socket_get_io_channel(GMythSocket * gmyth_socket) +{ + g_return_val_if_fail(gmyth_socket != NULL, NULL); + + return gmyth_socket->sd_io_ch; +} + +/** Verifies if the socket is able to read. + * + * @param gmyth_socket The GMythSocket instance. + * @return TRUE if the socket is able to read, FALSE if not. + */ +gboolean +gmyth_socket_is_able_to_read(GMythSocket * gmyth_socket) +{ + gboolean ret = TRUE; + + /* + * verify if the input (read) buffer is ready to receive data + */ + GIOCondition io_cond = + g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch); + + if ((io_cond & G_IO_IN) == 0) { + gmyth_debug("[%s] IO channel is not able to send data!\n", + __FUNCTION__); + ret = FALSE; + } + + return ret; + +} + +/** Verifies if the socket is able to write. + * + * @param gmyth_socket The GMythSocket instance. + * @return TRUE if the socket is able to write, FALSE if not. + */ +gboolean +gmyth_socket_is_able_to_write(GMythSocket * gmyth_socket) +{ + gboolean ret = TRUE; + + /* + * verify if the input (read) buffer is ready to receive data + */ + GIOCondition io_cond = + g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch); + + if (((io_cond & G_IO_OUT) == 0) || ((io_cond & G_IO_HUP) == 0)) { + gmyth_debug("[%s] IO channel is not able to send data!\n", + __FUNCTION__); + ret = FALSE; + } + + return ret; + +} + +/** Sends a command to the backend. + * + * @param gmyth_socket the GMythSocket instance. + * @param command The string command to be sent. + */ +gboolean +gmyth_socket_send_command(GMythSocket * gmyth_socket, GString * command) +{ + gboolean ret = TRUE; + + GIOStatus io_status = G_IO_STATUS_NORMAL; + + // GIOCondition io_cond; + GError *error = NULL; + + gchar *buffer = NULL; + + gsize bytes_written = 0; + + g_return_val_if_fail(gmyth_socket->sd_io_ch != NULL, FALSE); + + if (command == NULL || (command->len <= 0) || command->str == NULL) { + gmyth_debug("[%s] Invalid NULL command parameter!\n", + __FUNCTION__); + ret = FALSE; + goto done; + } + + g_mutex_lock(gmyth_socket->mutex); + gmyth_debug("Sending command to backend: %s\n", command->str); + + buffer = g_strnfill(BUFLEN, ' '); + g_snprintf(buffer, MYTH_PROTOCOL_FIELD_SIZE + 1, "%-8d", command->len); + + command = g_string_prepend(command, buffer); + + /* + * write bytes to socket + */ + io_status = + g_io_channel_write_chars(gmyth_socket->sd_io_ch, command->str, + command->len, &bytes_written, &error); + + + if ((io_status == G_IO_STATUS_ERROR) || (bytes_written <= 0)) { + gmyth_debug("[%s] Error while writing to socket", __FUNCTION__); + ret = FALSE; + } else if (bytes_written < command->len) { + gmyth_debug("[%s] Not all data was written socket", __FUNCTION__); + ret = FALSE; + } + + io_status = g_io_channel_flush(gmyth_socket->sd_io_ch, &error); + + if ((bytes_written != command->len) + || (io_status == G_IO_STATUS_ERROR)) { + gmyth_debug + ("[%s] Some problem occurred when sending data to the socket\n", + __FUNCTION__); + + ret = TRUE; + } + + g_mutex_unlock(gmyth_socket->mutex); + done: + if (error != NULL) { + gmyth_debug + ("[%s] Error found reading data from IO channel: (%d, %s)\n", + __FUNCTION__, error->code, error->message); + ret = FALSE; + g_error_free(error); + } + + if (buffer != NULL) + g_free(buffer); + + return ret; +} + +/** Starts Mythtv protocol level connection. Checks Mythtv protocol version + * supported by the backend and send the "ANN" command. + * + * @param gmyth_socket the GMythSocket instance. + * @param hostname_backend The backend hostname or IP address. + * @param port The backend port to connect. + * @param blocking_client A flag to choose between blocking and non-blocking + * @param with_events Sets the connection flag to receive events. + * backend connection. + */ +static gboolean +gmyth_socket_connect_to_backend_and_events(GMythSocket * gmyth_socket, + const gchar * hostname_backend, + gint port, + gboolean blocking_client, + gboolean with_events) +{ + if (!gmyth_socket_connect(gmyth_socket, hostname_backend, port)) { + gmyth_debug("[%s] Could not open socket to backend machine [%s]\n", + __FUNCTION__, hostname_backend); + return FALSE; + } + + if (gmyth_socket_check_protocol_version(gmyth_socket)) { + GString *result; + GString *base_str = g_string_new(""); + GString *hostname = NULL; + + hostname = gmyth_socket_get_local_hostname(); + if (hostname == NULL) { + gmyth_debug + ("Hostname not available, setting to n800frontend\n"); + hostname = g_string_new("n800frontend"); + } + + g_string_printf(base_str, "ANN %s %s %u", + (blocking_client ? "Playback" : "Monitor"), + hostname->str, with_events); + + gmyth_socket_send_command(gmyth_socket, base_str); + result = gmyth_socket_receive_response(gmyth_socket); + + if (result != NULL) { + gmyth_debug("Response received from backend: %s", result->str); + g_string_free(result, TRUE); + } + + g_string_free(hostname, TRUE); + g_string_free(base_str, TRUE); + + return TRUE; + } else { + gmyth_debug("[%s] GMythSocket could not connect to the backend", + __FUNCTION__); + return FALSE; + } +} + +/** Starts Mythtv protocol level connection. Checks Mythtv protocol version + * supported by the backend and send the "ANN" command. + * + * @param gmyth_socket the GMythSocket instance. + * @param hostname_backend The backend hostname or IP address. + * @param port The backend port to connect. + * @param blocking_client A flag to choose between blocking and non-blocking + */ +gboolean +gmyth_socket_connect_to_backend(GMythSocket * gmyth_socket, + const gchar * hostname_backend, gint port, + gboolean blocking_client) +{ + if (!gmyth_socket_connect_to_backend_and_events + (gmyth_socket, hostname_backend, port, blocking_client, FALSE)) { + gmyth_debug("Could not open socket to backend machine [%s]\n", + hostname_backend); + return FALSE; + } + + return TRUE; + +} + +/** Starts Mythtv protocol level connection. Checks Mythtv protocol version + * supported by the backend and send the "ANN" command. + * + * @param gmyth_socket the GMythSocket instance. + * @param hostname_backend The backend hostname or IP address. + * @param port The backend port to connect. + * @param blocking_client A flag to choose between blocking and non-blocking + */ +gboolean +gmyth_socket_connect_to_backend_events(GMythSocket * gmyth_socket, + const gchar * hostname_backend, + gint port, gboolean blocking_client) +{ + if (!gmyth_socket_connect_to_backend_and_events + (gmyth_socket, hostname_backend, port, blocking_client, TRUE)) { + gmyth_debug + ("Could not open socket to backend machine in order to receive events [%s]\n", + hostname_backend); + return FALSE; + } + + return TRUE; +} + +/** Closes the socket connection to the backend. + * + * @param gmyth_socket The GMythSocket instance. + */ +void +gmyth_socket_close_connection(GMythSocket * gmyth_socket) +{ + /* + * if ( gmyth_socket->sd != -1 ) { close (gmyth_socket->sd); + * gmyth_socket->sd = -1; } + */ + + if (gmyth_socket->sd_io_ch != NULL) { + g_io_channel_shutdown(gmyth_socket->sd_io_ch, TRUE, NULL); + g_io_channel_unref(gmyth_socket->sd_io_ch); + gmyth_socket->sd_io_ch = NULL; + gmyth_socket->sd = -1; + } + +} + + +/** Try the MythTV version numbers, and get the version returned by + * the possible REJECT message, in order to contruct a new + * MythTV version request. + * + * @param gmyth_socket The GMythSocket instance. + * @param mythtv_version The Mythtv protocol version to be tested + * + * @return The actual MythTV the client is connected to. + */ +gint +gmyth_socket_check_protocol_version_number(GMythSocket * gmyth_socket, + gint mythtv_version) +{ + GString *response = NULL; + GString *payload = NULL; + gboolean res = TRUE; + gint mythtv_new_version = MYTHTV_CANNOT_NEGOTIATE_VERSION; + guint max_iterations = MYTHTV_MAX_VERSION_CHECKS; + + assert(gmyth_socket); + + try_new_version: + payload = g_string_new("MYTH_PROTO_VERSION"); + g_string_append_printf(payload, " %d", mythtv_version); + + gmyth_socket_send_command(gmyth_socket, payload); + response = gmyth_socket_receive_response(gmyth_socket); + + if (response == NULL) { + gmyth_debug("[%s] Check protocol version error! Not answered!", + __FUNCTION__); + res = FALSE; + goto done; + } + + res = g_str_has_prefix(response->str, "ACCEPT"); + if (!res) { + gmyth_debug("[%s] Protocol version request error: %s", + __FUNCTION__, response->str); + /* + * get the version number returned by the REJECT message + */ + if ((res = g_str_has_prefix(response->str, "REJECT")) == TRUE) { + gchar *new_version = NULL; + + new_version = g_strrstr(response->str, "]"); + if (new_version != NULL) { + ++new_version; /* skip ']' character */ + if (new_version != NULL) { + gmyth_debug("[%s] got MythTV version = %s.\n", + __FUNCTION__, new_version); + mythtv_version = + (gint) g_ascii_strtoull(new_version, NULL, 10); + /* + * do reconnection to the socket (socket is closed if + * the MythTV version was wrong) + */ + gmyth_socket_connect(gmyth_socket, + gmyth_socket->hostname, + gmyth_socket->port); + new_version = NULL; + if (--max_iterations > 0) { + g_string_free(payload, TRUE); + g_string_free(response, TRUE); + goto try_new_version; + } else + goto done; + } + } + } + } + + /* + * change the return value to a valid one + */ + if (res) { + mythtv_new_version = mythtv_version; + gmyth_socket->mythtv_version = mythtv_new_version; + } + + done: + g_string_free(payload, TRUE); + g_string_free(response, TRUE); + + return mythtv_new_version; +} + +/** Verifies if the Mythtv backend supported the GMyth supported version. + * + * @param gmyth_socket The GMythSocket instance. + * @return TRUE if supports, FALSE if not. + */ +gboolean +gmyth_socket_check_protocol_version(GMythSocket * gmyth_socket) +{ + return ((gmyth_socket->mythtv_version = + gmyth_socket_check_protocol_version_number(gmyth_socket, + MYTHTV_VERSION_DEFAULT)) + != MYTHTV_CANNOT_NEGOTIATE_VERSION); +} + +/** Returns the Mythtv backend supported version. + * + * @param gmyth_socket The GMythSocket instance. + * @return The actual MythTV version number. + */ +gint +gmyth_socket_get_protocol_version(GMythSocket * gmyth_socket) +{ + return gmyth_socket->mythtv_version; +} + +/** Receives a backend answer after a gmyth_socket_send_command_call (). + * + * @param gmyth_socket The GMythSocket instance. + * @return The response received, or NULL if error or nothing was received. + */ +GString * +gmyth_socket_receive_response(GMythSocket * gmyth_socket) +{ + GIOStatus io_status = G_IO_STATUS_NORMAL; + GError *error = NULL; + gchar *buffer = NULL; + + GString *str = NULL; + + gsize bytes_read = 0; + gint len = 0; + + if (gmyth_socket == NULL) + return NULL; + + GIOCondition io_cond; + + /* + * verify if the input (read) buffer is ready to receive data + */ + g_mutex_lock(gmyth_socket->mutex); + + buffer = g_strnfill(MYTH_PROTOCOL_FIELD_SIZE, ' '); + if (NULL == gmyth_socket->sd_io_ch) { + gmyth_socket_connect(gmyth_socket, gmyth_socket->hostname, + gmyth_socket->port); + } + + io_cond = g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch); + /* + * if ( NULL == gmyth_socket->sd_io_ch->read_buf || ( NULL == + * gmyth_socket->sd_io_ch->read_buf->str ) ) gmyth_socket->sd_io_ch = + * g_io_channel_unix_new( gmyth_socket->sd ); + */ + + if (gmyth_socket->sd_io_ch->is_readable /* && !( ( io_cond & G_IO_IN ) + * == 0 ) */ ) + io_status = + g_io_channel_read_chars(gmyth_socket->sd_io_ch, buffer, + MYTH_PROTOCOL_FIELD_SIZE, &bytes_read, + &error); + else + return g_string_new(""); + + /* + * verify if the input (read) buffer is ready to receive data + */ + io_cond = g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch); + + // if ( ( io_cond & G_IO_IN ) == 0 ) + // return NULL; + + gmyth_debug("[%s] Bytes read = %d\n", __FUNCTION__, bytes_read); + + if ((io_status == G_IO_STATUS_ERROR) || (bytes_read <= 0)) { + gmyth_debug("[%s] Error in mythprotocol response from backend\n", + __FUNCTION__); + str = NULL; + // return NULL; + } else if (buffer != NULL && strlen(buffer) > 0) { + + // io_status = g_io_channel_flush( gmyth_socket->sd_io_ch, &error + // ); + /* + * verify if the input (read) buffer is ready to receive data + */ + // io_cond = g_io_channel_get_buffer_condition( + // gmyth_socket->sd_io_ch ); + + // if ( ( io_cond & G_IO_IN ) != 0 ) { + // gchar *buffer_aux = NULL; + + /* + * removes trailing whitespace + */ + // buffer_aux = g_strstrip (buffer); + len = (gint) g_ascii_strtoull(g_strstrip(buffer), NULL, 10); + + g_free(buffer); + + /* + * if (buffer_aux != NULL) { g_free (buffer_aux); buffer_aux = + * NULL; } + */ + + buffer = g_new0(gchar, len + 1); + + bytes_read = 0; + if (!(gmyth_socket != NULL && gmyth_socket->sd_io_ch != NULL)) + return NULL; + + if (gmyth_socket->sd_io_ch->is_readable) + io_status = + g_io_channel_read_chars(gmyth_socket->sd_io_ch, buffer, + len, &bytes_read, &error); + else + return g_string_new(""); + + buffer[bytes_read] = '\0'; + // } + } + + g_mutex_unlock(gmyth_socket->mutex); + // g_static_rw_lock_reader_unlock (&rwlock); + + gmyth_debug("Response received from backend: ----- {%s}\n", buffer); + if ((bytes_read != len) || (io_status == G_IO_STATUS_ERROR)) + str = NULL; + else + str = g_string_new(buffer); + + if (error != NULL) { + gmyth_debug + ("[%s] Error found receiving response from the IO channel: (%d, %s)\n", + __FUNCTION__, error->code, error->message); + str = NULL; + g_error_free(error); + } + + g_free(buffer); + return str; +} + +/** Format a Mythtv command from the str_list entries and send it to backend. + * + * @param gmyth_socket The GMythSocket instance. + * @param str_list The string list to form the command + * @return TRUE if command was sent, FALSE if any error happens. + */ +gboolean +gmyth_socket_write_stringlist(GMythSocket * gmyth_socket, + GMythStringList * str_list) +{ + + GList *tmp_list = NULL; + GPtrArray *ptr_array = NULL; + gchar *str_array = NULL; + + g_mutex_lock(gmyth_socket->mutex); + // g_static_rw_lock_writer_lock (&rwlock); + + ptr_array = g_ptr_array_sized_new(g_list_length(str_list->glist)); + + // FIXME: change this implementation! + tmp_list = str_list->glist; + for (; tmp_list; tmp_list = tmp_list->next) { + if (tmp_list->data != NULL) { + g_ptr_array_add(ptr_array, ((GString *) tmp_list->data)->str); + } else { + g_ptr_array_add(ptr_array, ""); + } + } + g_ptr_array_add(ptr_array, NULL); // g_str_joinv() needs a NULL + // terminated string + + str_array = g_strjoinv(MYTH_SEPARATOR, (gchar **) (ptr_array->pdata)); + + g_mutex_unlock(gmyth_socket->mutex); + // g_static_rw_lock_writer_unlock (&rwlock); + + gmyth_debug("[%s] Sending socket request: %s\n", __FUNCTION__, + str_array); + + // Sends message to backend + // TODO: implement looping to send remaining data, and add timeout + // testing! + GString *command = g_string_new(str_array); + + gmyth_socket_send_command(gmyth_socket, command); + + g_string_free(command, TRUE); + + g_free(str_array); + + /* + * ptr_array is pointing to data inside str_list->glist + */ + g_ptr_array_free(ptr_array, TRUE); + + return TRUE; +} + +/* + * Receives a backend command response and split it into the given string + * list. @param gmyth_socket The GMythSocket instance. @param str_list + * the string list to be filled. @return The number of received strings. + */ +gint +gmyth_socket_read_stringlist(GMythSocket * gmyth_socket, + GMythStringList * str_list) +{ + GString *response; + gint i; + + gmyth_string_list_clear_all(str_list); + + response = gmyth_socket_receive_response(gmyth_socket); + if (response != NULL && response->str != NULL && response->len > 0) { + gchar **str_array; + + g_mutex_lock(gmyth_socket->mutex); + + str_array = g_strsplit(response->str, MYTH_SEPARATOR, -1); + + for (i = 0; i < g_strv_length(str_array); i++) { + // if ( str_array[i] != NULL && strlen( str_array[i] ) > 0 ) + gmyth_string_list_append_char_array(str_list, str_array[i]); + } + + g_mutex_unlock(gmyth_socket->mutex); + g_strfreev(str_array); + } + + g_string_free(response, TRUE); + + return gmyth_string_list_length(str_list); +} + +/** Formats a Mythtv protocol command based on str_list and sends it to + * the connected backend. The backend response is overwritten into str_list. + * + * @param gmyth_socket The GMythSocket instance. + * @param str_list The string list to be sent, and on which the answer + * will be written. + * @return TRUE if command was sent and an answer was received, FALSE if any + * error happens. + */ +gint +gmyth_socket_sendreceive_stringlist(GMythSocket * gmyth_socket, + GMythStringList * str_list) +{ + gmyth_socket_write_stringlist(gmyth_socket, str_list); + + return gmyth_socket_read_stringlist(gmyth_socket, str_list); +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_socket.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_socket.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,147 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_socket.h + * + * @brief

MythTV socket implementation, according to the MythTV Project + * (www.mythtv.org). + * + * This component provides basic socket functionalities to interact with + * the Mythtv backend. + *

+ * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Lins Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_SOCKET_H__ +#define __GMYTH_SOCKET_H__ + +#include + +#include +#include +#include +#include +#include + +#include "gmyth_stringlist.h" + +G_BEGIN_DECLS +#define GMYTH_SOCKET_TYPE (gmyth_socket_get_type ()) +#define GMYTH_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SOCKET_TYPE, GMythSocket)) +#define GMYTH_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SOCKET_TYPE, GMythSocketClass)) +#define IS_GMYTH_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_SOCKET_TYPE)) +#define IS_GMYTH_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SOCKET_TYPE)) +#define GMYTH_SOCKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_SOCKET_TYPE, GMythSocketClass)) +typedef struct _GMythSocket GMythSocket; +typedef struct _GMythSocketClass GMythSocketClass; + +struct _GMythSocketClass { + GObjectClass parent_class; + + /* + * callbacks + */ + /* + * no one for now + */ +}; + +struct _GMythSocket { + GObject parent; + + GMutex *mutex; + + /* + * socket descriptor + */ + gint sd; + GIOChannel *sd_io_ch; + + gchar *hostname; + gint port; + gint mythtv_version; +}; + +/* + * used when no protocol version number was negotiated + */ +#define MYTHTV_CANNOT_NEGOTIATE_VERSION 0 + +GType gmyth_socket_get_type(void); + +GMythSocket *gmyth_socket_new(); + +GIOChannel *gmyth_socket_get_io_channel(GMythSocket * gmyth_socket); + +gboolean gmyth_socket_is_able_to_read(GMythSocket * gmyth_socket); +gboolean gmyth_socket_is_able_to_write(GMythSocket * gmyth_socket); + +gboolean gmyth_socket_send_command(GMythSocket * gmyth_socket, + GString * command); +GString *gmyth_socket_receive_response(GMythSocket * gmyth_socket); +gint gmyth_socket_sendreceive_stringlist(GMythSocket * + gmyth_socket, + GMythStringList * + str_list); + +gboolean gmyth_socket_connect(GMythSocket * gmyth_socket, + const gchar * hostname, gint port); +gboolean gmyth_socket_connect_with_timeout(GMythSocket * + gmyth_socket, + const gchar * hostname, + gint port, + guint timeout); + +gboolean gmyth_socket_connect_to_backend(GMythSocket * gmyth_socket, + const gchar * + hostname_backend, + gint port, + gboolean blocking_client); + +gboolean gmyth_socket_connect_to_backend_events(GMythSocket * + gmyth_socket, + const gchar * + hostname_backend, + gint port, + gboolean + blocking_client); + +gchar *gmyth_socket_get_primary_addr(void); + +GString *gmyth_socket_get_local_hostname(void); + +void gmyth_socket_close_connection(GMythSocket * gmyth_socket); + +gboolean gmyth_socket_check_protocol_version(GMythSocket * + gmyth_socket); +gint gmyth_socket_check_protocol_version_number(GMythSocket * + gmyth_socket, + gint + mythtv_version); + +gint gmyth_socket_get_protocol_version(GMythSocket * + gmyth_socket); + +gboolean gmyth_socket_write_stringlist(GMythSocket * gmyth_socket, + GMythStringList * str_list); +gint gmyth_socket_read_stringlist(GMythSocket * gmyth_socket, + GMythStringList * str_list); +G_END_DECLS +#endif /* __GMYTH_SOCKET_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_stringlist.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_stringlist.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,454 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_stringlist.c + * + * @brief

This component contains functions for dealing with the stringlist + * format of the mythprotocol. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_stringlist.h" + +#include "gmyth_debug.h" + +static void gmyth_string_list_class_init(GMythStringListClass * klass); +static void gmyth_string_list_init(GMythStringList * object); + +static void gmyth_string_list_dispose(GObject * object); +static void gmyth_string_list_finalize(GObject * object); + +G_DEFINE_TYPE(GMythStringList, gmyth_string_list, G_TYPE_OBJECT) + static void gmyth_string_list_class_init(GMythStringListClass * + klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_string_list_dispose; + gobject_class->finalize = gmyth_string_list_finalize; +} + +static void +gmyth_string_list_init(GMythStringList * gmyth_string_list) +{ + gmyth_string_list->glist = NULL; +} + +static void +gmyth_string_list_dispose(GObject * object) +{ + GMythStringList *gmyth_string_list = GMYTH_STRING_LIST(object); + + gmyth_string_list_clear_all(gmyth_string_list); + + G_OBJECT_CLASS(gmyth_string_list_parent_class)->dispose(object); +} + +static void +gmyth_string_list_finalize(GObject * object) +{ + // GMythStringList *gmyth_string_list = GMYTH_STRING_LIST(object); + + g_signal_handlers_destroy(object); + + G_OBJECT_CLASS(gmyth_string_list_parent_class)->finalize(object); +} + +/** Creates a new instance of GStringList. + * + * @return a new instance of GStringList. + */ +GMythStringList * +gmyth_string_list_new() +{ + GMythStringList *gmyth_string_list = + GMYTH_STRING_LIST(g_object_new(GMYTH_STRING_LIST_TYPE, NULL)); + + return gmyth_string_list; +} + +/** Appends a guint64 to the string list. + * + * @param strlist The GMythStringList instance. + * @param value The guint64 to be appended. + * + * @return The appended guint64 converted to a GString object. + */ +GString * +gmyth_string_list_append_int(GMythStringList * strlist, const gint value) +{ + GString *value_str = g_string_new(""); + + g_string_printf(value_str, "%d", value); + + strlist->glist = g_list_append(strlist->glist, value_str); + + return value_str; +} + + +/** Appends a gdouble to the string list. + * + * @param strlist The GMythStringList instance. + * @param value The gdouble to be appended. + * + * @return The appended gdouble converted to a GString object. + */ +GString * +gmyth_string_list_append_float(GMythStringList * strlist, const gdouble value) +{ + GString *value_str = g_string_new(""); + g_string_printf(value_str, "%f", value); + strlist->glist = g_list_append(strlist->glist, value_str); + return value_str; +} + + +/** Appends a guint64 to the string list. + * + * @param strlist The GMythStringList instance. + * @param value The guint64 to be appended. + * + * @return The appended guint64 converted to a GString object. + */ +GString * +gmyth_string_list_append_uint64(GMythStringList * strlist, + const guint64 value) +{ + GString *tmp_str1 = g_string_new(""); + GString *tmp_str2 = g_string_new(""); + + gmyth_debug("value = %llu.\n", value); + + gulong l2 = ((guint64) value & 0xffffffff); + gulong l1 = ((guint64) value >> 32); + + /* + * high order part of guint64 value + */ + g_string_printf(tmp_str1, "%lu", l1); + + gmyth_debug("[%s] uint64 (high) = %s\n", __FUNCTION__, tmp_str1->str); + + strlist->glist = g_list_append(strlist->glist, tmp_str1); + + /* + * low order part of guint64 value + */ + g_string_printf(tmp_str2, "%lu", l2); + + gmyth_debug("[%s] uint64 (low) = %s\n", __FUNCTION__, tmp_str2->str); + + strlist->glist = g_list_append(strlist->glist, tmp_str2); + + return tmp_str2; +} + +/** Appends a gint64 to the string list. + * + * @param strlist The GMythStringList instance. + * @param value The gint64 to be appended. + * + * @return The appended gint64 converted to a GString object. + */ +GString * +gmyth_string_list_append_int64(GMythStringList * strlist, + const gint64 value) +{ + GString *tmp_str1 = g_string_new(""); + GString *tmp_str2 = g_string_new(""); + + gmyth_debug("value = %lld.\n", value); + + glong l2 = ((gint64) value & 0xffffffff); + glong l1 = ((gint64) value >> 32); + + /* + * high order part of gint64 value + */ + g_string_printf(tmp_str1, "%ld", l1); + + gmyth_debug("[%s] int64 (high) = %s\n", __FUNCTION__, tmp_str1->str); + + strlist->glist = g_list_append(strlist->glist, tmp_str1); + + /* + * low order part of gint64 value + */ + g_string_printf(tmp_str2, "%ld", l2); + + gmyth_debug("[%s] int64 (low) = %s\n", __FUNCTION__, tmp_str2->str); + + strlist->glist = g_list_append(strlist->glist, tmp_str2); + + return tmp_str2; +} + +/** Appends a char array to the string list. + * + * @param strlist The GMythStringList instance. + * @param value The char array to be appended. + * + * @return The appended char array converted to a GString object. + */ +GString * +gmyth_string_list_append_char_array(GMythStringList * strlist, + const gchar * value) +{ + GString *tmp_str = NULL; + + g_return_val_if_fail(strlist != NULL, NULL); + + tmp_str = g_string_new(value); + + strlist->glist = g_list_append(strlist->glist, tmp_str); + + return tmp_str; +} + +/** Appends a string to the string list. + * + * @param strlist The GMythStringList instance. + * @param value The string to be appended. + * + * @return The appended string itself. + */ +GString * +gmyth_string_list_append_string(GMythStringList * strlist, GString * value) +{ + g_return_val_if_fail(strlist != NULL, NULL); + + if (value != NULL) { + strlist->glist = + g_list_append(strlist->glist, g_string_new(value->str)); + } else { + strlist->glist = g_list_append(strlist->glist, NULL); + } + + return value; +} + +/** Gets an integer value from the string list at the given position. + * + * @param strlist The GMythStringList instance. + * @param index the integer position in the list, starting with zero. + * @return The integer value. + */ +gint +gmyth_string_list_get_int(GMythStringList * strlist, const gint index) +{ + // TODO: Create static method check_index() + GString *tmp_str = NULL; + + g_return_val_if_fail(strlist != NULL, 0); + + tmp_str = (GString *) g_list_nth_data(strlist->glist, index); + + if (NULL == tmp_str || NULL == tmp_str->str + || strlen(tmp_str->str) <= 0) + return 0; + + return (gint) ( /* 0x00000000ffffffffL & (gint64) */ + g_ascii_strtoull(tmp_str->str, NULL, 10)); +} + +/** Gets a guint64 value from the string list at the given position. + * According to the Mythtv protocol, the 64 bits value is formed by + * two strings. + * + * @param strlist The GMythStringList instance. + * @param index the index of the first string forming the 64 bits value. + * Index starts with zero. + * @return The guint64 value. + */ +guint64 +gmyth_string_list_get_uint64(GMythStringList * strlist, const gint index) +{ + // TODO: Create static method check_index() + guint64 ret_value = 0; + guint64 l2 = 0; + + g_return_val_if_fail(strlist != NULL, 0); + + const GString *tmp_str1 = + (GString *) g_list_nth_data(strlist->glist, index); + const GString *tmp_str2 = + (GString *) g_list_nth_data(strlist->glist, index + 1); + + if (tmp_str1 != NULL) + gmyth_debug("[%s] seek high bytes = %s\n", __FUNCTION__, + tmp_str1->str); + if (tmp_str2 == NULL || strlen(tmp_str2->str) > 0) { + } else { + gmyth_debug("[%s] seek low bytes = %s\n", __FUNCTION__, + tmp_str2->str); + } + + guint64 l1 = ((guint64) g_ascii_strtoull(tmp_str1->str, NULL, 10) /* & + * 0xffffffff + */ + ); + + if (tmp_str2 != NULL && tmp_str2->str != NULL + && strlen(tmp_str2->str) > 0) { + l2 = ((guint64) g_ascii_strtoull(tmp_str2->str, NULL, 10) + /* + * & 0xffffffff + */ + ); + } else { + l2 = l1; + l1 = 0; + } + + gmyth_debug("[%s]\t[l1 == %llu, l2 == %llu]\n", __FUNCTION__, l1, l2); + + ret_value = + ((guint64) (l2) /* & 0xffffffff */ ) | ((guint64) l1 << 32); + + gmyth_debug("[%s] returning uint64 value = %llu\n", __FUNCTION__, + ret_value); + + return ret_value; +} + +/** Gets a gint64 value from the string list at the given position. + * According to the Mythtv protocol, the 64 bits value is formed by + * two strings. + * + * @param strlist The GMythStringList instance. + * @param index the index of the first string forming the 64 bits value. + * Index starts with zero. + * @return The gint64 value. + */ +gint64 +gmyth_string_list_get_int64(GMythStringList * strlist, const gint index) +{ + // TODO: Create static method check_index() + gint64 ret_value = 0; + gint64 l2 = 0; + + g_return_val_if_fail(strlist != NULL, 0); + + const GString *tmp_str1 = + (GString *) g_list_nth_data(strlist->glist, index); + const GString *tmp_str2 = + (GString *) g_list_nth_data(strlist->glist, index + 1); + + if (tmp_str1 != NULL) + gmyth_debug("[%s] seek high bytes = %s\n", __FUNCTION__, + tmp_str1->str); + if (tmp_str2 == NULL || strlen(tmp_str2->str) > 0) { + } else { + gmyth_debug("[%s] seek low bytes = %s\n", __FUNCTION__, + tmp_str2->str); + } + + gint64 l1 = ((guint64) g_ascii_strtoull(tmp_str1->str, NULL, 10) /* & + * 0xffffffff + */ + ); + + if (tmp_str2 != NULL && tmp_str2->str != NULL + && strlen(tmp_str2->str) > 0) { + l2 = ((gint64) g_ascii_strtoull(tmp_str2->str, NULL, 10) + /* + * & 0xffffffff + */ + ); + } else { + l2 = l1; + l1 = 0; + } + + gmyth_debug("[%s]\t[l1 == %lld, l2 == %lld]\n", __FUNCTION__, l1, l2); + + ret_value = ((gint64) (l2) /* & 0xffffffff */ ) | ((gint64) l1 << 32); + + gmyth_debug("[%s] returning int64 value = %lld\n", __FUNCTION__, + ret_value); + + return ret_value; +} + + +/** Gets a string from the string list at the given position. The GString must be deallocated. + * + * @param strlist The GMythStringList instance. + * @param index the string position in the list, starting with zero. + * @return A pointer to the string data. + */ +GString * +gmyth_string_list_get_string(GMythStringList * strlist, const gint index) +{ + GString *ret; + + if (!strlist || !(strlist->glist)) { + gmyth_debug("%s received Null arguments", __FUNCTION__); + return NULL; + } + + ret = (GString *) g_list_nth_data(strlist->glist, index); + + return g_string_new(ret->str); +} + + +static void +gmyth_string_list_clear_element(GString * str_elem, void *data_aux) +{ + if (str_elem != NULL) + g_string_free(str_elem, TRUE); +} + +/** Removes all strings from the string list. + * + * @param strlist The GMythStringList instance. + */ +void +gmyth_string_list_clear_all(GMythStringList * strlist) +{ + if (strlist != NULL && strlist->glist) { + g_list_foreach(strlist->glist, + (GFunc) gmyth_string_list_clear_element, NULL); + g_list_free(strlist->glist); + strlist->glist = NULL; + } +} + +/** Retrieves the number of elements in the string list. + * + * @param strlist The GMythStringList instance. + * @return the string list length. + */ +gint +gmyth_string_list_length(GMythStringList * strlist) +{ + if (!(strlist != NULL && strlist->glist != NULL)) + return 0; + + return g_list_length(strlist->glist); +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_stringlist.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_stringlist.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,108 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_stringlist.h + * + * @brief

This component contains functions for dealing with the stringlist + * format of the mythprotocol. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef GMYTH_STRING_LIST_H_ +#define GMYTH_STRING_LIST_H_ + +#include + +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS +#define GMYTH_STRING_LIST_TYPE (gmyth_string_list_get_type ()) +#define GMYTH_STRING_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_STRING_LIST_TYPE, GMythStringList)) +#define GMYTH_STRING_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_STRING_LIST_TYPE, GMythStringListClass)) +#define IS_GMYTH_STRING_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_STRING_LIST_TYPE)) +#define IS_GMYTH_STRING_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_STRING_LIST_TYPE)) +#define GMYTH_STRING_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_STRING_LIST_TYPE, GMythStringListClass)) +typedef struct _GMythStringList GMythStringList; +typedef struct _GMythStringListClass GMythStringListClass; + +struct _GMythStringListClass { + GObjectClass parent_class; + + /* + * callbacks + */ + /* + * no one for now + */ +}; + +struct _GMythStringList { + GObject parent; + + /* + * string list + */ + GList *glist; +}; + + +GType gmyth_string_list_get_type(void); + +GMythStringList *gmyth_string_list_new(void); + +void gmyth_string_list_clear_all(GMythStringList * strlist); +int gmyth_string_list_length(GMythStringList * strlist); + +GString *gmyth_string_list_append_float(GMythStringList * strlist, + const gdouble value); + +GString *gmyth_string_list_append_int(GMythStringList * strlist, + const gint value); +GString *gmyth_string_list_append_uint64(GMythStringList * strlist, + const guint64 value); + +GString *gmyth_string_list_append_int64(GMythStringList * strlist, + const gint64 value); + +GString *gmyth_string_list_append_char_array(GMythStringList * + strlist, + const char *value); +GString *gmyth_string_list_append_string(GMythStringList * strlist, + GString * value); + +int gmyth_string_list_get_int(GMythStringList * strlist, + const gint index); +guint64 gmyth_string_list_get_uint64(GMythStringList * strlist, + const gint index); +gint64 gmyth_string_list_get_int64(GMythStringList * strlist, + const gint index); +GString *gmyth_string_list_get_string(GMythStringList * strlist, + const gint index); + +#define gmyth_string_list_get_char_array(strlist, index) \ + (gmyth_string_list_get_string(strlist, index))->str + +G_END_DECLS +#endif /* GMYTH_STRING_LIST_H_ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_transcoder.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_transcoder.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,272 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_transcoder.c + * + * @brief

This file contains the transcoder class. + * + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. + * @author Artur Duque de Souza + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "gmyth_util.h" +#include "gmyth_debug.h" + +#include "gmyth_jobqueue.h" +#include "gmyth_transcoder.h" + +static void gmyth_transcoder_class_init(GMythTranscoderClass * klass); +static void gmyth_transcoder_init(GMythTranscoder * object); + +static void gmyth_transcoder_dispose(GObject * object); +static void gmyth_transcoder_finalize(GObject * object); + +G_DEFINE_TYPE(GMythTranscoder, gmyth_transcoder, G_TYPE_OBJECT) + static void gmyth_transcoder_class_init(GMythTranscoderClass * + klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->dispose = gmyth_transcoder_dispose; + gobject_class->finalize = gmyth_transcoder_finalize; +} + +static void +gmyth_transcoder_init(GMythTranscoder * transcoder) +{ + transcoder->started = FALSE; +} + +static void +gmyth_transcoder_dispose(GObject * object) +{ + GMythTranscoder *transcoder = GMYTH_TRANSCODER(object); + + g_free(transcoder->output_filename); + g_free(transcoder->filename); + g_free(transcoder->profile); + g_free(transcoder->starttime); + + if (transcoder->backend_info) + g_object_unref(transcoder->backend_info); + + G_OBJECT_CLASS(gmyth_transcoder_parent_class)->dispose(object); +} + +static void +gmyth_transcoder_finalize(GObject * object) +{ + g_signal_handlers_destroy(object); + G_OBJECT_CLASS(gmyth_transcoder_parent_class)->finalize(object); +} + +/** + * Creates a new instance of GMythTranscoder. + * + * @return a new instance of GMythTranscoder. + **/ +GMythTranscoder * +gmyth_transcoder_new(GMythBackendInfo * backend_info) +{ + GMythTranscoder *transcoder = GMYTH_TRANSCODER + (g_object_new(GMYTH_TRANSCODER_TYPE, NULL)); + + if (backend_info != NULL) { + g_object_ref(backend_info); + transcoder->backend_info = backend_info; + } + + return transcoder; +} + +/** + * + * gmyth_transcoder_date_change_format + * @brief converts a string like YYYY-MM-DDTHH:MM:SS into YYYYMMDDHHMMSS (vice versa) + * @param date_s gchar* + * @return gchar* with file or iso format + * + **/ +static gchar * +gmyth_transcoder_date_change_format(gchar * date_s, int format) +{ + if (date_s != NULL) { + gint length = strlen(date_s); + + // create the right date format + gchar *src = (gchar *) g_malloc0(sizeof(gchar) * length); + + strncpy(src, date_s, length); + + gchar *dst; + + if (format == DATE_FILE) { + dst = (gchar *) g_malloc0(sizeof(gchar) * 16); + snprintf(dst, 16, "%.4s%.2s%.2s%.2s%.2s%.2s", src, src + 5, + src + 7, src + 9, src + 11, src + 13); + dst[15] = '\0'; + } else if (format == DATE_ISO) { + dst = (gchar *) g_malloc0(sizeof(gchar) * 20); + snprintf(dst, 20, "%.4s-%.2s-%.2sT%.2s:%.2s:%.2s", src, + src + 4, src + 6, src + 8, src + 10, src + 12); + dst[19] = '\0'; + } + + gchar *ret = g_strdup(dst); + + g_free(src); + g_free(dst); + + return ret; + } else + return NULL; +} + +/** + * gmyth_transcoder_set_output + * @brief set transcoder to use output + * @param value gboolean + * @param outfile filename of output + * @return void set's up the var to value + * + **/ +void +gmyth_transcoder_set_output(GMythTranscoder * transcoder, + gboolean value, const gchar * outputfile) +{ + transcoder->output = value; + transcoder->output_filename = g_strdup(outputfile); +} + +/** + * gmyth_transcoder_set_file + * @brief set the file to transcoder + * @param file filename + * @return void set's up the var to value + * + **/ +void +gmyth_transcoder_set_filename(GMythTranscoder * transcoder, + const gchar * file) +{ + // fixme: if this method is called twice, memory will not be + // dealocated + // one transcoder can be used only for one file request? + if (file != NULL) { + gchar **splited = g_strsplit(file, "_", 2); + + // Get chanid + sscanf(splited[0], "%d", &(transcoder->chanid)); + + // Get starttime + gchar **date = g_strsplit(splited[1], ".", 2); + + transcoder->starttime = + gmyth_transcoder_date_change_format(date[0], DATE_ISO); + + transcoder->filename = g_strdup(file); + } +} + + +/** + * + * gmyth_transcoder_set_profile + * @brief set transcoder's profile + * @param rec GMythTranscoder* + * @param value the value + * @return gint representing the result + * + **/ +gint +gmyth_transcoder_set_profile(GMythTranscoder * trans, const gchar * value) +{ + g_return_val_if_fail(value != NULL, -1); + + trans->profile = g_strndup(value, strlen(value)); + + return 0; +} + +gboolean +gmyth_transcoder_start(GMythTranscoder * trans) +{ + g_return_val_if_fail(trans != NULL, FALSE); + g_return_val_if_fail(trans->backend_info != NULL, FALSE); + g_return_val_if_fail(trans->filename != NULL, FALSE); + + if (trans->started == FALSE) { // not started yet + if (!gmyth_util_file_exists(trans->backend_info, trans->filename)) { + gmyth_debug("File %s does not exist", trans->filename); + } + trans->started = gmyth_jobqueue_add_job(trans, "JOB_TRANSCODE"); + if (trans->started == FALSE) + gmyth_debug("Error while starting GMythTranscoder to file: %s", + trans->output_filename); + } else { + gmyth_debug("GMythTransfer already started!"); + } + + return trans->started; +} + +gboolean +gmyth_transcoder_pause(GMythTranscoder * trans) +{ + g_return_val_if_fail(trans != NULL, FALSE); + g_return_val_if_fail(trans->started == TRUE, FALSE); + + return gmyth_jobqueue_change_cmd(trans, "PAUSE", "JOB_TRANSCODE"); +} + +gboolean +gmyth_transcoder_resume(GMythTranscoder * trans) +{ + g_return_val_if_fail(trans != NULL, FALSE); + + return gmyth_jobqueue_change_cmd(trans, "RESUME", "JOB_TRANSCODE"); +} + +gboolean +gmyth_transcoder_cancel(GMythTranscoder * trans) +{ + g_return_val_if_fail(trans != NULL, FALSE); + g_return_val_if_fail(trans->started == TRUE, FALSE); + + trans->started = FALSE; + + return gmyth_jobqueue_change_cmd(trans, "STOP", "JOB_TRANSCODE"); +} + +// fixme: implement this method +gint +gmyth_transcoder_get_progress(GMythTranscoder * trans) +{ + static int fixme = 0; + + return (fixme++) % 101; +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_transcoder.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_transcoder.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,104 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_transcoder.h + * + * @brief

This file contains the transcoder class. + * + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. + * @author Artur Duque de Souza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _GMYTH_TRANSCODER_H +#define _GMYTH_TRANSCODER_H + +#include +#include + +#include "gmyth_stringlist.h" +#include "gmyth_backendinfo.h" +#include "gmyth_socket.h" +#include "gmyth_http.h" +#include "gmyth_recprofile.h" + +G_BEGIN_DECLS +#define GMYTH_TRANSCODER_TYPE (gmyth_transcoder_get_type ()) +#define GMYTH_TRANSCODER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TRANSCODER_TYPE, GMythTranscoder)) +#define GMYTH_TRANSCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TRANSCODER_TYPE, GMythTranscoderClass)) +#define IS_GMYTH_TRANSCODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_TRANSCODER_TYPE)) +#define IS_GMYTH_TRANSCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TRANSCODER_TYPE)) +#define GMYTH_TRANSCODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_TRANSCODER_TYPE, GMythTranscoderClass)) +#define DATE_ISO 0 +#define DATE_FILE 1 +typedef struct _GMythTranscoder GMythTranscoder; +typedef struct _GMythTranscoderClass GMythTranscoderClass; + +struct _GMythTranscoderClass { + GObjectClass parent_class; + + /* + * callbacks + */ +}; + +/** + * The GMythTranscoder structure is a class to implement functions + * related to transcoding. + */ +struct _GMythTranscoder { + GObject parent; + + gboolean cutlist; + gboolean output; + gboolean started; + + /* + * private begin + */ + gchar *output_filename; + gchar *filename; + gchar *profile; + /* + * private end + */ + + gchar *starttime; + + gint chanid; + + GMythBackendInfo *backend_info; +}; + +GType gmyth_transcoder_type(void); + +GMythTranscoder *gmyth_transcoder_new(GMythBackendInfo * backend_info); +void gmyth_transcoder_set_output(GMythTranscoder * transcode, + gboolean value, + const gchar * outputfile); +void gmyth_transcoder_set_filename(GMythTranscoder * transcode, + const gchar * file); +gint gmyth_transcoder_set_profile(GMythTranscoder * trans, + const gchar * value); +gboolean gmyth_transcoder_start(GMythTranscoder * trans); +gboolean gmyth_transcoder_pause(GMythTranscoder * trans); +gboolean gmyth_transcoder_resume(GMythTranscoder * trans); +gboolean gmyth_transcoder_cancel(GMythTranscoder * trans); +gint gmyth_transcoder_get_progress(GMythTranscoder * trans); + + +G_END_DECLS +#endif /*_GMYTH_TRANSCODER_H*/ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_tvchain.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_tvchain.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,620 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_tvchain.c + * + * @brief

This component contains functions for creating and accessing + * the tvchain functions for live tv playback. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_tvchain.h" + +#include +#include +#include +#include +#include + +#include "gmyth_epg.h" +#include "gmyth_util.h" +#include "gmyth_query.h" +#include "gmyth_scheduler.h" +#include "gmyth_debug.h" + +static void gmyth_tvchain_class_init(GMythTVChainClass * klass); +static void gmyth_tvchain_init(GMythTVChain * object); + +static void gmyth_tvchain_dispose(GObject * object); +static void gmyth_tvchain_finalize(GObject * object); + +static void free_tvchain_entry(gpointer data, gpointer user_data); + +G_DEFINE_TYPE(GMythTVChain, gmyth_tvchain, G_TYPE_OBJECT) + static void gmyth_tvchain_class_init(GMythTVChainClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_tvchain_dispose; + gobject_class->finalize = gmyth_tvchain_finalize; +} + +static void +gmyth_tvchain_init(GMythTVChain * tvchain) +{ + tvchain->tvchain_id = NULL; + + tvchain->cur_chanid = g_string_new(""); + tvchain->cur_startts = NULL; + + tvchain->mutex = g_mutex_new(); +} + +GMythTVChain * +gmyth_tvchain_new() +{ + GMythTVChain *tvchain = + GMYTH_TVCHAIN(g_object_new(GMYTH_TVCHAIN_TYPE, NULL)); + + return tvchain; +} + +static void +gmyth_tvchain_dispose(GObject * object) +{ + GMythTVChain *tvchain = GMYTH_TVCHAIN(object); + + if (tvchain->tvchain_id != NULL) { + g_string_free(tvchain->tvchain_id, TRUE); + tvchain->tvchain_id = NULL; + } + + if (tvchain->mutex != NULL) { + g_mutex_free(tvchain->mutex); + tvchain->mutex = NULL; + } + + if (tvchain->tvchain_list != NULL) { + g_list_foreach(tvchain->tvchain_list, free_tvchain_entry, NULL); + g_list_free(tvchain->tvchain_list); + } + + if (tvchain->cur_chanid != NULL) { + g_string_free(tvchain->cur_chanid, TRUE); + tvchain->cur_chanid = NULL; + } + + if (tvchain->backend_info) { + g_object_unref(tvchain->backend_info); + tvchain->backend_info = NULL; + } + + + G_OBJECT_CLASS(gmyth_tvchain_parent_class)->dispose(object); +} + +static void +gmyth_tvchain_finalize(GObject * object) +{ + g_signal_handlers_destroy(object); + + G_OBJECT_CLASS(gmyth_tvchain_parent_class)->finalize(object); +} + +/** Initializes the tvchain and generates the tvchain id. + * + * @param tvchain The GMythTVChain instance. + * @param hostname The local hostname used to generate the tvchain id. + */ +gboolean +gmyth_tvchain_initialize(GMythTVChain * tvchain, + GMythBackendInfo * backend_info) +{ + const char *hostname; + + assert(tvchain); + g_return_val_if_fail(backend_info != NULL, FALSE); + + g_object_ref(backend_info); + tvchain->backend_info = backend_info; + + hostname = gmyth_backend_info_get_hostname(backend_info); + + if (tvchain->tvchain_id == NULL) { + gchar *isodate = NULL; + GTimeVal *cur_time = g_new0(GTimeVal, 1); + + // struct tm* gmyth_util_time_val_to_date ( const GTimeVal* time ) + + g_get_current_time(cur_time); + isodate = + gmyth_util_time_to_isoformat_from_time_val_fmt + ("%Y-%m-%dT%H:%M:%S", cur_time); + + tvchain->tvchain_id = + g_string_sized_new(7 + strlen(hostname) + strlen(isodate)); + g_string_printf(tvchain->tvchain_id, "live-%s-%s", hostname, + isodate); + + gmyth_debug("[%s] tv_chain_id: %s", __FUNCTION__, + tvchain->tvchain_id->str); + + g_free(isodate); + g_free(cur_time); + } else { + gmyth_debug("[%s] TVchain already initialized", __FUNCTION__); + } + + return TRUE; +} + +/** Gets the tvchain id. + * + * @param tvchain The GMythTVChain instance. + * @return The tvchain id. + */ +GString * +gmyth_tvchain_get_id(GMythTVChain * tvchain) +{ + g_return_val_if_fail(tvchain != NULL + && tvchain->tvchain_id != NULL, NULL); + + return tvchain->tvchain_id; +} + +/** Reloads all tvchain entries in the database. + * + * @param tvchain The GMythTVChain instance. + * @return TRUE if success, or FALSE if error. + */ +gboolean +gmyth_tvchain_reload_all(GMythTVChain * tvchain) +{ + MYSQL_ROW msql_row; + MYSQL_RES *msql_res = NULL; + GMythQuery *gmyth_query = NULL; + gboolean ret = TRUE; + GString *stmt_str = NULL; + + g_mutex_lock(tvchain->mutex); + + /* + * gets the initial size of the TVChain entries list + */ + guint prev_size = g_list_length(tvchain->tvchain_list); + + gmyth_debug("[%s] chainid: %s", __FUNCTION__, + tvchain->tvchain_id->str); + + if (tvchain != NULL && tvchain->tvchain_list != NULL) { + g_list_free(tvchain->tvchain_list); + tvchain->tvchain_list = NULL; + } + + /* + * TODO: Reuse gmyth_query already connected from context + */ + gmyth_query = gmyth_query_new(); + if (!gmyth_query_connect(gmyth_query, tvchain->backend_info)) { + gmyth_debug("[%s] Could not connect to db", __FUNCTION__); + g_mutex_unlock(tvchain->mutex); + ret = FALSE; + goto done; + } + + stmt_str = g_string_new(""); + g_string_printf(stmt_str, + "SELECT chanid, starttime, endtime, discontinuity, " + "chainpos, hostprefix, cardtype, channame, input " + "FROM tvchain " + "WHERE chainid = \"%s\" ORDER BY chainpos;", + tvchain->tvchain_id->str); + + msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str); + if (msql_res != NULL) { + + while ((msql_row = mysql_fetch_row(msql_res)) != NULL) { + struct LiveTVChainEntry *entry = + g_new0(struct LiveTVChainEntry, 1); + entry->chanid = g_string_new(msql_row[0]); + entry->starttime = + gmyth_util_string_to_time_val((const gchar *) msql_row[1]); + entry->endtime = + gmyth_util_string_to_time_val((const gchar *) msql_row[2]); + entry->discontinuity = + g_ascii_strtoull(msql_row[3], NULL, 10) != 0; + entry->hostprefix = g_string_new(msql_row[5]); + entry->cardtype = g_string_new(msql_row[6]); + entry->channum = g_string_new(msql_row[7]); + entry->inputname = g_string_new(msql_row[8]); + + // m_maxpos = query.value(4).toInt() + 1; + gmyth_debug + ("[%s] Reading TV chain entry (channel %s): [%s, %s, %s]\n", + __FUNCTION__, entry->channum->str, entry->chanid->str, + (gchar *) msql_row[1], (gchar *) msql_row[2]); + + /* + * add this to get the actual start timestamp of the last + * recording + */ + if (tvchain->cur_startts < entry->starttime) + tvchain->cur_startts = entry->starttime; + + tvchain->tvchain_list = + g_list_append(tvchain->tvchain_list, entry); + } + } else { + gmyth_debug("gmyth_tvchain_reload_all query error!\n"); + g_mutex_unlock(tvchain->mutex); + + ret = FALSE; + goto done; + } + + g_mutex_unlock(tvchain->mutex); + + tvchain->cur_pos = + gmyth_tvchain_program_is_at(tvchain, tvchain->cur_chanid, + tvchain->cur_startts); + gmyth_debug("[%s] TVChain current position = %d.\n", __FUNCTION__, + tvchain->cur_pos); + + if (tvchain->cur_pos < 0) + tvchain->cur_pos = 0; + + // if (m_switchid >= 0) + // m_switchid = + // ProgramIsAt(m_switchentry.chanid,m_switchentry.starttime); + + if (prev_size != g_list_length(tvchain->tvchain_list)) { + gmyth_debug("[%s] Added new recording", __FUNCTION__); + } + + done: + if (stmt_str != NULL) + g_string_free(stmt_str, TRUE); + + if (msql_res != NULL) + mysql_free_result(msql_res); + + if (gmyth_query != NULL) + g_object_unref(gmyth_query); + + return ret; +} + +/** + * Get all the program info entries in the database. + * + * @param tvchain The GMythTVChain instance. + * + * @return A program info listage. + */ +GList * +gmyth_tvchain_get_program_info_list(GMythTVChain * tvchain) +{ + GList *prog_list = NULL; + MYSQL_ROW msql_row; + MYSQL_RES *msql_res = NULL; + GMythQuery *gmyth_query = NULL; + GString *stmt_str = NULL; + + g_mutex_lock(tvchain->mutex); + + gmyth_query = gmyth_query_new(); + if (!gmyth_query_connect(gmyth_query, tvchain->backend_info)) { + gmyth_debug("Could not connect to db."); + goto done; + } + + stmt_str = g_string_new(""); + g_string_printf(stmt_str, + "SELECT channum, icon " "FROM channel " + "ORDER BY channum;"); + + msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str); + if (msql_res != NULL) { + + while ((msql_row = mysql_fetch_row(msql_res)) != NULL) { + GMythProgramInfo *entry = gmyth_program_info_new(); + + entry->channame = g_string_new(msql_row[0]); + entry->chansign = g_string_new(msql_row[1]); + + gmyth_debug + ("Reading TV program info entry (channel %s): [%s - {%s, %s}]\n", + entry->channame->str, entry->chansign->str, + (gchar *) msql_row[0], (gchar *) msql_row[1]); + + prog_list = g_list_append(prog_list, entry); + } + } else { + gmyth_debug + ("Query error when trying to get the channel list from database!\n"); + goto done; + } + + done: + g_mutex_unlock(tvchain->mutex); + + if (stmt_str != NULL) + g_string_free(stmt_str, TRUE); + + if (msql_res != NULL) + mysql_free_result(msql_res); + + if (gmyth_query != NULL) + g_object_unref(gmyth_query); + + return prog_list; +} + +/** + * Get all the program info entries in the database, given a channel name. + * + * @param tvchain The GMythTVChain instance. + * @param channel The channel name. + * + * @return A program info listage, based on a given channel name. + */ +GList * +gmyth_tvchain_get_program_info_from_channel(GMythTVChain * tvchain, + const gchar * channel) +{ + GList *prog_list = NULL; + MYSQL_ROW msql_row; + MYSQL_RES *msql_res = NULL; + GMythQuery *gmyth_query = NULL; + GString *stmt_str = NULL; + + g_mutex_lock(tvchain->mutex); + + gmyth_query = gmyth_query_new(); + if (!gmyth_query_connect(gmyth_query, tvchain->backend_info)) { + gmyth_debug("Could not connect to db."); + goto done; + } + + stmt_str = g_string_new(""); + g_string_printf(stmt_str, + "SELECT channum, icon " + "FROM channel " + "WHERE channum = \"%s\" ORDER BY channum;", channel); + + msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str); + if (msql_res != NULL) { + + while ((msql_row = mysql_fetch_row(msql_res)) != NULL) { + GMythProgramInfo *entry = gmyth_program_info_new(); + + entry->channame = g_string_new(msql_row[0]); + entry->chansign = g_string_new(msql_row[1]); + + gmyth_debug + ("Reading TV program info entry (channel %s): [%s - {%s, %s}]\n", + entry->channame->str, entry->chansign->str, + (gchar *) msql_row[0], (gchar *) msql_row[1]); + + prog_list = g_list_append(prog_list, entry); + } + } else { + gmyth_debug + ("Query error when trying to get the channel list from database!\n"); + goto done; + } + + done: + g_mutex_unlock(tvchain->mutex); + + if (stmt_str != NULL) + g_string_free(stmt_str, TRUE); + + if (msql_res != NULL) + mysql_free_result(msql_res); + + if (gmyth_query != NULL) + g_object_unref(gmyth_query); + + return prog_list; +} + +/** + * Returns the internal index for the TV chain related to the given + * channel and start time. + * + * @param tvchain The GMythTVChain instance. + * @param chanid The channel id. + * @param startts The program start time. + * + * @return The position of the related program info in the TV chain. + */ +gint +gmyth_tvchain_program_is_at(GMythTVChain * tvchain, GString * chanid, + GTimeVal * startts) +{ + gint count = 0; + struct LiveTVChainEntry *entry; + GList *tmp_list = tvchain->tvchain_list; + guint list_size = g_list_length(tvchain->tvchain_list); + + g_mutex_lock(tvchain->mutex); + + for (; tmp_list && (count < list_size); + tmp_list = tvchain->tvchain_list->next, count++) { + entry = (struct LiveTVChainEntry *) tmp_list->data; + if (!g_strncasecmp(entry->chanid->str, chanid->str, chanid->len) + && entry->starttime == startts) { + g_mutex_unlock(tvchain->mutex); + return count; + } + } + g_mutex_unlock(tvchain->mutex); + + return -1; +} + +/** Get the program info associated to the tvchain. + * + * @param tvchain The GMythTVChain instance. + * @param index The tvchain index. + * + * @return The program info structure. + */ +GMythProgramInfo * +gmyth_tvchain_get_program_at(GMythTVChain * tvchain, gint index) +{ + struct LiveTVChainEntry *entry; + + entry = gmyth_tvchain_get_entry_at(tvchain, index); + + if (entry) + return gmyth_tvchain_entry_to_program(tvchain, entry); + + return NULL; +} + +/** Gets a LiveTVChainEntry associated to the tvchain by its index. + * + * @param tvchain The GMythTVChain instance. + * @param index The tvchain entry index + * @return The LiveTVchainEntry structure. + */ +struct LiveTVChainEntry * +gmyth_tvchain_get_entry_at(GMythTVChain * tvchain, gint index) +{ + struct LiveTVChainEntry *chain_entry = NULL; + + g_return_val_if_fail(tvchain != NULL + && tvchain->tvchain_list != NULL, NULL); + + g_mutex_lock(tvchain->mutex); + + gint size = g_list_length(tvchain->tvchain_list); + gint new_index = (index < 0 + || index >= size) ? size - 1 : index; + + if (new_index >= 0) + chain_entry = + (struct LiveTVChainEntry *) g_list_nth_data(tvchain-> + tvchain_list, + new_index); + + g_mutex_unlock(tvchain->mutex); + + if (chain_entry != NULL) { + gmyth_debug("[%s] Got TV Chain entry at %d.\n", __FUNCTION__, + new_index); + + } else { + gmyth_debug("[%s] failed to get entry at index %d", __FUNCTION__, + index); + } + + return chain_entry; +} + +/** + * Gets the program info from backend database associated to the tv chain entry. + * + * @param tvchain The GMythTVChain instance. + * @param entry the LiveTVChainEntry to be converted. + * + * @return The program info. + */ +GMythProgramInfo * +gmyth_tvchain_entry_to_program(GMythTVChain * tvchain, + struct LiveTVChainEntry * entry) +{ + GMythProgramInfo *proginfo = NULL; + + g_return_val_if_fail(tvchain != NULL, NULL); + + if (!entry || !tvchain) { + gmyth_debug + ("gmyth_tvchain_entry_to_program() received NULL argument"); + return NULL; + } + + GMythScheduler *scheduler = gmyth_scheduler_new(); + + gmyth_scheduler_connect(scheduler, tvchain->backend_info); + proginfo = gmyth_scheduler_get_recorded(scheduler, + entry->chanid, + entry->starttime); + gmyth_scheduler_disconnect(scheduler); + + if (proginfo) { + proginfo->pathname = + g_string_prepend(proginfo->pathname, entry->hostprefix->str); + } else { + gmyth_debug + ("tvchain_entry_to_program( chan id = %s, starttime = %ld) failed!", + entry->chanid->str, entry->starttime->tv_sec); + } + + return proginfo; +} + +static void +free_tvchain_entry(gpointer data, gpointer user_data) +{ + struct LiveTVChainEntry *entry; + + g_return_if_fail(data != NULL); + + entry = (struct LiveTVChainEntry *) data; + + if (entry->chanid != NULL) { + g_string_free(entry->chanid, TRUE); + } + + if (entry->starttime != NULL) { + g_free(entry->starttime); + } + + if (entry->endtime != NULL) { + g_free(entry->endtime); + } + + if (entry->hostprefix) { + g_string_free(entry->hostprefix, TRUE); + } + + if (entry->cardtype) { + g_string_free(entry->cardtype, TRUE); + } + + if (entry->channum) { + g_string_free(entry->channum, TRUE); + } + + if (entry->inputname) { + g_string_free(entry->inputname, TRUE); + } + + g_free(entry); +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_tvchain.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_tvchain.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,118 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_tvchain.h + * + * @brief

This component contains functions for creating and accessing + * the tvchain functions for live tv playback. + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef LIVETVCHAIN_H_ +#define LIVETVCHAIN_H_ + +#include +#include + +#include "gmyth_common.h" +#include "gmyth_backendinfo.h" + +G_BEGIN_DECLS +#define GMYTH_TVCHAIN_TYPE (gmyth_tvchain_get_type ()) +#define GMYTH_TVCHAIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TVCHAIN_TYPE, GMythTVChain)) +#define GMYTH_TVCHAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVCHAIN_TYPE, GMythTVChainClass)) +#define IS_GMYTH_TVCHAIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_TVCHAIN_TYPE)) +#define IS_GMYTH_TVCHAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVCHAIN_TYPE)) +#define GMYTH_TVCHAIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_TVCHAIN_TYPE, GMythTVChainClass)) +typedef struct _GMythTVChain GMythTVChain; +typedef struct _GMythTVChainClass GMythTVChainClass; + + +struct LiveTVChainEntry { + GString *chanid; + + GTimeVal *starttime; + GTimeVal *endtime; + + gboolean discontinuity; // if true, can't play smooth from + // last entry + GString *hostprefix; + GString *cardtype; + GString *channum; + GString *inputname; +}; + + +struct _GMythTVChainClass { + GObjectClass parent_class; + + /* + * callbacks + */ + /* + * no one for now + */ +}; + +struct _GMythTVChain { + GObject parent; + + GString *tvchain_id; + GList *tvchain_list; + + GTimeVal *cur_startts; + GString *cur_chanid; + gint cur_pos; + + GMythBackendInfo *backend_info; + + GMutex *mutex; +}; + +GType gmyth_tvchain_get_type(void); + +GMythTVChain *gmyth_tvchain_new(); + +gboolean gmyth_tvchain_initialize(GMythTVChain * tvchain, + GMythBackendInfo * backend_info); +gboolean gmyth_tvchain_reload_all(GMythTVChain * tvchain); +GString *gmyth_tvchain_get_id(GMythTVChain * tvchain); +gint gmyth_tvchain_program_is_at(GMythTVChain * tvchain, + GString * chanid, + GTimeVal * startts); + +struct LiveTVChainEntry *gmyth_tvchain_get_entry_at(GMythTVChain * tvchain, + gint index); + +GMythProgramInfo *gmyth_tvchain_entry_to_program(GMythTVChain * tvchain, struct LiveTVChainEntry + *entry); +GMythProgramInfo *gmyth_tvchain_get_program_at(GMythTVChain * tvchain, + gint index); + +GList *gmyth_tvchain_get_program_info_from_channel(GMythTVChain * + tvchain, + const gchar * + channel); + +GList *gmyth_tvchain_get_program_info_list(GMythTVChain * + tvchain); + +G_END_DECLS +#endif /* LIVETVCHAIN_H_ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_uri.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_uri.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,604 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_uri.c + * + * @brief

GMythURI utils + * - Extracts and parses a URI char string, in according with the RFC 2396 + * [http://www.ietf.org/rfc/rfc2396.txt] + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gmyth_uri.h" +#include "gmyth_socket.h" + +#include +#include +#include + +#include "gmyth_debug.h" + +/**************************************** +* Define +****************************************/ + +#define GMYTH_URI_KNKOWN_PORT (-1) +#define GMYTH_URI_DEFAULT_HTTP_PORT 80 +#define GMYTH_URI_DEFAULT_FTP_PORT 21 +#define GMYTH_URI_DEFAULT_MYTH_PORT 6543 +#define GMYTH_URI_DEFAULT_PATH "/" +#define GMYTH_URI_MAXLEN 256 + +#define GMYTH_URI_PROTOCOL_DELIM "://" +#define GMYTH_URI_USER_DELIM "@" +#define GMYTH_URI_COLON_DELIM ":" +#define GMYTH_URI_SLASH_DELIM "/" +#define GMYTH_URI_SBLACET_DELIM "[" +#define GMYTH_URI_EBLACET_DELIM "]" +#define GMYTH_URI_SHARP_DELIM "#" +#define GMYTH_URI_QUESTION_DELIM "?" +#define GMYTH_URI_E_DELIM "&" +#define GMYTH_URI_ESCAPING_CHAR "%" + +#define GMYTH_URI_PROTOCOL_MYTH "myth" +#define GMYTH_URI_PROTOCOL_HTTP "http" +#define GMYTH_URI_PROTOCOL_FTP "ftp" + + +static void gmyth_uri_class_init(GMythURIClass * klass); +static void gmyth_uri_init(GMythURI * object); + +static void gmyth_uri_dispose(GObject * object); +static void gmyth_uri_finalize(GObject * object); + +static void gmyth_uri_parser_setup_and_new(GMythURI * uri, + const gchar * value); +static gchar *gmyth_uri_print_field(const GString * field); + +G_DEFINE_TYPE(GMythURI, gmyth_uri, G_TYPE_OBJECT) + static void gmyth_uri_class_init(GMythURIClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_uri_dispose; + gobject_class->finalize = gmyth_uri_finalize; +} + +static void +gmyth_uri_init(GMythURI * gmyth_uri) +{ +} + +static void +gmyth_uri_dispose(GObject * object) +{ + GMythURI *gmyth_uri = GMYTH_URI(object); + + if (gmyth_uri->host != NULL) { + g_string_free(gmyth_uri->host, TRUE); + gmyth_uri->host = NULL; + } + + if (gmyth_uri->protocol != NULL) { + g_string_free(gmyth_uri->protocol, TRUE); + gmyth_uri->protocol = NULL; + } + + if (gmyth_uri->path != NULL) { + g_string_free(gmyth_uri->path, TRUE); + gmyth_uri->path = NULL; + } + + if (gmyth_uri->fragment != NULL) { + g_string_free(gmyth_uri->fragment, TRUE); + gmyth_uri->fragment = NULL; + } + + if (gmyth_uri->user != NULL) { + g_string_free(gmyth_uri->user, TRUE); + gmyth_uri->user = NULL; + } + + if (gmyth_uri->password != NULL) { + g_string_free(gmyth_uri->password, TRUE); + gmyth_uri->password = NULL; + } + + if (gmyth_uri->query != NULL) { + g_string_free(gmyth_uri->query, TRUE); + gmyth_uri->query = NULL; + } + + if (gmyth_uri->uri != NULL) { + g_string_free(gmyth_uri->uri, TRUE); + gmyth_uri->uri = NULL; + } + + + G_OBJECT_CLASS(gmyth_uri_parent_class)->dispose(object); +} + +static void +gmyth_uri_finalize(GObject * object) +{ + // GMythURI *gmyth_uri = GMYTH_URI(object); + + g_signal_handlers_destroy(object); + + G_OBJECT_CLASS(gmyth_uri_parent_class)->finalize(object); +} + +/** + * Creates a new instance of GMythURI. + * + * @return a new instance of GMythURI. + */ +GMythURI * +gmyth_uri_new(void) +{ + GMythURI *gmyth_uri = + GMYTH_URI(g_object_new(GMYTH_URI_TYPE, NULL)); + + return gmyth_uri; +} + +/** + * Creates a new instance of GMythURI. + * + * @param uri_str The URI string representing this URI instance. + * + * @return a new instance of GMythURI. + */ +GMythURI * +gmyth_uri_new_with_value(const gchar * uri_str) +{ + GMythURI *gmyth_uri = + GMYTH_URI(g_object_new(GMYTH_URI_TYPE, NULL)); + + gmyth_uri_parser_setup_and_new(gmyth_uri, uri_str); + + return gmyth_uri; +} + +/** + * Gets the starting offset of a substring inside a given string. + * + * @param haystack The given string to be searched for patterns. + * @param needle The substring that should be matched over the haystack. + * + * @return The starting offset to the given substring, or -1 if the + * haystack function parameter doesn't contains the needle string argument. + */ +static gint +gmyth_strstr(const gchar * haystack, const gchar * needle) +{ + + gchar *strPos; + + if (haystack == NULL || needle == NULL) + return -1; + strPos = strstr(haystack, needle); + if (strPos == NULL) + return -1; + + return (strPos - haystack); + +} + +/** + * Checks if a URI is absolute. + * + * @param uri The GMythURI instance. + * + * @return true, if the URI is absolute. + */ +static gboolean +gmyth_uri_isabsolute(const GMythURI * uri) +{ + gboolean ret = FALSE; + + g_return_val_if_fail(uri != NULL && uri->uri != NULL + && uri->protocol != NULL, FALSE); + + if (gmyth_strstr(uri->uri->str, GMYTH_URI_PROTOCOL_DELIM) == 0 + || strlen(uri->protocol->str) > 0) + ret = TRUE; + + return ret; +} + +/** + * Searches for the first reverse character occurrence, from a given + * list of characters, inside a given string. + * + * @param str The given string to be searched for characters occurrence. + * @param chars The characters list. If this string returns 4 on strlen, there are + * four possible characters to be matched. + * @param nchars The number of characters to be matched, which has at most + * strlen(chars). + * + * @return The starting offset to the first character occurrence, + * or -1 if the no character of the list could be found. + */ +static gint +gmyth_strrchr(const gchar * str, const gchar * chars, const gint nchars) +{ + + gint strLen; + gint i, + j; + + if (str == NULL || chars == NULL) + return -1; + + strLen = strlen(str); + for (i = (strLen - 1); 0 <= i; i--) { + for (j = 0; j < nchars; j++) { + if (str[i] == chars[j]) + return i; + } + } + + return -1; + +} + +static gchar * +gmyth_uri_print_field(const GString * field) +{ + if (field != NULL && field->str != NULL && strlen(field->str) > 0) + return field->str; + else + return ""; +} + +static gint +gmyth_uri_get_default_port (GMythURI * uri) +{ + const gchar *protocol = gmyth_uri_get_protocol(uri); + + if (strcmp(protocol, GMYTH_URI_PROTOCOL_HTTP) == 0) + return GMYTH_URI_DEFAULT_HTTP_PORT; + if (strcmp(protocol, GMYTH_URI_PROTOCOL_FTP) == 0) + return GMYTH_URI_DEFAULT_FTP_PORT; + if (strcmp(protocol, GMYTH_URI_PROTOCOL_MYTH) == 0) + return GMYTH_URI_DEFAULT_MYTH_PORT; + + return GMYTH_URI_KNKOWN_PORT; +} + +/** + * Parses a URI string into a GMythURI instance. + * + * @param uri The GMythURI instance. + * @param value The URI string to be parsed. + * + */ +static void +gmyth_uri_parser_setup_and_new(GMythURI * uri, const gchar * value) +{ + + gint uriLen; + gint currIdx; + gint protoIdx; + gint atIdx; + gint colonIdx; + gint shashIdx; + gint eIdx; + gchar *host; + gint eblacketIdx; + gint hostLen; + gint sharpIdx; + + /* + * gint questionIdx; gint queryLen; + */ + + uriLen = strlen(value); + uri->uri = g_string_new(value); + + currIdx = 0; + + /*** Protocol ****/ + protoIdx = gmyth_strstr(value, GMYTH_URI_PROTOCOL_DELIM); + if (0 < protoIdx) { + uri->protocol = g_string_new_len(value, protoIdx); + currIdx += protoIdx + strlen(GMYTH_URI_PROTOCOL_DELIM); + } + + /*** User (Password) ****/ + atIdx = gmyth_strstr(value + currIdx, GMYTH_URI_USER_DELIM); + if (0 < atIdx) { + colonIdx = gmyth_strstr(value + currIdx, GMYTH_URI_COLON_DELIM); + + if (0 < colonIdx && colonIdx < atIdx) { + uri->user = g_string_new_len(value + currIdx, colonIdx); + uri->password = + g_string_new_len(value + currIdx + colonIdx + 1, + atIdx - (colonIdx + 1)); + } else + uri->user = g_string_new_len(value + currIdx, atIdx - currIdx); + currIdx += atIdx + 1; + } + + /*** Host (Port) ****/ + shashIdx = gmyth_strstr(value + currIdx, GMYTH_URI_SLASH_DELIM); + if (0 < shashIdx) + uri->host = g_string_new_len(value + currIdx, shashIdx); + else if (gmyth_uri_isabsolute(uri) == TRUE) + uri->host = + g_string_new_len(value + currIdx, strlen(value) - currIdx); + + host = gmyth_uri_get_host(uri); + colonIdx = gmyth_strrchr(host, GMYTH_URI_COLON_DELIM, 1); + eblacketIdx = gmyth_strrchr(host, GMYTH_URI_EBLACET_DELIM, 1); + if ((0 < colonIdx) && (eblacketIdx < colonIdx)) { + GString *portStr = NULL; + GString *hostStr = g_string_new(host != NULL ? host : ""); + + hostLen = hostStr->len; + /**** host ****/ + uri->host = g_string_erase(uri->host, 0, hostLen); + uri->host = + g_string_insert_len(uri->host, 0, hostStr->str, colonIdx); + if (0 < hostLen) { + if (host[0] == '[' && host[hostLen - 1] == ']') + uri->host = + g_string_new_len(hostStr->str + 1, colonIdx - 2); + } + + /**** port ****/ + portStr = g_string_new_len(hostStr->str + colonIdx + 1, + hostLen - colonIdx - 1); + uri->port = (gint) g_ascii_strtoull(portStr->str, NULL, 10); + g_string_free(portStr, TRUE); + g_string_free(hostStr, TRUE); + } else { + uri->port = gmyth_uri_get_default_port (uri); + } + + if (shashIdx > 0) + currIdx += shashIdx; + + /* + * Handle relative URL + */ + if (gmyth_uri_isabsolute(uri) == FALSE) { + + if (shashIdx != 0) { + /* + * Add slash delimiter at the beginning of the URL, if it + * doesn't exist + */ + uri->path = g_string_new(GMYTH_URI_SLASH_DELIM); + } + uri->path = g_string_append(uri->path, value); + + } else { + /* + * First set path simply to the rest of URI + */ + uri->path = g_string_new_len(value + currIdx, uriLen - currIdx); + } + + // gmyth_debug( "uri value: %s", value ); + uri->query = + g_string_new(g_strstr_len + (value, strlen(value), GMYTH_URI_QUESTION_DELIM)); + + eIdx = gmyth_strstr(value + currIdx, GMYTH_URI_QUESTION_DELIM); + + if (0 < eIdx) { + uri->query = + g_string_new(g_strstr_len + (value, strlen(value), GMYTH_URI_QUESTION_DELIM)); + gmyth_debug("query = %s", uri->query->str); + } + + /**** Path (Query/Fragment) ****/ + sharpIdx = gmyth_strstr(value + currIdx, GMYTH_URI_E_DELIM); + if (0 < sharpIdx) { + uri->path = + g_string_append_len(uri->path, value + currIdx, sharpIdx); + uri->fragment = + g_string_new_len(value + currIdx + sharpIdx + 1, + uriLen - (currIdx + sharpIdx + 1)); + } + + gmyth_debug + ("[%s] GMythURI: host = %s, port = %d, path = %s, query = %s, fragment = %s, " + "user = %s, password = %s.\n", __FUNCTION__, + gmyth_uri_print_field(uri->host), uri->port, + gmyth_uri_print_field(uri->path), + gmyth_uri_print_field(uri->query), + gmyth_uri_print_field(uri->fragment), + gmyth_uri_print_field(uri->user), + gmyth_uri_print_field(uri->password)); + +} + +/** + * Compares 2 URI instances, and checks them for equality. + * + * @param uri The first GMythURI instance for comparison. + * @param uri The second GMythURI instance for comparison. + * + * @return true, if these two URI instances are equals. + */ +gboolean +gmyth_uri_is_equals(GMythURI * uri1, GMythURI * uri2) +{ + return (g_ascii_strcasecmp + (gmyth_uri_get_host(uri1), gmyth_uri_get_host(uri2)) == 0 + && gmyth_uri_get_port(uri1) == gmyth_uri_get_port(uri2)); +} + +/** + * Checks if the URI instance represents a LiveTV recording. + * + * @param uri The GMythURI instance. + * + * @return true, if the URI points to LiveTV content. + */ +gboolean +gmyth_uri_is_livetv(GMythURI * uri) +{ + gboolean ret = TRUE; + + g_return_val_if_fail(uri != NULL, FALSE); + g_return_val_if_fail(uri->uri != NULL, FALSE); + g_return_val_if_fail(uri->uri->str != NULL, FALSE); + + if ((strstr(uri->uri->str, "channel=") == NULL) && + (strstr(uri->uri->str, "livetv") == NULL)) + ret = FALSE; + + if (ret) + gmyth_debug("This URI is a LiveTV recording..."); + else + gmyth_debug("This URI is a stored remote recording."); + + return ret; + +} + +/** + * Gets the channel name fro a URI instance. + * + * @param uri The GMythURI instance. + * + * @return The channel name, got from the substring "?channel=[channel_name]" + * of the URI string. + */ +gchar * +gmyth_uri_get_channel_name(GMythURI * uri) +{ + gchar *channel = NULL; + + g_return_val_if_fail(uri != NULL && uri->uri != NULL + && uri->uri->str != NULL, FALSE); + + gchar *channel_query = g_strstr_len(gmyth_uri_get_query(uri), + strlen(gmyth_uri_get_query + (uri)), + "channel"); + + if (channel_query != NULL) { + gchar **chan_key_value = + g_strsplit(gmyth_uri_get_query(uri), "=", 2); + + /* + * gmyth_debug( "Channel tuple is [ %s, %s ]", chan_key_value[0], + * chan_key_value[1] ); + */ + + if (chan_key_value[1] != NULL && strlen(chan_key_value[1]) > 0) { + channel = g_strdup(chan_key_value[1]); + } + + if (chan_key_value != NULL) + g_strfreev(chan_key_value); + } + + gmyth_debug("Got channel decimal value from the URI: %s", channel); + + return channel; + +} + +/** + * Gets the channel number from a URI instance. + * + * @param uri The GMythURI instance. + * + * @return The channel number, got from the substring "?channel=[channel_number]" + * of the URI string, or -1 it if couldn't be converted. + */ +gint +gmyth_uri_get_channel_num(GMythURI * uri) +{ + gchar *channel_name = gmyth_uri_get_channel_name(uri); + + if (channel_name != NULL) { + return g_ascii_strtoull(channel_name, NULL, 10); + } + + return -1; + +} + +/** + * Checks if the URI instance represents a reference to a local file. + * + * @param uri The GMythURI instance. + * + * @return true, if the URI points to a local file. + */ +gboolean +gmyth_uri_is_local_file(const GMythURI * uri) +{ + gboolean ret = FALSE; + gint len = -1; + + GString *hostname = gmyth_socket_get_local_hostname(); + + g_return_val_if_fail(uri != NULL, FALSE); + + len = strlen(gmyth_uri_get_host(uri)); + + // gmyth_debug("URI: host = %s, hostname = %s.", uri->host->str, + // hostname != NULL ? hostname->str : "[no hostname]"); + + ret = (NULL != hostname && (g_ascii_strncasecmp(uri->host->str, (hostname)->str, len) == 0) /* || + * ( + * g_ascii_strncasecmp( + * gmyth_uri_get_host(uri), + * gmyth_socket_get_primary_addr(), + * len + * ) + * == + * 0 + * ) + */ + ); + + if (ret) + gmyth_debug("This URI is a local file..."); + else + gmyth_debug("This URI is NOT a local file..."); + + return ret; + +} + +char * +gmyth_uri_to_string(const GMythURI * uri) +{ + g_return_val_if_fail(uri != NULL, NULL); + g_return_val_if_fail(uri->uri != NULL, NULL); + + return g_strdup(uri->uri->str); +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_uri.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_uri.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,101 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_uri.h + * + * @brief

GMythURI utils + * - Extracts and parses a URI char string, in according with the RFC 2396 + * [http://www.ietf.org/rfc/rfc2396.txt] + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Rosfran Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _GMYTH_URI_H_ +#define _GMYTH_URI_H_ + +#include +#include + +#include +#include +#include + +G_BEGIN_DECLS +#define GMYTH_URI_TYPE (gmyth_uri_get_type ()) +#define GMYTH_URI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_URI_TYPE, GMythURI)) +#define GMYTH_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_URI_TYPE, GMythURIClass)) +#define IS_GMYTH_URI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_URI_TYPE)) +#define IS_GMYTH_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_URI_TYPE)) +#define GMYTH_URI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_URI_TYPE, GMythURIClass)) +typedef struct _GMythURI GMythURI; +typedef struct _GMythURIClass GMythURIClass; + + + /**************************************** + * Data Type + ****************************************/ + +struct _GMythURIClass { + GObjectClass parent_class; + + /* + * callbacks + */ + /* + * no one for now + */ +}; + +struct _GMythURI { + + GObject parent; + + GString *uri; + GString *host; + gint port; + GString *protocol; + GString *path; + GString *fragment; + GString *user; + GString *password; + GString *query; + +}; + +GType gmyth_uri_get_type(void); +GMythURI *gmyth_uri_new(void); +GMythURI *gmyth_uri_new_with_value(const gchar * value); +gboolean gmyth_uri_is_equals(GMythURI * uri1, GMythURI * uri2); +gboolean gmyth_uri_is_livetv(GMythURI * uri); +gint gmyth_uri_get_channel_num(GMythURI * uri); +gchar *gmyth_uri_get_channel_name(GMythURI * uri); +char *gmyth_uri_to_string(const GMythURI * uri); +gboolean gmyth_uri_is_local_file(const GMythURI * uri); + +#define gmyth_uri_get_host(urip) ( urip->host != NULL ? urip->host->str : "" ) +#define gmyth_uri_get_port(urip) ( urip->port ) +#define gmyth_uri_get_protocol(urip) ( urip->protocol != NULL ? urip->protocol->str : "" ) +#define gmyth_uri_get_path(urip) ( urip->path != NULL ? urip->path->str : "" ) +#define gmyth_uri_get_user(urip) ( urip->user != NULL ? urip->user->str : "" ) +#define gmyth_uri_get_password(urip) ( urip->password != NULL ? urip->password->str : "" ) +#define gmyth_uri_get_fragment(urip) ( urip->fragment != NULL ? urip->fragment->str : "" ) +#define gmyth_uri_get_query(urip) ( urip->query != NULL ? urip->query->str : "" ) + +G_END_DECLS +#endif /* _GMYTH_URI_H_ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_util.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_util.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,957 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_util.c + * + * @brief

This component provides utility functions + * (dealing with dates, time, string formatting, etc.). + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * @author Rosfran Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define _XOPEN_SOURCE +#define _XOPEN_SOURCE_EXTENDED +#define __USE_MISC + +#include +#include +#include +#include +#include + +#include "gmyth_socket.h" +#include "gmyth_recorder.h" +#include "gmyth_common.h" +#include "gmyth_debug.h" + +#include "gmyth_util.h" + +#if !GLIB_CHECK_VERSION (2, 10, 0) +gchar *g_time_val_to_iso8601(GTimeVal * time_); +gboolean g_time_val_from_iso8601(const gchar * iso_date, + GTimeVal * time_); +void g_date_set_time_val(GDate * date, GTimeVal * timeval); + +#endif + +/** Converts a time_t struct in a GString at ISO standard format + * (e.g. 2006-07-20T09:56:41). + * + * The returned GString memory should be deallocated from + * the calling function. + * + * @param time_value the time value to be converted + * @return GString* the converted isoformat string + */ +GString * +gmyth_util_time_to_isoformat(time_t time_value) +{ + struct tm tm_time; + GString *result; + + if (localtime_r(&time_value, &tm_time) == NULL) { + gmyth_debug("gmyth_util_time_to_isoformat convertion error!\n"); + return NULL; + } + + result = g_string_sized_new(20); + g_string_printf(result, "%04d-%02d-%02dT%02d:%02d:%02d", + tm_time.tm_year + 1900, tm_time.tm_mon + 1, + tm_time.tm_mday, tm_time.tm_hour, tm_time.tm_min, + tm_time.tm_sec); + + gmyth_debug("Result (ISO 8601) = %s", result->str); + + return result; +} + +/** Converts a time_t struct in a GString at ISO standard format + * (e.g. 2006-07-20T09:56:41). + * + * The returned GString memory should be deallocated from + * the calling function. + * + * @param time_value the GTimeValue to be converted + * @return GString* the converted isoformat string + */ +gchar * +gmyth_util_time_to_isoformat_from_time_val_fmt(const gchar * fmt_string, + const GTimeVal * time_val) +{ + gchar *result = NULL; + struct tm *tm_time = NULL; + time_t time; + + gint buffer_len = 0; + + g_return_val_if_fail(fmt_string != NULL, NULL); + + g_return_val_if_fail(time_val != NULL, NULL); + + time = time_val->tv_sec; // + (gint)( time_val->tv_usec / + // G_USEC_PER_SEC ); + + tm_time = g_malloc0(sizeof(struct tm)); + + if (NULL == localtime_r(&time, tm_time)) { + gmyth_debug("gmyth_util_time_to_isoformat convertion error!\n"); + } else { + /* + * we first check the return of strftime to allocate a buffer of + * the correct size + */ + buffer_len = strftime(NULL, SSIZE_MAX, fmt_string, tm_time); + if (buffer_len > 0) { + result = g_malloc0(buffer_len + 1); + if (result == NULL) { + gmyth_debug + ("gmyth_util_time_to_isoformat convertion error!\n"); + return NULL; + } + strftime(result, buffer_len + 1, fmt_string, tm_time); + gmyth_debug("Dateline (ISO result): %s", result); + } + } /* if */ + + gmyth_debug("Result (strftime) = %s", result); + + // strptime( result, "%Y-%m-%dT%H:%M:%SZ", tm_time ); + + // strftime( result, strlen(result), fmt_string, tm_time ); + + g_free(tm_time); + + gmyth_debug("Result (ISO 8601) = %s", result); + + return result; +} + +/** Converts a time_t struct in a GString at ISO standard format + * (e.g. 2006-07-20 09:56:41). + * + * The returned GString memory should be deallocated from + * the calling function. + * + * @param time_value the GTimeValue to be converted + * @return GString* the converted isoformat string + */ +gchar * +gmyth_util_time_to_isoformat_from_time_val(const GTimeVal * time) +{ + gchar *result = + gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%d %H:%M:%S", + time); + + // result[10] = ' '; + // result[ strlen(result) - 1] = '\0'; + + return result; +} + +/** Converts a time_t struct in a GString at ISO standard format 2 + * (e.g. 2006-07-20T09:56:41). + * + * The returned GString memory should be deallocated from + * the calling function. + * + * @param time_value the GTimeValue to be converted + * @return GString* the converted isoformat string + */ +gchar * +gmyth_util_time_to_mythformat_from_time_val(const GTimeVal * time) +{ + gchar *result = + gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%dT%H:%M:%S", + time); + + return result; +} + +/** Converts a time_t struct in a GString at ISO standard format + * (e.g. 2006-07-20T09:56:41). + * + * The returned GString memory should be deallocated from + * the calling function. + * + * @param time_value the GTimeValue to be converted + * @return GString* the converted isoformat string + */ +gchar * +gmyth_util_time_to_string_only_date(const GTimeVal * time) +{ + gchar *result = + gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%d", time); + // result[10] = ' '; + // result[ strlen(result) - 1] = '\0'; + return result; +} + +/** Converts a time_t struct in a GString at ISO standard format + * (e.g. 2006-07-20T09:56:41). + * + * The returned GString memory should be deallocated from + * the calling function. + * + * @param time_value the GTimeValue to be converted + * @return GString* the converted isoformat string + */ +gchar * +gmyth_util_time_to_string_only_time(const GTimeVal * time) +{ + gchar *result = + gmyth_util_time_to_isoformat_from_time_val_fmt("%H:%M:%S", time); + // result[10] = ' '; + // result[ strlen(result) - 1] = '\0'; + return result; +} + +/** Converts a time_t struct in a GString to the following + * format (e.g. 2006-07-20 09:56:41). + * + * The returned GString memory should be deallocated from + * the calling function. + * + * @param time_value the time value to be converted + * @return GString* the converted string + */ +GString * +gmyth_util_time_to_string(time_t time_value) +{ + GString *result = gmyth_util_time_to_isoformat(time_value); + + result->str[10] = ' '; + result->str[strlen(result->str) - 1] = '\0'; + + return result; +} + +/** Converts a time_t struct in a GString to the following + * format (e.g. 2006-07-20 09:56:41). + * + * The returned GString memory should be deallocated from + * the calling function. + * + * @param time_value the time value to be converted + * @return GString* the converted string + */ +gchar * +gmyth_util_time_to_string_from_time_val(const GTimeVal * time_val) +{ + gchar *result = + gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%d %H:%M:%S", + time_val); + + // result[10] = ' '; + + return result; +} + +/** Converts a GString in the following format + * (e.g. 2006-07-20 09:56:41) to a time_t struct. + * + * @param time_str the string to be converted + * @return time_t the time converted value + */ +time_t +gmyth_util_string_to_time(GString * time_str) +{ + gint year, + month, + day, + hour, + min, + sec; + + gmyth_debug("[%s] time_str = %s. [%s]", __FUNCTION__, + time_str != + NULL ? time_str->str : "[time string is NULL!]", + time_str->str); + + if (sscanf(time_str->str, "%04d-%02d-%02d %02d:%02d:%02d", + &year, &month, &day, &hour, &min, &sec) < 3) { + gmyth_debug("GMythUtil: isoformat_to_time converter error!\n"); + return 0; + } + + struct tm *tm_time = g_malloc0(sizeof(struct tm)); + + tm_time->tm_year = year - 1900; + tm_time->tm_mon = month - 1; + tm_time->tm_mday = day; + tm_time->tm_hour = hour; + tm_time->tm_min = min; + tm_time->tm_sec = sec; + + return mktime(tm_time); +} + +/** Converts a GString in the following format + * (e.g. 2006-07-20 09:56:41) to a time_t struct. + * + * @param time_str the string to be converted + * @return time_t the time converted value + */ +struct tm * +gmyth_util_time_val_to_date(const GTimeVal * time) +{ + struct tm *date = g_malloc0(sizeof(struct tm)); + time_t time_micros = time->tv_sec; // + (gint)( time->tv_usec + // + // + // / G_USEC_PER_SEC ); + + if (NULL == date) { + gmyth_debug + ("GMythUtil: GDate *gmyth_util_time_val_to_date (GTimeVal* time) - converter error!\n"); + return NULL; + } + + if (NULL == localtime_r(&time_micros, date)) { + gmyth_debug("gmyth_util_time_to_isoformat convertion error!\n"); + return NULL; + } + + gmyth_debug("Converted from GTimeVal == %s to GDate", asctime(date)); + + return date; +} + +/** Converts a GString in the following format + * (e.g. 2006-07-20 09:56:41) to a time_t struct. + * + * @param time_str the string to be converted + * @return time_t the time converted value + */ +GTimeVal * +gmyth_util_string_to_time_val_fmt(const gchar * fmt_string, + const gchar * time_str) +{ + GTimeVal *time = g_new0(GTimeVal, 1); + struct tm *tm_time = NULL; + time_t time_micros; + gchar *result; + + gmyth_debug("[%s] time_str = %s. [%s]", time_str, time_str != NULL ? + time_str : "[time string is NULL!]", time_str); + + if (NULL == time_str) { + gmyth_debug("GMythUtil: isoformat_to_time converter error!\n"); + return NULL; + } + + tm_time = g_malloc0(sizeof(struct tm)); + + /* + * we first check the return of strftime to allocate a buffer of the + * correct size + */ + result = strptime(time_str, "%Y-%m-%dT%H:%M:%S", tm_time); + if (NULL == result) { + /* + * we first check the return of strftime to allocate a buffer of + * the correct size + */ + result = strptime(time_str, "%Y-%m-%dT%H:%M:%SZ", tm_time); + if (NULL == result) { + /* + * we first check the return of strftime to allocate a buffer + * of the correct size + */ + result = strptime(time_str, "%Y-%m-%d %H:%M:%S", tm_time); + if (NULL == result) { + result = strptime(time_str, "%Y-%m-%dT%H:%M", tm_time); + if (NULL == result) { + gmyth_debug("Dateline (ISO result): %s", result); + g_free(tm_time); + return NULL; + // goto done; + } + } + } + } + + time_micros = mktime(tm_time); + + time->tv_sec = time_micros; // + (gint)( time_val->tv_usec / + // G_USEC_PER_SEC ); + + gmyth_debug("After mktime call... = %s", asctime(tm_time)); + + g_free(tm_time); + + return time; +} + +/** Converts a GString in the following format + * (e.g. 2006-07-20 09:56:41) to a time_t struct. + * + * @param time_str the string to be converted + * @return time_t the time converted value + */ +GTimeVal * +gmyth_util_string_to_time_val(const gchar * time_str) +{ + GTimeVal *time = + gmyth_util_string_to_time_val_fmt("%Y-%m-%d %H:%M:%S", time_str); + + return time; +} + +/** + * Checks if the given remote file exists. + * + * @param backend_info The GMythBackendInfo instance. + * @param filename The file name of the remote file. + * + * @return true, if the remote file exists. + */ +gboolean +gmyth_util_file_exists(GMythBackendInfo * backend_info, + const gchar * filename) +{ + GMythSocket *socket; + gboolean res = FALSE; + + gmyth_debug("Check if file %s exists", filename); + + g_return_val_if_fail(backend_info != NULL, FALSE); + g_return_val_if_fail(filename != NULL, FALSE); + + socket = gmyth_backend_info_get_connected_socket (backend_info); + if (socket != NULL) { + res = gmyth_util_file_exists_from_socket (socket, filename); + g_object_unref(socket); + } + return res; +} + +gboolean +gmyth_util_file_exists_from_socket (GMythSocket *sock, + const gchar *filename) +{ + gboolean res = FALSE; + gint length = 0; + GMythStringList *slist; + GMythProgramInfo *program = NULL; + + program = gmyth_program_info_new(); + program->pathname = g_string_new(filename); + + slist = gmyth_string_list_new(); + gmyth_string_list_append_char_array(slist, "QUERY_CHECKFILE"); + gmyth_program_info_to_string_list(program, slist); + + length = gmyth_socket_sendreceive_stringlist (sock, slist); + if (length > 0) + res = (gmyth_string_list_get_int(slist, 0) == 1); + + g_object_unref(program); + g_object_unref(slist); + + return res; +} + +gboolean +gmyth_util_get_backend_details (GMythSocket *sock, GMythBackendDetails **details) +{ + gboolean res = FALSE; + gint length = 0; + GMythStringList *slist; + + slist = gmyth_string_list_new(); + gmyth_string_list_append_char_array(slist, "QUERY_FREE_SPACE"); + + length = gmyth_socket_sendreceive_stringlist (sock, slist); + if (length >= 8) { + *details = g_new0 (GMythBackendDetails, 1); + (*details)->total_space = gmyth_string_list_get_uint64 (slist, 4) * 1024; + (*details)->used_space = gmyth_string_list_get_uint64 (slist, 6) * 1024; + res = TRUE; + } + + g_object_unref(slist); + + return res; +} + +void +gmyth_util_backend_details_free (GMythBackendDetails *details) +{ + g_free (details); +} + + +/** + * Checks if the given remote file exists, and gets its remote directory. + * + * @param backend_info The GMythBackendInfo instance. + * @param filename The file name of the remote file. + * @param current_dir String pointer to the directory where the remote file is stored. + * + * @return true, if the remote file exists. + */ +gboolean +gmyth_util_file_exists_and_get_remote_dir(GMythBackendInfo * backend_info, + const gchar * filename, + gchar ** current_dir) +{ + GMythSocket *socket; + gboolean res; + + *current_dir = NULL; + + socket = gmyth_socket_new(); + res = gmyth_socket_connect_to_backend(socket, backend_info->hostname, + backend_info->port, TRUE); + + if (res == TRUE) { + GMythStringList *slist; + GMythProgramInfo *program = NULL; + + program = gmyth_program_info_new(); + program->pathname = g_string_new(filename); + + slist = gmyth_string_list_new(); + gmyth_string_list_append_char_array(slist, "QUERY_CHECKFILE"); + + gmyth_program_info_to_string_list(program, slist); + + gmyth_socket_sendreceive_stringlist(socket, slist); + + res = (gmyth_string_list_get_int(slist, 0) == 1); + + if ((gmyth_string_list_length(slist) > 1) && + gmyth_string_list_get_char_array(slist, 1) != NULL) + *current_dir = + g_strdup(gmyth_string_list_get_char_array(slist, 1)); + + if (*current_dir != NULL) + gmyth_debug("Current directory = %s.", (*current_dir != NULL) + ? *current_dir : "[directory not found]"); + + g_object_unref(program); + + g_object_unref(slist); + + gmyth_socket_close_connection(socket); + } + g_object_unref(socket); + return res; +} + +/** + * Creates a file name to a possible existing remote file, + * based on some fields of the LiveTV/recorded program info. + * + * @param chan_id The channel ID number. + * @param start_time The start time of the recording. + * + * @return The string representing the file name. + */ +gchar * +gmyth_util_create_filename(const gint chan_id, const GTimeVal * start_time) +{ + gchar *basename = NULL; + + g_return_val_if_fail(start_time != NULL, NULL); + + gchar *isodate = + gmyth_util_time_to_isoformat_from_time_val_fmt("%Y%m%d%H%M%S", + start_time); + + basename = g_strdup_printf("%d_%s", chan_id, isodate); + + gmyth_debug("Basename (from chan_id and start_time): %s", basename); + + if (isodate) + g_free(isodate); + + return basename; +} + +/** + * Gets the channel list. + * + * @param backend_info The GMythBackendInfo instance. + * + * @return a pointer to a GList with all the channels. + */ +GList * +gmyth_util_get_channel_list(GMythBackendInfo * backend_info) +{ + GMythRecorder *recorder; + GList *channel_list = NULL; + gboolean res = FALSE; + + gmyth_debug("Gets channel list."); + + g_return_val_if_fail(backend_info != NULL, FALSE); + + recorder = + gmyth_recorder_new(1, + g_string_new(gmyth_backend_info_get_hostname + (backend_info)), + gmyth_backend_info_get_port(backend_info)); + res = gmyth_recorder_setup(recorder); + + if (res == TRUE) { + // GList* channel_list = gmyth_recorder_get_channel_list( recorder + // + // + // ); + gmyth_debug("Yeah, got channel list!!!"); + GList *ch = NULL; + GMythChannelInfo *channel_info = NULL; + + for (ch = gmyth_recorder_get_channel_list(recorder); ch != NULL;) { + channel_info = g_malloc0(sizeof(GMythChannelInfo)); + channel_info->channel_ID = 0; + channel_info->channel_num = + g_string_new(g_strdup((gchar *) ch->data)); + channel_info->channel_name = g_string_new(""); + gmyth_debug("Printing channel info... (%s)", + channel_info->channel_num->str); + channel_list = + g_list_append(channel_list, + g_memdup(channel_info, + sizeof(GMythChannelInfo))); + + ch = g_list_next(ch); + + if (channel_info != NULL) + g_free(channel_info); + } + + } /* if */ + else { + gmyth_debug("No, couldn't get the channel list!!!"); + } + + gmyth_debug("Got %d channels!!!", g_list_length(channel_list)); + + + g_object_unref(recorder); + + return channel_list; +} + +/** + * Gets all the recordings from remote encoder. + * + * @param backend_info The GMythBackendInfo instance. + * + * @return The program info's listage. + */ +GSList * +gmyth_util_get_all_recordings(GMythBackendInfo * backend_info) +{ + GSList *program_list = NULL; + GMythSocket *socket; + gboolean res; + + socket = gmyth_socket_new(); + res = gmyth_socket_connect_to_backend(socket, backend_info->hostname, + backend_info->port, TRUE); + + if (res == TRUE) { + GMythStringList *slist = gmyth_string_list_new(); + guint pos = 0; + + gmyth_string_list_append_char_array(slist, + "QUERY_RECORDINGS Play"); + + gmyth_socket_sendreceive_stringlist(socket, slist); + + if (slist != NULL && (gmyth_string_list_length(slist) > 0)) { + GMythProgramInfo *program = NULL; + + gmyth_debug("OK! Got the program list [size=%d].", + gmyth_string_list_length(slist)); + + do { + program = + gmyth_program_info_from_string_list_from_pos(slist, + pos); + + if (program != NULL) { + pos += 41; + + program_list = g_slist_append(program_list, program); + } else + break; + + } + while (gmyth_string_list_length(slist) > pos); + + } + /* + * if + */ + g_object_unref(slist); + + gmyth_socket_close_connection(socket); + } + g_object_unref(socket); + + return program_list; +} + +/** + * Checks if the given remote file exists, and gets its remote directory. + * + * @param backend_info The GMythBackendInfo instance. + * @param channel The channel name of the program info. + * + * @return The requested program info. + */ +GMythProgramInfo * +gmyth_util_get_recording_from_channel(GMythBackendInfo * backend_info, + const gchar * channel) +{ + GSList *program_list = NULL; + GMythProgramInfo *program = NULL; + + program_list = gmyth_util_get_all_recordings(backend_info); + + if (program_list != NULL && g_slist_length(program_list) > 0) { + GMythProgramInfo *program = NULL; + guint pos = 0; + + gmyth_debug("OK! Got the program list [size=%d].", + g_slist_length(program_list)); + + while (pos < g_slist_length(program_list)) { + program = + (GMythProgramInfo *) g_slist_nth_data(program_list, pos); + + if (program != NULL && program->channame != NULL && + g_ascii_strncasecmp(program->channame->str, channel, + strlen(channel)) == 0) { + break; + } + + ++pos; + + } /* while */ + + } + /* + * if + */ + return program; +} + +#if !GLIB_CHECK_VERSION (2, 10, 0) + +/* + * Hacked from glib 2.10 + */ + +static time_t +mktime_utc(struct tm *tm) +{ + time_t retval; + +#ifndef HAVE_TIMEGM + static const gint days_before[] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 + }; +#endif + +#ifndef HAVE_TIMEGM + if (tm->tm_mon < 0 || tm->tm_mon > 11) + return (time_t) - 1; + + retval = (tm->tm_year - 70) * 365; + retval += (tm->tm_year - 68) / 4; + retval += days_before[tm->tm_mon] + tm->tm_mday - 1; + + if (tm->tm_year % 4 == 0 && tm->tm_mon < 2) + retval -= 1; + + retval = + ((((retval * 24) + tm->tm_hour) * 60) + tm->tm_min) * 60 + + tm->tm_sec; +#else + retval = timegm(tm); +#endif /* !HAVE_TIMEGM */ + + return retval; +} + +gboolean +g_time_val_from_iso8601(const gchar * iso_date, GTimeVal * time_) +{ + struct tm tm; + long val; + + g_return_val_if_fail(iso_date != NULL, FALSE); + g_return_val_if_fail(time_ != NULL, FALSE); + + val = strtoul(iso_date, (char **) &iso_date, 10); + if (*iso_date == '-') { + /* + * YYYY-MM-DD + */ + tm.tm_year = val - 1900; + iso_date++; + tm.tm_mon = strtoul(iso_date, (char **) &iso_date, 10) - 1; + + if (*iso_date++ != '-') + return FALSE; + + tm.tm_mday = strtoul(iso_date, (char **) &iso_date, 10); + } else { + /* + * YYYYMMDD + */ + tm.tm_mday = val % 100; + tm.tm_mon = (val % 10000) / 100 - 1; + tm.tm_year = val / 10000 - 1900; + } + + if (*iso_date++ != 'T') + return FALSE; + + val = strtoul(iso_date, (char **) &iso_date, 10); + if (*iso_date == ':') { + /* + * hh:mm:ss + */ + tm.tm_hour = val; + iso_date++; + tm.tm_min = strtoul(iso_date, (char **) &iso_date, 10); + + if (*iso_date++ != ':') + return FALSE; + + tm.tm_sec = strtoul(iso_date, (char **) &iso_date, 10); + } else { + /* + * hhmmss + */ + tm.tm_sec = val % 100; + tm.tm_min = (val % 10000) / 100; + tm.tm_hour = val / 10000; + } + + time_->tv_sec = mktime_utc(&tm); + time_->tv_usec = 1; + + if (*iso_date == '.') + time_->tv_usec = strtoul(iso_date + 1, (char **) &iso_date, 10); + + if (*iso_date == '+' || *iso_date == '-') { + gint sign = (*iso_date == '+') ? -1 : 1; + + val = 60 * strtoul(iso_date + 1, (char **) &iso_date, 10); + + if (*iso_date == ':') + val = 60 * val + strtoul(iso_date + 1, NULL, 10); + else + val = 60 * (val / 100) + (val % 100); + + time_->tv_sec += (time_t) (val * sign); + } + + return TRUE; +} + + +gchar * +g_time_val_to_iso8601(GTimeVal * time_) +{ + gchar *retval; + + g_return_val_if_fail(time_->tv_usec >= 0 + && time_->tv_usec < G_USEC_PER_SEC, NULL); + +#define ISO_8601_LEN 21 +#define ISO_8601_FORMAT "%Y-%m-%dT%H:%M:%SZ" + retval = g_new0(gchar, ISO_8601_LEN + 1); + + strftime(retval, ISO_8601_LEN, ISO_8601_FORMAT, + gmtime(&(time_->tv_sec))); + + return retval; +} + + +/* + * Hacked from glib 2.10 + */ + +void +g_date_set_time_t(GDate * date, time_t timet) +{ + struct tm tm; + + g_return_if_fail(date != NULL); + +#ifdef HAVE_LOCALTIME_R + localtime_r(&timet, &tm); +#else + { + struct tm *ptm = localtime(&timet); + + if (ptm == NULL) { + /* + * Happens at least in Microsoft's C library if you pass a + * negative time_t. Use 2000-01-01 as default date. + */ +#ifndef G_DISABLE_CHECKS + g_return_if_fail_warning(G_LOG_DOMAIN, "g_date_set_time", + "ptm != NULL"); +#endif + + tm.tm_mon = 0; + tm.tm_mday = 1; + tm.tm_year = 100; + } else + memcpy((void *) &tm, (void *) ptm, sizeof(struct tm)); + } +#endif + + date->julian = FALSE; + + date->month = tm.tm_mon + 1; + date->day = tm.tm_mday; + date->year = tm.tm_year + 1900; + + g_return_if_fail(g_date_valid_dmy(date->day, date->month, date->year)); + + date->dmy = TRUE; +} + + +void +g_date_set_time_val(GDate * date, GTimeVal * timeval) +{ + g_date_set_time_t(date, (time_t) timeval->tv_sec); +} + + + + +#endif diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_util.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_util.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,82 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_util.h + * + * @brief

This component provides utility functions + * (dealing with dates, time, string formatting, etc.). + * + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. + * @author Hallyson Luiz de Morais Melo + * @author Rosfran Borges + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef GMYTH_UTIL_H_ +#define GMYTH_UTIL_H_ + +#include +#include + +#include "gmyth_stringlist.h" +#include "gmyth_backendinfo.h" +#include "gmyth_programinfo.h" + +G_BEGIN_DECLS + +typedef struct { + guint64 total_space; + guint64 used_space; +} GMythBackendDetails; + + +GString* gmyth_util_time_to_isoformat (time_t time_value); +GString* gmyth_util_time_to_string (time_t time_value); +time_t gmyth_util_string_to_time (GString *time_str); +gchar* gmyth_util_time_to_isoformat_from_time_val_fmt + (const gchar *fmt_string, + const GTimeVal *time_val); +GTimeVal* gmyth_util_string_to_time_val_fmt (const gchar *fmt_string, + const gchar *time_str); +GTimeVal* gmyth_util_string_to_time_val (const gchar *time_str); +gchar* gmyth_util_time_to_isoformat_from_time_val (const GTimeVal *time); +gchar* gmyth_util_time_to_mythformat_from_time_val (const GTimeVal *time); +gchar* gmyth_util_time_to_string_only_date (const GTimeVal *time); +gchar* gmyth_util_time_to_string_only_time (const GTimeVal *time); +gchar* gmyth_util_time_to_string_from_time_val (const GTimeVal *time_val); +struct tm* gmyth_util_time_val_to_date (const GTimeVal * time); + +gboolean gmyth_util_get_backend_details (GMythSocket *sock, GMythBackendDetails **details); +void gmyth_util_backend_details_free (GMythBackendDetails *details); + +gboolean gmyth_util_file_exists (GMythBackendInfo *backend_info, + const gchar * filename); +gboolean gmyth_util_file_exists_from_socket (GMythSocket *sock, + const gchar *filename); +gboolean gmyth_util_file_exists_and_get_remote_dir (GMythBackendInfo *backend_info, + const gchar *filename, + gchar **current_dir); +gchar* gmyth_util_create_filename (const gint chan_id, + const GTimeVal * start_time); +GList* gmyth_util_get_channel_list (GMythBackendInfo *backend_info); +GSList* gmyth_util_get_all_recordings (GMythBackendInfo *backend_info); +GMythProgramInfo* + gmyth_util_get_recording_from_channel (GMythBackendInfo *backend_info, + const gchar *channel); + +G_END_DECLS +#endif /* GMYTH_UTIL_H_ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_vlc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_vlc.c Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,290 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_vlc.c + * + * @brief

GMythVLC library provides functions that + * interact with a VLC server running telnet interface. + * + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. + * @author Artur Duque de Souza + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "gmyth_vlc.h" +#include "gmyth_debug.h" +#include "gmyth_socket.h" + +/* + * static functions + */ +static int _socket_send(int socket, gchar * msg); +static int _socket_recv(int socket, gchar * buf); + +/** Primitive function to send a message through the socket + * + * @param socket + * @param msg the message itself + * @return 0 if success + */ +static int +_socket_send(int socket, gchar * msg) +{ + size_t size = strlen(msg) + 2; // (\n + \0) + gchar *final = (gchar *) g_malloc0(sizeof(gchar) * size); + + g_snprintf(final, size, "%s\n", msg); + + if (send(socket, final, strlen(final), 0) == -1) + perror("GMyth_VLC: send error"); + + g_free(final); + return 0; +} + + +/** Primitive function to receive a message through the socket + * + * @param socket + * @param buf Buffer to put the message + * @return 0 if success + */ +static int +_socket_recv(int socket, gchar * buf) +{ + int numbytes = 0; + + if ((numbytes = recv(socket, buf, BUFFER - 1, 0)) == -1) { + perror("GMyth_VLC: recv error"); + return -1; + } + + buf[numbytes - 1] = '\0'; + return numbytes; +} + + +/** Function that adds options to the output media + * + * @param vlc structure with options for vlc + * @param output the number of the output media + * @param kind the type of option we'll change + * @param the params for the option + * @return 0 if success + */ +int +gmyth_vlc_setup_output(GMythVlc * vlc, int output, gchar * kind, + gchar * opts) +{ + int ret; + + size_t size = strlen(opts) + 25; + gchar *msg = g_malloc0(sizeof(gchar) * size); + + g_snprintf(msg, size, "setup output%d %s %s", output, kind, opts); + + ret = _socket_send(vlc->sockfd, msg); + + g_free(msg); + return ret; +} + + +/** Function to clean the playlist + * + * @param vlc structure with options for vlc + * @param output the number of the output media + * @param file the file we want to insert in the playlist + * @return 0 if success + */ +int +gmyth_vlc_clean_playlist(GMythVlc * vlc) +{ + return _socket_send(vlc->sockfd, "del all"); +} + + +/** Function to control the playlist + * + * @param vlc structure with options for vlc + * @param output the number of the output media + * @param command play, stop or pause(just for vod) + * @return 0 if success + */ +int +gmyth_vlc_control_input(GMythVlc * vlc, int output, gchar * command) +{ + size_t size = 25; + gchar *msg = g_malloc0(sizeof(gchar) * size); + + g_snprintf(msg, size, "control output%d %s", output, command); + + int ret = _socket_send(vlc->sockfd, msg); + + g_free(msg); + return ret; +} + + + +/** Function to insert an item in the playlist + * + * @param vlc structure with options for vlc + * @param output the number of the output media + * @param file the file we want to insert in the playlist + * @return 0 if success + */ +int +gmyth_vlc_create_input(GMythVlc * vlc, int output, gchar * file) +{ + return gmyth_vlc_setup_output(vlc, output, "input", file); +} + + +/** Function to create a channel in vlc + * + * @param vlc structure with options for vlc + * @param type the type of channel (broadcast, vod...) + * @param port + * @return 0 if success + */ +int +gmyth_vlc_create_channel(GMythVlc * vlc, gchar * type, int port, + int vcodec) +{ + int ret; + size_t size = 40; + gchar *msg = (gchar *) g_malloc0(sizeof(gchar) * size); + + g_snprintf(msg, size, "new output%d %s enabled loop", vlc->n_outputs, + type); + + ret = _socket_send(vlc->sockfd, msg); + + if (ret > -1) { + gmyth_vlc_setup_output(vlc, vlc->n_outputs, "option", + "sout-keep=1"); + + g_free(msg); + size = 256; + msg = (gchar *) g_malloc0(sizeof(gchar) * size); + + if (vcodec == MPEG1) + // Best transcode option for N800 (MP1V) + g_snprintf(msg, size, "#transcode{vcodec=mp1v,vb=384," + "fps=25.0,scale=1,acodec=mpga," + "ab=64,channels=1}:duplicate{dst=" + "std{access=http,mux=mpeg1,dst=" ":%d}}", port); + else + // Best transcode option for N800 (THEORA) + g_snprintf(msg, size, "#transcode{vcodec=theo,vb=384," + "fps=25.0,scale=1,acodec=vorb," + "ab=64,channels=1}:duplicate{dst=" + "std{access=http,mux=ogg,dst=" ":%d}}", port); + + ret = gmyth_vlc_setup_output(vlc, vlc->n_outputs, "output", msg); + + vlc->n_outputs++; + } + + g_free(msg); + + return ret; +} + + +/** Function to connect to vlc on the backend + * + * @param vlc structure with options for vlc + * @param backend_info infos about the backend + * @param passwd the password for telnet interface + * @return 0 if success + */ +int +gmyth_vlc_connect(GMythVlc * vlc, GMythBackendInfo * backend_info, + gchar * passwd, int port) +{ + int numbytes; + + if ((vlc->he = gethostbyname(backend_info->hostname)) == NULL) { + herror("GMyth_VLC: gethostbyname error"); + return -1; + } + + if ((vlc->sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { + perror("GMyth_VLC: socket error"); + return -1; + } + // Socket properties + vlc->their_addr.sin_family = AF_INET; + vlc->their_addr.sin_port = htons(port); + vlc->their_addr.sin_addr = *((struct in_addr *) vlc->he->h_addr); + memset(&(vlc->their_addr.sin_zero), '\0', 8); + + if (connect(vlc->sockfd, (struct sockaddr *) &(vlc->their_addr), + sizeof(struct sockaddr)) == -1) { + perror("GMyth_VLC: connect error. Check VLC's telnet interface"); + return -1; + } + // Receive the Password's Prompt + numbytes = _socket_recv(vlc->sockfd, vlc->buf); + + // Send the Password. We don't have to + // care about passwords being sent in plain text + // because telnet protocol does it. + _socket_send(vlc->sockfd, passwd); + + // Receive the Welcome msg + numbytes = _socket_recv(vlc->sockfd, vlc->buf); + if (numbytes > -1) + if (strncmp(vlc->buf, "\r\nWrong password.", 17) == 0) { + perror("Gmyth_VLC: passwd error. Check your passwd"); + return -2; + } + + + return 0; +} + + +/** Function to disconnect from vlc + * + * @param vlc structure with options for vlc + * @param backend_info infos about the backend + * @return 0 if success + */ +int +gmyth_vlc_disconnect(GMythVlc * vlc) +{ + + int ret; + + ret = gmyth_vlc_clean_playlist(vlc); + + if (ret > -1) { + vlc->n_outputs = 0; + vlc->n_inputs = 0; + } + + return close(vlc->sockfd); +} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gmyth_vlc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gmyth_vlc.h Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,96 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_vlc.h + * + * @brief

GMythVLC library provides functions that + * interact with a VLC server running telnet interface. + * + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. + * @author Artur Duque de Souza + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __GMYTH_VLC_H__ +#define __GMYTH_VLC_H__ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "gmyth_backendinfo.h" +#include "gmyth_util.h" + +G_BEGIN_DECLS +#define VLC_TELNET_PORT 4212 +#define BUFFER 512 +#define MPEG1 0 +#define THEORA 1 +typedef struct _GMythVlc GMythVlc; + +struct _GMythVlc { + int sockfd; + + // Number of outputs used + int n_outputs; + + // Number of inputs + int n_inputs; + + // Socket vars + struct hostent *he; + struct sockaddr_in their_addr; + + char buf[BUFFER]; +}; + + + +int gmyth_vlc_setup_output(GMythVlc * vlc, int output, + gchar * kind, gchar * opts); + + +int gmyth_vlc_clean_playlist(GMythVlc * vlc); + + +int gmyth_vlc_control_input(GMythVlc * vlc, int output, + gchar * command); + +int gmyth_vlc_create_input(GMythVlc * vlc, int output, + gchar * file); + +int gmyth_vlc_create_channel(GMythVlc * vlc, gchar * type, + int port, int vcodec); + +int gmyth_vlc_connect(GMythVlc * vlc, + GMythBackendInfo * backend_info, + gchar * passwd, int port); + +int gmyth_vlc_disconnect(GMythVlc * vlc); + +G_END_DECLS +#endif /* __GMYTH_VLC_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/gmyth/gst-indent.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/gmyth/gst-indent.sh Mon Feb 25 17:51:43 2008 +0000 @@ -0,0 +1,16 @@ +#!/bin/sh +indent \ + --braces-on-if-line \ + --blank-lines-after-declarations \ + --case-brace-indentation0 \ + --case-indentation4 \ + --braces-after-struct-decl-line \ + --line-length80 \ + --no-tabs \ + --cuddle-else \ + --dont-line-up-parentheses \ + --continuation-indentation4 \ + --honour-newlines \ + --tab-size4 \ + --indent-level4 \ + $* diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/samples/Makefile.am --- a/gmyth/samples/Makefile.am Mon Feb 25 17:45:36 2008 +0000 +++ b/gmyth/samples/Makefile.am Mon Feb 25 17:51:43 2008 +0000 @@ -7,7 +7,7 @@ gmyth_ls.c LDADD = \ - $(top_builddir)/src/libgmyth.la + $(top_builddir)/gmyth/libgmyth.la AM_CFLAGS = -g @@ -16,6 +16,6 @@ INCLUDES = \ -I$(top_srcdir) \ - -I$(top_srcdir)/src \ + -I$(top_srcdir)/gmyth \ $(GLIB_CFLAGS) \ $(GOBJECT_CFLAGS) diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/Makefile.am --- a/gmyth/src/Makefile.am Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -lib_LTLIBRARIES = libgmyth.la - -INCLUDES = -I$(top_srcdir)/src -I$(top_builddir)/src @GLIB_CFLAGS@ @GOBJECT_CFLAGS@ - -BUILT_SOURCES = \ - gmyth_marshal.c \ - gmyth_marshal.h - -libgmyth_la_SOURCES = \ - gmyth_common.c \ - gmyth_debug.c \ - gmyth_epg.c \ - gmyth_recorder.c \ - gmyth_remote_util.c \ - gmyth_tvchain.c \ - gmyth_scheduler.c \ - gmyth_util.c \ - gmyth_query.c \ - gmyth_socket.c \ - gmyth_stringlist.c \ - gmyth_monitor_handler.c \ - gmyth_file_transfer.c \ - gmyth_livetv.c \ - gmyth_backendinfo.c \ - gmyth_programinfo.c \ - gmyth_uri.c \ - gmyth_http.c \ - gmyth_vlc.c \ - gmyth_jobqueue.c \ - gmyth_transcoder.c \ - gmyth_recprofile.c \ - gmyth_file.c \ - gmyth_file_local.c \ - $(BUILT_SOURCES) - -EXTRA_libgmyth_la_SOURCES = gmyth_marshal.list - -gmyth_marshal.h: gmyth_marshal.list - glib-genmarshal --header --prefix=gmyth_marshal gmyth_marshal.list > gmyth_marshal.h.tmp - mv gmyth_marshal.h.tmp gmyth_marshal.h - -gmyth_marshal.c: gmyth_marshal.list gmyth_marshal.h - echo "#include \"glib-object.h\"" > gmyth_marshal.c.tmp - echo "#include \"gmyth_marshal.h\"" >> gmyth_marshal.c.tmp - glib-genmarshal --body --prefix=gmyth_marshal $(srcdir)/gmyth_marshal.list >> gmyth_marshal.c.tmp - mv gmyth_marshal.c.tmp gmyth_marshal.c - -libgmyth_la_CFLAGS = \ - -DDATADIR=\"$(pkgdatadir)\" \ - $(GLIB_CFLAGS) \ - $(GOBJECT_CFLAGS) \ - $(GST_CFLAGS) \ - $(GSTBASE_CFLAGS) \ - $(GSTPLUGINSBASE_CFLAGS) \ - $(MYSQL_CFLAGS) \ - $(LIBXML_CFLAGS) - -libgmyth_la_LDFLAGS = \ - -export-dynamic \ - $(GLIB_CFLAGS) \ - $(GOBJECT_CFLAGS) \ - $(MYSQL_LIBS) \ - $(GST_LIBS) \ - $(GSTBASE_LIBS) \ - $(GSTPLUGINS_LIBS) \ - $(LIBXML_LIBS) - -libgmyth_includedir = \ - $(pkgincludedir) - -libgmyth_include_HEADERS = \ - gmyth.h \ - gmyth_common.h \ - gmyth_debug.h \ - gmyth_epg.h \ - gmyth_recorder.h \ - gmyth_scheduler.h \ - gmyth_tvchain.h \ - gmyth_util.h \ - gmyth_query.h \ - gmyth_socket.h \ - gmyth_remote_util.h \ - gmyth_stringlist.h \ - gmyth_monitor_handler.h \ - gmyth_file_transfer.h \ - gmyth_livetv.h \ - gmyth_backendinfo.h \ - gmyth_programinfo.h \ - gmyth_uri.h \ - gmyth_http.h \ - gmyth_vlc.h \ - gmyth_jobqueue.h \ - gmyth_transcoder.h \ - gmyth_recprofile.h \ - gmyth_file.h \ - gmyth_file_local.h - -CLEANFILES = $(BUILT_SOURCES) diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth-indent.sh --- a/gmyth/src/gmyth-indent.sh Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -#!/bin/sh -indent \ - -gnu \ - -i4 \ - -l80 \ - -bfda \ - -nut \ - -pcs \ - -psl \ - -bli0 \ - -cs \ - -cli0 \ - -nbfda \ - -sai \ - -saw \ - -saf \ - -sbi4 \ - -npro \ - -nfca \ - -nsc \ - -ts4 \ - -prs \ - -bap \ - $* - diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth.h --- a/gmyth/src/gmyth.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth.h - * - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Renato Filho - * - *//* - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - - -#ifndef _GMYTH_H_ -#define _GMYTH_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif /* _GMYTH_H_ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_backendinfo.c --- a/gmyth/src/gmyth_backendinfo.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,395 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_backend_info.c - * - * @brief

This component represents all the MythTV backend server - * configuration information. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Hallyson Melo - * @author Rosfran Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gmyth_backendinfo.h" -#include "gmyth_uri.h" -#include "gmyth_debug.h" - -static void gmyth_backend_info_class_init(GMythBackendInfoClass * - klass); -static void gmyth_backend_info_init(GMythBackendInfo * object); - -static void gmyth_backend_info_dispose(GObject * object); -static void gmyth_backend_info_finalize(GObject * object); - -G_DEFINE_TYPE(GMythBackendInfo, gmyth_backend_info, G_TYPE_OBJECT); -static void gmyth_backend_info_class_init(GMythBackendInfoClass * - klass) -{ - GObjectClass *gobject_class; - - gobject_class = (GObjectClass *) klass; - - gobject_class->dispose = gmyth_backend_info_dispose; - gobject_class->finalize = gmyth_backend_info_finalize; -} - -static void -gmyth_backend_info_init(GMythBackendInfo * backend_info) -{ - backend_info->hostname = NULL; - backend_info->port = -1; - backend_info->username = NULL; - backend_info->password = NULL; - backend_info->db_name = NULL; - backend_info->db_port = 0; - backend_info->status_port = -1; -} - -static void -gmyth_backend_info_dispose(GObject * object) -{ - GMythBackendInfo *backend_info = GMYTH_BACKEND_INFO(object); - - g_free(backend_info->hostname); - g_free(backend_info->username); - g_free(backend_info->password); - g_free(backend_info->db_name); - - if (backend_info->sock) - g_object_unref (backend_info->sock); - - backend_info->hostname = NULL; - backend_info->port = -1; - backend_info->username = NULL; - backend_info->password = NULL; - backend_info->db_name = NULL; - backend_info->db_port = 0; - backend_info->status_port = -1; - backend_info->sock = NULL; - - G_OBJECT_CLASS(gmyth_backend_info_parent_class)->dispose(object); -} - -static void -gmyth_backend_info_finalize(GObject * object) -{ - g_signal_handlers_destroy(object); - - G_OBJECT_CLASS(gmyth_backend_info_parent_class)->finalize(object); -} - -/** - * Creates a new instance of GMythBackendInfo. - * - * @return a new instance of GMythBackendInfo. - */ -GMythBackendInfo * -gmyth_backend_info_new() -{ - GMythBackendInfo *backend_info = - GMYTH_BACKEND_INFO(g_object_new(GMYTH_BACKEND_INFO_TYPE, NULL)); - - return backend_info; -} - -/** - * Creates a new instance of GMythBackendInfo, based on a given set of - * configuration parameters. - * - * @param hostname The hostname to the MythTV backend server. - * @param username The user name to the MythTV backend MySQL server. - * @param password The password to the user of the MythTV backend MySQL server. - * @param db_name The database name of the MythTV backend, stored on the MySQL server. - * @param port The port number of the MythTV backend server (commonly is 6543). - * - * @return a new instance of GMythBackendInfo. - */ -GMythBackendInfo * -gmyth_backend_info_new_full(const gchar * hostname, const gchar * username, - const gchar * password, const gchar * db_name, - gint port) -{ - GMythBackendInfo *backend_info = - GMYTH_BACKEND_INFO(g_object_new(GMYTH_BACKEND_INFO_TYPE, NULL)); - - gmyth_backend_info_set_hostname(backend_info, hostname); - gmyth_backend_info_set_username(backend_info, username); - gmyth_backend_info_set_password(backend_info, password); - gmyth_backend_info_set_db_name(backend_info, db_name); - gmyth_backend_info_set_port(backend_info, port); - - return backend_info; -} - -/** - * Creates a new instance of GMythBackendInfo, based on the - * MythTV's backend server URI string. - * - * @param uri_str The URI string pointing to the MythTV backend server. - * - * @return a new instance of GMythBackendInfo. - */ -GMythBackendInfo * -gmyth_backend_info_new_with_uri(const gchar * uri_str) -{ - GMythBackendInfo *backend_info; - GMythURI *uri; - gchar **path_parts; - gchar *db; - - backend_info = GMYTH_BACKEND_INFO(g_object_new(GMYTH_BACKEND_INFO_TYPE, NULL)); - uri = gmyth_uri_new_with_value (uri_str); - path_parts = g_strsplit(gmyth_uri_get_path(uri), "&", -1); - gmyth_backend_info_set_hostname(backend_info, gmyth_uri_get_host(uri)); - gmyth_backend_info_set_username(backend_info, gmyth_uri_get_user(uri)); - gmyth_backend_info_set_password(backend_info, - gmyth_uri_get_password(uri)); - - /* - * gets the path info to database name, from the URI, and removes the - * trash chars - */ - if ((path_parts != NULL) && (strlen (path_parts[0]) > 0)) - { - db = path_parts[0]+2; - } - else - { - db = gmyth_uri_get_path(uri); - } - - gmyth_backend_info_set_db_name(backend_info, db); - - gmyth_backend_info_set_port(backend_info, gmyth_uri_get_port(uri)); - - g_object_unref(uri); - g_strfreev(path_parts); - - return backend_info; -} - -void -gmyth_backend_info_set_hostname(GMythBackendInfo * backend_info, - const gchar * hostname) -{ - g_return_if_fail(backend_info != NULL); - - if (NULL == hostname || strlen(hostname) <= 0) { - gmyth_debug("Error trying to set a hostname equals to NULL."); - } else { - backend_info->hostname = g_strdup(hostname); - } -} - -void -gmyth_backend_info_set_username(GMythBackendInfo * backend_info, - const gchar * username) -{ - g_return_if_fail(backend_info != NULL); - - backend_info->username = g_strdup(username); -} - -void -gmyth_backend_info_set_password(GMythBackendInfo * backend_info, - const gchar * password) -{ - g_return_if_fail(backend_info != NULL); - - backend_info->password = g_strdup(password); -} - -void -gmyth_backend_info_set_db_name(GMythBackendInfo * backend_info, - const gchar * db_name) -{ - g_return_if_fail(backend_info != NULL); - - backend_info->db_name = g_strdup(db_name); -} - -void -gmyth_backend_info_set_db_port(GMythBackendInfo * backend_info, gint db_port) -{ - g_return_if_fail(backend_info != NULL); - - if (db_port <= 0) { - gmyth_debug("Error trying to set a port less than 0."); - } else { - backend_info->db_port = db_port; - } -} - -void -gmyth_backend_info_set_port(GMythBackendInfo * backend_info, gint port) -{ - g_return_if_fail(backend_info != NULL); - - if (port <= 0) { - gmyth_debug("Error trying to set a port less than 0."); - } else { - backend_info->port = port; - } -} - -void -gmyth_backend_info_set_status_port(GMythBackendInfo * backend_info, - gint port) -{ - g_return_if_fail(backend_info != NULL); - - if (port <= 0) { - gmyth_debug - ("Error trying to set the status port to less than zero."); - } else { - backend_info->status_port = port; - } -} - -const gchar * -gmyth_backend_info_get_hostname(GMythBackendInfo * backend_info) -{ - g_return_val_if_fail(backend_info != NULL, NULL); - - return backend_info->hostname; -} - -const gchar * -gmyth_backend_info_get_username(GMythBackendInfo * backend_info) -{ - g_return_val_if_fail(backend_info != NULL, NULL); - - return backend_info->username; -} - -const gchar * -gmyth_backend_info_get_password(GMythBackendInfo * backend_info) -{ - g_return_val_if_fail(backend_info != NULL, NULL); - - return backend_info->password; -} - -const gchar * -gmyth_backend_info_get_db_name(GMythBackendInfo * backend_info) -{ - g_return_val_if_fail(backend_info != NULL, NULL); - - return backend_info->db_name; -} - -gint -gmyth_backend_info_get_idb_port(GMythBackendInfo * backend_info) -{ - g_return_val_if_fail(backend_info != NULL, -1); - - return backend_info->db_port; -} - - -gint -gmyth_backend_info_get_port(GMythBackendInfo * backend_info) -{ - g_return_val_if_fail(backend_info != NULL, -1); - - return backend_info->port; -} - -/** - * Creates a new instance of GMythURI, based on the GMythBackendInfo instance to the - * MythTV's backend server. - * - * @param backend_info The GMythBackendInfo instance. - * - * @return an instance of GMythURI, created from a GMythBackendInfo. - */ -GMythURI * -gmyth_backend_info_get_uri(GMythBackendInfo * backend_info) -{ - GMythURI *uri = NULL; - gchar *uri_str = NULL; - gchar *user_info = NULL; - gchar *db_data = NULL; - - if ((backend_info->username != NULL - && strlen(backend_info->username) > 0)) - user_info = - g_strdup_printf("%s:%s@", backend_info->username, - backend_info->password); - - if (backend_info->db_name != NULL && strlen(backend_info->db_name) > 0) { - if ((g_strrstr(backend_info->db_name, "_") != NULL)) - db_data = g_strdup(backend_info->db_name); - else - db_data = g_strdup_printf("?%s&", backend_info->db_name); - } - // else if ( ( ( g_strrstr( backend_info->path, "livetv" ) != NULL ) - // || - // ( g_strrstr( backend_info->path, "/?" ) != NULL ) ) - - uri_str = g_strdup_printf("myth://%s%s:%d/%s", user_info != NULL - && strlen(user_info) > 0 ? user_info : "", - backend_info->hostname, backend_info->port, - db_data != NULL - && strlen(db_data) > 0 ? db_data : ""); - uri = gmyth_uri_new_with_value(uri_str); - - if (user_info != NULL) - g_free(user_info); - - if (db_data != NULL) - g_free(db_data); - - g_free(uri_str); - - return uri; -} - -gboolean -gmyth_backend_info_is_local_file(GMythBackendInfo * backend_info) -{ - g_return_val_if_fail(backend_info != NULL, FALSE); - - return - gmyth_uri_is_local_file(gmyth_backend_info_get_uri(backend_info)); -} - -GMythSocket* -gmyth_backend_info_get_connected_socket (GMythBackendInfo *backend_info) -{ - if (backend_info->sock == NULL) { - gboolean res; - backend_info->sock = gmyth_socket_new (); - res = gmyth_socket_connect_to_backend (backend_info->sock, - backend_info->hostname, - backend_info->port, - TRUE); - if (res == FALSE) { - g_object_unref (backend_info->sock); - backend_info->sock = NULL; - return NULL; - } - } - - return g_object_ref (backend_info->sock); -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_backendinfo.h --- a/gmyth/src/gmyth_backendinfo.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,121 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_backend_info.h - * - * @brief

This component represents all the MythTV backend server - * configuration information. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Hallyson Melo - * @author Rosfran Borges - * -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __GMYTH_BACKEND_INFO_H__ -#define __GMYTH_BACKEND_INFO_H__ - -#include - -#include "gmyth_uri.h" -#include "gmyth_socket.h" - -G_BEGIN_DECLS -#define GMYTH_BACKEND_INFO_TYPE \ - (gmyth_backend_info_get_type ()) -#define GMYTH_BACKEND_INFO(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_BACKEND_INFO_TYPE, GMythBackendInfo)) -#define GMYTH_BACKEND_INFO_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_BACKEND_INFO_TYPE, GMythBackendInfoClass)) -#define IS_GMYTH_BACKEND_INFO(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_BACKEND_INFO_TYPE)) -#define IS_GMYTH_BACKEND_INFO_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_BACKEND_INFO_TYPE)) -#define GMYTH_BACKEND_INFO_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_BACKEND_INFO_TYPE, GMythBackendInfoClass)) - -typedef struct _GMythBackendInfo GMythBackendInfo; -typedef struct _GMythBackendInfoClass GMythBackendInfoClass; - -struct _GMythBackendInfoClass { - GObjectClass parent_class; - - /* - * callbacks - */ - /* - * no one for now - */ -}; - -struct _GMythBackendInfo { - GObject parent; - /** The backend hostname or ip address. */ - gchar *hostname; - /** The backend port. */ - gint port; - /** The username to connect to the mysql server. */ - gchar *username; - /** The password to connect to the mysql server. */ - gchar *password; - /** The mythtv's mysql database name. */ - gchar *db_name; - /** The mysql database port */ - gint db_port; - /** The backend status port for http connection */ - gint status_port; - - /* Private */ - GMythSocket *sock; -}; - - -GType gmyth_backend_info_get_type (void) G_GNUC_CONST; -GMythBackendInfo* gmyth_backend_info_new (void); -GMythBackendInfo* gmyth_backend_info_new_full (const gchar *hostname, - const gchar *username, - const gchar *password, - const gchar *db_name, - gint port); -GMythBackendInfo* gmyth_backend_info_new_with_uri (const gchar *uri_str); -void gmyth_backend_info_set_hostname (GMythBackendInfo *backend_info, - const gchar *hostname); -void gmyth_backend_info_set_username (GMythBackendInfo *backend_info, - const gchar *username); -void gmyth_backend_info_set_password (GMythBackendInfo *backend_info, - const gchar *password); -void gmyth_backend_info_set_db_name (GMythBackendInfo *backend_info, - const gchar *db_name); -void gmyth_backend_info_set_db_port (GMythBackendInfo *backend_info, - gint db_port); -void gmyth_backend_info_set_port (GMythBackendInfo *backend_info, - gint port); -void gmyth_backend_info_set_status_port (GMythBackendInfo *backend_info, - gint port); -const gchar* gmyth_backend_info_get_hostname (GMythBackendInfo *backend_info); -const gchar* gmyth_backend_info_get_username (GMythBackendInfo *backend_info); -const gchar* gmyth_backend_info_get_password (GMythBackendInfo *backend_info); -const gchar* gmyth_backend_info_get_db_name (GMythBackendInfo *backend_info); -gint gmyth_backend_info_get_db_port (GMythBackendInfo *backend_info); -gint gmyth_backend_info_get_port (GMythBackendInfo *backend_info); -GMythURI* gmyth_backend_info_get_uri (GMythBackendInfo *backend_info); -gboolean gmyth_backend_info_is_local_file (GMythBackendInfo *backend_info); -GMythSocket* gmyth_backend_info_get_connected_socket - (GMythBackendInfo *backend_info); - -G_END_DECLS -#endif /* __GMYTH_BACKEND_INFO_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_common.c --- a/gmyth/src/gmyth_common.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_common.c - * - * @brief

This file contains basic common functions for the gmyth library. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Leonardo Sobral Cunha - * @author Rosfran Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gmyth_common.h" -#include "gmyth_debug.h" -#include "gmyth_util.h" - -static void free_channel_data(gpointer data, gpointer user_data); -static void free_program_data(gpointer data, gpointer user_data); - -/** -* Frees the memory allocated to the GMythChannelInfo objects inside list. -* The list memory is also released by g_list_free(). If LIST is NULL it -* simply returns. -* -* @param list the GList containing a list of GMythChannelInfo to free. -*/ -void -gmyth_free_channel_list(GList * list) -{ - g_return_if_fail(list != NULL); - - g_list_foreach(list, free_channel_data, NULL); - g_list_free(list); -} - -/** - * Frees the memory allocated to the GMythProgramInfo objects inside list. - * The list memory is also released by g_list_free(). If list is NULL it - * simply returns. - * - * @param list the GList containing a list of GMythProgramInfo to free. - */ -void -gmyth_free_program_list(GList * list) -{ - g_return_if_fail(list != NULL); - - g_list_foreach(list, free_program_data, NULL); - g_list_free(list); -} - -void -gmyth_channel_info_free(GMythChannelInfo * channel) -{ - g_return_if_fail(channel != NULL); - - if (channel->channel_num) - g_string_free(channel->channel_num, TRUE); - - if (channel->channel_name) - g_string_free(channel->channel_name, TRUE); - - if (channel->channel_icon) - g_string_free(channel->channel_icon, TRUE); - - g_free(channel); -} - -/** - * Prints the channel info to the standard output. The gmyth debug must be enabled. - * @param channel_info the GMythChannelInfo instance - */ -void -gmyth_channel_info_print(GMythChannelInfo * channel_info) -{ -#ifdef GMYTH_USE_DEBUG - if (channel_info != NULL) { - g_return_if_fail(channel_info->channel_name != NULL); - g_return_if_fail(channel_info->channel_num != NULL); - - gmyth_debug("ChannelInfo (Name, Num, ID) = (%s, %s, %d)", - channel_info->channel_name->str, - channel_info->channel_num->str, - channel_info->channel_ID); - - } -#endif -} - -/** - * Prints the program info to the standard output. The gmyth debug must be enabled. - * @param channel_info the GMythProgramInfo instance - */ -void -gmyth_program_info_print(GMythProgramInfo * program_info) -{ -#ifdef GMYTH_USE_DEBUG - g_return_if_fail(program_info); - - gmyth_debug("ProgramInfo\n\tTitle = %s\n\t" - "Description = %s\n\t" - "Start time= %s\t" - "End time = %s\n" - "Path name = %s\n" - "File size = %lld\n", - program_info->title ? program_info->title->str : "NULL", - program_info->description ? program_info->description-> - str : "NULL", - gmyth_util_time_to_string_from_time_val(program_info-> - startts), - gmyth_util_time_to_string_from_time_val(program_info-> - endts), - program_info->pathname ? program_info->pathname-> - str : "NULL", program_info->filesize); -#endif -} - -static void -free_channel_data(gpointer data, gpointer user_data) -{ - /* - * Frees the GMythChannelInfo structure - */ - GMythChannelInfo *channel = (GMythChannelInfo *) data; - - gmyth_channel_info_free(channel); -} - -static void -free_program_data(gpointer data, gpointer user_data) -{ - g_return_if_fail(data != NULL); - - g_object_unref((GMythProgramInfo *) data); -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_common.h --- a/gmyth/src/gmyth_common.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_common.h - * - * @brief

This file contains basic common functions for the gmyth library. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Leonardo Sobral Cunha - * @author Rosfran Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GMYTH_COMMON_H_ -#define GMYTH_COMMON_H_ - -#include -#include - -#include "gmyth_programinfo.h" - -G_BEGIN_DECLS - /** - * The GMythChannelInfo structure represents the channel information - * stored in the backend database. - */ - typedef struct { - /** The channel ID in backend database */ - gint channel_ID; - - /** The channel number */ - GString *channel_num; - - /** The channel name in backend database */ - GString *channel_name; - - /** The channel icon path in the backend database */ - GString *channel_icon; -} GMythChannelInfo; - -void gmyth_free_channel_list (GList *list); -void gmyth_free_program_list (GList *list); -void gmyth_channel_info_free (GMythChannelInfo *channel_info); -void gmyth_channel_info_print (GMythChannelInfo *channel_info); -void gmyth_program_info_print (GMythProgramInfo *program_info); - -G_END_DECLS -#endif /* GMYTH_COMMON_H_ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_debug.c --- a/gmyth/src/gmyth_debug.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_debug.c - * - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Renato Filho - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gmyth_debug.h" - -void -gmyth_debug_real(const char *func, - const char *file, const int line, gboolean newline, - const char *format, ...) -{ - va_list args; - char buffer[1025]; - char str_time[255]; - time_t the_time; - - va_start(args, format); - - g_vsnprintf(buffer, 1024, format, args); - - va_end(args); - - time(&the_time); - strftime(str_time, 254, "%H:%M:%S", localtime(&the_time)); - - g_printerr(newline ? "(%s) [%p] [%s] %s:%d: %s\n" : - "(%s) [%p] [%s] %s:%d: %s", str_time, g_thread_self(), func, - file, line, buffer); -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_debug.h --- a/gmyth/src/gmyth_debug.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_debug.h - * - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Renato Filho - * -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __GMYTH_DEBUG_H__ -#define __GMYTH_DEBUG_H__ - -#include -#include -#include - -G_BEGIN_DECLS -#ifdef GMYTH_USE_DEBUG -#define gmyth_debug(...) gmyth_debug_real (__FUNCTION__, __FILE__, __LINE__, TRUE, __VA_ARGS__) -#else -#define gmyth_debug(...) -#endif - void -gmyth_debug_real(const char *func, - const char *file, int line, gboolean newline, - const char *format, ...) -G_GNUC_PRINTF(5, 6); - -G_END_DECLS -#endif diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_epg.c --- a/gmyth/src/gmyth_epg.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,446 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_epg.c - * - * @brief

GMythEPG class provides access to the program and channel data - * from the Electronic Program Guide (EPG) of the Mythtv backend. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Leonardo Sobral Cunha - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include - -#include "gmyth_epg.h" -#include "gmyth_programinfo.h" -#include "gmyth_util.h" -#include "gmyth_file_transfer.h" -#include "gmyth_debug.h" - -#define CONNECT_TIMEOUT 6 - -static void gmyth_epg_class_init(GMythEPGClass * klass); -static void gmyth_epg_init(GMythEPG * object); - -static void gmyth_epg_dispose(GObject * object); -static void gmyth_epg_finalize(GObject * object); - -G_DEFINE_TYPE(GMythEPG, gmyth_epg, G_TYPE_OBJECT) - static void gmyth_epg_class_init(GMythEPGClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->dispose = gmyth_epg_dispose; - gobject_class->finalize = gmyth_epg_finalize; -} - -static void -gmyth_epg_init(GMythEPG * gmyth_epg) -{ - -} - -static void -gmyth_epg_dispose(GObject * object) -{ - GMythEPG *gmyth_epg = GMYTH_EPG(object); - - if (gmyth_epg->sqlquery != NULL) { - g_object_unref(gmyth_epg->sqlquery); - gmyth_epg->sqlquery = NULL; - } - - G_OBJECT_CLASS(gmyth_epg_parent_class)->dispose(object); -} - -static void -gmyth_epg_finalize(GObject * object) -{ - g_signal_handlers_destroy(object); - - G_OBJECT_CLASS(gmyth_epg_parent_class)->finalize(object); -} - -/** - * Creates a new instance of GMythEPG. - * - * @return a new instance of GMythEPG. - */ -GMythEPG * -gmyth_epg_new(void) -{ - GMythEPG *epg = GMYTH_EPG(g_object_new(GMYTH_EPG_TYPE, NULL)); - - return epg; -} - -/** Connects to the Mysql database in the backend. The backend address - * is loaded from the GMythSettings instance. - * - * @param gmyth_epg the GMythEPG instance to be connected. - * @return true if connection was success, false if failed. - */ -gboolean -gmyth_epg_connect(GMythEPG * gmyth_epg, GMythBackendInfo * backend_info) -{ - g_return_val_if_fail(gmyth_epg != NULL, FALSE); - - if (gmyth_epg->sqlquery == NULL) { - gmyth_debug("[%s] Creating gmyth_query", __FUNCTION__); - gmyth_epg->sqlquery = gmyth_query_new(); - } - - if (!gmyth_query_connect_with_timeout(gmyth_epg->sqlquery, - backend_info, CONNECT_TIMEOUT)) { - gmyth_debug("[%s] Error while connecting to db", __FUNCTION__); - return FALSE; - } - - gmyth_epg->backend_info = backend_info; - g_object_ref(backend_info); - - return TRUE; -} - -/** Disconnects from the Mysql database in the backend. - * - * @param gmyth_epg the GMythEPG instance to be disconnected - * @return true if disconnection was success, false if failed. - */ -gboolean -gmyth_epg_disconnect(GMythEPG * gmyth_epg) -{ - g_return_val_if_fail(gmyth_epg != NULL, FALSE); - - if (gmyth_epg->sqlquery != NULL) { - gmyth_query_disconnect(gmyth_epg->sqlquery); - g_object_unref(gmyth_epg->sqlquery); - gmyth_epg->sqlquery = NULL; - } - - if (gmyth_epg->backend_info != NULL) { - g_object_unref(gmyth_epg->backend_info); - gmyth_epg->backend_info = NULL; - } - - return TRUE; -} - -/** Retrieves the available list of channels from the backend Mysql database. - * - * @param gmyth_epg the GMythEPG instance. - * @param glist_ptr the GSList pointer to be filled with the loaded list address. - * @return The amount of channels retrieved from database, or -1 if error. - */ -gint -gmyth_epg_get_channel_list(GMythEPG * gmyth_epg, GList ** glist_ptr) -{ - MYSQL_RES *msql_res; - - g_return_val_if_fail(gmyth_epg != NULL, -1); - - msql_res = gmyth_query_process_statement(gmyth_epg->sqlquery, - "SELECT chanid, channum, name, icon FROM channel;"); - - (*glist_ptr) = NULL; - - if (msql_res == NULL) { - gmyth_debug("[%s] msql query returned NULL MYSQL_RES", - __FUNCTION__); - return -1; - } else { - MYSQL_ROW row; - GMythChannelInfo *channel_info; - - while ((row = mysql_fetch_row(msql_res)) != NULL) { - - channel_info = g_new0(GMythChannelInfo, 1); - channel_info->channel_ID = - (gint) g_ascii_strtoull(row[0], NULL, 10); - channel_info->channel_num = g_string_new(row[1]); - channel_info->channel_name = g_string_new(row[2]); - channel_info->channel_icon = g_string_new(row[3]); -#ifdef GMYTH_USE_DEBUG - gmyth_channel_info_print(channel_info); -#endif - (*glist_ptr) = g_list_append((*glist_ptr), channel_info); - } - } - mysql_free_result(msql_res); - - return (!(*glist_ptr)) ? 0 : g_list_length(*glist_ptr); -} - -GMythChannelInfo * -gmyth_epg_get_channel_info(GMythEPG * gmyth_epg, gint channel_id) -{ - GMythChannelInfo *channel_info = NULL; - MYSQL_RES *msql_res; - gchar *query_str; - - g_return_val_if_fail(gmyth_epg != NULL, NULL); - - query_str = - g_strdup_printf - ("SELECT channum, name, icon FROM channel WHERE chanid=%d;", - channel_id); - msql_res = - gmyth_query_process_statement(gmyth_epg->sqlquery, query_str); - - if (msql_res == NULL) { - gmyth_debug("[%s] msql query returned NULL MYSQL_RES", - __FUNCTION__); - return NULL; - } else { - MYSQL_ROW row; - - if ((row = mysql_fetch_row(msql_res)) != NULL) { - - channel_info = g_new0(GMythChannelInfo, 1); - channel_info->channel_ID = channel_id; - channel_info->channel_num = g_string_new(row[0]); - channel_info->channel_name = g_string_new(row[1]); - channel_info->channel_icon = g_string_new(row[2]); -#ifdef GMYTH_USE_DEBUG - gmyth_channel_info_print(channel_info); -#endif - } - } - mysql_free_result(msql_res); - - return channel_info; -} - -/** - * Retrieves the available list of channels from the backend Mysql database. - * - * @param gmyth_epg the GMythEPG instance. - * @param proglist the GSList pointer to be filled with the loaded list. - * @param chan_num the channel num on which to search for program. - * @param starttime the start time to search for programs. - * @param endtime the end time to search for programs. - * @return The amount of channels retrieved from database, or -1 if error. - */ -gint -gmyth_epg_get_program_list(GMythEPG * gmyth_epg, GList ** proglist, - const gint chan_num, GTimeVal * starttime, - GTimeVal * endtime) -{ - - gchar *startts = - gmyth_util_time_to_string_from_time_val(starttime); - gchar *endts = - gmyth_util_time_to_string_from_time_val(endtime); - MYSQL_ROW row; - GString *querystr; - - assert(gmyth_epg); - - querystr = - g_string_new - ("SELECT DISTINCT program.chanid, program.starttime, program.endtime, " - " program.title, program.subtitle, program.description, " - " program.category, channel.channum, channel.callsign, " - " channel.name, program.previouslyshown, channel.commfree, " - " channel.outputfilters, program.seriesid, program.programid, " - " program.airdate, program.stars, program.originalairdate, " - " program.category_type, record.recordid, " - " oldrecstatus.rectype, oldrecstatus.recstatus, " - " oldrecstatus.findid " - "FROM program " - "LEFT JOIN channel ON program.chanid = channel.chanid " - "LEFT JOIN record ON " - " program.chanid = record.chanid AND " - " DATE (program.starttime) = record.startdate AND " - " TIME (program.starttime) = record.starttime AND " - " DATE (program.endtime) = record.enddate AND " - " TIME (program.endtime) = record.endtime " - "LEFT JOIN oldrecorded AS oldrecstatus ON " - " program.title = oldrecstatus.title AND " - " channel.callsign = oldrecstatus.station AND " - " program.starttime = oldrecstatus.starttime "); - - g_string_append_printf(querystr, - "WHERE program.chanid = %d " - " AND program.endtime >= '%s' " - " AND program.starttime <= '%s' " - " AND program.manualid = 0 ", chan_num, - startts, endts); - - if (!g_strrstr(querystr->str, " GROUP BY ")) - querystr = g_string_append(querystr, - " GROUP BY program.starttime, channel.channum, " - " channel.callsign, program.title "); - - if (!g_strrstr(querystr->str, " LIMIT ")) - querystr = g_string_append(querystr, " LIMIT 1000 "); - - MYSQL_RES *res_set = - gmyth_query_process_statement(gmyth_epg->sqlquery, querystr->str); - - if (res_set == NULL) { - gmyth_debug("[%s] msql query returned NULL MYSQL_RES", - __FUNCTION__); - return -1; - } - - *proglist = NULL; - while ((row = mysql_fetch_row(res_set)) != NULL) { - - GMythProgramInfo *p = gmyth_program_info_new(); - - p->channel_id = (int) g_ascii_strtoull (row[0], NULL, 10); - - p->startts = gmyth_util_string_to_time_val(row[1]); - p->endts = gmyth_util_string_to_time_val(row[2]); - - p->recstartts = g_new0(GTimeVal, 1); - p->recstartts->tv_sec = p->startts->tv_sec; - p->recstartts->tv_usec = p->startts->tv_usec; - - p->recendts = g_new0(GTimeVal, 1); - p->recendts->tv_sec = p->endts->tv_sec; - p->recendts->tv_usec = p->endts->tv_usec; - - p->lastmodified = g_new0(GTimeVal, 1); - p->lastmodified->tv_sec = p->startts->tv_sec; - p->lastmodified->tv_usec = p->startts->tv_usec; - - - p->title = g_string_new(row[3]); - p->subtitle = g_string_new(row[4]); - p->description = g_string_new(row[5]); - p->category = g_string_new(row[6]); - p->chanstr = g_string_new(row[7]); - p->chansign = g_string_new(row[8]); - p->channame = g_string_new(row[9]); - p->repeat = g_ascii_strtoull(row[10], NULL, 10); - p->chancommfree = g_ascii_strtoull(row[11], NULL, 10); - p->chanOutputFilters = g_string_new(row[12]); - p->seriesid = g_string_new(row[13]); - p->program_id = g_string_new(row[14]); - p->year = g_string_new(row[15]); - p->stars = g_ascii_strtod(row[16], NULL); - - if (!row[17] || !strcmp(row[17], "")) { - p->originalAirDate = 0; - p->hasAirDate = FALSE; - } else { - p->originalAirDate = gmyth_util_string_to_time_val(row[17]); - p->hasAirDate = TRUE; - } - - p->catType = g_string_new(row[18]); - if (row[19] != NULL) - p->recordid = g_ascii_strtoull(row[19], NULL, 10); - - *proglist = g_list_append(*proglist, p); - -#ifdef GMYTH_USE_DEBUG - gmyth_program_info_print(p); -#endif - } - - /* - * deallocate - */ - mysql_free_result(res_set); - g_string_free(querystr, TRUE); - - return g_list_length (*proglist); -} - -gboolean -gmyth_epg_channel_has_icon(GMythEPG * gmyth_epg, - GMythChannelInfo * channel_info) -{ - gboolean res = FALSE; - - g_return_val_if_fail(gmyth_epg != NULL, FALSE); - g_return_val_if_fail(channel_info != NULL, FALSE); - - if (channel_info->channel_icon != NULL) { - res = gmyth_util_file_exists(gmyth_epg->backend_info, - channel_info->channel_icon->str); - } - - return res; - -} - -/** - * - * @param data the data pointer to be filled with icon binary data. It must be freed by the calling function. - * @return TRUE if success, FALSE if any error happens. - */ -gboolean -gmyth_epg_channel_get_icon(GMythEPG * gmyth_epg, - GMythChannelInfo * channel_info, guint8 ** data, - guint * length) -{ - gboolean res = FALSE; - - g_return_val_if_fail(gmyth_epg != NULL, FALSE); - g_return_val_if_fail(channel_info != NULL, FALSE); - - if (gmyth_epg_channel_has_icon(gmyth_epg, channel_info)) { - GMythFileTransfer *transfer = - gmyth_file_transfer_new(gmyth_epg->backend_info); - - GMythFileReadResult gmyth_res; - GByteArray *icon_data; - guint64 icon_length = 0; - - res = gmyth_file_transfer_open(transfer, - channel_info->channel_icon->str); - if (!res) { - gmyth_debug("Channel icon could not be opened"); - return FALSE; - } - - icon_length = gmyth_file_transfer_get_filesize(transfer); - if (icon_length <= 0) { - gmyth_debug("Channel icon file size is zero or negative"); - return FALSE; - } - - icon_data = g_byte_array_new(); - gmyth_res = gmyth_file_transfer_read(transfer, - icon_data, - icon_length, FALSE); - if (gmyth_res == GMYTH_FILE_READ_EOF) { - *length = icon_length; - *data = icon_data->data; - g_byte_array_free(icon_data, FALSE); - res = TRUE; - } else { - *length = 0; - *data = NULL; - g_byte_array_free(icon_data, TRUE); - } - } - - return res; -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_epg.h --- a/gmyth/src/gmyth_epg.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_epg.h - * - * @brief

GMythEPG class provides access to the program and channel data - * from the Electronic Program Guide (EPG) of the Mythtv backend. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Leonardo Sobral Cunha - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GMYTH_EPG_H_ -#define GMYTH_EPG_H_ - -#include - -#include "gmyth_query.h" -#include "gmyth_common.h" - -G_BEGIN_DECLS -#define GMYTH_EPG_TYPE (gmyth_epg_get_type ()) -#define GMYTH_EPG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_EPG_TYPE, GMythEPG)) -#define GMYTH_EPG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_EPG_TYPE, GMythEPGClass)) -#define IS_GMYTH_EPG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_EPG_TYPE)) -#define IS_GMYTH_EPG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_EPG_TYPE)) -#define GMYTH_EPG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_EPG_TYPE, GMythEPGClass)) -typedef struct _GMythEPG GMythEPG; -typedef struct _GMythEPGClass GMythEPGClass; - -struct _GMythEPGClass { - GObjectClass parent_class; - - /* - * callbacks - */ - /* - * no one for now - */ -}; - -struct _GMythEPG { - GObject parent; - - GMythQuery *sqlquery; - GMythBackendInfo *backend_info; -}; - -GType gmyth_epg_get_type (void) G_GNUC_CONST;; -GMythEPG* gmyth_epg_new (void); -gboolean gmyth_epg_connect (GMythEPG *gmyth_epg, - GMythBackendInfo *backend_info); -gboolean gmyth_epg_disconnect (GMythEPG *gmyth_epg); -gint gmyth_epg_get_channel_list (GMythEPG *gmyth_epg, - GList **glist_ptr); -gint gmyth_epg_get_program_list (GMythEPG *gmyth_epg, - GList **proglist, - gint chanNum, - GTimeVal *starttime, - GTimeVal *endtime); -GMythChannelInfo*gmyth_epg_get_channel_info (GMythEPG *gmyth_epg, - gint channel_id); -gboolean gmyth_epg_channel_has_icon (GMythEPG *gmyth_epg, - GMythChannelInfo *channel); -gboolean gmyth_epg_channel_get_icon (GMythEPG *gmyth_epg, - GMythChannelInfo *channel, - guint8 **data, - guint *length); - -G_END_DECLS -#endif /* GMYTH_EPG_H_ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_file.c --- a/gmyth/src/gmyth_file.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,515 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_file.c - * - * @brief

GMythFile deals with the file streaming media remote/local - * transfering to the MythTV frontend. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Rosfran Lins Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gmyth_file.h" -#include "gmyth_recorder.h" -#include "gmyth_util.h" -#include "gmyth_socket.h" -#include "gmyth_stringlist.h" -#include "gmyth_debug.h" -#include "gmyth_uri.h" -#include "gmyth_marshal.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define GMYTH_FILE_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_TYPE, GMythFilePrivate)) - -struct _GMythFilePrivate { - gboolean disposed; - gint64 offset; - guint64 filesize; - - GMythBackendInfo *backend_info; - - /* - * Myth URI structure - */ - gchar *filename; - - gint file_id; -}; - -enum { - PROP_GMYTH_FILE_DUMMY, - PROP_GMYTH_FILE_FILENAME, - PROP_GMYTH_FILE_OFFSET, - PROP_GMYTH_FILE_FILESIZE, - PROP_GMYTH_FILE_BACKEND_INFO, - PROP_GMYTH_FILE_FILEID -}; - -static void gmyth_file_set_property(GObject * object, guint prop_id, - const GValue * value, - GParamSpec * pspec); -static void gmyth_file_get_property(GObject * object, guint prop_id, - GValue * value, - GParamSpec * pspec); - -static void gmyth_file_class_init(GMythFileClass * klass); -static void gmyth_file_init(GMythFile * object); -static void gmyth_file_dispose(GObject * object); -static void gmyth_file_finalize(GObject * object); - -G_DEFINE_TYPE(GMythFile, gmyth_file, G_TYPE_OBJECT) - static void gmyth_file_class_init(GMythFileClass * klass) -{ - GObjectClass *gobject_class; - GMythFileClass *gtransfer_class; - - gobject_class = (GObjectClass *) klass; - gtransfer_class = (GMythFileClass *) gobject_class; - - gobject_class->dispose = gmyth_file_dispose; - gobject_class->finalize = gmyth_file_finalize; - - gobject_class->set_property = gmyth_file_set_property; - gobject_class->get_property = gmyth_file_get_property; - - g_object_class_install_property - (gobject_class, PROP_GMYTH_FILE_FILENAME, - g_param_spec_string("filename", "filename", - "The file name.", - "", - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB | G_PARAM_READABLE | - G_PARAM_WRITABLE)); - - g_object_class_install_property - (gobject_class, PROP_GMYTH_FILE_OFFSET, - g_param_spec_int64("file-offset", "file-offset", - "The offset (position) of this file", 0, - G_MAXINT64, 0, - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB | G_PARAM_READABLE | - G_PARAM_WRITABLE)); - - g_object_class_install_property - (gobject_class, PROP_GMYTH_FILE_FILESIZE, - g_param_spec_uint64("file-size", "file-size", - "The file size in bytes", - 0, G_MAXUINT64, 0, - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB | G_PARAM_READABLE | - G_PARAM_WRITABLE)); - - g_object_class_install_property - (gobject_class, PROP_GMYTH_FILE_BACKEND_INFO, - g_param_spec_object("backend-info", "backend-info", - "The Backend Information about the remote server", - G_TYPE_OBJECT, - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB | G_PARAM_READABLE | - G_PARAM_WRITABLE)); - - g_object_class_install_property - (gobject_class, PROP_GMYTH_FILE_FILEID, - g_param_spec_int("file-id", "file-id", - "The file ID", 0, G_MAXINT, 0, - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | - G_PARAM_STATIC_BLURB | G_PARAM_READABLE | - G_PARAM_WRITABLE)); - - g_type_class_add_private(gobject_class, sizeof(GMythFilePrivate)); - -} - -static void -gmyth_file_init(GMythFile * file) -{ - g_return_if_fail(file != NULL); - - file->priv = GMYTH_FILE_GET_PRIVATE(file); -} - -static void -gmyth_file_dispose(GObject * object) -{ - GMythFilePrivate *priv; - GMythFile *file = GMYTH_FILE(object); - - g_return_if_fail(file != NULL); - - priv = GMYTH_FILE_GET_PRIVATE(file); - - if (priv->disposed) { - /* - * If dispose did already run, return. - */ - return; - } - - /* - * Make sure dispose does not run twice. - */ - priv->disposed = TRUE; - - if (priv->backend_info != NULL) { - g_object_unref(priv->backend_info); - priv->backend_info = NULL; - } - - if (priv->filename != NULL) { - g_free(priv->filename); - priv->filename = NULL; - } - - G_OBJECT_CLASS(gmyth_file_parent_class)->dispose(object); -} - -static void -gmyth_file_finalize(GObject * object) -{ - g_signal_handlers_destroy(object); - - G_OBJECT_CLASS(gmyth_file_parent_class)->finalize(object); -} - -/** - * Creates a new instance of GMythFile. - * - * @param backend_info The BackendInfo instance, with all the MythTV network - * configuration data. - * - * @return a new instance of the File Transfer. - */ -GMythFile * -gmyth_file_new(GMythBackendInfo * backend_info) -{ - GMythFile *file = NULL; - - g_return_val_if_fail(backend_info != NULL, NULL); - - GParameter *__params = g_new0(GParameter, 1); - GParameter *__params_it = __params; - - (__params_it->name = - "backend-info", g_value_init(&__params_it->value, G_TYPE_OBJECT), - g_value_set_object(&__params_it->value, backend_info), __params_it++); - file = - g_object_newv(GMYTH_FILE_TYPE, __params_it - __params, __params); - - return file; -} - -gchar * -gmyth_file_get_file_name(GMythFile * file) -{ - GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(file); - - g_return_val_if_fail(file != NULL, NULL); - - return priv->filename; -} - -void -gmyth_file_set_file_name(GMythFile * file, const gchar * filename) -{ - g_return_if_fail(file != NULL); - g_return_if_fail(filename != NULL); - - gchar *__temp2 = NULL; - const gchar *__temp1 = NULL; - - file->priv->filename = (__temp2 = - (__temp1 = - filename, - (__temp1 == NULL ? NULL : g_strdup(__temp1))), - (file->priv->filename == - NULL ? NULL : (file->priv->filename = - (g_free(file->priv->filename), - NULL))), __temp2); -} - -/** - * Creates a new instance of GMythFile. - * - * @param uri_str The URI poiting to the MythTV backend server. - * - * @return a new instance of the File Transfer. - */ -GMythFile * -gmyth_file_new_with_uri(const gchar * uri_str) -{ - GMythFile *file = GMYTH_FILE(g_object_new(GMYTH_FILE_TYPE, NULL)); - GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(file); - - priv->backend_info = gmyth_backend_info_new_with_uri(uri_str); - return file; -} - -/** - * Open a File Transfer connection in order to get a remote file. - * - * @param file The actual File Transfer instance. - * @param filename The file name of the remote file to be transfered to the client. - * - * @return true, if the connection opening had been done successfully. - */ -gboolean -gmyth_file_setup(GMythFile * file, const gchar * filename) -{ - gboolean ret = TRUE; - GMythFilePrivate *priv; - - g_return_val_if_fail(file != NULL, FALSE); - g_return_val_if_fail(filename != NULL && strlen(filename) > 0, FALSE); - - priv = GMYTH_FILE_GET_PRIVATE(file); - - if (priv->filename != NULL) { - gmyth_file_close(file); - } - - priv->filename = g_strdup(filename); - - return ret; -} - -/** - * Closes a remote File Transfer connection. - * - * @param file The actual File Transfer instance. - */ -void -gmyth_file_close(GMythFile * file) -{ - GMythFilePrivate *priv; - - priv = GMYTH_FILE_GET_PRIVATE(file); - - if (priv->filename) { - g_free(priv->filename); - priv->filename = NULL; - } - -} - -/** - * Gets the actual file size of the binary content. - * - * @param file The actual File Transfer instance. - * - * @return The actual file size in bytes. - */ -guint64 -gmyth_file_get_filesize(GMythFile * file) -{ - GMythFilePrivate *priv; - - g_return_val_if_fail(file != NULL, 0); - - priv = GMYTH_FILE_GET_PRIVATE(file); - return priv->filesize; -} - -/** - * Sets the actual file size. - * - * @param file The actual File Transfer instance. - * @param filesize The actual File Transfer size, in bytes. - */ -void -gmyth_file_set_filesize(GMythFile * file, guint64 filesize) -{ - GMythFilePrivate *priv; - - priv = GMYTH_FILE_GET_PRIVATE(file); - - priv->filesize = filesize; -} - -/** - * Gets the actual offset of the binary content. - * - * @param file The actual File Transfer instance. - * - * @return The actual file offset in bytes. - */ -gint64 -gmyth_file_get_offset(GMythFile * file) -{ - g_return_val_if_fail(file != NULL, 0); - - return file->priv->offset; -} - -/** - * Sets the actual file offset. - * - * @param file The actual File instance. - * @param filesize The actual File offset, in bytes. - */ -void -gmyth_file_set_offset(GMythFile * file, gint64 offset) -{ - GMythFilePrivate *priv; - - priv = GMYTH_FILE_GET_PRIVATE(file); - - priv->offset = offset; -} - -gchar * -gmyth_file_get_uri(GMythFile * file) -{ - GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(file); - gchar *uri = NULL; - - g_return_val_if_fail(file != NULL, NULL); - - if (g_strstr_len(priv->filename, strlen(priv->filename), "://") != - NULL) - uri = g_strdup(priv->filename); - else - uri = - g_strdup_printf("myth://%s:%d/%s", - gmyth_backend_info_get_hostname(priv-> - backend_info), - gmyth_backend_info_get_port(priv-> - backend_info), - priv->filename); - - return uri; -} - -static void -gmyth_file_set_property(GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(GMYTH_FILE(object)); - - switch (prop_id) { - case PROP_GMYTH_FILE_FILENAME: - { - if (!g_value_get_string(value)) { - break; - } - - if (priv->filename != NULL) { - g_free(priv->filename); - priv->filename = NULL; - } - - priv->filename = g_value_dup_string(value); - gmyth_debug("Changed the filename to [%s]!", priv->filename); - break; - } - case PROP_GMYTH_FILE_OFFSET: - { - priv->offset = g_value_get_int64(value); - break; - } - case PROP_GMYTH_FILE_FILESIZE: - { - priv->filesize = g_value_get_uint64(value); - break; - } - case PROP_GMYTH_FILE_BACKEND_INFO: - { - if (!g_value_get_object(value)) { - break; - } - - if (priv->backend_info != NULL) { - g_object_unref(priv->backend_info); - priv->backend_info = NULL; - } - - priv->backend_info = g_value_get_object(value); - gmyth_debug("Changed the backend info to [%s]!", - gmyth_backend_info_get_hostname(priv-> - backend_info)); - break; - } - case PROP_GMYTH_FILE_FILEID: - { - priv->file_id = g_value_get_int(value); - break; - } - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } - -} - -static void -gmyth_file_get_property(GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(GMYTH_FILE(object)); - - switch (prop_id) { - case PROP_GMYTH_FILE_FILENAME: - { - gmyth_debug("Got the filename to [%s]!", priv->filename); - g_value_set_string(value, priv->filename); - break; - } - case PROP_GMYTH_FILE_OFFSET: - { - g_value_set_int64(value, priv->offset); - break; - } - case PROP_GMYTH_FILE_FILESIZE: - { - g_value_set_uint64(value, priv->filesize); - break; - } - case PROP_GMYTH_FILE_BACKEND_INFO: - { - g_value_set_object(value, priv->backend_info); - break; - } - case PROP_GMYTH_FILE_FILEID: - { - g_value_set_int(value, priv->file_id); - break; - } - default: - { - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } - } - -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_file.h --- a/gmyth/src/gmyth_file.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_file.h - * - * @brief

GMythFile is the parent GMObject that deals with the file streaming - * media remote/local transfering to the MythTV frontend. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Rosfran Lins Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __GMYTH_FILE_H__ -#define __GMYTH_FILE_H__ - -#include -#include - -#include "gmyth_uri.h" -#include "gmyth_backendinfo.h" - -#include -#include -#include -#include -#include -#include - -G_BEGIN_DECLS -#define GMYTH_FILE_TYPE (gmyth_file_get_type ()) -#define GMYTH_FILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_FILE_TYPE, GMythFile)) -#define GMYTH_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TYPE, GMythFileClass)) -#define IS_GMYTH_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_FILE_TYPE)) -#define IS_GMYTH_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TYPE)) -#define GMYTH_FILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_FILE_TYPE, GMythFileClass)) - -typedef enum { - GMYTH_FILE_READ_OK = 0, - GMYTH_FILE_READ_NEXT_PROG_CHAIN = 1, - GMYTH_FILE_READ_ERROR = 2, - GMYTH_FILE_READ_EOF = 3 -} GMythFileReadResult; - -typedef struct _GMythFile GMythFile; -typedef struct _GMythFileClass GMythFileClass; -typedef struct _GMythFilePrivate GMythFilePrivate; - -struct _GMythFile { - GObject parent; - GMythFilePrivate *priv; -}; - -struct _GMythFileClass { - GObjectClass parent_class; -}; - -GType gmyth_file_get_type (void); -GMythFile *gmyth_file_new (GMythBackendInfo *backend_info); -gchar *gmyth_file_get_file_name (GMythFile *file); -void gmyth_file_set_file_name (GMythFile *file, - const gchar *filename); -gboolean gmyth_file_setup (GMythFile *file, - const gchar *filename); -void gmyth_file_close (GMythFile *file); -gboolean gmyth_file_is_open (GMythFile *file); -guint64 gmyth_file_get_filesize (GMythFile *file); -void gmyth_file_set_filesize (GMythFile *file, - guint64 filesize); -gint64 gmyth_file_get_offset (GMythFile *file); -void gmyth_file_set_offset (GMythFile *file, - gint64 offset); -gchar *gmyth_file_get_uri (GMythFile *file); - -G_END_DECLS -#endif /* __GMYTH_FILE_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_file_local.c --- a/gmyth/src/gmyth_file_local.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,464 +0,0 @@ -/** - * GMyth Library - * - * @file_local gmyth/gmyth_file_local.c - * - * @brief

GMythFileLocal deals with the file_local streaming media remote/local - * transfering to the MythTV frontend. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Rosfran Lins Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gmyth_file_local.h" -#include "gmyth_recorder.h" -#include "gmyth_util.h" -#include "gmyth_socket.h" -#include "gmyth_stringlist.h" -#include "gmyth_debug.h" -#include "gmyth_uri.h" -#include "gmyth_marshal.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define GMYTH_FILE_LOCAL_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_LOCAL_TYPE, GMythFileLocalPrivate)) - -struct _GMythFileLocalPrivate { - - gboolean disposed; - - GMutex *mutex; - - gint fd; - - GIOChannel *file_io; - -}; - -static void gmyth_file_local_class_init(GMythFileLocalClass * klass); -static void gmyth_file_local_init(GMythFileLocal * object); -static void gmyth_file_local_dispose(GObject * object); -static void gmyth_file_local_finalize(GObject * object); - -static gboolean _control_acquire_context(GMythFileLocal * file_local, - gboolean do_wait); - -static gboolean _control_release_context(GMythFileLocal * file_local); - -G_DEFINE_TYPE(GMythFileLocal, gmyth_file_local, GMYTH_FILE_TYPE) - static void gmyth_file_local_class_init(GMythFileLocalClass * - klass) -{ - GObjectClass *gobject_class; - GMythFileLocalClass *gtransfer_class; - - gobject_class = (GObjectClass *) klass; - gtransfer_class = (GMythFileLocalClass *) gobject_class; - - gobject_class->dispose = gmyth_file_local_dispose; - gobject_class->finalize = gmyth_file_local_finalize; - - g_type_class_add_private(gobject_class, sizeof(GMythFileLocalPrivate)); - -} - -static void -gmyth_file_local_init(GMythFileLocal * file_local) -{ - GMythFileLocalPrivate *priv; - - g_return_if_fail(file_local != NULL); - - priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local); - - priv->mutex = g_mutex_new(); -} - -static void -gmyth_file_local_dispose(GObject * object) -{ - GMythFileLocalPrivate *priv; - GMythFileLocal *file_local = GMYTH_FILE_LOCAL(object); - - g_return_if_fail(file_local != NULL); - - priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local); - - if (priv->disposed) { - /* - * If dispose did already run, return. - */ - return; - } - - /* - * Make sure dispose does not run twice. - */ - priv->disposed = TRUE; - - if (priv->mutex != NULL) { - g_mutex_free(priv->mutex); - priv->mutex = NULL; - } - - if (priv->file_io != NULL) { - g_io_channel_unref(priv->file_io); - priv->file_io = NULL; - } - - G_OBJECT_CLASS(gmyth_file_local_parent_class)->dispose(object); -} - -static void -gmyth_file_local_finalize(GObject * object) -{ - g_signal_handlers_destroy(object); - - G_OBJECT_CLASS(gmyth_file_local_parent_class)->finalize(object); -} - -/** - * Creates a new instance of GMythFileLocal. - * - * @param backend_info The BackendInfo instance, with all the MythTV network - * configuration data. - * - * @return a new instance of the File Transfer. - */ -GMythFileLocal * -gmyth_file_local_new(GMythBackendInfo * backend_info) -{ - GMythFileLocal *file_local = - GMYTH_FILE_LOCAL(g_object_new(GMYTH_FILE_LOCAL_TYPE, NULL)); - - g_object_set(GMYTH_FILE(file_local), "backend-info", &backend_info, - NULL); - - return file_local; -} - -/** - * Creates a new instance of GMythFileLocal. - * - * @param uri_str The URI poiting to the MythTV backend server. - * - * @return a new instance of the File Transfer. - */ -GMythFileLocal * -gmyth_file_local_new_with_uri(const gchar * uri_str) -{ - GMythFileLocal *file_local = - GMYTH_FILE_LOCAL(g_object_new(GMYTH_FILE_LOCAL_TYPE, NULL)); - GMythURI *uri = gmyth_uri_new_with_value(uri_str); - - gmyth_debug("GMythURI path segment = %s", gmyth_uri_get_path(uri)); - - g_object_set(GMYTH_FILE(file_local), - "backend-info", gmyth_backend_info_new_with_uri(uri_str), - "filename", g_strdup(gmyth_uri_get_path(uri)), NULL); - - g_object_unref(uri); - - return file_local; -} - -gchar * -gmyth_file_local_get_file_name(GMythFileLocal * file_local) -{ - return gmyth_file_get_file_name(GMYTH_FILE(file_local)); -} - -void -gmyth_file_local_set_file_name(GMythFileLocal * file_local, - const gchar * filename) -{ - gmyth_file_set_file_name(GMYTH_FILE(file_local), filename); -} - -/** - * Open a File in order to get a local file. - * - * @param file_local The actual File Transfer instance. - * - * @return true, if the connection opening had been done successfully. - */ -gboolean -gmyth_file_local_open(GMythFileLocal * file_local) -{ - gboolean ret = TRUE; - GMythFileLocalPrivate *priv; - gchar *file_name_uri = NULL; - - g_return_val_if_fail(file_local != NULL, FALSE); - - priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local); - file_name_uri = gmyth_file_local_get_file_name(file_local); - - if (file_name_uri != NULL) { - priv->file_io = - g_io_channel_new_file(g_strdup(file_name_uri), "r+", NULL); - g_free(file_name_uri); - } - - if (priv->file_io < 0) - ret = FALSE; - - return ret; -} - -/** - * Closes a remote File Transfer connection. - * - * @param file_local The actual File Transfer instance. - */ -void -gmyth_file_local_close(GMythFileLocal * file_local) -{ - g_return_if_fail(file_local != NULL); -} - -/** - * Acquire access to a local file read/write pointer. - * - * @param transfer The actual File Local instance. - * @param do_wait Waits or not on a GCond, when trying to read from the remote socket. - * - * @return true, if the acquire had been got. - */ -static gboolean -_control_acquire_context(GMythFileLocal * file_local, gboolean do_wait) -{ - gboolean ret = TRUE; - GMythFileLocalPrivate *priv; - - g_return_val_if_fail(file_local != NULL, FALSE); - priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local); - - g_mutex_lock(priv->mutex); - return ret; -} - -/** - * Release access to a local file read/write pointer. - * - * @param transfer The actual File Transfer instance. - * - * @return true, if the local file read/write permissions had been releaseds. - */ -static gboolean -_control_release_context(GMythFileLocal * file_local) -{ - gboolean ret = TRUE; - GMythFileLocalPrivate *priv; - - g_return_val_if_fail(file_local != NULL, FALSE); - priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local); - - g_mutex_unlock(priv->mutex); - - return ret; -} - -/** - * Reads a block from a remote file. - * - * @param transfer The actual File Transfer instance. - * @param data A GByteArray instance, where all the binary data representing - * the remote file will be stored. - * @param size The block size, in bytes, to be requested from a remote file. - * @param read_unlimited Tells the backend to read indefinitely (LiveTV), or only - * gets the actual size - * - * @return The actual block size (in bytes) returned by REQUEST_BLOCK message, - * or the error code. - */ -GMythFileReadResult -gmyth_file_local_read(GMythFileLocal * file_local, GByteArray * data, - gint size, gboolean read_unlimited) -{ - gsize bytes_read = 0; - gint64 total_read = 0; - GMythFileReadResult retval = GMYTH_FILE_READ_OK; - GMythFileLocalPrivate *priv; - - GError *error = NULL; - - GIOCondition io_cond; - GIOStatus io_status = G_IO_STATUS_NORMAL; - - g_return_val_if_fail(file_local != NULL, FALSE); - g_return_val_if_fail(data != NULL, GMYTH_FILE_READ_ERROR); - - priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local); - - io_status = g_io_channel_set_encoding(priv->file_io, NULL, &error); - if (io_status == G_IO_STATUS_NORMAL) - gmyth_debug("Setting encoding to binary file data stream.\n"); - - io_cond = g_io_channel_get_buffer_condition(priv->file_io); - - _control_acquire_context(file_local, TRUE); - - if (size > 0) { - gchar *data_buffer = g_new0(gchar, size); - - io_status = g_io_channel_read_chars(priv->file_io, - data_buffer, (gsize) size, - &bytes_read, &error); - - if (io_status != G_IO_STATUS_NORMAL) { - gmyth_debug("Error on io_channel"); - g_free(data_buffer); - retval = GMYTH_FILE_READ_ERROR; - goto error; - } - - /* - * append new data to the increasing byte array - */ - data = - g_byte_array_append(data, (const guint8 *) data_buffer, - bytes_read); - total_read += bytes_read; - - if (!read_unlimited - && (gmyth_file_local_get_filesize(file_local) > 0) - && (gmyth_file_local_get_offset(file_local) == - gmyth_file_local_get_filesize(file_local))) { - retval = GMYTH_FILE_READ_EOF; - goto error; - } - - g_free(data_buffer); - } else { - retval = GMYTH_FILE_READ_ERROR; - } - - error: - _control_release_context(file_local); - - if (error != NULL) { - gmyth_debug("Cleaning-up ERROR: [msg = %s, code = %d]\n", - error->message, error->code); - g_error_free(error); - } - - if (total_read > 0) - gmyth_file_local_set_offset(file_local, - (gmyth_file_local_get_offset - (file_local) + total_read)); - - return retval; -} - -gint64 -gmyth_file_local_seek(GMythFileLocal * file_local, gint64 pos, - GSeekType whence) -{ - GMythFileLocalPrivate *priv; - - GError *error; - - GIOStatus io_status = G_IO_STATUS_NORMAL; - - g_return_val_if_fail(file_local != NULL, -1); - - priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local); - - io_status = - g_io_channel_seek_position(priv->file_io, pos, whence, &error); - - if (io_status == G_IO_STATUS_ERROR) - pos = -1; - - return pos; - -} - -/** - * Gets the actual file_local size of the binary content. - * - * @param file_local The actual File Transfer instance. - * - * @return The actual file_local size in bytes. - */ -guint64 -gmyth_file_local_get_filesize(GMythFileLocal * file_local) -{ - g_return_val_if_fail(file_local != NULL, 0); - - return gmyth_file_get_filesize(GMYTH_FILE(file_local)); -} - -/** - * Sets the actual file_local size. - * - * @param file_local The actual File Transfer instance. - * @param filesize The actual File Transfer size, in bytes. - */ -void -gmyth_file_local_set_filesize(GMythFileLocal * file_local, - guint64 filesize) -{ - g_return_if_fail(file_local != NULL); - - gmyth_file_set_filesize(GMYTH_FILE(file_local), filesize); -} - -/** - * Gets the actual file offset of the binary content. - * - * @param file_local The actual File Transfer instance. - * - * @return The actual file offset in bytes. - */ -gint64 -gmyth_file_local_get_offset(GMythFileLocal * file_local) -{ - g_return_val_if_fail(file_local != NULL, 0); - - return gmyth_file_get_offset(GMYTH_FILE(file_local)); -} - -/** - * Sets the actual file offset. - * - * @param file_local The actual File Local instance. - * @param offset The actual File Local offset, in bytes. - */ -void -gmyth_file_local_set_offset(GMythFileLocal * file_local, gint64 offset) -{ - g_return_if_fail(file_local != NULL); - - gmyth_file_set_offset(GMYTH_FILE(file_local), offset); -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_file_local.h --- a/gmyth/src/gmyth_file_local.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_file_local_local.h - * - * @brief

GMythFileLocal is the parent GMythFile that deals with the file streaming - * media local transfering from the MythTV backend. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Rosfran Lins Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __GMYTH_FILE_LOCAL_H__ -#define __GMYTH_FILE_LOCAL_H__ - -#include -#include - -#include "gmyth_file.h" -#include "gmyth_uri.h" -#include "gmyth_backendinfo.h" - -#include -#include -#include -#include -#include -#include - -G_BEGIN_DECLS -#define GMYTH_FILE_LOCAL_TYPE (gmyth_file_local_get_type ()) -#define GMYTH_FILE_LOCAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_FILE_LOCAL_TYPE, GMythFileLocal)) -#define GMYTH_FILE_LOCAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_LOCAL_TYPE, GMythFileLocalClass)) -#define IS_GMYTH_FILE_LOCAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_FILE_LOCAL_TYPE)) -#define IS_GMYTH_FILE_LOCAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_LOCAL_TYPE)) -#define GMYTH_FILE_LOCAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_FILE_LOCAL_TYPE, GMythFileLocalClass)) -typedef struct _GMythFileLocal GMythFileLocal; -typedef struct _GMythFileLocalClass GMythFileLocalClass; -typedef struct _GMythFileLocalPrivate GMythFileLocalPrivate; - -struct _GMythFileLocal { - GMythFile parent; -}; - -struct _GMythFileLocalClass { - GMythFileClass parent_class; -}; - - -GType gmyth_file_local_get_type(void); -GMythFileLocal *gmyth_file_local_new(GMythBackendInfo * backend_info); -GMythFileLocal *gmyth_file_local_new_with_uri(const gchar * uri); -gchar *gmyth_file_local_get_file_name(GMythFileLocal * - file_local); -void gmyth_file_local_set_file_name(GMythFileLocal * file_local, - const gchar * filename); -gboolean gmyth_file_local_open(GMythFileLocal * file_local); -void gmyth_file_local_close(GMythFileLocal * file_local); -gboolean gmyth_file_local_is_open(GMythFileLocal * file_local); - -GMythFileReadResult -gmyth_file_local_read(GMythFileLocal * file_local, - GByteArray * data, gint size, - gboolean read_unlimited); - -gint64 gmyth_file_local_seek(GMythFileLocal * file_local, - gint64 pos, GSeekType whence); - -guint64 gmyth_file_local_get_filesize(GMythFileLocal * file_local); -void gmyth_file_local_set_filesize(GMythFileLocal * file, - guint64 filesize); - -gint64 gmyth_file_local_get_offset(GMythFileLocal * file_local); -void gmyth_file_local_set_offset(GMythFileLocal * file_local, - gint64 offset); - -G_END_DECLS -#endif /* __GMYTH_FILE_LOCAL_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_file_transfer.c --- a/gmyth/src/gmyth_file_transfer.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1014 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_file_transfer.c - * - * @brief

GMythFileTransfer deals with the file streaming media remote/local - * transfering to the MythTV frontend. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Rosfran Lins Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * GStreamer MythTV plug-in properties: - * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv] - * - path (qurl - remote file to be opened) - * - port number * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gmyth_file_transfer.h" -#include "gmyth_recorder.h" -#include "gmyth_util.h" -#include "gmyth_socket.h" -#include "gmyth_stringlist.h" -#include "gmyth_debug.h" -#include "gmyth_uri.h" -#include "gmyth_marshal.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER " - - -#define GMYTH_FILE_TRANSFER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferPrivate)) - -enum myth_sock_types { - GMYTH_PLAYBACK_TYPE = 0, - GMYTH_MONITOR_TYPE, - GMYTH_FILETRANSFER_TYPE, - GMYTH_RINGBUFFER_TYPE -}; - -struct _GMythFileTransferPrivate { - GMythRecorder *recorder; - - gboolean do_next_program_chain; - gboolean disposed; - gboolean livetv_wait; - - /* - * MythTV version number - */ - gint mythtv_version; - - /* - * socket descriptors - */ - GMythSocket *control_sock; - GMythSocket *sock; - GMutex *mutex; - gint file_id; -}; - -static void gmyth_file_transfer_class_init(GMythFileTransferClass * - klass); -static void gmyth_file_transfer_init(GMythFileTransfer * object); -static void gmyth_file_transfer_dispose(GObject * object); -static void gmyth_file_transfer_finalize(GObject * object); -static void _file_transfer_program_info_changed(GMythFileTransfer * - transfer, - gint msg_code, - gpointer - livetv_recorder); -static gboolean _connect_to_backend(GMythFileTransfer * transfer); -static gboolean _control_acquire_context(GMythFileTransfer * transfer, - gboolean do_wait); -static gboolean _control_release_context(GMythFileTransfer * transfer); - -G_DEFINE_TYPE(GMythFileTransfer, gmyth_file_transfer, GMYTH_FILE_TYPE) - static void gmyth_file_transfer_class_init(GMythFileTransferClass * - klass) -{ - GObjectClass *gobject_class; - GMythFileTransferClass *gtransfer_class; - - gobject_class = (GObjectClass *) klass; - gtransfer_class = (GMythFileTransferClass *) gobject_class; - - gobject_class->dispose = gmyth_file_transfer_dispose; - gobject_class->finalize = gmyth_file_transfer_finalize; - - g_type_class_add_private(gobject_class, - sizeof(GMythFileTransferPrivate)); - - gtransfer_class->program_info_changed_handler = - _file_transfer_program_info_changed; - - gtransfer_class->program_info_changed_handler_signal_id = - g_signal_new("program-info-changed", - G_TYPE_FROM_CLASS(gtransfer_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | - G_SIGNAL_NO_HOOKS, 0, NULL, NULL, - gmyth_marshal_VOID__INT_POINTER, G_TYPE_NONE, 2, - G_TYPE_INT, G_TYPE_POINTER); - -} - -static void -gmyth_file_transfer_init(GMythFileTransfer * transfer) -{ - g_return_if_fail(transfer != NULL); - - transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); - transfer->priv->mutex = g_mutex_new(); - - g_signal_connect(G_OBJECT(transfer), "program-info-changed", - (GCallback) (GMYTH_FILE_TRANSFER_GET_CLASS - (transfer)->program_info_changed_handler), - NULL); -} - -static void -gmyth_file_transfer_dispose(GObject * object) -{ - GMythFileTransferPrivate *priv; - GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER(object); - - g_return_if_fail(transfer != NULL); - - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); - - if (priv->disposed) { - /* - * If dispose did already run, return. - */ - return; - } - - /* - * Make sure dispose does not run twice. - */ - priv->disposed = TRUE; - - if (priv->mutex != NULL) { - g_mutex_free(priv->mutex); - priv->mutex = NULL; - } - - if (priv->control_sock != NULL) { - g_object_unref(priv->control_sock); - priv->control_sock = NULL; - } - - if (priv->sock != NULL) { - g_object_unref(priv->sock); - priv->sock = NULL; - } - - if (priv->recorder != NULL) { - g_object_unref(priv->recorder); - priv->recorder = NULL; - } - - G_OBJECT_CLASS(gmyth_file_transfer_parent_class)->dispose(object); -} - -static void -gmyth_file_transfer_finalize(GObject * object) -{ - g_signal_handlers_destroy(object); - - G_OBJECT_CLASS(gmyth_file_transfer_parent_class)->finalize(object); -} - -/** - * Creates a new instance of GMythFileTransfer. - * - * @param backend_info The BackendInfo instance, with all the MythTV network - * configuration data. - * - * @return a new instance of the File Transfer. - */ -GMythFileTransfer * -gmyth_file_transfer_new(GMythBackendInfo * backend_info) -{ - GMythFileTransfer *transfer = g_object_new(GMYTH_FILE_TRANSFER_TYPE, - "backend-info", - backend_info, - NULL); - - // GValue val = {0,}; - // backend_info = g_object_ref( backend_info ); - gmyth_debug("Creating FileTransfer BackendInfo hostname = %s", - gmyth_backend_info_get_hostname(backend_info)); - // GMythBackendInfo *backend_info = gmyth_backend_info_new_with_uri - // (uri_str); - // g_value_init (&val, G_TYPE_OBJECT); - // g_value_set_object (&val, backend_info); - // g_object_set (G_OBJECT (transfer), "backend-info", &val, NULL); - - return transfer; -} - -gchar * -gmyth_file_transfer_get_file_name(GMythFileTransfer * transfer) -{ - gchar *filename; - - g_object_get(G_OBJECT(transfer), "filename", &filename, NULL); - - return filename; -} - -/** - * Creates a new instance of GMythFileTransfer. - * - * @param uri_str The URI poiting to the MythTV backend server. - * - * @return a new instance of the File Transfer. - */ -GMythFileTransfer * -gmyth_file_transfer_new_with_uri(const gchar * uri_str) -{ - GMythFileTransfer *transfer = - GMYTH_FILE_TRANSFER(g_object_new(GMYTH_FILE_TRANSFER_TYPE, NULL)); - gmyth_debug("URI str = %s", uri_str); - // GMythBackendInfo *backend_info = gmyth_backend_info_new_with_uri - // (uri_str); - GValue val = { 0, }; - g_value_init(&val, G_TYPE_OBJECT); - g_value_set_object(&val, gmyth_backend_info_new_with_uri(uri_str)); - g_object_set(G_OBJECT(transfer), "backend-info", &val, NULL); - - return transfer; -} - -/** - * Open a File Transfer connection in order to get a remote file. - * - * @param transfer The actual File Transfer instance. - * @param filename The file name of the remote file to be transferred to the client. - * - * @return true, if the connection opening had been done successfully. - */ -gboolean -gmyth_file_transfer_open(GMythFileTransfer * transfer, - const gchar * filename) -{ - gboolean ret = TRUE; - GMythFileTransferPrivate *priv; - - g_return_val_if_fail(transfer != NULL, FALSE); - g_return_val_if_fail(filename != NULL && strlen(filename) > 0, FALSE); - - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); - - gmyth_debug("Opening the FileTransfer... (%s)", filename); - - g_object_set(GMYTH_FILE(transfer), "filename", filename, NULL); - - /* - * configure the control socket - */ - if (TRUE /* priv->control_sock == NULL */ ) { - if (!_connect_to_backend(transfer)) { - gmyth_debug("Connection to backend failed (Control Socket)."); - ret = FALSE; - } - - if (priv->do_next_program_chain) { - priv->do_next_program_chain = FALSE; // fixme - gmyth_debug - ("New file available before the current file was opened"); - GMythProgramInfo *prog_info = - gmyth_recorder_get_current_program_info(priv->recorder); - - if (prog_info != NULL && prog_info->pathname != NULL - && strlen(prog_info->pathname->str) > 0 - && g_ascii_strcasecmp(prog_info->pathname->str, - gmyth_file_get_file_name(GMYTH_FILE - (transfer))) - != 0) - ret = - gmyth_file_transfer_open(transfer, - g_strrstr(prog_info-> - pathname->str, - "/")); - - if (prog_info != NULL) - g_object_unref(prog_info); - - if (!ret) - gmyth_debug("Cannot change to the next program info!"); - else - gmyth_debug("OK!!! MOVED to the next program info [%s]!", - gmyth_file_get_file_name(GMYTH_FILE - (transfer))); - - } else { - gmyth_debug - ("None new file found. We continue with the same file opened before"); - } - - } else { - gmyth_debug("Remote transfer control socket already created."); - } - - gmyth_debug("Got file with size = %lld.\n", - gmyth_file_get_filesize(GMYTH_FILE(transfer))); - - return ret; -} - -/** - * Connect a File Transfer binary client socket to a remote file. - * - * @param transfer The actual File Transfer instance. - * - * @return true, if the connection had been configured successfully. - */ -static gboolean -_connect_to_backend(GMythFileTransfer * transfer) -{ - GString *base_str = NULL; - GString *hostname = NULL; - GMythStringList *strlist = NULL; - gboolean ret = TRUE; - GMythFileTransferPrivate *priv; - GMythBackendInfo *backend_info; - - g_return_val_if_fail(transfer != NULL, FALSE); - - g_object_get(GMYTH_FILE(transfer), "backend-info", &backend_info, - NULL); - - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); - _control_acquire_context(transfer, TRUE); - - /* - * Creates the control socket - */ - - if (priv->control_sock != NULL) { - g_object_unref(priv->control_sock); - priv->control_sock = NULL; - } - - base_str = g_string_new(""); - - priv->control_sock = gmyth_socket_new(); - // Connects the socket, send Mythtv ANN command and verify Mythtv - // protocol version - if (!gmyth_socket_connect_to_backend(priv->control_sock, - backend_info->hostname, - backend_info->port, TRUE)) { - - _control_release_context(transfer); - g_object_unref(priv->control_sock); - priv->control_sock = NULL; - return FALSE; - } - - /* - * Creates the data socket - */ - if (priv->sock != NULL) { - g_object_unref(priv->sock); - priv->sock = NULL; - } - - priv->sock = gmyth_socket_new(); - gmyth_socket_connect(priv->sock, backend_info->hostname, - backend_info->port); - gmyth_debug("Connecting file transfer... (%s, %d)", - backend_info->hostname, backend_info->port); - - strlist = gmyth_string_list_new(); - hostname = gmyth_socket_get_local_hostname(); - gmyth_debug("[%s] MythTV version (from backend) = %d.\n", __FUNCTION__, - priv->control_sock->mythtv_version); - if (priv->control_sock->mythtv_version > 26) - g_string_printf(base_str, "ANN FileTransfer %s 1 -1", - hostname->str); - else - g_string_printf(base_str, "ANN FileTransfer %s", hostname->str); - - gmyth_string_list_append_string(strlist, base_str); - gmyth_string_list_append_char_array(strlist, - gmyth_file_get_file_name(GMYTH_FILE - (transfer))); - - gmyth_socket_write_stringlist(priv->sock, strlist); - - /* - * MONITOR Handler - DVB TV Chain update messages!!! - */ - - gmyth_socket_read_stringlist(priv->sock, strlist); - - /* - * file identification used in future file transfer requests to - * backend - */ - priv->file_id = gmyth_string_list_get_int(strlist, 1); - - /* - * Myth URI stream file size - decoded using two 8-bytes sequences (64 - * bits/long long types) - */ - gmyth_file_set_filesize(GMYTH_FILE(transfer), - gmyth_string_list_get_int64(strlist, 2)); - - gmyth_debug("***** Received: recordernum = %d, filesize = %" - G_GUINT64_FORMAT "\n", priv->file_id, - gmyth_file_get_filesize(GMYTH_FILE(transfer))); - - if (gmyth_file_get_filesize(GMYTH_FILE(transfer)) < 0) { - gmyth_debug - ("Got filesize equals to %llu is lesser than 0 [invalid stream file]\n", - gmyth_file_get_filesize(GMYTH_FILE(transfer))); - g_object_unref(priv->sock); - priv->sock = NULL; - ret = FALSE; - } - - _control_release_context(transfer); - - if (strlist != NULL) - g_object_unref(strlist); - - if (base_str != NULL) - g_string_free(base_str, TRUE); - - if (hostname != NULL) - g_string_free(hostname, TRUE); - - return ret; -} - -/** - * Receives a GObject signal coming from a LiveTV instance, all the time a - * program info changes. - * - * @param transfer The actual File Transfer instance. - * @param msg_code The MythTV backend message status code. - * @param live_tv A pointer to the LiveTV instance. * - */ -void -gmyth_file_transfer_emit_program_info_changed_signal(GMythFileTransfer * - transfer, - gint msg_code, - gpointer - live_tv_recorder) -{ - gmyth_debug("Calling signal handler... [FILE_TRANSFER]"); - - g_signal_emit(transfer, GMYTH_FILE_TRANSFER_GET_CLASS(transfer)->program_info_changed_handler_signal_id, 0, /* details - */ - msg_code, live_tv_recorder); - -} - -/** - * Checks if the actual File Transfer connection is open. - * - * @param transfer The actual File Transfer instance. - * - * @return true, if the File Transfer connection is opened. - */ -gboolean -gmyth_file_transfer_is_open(GMythFileTransfer * transfer) -{ - GMythStringList *strlist; - GMythFileTransferPrivate *priv; - GString *query; - - g_return_val_if_fail(transfer != NULL, FALSE); - - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); - g_return_val_if_fail(priv->control_sock != NULL, FALSE); - g_return_val_if_fail(priv->sock != NULL, FALSE); - - _control_acquire_context(transfer, TRUE); - - strlist = gmyth_string_list_new(); - query = g_string_new(GMYTHTV_QUERY_HEADER); - g_string_append_printf(query, "%d", priv->file_id); - - gmyth_string_list_append_string(strlist, query); - gmyth_string_list_append_char_array(strlist, "IS_OPEN"); - - gmyth_socket_write_stringlist(priv->control_sock, strlist); - gmyth_socket_read_stringlist(priv->control_sock, strlist); - - _control_release_context(transfer); - - g_string_free(query, TRUE); - g_object_unref(strlist); - - return (strlist != NULL && gmyth_string_list_get_int(strlist, 0) == 1); -} - -/** - * Closes a remote File Transfer connection. - * - * @param transfer The actual File Transfer instance. - */ -void -gmyth_file_transfer_close(GMythFileTransfer * transfer) -{ - GMythStringList *strlist; - GMythFileTransferPrivate *priv; - GString *query; - - g_return_if_fail(transfer != NULL); - - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); - - if (priv->control_sock == NULL) - return; - - _control_acquire_context(transfer, TRUE); - - strlist = gmyth_string_list_new(); - query = g_string_new(GMYTHTV_QUERY_HEADER); - g_string_append_printf(query, "%d", priv->file_id); - - gmyth_string_list_append_string(strlist, query); - gmyth_string_list_append_char_array(strlist, "DONE"); - - if (gmyth_socket_sendreceive_stringlist(priv->control_sock, strlist) <= - 0) { - // fixme: time out??? - gmyth_debug("Remote file timeout.\n"); - } - - g_string_free(query, TRUE); - g_object_unref(strlist); - - if (priv->sock) { - g_object_unref(priv->sock); - priv->sock = NULL; - } - - if (priv->control_sock) { - g_object_unref(priv->control_sock); - priv->control_sock = NULL; - } - - _control_release_context(transfer); -} - -/** - * Do a seek operation (moves the read/write file pointer) on a remote file. - * - * @param transfer The actual File Transfer instance. - * @param pos The position to be moved in the remote file. - * @param whence Tells to what direction seek movement should be done. - * - * @return The actual position on the remote file (after seek has been done). - */ -gint64 -gmyth_file_transfer_seek(GMythFileTransfer * transfer, guint64 pos, - gint whence) -{ - GMythStringList *strlist = gmyth_string_list_new(); - GMythFileTransferPrivate *priv; - GString *query; - - g_return_val_if_fail(transfer != NULL, FALSE); - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); - - g_return_val_if_fail(priv->sock != NULL, -1); - g_return_val_if_fail(priv->control_sock != NULL, -1); - - strlist = gmyth_string_list_new(); - query = g_string_new(GMYTHTV_QUERY_HEADER); - g_string_append_printf(query, "%d", priv->file_id); - - /* - * myth_control_acquire_context( transfer, TRUE ); - */ - - gmyth_string_list_append_string(strlist, query); - gmyth_string_list_append_char_array(strlist, "SEEK"); - gmyth_string_list_append_uint64(strlist, pos); - - gmyth_string_list_append_int(strlist, whence); - - if (pos > 0) - gmyth_string_list_append_uint64(strlist, pos); - else - gmyth_string_list_append_uint64(strlist, - gmyth_file_get_offset(GMYTH_FILE - (transfer))); - - gmyth_socket_sendreceive_stringlist(priv->control_sock, strlist); - - gint64 retval = gmyth_string_list_get_int64(strlist, 0); - - gmyth_file_set_offset(GMYTH_FILE(transfer), retval); - gmyth_debug("Got reading position pointer from the streaming = %lld\n", - retval); - - g_object_unref(strlist); - g_string_free(query, TRUE); - - /* - * myth_control_release_context( transfer ); - */ - - return retval; -} - -/** - * Acquire access to a remote file socket read/write pointer. - * - * @param transfer The actual File Transfer instance. - * @param do_wait Waits or not on a GCond, when trying to read from the remote socket. - * - * @return true, if the acquire had been got. - */ -static gboolean -_control_acquire_context(GMythFileTransfer * transfer, gboolean do_wait) -{ - gboolean ret = TRUE; - GMythFileTransferPrivate *priv; - - g_return_val_if_fail(transfer != NULL, FALSE); - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); - - g_mutex_lock(priv->mutex); - return ret; -} - -/** - * Release access to a remote file socket read/write pointer. - * - * @param transfer The actual File Transfer instance. - * - * @return true, if the socket read/write permissions had been releaseds. - */ -static gboolean -_control_release_context(GMythFileTransfer * transfer) -{ - gboolean ret = TRUE; - GMythFileTransferPrivate *priv; - - g_return_val_if_fail(transfer != NULL, FALSE); - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); - - g_mutex_unlock(priv->mutex); - - return ret; -} - -/** - * Reads a block from a remote file. - * - * @param transfer The actual File Transfer instance. - * @param data A GByteArray instance, where all the binary data representing - * the remote file will be stored. - * @param size The block size, in bytes, to be requested from a remote file. - * @param read_unlimited Tells the backend to read indefinitely (LiveTV), or only - * gets the actual size - * - * @return The actual block size (in bytes) returned by REQUEST_BLOCK message, - * or the error code. - */ -GMythFileReadResult -gmyth_file_transfer_read(GMythFileTransfer * transfer, GByteArray * data, - gint size, gboolean read_unlimited) -{ - gint bytes_sent = 0; - gsize bytes_read = 0; - gint64 total_read = 0; - GMythFileReadResult retval = GMYTH_FILE_READ_OK; - GMythFileTransferPrivate *priv; - - GError *error = NULL; - - GIOChannel *io_channel; - GIOChannel *io_channel_control; - - GIOCondition io_cond; - GIOCondition io_cond_control; - GIOStatus io_status = G_IO_STATUS_NORMAL; - GIOStatus io_status_control = G_IO_STATUS_NORMAL; - - GMythStringList *strlist; - GMythStringList *ret_strlist = NULL; - gboolean ret = TRUE; - GString *query; - - g_return_val_if_fail(transfer != NULL, FALSE); - g_return_val_if_fail(data != NULL, GMYTH_FILE_READ_ERROR); - - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); - - strlist = gmyth_string_list_new(); - - io_channel = priv->sock->sd_io_ch; - io_channel_control = priv->control_sock->sd_io_ch; - - io_status = g_io_channel_set_encoding(io_channel, NULL, &error); - if (io_status == G_IO_STATUS_NORMAL) - gmyth_debug("[%s] Setting encoding to binary data socket).\n", - __FUNCTION__); - - io_cond = g_io_channel_get_buffer_condition(io_channel); - - io_cond_control = g_io_channel_get_buffer_condition(io_channel); - if (priv->sock == NULL || (io_status == G_IO_STATUS_ERROR)) { - g_printerr - ("gmyth_file_transfer_read(): Called with no raw socket.\n"); - return GMYTH_FILE_READ_ERROR; - } - - if (priv->control_sock == NULL - || (io_status_control == G_IO_STATUS_ERROR)) { - g_printerr - ("gmyth_file_transfer_read(): Called with no control socket.\n"); - return GMYTH_FILE_READ_ERROR; - } - - query = g_string_new(GMYTHTV_QUERY_HEADER); - g_string_append_printf(query, "%d", priv->file_id); - gmyth_debug("[%s] Transfer_query = %s\n", __FUNCTION__, query->str); - - _control_acquire_context(transfer, TRUE); - // Do Read - gmyth_string_list_append_char_array(strlist, query->str); - gmyth_string_list_append_char_array(strlist, "REQUEST_BLOCK"); - gmyth_string_list_append_int(strlist, size - total_read); - - guint iter_count = 3; - - do { - bytes_sent = 0; - - // Request the block to the backend - gmyth_socket_write_stringlist(priv->control_sock, strlist); - - if (ret_strlist != NULL) - g_object_unref(ret_strlist); - - ret_strlist = gmyth_string_list_new(); - // Receives the backand answer - gmyth_socket_read_stringlist(priv->control_sock, ret_strlist); - - if (ret_strlist != NULL - && gmyth_string_list_length(ret_strlist) > 0) { - bytes_sent = gmyth_string_list_get_int(ret_strlist, 0); // -1 - // on - // backend - // error - gmyth_debug("[%s] got SENT buffer message = %d\n", - __FUNCTION__, bytes_sent); - } - - if (read_unlimited && (bytes_sent == 0)) { - g_usleep(300); - } - - --iter_count; - - } - while (read_unlimited && (bytes_sent == 0) && iter_count > 0); - - if (bytes_sent > 0) { - gchar *data_buffer = g_new0(gchar, bytes_sent); - - io_status = g_io_channel_read_chars(io_channel, - data_buffer, - (gsize) bytes_sent, - &bytes_read, &error); - - if (io_status != G_IO_STATUS_NORMAL) { - gmyth_debug("Error on io_channel"); - g_free(data_buffer); - g_object_unref(strlist); - retval = GMYTH_FILE_READ_ERROR; - goto error; - } - - /* - * append new data to the increasing byte array - */ - data = - g_byte_array_append(data, (const guint8 *) data_buffer, - bytes_read); - gmyth_file_set_offset(GMYTH_FILE(transfer), - gmyth_file_get_offset(GMYTH_FILE(transfer)) + - bytes_read); - - if (!read_unlimited - && (gmyth_file_get_filesize(GMYTH_FILE(transfer)) > 0) - && (gmyth_file_get_offset(GMYTH_FILE(transfer)) == - gmyth_file_get_filesize(GMYTH_FILE(transfer)))) { - retval = GMYTH_FILE_READ_EOF; - goto error; - } - - g_free(data_buffer); - } else { - retval = GMYTH_FILE_READ_ERROR; - } - - if (strlist != NULL) { - g_object_unref(strlist); - strlist = NULL; - } - - if (ret_strlist != NULL) { - g_object_unref(ret_strlist); - ret_strlist = NULL; - } - - if (read_unlimited && (bytes_sent == 0)) { - gmyth_debug("Trying to move to the next program chain..."); - if (priv->recorder != NULL && priv->do_next_program_chain) { - priv->do_next_program_chain = FALSE; - retval = GMYTH_FILE_READ_NEXT_PROG_CHAIN; - GMythProgramInfo *prog_info = - gmyth_recorder_get_current_program_info(priv->recorder); - - gmyth_debug - ("Comparing if the current prog. info = %s [strlen == %d] is equals to " - " %s [strlen == %d]...", prog_info->pathname->str, - strlen(prog_info->pathname->str), - gmyth_file_get_file_name(GMYTH_FILE(transfer)), - strlen(gmyth_file_get_file_name(GMYTH_FILE(transfer)))); - - if (prog_info != NULL && prog_info->pathname != NULL - && strlen(prog_info->pathname->str) > 0 - && (NULL == - g_strstr_len(prog_info->pathname->str, - strlen(prog_info->pathname->str), - gmyth_file_get_file_name(GMYTH_FILE - (transfer))))) { - /* - * releasing context got at this function starting... - */ - _control_release_context(transfer); - ret = - gmyth_file_transfer_open(transfer, - g_strrstr(prog_info-> - pathname->str, - "/")); - _control_acquire_context(transfer, TRUE); - /* - * acquiring context released at this function stopping... - */ - - if (prog_info != NULL) - g_object_unref(prog_info); - - if (!ret) - gmyth_debug("Cannot change to the next program info!"); - else - gmyth_debug - ("OK!!! MOVED to the next program info [%s]!", - gmyth_file_get_file_name(GMYTH_FILE(transfer))); - } - - } - - } - /* - * if - */ - error: - - _control_release_context(transfer); - g_string_free(query, TRUE); - - if (error != NULL) { - gmyth_debug("Cleaning-up ERROR: %s [msg = %s, code = %d]\n", - __FUNCTION__, error->message, error->code); - g_error_free(error); - } - - if (total_read > 0) - gmyth_file_set_offset(GMYTH_FILE(transfer), - gmyth_file_get_offset(GMYTH_FILE - (transfer)) + - total_read); - - return retval; -} - -static void -_file_transfer_program_info_changed(GMythFileTransfer * transfer, - gint msg_code, - gpointer livetv_recorder) -{ - GMythRecorder *recorder; - GMythFileTransferPrivate *priv; - - g_return_if_fail(transfer != NULL); - - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); - - recorder = GMYTH_RECORDER(livetv_recorder); - gmyth_debug - ("Program info changed! ( file transfer orig. = %p, ptr. = [%s] )", - transfer, livetv_recorder != NULL ? "[NOT NULL]" : "[NULL]"); - - if (NULL != recorder) { - gmyth_debug - ("YES, the requested program info movement on the LiveTV transfer is authentical!"); - } - - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); - g_object_ref(recorder); - priv->recorder = recorder; - priv->do_next_program_chain = TRUE; -} - -/** - * Sets the timeout flag of a file being transfered. - * - * @param transfer The actual File Transfer instance. - * @param fast If this is true, sets the remote timeout to be as fast - * as possible. - * - * @return true, if the acquire had been got. - */ -gboolean -gmyth_file_transfer_settimeout(GMythFileTransfer * transfer, gboolean fast) -{ - GMythFileTransferPrivate *priv; - GMythStringList *strlist = NULL; - - g_return_val_if_fail(transfer != NULL, FALSE); - - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); - - g_return_val_if_fail(priv->sock != NULL, FALSE); - g_return_val_if_fail(priv->control_sock != NULL, FALSE); - - _control_acquire_context(transfer, TRUE); - - strlist = gmyth_string_list_new(); - gmyth_string_list_append_char_array(strlist, GMYTHTV_QUERY_HEADER); - gmyth_string_list_append_char_array(strlist, "SET_TIMEOUT"); - gmyth_string_list_append_int(strlist, fast); - - gint strlist_len = - gmyth_socket_sendreceive_stringlist(priv->control_sock, - strlist); - - if (strlist_len > 0) - gmyth_debug("Yes, timeout was changed: %s.", - gmyth_string_list_get_char_array(strlist, 0)); - else - gmyth_debug("Timeout cannot be changed!"); - - _control_release_context(transfer); - - gmyth_debug("%s setting timeout flag of this file transfer = %s\n", - strlist_len > 0 ? "Yes," : "NOT", - fast ? "FAST" : "NOT FAST"); - - g_object_unref(strlist); - - return TRUE; -} - -/** - * Gets the actual file size of the binary content. - * - * @param transfer The actual File Transfer instance. - * - * @return The actual file size in bytes. - */ -guint64 -gmyth_file_transfer_get_filesize(GMythFileTransfer * transfer) -{ - guint64 filesize; - - g_return_val_if_fail(transfer != NULL, 0); - - g_object_get(GMYTH_FILE(transfer), "file-size", &filesize, NULL); - - return filesize; -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_file_transfer.h --- a/gmyth/src/gmyth_file_transfer.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_file_transfer.h - * - * @brief

GMythFileTransfer deals with the file streaming media remote/local - * transfering to the MythTV frontend. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Rosfran Lins Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __GMYTH_FILE_TRANSFER_H__ -#define __GMYTH_FILE_TRANSFER_H__ - -#include -#include - -#include "gmyth_file.h" -#include "gmyth_socket.h" -#include "gmyth_uri.h" -#include "gmyth_backendinfo.h" - -#include -#include -#include -#include -#include -#include - -G_BEGIN_DECLS -#define GMYTH_FILE_TRANSFER_TYPE (gmyth_file_transfer_get_type ()) -#define GMYTH_FILE_TRANSFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransfer)) -#define GMYTH_FILE_TRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferClass)) -#define IS_GMYTH_FILE_TRANSFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_FILE_TRANSFER_TYPE)) -#define IS_GMYTH_FILE_TRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TRANSFER_TYPE)) -#define GMYTH_FILE_TRANSFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferClass)) -typedef struct _GMythFileTransfer GMythFileTransfer; -typedef struct _GMythFileTransferClass GMythFileTransferClass; -typedef struct _GMythFileTransferPrivate GMythFileTransferPrivate; - -struct _GMythFileTransfer { - GMythFile parent; - GMythFileTransferPrivate *priv; -}; - -struct _GMythFileTransferClass { - GMythFileClass parent_class; - - /* - * callbacks - */ - guint program_info_changed_handler_signal_id; - - /* - * signal default handlers - */ - void (*program_info_changed_handler) (GMythFileTransfer * - transfer, - gint msg_code, - gpointer - livetv_recorder); -}; - - -GType gmyth_file_transfer_get_type(void); -GMythFileTransfer *gmyth_file_transfer_new(GMythBackendInfo * - backend_info); -gchar *gmyth_file_transfer_get_file_name(GMythFileTransfer * - transfer); -gboolean gmyth_file_transfer_open(GMythFileTransfer * transfer, - const gchar * filename); -void gmyth_file_transfer_close(GMythFileTransfer * transfer); -gboolean gmyth_file_transfer_is_open(GMythFileTransfer * transfer); - -GMythFileReadResult -gmyth_file_transfer_read(GMythFileTransfer * transfer, - GByteArray * data, gint size, - gboolean read_unlimited); -gint64 gmyth_file_transfer_seek(GMythFileTransfer * transfer, - guint64 pos, gint whence); -gboolean gmyth_file_transfer_settimeout(GMythFileTransfer * - transfer, gboolean fast); -guint64 gmyth_file_transfer_get_filesize(GMythFileTransfer * - transfer); - -void - gmyth_file_transfer_emit_program_info_changed_signal(GMythFileTransfer * - transfer, - gint - msg_code, - gpointer - live_tv_recorder); - -G_END_DECLS -#endif /* __GMYTH_FILE_TRANSFER_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_http.c --- a/gmyth/src/gmyth_http.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1037 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_http.c - * - * @brief

GMythHttp library provides a wrapper to access - * data from the database using http+xml - * - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. - * @author Artur Duque de Souza - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include - -#include "gmyth_http.h" -#include "gmyth_debug.h" -#include "gmyth_socket.h" - -xmlXPathObjectPtr -getnodeset(xmlDocPtr doc, xmlChar * xpath) -{ - - xmlXPathContextPtr context; - xmlXPathObjectPtr result; - - context = xmlXPathNewContext(doc); - result = xmlXPathEvalExpression(xpath, context); - - if (xmlXPathNodeSetIsEmpty(result->nodesetval)) { - g_fprintf(stderr, "Error: No result at XPath\n"); - return NULL; - } - - xmlXPathFreeContext(context); - return result; -} - - -xmlDocPtr -XMLParse(const char *content, int length) -{ - xmlDocPtr doc; /* the resulting document tree */ - - doc = xmlReadMemory(content, length, NULL, NULL, 0); - if (doc == NULL) { - g_fprintf(stderr, "Error: Failed to parse XML document\n"); - return NULL; - } - - return doc; -} - -xmlXPathObjectPtr -getXPath(xmlChar * xpath, xmlDocPtr doc) -{ - xmlXPathObjectPtr result; - - result = getnodeset(doc, xpath); - return result; -} - - -/** Retrieves the Progam List from the Channel - * - * @param nodeTab A pointer to a node inside the XML - * @return A GSList containing a list of all the programs - */ -GSList * -get_Program_List(xmlNodePtr node) -{ - GSList *program_list = NULL; - - while (node != NULL) { - if (g_ascii_strcasecmp((char *) node->name, "text") != 0) { - GMythProgram *program = (GMythProgram *) - g_malloc(sizeof(struct _GMythProgram)); - - program->title = g_strdup((char *) - xmlGetProp(node, - (xmlChar *) "title")); - - program->subtitle = g_strdup((char *) - xmlGetProp(node, (xmlChar *) - "subtitle")); - - program->catType = g_strdup((char *) - xmlGetProp(node, (xmlChar *) - "catType")); - - program->category = g_strdup((char *) - xmlGetProp(node, (xmlChar *) - "category")); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "repeat"), - "%d", &(program->repeat)); - - program->startTime = gmyth_util_string_to_time_val - ((char *) xmlGetProp(node, (xmlChar *) "startTime")); - - program->endTime = gmyth_util_string_to_time_val - ((char *) xmlGetProp(node, (xmlChar *) "endTime")); - - program_list = g_slist_append(program_list, program); - } - - node = node->next; - } - - return program_list; -} - -/** Retrieves the Channel List from the ProgramGuide - * - * @param node A pointer to a node inside the XML - * @param epg The struct where is the current epg - * @return The epg from "param" updated - */ -void -get_Channel_List(xmlNodePtr node, GMythEpg * epg) -{ - epg->channelList = NULL; - - while (node != NULL) { - - if (g_ascii_strcasecmp((char *) node->name, "text") != 0) { - GMythChannel *channel = (GMythChannel *) g_malloc - (sizeof(struct _GMythChannel)); - - channel->channelName = g_strdup((char *) - xmlGetProp(node, (xmlChar *) - "channelName")); - - channel->chanNum = g_strdup((char *) - xmlGetProp(node, (xmlChar *) - "chanNum")); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "chanId"), - "%d", &(channel->chanId)); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "callSign"), - "%d", &(channel->callSign)); - - channel->programList = get_Program_List(node->children); - - epg->channelList = g_slist_append(epg->channelList, channel); - - } - - node = node->next; - } -} - -/** Retrieves the properties from the ProgramGuide - * - * @param nodeTab A pointer to a node inside the XML - * @param epg The struct where is the current epg - * @return The epg from "param" updated - */ -void -get_ProgramGuide_Properties(xmlNodePtr nodeTab, GMythEpg * epg) -{ - - xmlNode *ptr = nodeTab->children->next->children; - - epg->startTime = gmyth_util_string_to_time_val((char *) ptr->content); - - ptr = ptr->parent->next->next->children; - epg->endTime = gmyth_util_string_to_time_val((char *) ptr->content); - - ptr = ptr->parent->next->next->children; - sscanf((char *) ptr->content, "%d", &(epg->startChanId)); - - ptr = ptr->parent->next->next->children; - sscanf((char *) ptr->content, "%d", &(epg->endChanId)); - - ptr = ptr->parent->next->next->children; - sscanf((char *) ptr->content, "%d", &(epg->numOfChannels)); - - ptr = ptr->parent->next->next->children; - sscanf((char *) ptr->content, "%d", &(epg->details)); - - ptr = ptr->parent->next->next->children; - sscanf((char *) ptr->content, "%d", &(epg->totalCount)); - - ptr = ptr->parent->next->next->children; - epg->asOf = gmyth_util_string_to_time_val((char *) ptr->content); - - ptr = ptr->parent->next->next->children; - epg->version = g_strdup((char *) ptr->content); - - ptr = ptr->parent->next->next->children; - sscanf((char *) ptr->content, "%d", &(epg->protoVer)); - - ptr = ptr->parent->next->next->children; - // go to Channel section and retrieve Channels and Programs - if (epg->numOfChannels > 0) - get_Channel_List(ptr, epg); - else - epg->channelList = NULL; -} - -/** Aux function to retrieve the Eletronic Program Guide - * - * @param doc An XML document (xmlDocPtr) - * @return The epg - */ -void -getEpg(xmlDocPtr doc, GMythEpg * epg) -{ - xmlXPathObjectPtr result; - xmlNodeSetPtr nodeset; - xmlChar *keyword; - - int i; - - result = getXPath((xmlChar *) "/*", doc); - - if (result) { - nodeset = result->nodesetval; - for (i = 0; i < nodeset->nodeNr; i++) { - keyword = (xmlChar *) nodeset->nodeTab[i]->name; - if (g_ascii_strcasecmp - ((char *) keyword, "GetProgramGuideResponse") == 0) { - get_ProgramGuide_Properties(nodeset->nodeTab[i], epg); - break; - } - } - xmlXPathFreeObject(result); - } - -} - - - -/** Retrieves the Eletronic Program Guide from the backend - * - * @param doc An XML document (xmlDocPtr) - * @return The epg - */ -GMythEpg -gmyth_http_retrieve_epg(GMythBackendInfo * backend_info, - GTimeVal * StartTime, GTimeVal * EndTime, - gint StartChanId, gint NumOfChannels, - gchar * Details) -{ - GMythEpg epg; - MemoryStruct chunk; - - chunk.memory = NULL; /* we expect realloc(NULL, size) to work */ - chunk.size = 0; /* no data at this point */ - - gchar *starttime; - - starttime = (gchar *) xmlURIEscapeStr((const xmlChar *) - gmyth_util_time_to_mythformat_from_time_val - (StartTime), NULL); - - gchar *endtime; - - endtime = (gchar *) xmlURIEscapeStr((const xmlChar *) - gmyth_util_time_to_mythformat_from_time_val - (EndTime), NULL); - - GString *command = g_string_new(""); - - g_string_printf(command, - "GetProgramGuide?StartTime=%s&EndTime=%s&StartChanId=%d" - "&NumOfChannels=%d&Details=%s", starttime, endtime, - StartChanId, NumOfChannels, Details); - gmyth_debug("HTTP Request command = %s\n", command->str); - - chunk = gmyth_http_request(backend_info, command); - if (chunk.memory != NULL) { - xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory)); - - getEpg(doc, &epg); - free(chunk.memory); - } - - return epg; -} - - -GMythRecorded_Recording -retrieve_recorded_recording(xmlNodePtr node) -{ - GMythRecorded_Recording recording; - - if (g_ascii_strcasecmp((char *) node->name, "text") != 0) { - - sscanf((char *) xmlGetProp(node, (xmlChar *) "dupInType"), - "%d", &(recording.dupInType)); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "dupMethod"), - "%d", &(recording.dupMethod)); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "recStatus"), - "%d", &(recording.recStatus)); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "encoderId"), - "%d", &(recording.encoderId)); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "recordId"), - "%d", &(recording.recordId)); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "recType"), - "%d", &(recording.recType)); - - recording.playGroup = g_strdup((char *) - xmlGetProp(node, (xmlChar *) - "playGroup")); - - recording.recGroup = g_strdup((char *) - xmlGetProp(node, - (xmlChar *) "recGroup")); - - recording.recProfile = g_strdup((char *) - xmlGetProp(node, (xmlChar *) - "recProfile")); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "recPriority"), - "%d", &(recording.recPriority)); - - recording.recStartTs = gmyth_util_string_to_time_val - ((char *) xmlGetProp(node, (xmlChar *) "recStartTs")); - - recording.recEndTs = gmyth_util_string_to_time_val - ((char *) xmlGetProp(node, (xmlChar *) "recEndTs")); - } - - return recording; -} - - -GMythRecorded_Channel -retrieve_recorded_channel(xmlNodePtr node) -{ - GMythRecorded_Channel channel; - - if (g_ascii_strcasecmp((char *) node->name, "text") != 0) { - - channel.chanFilters = g_strdup((char *) - xmlGetProp(node, (xmlChar *) - "chanFilters")); - - channel.channelName = g_strdup((char *) - xmlGetProp(node, (xmlChar *) - "channelName")); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "chanNum"), - "%d", &(channel.chanNum)); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "sourceId"), - "%d", &(channel.sourceId)); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "commFree"), - "%d", &(channel.commFree)); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "inputId"), - "%d", &(channel.inputId)); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "chanId"), - "%d", &(channel.chanId)); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "callSign"), - "%d", &(channel.callSign)); - } - - return channel; -} - - - -/** Retrieves all the programs from Recorded XML - * - * @param nodeTab A pointer to a node inside the XML - * @param recorded The struct where is the current epg - * @return list with all the recorded programs - */ -GSList * -get_Recorded_Programs(xmlNodePtr node) -{ - GSList *programList = NULL; - - while (node != NULL) { - - if (g_ascii_strcasecmp((char *) node->name, "text") != 0) { - - GMythRecorded_Program *program = (GMythRecorded_Program *) - g_malloc(sizeof(struct _GMythRecorded_Program)); - - sscanf((char *) - xmlGetProp(node, (xmlChar *) "programFlags"), "%d", - &(program->programFlags)); - - program->title = g_strdup((char *) - xmlGetProp(node, - (xmlChar *) "title")); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "programId"), - "%d", &(program->programId)); - - program->catType = g_strdup((char *) - xmlGetProp(node, (xmlChar *) - "catType")); - - program->category = g_strdup((char *) - xmlGetProp(node, (xmlChar *) - "category")); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "seriesId"), - "%d", &(program->seriesId)); - - - program->startTime = gmyth_util_string_to_time_val - ((char *) xmlGetProp(node, (xmlChar *) "startTime")); - - program->endTime = gmyth_util_string_to_time_val - ((char *) xmlGetProp(node, (xmlChar *) "endTime")); - - program->lastModified = gmyth_util_string_to_time_val((char *) - xmlGetProp - (node, - (xmlChar - *) - "lastModified")); - - /* - * TODO: FIX ME at gmyth_util program->asOf = - * gmyth_util_string_to_time_val\ ((char *)xmlGetProp(node, - * (xmlChar *)"airdate")); - */ - - program->subTitle = g_strdup((char *) - xmlGetProp(node, (xmlChar *) - "subTitle")); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "stars"), - "%d", &(program->stars)); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "repeat"), - "%d", &(program->repeat)); - - sscanf((char *) xmlGetProp(node, (xmlChar *) "fileSize"), - "%d", &(program->repeat)); - - program->hostname = g_strdup((char *) - xmlGetProp(node, (xmlChar *) - "hostname")); - - program->channel = retrieve_recorded_channel(node->children); - - // Skip the \n - program->recording = - retrieve_recorded_recording(node->children->next->next); - - // add to the list - programList = g_slist_append(programList, program); - } - - node = node->next; - } - - return programList; -} - -/** Retrieves the properties from Recorded XML - * - * @param nodeTab A pointer to a node inside the XML - * @param recorded The struct where is the current epg - * @return "recorded" from "param" updated - */ -void -get_Recorded_Properties(xmlNodePtr nodeTab, GMythRecorded * recorded) -{ - xmlNode *ptr = nodeTab->children->next->children; - - sscanf((char *) ptr->content, "%d", &(recorded->totalCount)); - - - ptr = ptr->parent->next->next->children; - recorded->asOf = gmyth_util_string_to_time_val((char *) ptr->content); - - ptr = ptr->parent->next->next->children; - recorded->version = g_strdup((char *) ptr->content); - - ptr = ptr->parent->next->next->children; - sscanf((char *) ptr->content, "%d", &(recorded->protoVer)); - - ptr = ptr->parent->next->next->children; - if (recorded->totalCount > 0) - recorded->programList = get_Recorded_Programs(ptr->children); - -} - - -/** Aux function to retrieve Recorded programs - * - * @param doc An XML document (xmlDocPtr) - * @return The recorded var updated - */ -void -getRecorded(xmlDocPtr doc, GMythRecorded * recorded) -{ - xmlXPathObjectPtr result; - xmlNodeSetPtr nodeset; - xmlChar *keyword; - - int i; - - result = getXPath((xmlChar *) "/*", doc); - - if (result) { - nodeset = result->nodesetval; - for (i = 0; i < nodeset->nodeNr; i++) { - keyword = (xmlChar *) nodeset->nodeTab[i]->name; - if (g_ascii_strcasecmp - ((char *) keyword, "GetRecordedResponse") == 0) { - get_Recorded_Properties(nodeset->nodeTab[i], recorded); - break; - } - } - xmlXPathFreeObject(result); - } - -} - - -/** Function to retrieve the files that are recorded - * - */ -GMythRecorded -gmyth_http_retrieve_recorded(GMythBackendInfo * backend_info) -{ - GMythRecorded recorded; - MemoryStruct chunk; - - chunk.memory = NULL; - chunk.size = 0; - - GString *command = g_string_new(""); - - g_string_printf(command, "GetRecorded"); - - chunk = gmyth_http_request(backend_info, command); - if (chunk.memory != NULL) { - xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory)); - - getRecorded(doc, &recorded); - free(chunk.memory); - } - - return recorded; -} - - - -/** Function to retrieve jobqueue status - * - */ -gint -gmyth_http_retrieve_job_status(GMythBackendInfo * backend_info, - gint chanid, GTimeVal * start) -{ - gint status = 0; - gint count = 0; - gint temp_chanid = 0; - GTimeVal *temp_start = NULL; - int i; - - xmlXPathObjectPtr result; - xmlNodeSetPtr nodeset; - xmlNodePtr node; - MemoryStruct chunk; - - chunk.memory = NULL; - chunk.size = 0; - - GString *command = g_string_new(""); - - g_string_printf(command, "GetStatus"); - - chunk = gmyth_http_request(backend_info, command); - - if (chunk.memory != NULL) { - xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory)); - - result = getXPath((xmlChar *) "/Status/JobQueue", doc); - if (result) { - nodeset = result->nodesetval; - node = nodeset->nodeTab[0]; - sscanf((char *) xmlGetProp(node, (xmlChar *) "count"), - "%d", &count); - - if (count > 0) { - - // Get the first child - node = node->children->next; - - for (i = 0; i < count; i++) { - - sscanf((char *) - xmlGetProp(node, (xmlChar *) "chanId"), "%d", - &temp_chanid); - - if (chanid == temp_chanid) { - temp_start = gmyth_util_string_to_time_val((char *) - xmlGetProp - (node, - (xmlChar - *) - "startTime")); - - if ((temp_start->tv_sec == start->tv_sec) && - (temp_start->tv_usec == start->tv_usec)) - sscanf((char *) - xmlGetProp(node, - (xmlChar *) "status"), - "%d", &status); - } - // Escape "text" node - node = node->next->next; - } - } - - } - - xmlXPathFreeObject(result); - free(chunk.memory); - - } - - return status; -} - - - -/** Function to retrieve settings on the backend - * - * @param backend_info infos about the backend - * @param key the key you want to retrieve - * @param hostname the hostname that the key is set up - * @return the value of the key - */ -gchar * -gmyth_http_retrieve_setting(GMythBackendInfo * backend_info, - gchar * key, gchar * hostname) -{ - xmlXPathObjectPtr result; - xmlNodeSetPtr nodeset; - xmlChar *keyword; - MemoryStruct chunk; - gchar *value = NULL; - - chunk.memory = NULL; - chunk.size = 0; - - GString *command = g_string_new(""); - - g_string_printf(command, "GetSetting?Key=%s&HostName=%s&Default=NULL", - key, hostname); - - chunk = gmyth_http_request(backend_info, command); - - if (chunk.memory != NULL) { - xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory)); - - result = getXPath((xmlChar *) "/GetSettingResponse/Values/*", doc); - - if (result) { - nodeset = result->nodesetval; - keyword = (xmlChar *) nodeset->nodeTab[0]->name; - if (g_ascii_strcasecmp((char *) keyword, "Value") == 0) { - // Here we have the value - value = (gchar *) nodeset->nodeTab[0]->children->content; - } - xmlXPathFreeObject(result); - } - - free(chunk.memory); - } - - return value; -} - -/** Common steps for rec_profile's functions - * - * @param backend_info infos about the backend - * @param id the profile's id that you want to delete - * @return 0 if OK - */ -gint -rec_profile_common(GMythBackendInfo * backend_info, GString * command) -{ - xmlXPathObjectPtr result; - xmlNodeSetPtr nodeset; - xmlChar *keyword; - MemoryStruct chunk; - - chunk.memory = NULL; - chunk.size = 0; - - int ret = -1; - - chunk = gmyth_http_request(backend_info, command); - - if (chunk.memory != NULL) { - xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory)); - - result = getXPath((xmlChar *) "/*", doc); - - if (result) { - nodeset = result->nodesetval; - keyword = (xmlChar *) nodeset->nodeTab[0]->name; - - if (g_ascii_strcasecmp((char *) keyword, "Success") == 0) - ret = 0; - - xmlXPathFreeObject(result); - } - - free(chunk.memory); - } - - return ret; -} - - -/** Function to delete recording profiles - * - * @param backend_info infos about the backend - * @param id the profile's id that you want to delete - * @return 0 if OK - */ -gint -gmyth_http_del_rec_profile(GMythBackendInfo * backend_info, gint id) -{ - - GString *command = g_string_new(""); - - g_string_printf(command, "delRecProfiles?id=%d", id); - - - return rec_profile_common(backend_info, command); -} - -/** Function to create recording profiles - * - * @param backend_info infos about the backend - * @param profilename the name of profile you want to use - * @param groupname the name of groupname you want to use - * @param vcodec the name of the video codec you want to use - * @param acodec the name of the audo codec you want to use - * @return 0 if OK - */ -gint -gmyth_http_create_rec_profile(GMythBackendInfo * backend_info, - GMythRecProfile * profile) -{ - - if (profile->name != NULL && profile->group != NULL && - profile->vcodec && profile->acodec && profile->options != NULL) { - GString *command = g_string_new(""); - - g_string_printf(command, "createRecProfiles?profilename=%s&" - "groupname=%s&vcodec=%s&acodec=%s&" - "transcodelossless=%d&transcoderesize=%d&" - "width=%d&height=%d&rtjpegquality=%d&" - "rtjpeglumafilter=%d&rtjpegchromafilter=%d&" - "mpeg4bitrate=%d&mpeg4maxquality=%d&" - "mpeg4minquality=%d&mpeg4qualdiff=%d&" - "mpeg4scalebitrate=%d&mpeg4optionvhq=%d&" - "mpeg4option4mv=%d&mpeg4optionidct=%d&" - "mpeg4optionime=%d&hardwaremjpegquality=%d&" - "hardwaremjpeghdecimation=%d&hardwaremjpegvdecimation=%d&" - "mpeg2streamtype=%s&mpeg2aspectratio=%s&" - "mpeg2bitrate=%d&mpeg2maxbitrate=%d&" - "samplerate=%d&mp3quality=%d&" - "volume=%d&mpeg2audtype=%s&" - "mpeg2audbitratel1=%d&mpeg2audbitratel2=%d&" - "mpeg2audvolume=%d", - profile->name, profile->group, - profile->vcodec, profile->acodec, - profile->options->transcodelossless, - profile->options->transcoderesize, - profile->options->width, - profile->options->height, - profile->options->rtjpegquality, - profile->options->rtjpeglumafilter, - profile->options->rtjpegchromafilter, - profile->options->mpeg4bitrate, - profile->options->mpeg4maxquality, - profile->options->mpeg4minquality, - profile->options->mpeg4qualdiff, - profile->options->mpeg4scalebitrate, - profile->options->mpeg4optionvhq, - profile->options->mpeg4option4mv, - profile->options->mpeg4optionidct, - profile->options->mpeg4optionime, - profile->options->hardwaremjpegquality, - profile->options->hardwaremjpeghdecimation, - profile->options->hardwaremjpegvdecimation, - profile->options->mpeg2streamtype, - profile->options->mpeg2aspectratio, - profile->options->mpeg2bitrate, - profile->options->mpeg2maxbitrate, - profile->options->samplerate, - profile->options->mp3quality, - profile->options->volume, - profile->options->mpeg2audtype, - profile->options->mpeg2audbitratel1, - profile->options->mpeg2audbitratel2, - profile->options->mpeg2audvolume); - - - return rec_profile_common(backend_info, command); - } else - return -1; -} - -/** Function to retrieve recording profiles - * - * @param backend_info infos about the backend - * @param groupname the name of group you want to retrieve - * @return the list of profiles - */ -GSList * -gmyth_http_retrieve_rec_profiles(GMythBackendInfo * backend_info, - gchar * groupname) -{ - xmlXPathObjectPtr result; - xmlNodeSetPtr nodeset; - xmlChar *keyword; - MemoryStruct chunk; - GSList *profiles = NULL; - - chunk.memory = NULL; - chunk.size = 0; - - GString *command = g_string_new(""); - - g_string_printf(command, "GetRecProfiles?groupname=%s", groupname); - - chunk = gmyth_http_request(backend_info, command); - - if (chunk.memory != NULL) { - xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory)); - - result = getXPath((xmlChar *) "/*", doc); - - if (result) { - nodeset = result->nodesetval; - keyword = (xmlChar *) nodeset->nodeTab[0]->name; - - if (g_ascii_strcasecmp((char *) keyword, "Profiles") == 0) { - xmlNodePtr node = nodeset->nodeTab[0]->children->next; - GMythRecProfile *profile; - - while (node != NULL) { - if (g_ascii_strcasecmp((char *) node->name, "text") != - 0) { - profile = gmyth_recprofile_new(); - - sscanf((char *) xmlGetProp(node, (xmlChar *) - "id"), "%d", - &(profile->id)); - - profile->name = g_strdup((char *) - xmlGetProp(node, - (xmlChar *) - "name")); - - profile->vcodec = g_strdup((char *) - xmlGetProp(node, - (xmlChar *) - "vcodec")); - - profile->acodec = g_strdup((char *) - xmlGetProp(node, - (xmlChar *) - "acodec")); - - profile->group = g_strdup(groupname); - - profiles = g_slist_append(profiles, profile); - } - node = node->next; - } - - } - xmlXPathFreeObject(result); - } - - free(chunk.memory); - } - - return profiles; -} - - - -/* - * Aux functions got from libcurl - */ -void * -myrealloc(void *ptr, size_t size) -{ - /* - * There might be a realloc() out there that doesn't like reallocing - * NULL pointers, so we take care of it here - */ - if (ptr) - return realloc(ptr, size); - else - return malloc(size); -} - -size_t -WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) -{ - size_t realsize = size * nmemb; - MemoryStruct *mem = (struct _MemoryStruct *) data; - - mem->memory = - (char *) myrealloc(mem->memory, mem->size + realsize + 1); - if (mem->memory) { - memcpy(&(mem->memory[mem->size]), ptr, realsize); - mem->size += realsize; - mem->memory[mem->size] = 0; - } - - return realsize; -} - - -/** Send HTTP Command and receives the result of it - * - * @return A string with the response from the server - * NULL if there is no response. - */ -MemoryStruct -gmyth_http_request(GMythBackendInfo * backend_info, GString * command) -{ - LIBXML_TEST_VERSION - size_t size = - strlen(backend_info->hostname) + strlen(command->str) + 20; - - gchar *URL = (gchar *) g_malloc(sizeof(gchar) * size); - gchar *mid = (gchar *) g_malloc(sizeof(gchar) * 6); - - mid = ""; - - if (g_ascii_strcasecmp(command->str, "GetStatus") && - g_ascii_strcasecmp(command->str, "GetStatusHTML")) { - mid = "Myth/"; - } - - g_snprintf(URL, size, "http://%s:%d/%s%s", - backend_info->hostname, backend_info->status_port, mid, - command->str); - - CURL *curl_handle; - - MemoryStruct chunk; - - chunk.memory = NULL; /* we expect realloc(NULL, size) to work */ - chunk.size = 0; /* no data at this point */ - - curl_global_init(CURL_GLOBAL_ALL); - - /* - * init the curl session - */ - curl_handle = curl_easy_init(); - - /* - * specify URL to get - */ - curl_easy_setopt(curl_handle, CURLOPT_URL, URL); - - /* - * send all data to this function - */ - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, - WriteMemoryCallback); - - /* - * we pass our 'chunk' struct to the callback function - */ - curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &chunk); - - /* - * some servers don't like requests that are made without a user-agent - * field, so we provide one - */ - curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); - - /* - * set timeout - */ - curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 20); - - /* - * get it! - */ - curl_easy_perform(curl_handle); - - /* - * cleanup curl stuff - */ - curl_easy_cleanup(curl_handle); - - return chunk; -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_http.h --- a/gmyth/src/gmyth_http.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,204 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_http.h - * - * @brief

GMythHttp library provides a wrapper to access - * data from the database using http+xml - * - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. - * @author Artur Duque de Souza - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __GMYTH_HTTP_H__ -#define __GMYTH_HTTP_H__ - -#include - -#include -#include -#include -#include -#include -#include - -#include "gmyth_backendinfo.h" -#include "gmyth_util.h" -#include "gmyth_recprofile.h" - -#include -#include -#include - -G_BEGIN_DECLS -#define MYTH_PORT_STATUS 6544 -#define JOB_UNKNOWN 0x0000 -#define JOB_QUEUED 0x0001 -#define JOB_PENDING 0x0002 -#define JOB_STARTING 0x0003 -#define JOB_RUNNING 0x0004 -#define JOB_STOPPING 0x0005 -#define JOB_PAUSED 0x0006 -#define JOB_RETRY 0x0007 -#define JOB_ERRORING 0x0008 -#define JOB_ABORTING 0x0009 - // JOB_DONE is a mask to indicate the job is done - // whatever the status is -#define JOB_DONE 0x0100 -#define JOB_FINISHED 0x0110 -#define JOB_ABORTED 0x0120 -#define JOB_ERRORED 0x0130 -#define JOB_CANCELLED 0x0140 -typedef struct _GMythRecorded_Recording GMythRecorded_Recording; -typedef struct _GMythRecorded_Channel GMythRecorded_Channel; -typedef struct _GMythRecorded_Program GMythRecorded_Program; -typedef struct _GMythRecorded GMythRecorded; -typedef struct _GMythProgram GMythProgram; -typedef struct _GMythChannel GMythChannel; -typedef struct _GMythEpg GMythEpg; -typedef struct _MemoryStruct MemoryStruct; - -struct _MemoryStruct { - char *memory; - size_t size; -}; - -struct _GMythProgram { - gchar *title; - gchar *subtitle; - gchar *catType; - gchar *category; - gint repeat; - GTimeVal *startTime; - GTimeVal *endTime; -}; - -struct _GMythChannel { - gchar *channelName; - gchar *chanNum; - gint chanId; - gint callSign; - GSList *programList; -}; - -struct _GMythEpg { - gint startChanId; - gint endChanId; - gchar *version; - gint protoVer; - gint totalCount; - gint numOfChannels; - GTimeVal *asOf; - GTimeVal *startTime; - GTimeVal *endTime; - gint details; - GSList *channelList; -}; - - -struct _GMythRecorded_Recording { - gint dupInType; - gint dupMethod; - gchar *playGroup; - gchar *recGroup; - gchar *recProfile; - gint recPriority; - gint recStatus; - gint encoderId; - gint recordId; - gint recType; - GTimeVal *recStartTs; - GTimeVal *recEndTs; -}; - - -struct _GMythRecorded_Channel { - gchar *chanFilters; - gchar *channelName; - gint chanNum; - gint sourceId; - gint commFree; - gint inputId; - gint chanId; - gint callSign; -}; - - -struct _GMythRecorded_Program { - gint programFlags; - gchar *title; - gint programId; - gchar *catType; - gchar *category; - gint seriesId; - GTimeVal *startTime; - GTimeVal *endTime; - GTimeVal *airdate; // ? - GTimeVal *lastModified; - gchar *subTitle; - gint stars; - gint repeat; - gint fileSize; - gchar *hostname; - GMythRecorded_Channel channel; - GMythRecorded_Recording recording; -}; - -struct _GMythRecorded { - gchar *version; - gint protoVer; - gint totalCount; - GTimeVal *asOf; - GSList *programList; -}; - - -gint gmyth_http_retrieve_job_status(GMythBackendInfo * - backend_info, gint chanid, - GTimeVal * start); - -gchar *gmyth_http_retrieve_setting(GMythBackendInfo * - backend_info, gchar * key, - gchar * hostname); - -GMythEpg gmyth_http_retrieve_epg(GMythBackendInfo * backend_info, - GTimeVal * StartTime, - GTimeVal * EndTime, - gint StartChanId, - gint NumOfChannels, - gchar * Details); - -GMythRecorded gmyth_http_retrieve_recorded(GMythBackendInfo * - backend_info); - -GSList *gmyth_http_retrieve_rec_profiles(GMythBackendInfo * - backend_info, - gchar * groupname); - -gint gmyth_http_create_rec_profile(GMythBackendInfo * - backend_info, - GMythRecProfile * profile); - -gint gmyth_http_del_rec_profile(GMythBackendInfo * backend_info, - gint id); - -MemoryStruct gmyth_http_request(GMythBackendInfo * backend_info, - GString * command); - -G_END_DECLS -#endif /* __GMYTH_HTTP_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_jobqueue.c --- a/gmyth/src/gmyth_jobqueue.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,200 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_jobqueue.c - * - * @brief

Library to use JobQueue from mythbackend - * - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. - * @author Artur Duque de Souza - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gmyth_jobqueue.h" -#include "gmyth_http.h" -#include "gmyth_debug.h" -#include "gmyth_socket.h" - -/** Function to connect - * - * @param backend_info the backendinfo - * @return gboolean - result of connection - * - */ -static GMythSocket * -backend_connect(GMythBackendInfo * backend_info) -{ - GMythSocket *socket = gmyth_socket_new(); - - if (gmyth_socket_connect_to_backend(socket, - gmyth_backend_info_get_hostname - (backend_info), - gmyth_backend_info_get_port - (backend_info), TRUE) == TRUE) { - gmyth_debug("Backend socket connection success"); - return socket; - } else { - gmyth_debug("Connection failed"); - return NULL; - } -} - - -/** Function to send a command to the backend - * - * @param socket pointer to a socket - * @param action the action itself - * @param job the action itself - * @param chanid the action itself - * @param starttime the action itself - * @param options the action itself - * @return the value returned by the backend - * - */ -static gchar * -send_command(GMythSocket * socket, gchar * action, - gchar * job, gint chanid, gchar * starttime, gchar * options) -{ - GString *command = g_string_new(""); - GString *ret_str; - gchar *ret; - - GMythStringList *retlist = gmyth_string_list_new(); - - g_string_printf(command, "JOBQUEUE %s %s %d %s %s", action, job, - chanid, starttime, options); - - gmyth_string_list_append_string(retlist, command); - gmyth_socket_write_stringlist(socket, retlist); - - // receive answer - gmyth_socket_read_stringlist(socket, retlist); - ret_str = gmyth_string_list_get_string(retlist, 0); - - // ret = ret_str->str; - ret = g_string_free(ret_str, FALSE); - g_string_free(command, TRUE); - - gmyth_string_list_clear_all(retlist); - g_object_unref(retlist); - - return ret; -} - - -/** Function to analyze the response from the backend - * - * @param ret the msg returned by the backend - * @param value the expected value - * @return 0 if success and -1 if error - * - */ -static gboolean -test_result(gchar * ret, gchar * value) -{ - if (g_ascii_strcasecmp(ret, value) == 0) { - return TRUE; - } else { - gmyth_debug("JobQueue Error: %s", ret); - return FALSE; - } -} - -/** Function to add a job inside JOBQUEUE - * - * @param transcode object holding all the info about the transcoding - * @param job the job you want to add the action - * @return TRUE if the job was added, FALSE if not - * - */ -gboolean -gmyth_jobqueue_add_job(GMythTranscoder * transcode, gchar * job) -{ - GMythSocket *socket = backend_connect(transcode->backend_info); - gboolean res = FALSE; - - if (socket != NULL) { - GString *options = g_string_new(""); - gchar *ret = NULL; - - if (g_ascii_strcasecmp(job, "JOB_TRANSCODE") == 0) { - if (transcode->cutlist) - g_string_append(options, " JOB_USE_CUTLIST"); - - if (transcode->output) - g_string_append_printf(options, " JOB_OUTPUT %s", - transcode->output_filename); - - if (transcode->profile != NULL) - g_string_append_printf(options, " %s", transcode->profile); - } - ret = send_command(socket, "ADD", job, transcode->chanid, - transcode->starttime, options->str); - res = test_result(ret, "JOBQUEUE_OK"); - gmyth_socket_close_connection(socket); - - g_object_unref(socket); - - g_string_free(options, TRUE); - - if (ret) - g_free(ret); - - } else { - gmyth_debug("JobQueue Connection Failed"); - } - - return res; -} - -/** Function to change a job cmd inside JOBQUEUE - * - * @param transcode object holding all the info about the transcoding - * @param action the action (ADD) - * @param job the job you want to add the action - * @return the value of the key - * - */ -gboolean -gmyth_jobqueue_change_cmd(GMythTranscoder * transcode, gchar * action, - gchar * job) -{ - GMythSocket *socket = backend_connect(transcode->backend_info); - gboolean res = FALSE; - - if (socket != NULL) { - gchar *ret = send_command(socket, action, job, - transcode->chanid, - transcode->starttime, ""); - - res = test_result(ret, "JOBQUEUE_CHANGED_CMD_OK"); - - gmyth_socket_close_connection(socket); - g_object_unref(socket); - - g_free(ret); - - } else { - gmyth_debug("JobQueue Connection Failed"); - } - - return res; -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_jobqueue.h --- a/gmyth/src/gmyth_jobqueue.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_jobqueue.h - * - * @brief

Library to use JobQueue from mythbackend - * - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. - * @author Artur Duque de Souza - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __GMYTH_JOBQUEUE_H__ -#define __GMYTH_JOBQUEUE_H__ - -#include - -#include -#include -#include -#include -#include -#include - -#include "gmyth_stringlist.h" -#include "gmyth_backendinfo.h" -#include "gmyth_transcoder.h" -#include "gmyth_socket.h" -#include "gmyth_util.h" - -G_BEGIN_DECLS - gboolean gmyth_jobqueue_add_job(GMythTranscoder * transcoder, - gchar * job); -gboolean gmyth_jobqueue_change_cmd(GMythTranscoder * transcoder, - gchar * action, gchar * job); - -G_END_DECLS -#endif /* __GMYTH_JOBQUEUE_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_livetv.c --- a/gmyth/src/gmyth_livetv.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,980 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_livetv.c - * - * @brief

GMythLiveTV starts a remote TV session with the MythTV backend. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Rosfran Lins Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gmyth_livetv.h" -#include "gmyth_remote_util.h" -#include "gmyth_tvchain.h" -#include "gmyth_socket.h" -#include "gmyth_backendinfo.h" -#include "gmyth_debug.h" - -#include "gmyth_file.h" -#include "gmyth_file_transfer.h" -#include "gmyth_file_local.h" -#include "gmyth_monitor_handler.h" - -#include "gmyth_common.h" -#include "gmyth_util.h" - -static void gmyth_livetv_class_init(GMythLiveTVClass * klass); -static void gmyth_livetv_init(GMythLiveTV * object); - -static void gmyth_livetv_dispose(GObject * object); -static void gmyth_livetv_finalize(GObject * object); - -static gint tvchain_curr_index = -1; - -/* - * static GStaticMutex lock = G_STATIC_MUTEX_INIT; - */ - -#define GMYTHTV_TRANSFER_MAX_WAITS 100 - -G_DEFINE_TYPE(GMythLiveTV, gmyth_livetv, G_TYPE_OBJECT) - static void gmyth_livetv_class_init(GMythLiveTVClass * klass) -{ - GObjectClass *gobject_class; - - gobject_class = (GObjectClass *) klass; - - gobject_class->dispose = gmyth_livetv_dispose; - gobject_class->finalize = gmyth_livetv_finalize; -} - -static void -gmyth_livetv_init(GMythLiveTV * livetv) -{ - livetv->monitor = NULL; - livetv->backend_info = NULL; - livetv->local_hostname = NULL; - livetv->file = NULL; - livetv->setup_done = FALSE; - - livetv->socket = NULL; - livetv->recorder = NULL; - livetv->tvchain = NULL; - livetv->proginfo = NULL; - livetv->uri = NULL; - - livetv->mutex = g_mutex_new(); -} - -static void -gmyth_livetv_dispose(GObject * object) -{ - GMythLiveTV *livetv = GMYTH_LIVETV(object); - - - if (livetv->disposed) { - /* - * If dispose did already run, return. - */ - return; - } - - /* - * Make sure dispose does not run twice. - */ - livetv->disposed = TRUE; - - if (livetv->monitor != NULL) { - g_object_unref(livetv->monitor); - livetv->monitor = NULL; - } - - - if (livetv->file != NULL) { - g_object_unref(livetv->file); - livetv->file = NULL; - } - - if (livetv->recorder != NULL) { - // gmyth_recorder_close(livetv->recorder); - g_object_unref(livetv->recorder); - livetv->recorder = NULL; - } - - if (livetv->socket != NULL) { - g_object_unref(livetv->socket); - livetv->socket = NULL; - } - - if (livetv->tvchain != NULL) { - g_object_unref(livetv->tvchain); - livetv->tvchain = NULL; - } - - if (livetv->proginfo != NULL) { - g_object_unref(livetv->proginfo); - livetv->proginfo = NULL; - } - - if (livetv->backend_info != NULL) { - g_object_unref(livetv->backend_info); - livetv->backend_info = NULL; - } - - if (livetv->uri != NULL) { - g_object_unref(livetv->uri); - livetv->uri = NULL; - } - - if (livetv->mutex != NULL) { - g_mutex_free(livetv->mutex); - livetv->mutex = NULL; - } - - if (livetv->local_hostname != NULL) { - g_string_free(livetv->local_hostname, TRUE); - livetv->local_hostname = NULL; - } - - G_OBJECT_CLASS(gmyth_livetv_parent_class)->dispose(object); -} - -static void -gmyth_livetv_finalize(GObject * object) -{ - g_signal_handlers_destroy(object); - - G_OBJECT_CLASS(gmyth_livetv_parent_class)->finalize(object); -} - -/** - * Creates a new GMythLiveTV instance - * - * @return a newly allocated GMythLiveTV instance - */ -GMythLiveTV * -gmyth_livetv_new(GMythBackendInfo * backend_info) -{ - GMythLiveTV *livetv = - GMYTH_LIVETV(g_object_new(GMYTH_LIVETV_TYPE, NULL)); - - livetv->backend_info = backend_info; - g_object_ref(livetv->backend_info); - - return livetv; -} - -/** - * The GObject signal handler function, from which all status messages - * from the Monitor Handler will be advertized, all time it receives - * LiveTV status messages from the MythTV backend - * - * @param monitor a GMythMonitorHandler instance - * @param msg_code the MythTV's server numeric status code - * @param message the message's string description - * @param user_data pointer to the GMythLiveTV instance - */ -static void -gmyth_livetv_monitor_signal_handler(GMythMonitorHandler * monitor, - gint msg_code, gchar * message, - gpointer user_data) -{ - GMythLiveTV *live_tv = GMYTH_LIVETV(user_data); - - gmyth_debug - ("LIVETV Signal handler ( msg = %s, code = %d, live_tv param = %s, user_data = %s )\n", - message, msg_code, live_tv != NULL ? "" : "NULL", - user_data != NULL ? "" : "NULL"); - - if (NULL == live_tv || !IS_GMYTH_FILE_TRANSFER(live_tv->file)) { - gmyth_debug("LiveTV_obj is equals to NULL!!!"); - return; - } - - switch (msg_code) { - - case GMYTH_BACKEND_PROGRAM_INFO_CHANGED: - { - gmyth_debug - ("LIVETV Program Changed request received [ msg = %s ]. Watching if the new " - "TV Chain ID is the same as the old one...\n", message); - if (g_ascii_strcasecmp - (message, - (gmyth_tvchain_get_id(live_tv->tvchain))->str) != 0) { - gmyth_debug - ("OK!!! MOVED to the next program chain [actual == %s]!", - (gmyth_tvchain_get_id(live_tv->tvchain))->str); - /* - * advertises the FileTransfer about the program info - * changed - */ - if (live_tv->file != NULL) { - gmyth_debug - ("Emitting signal to the FileTransfer... [ \"program-info-changed \" ]"); - - gmyth_file_transfer_emit_program_info_changed_signal - (GMYTH_FILE_TRANSFER(live_tv->file), msg_code, - (gpointer) (live_tv->recorder)); - - /* - * gmyth_livetv_monitor_handler_stop( live_tv ); - */ - } else - gmyth_debug - ("LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n"); - } - break; - } - case GMYTH_BACKEND_DONE_RECORDING: - { - gmyth_debug - ("LIVETV Program Changed request received [ msg = %s ]. Watching if the new " - "TV Chain ID is the same as the old one...\n", message); - if (g_ascii_strcasecmp - (message, - (gmyth_tvchain_get_id(live_tv->tvchain))->str) != 0) { - gmyth_debug - ("OK!!! MOVED to the next program chain [actual == %s]!", - (gmyth_tvchain_get_id(live_tv->tvchain))->str); - /* - * advertises the FileTransfer about the program info - * changed - */ - if (live_tv->file != NULL) { - gmyth_debug - ("Emitting signal to the FileTransfer... [ \"backend-done-recording\" ]"); - - gmyth_file_transfer_emit_program_info_changed_signal - (GMYTH_FILE_TRANSFER(live_tv->file), msg_code, - (gpointer) (live_tv->recorder)); - - } else - gmyth_debug - ("LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n"); - } - break; - } - case GMYTH_BACKEND_STOP_LIVETV: - { - gmyth_debug - ("LIVETV Stop LiveTV request received [ msg = %s ]. Going out the " - "LiveTV...\n", message); - /* - * stops the LiveTV - */ - if (live_tv != NULL) { - gmyth_debug("Going out the LiveTV... [ \"quit-livetv\" ]"); - - g_object_unref(live_tv); - } else - gmyth_debug - ("LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n"); - - break; - } - default: - break; - } /* switch (Monitor Handler messages) */ - -} - -/** - * Starts the Monitor Handler to this GMythLiveTV session, in order - * to receive the status messages from the MythTV's backend server - * - * @param live_tv the GMythLiveTV instance - * - * @return true if the Monitor Handler start-up process - * had been concluded succcesfully - */ -gboolean -gmyth_livetv_monitor_handler_start(GMythLiveTV * livetv) -{ - gboolean res = TRUE; - - if (livetv->monitor != NULL) { - g_object_unref(livetv->monitor); - livetv->monitor = NULL; - } - - livetv->monitor = gmyth_monitor_handler_new(); - res = - gmyth_monitor_handler_open(livetv->monitor, - livetv->backend_info->hostname, - livetv->backend_info->port); - - if (res == TRUE) { - gmyth_debug - ("Connect MythTV Monitor event socket! Trying to start the message handler..."); - - res = gmyth_monitor_handler_start(livetv->monitor); - - if (res) { - gmyth_debug - ("MythTV Monitor event socket connected and listening!"); - g_signal_connect(G_OBJECT(livetv->monitor), - "backend-events-handler", (GCallback) - gmyth_livetv_monitor_signal_handler, livetv); - } else { - gmyth_debug - ("Problems when trying to start MythTV Monitor event socket!"); - goto error; - } - } - - error: - return res; - -} - -/** - * Stops the Monitor Handler to this GMythLiveTV session, in order - * to stop receiving the status messages from the MythTV's backend server - * - * @param live_tv the GMythLiveTV instance - * - * @return true if the Monitor Handler shutdown process - * had been concluded succcesfully - */ -void -gmyth_livetv_monitor_handler_stop(GMythLiveTV * livetv) -{ - - if (livetv->monitor != NULL) { - g_object_unref(livetv->monitor); - livetv->monitor = NULL; - } - -} - -#if 0 -static gchar * -gmyth_livetv_create_remote_url(GMythLiveTV * livetv) -{ - gchar *uri = g_strdup(""); - - gmyth_backend_info_get_remote_h - // gmyth_backend(livetv->backend_info) - return uri; -} -#endif - -/** - * Configures the GMythLiveTV session, sends SPAWN_LIVETV message, - * sets the channel name, and gets the first program info about the - * actual recording - * - * @param live_tv the GMythLiveTV instance - * @param channel the channel name (the chan_name field, from the tvchain table) - * @param backend_info the GMythBackendInfo describing the remote server - * - * @return true if the LiveTV's recorder instance configuration - * had been concluded succcesfully - */ -static gboolean -gmyth_livetv_setup_recorder_channel_name(GMythLiveTV * livetv, - gchar * channel) -{ - gboolean res = TRUE; - - g_return_val_if_fail(livetv != NULL, FALSE); - - g_mutex_lock(livetv->mutex); - - if (livetv->socket == NULL) { - livetv->socket = gmyth_socket_new(); - /* - * FIME: Implement this at gmyth_socket - */ - res = - gmyth_socket_connect_to_backend(livetv->socket, - livetv->backend_info->hostname, - livetv->backend_info->port, - TRUE); - if (!res) { - gmyth_debug("[%s] LiveTV can not connect to backend", - __FUNCTION__); - res = FALSE; - goto error; - } - } - - livetv->is_livetv = TRUE; - - livetv->local_hostname = gmyth_socket_get_local_hostname(); - - if (livetv->local_hostname == NULL) { - g_warning("livetv could not retrieve the local hostname"); - res = FALSE; - goto error; - } else { - gmyth_debug("Local hostname: %s", livetv->local_hostname->str); - } - - if (livetv->recorder != NULL) { - g_object_unref(livetv->recorder); - livetv->recorder = NULL; - } - - if (gmyth_remote_util_get_free_recorder_count(livetv->socket) <= 0) { - gmyth_debug("No free remote encoder available."); - res = FALSE; - goto error; - } - - /* - * Gets the recorder num - */ - livetv->recorder = - remote_request_next_free_recorder(livetv->socket, -1); - gmyth_socket_close_connection(livetv->socket); - - if (NULL == livetv->recorder) { - gmyth_debug("[%s] None remote encoder available", __FUNCTION__); - res = FALSE; - goto error; - } - - /* - * Init remote encoder. Opens its control socket. - */ - res = gmyth_recorder_setup(livetv->recorder); - if (!res) { - gmyth_debug("[%s] Fail while setting remote encoder\n", - __FUNCTION__); - res = FALSE; - goto error; - } - - /* - * Creates livetv chain handler - */ - livetv->tvchain = gmyth_tvchain_new(); - gmyth_tvchain_initialize(livetv->tvchain, livetv->backend_info); - - if (livetv->tvchain == NULL || livetv->tvchain->tvchain_id == NULL) { - res = FALSE; - goto error; - } - // Spawn live tv. Uses the socket to send mythprotocol data to start - // livetv in the backend (remotelly) - res = gmyth_recorder_spawntv(livetv->recorder, - gmyth_tvchain_get_id(livetv->tvchain)); - if (!res) { - gmyth_debug("[%s] Fail while spawn tv\n", __FUNCTION__); - res = FALSE; - goto error; - } - - if (res == TRUE) { - /* - * loop finished, set the max tries variable to zero again... - */ - gint wait_to_transfer = 0; - - while (wait_to_transfer++ < GMYTHTV_TRANSFER_MAX_WAITS && - (gmyth_recorder_is_recording(livetv->recorder) == FALSE)) - g_usleep(300); - - if (channel != NULL) { - /* - * Pauses remote encoder. - */ - res = gmyth_recorder_pause_recording(livetv->recorder); - if (!res) { - gmyth_debug("[%s] Fail while pausing remote encoder\n", - __FUNCTION__); - res = FALSE; - goto error; - } - - if (gmyth_recorder_check_channel_name - (livetv->recorder, channel)) { - if (gmyth_recorder_set_channel_name - (livetv->recorder, channel)) { - gmyth_debug("Channel changed!!! [%s].\n", channel); - } - } - - } - /* - * if - changes the channel number - */ - /* - * sleep (5); - */ - /* - * FIXME: this is evil (tpm) - */ - } - - /* - * DEBUG message - */ - GMythProgramInfo *prog_info = - gmyth_recorder_get_current_program_info(livetv->recorder); - - if (NULL == prog_info) { - gmyth_debug("ProgramInfo is equals to NULL!!!"); - - gint i; - gchar *channame = NULL; - - gmyth_debug("Problem getting current proginfo!\n"); - - /* - * mythbackend must not be tuned in to a channel, so keep - * changing channels until we find a valid one, or until - * we decide to give up. - */ - for (i = 1; i < 1000; i++) { - if (channame != NULL) - g_free(channame); - channame = g_strdup_printf("%d", i); - if (gmyth_recorder_set_channel_name(livetv->recorder, channame) - < 0) { - continue; - } - prog_info = - gmyth_recorder_get_next_program_info(livetv->recorder, - BROWSE_DIRECTION_UP); - gmyth_program_info_print(prog_info); - if (prog_info != NULL) - break; - } - - } - - /* - * if - Program Info - */ - /* - * prints program info data text - */ - gmyth_debug("New ProgramInfo...\n"); - gmyth_program_info_print(prog_info); - - /* - * check if the program chain could be obtained from the MythTV - * protocol message - */ - if (prog_info != NULL) { - gmyth_backend_info_set_username(livetv->tvchain->backend_info, - "mythtv"); - gmyth_backend_info_set_password(livetv->tvchain->backend_info, - "mythtv"); - gmyth_backend_info_set_db_name(livetv->tvchain->backend_info, - "mythconverg"); - GList *prog_list = - gmyth_tvchain_get_program_info_from_channel(livetv->tvchain, - channel); - GMythProgramInfo *ch_prog = NULL; - - if (prog_list != NULL && g_list_length(prog_list) > 0) { - ch_prog = (GMythProgramInfo *) g_list_nth_data(prog_list, 0); - gmyth_debug - ("Channel program info (from a list with size = %d)!", - g_list_length(prog_list)); - gmyth_program_info_print(ch_prog); - } - - gmyth_debug("Program Info: %s\n", - gmyth_program_info_to_string(prog_info)); - livetv->proginfo = prog_info; - /* - * testing change channel - */ - // gmyth_recorder_spawntv_no_tvchain( livetv->recorder ); - } else { - - /* - * check for the program info in the TV program chain could be - * obtained from the MythTV MySQL database - */ - - /* - * Reload all TV chain from Mysql database. - */ - gmyth_tvchain_reload_all(livetv->tvchain); - - if (livetv->tvchain == NULL) { - res = FALSE; - goto error; - } - - /* - * Get program info from database using chanid and starttime - */ - livetv->proginfo = - gmyth_tvchain_get_program_at(livetv->tvchain, - tvchain_curr_index++); - if (livetv->proginfo == NULL) { - gmyth_debug("LiveTV not successfully started.\n"); - res = FALSE; - goto error; - } else { - res = TRUE; - gmyth_debug - ("GMythLiveTV: All requests to backend to start TV were OK. [%s]\n", - livetv->proginfo->pathname->str); - } - - } - - livetv->uri = - (GMythURI *) gmyth_backend_info_get_uri(livetv->backend_info); - - g_mutex_unlock(livetv->mutex); - - if (!gmyth_livetv_monitor_handler_start(livetv)) { - res = FALSE; - gmyth_debug("LiveTV MONITOR handler error on setup!"); - goto error; - } - - livetv->setup_done = TRUE; - - return res; - - error: - g_mutex_unlock(livetv->mutex); - - gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__); - - res = FALSE; - - if (livetv->local_hostname != NULL) { - g_string_free(livetv->local_hostname, TRUE); - livetv->local_hostname = NULL; - } - - gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__); - - if (livetv->recorder != NULL) { - g_object_unref(livetv->recorder); - livetv->recorder = NULL; - } - - gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__); - - if (livetv->tvchain != NULL) { - g_object_unref(livetv->tvchain); - livetv->tvchain = NULL; - } - - gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__); - - if (livetv->proginfo != NULL) { - g_object_unref(livetv->proginfo); - livetv->proginfo = NULL; - } - - gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__); - - if (livetv->monitor != NULL) { - g_object_unref(livetv->monitor); - livetv->monitor = NULL; - } - - - gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__); - - return res; - -} - -/** - * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, - * sets the channel name, and gets the first program info about the - * actual recording - * - * @param live_tv the GMythLiveTV instance - * @param channel the channel name, in numerical format - * @param backend_info the GMythBackendInfo describing the remote server - * - * @return true if the LiveTV's recorder instance configuration - * had been concluded succcesfully - */ -static gboolean -gmyth_livetv_setup_recorder(GMythLiveTV * livetv, gint channel) -{ - return gmyth_livetv_setup_recorder_channel_name(livetv, - (channel != - -1) ? - g_strdup_printf("%d", - channel) - : NULL); -} - -/** - * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, - * sets the channel name (numerical format), and gets the first program info about the - * actual recording - * - * @param live_tv the GMythLiveTV instance - * @param channel the channel name, in numerical format - * @param backend_info the GMythBackendInfo describing the remote server - * - * @return true if the LiveTV's recorder instance configuration - * had been concluded succcesfully - */ -gboolean -gmyth_livetv_channel_setup(GMythLiveTV * livetv, gint channel) -{ - return gmyth_livetv_setup_recorder(livetv, channel); -} - -/** - * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, - * sets the channel name (string format), and gets the first program info about the - * actual recording - * - * @param live_tv the GMythLiveTV instance - * @param channel the channel name, in numerical format - * @param backend_info the GMythBackendInfo describing the remote server - * - * @return true if the LiveTV's recorder instance configuration - * had been concluded succcesfully - */ -gboolean -gmyth_livetv_channel_name_setup(GMythLiveTV * livetv, gchar * channel) -{ - return gmyth_livetv_setup_recorder_channel_name(livetv, channel); -} - -/** - * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, - * and gets the first program info about the actual recording - * (doesn't changes the channel). - * - * @param live_tv the GMythLiveTV instance - * @param backend_info the GMythBackendInfo describing the remote server - * - * @return true if the LiveTV's recorder instance configuration - * had been concluded succcesfully - */ -gboolean -gmyth_livetv_setup(GMythLiveTV * livetv) -{ - return gmyth_livetv_setup_recorder(livetv, -1); -} - -/** - * Gets the next program info from this GMythLiveTV session. - * - * @param live_tv the GMythLiveTV instance - * - * @return true if the next program info could be got - */ -gboolean -gmyth_livetv_next_program_chain(GMythLiveTV * livetv) -{ - gboolean res = TRUE; - GMythProgramInfo *prog_info = NULL; - - if (!livetv->setup_done) { - gmyth_debug("Call the setup function first!"); - goto error; - } - - gmyth_debug("Current ProgramInfo...\n"); - prog_info = gmyth_recorder_get_current_program_info(livetv->recorder); - - if (prog_info != NULL) { - livetv->proginfo = prog_info; - } else { - gmyth_debug - ("ProgramInfo equals to NULL!!! Getting the next program info..."); - prog_info = - gmyth_recorder_get_next_program_info(livetv->recorder, - BROWSE_DIRECTION_RIGHT); - livetv->proginfo = prog_info; - } - /* - * prints program info data text - */ - gmyth_program_info_print(prog_info); - - if (prog_info != NULL) { - res = TRUE; - livetv->proginfo = prog_info; - gmyth_debug - ("GMythLiveTV: All requests to backend to start TV were OK, program info changed."); - } else { - gmyth_debug - ("[%s] LiveTV not successfully started on the next program chain.\n", - __FUNCTION__); - goto error; - } - - livetv->setup_done = TRUE; - - return res; - - error: - gmyth_debug("ERROR running LiveTV setup.\n"); - - res = FALSE; - - g_string_free(livetv->local_hostname, TRUE); - - if (livetv->recorder != NULL) { - g_object_unref(livetv->recorder); - livetv->recorder = NULL; - } - - if (livetv->tvchain != NULL) { - g_object_unref(livetv->tvchain); - livetv->tvchain = NULL; - } - - if (livetv->proginfo != NULL) { - g_object_unref(livetv->proginfo); - livetv->proginfo = NULL; - } - - return res; -} - -/** - * Creates a File Transfer session, using all configuration information - * got from the actual program info. - * - * @param live_tv the GMythLiveTV instance - * - * @return the actual GMythFileTransfer instance, generated using the - * data got from the actual program info. - */ -GMythFile* -gmyth_livetv_create_file_transfer(GMythLiveTV * livetv) -{ - // GMythURI* uri = NULL; - - if (NULL == livetv) - return NULL; - - if (!livetv->setup_done) { - gmyth_debug - ("Error: You must do the LiveTV setup, just before generating the FileTransfer from LiveTV source!"); - return NULL; - } - - if (livetv->proginfo != NULL) - gmyth_debug("URI path (from program info) = %s.\n", - livetv->proginfo->pathname->str); - else - gmyth_debug("URI path (from URI) = %s.\n", livetv->uri->uri->str); - - g_mutex_lock(livetv->mutex); - - if (livetv->file != NULL) { - /* - * gmyth_file_transfer_close( livetv->file ); - */ - g_object_unref(livetv->file); - livetv->file = NULL; - } - - if (livetv->uri != NULL) { - gmyth_debug - ("URI is not NULL, creating from the ProgramInfo pathname... (%s)", - livetv->proginfo->pathname->str); - livetv->uri->path = g_string_erase(livetv->uri->path, 0, -1); - livetv->uri->path = - g_string_new(g_strrstr(livetv->proginfo->pathname->str, "/")); - } else { - gmyth_debug - ("URI is NULL, creating from the ProgramInfo pathname... (%s)", - livetv->proginfo->pathname->str); - livetv->uri = - gmyth_uri_new_with_value(livetv->proginfo->pathname->str); - } - - if (NULL == livetv->uri) { - gmyth_debug("Couldn't parse the URI to start LiveTV! [ uri = %s ]", - livetv->proginfo->pathname->str); - goto done; - } - - if (gmyth_uri_is_local_file(livetv->uri)) - livetv->file = - GMYTH_FILE(gmyth_file_local_new(livetv->backend_info)); - else { - livetv->file = - GMYTH_FILE(gmyth_file_transfer_new(livetv->backend_info)); - /* - * gmyth_file_transfer_settimeout( - * GMYTH_FILE_TRANSFER(livetv->file), TRUE ); - */ - } - - if (NULL == livetv->file) { - gmyth_debug - ("Error: couldn't create the FileTransfer from LiveTV source!"); - goto done; - } - - g_object_ref(livetv->file); - -done: - g_mutex_unlock(livetv->mutex); - return livetv->file; -} - -/** - * Stops this LiveTV session. - * - * @param live_tv the GMythLiveTV instance - */ -void -gmyth_livetv_stop_playing(GMythLiveTV * livetv) -{ - gmyth_debug("Stopping the LiveTV...\n"); - - if (livetv->is_livetv) { - if (!gmyth_recorder_stop_livetv(livetv->recorder)) { - gmyth_debug("[%s] Error while stoping remote encoder", - __FUNCTION__); - } - - if (!gmyth_recorder_finish_recording(livetv->recorder)) { - gmyth_debug - ("[%s] Error while finishing recording on remote encoder", - __FUNCTION__); - } - } -} - -gboolean -gmyth_livetv_is_playing(GMythLiveTV * livetv) -{ - return TRUE; -} - -void -gmyth_livetv_start_playing(GMythLiveTV * livetv) -{ - - // TODO - -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_livetv.h --- a/gmyth/src/gmyth_livetv.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_livetv.h - * - * @brief

GMythLiveTV starts a remote TV session with the MythTV backend. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Rosfran Lins Borges - * -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GMYTH_LIVETV_H_ -#define GMYTH_LIVETV_H_ - -#include -#include - -#include "gmyth_recorder.h" -#include "gmyth_tvchain.h" -#include "gmyth_monitor_handler.h" -#include "gmyth_file.h" -#include "gmyth_programinfo.h" -#include "gmyth_backendinfo.h" - -G_BEGIN_DECLS -#define GMYTH_LIVETV_TYPE (gmyth_livetv_get_type ()) -#define GMYTH_LIVETV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_LIVETV_TYPE, GMythLiveTV)) -#define GMYTH_LIVETV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_LIVETV_TYPE, GMythLiveTVClass)) -#define IS_GMYTH_LIVETV(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_LIVETV_TYPE)) -#define IS_GMYTH_LIVETV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_LIVETV_TYPE)) -#define GMYTH_LIVETV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_LIVETV_TYPE, GMythLiveTVClass)) -typedef struct _GMythLiveTV GMythLiveTV; -typedef struct _GMythLiveTVClass GMythLiveTVClass; - -struct _GMythLiveTVClass { - GObjectClass parent_class; - - /* - * callbacks - */ -}; - -struct _GMythLiveTV { - GObject parent; - - GMythSocket *socket; - - GString *local_hostname; - - GMythBackendInfo *backend_info; - - GMythRecorder *recorder; - GMythTVChain *tvchain; - GMythProgramInfo *proginfo; - - GMythFile *file; - - GMythMonitorHandler *monitor; - GMythURI *uri; - - gboolean is_livetv; - gboolean setup_done; - - GMutex *mutex; - gboolean disposed; -}; - -GType gmyth_livetv_get_type(void); - -GMythLiveTV *gmyth_livetv_new(GMythBackendInfo * backend_info); - -void gmyth_livetv_start_playing(GMythLiveTV * livetv); -void gmyth_livetv_stop_playing(GMythLiveTV * livetv); - -gboolean gmyth_livetv_setup(GMythLiveTV * livetv); -gboolean gmyth_livetv_channel_setup(GMythLiveTV * livetv, - gint channel); -gboolean gmyth_livetv_channel_name_setup(GMythLiveTV * livetv, - gchar * channel); -gboolean gmyth_livetv_next_program_chain(GMythLiveTV * livetv); - -GMythFile *gmyth_livetv_create_file_transfer(GMythLiveTV * livetv); - -gboolean gmyth_livetv_monitor_handler_start(GMythLiveTV * livetv); -void gmyth_livetv_monitor_handler_stop(GMythLiveTV * livetv); - -G_END_DECLS -#endif /* GMYTH_LIVETV_H_ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_marshal.list --- a/gmyth/src/gmyth_marshal.list Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -VOID:INT,STRING -VOID:INT,POINTER diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_monitor_handler.c --- a/gmyth/src/gmyth_monitor_handler.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,593 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_monitor_handler.c - * - * @brief

GMythMonitorHandler deals with the streaming media events remote/local - * that are sent to the MythTV frontend. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Rosfran Lins Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * GStreamer MythTV plug-in properties: - * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv] - * - path (qurl - remote file to be opened) - * - port number * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "gmyth_marshal.h" - -#include "gmyth_monitor_handler.h" -#include "gmyth_debug.h" - -#define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER " - -#define GMYTHTV_VERSION 30 - -#define GMYTHTV_TRANSFER_MAX_WAITS 700 - -#define GMYTHTV_BUFFER_SIZE 8*1024 - -#ifdef GMYTHTV_ENABLE_DEBUG -#define GMYTHTV_ENABLE_DEBUG 1 -#else -#undef GMYTHTV_ENABLE_DEBUG -#endif - -/* - * this NDEBUG is to maintain compatibility with GMyth library - */ -#ifndef NDEBUG -#define GMYTHTV_ENABLE_DEBUG 1 -#endif - -static gboolean gmyth_monitor_handler_listener (GIOChannel *io_channel, - GIOCondition condition, - gpointer data); - -static void gmyth_monitor_handler_default_listener(GMythMonitorHandler - * monitor, - gint msg_code, - gchar * message); - -static void gmyth_monitor_handler_class_init(GMythMonitorHandlerClass * - klass); -static void gmyth_monitor_handler_init(GMythMonitorHandler * object); - -static void gmyth_monitor_handler_dispose(GObject * object); -static void gmyth_monitor_handler_finalize(GObject * object); - -static gboolean gmyth_connect_to_backend_monitor(GMythMonitorHandler * - monitor); - -static gboolean gmyth_monitor_handler_setup(GMythMonitorHandler * monitor, - GIOChannel * channel); - -void gmyth_monitor_handler_close(GMythMonitorHandler * monitor); - -G_DEFINE_TYPE(GMythMonitorHandler, gmyth_monitor_handler, G_TYPE_OBJECT); - -static void -gmyth_monitor_handler_class_init(GMythMonitorHandlerClass * klass) -{ - GObjectClass *gobject_class; - GMythMonitorHandlerClass *gmonitor_class; - - gobject_class = (GObjectClass *) klass; - gmonitor_class = (GMythMonitorHandlerClass *) gobject_class; - - gobject_class->dispose = gmyth_monitor_handler_dispose; - gobject_class->finalize = gmyth_monitor_handler_finalize; - - gmonitor_class->backend_events_handler_signal_id = - g_signal_new("backend-events-handler", - G_TYPE_FROM_CLASS(gmonitor_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | - G_SIGNAL_NO_HOOKS, 0, NULL, NULL, - gmyth_marshal_VOID__INT_STRING, G_TYPE_NONE, 2, - G_TYPE_INT, G_TYPE_STRING); - - gmonitor_class->backend_events_handler = - gmyth_monitor_handler_default_listener; - -} - -static void -gmyth_monitor_handler_init(GMythMonitorHandler * monitor) -{ - g_return_if_fail(monitor != NULL); - - monitor->event_sock = NULL; - monitor->hostname = NULL; - monitor->port = 0; - monitor->actual_index = 0; - monitor->allow_msgs_listener = FALSE; - /* - * it is used for signalizing the event socket consumer thread - */ - monitor->mutex = g_mutex_new(); -} - -static void -gmyth_monitor_handler_dispose(GObject * object) -{ - GMythMonitorHandler *monitor = GMYTH_MONITOR_HANDLER(object); - - gmyth_monitor_handler_close(monitor); - - monitor->allow_msgs_listener = FALSE; - - if (monitor->io_source != 0) { - g_source_remove (monitor->io_source); - monitor->io_source = 0; - } - - /* - * mutex to control access to the event socket consumer thread - */ - if (monitor->mutex != NULL) { - // g_mutex_unlock( monitor->mutex ); - g_mutex_free(monitor->mutex); - monitor->mutex = NULL; - } - - if (monitor->event_sock != NULL) { - g_object_unref(monitor->event_sock); - monitor->event_sock = NULL; - } - - if (monitor->hostname != NULL) { - g_free(monitor->hostname); - monitor->hostname = NULL; - } - - - if (monitor->backend_msgs != NULL) { - g_hash_table_destroy(monitor->backend_msgs); - monitor->backend_msgs = NULL; - } - - /* - * if ( io_watcher_cond != NULL ) { g_cond_free( io_watcher_cond ); - * io_watcher_cond = NULL; } - */ - - - G_OBJECT_CLASS(gmyth_monitor_handler_parent_class)->dispose(object); -} - -static void -gmyth_monitor_handler_finalize(GObject * object) -{ - g_signal_handlers_destroy(object); - - G_OBJECT_CLASS(gmyth_monitor_handler_parent_class)->finalize(object); -} - -/** - * Creates a new instance of GMyth Monitor Handler. - * - * @return a new instance of the Monitor Handler. - */ -GMythMonitorHandler * -gmyth_monitor_handler_new(void) -{ - GMythMonitorHandler *monitor = - GMYTH_MONITOR_HANDLER(g_object_new - (GMYTH_MONITOR_HANDLER_TYPE, FALSE)); - - return monitor; -} - -/** - * Acquire the mutex to have access to the IO Watcher listener. - * - * @param monitor The GMythMonitorHandler instance. - * @param do_wait Tells the IO Watcher to wait on the GCond. (obsolete) - * - * @return true, if the access to IO Watcher was acquired. - */ -static gboolean -myth_control_acquire_context(GMythMonitorHandler * monitor, - gboolean do_wait) -{ - - gboolean ret = TRUE; - - g_mutex_lock(monitor->mutex); - - return ret; - -} - -/** - * Release the mutex to have access to the IO Watcher listener. - * - * @param monitor The GMythMonitorHandler instance. - * - * @return true, if the access to IO Watcher was released. - */ -static gboolean -myth_control_release_context(GMythMonitorHandler * monitor) -{ - - gboolean ret = TRUE; - - g_mutex_unlock(monitor->mutex); - - return ret; -} - -void -gmyth_monitor_handler_close(GMythMonitorHandler * monitor) -{ - monitor->allow_msgs_listener = FALSE; - -#if 0 - if (monitor->monitor_th != NULL) { - g_thread_pool_free(monitor->monitor_th, TRUE, FALSE); - // g_thread_exit( monitor->monitor_th ); - /* - * if ( monitor->monitor_th != NULL ) g_object_unref( - * monitor->monitor_th ); - */ - monitor->monitor_th = NULL; - } - - if (monitor->event_sock != NULL) { - gmyth_socket_close_connection(monitor->event_sock); - } -#endif - -} - -/** - * Opens connection the the Monitor socket on MythTV backend server, - * where all status messages are notified to the client. - * - * @param monitor The GMythMonitorHandler instance. - * @param hostname The remote host name of the MythTV backend server. - * @param port The remote port number of the MythTV backend server. - * - * @return true, if the connection was successfully opened. - */ -gboolean -gmyth_monitor_handler_open(GMythMonitorHandler * monitor, - const gchar * hostname, gint port) -{ - gboolean ret = TRUE; - - g_return_val_if_fail(hostname != NULL, FALSE); - - if (monitor->hostname != NULL) { - g_free(monitor->hostname); - monitor->hostname = NULL; - } - - monitor->hostname = g_strdup(hostname); - monitor->port = port; - - gmyth_debug("Monitor event socket --- hostname: %s, port %d\n", - monitor->hostname, monitor->port); - - if (monitor->event_sock != NULL) { - g_object_unref(monitor->event_sock); - monitor->event_sock = NULL; - } - - /* - * configure the event socket - */ - if (!gmyth_connect_to_backend_monitor(monitor)) { - gmyth_debug("Connection to backend failed (Event Socket)!"); - ret = FALSE; - } else { - gmyth_debug ("Remote monitor event socket had been succesfully create"); - } - - return ret; -} - -/** - * Reads the data got from the connection to the Monitor socket, - * and looks for some important status messages. - * - * @param monitor The GMythMonitorHandler instance. - * @param strlist The GMythStringList instance got from the Monitor remote socket. - * @param back_msg_action A string pointer to the status message detailed description. - * - * @return The backend status message code ID. - */ -static gint -gmyth_monitor_handler_is_backend_message(GMythMonitorHandler * monitor, - GMythStringList * strlist, - gchar ** back_msg_action) -{ - gint msg_type = GMYTH_BACKEND_NO_MESSAGE; - GString *back_msg = NULL; - - if (gmyth_string_list_length(strlist) > 0) { - - back_msg = gmyth_string_list_get_string(strlist, 0); - if (back_msg != NULL && back_msg->str != NULL && - strstr(back_msg->str, "BACKEND") != NULL) { - gmyth_debug("MONITOR HANDLER - Received backend message = %s", - back_msg->str); - *back_msg_action = - gmyth_string_list_get_char_array(strlist, 1); - - if (back_msg_action != NULL) { - - if (g_strstr_len - (*back_msg_action, strlen(*back_msg_action), - "LIVETV_CHAIN") - || g_strstr_len(*back_msg_action, - strlen(*back_msg_action), - "RECORDING_LIST_CHANGE") - || g_strstr_len(*back_msg_action, - strlen(*back_msg_action), - "SCHEDULE_CHANGE") - || g_strstr_len(*back_msg_action, - strlen(*back_msg_action), - "LIVETV_WATCH")) { - gmyth_debug - ("MONITOR: message type == GMYTH_BACKEND_PROGRAM_INFO_CHANGED, msg = %s", - *back_msg_action); - msg_type = GMYTH_BACKEND_PROGRAM_INFO_CHANGED; - } else if (g_strstr_len - (*back_msg_action, strlen(*back_msg_action), - "DONE_RECORDING")) { - gmyth_debug - ("MONITOR: message type == GMYTH_BACKEND_DONE_RECORDING, msg = %s", - *back_msg_action); - msg_type = GMYTH_BACKEND_DONE_RECORDING; - } else if (g_strstr_len - (*back_msg_action, strlen(*back_msg_action), - "QUIT")) { - gmyth_debug - ("MONITOR: message type == GMYTH_BACKEND_STOP_LIVETV, msg = %s", - *back_msg_action); - msg_type = GMYTH_BACKEND_STOP_LIVETV; - } - - /* - * g_hash_table_insert ( monitor->backend_msgs, - * &(monitor->actual_index), *back_msg_action ); - */ - - } - /* - * if - */ - } - /* - * if - */ - if (back_msg != NULL) { - g_string_free(back_msg, TRUE); - back_msg = NULL; - } - - } /* if - Does Monitor got any message from - * * * backend? */ - else { - *back_msg_action = g_strdup(""); - } - - return msg_type; - -} - -static void -gmyth_monitor_handler_default_listener(GMythMonitorHandler * monitor, - gint msg_code, gchar * message) -{ - // assert( message!= NULL ); - gmyth_debug("DEFAULT Signal handler ( msg = %s, code = %d )\n", - message, msg_code); -} - -static void -gmyth_monitor_handler_print(GString * str, gpointer ptr) -{ - gmyth_debug("Backend message event: %s --- ", str->str); -} - -/** - * Opens connection the the Monitor socket on MythTV backend server, - * where all status messages are notified to the client. - * - * @param data Pointer to the GMythMonitorHandler. - * - * @return Pointer to a gboolean true value, if the data was - * successfully read. - */ -static gboolean -gmyth_monitor_handler_listener (GIOChannel *io_channel, - GIOCondition io_cond, - gpointer data) -{ - GMythMonitorHandler *monitor; - guint recv = 0; - gsize len = 0; - GMythStringList *strlist = NULL; - gint bytes_sent = 0; - - monitor = (GMythMonitorHandler *) data; - - gmyth_debug("Entering MONITOR handler listener..."); - - myth_control_acquire_context(monitor, TRUE); - - if (((io_cond & G_IO_HUP) != 0) || - ((io_cond & G_IO_ERR) != 0)) { - goto clean_up; - } - - - gmyth_debug("Listening on Monitor socket...!\n"); - strlist = gmyth_string_list_new(); - - len = gmyth_socket_read_stringlist(monitor->event_sock, strlist); - if ((len > 0) && strlist != NULL && gmyth_string_list_length(strlist) > 0) { - gchar *back_msg_action; - gint msg_type; - - bytes_sent = gmyth_string_list_get_int(strlist, 0); - // on backend error - gmyth_debug ("received data buffer from IO event channel... %d strings gone!\n", len); - recv += len; - - /* - * debug purpose: prints out all the string list - * elements - */ - g_list_foreach(strlist->glist, - (GFunc) gmyth_monitor_handler_print, - NULL); - - back_msg_action = g_new0(gchar, 1); - msg_type = gmyth_monitor_handler_is_backend_message(monitor, - strlist, - &back_msg_action); - - if (msg_type != GMYTH_BACKEND_NO_MESSAGE) { - g_signal_emit(monitor, - GMYTH_MONITOR_HANDLER_GET_CLASS(monitor)->backend_events_handler_signal_id, - 0, msg_type, back_msg_action); - } - - if (back_msg_action != NULL) - g_free(back_msg_action); - - g_object_unref(strlist); - } - -clean_up: - myth_control_release_context(monitor); - return TRUE; -} - -/** - * Opens connection events' socket the the Monitor socket on - * MythTV backend server. - * - * @param monitor The GMythMonitorHandler instance. - * - * @return true, if the socket was successfully opened. - */ -static gboolean -gmyth_connect_to_backend_monitor(GMythMonitorHandler * monitor) -{ - gboolean ret = TRUE; - - monitor->event_sock = gmyth_socket_new(); - - /* - * Connects the socket, send Mythtv ANN Monitor and verify Mythtv - * protocol version - */ - if (!gmyth_socket_connect_to_backend_events(monitor->event_sock, - monitor->hostname, - monitor->port, FALSE)) { - g_object_unref(monitor->event_sock); - monitor->event_sock = NULL; - ret = FALSE; - } - - return ret; -} - -/** - * Opens connection the the Monitor socket on MythTV backend server, - * where all status messages are notified to the client. - * - * @param monitor The GMythMonitorHandler instance. - * @param channel The GIOChannel instance to the Monitor socket. - * - * @return Pointer to the boolean value, and it is true only if the - * GMythMonitorHandler could be configured. - */ -static gboolean -gmyth_monitor_handler_setup(GMythMonitorHandler * monitor, - GIOChannel * channel) -{ - gboolean ret = TRUE; - - if (channel != NULL) { - monitor->allow_msgs_listener = TRUE; - monitor->io_source = g_io_add_watch (channel, G_IO_IN | G_IO_ERR | G_IO_HUP, - gmyth_monitor_handler_listener, - monitor); - } else { - ret = FALSE; - } - return ret; -} - -/** - * Starts the MonitorHandler thread to the GIOWatcher. - * - * @param monitor The GMythMonitorHandler instance. - * - * @return true, if the MonitorHandler was started. - */ -gboolean -gmyth_monitor_handler_start(GMythMonitorHandler * monitor) -{ - gboolean ret = TRUE; - - if (!(ret = g_thread_supported())) { - gmyth_debug("Thread system wasn't initialized, starting NOW!!!"); - g_thread_init(NULL); - } - - ret = - gmyth_monitor_handler_setup(monitor, - monitor->event_sock->sd_io_ch); - if (ret) { - gmyth_debug - ("\n[%s]\tOK! Starting listener on the MONITOR event socket...[thread location = %p]\n", - __FUNCTION__, g_thread_self()); - } else { - gmyth_debug - ("\n[%s]\tERROR! Coudn't start listener on the MONITOR event socket...[thread location = %p]\n", - __FUNCTION__, g_thread_self()); - ret = FALSE; - } - - gmyth_debug - ("[%s] Watch listener function over the IO control channel? %s!!!\n", - __FUNCTION__, (ret == TRUE ? "YES" : "NO")); - - return ret; -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_monitor_handler.h --- a/gmyth/src/gmyth_monitor_handler.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,122 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_monitor_handler.h - * - * @brief

GMythMonitorHandler deals with the streaming media events remote/local - * that are sent to the MythTV frontend. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Rosfran Lins Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __GMYTH_MONITOR_HANDLER_H__ -#define __GMYTH_MONITOR_HANDLER_H__ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "gmyth_socket.h" -#include "gmyth_uri.h" - -G_BEGIN_DECLS -#define GMYTH_MONITOR_HANDLER_TYPE (gmyth_monitor_handler_get_type ()) -#define GMYTH_MONITOR_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_MONITOR_HANDLER_TYPE, GMythMonitorHandler)) -#define GMYTH_MONITOR_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_MONITOR_HANDLER_TYPE, GMythMonitorHandlerClass)) -#define IS_GMYTH_MONITOR_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_MONITOR_HANDLER_TYPE)) -#define IS_GMYTH_MONITOR_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_MONITOR_HANDLER_TYPE)) -#define GMYTH_MONITOR_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_MONITOR_HANDLER_TYPE, GMythMonitorHandlerClass)) -#define GMYTHTV_MONITOR_HANDLER_READ_ERROR -314 - enum { - GMYTH_BACKEND_NO_MESSAGE = 0, - GMYTH_BACKEND_PROGRAM_INFO_CHANGED, - GMYTH_BACKEND_DONE_RECORDING, - GMYTH_BACKEND_STOP_LIVETV -}; - -typedef struct _GMythMonitorHandler GMythMonitorHandler; -typedef struct _GMythMonitorHandlerClass GMythMonitorHandlerClass; - -struct _GMythMonitorHandlerClass { - GObjectClass parent_class; - - /* - * callbacks - */ - guint backend_events_handler_signal_id; - - /* - * signal default handlers - */ - void (*backend_events_handler) (GMythMonitorHandler * - monitor, gint msg_code, - gchar * message); -}; - -struct _GMythMonitorHandler { - GObject parent; - - /* - * MythTV version number - */ - gint mythtv_version; - - /* - * socket descriptors - */ - GMythSocket *event_sock; - - //gpointer(*gmyth_monitor_handler_listener) (gpointer data); - - gchar *hostname; - gint port; - - gint64 actual_index; - - gboolean allow_msgs_listener; - - /* - * stores the messages coming from the backend - */ - GHashTable *backend_msgs; - - GMutex *mutex; - guint io_source; -}; - -GType gmyth_monitor_handler_get_type(void); - -GMythMonitorHandler *gmyth_monitor_handler_new(void); - -gboolean gmyth_monitor_handler_open(GMythMonitorHandler * monitor, - const gchar * hostname, - gint port); - -gboolean gmyth_monitor_handler_start(GMythMonitorHandler * monitor); - -void gmyth_monitor_handler_close(GMythMonitorHandler * monitor); - -G_END_DECLS -#endif /* __GMYTH_MONITOR_HANDLER_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_programinfo.c --- a/gmyth/src/gmyth_programinfo.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,582 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_programinfo.c - * - * @brief

GMythProgramInfo representing the program info, with the - * configuration data to the actual remote file in the TV chain. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Rosfran Borges - * @author Leonardo Sobral Cunha - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "gmyth_programinfo.h" -#include "gmyth_util.h" -#include "gmyth_debug.h" - -static void gmyth_program_info_class_init(GMythProgramInfoClass * - klass); -static void gmyth_program_info_init(GMythProgramInfo * object); - -static void gmyth_program_info_dispose(GObject * object); -static void gmyth_program_info_finalize(GObject * object); - -G_DEFINE_TYPE(GMythProgramInfo, gmyth_program_info, G_TYPE_OBJECT) - static const gchar *gmyth_program_info_non_null_value(const GString * - str); - - static void gmyth_program_info_class_init(GMythProgramInfoClass * - klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->dispose = gmyth_program_info_dispose; - gobject_class->finalize = gmyth_program_info_finalize; -} - -static void -gmyth_program_info_init(GMythProgramInfo * gmyth_program_info) -{ - gmyth_program_info->chancommfree = 0; - - /** A flag informing if the program has video or not. */ - gmyth_program_info->isVideo = FALSE; - gmyth_program_info->lenMins = 0; - - gmyth_program_info->stars = 0.0f; - gmyth_program_info->repeat = 0; - - gmyth_program_info->hasAirDate = FALSE; - - gmyth_program_info->spread = 0; - gmyth_program_info->startCol = 0; - - gmyth_program_info->recpriority2 = 0; - gmyth_program_info->reactivate = 0; - - gmyth_program_info->recordid = 0; - gmyth_program_info->parentid = 0; - - /** The backend video source id associated to this program.*/ - gmyth_program_info->sourceid = 0; - /** the backend input id associated to this program.*/ - gmyth_program_info->inputid = 0; - /** The backend card id associated to this program.*/ - gmyth_program_info->cardid = 0; - gmyth_program_info->shareable = FALSE; - gmyth_program_info->duplicate = FALSE; - - gmyth_program_info->findid = 0; - - gmyth_program_info->programflags = 0; - gmyth_program_info->transcoder = 0; - - gmyth_program_info->recpriority = 0; - - /** The file size of the recorded program.*/ - gmyth_program_info->filesize = -1; -} - -static void -gmyth_program_info_dispose(GObject * object) -{ - GMythProgramInfo *gmyth_program_info = GMYTH_PROGRAM_INFO(object); - - /** The program start time. */ - g_free(gmyth_program_info->startts); - - /** The program end time. */ - g_free(gmyth_program_info->endts); - - /** The recording schedule start time. */ - g_free(gmyth_program_info->recstartts); - - /** The recording schedule end time */ - g_free(gmyth_program_info->recendts); - - /** The program title. */ - if (gmyth_program_info->title != NULL) { - g_string_free(gmyth_program_info->title, TRUE); - gmyth_program_info->title = NULL; - } - - /** The program subtitle. */ - if (gmyth_program_info->subtitle != NULL) { - g_string_free(gmyth_program_info->subtitle, TRUE); - gmyth_program_info->subtitle = NULL; - } - - /** The program description. */ - if (gmyth_program_info->description != NULL) { - g_string_free(gmyth_program_info->description, TRUE); - gmyth_program_info->description = NULL; - } - - /** The program category. */ - if (gmyth_program_info->category != NULL) { - g_string_free(gmyth_program_info->category, TRUE); - gmyth_program_info->category = NULL; - } - - if (gmyth_program_info->chanstr != NULL) { - g_string_free(gmyth_program_info->chanstr, TRUE); - gmyth_program_info->chanstr = NULL; - } - - if (gmyth_program_info->chansign != NULL) { - g_string_free(gmyth_program_info->chansign, TRUE); - gmyth_program_info->chansign = NULL; - } - - /** The associated channel name. */ - if (gmyth_program_info->channame != NULL) { - g_string_free(gmyth_program_info->channame, TRUE); - gmyth_program_info->channame = NULL; - } - - if (gmyth_program_info->chanOutputFilters != NULL) { - g_string_free(gmyth_program_info->chanOutputFilters, TRUE); - gmyth_program_info->chanOutputFilters = NULL; - } - - if (gmyth_program_info->seriesid != NULL) { - g_string_free(gmyth_program_info->seriesid, TRUE); - gmyth_program_info->chanOutputFilters = NULL; - } - - /** The program unique id. */ - if (gmyth_program_info->program_id != NULL) { - g_string_free (gmyth_program_info->program_id, TRUE); - gmyth_program_info->program_id = NULL; - } - - if (gmyth_program_info->catType != NULL) { - g_string_free(gmyth_program_info->catType, TRUE); - gmyth_program_info->catType = NULL; - } - - if (gmyth_program_info->sortTitle != NULL) { - g_string_free(gmyth_program_info->sortTitle, TRUE); - gmyth_program_info->sortTitle = NULL; - } - - if (gmyth_program_info->year != NULL) { - g_string_free(gmyth_program_info->year, TRUE); - gmyth_program_info->year = NULL; - } - - g_free(gmyth_program_info->originalAirDate); - - g_free(gmyth_program_info->lastmodified); - - g_free(gmyth_program_info->lastInUseTime); - - if (gmyth_program_info->schedulerid != NULL) { - g_string_free(gmyth_program_info->schedulerid, TRUE); - gmyth_program_info->schedulerid = NULL; - } - - if (gmyth_program_info->recgroup != NULL) { - g_string_free(gmyth_program_info->recgroup, TRUE); - gmyth_program_info->recgroup = NULL; - } - - if (gmyth_program_info->playgroup != NULL) { - g_string_free(gmyth_program_info->playgroup, TRUE); - gmyth_program_info->playgroup = NULL; - } - - /** The file name of the recorded program.*/ - if (gmyth_program_info->pathname != NULL) { - g_string_free(gmyth_program_info->pathname, TRUE); - gmyth_program_info->pathname = NULL; - } - - if (gmyth_program_info->hostname != NULL) { - g_string_free(gmyth_program_info->hostname, TRUE); - gmyth_program_info->hostname = NULL; - } - - G_OBJECT_CLASS(gmyth_program_info_parent_class)->dispose(object); -} - -static void -gmyth_program_info_finalize(GObject * object) -{ - g_signal_handlers_destroy(object); - - G_OBJECT_CLASS(gmyth_program_info_parent_class)->finalize(object); -} - -/** - * Creates a new instance of GMythProgramInfo. - * - * @return a new instance of GMythProgramInfo. - */ -GMythProgramInfo * -gmyth_program_info_new(void) -{ - GMythProgramInfo *program_info = - GMYTH_PROGRAM_INFO(g_object_new(GMYTH_PROGRAM_INFO_TYPE, NULL)); - - return program_info; -} - -/** - * Converts an instance of a GMythProgramInfo, to a GMythStringList. - * - * @param prog A GMythProgramInfo instance. - * @param slist The GMythStringList to be passed to this function, in order to - * give the responsibility of the string list creation to the - * API user. - * - * @return a GMythStringList with the program info fields. - */ -GMythStringList * -gmyth_program_info_to_string_list(GMythProgramInfo * prog, - GMythStringList * slist) -{ - g_return_val_if_fail(prog != NULL, NULL); - g_return_val_if_fail(slist != NULL, NULL); - - gmyth_string_list_append_string(slist, prog->title); /* 0 */ - gmyth_string_list_append_string(slist, prog->subtitle); /* 1 */ - gmyth_string_list_append_string(slist, prog->description); /* 2 */ - gmyth_string_list_append_string(slist, prog->category); /* 3 */ - gmyth_string_list_append_int (slist, prog->channel_id); /* 4 */ - gmyth_string_list_append_string(slist, prog->chanstr); /* 5 */ - gmyth_string_list_append_string(slist, prog->chansign); /* 6 */ - gmyth_string_list_append_string(slist, prog->channame); /* 7 */ - gmyth_string_list_append_string(slist, prog->pathname); /* 8 */ - gmyth_string_list_append_int64(slist, 0); /* 9 */ - - // fixme - // gmyth_string_list_append_int64 (slist, 100/*prog->filesize*/); /* 9 - // - // - // */ - // gmyth_string_list_append_int (slist, 0); /* 10 */ - - if (prog->startts) - gmyth_string_list_append_int(slist, prog->startts->tv_sec); /* 11 */// DATETIME_TO_LIST(startts) - else - gmyth_string_list_append_int(slist, 0); - - if (prog->endts) - gmyth_string_list_append_int(slist, prog->endts->tv_sec); /* 12 */// DATETIME_TO_LIST(endts) - else - gmyth_string_list_append_int(slist, 0); - - gmyth_string_list_append_int(slist, prog->duplicate); /* 13 */ - gmyth_string_list_append_int(slist, prog->shareable); /* 14 */ - gmyth_string_list_append_int(slist, prog->findid); /* 15 */ - gmyth_string_list_append_string(slist, prog->hostname); /* 16 */ - gmyth_string_list_append_int(slist, prog->sourceid); /* 17 */ - gmyth_string_list_append_int(slist, prog->cardid); /* 18 */ - gmyth_string_list_append_int(slist, prog->inputid); /* 19 */ - gmyth_string_list_append_int(slist, prog->recpriority); /* 20 */ - gmyth_string_list_append_int(slist, 0 /* prog->recstatus */ ); /* 21 */ - gmyth_string_list_append_int(slist, prog->recordid); /* 22 */ - gmyth_string_list_append_int(slist, 0 /* prog->rectype */ ); /* 23 */ - gmyth_string_list_append_int(slist, 0 /* prog->dupin */ ); /* 24 */ - gmyth_string_list_append_int(slist, 0 /* prog->dupmethod */ ); /* 25 */ - gmyth_string_list_append_int(slist, prog->recstartts != NULL ? prog->recstartts->tv_sec : 0); /* 26 - */// DATETIME_TO_LIST(recstartts) - gmyth_string_list_append_int(slist, prog->recendts != NULL ? prog->recendts->tv_sec : 0); /* 27 - */// DATETIME_TO_LIST(recendts) - gmyth_string_list_append_int(slist, prog->repeat); /* 28 */ - gmyth_string_list_append_int(slist, prog->programflags); /* 29 */ - gmyth_string_list_append_char_array(slist, "Default"); /* 30 */// prog->(recgroup - // - // - // != "") ? - // recgroup : - // "Default") - gmyth_string_list_append_int(slist, prog->chancommfree); /* 31 */ - gmyth_string_list_append_string(slist, prog->chanOutputFilters); /* 32 - */ - gmyth_string_list_append_string(slist, prog->seriesid); /* 33 */ - gmyth_string_list_append_string(slist, prog->program_id); /* 34 */ - gmyth_string_list_append_char_array(slist, ""); /* 35 */ - gmyth_string_list_append_int(slist, prog->lastmodified != NULL ? prog->lastmodified->tv_sec : 0); /* 36 - */// DATETIME_TO_LIST(lastmodified) - gmyth_string_list_append_int(slist, 0); /* 37 */// FLOAT_TO_LIST(stars) - gmyth_string_list_append_int(slist, prog->originalAirDate != NULL ? prog->originalAirDate->tv_sec : 0); /* 38 - */// DATETIME_TO_LIST(QDateTime(originalAirDate)) - gmyth_string_list_append_int(slist, prog->hasAirDate); /* 39 */ - gmyth_string_list_append_char_array(slist, "Default"); /* 40 */// prog->(playgroup - // - // - // != "") ? - // playgroup : - // "Default") - gmyth_string_list_append_int(slist, prog->recpriority2); /* 41 */ - - return slist; -} - -/** - * Converts an instance of a GMythStringList, to a GMythProgramInfo. - * - * @param slist The GMythStringList got from the MythTV backend server. - * @param pos The position in the GMythStringList to start getting the fields. - * - * @return a GMythProgramInfo representing the string list got from network. - */ -GMythProgramInfo * -gmyth_program_info_from_string_list_from_pos(GMythStringList * slist, - guint pos) -{ - GMythProgramInfo *prog = gmyth_program_info_new(); - - g_return_val_if_fail(slist != NULL && - gmyth_string_list_get_string(slist, pos) != NULL, - NULL); - - prog->title = gmyth_string_list_get_string(slist, pos); - prog->subtitle = gmyth_string_list_get_string(slist, pos + 1); - prog->description = gmyth_string_list_get_string(slist, pos + 2); - prog->category = gmyth_string_list_get_string(slist, pos + 3); - prog->channel_id = gmyth_string_list_get_int (slist, pos + 4); - prog->channame = gmyth_string_list_get_string(slist, pos + 5); - prog->chanstr = gmyth_string_list_get_string(slist, pos + 6); - prog->chansign = gmyth_string_list_get_string(slist, pos + 7); - prog->pathname = gmyth_string_list_get_string(slist, pos + 8); - - prog->filesize = gmyth_string_list_get_int64(slist, pos + 9); - - gmyth_debug("Prog info: [ %s, %s, %s, %s, %s, %s, %s, %s, %d ]\n", - gmyth_program_info_non_null_value(prog->title), - gmyth_program_info_non_null_value(prog->subtitle), - gmyth_program_info_non_null_value(prog->description), - gmyth_program_info_non_null_value(prog->category), - gmyth_program_info_non_null_value(prog->channame), - gmyth_program_info_non_null_value(prog->chanstr), - gmyth_program_info_non_null_value(prog->chansign), - gmyth_program_info_non_null_value(prog->pathname), - gmyth_string_list_get_int(slist, pos + 11)); - - prog->startts = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 11)))->str); // DATETIME_TO_LIST(startts) - prog->endts = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 12)))->str); // DATETIME_TO_LIST(endts) - prog->duplicate = gmyth_string_list_get_int(slist, pos + 13); - prog->shareable = gmyth_string_list_get_int(slist, pos + 14); - prog->findid = gmyth_string_list_get_int(slist, pos + 15); - prog->hostname = gmyth_string_list_get_string(slist, pos + 16); - prog->sourceid = gmyth_string_list_get_int(slist, pos + 17); - prog->cardid = gmyth_string_list_get_int(slist, pos + 18); - prog->inputid = gmyth_string_list_get_int(slist, pos + 19); - prog->recpriority = gmyth_string_list_get_int(slist, pos + 20); - prog->reactivate = gmyth_string_list_get_int(slist, pos + 21); - prog->recordid = gmyth_string_list_get_int(slist, pos + 22); - gmyth_string_list_get_int(slist, pos + 23); - gmyth_string_list_get_int(slist, pos + 24); - gmyth_string_list_get_int(slist, pos + 25); - prog->recstartts = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 26)))->str); // DATETIME_TO_LIST(recstartts) - prog->recendts = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 27)))->str); // DATETIME_TO_LIST(recendts) - prog->repeat = gmyth_string_list_get_int(slist, pos + 28); - prog->programflags = gmyth_string_list_get_int(slist, pos + 29); - prog->recgroup = gmyth_string_list_get_string(slist, pos + 30); // prog->(recgroup - // - // - // != - // "") - // ? - // recgroup - // : - // "Default") - prog->chancommfree = gmyth_string_list_get_int(slist, pos + 31); - prog->chanOutputFilters = - gmyth_string_list_get_string(slist, pos + 32); - prog->seriesid = gmyth_string_list_get_string(slist, pos + 33); - prog->program_id = gmyth_string_list_get_string(slist, pos + 34); - gmyth_string_list_get_string(slist, pos + 35); - prog->lastmodified = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 36)))->str); // DATETIME_TO_LIST(lastmodified) - gmyth_string_list_get_int(slist, pos + 37); // FLOAT_TO_LIST(stars) - prog->originalAirDate = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 38)))->str); // DATETIME_TO_LIST(QDateTime(originalAirDate)) - prog->hasAirDate = gmyth_string_list_get_int(slist, pos + 39); - prog->playgroup = gmyth_string_list_get_string(slist, pos + 40); // prog->(playgroup - // - // - // != - // "") - // ? - // playgroup - // : - // "Default") - prog->recpriority2 = gmyth_string_list_get_int(slist, pos + 41); - - return prog; -} - -/** - * Converts an instance of a GMythStringList, to a GMythProgramInfo. - * - * @param slist The GMythStringList got from the MythTV backend server. - * - * @return a GMythProgramInfo representing the string list got from network. - */ -GMythProgramInfo * -gmyth_program_info_from_string_list(GMythStringList * slist) -{ - GMythProgramInfo *prog = NULL; - - g_return_val_if_fail(slist != NULL, NULL); - - prog = gmyth_program_info_from_string_list_from_pos(slist, 0); - - return prog; -} - -/** - * Converts an instance of a GMythStringList, to a GMythProgramInfo ( NEXT_PROGRAM_INFO ). - * - * @param slist The GMythStringList got from the MythTV backend server. - * - * @return a GMythProgramInfo representing the string list got from network. - */ -GMythProgramInfo * -gmyth_program_info_from_string_list_next_prog(GMythStringList * slist) -{ - GMythProgramInfo *prog = gmyth_program_info_new(); - - g_return_val_if_fail(slist != NULL, NULL); - - /* - * {Home Improvement[]:[]No, No, Godot[]:[] US sitcom about a - * DIY-obsessed father of three. When Tim tries to sell off his extra - * ticket for an ice hockey game, he is arrested as a tout.[]:[] - * Sitcom[]:[]2007-04-18T15:30:00[]:[]2007-04-18T16:00:00[]:[]ABC1[]:[] - * /home/hmelo/.mythtv/channels/abc1.jpg[]:[]abc1[]:[]2000[]:[]25725844[]:[] - * } - */ - - prog->title = gmyth_string_list_get_string(slist, 0); - prog->subtitle = gmyth_string_list_get_string(slist, 1); - prog->description = gmyth_string_list_get_string(slist, 2); - prog->category = gmyth_string_list_get_string(slist, 3); - prog->startts = gmyth_util_string_to_time_val(gmyth_string_list_get_char_array(slist, 4)); // DATETIME_TO_LIST(startts) - prog->endts = gmyth_util_string_to_time_val(gmyth_string_list_get_char_array(slist, 5)); // DATETIME_TO_LIST(endts) - prog->channame = gmyth_string_list_get_string(slist, 6); - prog->chansign = gmyth_string_list_get_string(slist, 7); - prog->chanstr = gmyth_string_list_get_string(slist, 8); - prog->channel_id = gmyth_string_list_get_int (slist, 9); - prog->filesize = gmyth_string_list_get_int64(slist, 10); - - gmyth_debug - ("NEXT program info: [ %s, %s, %s, %s, %s, %s, %s, %s ]\n", - gmyth_program_info_non_null_value(prog->title), - gmyth_program_info_non_null_value(prog->subtitle), - gmyth_program_info_non_null_value(prog->description), - gmyth_program_info_non_null_value(prog->category), - gmyth_program_info_non_null_value(prog->channame), - gmyth_program_info_non_null_value(prog->chanstr), - gmyth_program_info_non_null_value(prog->chansign), - gmyth_program_info_non_null_value(prog->pathname)); - - return prog; -} - -static const gchar * -gmyth_program_info_non_null_value(const GString * str) -{ - return (str != NULL && str->str != NULL - && strlen(str->str) > 0 ? str->str : " "); -} - -/** - * Prints out an instance of a GMythProgramInfo. - * - * @param prog A GMythProgramInfo instance. - * - * @return a string representing the program info. - */ -const gchar * -gmyth_program_info_to_string(const GMythProgramInfo * prog) -{ - return - g_strdup_printf - ("Title: %s, Subtitle: %s, Description: %s, Category: %s, Channel ID: %d, " - "Channel Name: %s, Chan str: %s, Channel Sign: %s, Path Name: %s, File Size: %lld, \n" - "Start TS: %s, End TS: %s, Duplicate: %d, Shareable: %d, Find ID: %d, Hostname: %s, " - "Source ID: %d, Vard ID: %d, Input ID: %d, Rec Priority: %d, Reactivate: %d, \n" - "Record ID: %d, Rec Start TS: %s, Rec End TS: %s, Repeat: %d, Program Flags: %d, " - "Rec Group: %s, Channel Comm Free: %d, Channel Output Filters: %s, Series ID: %s, \n" - "Program ID: %s, Last Modified Date: %s, Original Air Date: %s, Has Air Date: %d, " - "Play Group: %s.\n", - gmyth_program_info_non_null_value(prog->title), - gmyth_program_info_non_null_value(prog->subtitle), - gmyth_program_info_non_null_value(prog->description), - gmyth_program_info_non_null_value(prog->category), - prog->channel_id, - gmyth_program_info_non_null_value(prog->channame), - gmyth_program_info_non_null_value(prog->chanstr), - gmyth_program_info_non_null_value(prog->chansign), - gmyth_program_info_non_null_value(prog->pathname), prog->filesize, - gmyth_util_time_to_string_from_time_val(prog->startts), - gmyth_util_time_to_string_from_time_val(prog->endts), - prog->duplicate, prog->shareable, prog->findid, - gmyth_program_info_non_null_value(prog->hostname), prog->sourceid, - prog->cardid, prog->inputid, prog->recpriority, prog->reactivate, - prog->recordid, - gmyth_util_time_to_string_from_time_val(prog->recstartts), - gmyth_util_time_to_string_from_time_val(prog->recendts), - prog->repeat, prog->programflags, - gmyth_program_info_non_null_value(prog->recgroup), - prog->chancommfree, - gmyth_program_info_non_null_value(prog->chanOutputFilters), - gmyth_program_info_non_null_value(prog->seriesid), - gmyth_program_info_non_null_value(prog->program_id), - gmyth_util_time_to_string_from_time_val(prog->lastmodified), - gmyth_util_time_to_string_from_time_val(prog->originalAirDate), - prog->hasAirDate, - gmyth_program_info_non_null_value(prog->playgroup)); -} - -/** - * Say if an instance of a GMythProgramInfo is equals to another one. - * - * @param prog The first GMythProgramInfo instance. - * @param prog The second GMythProgramInfo instance. - * - * @return true, if the program infos are equals. - */ -gboolean -gmyth_program_info_is_equals(const GMythProgramInfo * prog1, - const GMythProgramInfo * prog2) -{ - if ((strcmp(gmyth_program_info_non_null_value(prog1->title), - gmyth_program_info_non_null_value(prog2->title)) == 0) - || - (strcmp - (gmyth_program_info_non_null_value(prog1->pathname), - gmyth_program_info_non_null_value(prog2->pathname)) == 0)) - return TRUE; - else - return FALSE; - -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_programinfo.h --- a/gmyth/src/gmyth_programinfo.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,180 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_programinfo.h - * - * @brief

GMythProgramInfo representing the program info, with the - * configuration data to the actual remote file in the TV chain. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Rosfran Borges - * @author Leonardo Sobral Cunha - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef _GMYTH_PROGRAMINFO_H -#define _GMYTH_PROGRAMINFO_H - -#include -#include - -#include "gmyth_stringlist.h" - -G_BEGIN_DECLS -#define GMYTH_PROGRAM_INFO_TYPE (gmyth_program_info_get_type ()) -#define GMYTH_PROGRAM_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_PROGRAM_INFO_TYPE, GMythProgramInfo)) -#define GMYTH_PROGRAM_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_PROGRAM_INFO_TYPE, GMythProgramInfoClass)) -#define IS_GMYTH_PROGRAM_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_PROGRAM_INFO_TYPE)) -#define IS_GMYTH_PROGRAM_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_PROGRAM_INFO_TYPE)) -#define GMYTH_PROGRAM_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_PROGRAM_INFO_TYPE, GMythProgramInfoClass)) -typedef struct _GMythProgramInfo GMythProgramInfo; -typedef struct _GMythProgramInfoClass GMythProgramInfoClass; - -struct _GMythProgramInfoClass { - GObjectClass parent_class; - - /* - * callbacks - */ -}; - -/** - * The GMythProgramInfo structure represents a program information - * stored in the database. It could be a program from the EPG data, - * a program scheduled to be recorded, or a program already recorded. - */ -struct _GMythProgramInfo { - GObject parent; - - /** The channel unique ID. */ - gint channel_id; - /** The program start time. */ - GTimeVal *startts; - /** The program end time. */ - GTimeVal *endts; - /** The recording schedule start time. */ - GTimeVal *recstartts; - /** The recording schedule end time */ - GTimeVal *recendts; - - /** The program title. */ - GString *title; - /** The program subtitle. */ - GString *subtitle; - /** The program description. */ - GString *description; - /** The program category. */ - GString *category; - - GString *chanstr; - GString *chansign; - /** The associated channel name. */ - GString *channame; - gint chancommfree; - GString *chanOutputFilters; - - GString *seriesid; - /** The program unique id. */ - GString *program_id; - GString *catType; - - GString *sortTitle; - - /** A flag informing if the program has video or not. */ - gboolean isVideo; - gint lenMins; - - GString *year; - gdouble stars; - gint repeat; - - GTimeVal *originalAirDate; - GTimeVal *lastmodified; - GTimeVal *lastInUseTime; - - gboolean hasAirDate; - - gint spread; - gint startCol; - - gint recpriority2; - gint reactivate; - - gint recordid; - gint parentid; - - /** The backend video source id associated to this program.*/ - gint sourceid; - /** the backend input id associated to this program.*/ - gint inputid; - /** The backend card id associated to this program.*/ - gint cardid; - gboolean shareable; - gboolean duplicate; - - GString *schedulerid; - gint findid; - - gint programflags; - gint transcoder; - - GString *recgroup; - GString *playgroup; - gint rectype; - gint recstatus; - gint recpriority; - gint dupin; - gint dupmethod; - - /** The file size of the recorded program.*/ - gint64 filesize; - - /** The file name of the recorded program.*/ - GString *pathname; - GString *hostname; -}; - -GType gmyth_program_info_get_type(void); - -GMythProgramInfo *gmyth_program_info_new(void); - -GMythStringList *gmyth_program_info_to_string_list(GMythProgramInfo * prog, - GMythStringList * - slist); - -GMythProgramInfo - * gmyth_program_info_from_string_list_from_pos(GMythStringList * slist, - guint pos); - -GMythProgramInfo *gmyth_program_info_from_string_list(GMythStringList * - slist); - -GMythProgramInfo - * gmyth_program_info_from_string_list_next_prog(GMythStringList * - slist); - -const gchar *gmyth_program_info_to_string(const GMythProgramInfo * - prog); - -gboolean gmyth_program_info_is_equals(const GMythProgramInfo * - prog1, - const GMythProgramInfo * - prog2); - -G_END_DECLS -#endif /*_GMYTH_PROGRAMINFO_H*/ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_query.c --- a/gmyth/src/gmyth_query.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,280 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_query.c - * - * @brief

GMythQuery class provides a wrapper for accessing - * the libmysqlclient funtions. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Leonardo Sobral Cunha - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "gmyth_query.h" -#include "gmyth_debug.h" - -static void gmyth_query_class_init(GMythQueryClass * klass); -static void gmyth_query_init(GMythQuery * object); - -static void gmyth_query_dispose(GObject * object); -static void gmyth_query_finalize(GObject * object); - -static void gmyth_query_print_error(MYSQL * conn, char *message); - -G_DEFINE_TYPE(GMythQuery, gmyth_query, G_TYPE_OBJECT) - static void gmyth_query_class_init(GMythQueryClass * klass) -{ - GObjectClass *gobject_class; - - gobject_class = (GObjectClass *) klass; - - gobject_class->dispose = gmyth_query_dispose; - gobject_class->finalize = gmyth_query_finalize; -} - -static void -gmyth_query_init(GMythQuery * gmyth_query) -{ - gmyth_query->backend_info = NULL; - - /* - * initialize connection handler - */ - gmyth_query->conn = mysql_init(NULL); - - if (!(gmyth_query->conn)) - g_warning("[%s] MSQL structure not initialized", __FUNCTION__); -} - -static void -gmyth_query_dispose(GObject * object) -{ - GMythQuery *gmyth_query = GMYTH_QUERY(object); - - if (gmyth_query->conn != NULL) { - gmyth_query_disconnect(gmyth_query); - } - - if (gmyth_query->backend_info) { - g_object_unref(gmyth_query->backend_info); - gmyth_query->backend_info = NULL; - } - - G_OBJECT_CLASS(gmyth_query_parent_class)->dispose(object); -} - -static void -gmyth_query_finalize(GObject * object) -{ - g_signal_handlers_destroy(object); - - G_OBJECT_CLASS(gmyth_query_parent_class)->finalize(object); -} - -/** Creates a new instance of GMythQuery. - * - * @return a new instance of GMythQuery. - */ -GMythQuery * -gmyth_query_new() -{ - GMythQuery *sql_query = - GMYTH_QUERY(g_object_new(GMYTH_QUERY_TYPE, NULL)); - - return sql_query; -} - -gboolean -gmyth_query_connect_with_timeout(GMythQuery * gmyth_query, - GMythBackendInfo * backend_info, - guint timeout) -{ - assert(gmyth_query); - - if (gmyth_query->conn == NULL) - gmyth_query->conn = mysql_init(NULL); - - if (timeout != 0) { - /* - * sets connection timeout - */ - mysql_options(gmyth_query->conn, MYSQL_OPT_CONNECT_TIMEOUT, - (gchar *) & timeout); - } - - return gmyth_query_connect(gmyth_query, backend_info); -} - -/** Connects to the Mysql database in the backend. The backend address - * is loaded from the GMythBackendInfo instance. - * - * @param gmyth_query the GMythEPG instance to be connected. - * @return true if connection was success, false if failed. - */ -gboolean -gmyth_query_connect(GMythQuery * gmyth_query, - GMythBackendInfo * backend_info) -{ - assert(gmyth_query); - g_return_val_if_fail(backend_info != NULL, FALSE); - g_return_val_if_fail(backend_info->hostname != NULL, FALSE); - g_return_val_if_fail(backend_info->username != NULL, FALSE); - g_return_val_if_fail(backend_info->password != NULL, FALSE); - g_return_val_if_fail(backend_info->db_name != NULL, FALSE); - - if (gmyth_query->backend_info != NULL) { - g_object_unref(gmyth_query->backend_info); - } - gmyth_query->backend_info = g_object_ref(backend_info); - - if (gmyth_query->conn == NULL) { - gmyth_query->conn = mysql_init(NULL); - } - - /* - * connect to server - */ - if (mysql_real_connect(gmyth_query->conn, - gmyth_query->backend_info->hostname, - gmyth_query->backend_info->username, - gmyth_query->backend_info->password, - gmyth_query->backend_info->db_name, - gmyth_query->backend_info->db_port, - NULL, - 0) == NULL) { - gmyth_query_print_error(gmyth_query->conn, - "mysql_real_connect() failed"); - return FALSE; - } - - gmyth_debug - ("[%s] Connection to Mysql server succeeded! (host = %s, user = %s, " - "password = %s, db name = %s)", __FUNCTION__, - gmyth_query->backend_info->hostname, - gmyth_query->backend_info->username, - gmyth_query->backend_info->password, - gmyth_query->backend_info->db_name); - - return TRUE; -} - -/** Disconnects from the Mysql database in the backend. - * - * @param gmyth_query the GMythQuery instance to be disconnected - * @return true if disconnection was success, false if failed. - */ -gboolean -gmyth_query_disconnect(GMythQuery * gmyth_query) -{ - g_return_val_if_fail(gmyth_query != NULL, FALSE); - g_return_val_if_fail(gmyth_query->conn != NULL, FALSE); - - /* - * TODO: Check how to return error - */ - gmyth_debug("[%s] Closing gmyth_query->conn", __FUNCTION__); - - mysql_close(gmyth_query->conn); - gmyth_query->conn = NULL; - - return TRUE; -} - -static void -gmyth_query_print_error(MYSQL * conn, char *message) -{ - gmyth_debug("%s", message); - - if (conn != NULL) { -#if MYSQL_VERSION_ID >= 40101 - gmyth_debug("Error %u (%s): %s\n", - mysql_errno(conn), mysql_sqlstate(conn), - mysql_error(conn)); -#else - gmyth_debug("Error %u: %s\n", mysql_errno(conn), - mysql_error(conn)); -#endif - } -} - -/** Sends the given query to the backend returning the query result as - * MYSQL_RES pointer. - * - * FIXME: this function is returning NULL whether any error happens - * or no rows are returned (e.g. UPDATE or REPLACE). - * - * @param gmyth_query the GMythQuery instance. - * @param stmt_str the query text. - * @return the MYSQL_RES result pointer or NULL if any error happens. - */ -MYSQL_RES* -gmyth_query_process_statement(GMythQuery * gmyth_query, char *stmt_str) -{ - assert(gmyth_query); - - gmyth_debug("[%s] Running mysql query %s", __FUNCTION__, stmt_str); - - if (gmyth_query == NULL) - return NULL; - - //the statement failed - if (mysql_query(gmyth_query->conn, stmt_str) != 0) { - gmyth_query_print_error(gmyth_query->conn, - "Could not execute statement"); - return NULL; - } - - //the statement succeeded; determine whether it returned data - return mysql_store_result(gmyth_query->conn); -} - -MYSQL_RES* -gmyth_query_process_statement_with_increment(GMythQuery * gmyth_query, - char *stmt_str, gulong * id) -{ - assert(gmyth_query); - - gmyth_debug("[%s] Running mysql query %s", __FUNCTION__, stmt_str); - - if (gmyth_query == NULL) - return NULL; - - /* - * the statement failed - */ - if (mysql_query(gmyth_query->conn, stmt_str) != 0) { - gmyth_query_print_error(gmyth_query->conn, - "Could not execute statement"); - return NULL; - } - - *id = (my_ulonglong) mysql_insert_id(gmyth_query->conn); - - /* - * the statement succeeded; determine whether it returned data - */ - return mysql_store_result(gmyth_query->conn); -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_query.h --- a/gmyth/src/gmyth_query.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_query.h - * - * @brief

GMythQuery class provides a wrapper for accessing - * the libmysqlclient funtions. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Leonardo Sobral Cunha - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __GMYTH_QUERY_H__ -#define __GMYTH_QUERY_H__ - -#include - -/* - * MYSQL includes - */ -#include - -#include "gmyth_backendinfo.h" - -G_BEGIN_DECLS -#define GMYTH_QUERY_TYPE (gmyth_query_get_type ()) -#define GMYTH_QUERY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_QUERY_TYPE, GMythQuery)) -#define GMYTH_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_QUERY_TYPE, GMythQueryClass)) -#define IS_GMYTH_QUERY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_QUERY_TYPE)) -#define IS_GMYTH_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_QUERY_TYPE)) -#define GMYTH_QUERY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_QUERY_TYPE, GMythQueryClass)) -typedef struct _GMythQuery GMythQuery; -typedef struct _GMythQueryClass GMythQueryClass; - -struct _GMythQueryClass { - GObjectClass parent_class; - - /* - * callbacks - */ - /* - * no one for now - */ -}; - -struct _GMythQuery { - GObject parent; - - GMythBackendInfo *backend_info; - - /* - * pointer to connection handler - */ - MYSQL *conn; -}; - - -GType gmyth_query_get_type(void); - -GMythQuery *gmyth_query_new(void); -MYSQL_RES *gmyth_query_process_statement(GMythQuery * gmyth_query, - gchar * stmt_str); -MYSQL_RES *gmyth_query_process_statement_with_increment(GMythQuery * - gmyth_query, - char - *stmt_str, - gulong * id); - -gboolean gmyth_query_connect(GMythQuery * gmyth_query, - GMythBackendInfo * backend_info); -gboolean gmyth_query_connect_with_timeout(GMythQuery * gmyth_query, - GMythBackendInfo * - backend_info, - guint timeout); -gboolean gmyth_query_disconnect(GMythQuery * gmyth_query); - -G_END_DECLS -#endif /* __GMYTH_QUERY_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_recorder.c --- a/gmyth/src/gmyth_recorder.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1388 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_recorder.c - * - * @brief

GMythRecorder defines functions for playing live tv. - * - * The remote encoder is used by gmyth_tvplayer to setup livetv. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Hallyson Luiz de Morais Melo - * @author Rosfran Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gmyth_recorder.h" - -#include - -#include "gmyth_stringlist.h" -#include "gmyth_util.h" -#include "gmyth_common.h" -#include "gmyth_debug.h" - -#define GMYTHTV_RECORDER_HEADER "QUERY_RECORDER" - -static void gmyth_recorder_class_init(GMythRecorderClass * klass); -static void gmyth_recorder_init(GMythRecorder * object); - -static void gmyth_recorder_dispose(GObject * object); -static void gmyth_recorder_finalize(GObject * object); - -G_DEFINE_TYPE(GMythRecorder, gmyth_recorder, G_TYPE_OBJECT) - static void gmyth_recorder_class_init(GMythRecorderClass * klass) -{ - GObjectClass *gobject_class; - - gobject_class = (GObjectClass *) klass; - - gobject_class->dispose = gmyth_recorder_dispose; - gobject_class->finalize = gmyth_recorder_finalize; -} - -static void -gmyth_recorder_init(GMythRecorder * gmyth_remote_encoder) -{ -} - -static void -gmyth_recorder_dispose(GObject * object) -{ - GMythRecorder *recorder = GMYTH_RECORDER(object); - - gmyth_recorder_close(recorder); - - if (recorder->mutex != NULL) { - g_mutex_free(recorder->mutex); - recorder->mutex = NULL; - } - - if (recorder->myth_socket != NULL) { - g_object_unref(recorder->myth_socket); - recorder->myth_socket = NULL; - } - - if (recorder->progs_info_list != NULL) - gmyth_free_program_list(recorder->progs_info_list); - - if (recorder->hostname != NULL) - g_string_free(recorder->hostname, TRUE); - - G_OBJECT_CLASS(gmyth_recorder_parent_class)->dispose(object); -} - -static void -gmyth_recorder_finalize(GObject * object) -{ - g_signal_handlers_destroy(object); - - G_OBJECT_CLASS(gmyth_recorder_parent_class)->finalize(object); -} - -void -gmyth_recorder_close(GMythRecorder * recorder) -{ - if (recorder != NULL && recorder->recorder_num != -1) { - g_mutex_lock(recorder->mutex); - - gmyth_recorder_stop_playing(recorder); - gmyth_recorder_stop_livetv(recorder); - gmyth_recorder_finish_recording(recorder); - gmyth_recorder_free_tuner(recorder); - - g_mutex_unlock(recorder->mutex); - } -} - -/** Creates a new instance of GMythRecorder. - * - * @return a new instance of GMythRecorder. - */ -GMythRecorder * -gmyth_recorder_new(int num, GString * hostname, gshort port) -{ - GMythRecorder *encoder = - GMYTH_RECORDER(g_object_new(GMYTH_RECORDER_TYPE, FALSE)); - - encoder->recorder_num = num; - encoder->hostname = g_string_new(hostname->str); - encoder->port = port; - - encoder->mutex = g_mutex_new(); - - encoder->progs_info_list = NULL; - - return encoder; -} - -/** Configures the remote encoder instance connecting it to Mythtv backend. - * - * @param recorder the GMythRecorder instance. - * - * @return TRUE if successfull, FALSE if any error happens. - */ -gboolean -gmyth_recorder_setup(GMythRecorder * recorder) -{ - assert(recorder); - gmyth_debug("[%s] Creating socket and connecting to backend", - __FUNCTION__); - - if (recorder->myth_socket == NULL) { - recorder->myth_socket = gmyth_socket_new(); - - if (!gmyth_socket_connect_to_backend(recorder->myth_socket, - recorder->hostname->str, - recorder->port, TRUE)) { - gmyth_debug - ("GMythRemoteEncoder: Connection to backend failed"); - return FALSE; - } - } else { - gmyth_debug("Remote encoder socket already created\n"); - } - - return TRUE; -} - -/** Sends the SPAWN_LIVETV command through Mythtv protocol. This command - * requests the backend to start capturing TV content. - * - * @param recorder The GMythRecorder instance. - * @param tvchain_id The tvchain unique id. - * @return true if success, false if any error happens. - */ -gboolean -gmyth_recorder_spawntv(GMythRecorder * recorder, GString * tvchain_id) -{ - GMythStringList *str_list; - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); - gboolean ret = TRUE; - - gmyth_debug("[%s] Spawntv with tvchain_id = %s", __FUNCTION__, - tvchain_id->str); - - str_list = gmyth_string_list_new(); - - g_mutex_lock(recorder->mutex); - - g_string_append_printf(tmp_str, " %d", recorder->recorder_num); - - gmyth_string_list_append_string(str_list, tmp_str); - g_string_free(tmp_str, TRUE); - - gmyth_string_list_append_char_array(str_list, "SPAWN_LIVETV"); - - gmyth_string_list_append_string(str_list, tvchain_id); - gmyth_string_list_append_int(str_list, 0); // PIP = FALSE (0) - - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); - - tmp_str = gmyth_string_list_get_string(str_list, 0); - - if (tmp_str == NULL) { - gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__, - tmp_str->str); - ret = FALSE; - goto cleanup; - } - - if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) { - gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__, - tmp_str->str); - ret = FALSE; - goto cleanup; - } - - cleanup: - g_mutex_unlock(recorder->mutex); - - g_string_free(tmp_str, TRUE); - g_object_unref(str_list); - - return ret; -} - -/** - * Sends the SPAWN_LIVETV command through Mythtv protocol. This command - * requests the backend to start capturing TV content, but it doesn't need - * the TV chain ID. - * - * @param recorder The GMythRecorder instance. - * @return true if success, false if any error happens. - */ -gboolean -gmyth_recorder_spawntv_no_tvchain(GMythRecorder * recorder) -{ - GMythStringList *str_list; - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); - gboolean ret = TRUE; - - gmyth_debug("[%s] Spawntv, no TV chain!", __FUNCTION__); - - str_list = gmyth_string_list_new(); - - g_mutex_lock(recorder->mutex); - - g_string_append_printf(tmp_str, " %d", recorder->recorder_num); - - gmyth_string_list_append_string(str_list, tmp_str); - g_string_free(tmp_str, TRUE); - - gmyth_string_list_append_char_array(str_list, "SPAWN_LIVETV"); - - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); - - tmp_str = gmyth_string_list_get_string(str_list, 0); - - if (tmp_str == NULL) { - gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__, - tmp_str->str); - ret = FALSE; - goto cleanup; - } - - if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) { - gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__, - tmp_str->str); - ret = FALSE; - goto cleanup; - } - - cleanup: - g_mutex_unlock(recorder->mutex); - - g_string_free(tmp_str, TRUE); - g_object_unref(str_list); - - return ret; -} - -/** Sends the command STOP_LIVETV to Mythtv backend. - * - * @param recorder the GMythRecorder instance. - * @return true if success, false if any error happens. - */ -gboolean -gmyth_recorder_stop_livetv(GMythRecorder * recorder) -{ - GMythStringList *str_list; - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); - gboolean ret = TRUE; - - gmyth_debug("[%s]", __FUNCTION__); - - str_list = gmyth_string_list_new(); - - g_string_append_printf(tmp_str, " %d", recorder->recorder_num); - - gmyth_string_list_append_string(str_list, tmp_str); - g_string_free(tmp_str, TRUE); - - gmyth_string_list_append_char_array(str_list, "STOP_LIVETV"); - - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); - - tmp_str = gmyth_string_list_get_string(str_list, 0); - - if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) { - gmyth_debug("[%s] Stop livetv request returned %s", __FUNCTION__, - tmp_str->str); - ret = FALSE; - goto cleanup; - } - - cleanup: - g_string_free(tmp_str, TRUE); - g_object_unref(str_list); - - return ret; -} - -/** Sends the FRONTEND_READY command through Mythtv protocol. This command - * advertises the backend to start capturing TV content. - * - * @param recorder The GMythRecorder instance. - * @return TRUE if success, FALSE if any error happens. - */ -gboolean -gmyth_recorder_send_frontend_ready_command(GMythRecorder * recorder) -{ - GMythStringList *str_list; - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); - gboolean ret = TRUE; - - gmyth_debug("[%s] FRONTEND_READY with recorder id = %d", __FUNCTION__, - recorder->recorder_num); - - str_list = gmyth_string_list_new(); - - g_mutex_lock(recorder->mutex); - - g_string_append_printf(tmp_str, " %d", recorder->recorder_num); - - gmyth_string_list_append_string(str_list, tmp_str); - g_string_free(tmp_str, TRUE); - - gmyth_string_list_append_char_array(str_list, "FRONTEND_READY"); - - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); - - tmp_str = gmyth_string_list_get_string(str_list, 0); - - if (tmp_str == NULL) { - gmyth_debug - ("[%s] FRONTEND_READY command request couldn't returns, reason: %s", - __FUNCTION__, tmp_str->str); - ret = FALSE; - goto cleanup; - } - - if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) { - gmyth_debug("[%s] FRONTEND_READY request returned %s", - __FUNCTION__, tmp_str->str); - ret = FALSE; - goto cleanup; - } - - cleanup: - g_mutex_unlock(recorder->mutex); - g_string_free(tmp_str, TRUE); - g_object_unref(str_list); - - return ret; -} - -/** Send a CHECK_CHANNEL command request to the backend, in order to find if a - * certain channel actually exists. - * - * @param recorder The GMythRecorder instance. - * @param channel The new channel to be checked (string format). - * @return true if success, false if any error happens. - */ -gboolean -gmyth_recorder_check_channel_name(GMythRecorder * recorder, - gchar * channel) -{ - GMythStringList *str_list; - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); - gboolean ret = TRUE; - - gmyth_debug("[%s] CHECK_CHANNEL with channel = %s", __FUNCTION__, - channel); - - str_list = gmyth_string_list_new(); - - g_mutex_lock(recorder->mutex); - - g_string_append_printf(tmp_str, " %d", recorder->recorder_num); - - gmyth_string_list_append_string(str_list, tmp_str); - g_string_free(tmp_str, TRUE); - - gmyth_string_list_append_char_array(str_list, "CHECK_CHANNEL"); - - gmyth_string_list_append_char_array(str_list, channel); - - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); - - tmp_str = gmyth_string_list_get_string(str_list, 0); - - if (tmp_str == NULL) { - gmyth_debug("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__, - tmp_str->str); - ret = FALSE; - goto cleanup; - } - - if (g_ascii_strncasecmp(tmp_str->str, "ok", 2) == 0 - || g_ascii_strncasecmp(tmp_str->str, "0", 1) == 0) { - gmyth_debug("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__, - tmp_str->str); - ret = FALSE; - goto cleanup; - } - - cleanup: - g_mutex_unlock(recorder->mutex); - g_string_free(tmp_str, TRUE); - g_object_unref(str_list); - - return ret; -} - -/** Send a CHECK_CHANNEL command request to the backend, in order to find if a - * certain channel actually exists. - * - * @param recorder The GMythRecorder instance. - * @param channel The new channel to be checked (decimal integer value). - * @return true if success, false if any error happens. - */ -gboolean -gmyth_recorder_check_channel(GMythRecorder * recorder, gint channel) -{ - return gmyth_recorder_check_channel_name(recorder, - g_strdup_printf("%d", - channel)); -} - -/** Send a SET_CHANNEL command request to the backend, to start streaming on another - * TV content channel. - * - * @param recorder The GMythRecorder instance. - * @param channel The new channel to be loaded. - * @return true if success, false if any error happens. - */ -gboolean -gmyth_recorder_set_channel(GMythRecorder * recorder, gint channel) -{ - GMythStringList *str_list; - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); - gboolean ret = TRUE; - - gmyth_debug("[%s] SET_CHANNEL with channel = %d", __FUNCTION__, - channel); - - str_list = gmyth_string_list_new(); - - g_mutex_lock(recorder->mutex); - - g_string_append_printf(tmp_str, " %d", recorder->recorder_num); - - gmyth_string_list_append_string(str_list, tmp_str); - g_string_free(tmp_str, TRUE); - - gmyth_string_list_append_char_array(str_list, "SET_CHANNEL"); - - gmyth_string_list_append_int(str_list, channel); - - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); - - tmp_str = gmyth_string_list_get_string(str_list, 0); - - if (tmp_str == NULL) { - gmyth_debug("[%s] SET_CHANNEL request returned %s", __FUNCTION__, - tmp_str->str); - ret = FALSE; - goto cleanup; - } - - if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) { - gmyth_debug("[%s] SET_CHANNEL request returned %s", __FUNCTION__, - tmp_str->str); - ret = FALSE; - goto cleanup; - } - - cleanup: - g_mutex_unlock(recorder->mutex); - g_string_free(tmp_str, TRUE); - g_object_unref(str_list); - - return ret; -} - -/** Send a SET_CHANNEL command request to the backend, to start streaming on another - * TV content channel. - * - * @param recorder The GMythRecorder instance. - * @param channel The new channel to be loaded. - * @return true if success, false if any error happens. - */ -gboolean -gmyth_recorder_set_channel_name(GMythRecorder * recorder, - const gchar * channel) -{ - GMythStringList *str_list; - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); - gboolean ret = TRUE; - - gmyth_debug("[%s] SET_CHANNEL with channel name = %s", __FUNCTION__, - channel); - - str_list = gmyth_string_list_new(); - - g_mutex_lock(recorder->mutex); - - g_string_append_printf(tmp_str, " %d", recorder->recorder_num); - - gmyth_string_list_append_string(str_list, tmp_str); - g_string_free(tmp_str, TRUE); - - gmyth_string_list_append_char_array(str_list, "SET_CHANNEL"); - gmyth_string_list_append_char_array(str_list, channel); - - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); - - tmp_str = gmyth_string_list_get_string(str_list, 0); - - if (tmp_str == NULL) { - gmyth_debug("[%s] SET_CHANNEL name request returned NULL!", - __FUNCTION__); - ret = FALSE; - goto cleanup; - } - - if (tmp_str != NULL && g_ascii_strncasecmp(tmp_str->str, "ok", 2) - /* - * || g_ascii_strtoull( tmp_str->str, NULL, 10 ) == 0 - */ - ) { - g_warning("[%s] SET_CHANNEL name request returned not ok", - __FUNCTION__); - ret = FALSE; - goto cleanup; - } - - cleanup: - g_mutex_unlock(recorder->mutex); - g_string_free(tmp_str, TRUE); - g_object_unref(str_list); - - return ret; -} - -/** - * Changes the channel of the actual Recorder. - * - * CHANNEL_DIRECTION_UP - Go up one channel in the listing - * - * CHANNEL_DIRECTION_DOWN - Go down one channel in the listing - * - * CHANNEL_DIRECTION_FAVORITE - Go to the next favorite channel - * - * CHANNEL_DIRECTION_SAME - Stay - * - * @param recorder The GMythRecorder instance. - * @param direction The new channel direction where to move to. - * @return true if success, false if any error happens. - */ -gboolean -gmyth_recorder_change_channel(GMythRecorder * recorder, - const GMythRecorderChannelChangeDirection - direction) -{ - GMythStringList *str_list; - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); - gboolean ret = TRUE; - - gmyth_debug("[%s] CHANGE_CHANNEL to the channel direction = %u", - __FUNCTION__, direction); - - str_list = gmyth_string_list_new(); - - g_mutex_lock(recorder->mutex); - - g_string_append_printf(tmp_str, " %d", recorder->recorder_num); - - gmyth_string_list_append_string(str_list, tmp_str); - g_string_free(tmp_str, TRUE); - - gmyth_string_list_append_char_array(str_list, "CHANGE_CHANNEL"); - gmyth_string_list_append_int(str_list, direction); - - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); - - tmp_str = gmyth_string_list_get_string(str_list, 0); - - if (tmp_str == NULL) { - gmyth_debug("[%s] CHANGE_CHANNEL name request returned %s", - __FUNCTION__, tmp_str->str); - ret = FALSE; - goto cleanup; - } - - if (g_ascii_strncasecmp(tmp_str->str, "ok", 2) - || g_ascii_strtoull(tmp_str->str, NULL, 10) == 0) { - gmyth_debug("[%s] CHANGE_CHANNEL name request returned %s", - __FUNCTION__, tmp_str->str); - ret = FALSE; - goto cleanup; - } - - cleanup: - g_mutex_unlock(recorder->mutex); - g_string_free(tmp_str, TRUE); - g_object_unref(str_list); - - return ret; -} - -/** - * Gets the channel's list from the MythTV backend server. - * - * @param recorder The GMythRecorder instance. - * - * @return a GList* instance with all the channel names. - */ -GList * -gmyth_recorder_get_channel_list(GMythRecorder * recorder) -{ - - GList *channel_list = NULL; - gchar *channel = NULL; - guint i; - - for (i = 0; i < 1000; i++) { - channel = g_strdup_printf("%u", i); - - if (gmyth_recorder_check_channel_name(recorder, channel)) { - channel_list = g_list_append(channel_list, g_strdup(channel)); - } - - } /* for - channel list */ - - g_free(channel); - - return channel_list; - -} - -/** Send a PAUSE command request to the backend, to pause streaming on another - * TV content channel. - * - * @param recorder The GMythRecorder instance. - * @return true if success, false if any error happens. - */ -gboolean -gmyth_recorder_pause_recording(GMythRecorder * recorder) -{ - GMythStringList *str_list; - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); - gboolean ret = TRUE; - - gmyth_debug("[%s] PAUSE", __FUNCTION__); - - str_list = gmyth_string_list_new(); - - g_mutex_lock(recorder->mutex); - - g_string_append_printf(tmp_str, " %d", recorder->recorder_num); - - gmyth_string_list_append_string(str_list, tmp_str); - g_string_free(tmp_str, TRUE); - - gmyth_string_list_append_char_array(str_list, "PAUSE"); - - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); - - tmp_str = gmyth_string_list_get_string(str_list, 0); - - if (tmp_str == NULL) { - gmyth_debug("[%s] PAUSE name request returned %s", __FUNCTION__, - tmp_str->str); - ret = FALSE; - goto cleanup; - } - - if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) { - gmyth_debug("[%s] PAUSE name request returned %s", __FUNCTION__, - tmp_str->str); - ret = FALSE; - goto cleanup; - } - - cleanup: - g_mutex_unlock(recorder->mutex); - g_string_free(tmp_str, TRUE); - g_object_unref(str_list); - - return ret; -} - -static gboolean -gmyth_recorder_find_if_program_exists(GMythRecorder * recorder, - GMythProgramInfo * prog) -{ - GList *lst = NULL; - - g_return_val_if_fail(recorder != NULL - && recorder->progs_info_list != NULL, FALSE); - - for (lst = recorder->progs_info_list; lst != NULL; - lst = g_list_next(lst)) { - gmyth_debug("Got program info from list = [%s]", - gmyth_program_info_to_string((GMythProgramInfo *) - lst->data)); - if (gmyth_program_info_is_equals - (prog, (GMythProgramInfo *) lst->data)) - return TRUE; - } - - return FALSE; -} - -/** - * Requests the actual program info from the MythTV backend server. - * - * @param recorder The GMythRecorder instance. - * @return The actual program info. - */ -GMythProgramInfo * -gmyth_recorder_get_current_program_info(GMythRecorder * recorder) -{ - GMythStringList *str_list = NULL; - GMythProgramInfo *program_info = NULL; - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); - - str_list = gmyth_string_list_new(); - - g_mutex_lock(recorder->mutex); - - g_string_append_printf(tmp_str, " %d", recorder->recorder_num); - - gmyth_string_list_append_string(str_list, tmp_str); - - if (recorder->myth_socket->mythtv_version >= 26) - gmyth_string_list_append_char_array(str_list, - "GET_CURRENT_RECORDING"); - else - gmyth_string_list_append_char_array(str_list, "GET_PROGRAM_INFO"); - - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); - - if (str_list == NULL) { - gmyth_debug - ("[%s] GET_PROGRAM_INFO request returned. Error getting program info, string list equals to NULL!", - __FUNCTION__); - goto cleanup; - } - - program_info = gmyth_program_info_from_string_list(str_list); - - if (NULL == program_info || NULL == program_info->pathname - || program_info->pathname->len <= 0) { - gmyth_debug - ("GET_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!"); - - if (program_info) - g_object_unref(program_info); - - program_info = NULL; - - goto cleanup; - } - - if (!gmyth_recorder_find_if_program_exists(recorder, program_info)) - recorder->progs_info_list = - g_list_append(recorder->progs_info_list, - g_object_ref(program_info)); - cleanup: - g_mutex_unlock(recorder->mutex); - g_string_free(tmp_str, TRUE); - g_object_unref(str_list); - - return program_info; -} - -/** - * Requests the actual program info from the MythTV backend server. - * - * @param rec_id The GMythRecorder record number. - * @return The GMythRecorder instance. - */ -GMythRecorder * -gmyth_recorder_get_recorder_from_num(gint rec_id) -{ - GMythRecorder *recorder = NULL; - GMythStringList *str_list; - GString *tmp_str = g_string_new("GET_RECORDER_FROM_NUM"); - gint command_size = 0; - - gchar *recorder_host = NULL; - gint recorder_port; - - str_list = gmyth_string_list_new(); - - /* - * g_string_append_printf ( tmp_str, " %d", recorder->recorder_num ); - */ - - g_mutex_lock(recorder->mutex); - - gmyth_string_list_append_string(str_list, tmp_str); - - gmyth_string_list_append_int(str_list, rec_id); - - command_size = - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, - str_list); - - if (str_list == NULL) { - gmyth_debug - ("[%s] GET_RECORDER_FROM_NUM request returned. Error getting recorder number %d, it is equals to NULL!!!", - __FUNCTION__, rec_id); - return NULL; - } - - if (command_size > 0) { - recorder_host = gmyth_string_list_get_char_array(str_list, 0); - recorder_port = gmyth_string_list_get_int(str_list, 1); - - if (g_strstr_len(recorder_host, strlen(recorder_host), "nohost") - != NULL) { - gmyth_debug - ("No available recorder with the recorder ID number %d!", - rec_id); - } else { - - recorder = gmyth_recorder_new(rec_id, - g_string_new(recorder_host), - (gshort) recorder_port); - - if (NULL == recorder) { - gmyth_debug - ("[%s] GET_RECORDER_FROM_NUM request returned. Error getting recorder number %d, it is equals to NULL!!!", - __FUNCTION__, rec_id); - g_object_unref(recorder); - return NULL; - } - - } - - } else { - gmyth_debug - ("Cannot find a valuable recorder with the recorder ID number %d, backend server error!", - rec_id); - } - - g_mutex_unlock(recorder->mutex); - - g_object_unref(str_list); - - g_string_free(tmp_str, TRUE); - - g_free(recorder_host); - - return recorder; - -} - -/** - * Requests the actual program info from the MythTV backend server. - * - * @param recorder The GMythRecorder instance. - * @param direction The direction to move based on the current channel (forward, backward, - * up, down). - * - * @return The GMythProgramInfo next program info instance. - */ -GMythProgramInfo * -gmyth_recorder_get_next_program_info(GMythRecorder * recorder, - const GMythRecorderBrowseDirection - direction) -{ - GMythProgramInfo *actual_proginfo = NULL; - GMythProgramInfo *program_info = NULL; - GMythStringList *str_list; - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); - - gchar *date = NULL; - struct tm *tm = NULL; - time_t t; - - actual_proginfo = gmyth_recorder_get_current_program_info(recorder); - - str_list = gmyth_string_list_new(); - - g_mutex_lock(recorder->mutex); - - g_string_append_printf(tmp_str, " %d", recorder->recorder_num); - - t = time(NULL); - tm = localtime(&t); - date = g_strdup_printf("%.4d%.2d%.2d%.2d%.2d%.2d", tm->tm_year + 1900, - tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, - tm->tm_min, tm->tm_sec); - - gmyth_string_list_append_string(str_list, tmp_str); - gmyth_string_list_append_char_array(str_list, "GET_NEXT_PROGRAM_INFO"); - gmyth_string_list_append_string(str_list, actual_proginfo->channame); - gmyth_string_list_append_int(str_list, actual_proginfo->channel_id); - gmyth_string_list_append_int(str_list, direction); - gmyth_string_list_append_char_array(str_list, date); - - if (gmyth_socket_sendreceive_stringlist - (recorder->myth_socket, str_list) - > 0) { - - if (str_list == NULL) { - gmyth_debug - ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!", - __FUNCTION__); - goto done; - } - program_info = - gmyth_program_info_from_string_list_next_prog(str_list); - - if (NULL == program_info) { - gmyth_debug - ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting next program info, it is equals to NULL!!!", - __FUNCTION__); - g_object_unref(program_info); - goto done; - } - - if ( /* ( program_info->chanid != NULL && - * strlen( program_info->chanid->str ) > 0 - * * * * * * ) && */ - (program_info->chansign != NULL - && strlen(program_info->chansign->str) > 0)) { - gmyth_debug("OK!!! Got the next program info... [%s].", - program_info->chansign->str); - } else { - gmyth_debug - ("GET_NEXT_PROGRAM_INFO request returned. Error getting next program info, it is equals to NULL!!!"); - g_object_unref(program_info); - program_info = NULL; - } - - } - /* - * if - */ - done: - - g_mutex_unlock(recorder->mutex); - - if (actual_proginfo != NULL) - g_object_unref(actual_proginfo); - - if (str_list != NULL) - g_object_unref(str_list); - - if (tmp_str != NULL) - g_string_free(tmp_str, TRUE); - - if (date != NULL) - g_free(date); - // if ( tm != NULL) - // g_free (tm); - - return program_info; -} - -/** - * Requests the program info from the MythTV backend server, based on its - * channel name. - * - * @param recorder The GMythRecorder instance. - * @return The GMythProgramInfo next program info instance. - */ -GMythProgramInfo * -gmyth_recorder_get_program_info_from_channel_name(GMythRecorder * recorder, - const gchar * channel) -{ - // GMythProgramInfo* actual_proginfo= NULL; - GMythProgramInfo *program_info = NULL; - GMythStringList *str_list; - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER); - - /* - * gchar *date = NULL; struct tm *tm = NULL; time_t t; - * - * actual_proginfo = - * gmyth_recorder_get_current_program_info(recorder); - */ - - str_list = gmyth_string_list_new(); - - g_mutex_lock(recorder->mutex); - - g_string_append_printf(tmp_str, " %d", recorder->recorder_num); - - /* - * t = time(NULL); tm = localtime(&t); date = - * g_strdup_printf("%.4d%.2d%.2d%.2d%.2d%.2d", tm->tm_year + 1900, - * tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - */ - - gmyth_string_list_append_string(str_list, tmp_str); - gmyth_string_list_append_char_array(str_list, "GET_NEXT_PROGRAM_INFO"); - gmyth_string_list_append_char_array(str_list, channel); - gmyth_string_list_append_char_array(str_list, "0"); - gmyth_string_list_append_int(str_list, BROWSE_DIRECTION_UP); - gmyth_string_list_append_char_array(str_list, "0"); - - do { - - if (str_list != NULL && - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, - str_list) > 0) { - - if (str_list == NULL) { - gmyth_debug - ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!", - __FUNCTION__); - goto done; - } - program_info = - gmyth_program_info_from_string_list_next_prog(str_list); - - if (NULL == program_info) { - gmyth_debug - ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting next program info, it is equals to NULL!!!", - __FUNCTION__); - g_object_unref(program_info); - goto done; - } - - if ( /* ( program_info->chanid != NULL && - * strlen( program_info->chanid->str ) > 0 - * * * * * * ) && */ - (program_info->chansign != NULL - && strlen(program_info->chansign->str) > 0)) { - gmyth_debug("OK!!! Got the next program info... [%s].", - program_info->chansign->str); - } else { - gmyth_debug - ("GET_NEXT_PROGRAM_INFO request returned. Error getting " - "next program info, it is equals to NULL!!!"); - g_object_unref(program_info); - program_info = NULL; - } - - } - /* - * if - */ - } - while (str_list != NULL); - - done: - - g_mutex_unlock(recorder->mutex); - - if (str_list != NULL) - g_object_unref(str_list); - - if (tmp_str != NULL) - g_string_free(tmp_str, TRUE); - - return program_info; -} - -/** - * Requests the actual remote file position on a LiveTV instance. - * - * @param recorder The GMythRecorder instance. - * - * @return The position, in bytes, of the offset to the read header. - */ -gint64 -gmyth_recorder_get_file_position(GMythRecorder * recorder) -{ - gint64 pos = 0; - GString *query = g_string_new(GMYTHTV_RECORDER_HEADER); - - GMythStringList *str_list = gmyth_string_list_new(); - - g_mutex_lock(recorder->mutex); - - g_string_append_printf(query, " %d", recorder->recorder_num); - - gmyth_string_list_append_string(str_list, query); - gmyth_string_list_append_char_array(str_list, "GET_FILE_POSITION"); - - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); - - if (str_list != NULL && gmyth_string_list_length(str_list) > 0) { - GString *str = NULL; - - if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL - && strstr(str->str, "bad") == NULL) - pos = gmyth_string_list_get_int64(str_list, 0); - g_string_free(str, TRUE); - } -#ifndef GMYTHTV_ENABLE_DEBUG - gmyth_debug("[%s] Got file position = %lld\n", __FUNCTION__, pos); -#endif - - g_mutex_unlock(recorder->mutex); - - if (str_list != NULL) - g_object_unref(str_list); - - g_string_free(query, TRUE); - - return pos; -} - -/** - * Asks MythTV backend server about if it started to record the remote file. - * - * @param recorder The GMythRecorder instance. - * - * @return true, if the actual remote file is bein recorded. - */ -gboolean -gmyth_recorder_is_recording(GMythRecorder * recorder) -{ - gboolean ret = TRUE; - - g_return_val_if_fail(recorder != NULL, FALSE); - - GMythStringList *str_list = gmyth_string_list_new(); - GString *message = g_string_new(""); - - g_mutex_lock(recorder->mutex); - - g_string_printf(message, "%s %d", GMYTHTV_RECORDER_HEADER, - recorder->recorder_num); - gmyth_string_list_append_string(str_list, message); - gmyth_string_list_append_char_array(str_list, "IS_RECORDING"); - - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); - - if (str_list != NULL && gmyth_string_list_length(str_list) > 0) { - GString *str = NULL; - - if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL - && strcmp(str->str, "bad") != 0) { - gint is_rec = - gmyth_string_list_get_int(str_list, 0); - - if (is_rec != 0) - ret = TRUE; - else - ret = FALSE; - } - g_string_free(str, TRUE); - } - - gmyth_debug("%s, stream is %s being recorded!\n", ret ? "YES" : "NO", - ret ? "" : "NOT"); - // g_static_mutex_unlock (&mutex); - - g_mutex_unlock(recorder->mutex); - - if (str_list != NULL) - g_object_unref(str_list); - - g_string_free(message, TRUE); - - return ret; - -} - -/** - * Finish remote file recording process. - * - * @param recorder The GMythRecorder instance. - * - * @return true, if the recording had been actually closed. - */ -gboolean -gmyth_recorder_finish_recording(GMythRecorder * recorder) -{ - gboolean ret = TRUE; - - g_return_val_if_fail(recorder != NULL, FALSE); - - GMythStringList *str_list = gmyth_string_list_new(); - GString *message = g_string_new(""); - - g_string_printf(message, "%s %d", GMYTHTV_RECORDER_HEADER, - recorder->recorder_num); - gmyth_string_list_append_string(str_list, message); - gmyth_string_list_append_char_array(str_list, "FINISH_RECORDING"); - - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); - - if (str_list != NULL && gmyth_string_list_length(str_list) > 0) { - GString *str = NULL; - - if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL && - strcmp(str->str, "ok") != 0) { - gint is_rec = - gmyth_string_list_get_int(str_list, 0); - - if (is_rec != 0) - ret = TRUE; - else - ret = FALSE; - } - g_string_free(str, TRUE); - } - - gmyth_debug("%s, stream is %s finished!\n", ret ? "YES" : "NO", - ret ? "" : "NOT"); - // g_static_mutex_unlock (&mutex); - - if (str_list != NULL) - g_object_unref(str_list); - - g_string_free(message, TRUE); - - return ret; -} - - -/** - * Stops playing the remote file. - * - * @param recorder The GMythRecorder instance. - * - * @return true, if the recording had been actually stopped. - */ -gboolean -gmyth_recorder_stop_playing(GMythRecorder * recorder) -{ - gboolean ret = TRUE; - - g_return_val_if_fail(recorder != NULL, FALSE); - - GMythStringList *str_list = gmyth_string_list_new(); - GString *message = g_string_new(""); - - g_string_printf(message, "%s %d", GMYTHTV_RECORDER_HEADER, - recorder->recorder_num); - gmyth_string_list_append_string(str_list, message); - gmyth_string_list_append_char_array(str_list, "STOP_PLAYING"); - - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); - - if (str_list != NULL && gmyth_string_list_length(str_list) > 0) { - GString *str = NULL; - - if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL && - strcmp(str->str, "ok") != 0) { - gint is_rec = - gmyth_string_list_get_int(str_list, 0); - - if (is_rec != 0) - ret = TRUE; - else - ret = FALSE; - } - g_string_free(str, TRUE); - } - - gmyth_debug("%s, stream is %s stopped!\n", ret ? "YES" : "NO", - ret ? "" : "NOT"); - - if (str_list != NULL) - g_object_unref(str_list); - - g_string_free(message, TRUE); - - return ret; -} - -/** - * Free the tuner responsible for recording this channel. - * - * @param recorder The GMythRecorder instance. - * - * @return true, if the tuner had been freed. - */ -gboolean -gmyth_recorder_free_tuner(GMythRecorder * recorder) -{ - gboolean ret = TRUE; - - g_return_val_if_fail(recorder != NULL, FALSE); - - GMythStringList *str_list = gmyth_string_list_new(); - GString *message = g_string_new(""); - - g_string_printf(message, "%s %d", "FREE_TUNER", - recorder->recorder_num); - gmyth_string_list_append_string(str_list, message); - - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); - - if (str_list != NULL && gmyth_string_list_length(str_list) > 0) { - GString *str = NULL; - - if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL && - g_ascii_strncasecmp(str->str, "ok", 2) != 0) { - gint is_rec = - gmyth_string_list_get_int(str_list, 0); - - if (is_rec != 0) - ret = TRUE; - else - ret = FALSE; - } - g_string_free(str, TRUE); - } - - gmyth_debug("%s, tuner is %s freed!\n", ret ? "YES" : "NO", - ret ? "" : "NOT"); - - if (str_list != NULL) - g_object_unref(str_list); - - g_string_free(message, TRUE); - - return ret; -} - -/** - * Asks the MythTV backend server about the frame rate - * of this LiveTV instance. - * - * @param recorder The GMythRecorder instance. - * - * @return The framerate (double value) of the current video. - */ -gdouble -gmyth_recorder_get_framerate(GMythRecorder * recorder) -{ - gdouble fr = 0.0f; - GString *query = g_string_new(GMYTHTV_RECORDER_HEADER); - - GMythStringList *str_list = gmyth_string_list_new(); - - g_mutex_lock(recorder->mutex); - - g_string_append_printf(query, " %d", recorder->recorder_num); - - gmyth_string_list_append_string(str_list, query); - gmyth_string_list_append_char_array(str_list, "GET_FRAMERATE"); - - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list); - - if (str_list != NULL && gmyth_string_list_length(str_list) > 0) { - GString *str = NULL; - - if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL - && strstr(str->str, "bad") == NULL) - fr = g_ascii_strtod(str->str, NULL); - - g_string_free(str, TRUE); - } -#ifndef GMYTHTV_ENABLE_DEBUG - gmyth_debug("[%s] Got file position = %f\n", __FUNCTION__, fr); -#endif - - g_mutex_unlock(recorder->mutex); - - if (str_list != NULL) - g_object_unref(str_list); - - g_string_free(query, TRUE); - - return fr; - -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_recorder.h --- a/gmyth/src/gmyth_recorder.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,162 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_recorder.h - * - * @brief

GMythRecorder defines functions for playing live tv. - * - * The remote encoder is used by gmyth_tvplayer to setup livetv. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Hallyson Luiz de Morais Melo - * @author Rosfran Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __GMYTH_RECORDER_H__ -#define __GMYTH_RECORDER_H__ - -#include - -#include "gmyth_socket.h" -#include "gmyth_programinfo.h" - -#include -#include -#include -#include -#include -#include - -G_BEGIN_DECLS -#define GMYTH_RECORDER_TYPE (gmyth_recorder_get_type ()) -#define GMYTH_RECORDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_RECORDER_TYPE, GMythRecorder)) -#define GMYTH_RECORDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECORDER_TYPE, GMythRecorderClass)) -#define IS_GMYTH_RECORDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_RECORDER_TYPE)) -#define IS_GMYTH_RECORDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECORDER_TYPE)) -#define GMYTH_RECORDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_RECORDER_TYPE, GMythRecorderClass)) -typedef struct _GMythRecorder GMythRecorder; -typedef struct _GMythRecorderClass GMythRecorderClass; - -struct _GMythRecorderClass { - GObjectClass parent_class; - - /* - * callbacks - */ - /* - * no one for now - */ -}; - -struct _GMythRecorder { - GObject parent; - - /* - * socket descriptor - */ - GMythSocket *myth_socket; - - gint recorder_num; - GString *hostname; - gint port; - - GList *progs_info_list; - - GMutex *mutex; -}; - -typedef enum _GMythRecorderChannelChangeDirection { - CHANNEL_DIRECTION_UP = 0, - CHANNEL_DIRECTION_DOWN, - CHANNEL_DIRECTION_FAVORITE, - CHANNEL_DIRECTION_SAME -} GMythRecorderChannelChangeDirection; - -typedef enum _GMythRecorderBrowseDirection { - BROWSE_DIRECTION_SAME = 0, /* Stay in the same place */ - BROWSE_DIRECTION_UP, /* Move up one slot (down one channel) */ - BROWSE_DIRECTION_DOWN, /* Move down one slot (up one channel) */ - BROWSE_DIRECTION_LEFT, /* Move left one slot (down one time slot) - */ - BROWSE_DIRECTION_RIGHT, /* Move right one slot (up one time slot) */ - BROWSE_DIRECTION_FAVORITE /* Move to the next favorite slot */ -} GMythRecorderBrowseDirection; - -GType gmyth_recorder_get_type(void); - -GMythRecorder *gmyth_recorder_new(int num, GString * hostname, - gshort port); - -void gmyth_recorder_close(GMythRecorder * recorder); - -gboolean gmyth_recorder_setup(GMythRecorder * recorder); -gboolean gmyth_recorder_spawntv(GMythRecorder * recorder, - GString * tvchain_id); - -gboolean gmyth_recorder_spawntv_no_tvchain(GMythRecorder * - recorder); - -gboolean gmyth_recorder_stop_livetv(GMythRecorder * recorder); - -gboolean gmyth_recorder_send_frontend_ready_command(GMythRecorder * - recorder); - -gboolean gmyth_recorder_check_channel(GMythRecorder * recorder, - gint channel); - -gboolean gmyth_recorder_check_channel_name(GMythRecorder * recorder, - gchar * channel); - -gboolean gmyth_recorder_set_channel(GMythRecorder * recorder, - gint channel); - -gboolean gmyth_recorder_set_channel_name(GMythRecorder * recorder, - const gchar * channel); - -gboolean gmyth_recorder_change_channel(GMythRecorder * recorder, const - GMythRecorderChannelChangeDirection - direction); - -GList *gmyth_recorder_get_channel_list(GMythRecorder * recorder); - -gboolean gmyth_recorder_pause_recording(GMythRecorder * recorder); - -GMythProgramInfo *gmyth_recorder_get_current_program_info(GMythRecorder * - recorder); - -GMythProgramInfo *gmyth_recorder_get_next_program_info(GMythRecorder * - recorder, const - GMythRecorderBrowseDirection - direction); - -GMythRecorder *gmyth_recorder_get_recorder_from_num(gint rec_id); - -gint64 gmyth_recorder_get_file_position(GMythRecorder * recorder); - -gboolean gmyth_recorder_is_recording(GMythRecorder * recorder); - -gboolean gmyth_recorder_finish_recording(GMythRecorder * recorder); - -gboolean gmyth_recorder_stop_playing(GMythRecorder * recorder); - -gboolean gmyth_recorder_free_tuner(GMythRecorder * recorder); - -gdouble gmyth_recorder_get_framerate(GMythRecorder * recorder); - -G_END_DECLS -#endif /* __GMYTH_REMOTE_ENCODER_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_recprofile.c --- a/gmyth/src/gmyth_recprofile.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,264 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_recprofile.c - * - * @brief

This file contains the recprofile class. - * - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. - * @author Artur Duque de Souza - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "gmyth_recprofile.h" -#include "gmyth_util.h" -#include "gmyth_debug.h" -#include "gmyth_http.h" - -static void gmyth_recprofile_class_init(GMythRecProfileClass * klass); -static void gmyth_recprofile_init(GMythRecProfile * object); - -static void gmyth_recprofile_dispose(GObject * object); -static void gmyth_recprofile_finalize(GObject * object); - -G_DEFINE_TYPE(GMythRecProfile, gmyth_recprofile, G_TYPE_OBJECT) - static void gmyth_recprofile_class_init(GMythRecProfileClass * - klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->dispose = gmyth_recprofile_dispose; - gobject_class->finalize = gmyth_recprofile_finalize; -} - -static void -gmyth_recprofile_init(GMythRecProfile * recprofile) -{ -} - -static void -gmyth_recprofile_dispose(GObject * object) -{ - GMythRecProfile *recprofile = GMYTH_RECPROFILE(object); - - if (recprofile->name) - g_free(recprofile->name); - - if (recprofile->group) - g_free(recprofile->group); - - if (recprofile->vcodec) - g_free(recprofile->vcodec); - - if (recprofile->acodec) - g_free(recprofile->acodec); - - if (recprofile->options) - g_free(recprofile->options); - - G_OBJECT_CLASS(gmyth_recprofile_parent_class)->dispose(object); -} - -static void -gmyth_recprofile_finalize(GObject * object) -{ - g_signal_handlers_destroy(object); - G_OBJECT_CLASS(gmyth_recprofile_parent_class)->finalize(object); -} - -/** - * Creates a new instance of GMythRecProfile. - * - * @return a new instance of GMythRecProfile. - **/ -GMythRecProfile * -gmyth_recprofile_new(void) -{ - GMythRecProfile *recprofile = GMYTH_RECPROFILE - (g_object_new(GMYTH_RECPROFILE_TYPE, NULL)); - - recprofile->id = 0; - recprofile->name = NULL; - recprofile->group = NULL; - recprofile->vcodec = NULL; - recprofile->acodec = NULL; - recprofile->options = NULL; - - return recprofile; -} - - -/** - * - * gmyth_recprofile_get_profile_list - * @brief get profile list from the backend - * @param backend_info GMythBackendInfo* - * @return GSList - * - **/ -GSList * -gmyth_recprofile_get_profile_list(GMythBackendInfo * backend_info) -{ - return gmyth_http_retrieve_rec_profiles(backend_info, "Transcoders"); -} - -/** - * - * gmyth_recprofile_create_profile - * @brief get profile list from the backend - * @param backend_info GMythBackendInfo* - * @param profile GMythRecProfile* - * @return gint representing the result - * - **/ -gint -gmyth_recprofile_create_profile(GMythBackendInfo * backend_info, - GMythRecProfile * profile) -{ - return gmyth_http_create_rec_profile(backend_info, profile); -} - -/** - * - * gmyth_recprofile_del_profile - * @brief del profile from the backend - * @param backend_info GMythBackendInfo* - * @param id profile's id - * @return gint representing the result - * - **/ -gint -gmyth_recprofile_del_profile_list(GMythBackendInfo * backend_info, gint id) -{ - return gmyth_http_del_rec_profile(backend_info, id); -} - -/** - * - * gmyth_recprofile_set_id - * @brief set recprofile's id - * @param rec GMythRecProfile* - * @param id profile's id - * @return gint representing the result - * - **/ -gint -gmyth_recprofile_set_id(GMythRecProfile * rec, gint id) -{ - rec->id = id; - return 0; -} - -/** - * - * gmyth_recprofile_set - * @brief set recprofile's property - * @param rec GMythRecProfile* - * @param member the member you want to modify - * @param value the value - * @return gint representing the result - * - **/ -gint -gmyth_recprofile_set(GMythRecProfile * rec, gchar * member, gchar * value) -{ - int ret = 0; - - if (value != NULL) { - if (g_ascii_strcasecmp(member, "name") == 0) - rec->name = g_strndup(value, strlen(value)); - else if (g_ascii_strcasecmp(member, "group") == 0) - rec->group = g_strndup(value, strlen(value)); - else if (g_ascii_strcasecmp(member, "vcodec") == 0) - rec->vcodec = g_strndup(value, strlen(value)); - else if (g_ascii_strcasecmp(member, "acodec") == 0) - rec->acodec = g_strndup(value, strlen(value)); - else - ret = -1; - } else - ret = -1; - - return ret; -} - -/** - * - * gmyth_recprofile_set_name - * @brief set recprofile's name - * @param rec GMythRecProfile* - * @param name profile's name - * @return gint representing the result - * - **/ -gint -gmyth_recprofile_set_name(GMythRecProfile * rec, gchar * name) -{ - return gmyth_recprofile_set(rec, "name", name); -} - -/** - * - * gmyth_recprofile_set_group - * @brief set recprofile's group - * @param rec GMythRecProfile* - * @param group profile's group - * @return gint representing the result - * - **/ -gint -gmyth_recprofile_set_group(GMythRecProfile * rec, gchar * group) -{ - return gmyth_recprofile_set(rec, "group", group); -} - -/** - * - * gmyth_recprofile_set_vcodec - * @brief set recprofile's vcodec - * @param rec GMythRecProfile* - * @param vcodec profile's vcodec - * @return gint representing the result - * - **/ -gint -gmyth_recprofile_set_vcodec(GMythRecProfile * rec, gchar * vcodec) -{ - return gmyth_recprofile_set(rec, "vcodec", vcodec); -} - -/** - * - * gmyth_recprofile_set_acodec - * @brief set recprofile's acodec - * @param rec GMythRecProfile* - * @param acodec profile's acodec - * @return gint representing the result - * - **/ -gint -gmyth_recprofile_set_acodec(GMythRecProfile * rec, gchar * acodec) -{ - return gmyth_recprofile_set(rec, "acodec", acodec); -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_recprofile.h --- a/gmyth/src/gmyth_recprofile.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_recprofile.h - * - * @brief

This file contains the recprofile class. - * - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. - * @author Artur Duque de Souza - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _GMYTH_RECPROFILE_H -#define _GMYTH_RECPROFILE_H - -#include -#include - -#include "gmyth_stringlist.h" -#include "gmyth_backendinfo.h" -#include "gmyth_socket.h" - -G_BEGIN_DECLS -#define GMYTH_RECPROFILE_TYPE (gmyth_recprofile_get_type ()) -#define GMYTH_RECPROFILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_RECPROFILE_TYPE, GMythRecProfile)) -#define GMYTH_RECPROFILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECPROFILE_TYPE, GMythRecProfileClass)) -#define IS_GMYTH_RECPROFILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_RECPROFILE_TYPE)) -#define IS_GMYTH_RECPROFILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECPROFILE_TYPE)) -#define GMYTH_RECPROFILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_RECPROFILE_TYPE, GMythRecProfileClass)) -typedef struct _Options Options; -typedef struct _GMythRecProfile GMythRecProfile; -typedef struct _GMythRecProfileClass GMythRecProfileClass; - -struct _GMythRecProfileClass { - GObjectClass parent_class; - gint teste; - /* - * callbacks - */ -}; - -struct _GMythRecProfile { - gint id; - gchar *name; - gchar *group; - gchar *vcodec; - gchar *acodec; - Options *options; -}; - -struct _Options { - gint transcodelossless; - gint transcoderesize; - gint width; - gint height; - gint rtjpegquality; - gint rtjpeglumafilter; - gint rtjpegchromafilter; - gint mpeg4bitrate; - gint mpeg4maxquality; - gint mpeg4minquality; - gint mpeg4qualdiff; - gint mpeg4scalebitrate; - gint mpeg4optionvhq; - gint mpeg4option4mv; - gint mpeg4optionidct; - gint mpeg4optionime; - gint hardwaremjpegquality; - gint hardwaremjpeghdecimation; - gint hardwaremjpegvdecimation; - gchar *mpeg2streamtype; - gchar *mpeg2aspectratio; - gint mpeg2bitrate; - gint mpeg2maxbitrate; - gint samplerate; - gint mp3quality; - gint volume; - gchar *mpeg2audtype; - gint mpeg2audbitratel1; - gint mpeg2audbitratel2; - gint mpeg2audvolume; -}; - -GType gmyth_recprofile_type(void); - -GMythRecProfile *gmyth_recprofile_new(void); - -GSList *gmyth_recprofile_get_profile_list(GMythBackendInfo * - backend_info); - -gint gmyth_recprofile_create_profile(GMythBackendInfo * - backend_info, - GMythRecProfile * profile); - -gint gmyth_recprofile_del_profile_list(GMythBackendInfo * - backend_info, gint id); - -gint gmyth_recprofile_set_acodec(GMythRecProfile * rec, - gchar * acodec); -gint gmyth_recprofile_set_vcodec(GMythRecProfile * rec, - gchar * vcodec); -gint gmyth_recprofile_set_group(GMythRecProfile * rec, - gchar * group); -gint gmyth_recprofile_set_name(GMythRecProfile * rec, - gchar * name); -gint gmyth_recprofile_set_id(GMythRecProfile * rec, gint id); - -G_END_DECLS -#endif /*_GMYTH_RECPROFILE_H*/ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_remote_util.c --- a/gmyth/src/gmyth_remote_util.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_remote_util.c - * - * @brief

This component provides utility functions for accessing remote data. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Hallyson Luiz de Morais Melo - * @author Rosfran Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gmyth_remote_util.h" - -#include "gmyth_recorder.h" -#include "gmyth_stringlist.h" -#include "gmyth_debug.h" - -/** - * Requests the Mythtv backend for a free remote recorder. - * - * @param socket The socket instance where to send the command. - * @param curr The recorder index, or -1 to consider the first one. - * - * @return the remote encoder instance available, or NULL if any error happens. - */ -GMythRecorder * -remote_request_next_free_recorder(GMythSocket * socket, gint curr) -{ - GMythRecorder *recorder = NULL; - GString *hostname; - gint num, - port; - - GMythStringList *strlist = gmyth_string_list_new(); - - gmyth_debug("[%s] Request next free recorder in the backend", - __FUNCTION__); - - gmyth_string_list_append_char_array(strlist, "GET_NEXT_FREE_RECORDER"); - gmyth_string_list_append_int(strlist, curr); - - if (!gmyth_socket_sendreceive_stringlist(socket, strlist)) { - g_warning("GET_NEXT_FREE_RECORDER request error!\n"); - return NULL; - } - - num = gmyth_string_list_get_int(strlist, 0); - hostname = gmyth_string_list_get_string(strlist, 1); - port = gmyth_string_list_get_int(strlist, 2); - - if (num < 0 || port < 0) - goto clean_up; - - gmyth_debug - ("[%s] Free recorder info received: num: %d, hostname: %s, port: %d", - __FUNCTION__, num, hostname->str, port); - - recorder = gmyth_recorder_new(num, hostname, port); - - clean_up: - - g_string_free(hostname, TRUE); - g_object_unref(strlist); - - return recorder; -} - -/** - * Requests the Mythtv backend for the number of free remote recorders. - * - * @param socket The socket instance where to send the command. - * - * @return the number of remote encoders instance available, or 0 if no one is actually free.. - */ -gint -gmyth_remote_util_get_free_recorder_count(GMythSocket * socket) -{ - gint num_recs = 0; - - GMythStringList *strlist = gmyth_string_list_new(); - - gmyth_debug("[%s] Request next free recorder in the backend", - __FUNCTION__); - - gmyth_string_list_append_char_array(strlist, - "GET_FREE_RECORDER_COUNT"); - - if (!gmyth_socket_sendreceive_stringlist(socket, strlist)) { - gmyth_debug("GET_FREE_RECORDER_COUNT request error!"); - return 0; - } - - num_recs = gmyth_string_list_get_int(strlist, 0); - - if (num_recs < 0) - goto clean_up; - - gmyth_debug("[%s] Free recorder info received: num recorders: %d", - __FUNCTION__, num_recs); - - clean_up: - - g_object_unref(strlist); - - return num_recs; -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_remote_util.h --- a/gmyth/src/gmyth_remote_util.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_remote_util.h - * - * @brief

This component provides utility functions for accessing remote data. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Hallyson Luiz de Morais Melo - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __REMOTE_UTIL_H__ -#define __REMOTE_UTIL_H__ - -#include -#include "gmyth_recorder.h" -#include "gmyth_socket.h" - -G_BEGIN_DECLS - GMythRecorder * remote_request_next_free_recorder(GMythSocket * socket, - gint curr); -gint gmyth_remote_util_get_free_recorder_count(GMythSocket * - socket); - -G_END_DECLS -#endif diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_scheduler.c --- a/gmyth/src/gmyth_scheduler.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1266 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_scheduler.c - * - * @brief

The scheduler encapsulates all functions for browsing, scheduling - * and modifying the recorded content. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Alexsandro Jose Virginio dos Santos - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include -#include - -#include "gmyth_scheduler.h" -#include "gmyth_util.h" -#include "gmyth_query.h" -#include "gmyth_socket.h" -#include "gmyth_debug.h" - -static void gmyth_scheduler_class_init(GMythSchedulerClass * klass); -static void gmyth_scheduler_init(GMythScheduler * object); - -static void gmyth_scheduler_dispose(GObject * object); -static void gmyth_scheduler_finalize(GObject * object); - -static gboolean update_backend(GMythScheduler * scheduler, gint record_id); - -G_DEFINE_TYPE(GMythScheduler, gmyth_scheduler, G_TYPE_OBJECT) - static void gmyth_scheduler_class_init(GMythSchedulerClass * klass) -{ - GObjectClass *gobject_class; - - gobject_class = (GObjectClass *) klass; - - gobject_class->dispose = gmyth_scheduler_dispose; - gobject_class->finalize = gmyth_scheduler_finalize; -} - -static void -gmyth_scheduler_init(GMythScheduler * sched) -{ - sched->recordid = 0; - sched->type = 0; - sched->search = 0; - sched->profile = g_string_new(""); - - sched->dupin = 0; - sched->dupmethod = 0; - sched->autoexpire = 0; - sched->autotranscode = 0; - sched->transcoder = 0; - - sched->autocommflag = 0; - sched->autouserjob1 = 0; - sched->autouserjob2 = 0; - sched->autouserjob3 = 0; - sched->autouserjob4 = 0; - - sched->startoffset = 0; - sched->endoffset = 0; - sched->maxepisodes = 0; - sched->maxnewest = 0; - - sched->recpriority = 0; - sched->recgroup = g_string_new(""); - sched->playgroup = g_string_new(""); - - sched->prefinput = 0; - sched->inactive = 0; - - sched->search_type = g_string_new(""); - sched->search_what = g_string_new(""); - - sched->msqlquery = gmyth_query_new(); -} - -static void -gmyth_scheduler_dispose(GObject * object) -{ - GMythScheduler *scheduler = GMYTH_SCHEDULER(object); - - if (scheduler->backend_info) { - g_object_unref(scheduler->backend_info); - scheduler->backend_info = NULL; - } - - if (scheduler->msqlquery) { - g_object_unref(scheduler->msqlquery); - scheduler->msqlquery = NULL; - } - - g_string_free(scheduler->profile, TRUE); - g_string_free(scheduler->recgroup, TRUE); - g_string_free(scheduler->playgroup, TRUE); - g_string_free(scheduler->search_type, TRUE); - g_string_free(scheduler->search_what, TRUE); - - G_OBJECT_CLASS(gmyth_scheduler_parent_class)->dispose(object); -} - -static void -gmyth_scheduler_finalize(GObject * object) -{ - g_signal_handlers_destroy(object); - - G_OBJECT_CLASS(gmyth_scheduler_parent_class)->finalize(object); -} - -/** Creates a new instance of GMythScheduler. - * - * @return a new instance of GMythScheduler. - */ -GMythScheduler * -gmyth_scheduler_new() -{ - GMythScheduler *scheduler = - GMYTH_SCHEDULER(g_object_new(GMYTH_SCHEDULER_TYPE, NULL)); - - return scheduler; -} - -gboolean -gmyth_scheduler_connect(GMythScheduler * scheduler, - GMythBackendInfo * backend_info) -{ - return gmyth_scheduler_connect_with_timeout(scheduler, backend_info, - 0); -} - -/** Connects to the Mysql database in the backend. The backend address - * is loaded from the GMythSettings instance. - * - * @param scheduler the GMythScheduler instance to be connected. - * @return true if connection was success, false if failed. - */ -gboolean -gmyth_scheduler_connect_with_timeout(GMythScheduler * scheduler, - GMythBackendInfo * backend_info, - guint timeout) -{ - assert(scheduler); - g_return_val_if_fail(backend_info != NULL, FALSE); - - if (scheduler->backend_info) - g_object_unref(scheduler->backend_info); - - scheduler->backend_info = g_object_ref(backend_info); - - if (scheduler->msqlquery == NULL) { - g_warning("[%s] GMythScheduler db initializing", __FUNCTION__); - scheduler->msqlquery = gmyth_query_new(); - } - - if (!gmyth_query_connect_with_timeout(scheduler->msqlquery, - scheduler->backend_info, - timeout)) { - g_warning("[%s] Error while connecting to db", __FUNCTION__); - return FALSE; - } - - return TRUE; -} - -/** Disconnects from the Mysql database in the backend. - * - * @param scheduler the GMythScheduler instance to be disconnected - * @return true if disconnection was success, false if failed. - */ -gboolean -gmyth_scheduler_disconnect(GMythScheduler * scheduler) -{ - assert(scheduler); - - if (scheduler->msqlquery != NULL) { - gmyth_query_disconnect(scheduler->msqlquery); - } - - return TRUE; -} - -/** Retrieves from the backend Mysql database the list of recording schedules. - * - * @param scheduler The GMythScheduler instance. - * @param schedule_list the GList pointer to be filled with the loaded list of ScheduleInfo items. - * @return The amount of schedules retrieved from database, or -1 if error. - */ -gint -gmyth_scheduler_get_schedule_list(GMythScheduler * scheduler, - GList ** schedule_list) -{ - ScheduleInfo *schedule; - MYSQL_RES *msql_res; - GString *query_str = g_string_new(""); - gchar *date_time = NULL; - - assert(scheduler); - - g_string_printf(query_str, - "SELECT recordid,programid,chanid,starttime,startdate," - "endtime,enddate,title,subtitle,description,category,type,parentid,seriesid FROM record;"); - - if (scheduler->msqlquery == NULL) { - g_warning("[%s] Scheduler db connection not initialized", - __FUNCTION__); - return -1; - } - msql_res = - gmyth_query_process_statement(scheduler->msqlquery, - query_str->str); - - if (msql_res == NULL) { - g_warning("DB retrieval of schedule list failed"); - return -1; - } else { - MYSQL_ROW row; - - *schedule_list = NULL; - - while ((row = mysql_fetch_row(msql_res)) != NULL) { - schedule = g_new0(ScheduleInfo, 1); - gint type = 0; - - schedule->schedule_id = - (guint) g_ascii_strtoull(row[0], NULL, 10); - schedule->program_id = g_string_new (row[1]); - schedule->channel_id = (gint) g_ascii_strtoull (row[2], NULL, 10); - - /* - * generate a time_t from a time and a date db field - */ - date_time = g_strdup_printf("%sT%s", row[4], row[3]); - schedule->start_time = - gmyth_util_string_to_time_val(date_time); - g_free(date_time); - - /* - * generate a time_t from a time and a date db field - */ - date_time = g_strdup_printf("%sT%s", row[6], row[5]); - schedule->end_time = gmyth_util_string_to_time_val(date_time); - g_free(date_time); - - schedule->title = g_string_new(row[7]); - schedule->subtitle = g_string_new(row[8]); - schedule->description = g_string_new(row[9]); - schedule->category = g_string_new(row[10]); - type = g_ascii_strtoull (row[11], NULL, 10); - if (type == 4) { - schedule->type = GMYTH_SCHEDULE_ALL_OCCURRENCES; - } else if (type == 1) { - schedule->type = GMYTH_SCHEDULE_ONE_OCCURRENCE; - } else if (type == 8) { - schedule->type = GMYTH_SCHEDULE_EXCEPTION; - schedule->parentid = (gint) g_ascii_strtoull (row[12], NULL, 10); - } - - schedule->seriesid = g_string_new (row[13]); - - (*schedule_list) = g_list_append(*(schedule_list), schedule); - } - } - - mysql_free_result(msql_res); - g_string_free(query_str, TRUE); - - return (*schedule_list == NULL) ? 0 : g_list_length(*schedule_list); -} - -/** Retrieves from the backend Mysql database the list of recorded programs. - * - * @param scheduler The GMythScheduler instance. - * @param recorded_list the GList pointer to be filled with the loaded RecordInfo items. - * @return The amount of recorded retrieved from database, or -1 if error. - */ -gint -gmyth_scheduler_get_recorded_list(GMythScheduler * scheduler, - GList ** recorded_list) -{ - RecordedInfo *record; - MYSQL_RES *msql_res; - GString *query_str = g_string_new(""); - - assert(scheduler); - - g_string_printf(query_str, - "SELECT recordid,programid,chanid,starttime,progstart," - "endtime,progend,title,subtitle,description,category," - "filesize,basename,seriesid FROM recorded WHERE recgroup != 'LiveTV'"); - - if (scheduler->msqlquery == NULL) { - g_warning("[%s] Scheduler db connection not initialized", - __FUNCTION__); - return -1; - } - - msql_res = - gmyth_query_process_statement(scheduler->msqlquery, - query_str->str); - - if (msql_res == NULL) { - g_warning("DB retrieval of recording list failed"); - return -1; - } else { - MYSQL_ROW row; - - (*recorded_list) = NULL; - - while ((row = mysql_fetch_row(msql_res)) != NULL) { - record = g_new0(RecordedInfo, 1); - - record->record_id = (guint) g_ascii_strtoull(row[0], NULL, 10); - record->program_id = g_string_new (row[1]); - record->channel_id = (gint) g_ascii_strtoull(row[2], NULL, 10); - record->start_time = gmyth_util_string_to_time_val(row[3]); - record->end_time = gmyth_util_string_to_time_val(row[5]); - - record->title = g_string_new(row[7]); - record->subtitle = g_string_new(row[8]); - record->description = g_string_new(row[9]); - record->category = g_string_new(row[10]); - record->filesize = g_ascii_strtoull(row[11], NULL, 10); - record->basename = g_string_new(row[12]); - record->seriesid = g_string_new(row[13]); - - (*recorded_list) = g_list_append((*recorded_list), record); - } - } - - mysql_free_result(msql_res); - g_string_free(query_str, TRUE); - - return (*recorded_list == NULL) ? 0 : g_list_length(*recorded_list); -} - -RecordedInfo* -gmyth_scheduler_get_recorded_info (GMythScheduler *scheduler, - const gchar* basename) -{ - RecordedInfo *record = NULL; - MYSQL_RES *msql_res; - GString *query_str = g_string_new(""); - - assert(scheduler); - - g_string_printf(query_str, - "SELECT recordid,programid,chanid,starttime,progstart," - "endtime,progend,title,subtitle,description,category," - "filesize,basename,seriesid FROM recorded " - "WHERE recgroup != 'LiveTV' AND basename = '%s'", basename); - - if (scheduler->msqlquery == NULL) { - g_warning("[%s] Scheduler db connection not initialized", - __FUNCTION__); - return NULL; - } - - msql_res = - gmyth_query_process_statement(scheduler->msqlquery, - query_str->str); - - if (msql_res == NULL) { - g_warning("DB retrieval of recording list failed"); - return NULL; - } else { - MYSQL_ROW row; - row = mysql_fetch_row(msql_res); - if (row != NULL) { - record = g_new0(RecordedInfo, 1); - record->record_id = (guint) g_ascii_strtoull(row[0], NULL, 10); - record->program_id = g_string_new (row[1]); - record->channel_id = (gint) g_ascii_strtoull(row[2], NULL, 10); - record->start_time = gmyth_util_string_to_time_val(row[3]); - record->end_time = gmyth_util_string_to_time_val(row[5]); - record->title = g_string_new(row[7]); - record->subtitle = g_string_new(row[8]); - record->description = g_string_new(row[9]); - record->category = g_string_new(row[10]); - record->filesize = g_ascii_strtoull(row[11], NULL, 10); - record->basename = g_string_new(row[12]); - record->seriesid = g_string_new(row[13]); - } - } - - mysql_free_result(msql_res); - g_string_free(query_str, TRUE); - - return record; -} - - -static void -_set_value(GMythQuery * myth_query, char *field, gchar * value, - gint rec_id) -{ - gchar *query = - g_strdup_printf - ("UPDATE record SET recordid = %d, %s = \"%s\" WHERE recordid = %d;", - rec_id, field, value, rec_id); - - gmyth_query_process_statement(myth_query, query); - g_free(query); -} - -static void -_set_int_value(GMythQuery * myth_query, char *field, gint value, - gint rec_id) -{ - gchar *str_value = g_strdup_printf("%d", value); - - _set_value(myth_query, field, str_value, rec_id); - g_free(str_value); -} - -ScheduleInfo* -gmyth_scheduler_add_schedule_program (GMythScheduler * scheduler, - GMythProgramInfo *program, - GMythScheduleType type) -{ - ScheduleInfo *info; - - info = g_new0 (ScheduleInfo, 1); - info->program_id = g_string_new (program->program_id->str); - info->channel_id = program->channel_id; - info->start_time = g_new0 (GTimeVal, 1); - *info->start_time = *program->startts; - info->end_time = g_new0 (GTimeVal, 1); - *info->end_time = *program->endts; - info->seriesid = g_string_new (program->seriesid->str); - info->title = g_string_new (program->title->str); - info->subtitle = g_string_new (program->subtitle->str); - info->description = g_string_new (program->description->str); - info->category = g_string_new (program->category->str); - info->type = type; - - if (gmyth_scheduler_add_schedule_full (scheduler, info, type)) - { - if (!program->recstartts) - program->recstartts = g_new0 (GTimeVal, 1); - *program->recstartts = *info->start_time; - - if (!program->recendts) - program->recendts = g_new0 (GTimeVal, 1); - *program->recendts = *info->end_time; - - program->recordid = info->schedule_id; - return info; - } - - gmyth_schedule_info_free (info); - return NULL; -} - - -gboolean -gmyth_scheduler_add_schedule_full (GMythScheduler * scheduler, - ScheduleInfo * schedule_info, GMythScheduleType type) -{ - MYSQL_RES *msql_res; - gchar *query_str = "INSERT record (recordid) VALUE (0);"; - gchar *station = NULL; - gulong rec_id; - - g_return_val_if_fail (IS_GMYTH_SCHEDULER (scheduler), FALSE); - - if (scheduler->msqlquery == NULL) { - g_warning("[%s] Scheduler db connection not initialized", - __FUNCTION__); - return FALSE; - } - - msql_res = - gmyth_query_process_statement_with_increment(scheduler->msqlquery, - query_str, &rec_id); - mysql_free_result(msql_res); - - // Retrieves the station info - query_str = - g_strdup_printf - ("SELECT callsign FROM channel WHERE chanid = %d;", - schedule_info->channel_id); - msql_res = - gmyth_query_process_statement(scheduler->msqlquery, query_str); - if (msql_res == NULL) { - g_warning("[%s] msql query returned NULL MYSQL_RES", __FUNCTION__); - return FALSE; - } else { - MYSQL_ROW row; - - if ((row = mysql_fetch_row(msql_res)) != NULL) { - station = g_strdup(row[0]); - } - } - mysql_free_result(msql_res); - g_free(query_str); - - // _set_value (field, value, id); - _set_int_value(scheduler->msqlquery, "chanid", - schedule_info->channel_id, rec_id); - _set_value(scheduler->msqlquery, "station", station, rec_id); - _set_value(scheduler->msqlquery, "title", schedule_info->title->str, - rec_id); - // / subtitle, description - _set_value(scheduler->msqlquery, "starttime", - gmyth_util_time_to_string_only_time(schedule_info-> - start_time), rec_id); - _set_value(scheduler->msqlquery, "startdate", - gmyth_util_time_to_string_only_date(schedule_info-> - start_time), rec_id); - _set_value(scheduler->msqlquery, "endtime", - gmyth_util_time_to_string_only_time(schedule_info-> - end_time), rec_id); - _set_value(scheduler->msqlquery, "enddate", - gmyth_util_time_to_string_only_date(schedule_info-> - end_time), rec_id); - // / category, series id, program id - // _set_value (scheduler->msqlquery, "findday", - // (gmyth_util_time_val_to_date( schedule_info->start_time - // ))->tm_wday, rec_id); - // _set_value (scheduler->msqlquery, "findtime", - // gmyth_util_time_to_string_only_time( schedule_info->start_time), - // rec_id); - // _set_int_value (scheduler->msqlquery, "findid", - // (gint)(schedule_info->start_time->tv_sec/60/60/24 + 719528), - // rec_id); - - if (schedule_info->seriesid) - _set_value(scheduler->msqlquery, "seriesid", - schedule_info->seriesid->str, rec_id); - - _set_value(scheduler->msqlquery, "parentid", "0", rec_id); - _set_value(scheduler->msqlquery, "search", "0", rec_id); - - if (type == GMYTH_SCHEDULE_ALL_OCCURRENCES) { - _set_int_value(scheduler->msqlquery, "type", 3, rec_id); - } else if (type == GMYTH_SCHEDULE_ONE_OCCURRENCE) { - _set_int_value(scheduler->msqlquery, "type", 1, rec_id); - } else if (type == GMYTH_SCHEDULE_EXCEPTION) { - _set_int_value(scheduler->msqlquery, "type", 8, rec_id); - _set_int_value(scheduler->msqlquery, "parentid", schedule_info->parentid, - rec_id); - } - - _set_value(scheduler->msqlquery, "recpriority", "0", rec_id); - _set_value(scheduler->msqlquery, "startoffset", "0", rec_id); - _set_value(scheduler->msqlquery, "endoffset", "0", rec_id); - _set_value(scheduler->msqlquery, "dupmethod", "6", rec_id); // ? - _set_value(scheduler->msqlquery, "dupin", "15", rec_id); // ? - - _set_value(scheduler->msqlquery, "prefinput", "0", rec_id); - _set_value(scheduler->msqlquery, "inactive", "0", rec_id); - _set_value(scheduler->msqlquery, "profile", "Default", rec_id); - _set_value(scheduler->msqlquery, "recgroup", "Default", rec_id); - _set_value(scheduler->msqlquery, "storagegroup", "Default", rec_id); - _set_value(scheduler->msqlquery, "playgroup", "Default", rec_id); - _set_value(scheduler->msqlquery, "autoexpire", "1", rec_id); - _set_value(scheduler->msqlquery, "maxepisodes", "0", rec_id); - _set_value(scheduler->msqlquery, "maxnewest", "0", rec_id); - _set_value(scheduler->msqlquery, "autocommflag", "1", rec_id); - _set_value(scheduler->msqlquery, "autotranscode", "0", rec_id); - _set_value(scheduler->msqlquery, "transcoder", "0", rec_id); - - _set_value(scheduler->msqlquery, "autouserjob1", "0", rec_id); - _set_value(scheduler->msqlquery, "autouserjob2", "0", rec_id); - _set_value(scheduler->msqlquery, "autouserjob3", "0", rec_id); - _set_value(scheduler->msqlquery, "autouserjob4", "0", rec_id); - - schedule_info->schedule_id = rec_id; - - /* Notify the backend of changes */ - return update_backend(scheduler, rec_id); -} - -/** Requests the Mysql database in the backend to add a new schedule. - * - * @param scheduler the GMythScheduler instance. - * @param schedule_info the ScheduleInfo with recording schedule information - * to be added. record_id = -1 to add a new schedule, otherwise this - * function will update the schedule in the db - * @return gboolean returns FALSE if some error occurs, TRUE otherwise - */ -gboolean -gmyth_scheduler_add_schedule (GMythScheduler * scheduler, - ScheduleInfo * schedule_info) -{ - return gmyth_scheduler_add_schedule_full (scheduler, schedule_info, - GMYTH_SCHEDULE_ONE_OCCURRENCE); -} - -/** Requests the Mysql database in the backend to remove an existing schedule. - * - * @param scheduler the GMythScheduler instance. - * @param schedule_id The schedule's record id to be removed - * @return gboolean TRUE if success, FALSE if error - */ -gboolean -gmyth_scheduler_delete_schedule(GMythScheduler * scheduler, gint schedule_id) -{ - - MYSQL_RES *msql_res; - GString *query_str = NULL; - - g_return_val_if_fail (scheduler != NULL, FALSE); - - - if (scheduler->msqlquery == NULL) { - g_warning("[%s] Scheduler db connection not initialized", - __FUNCTION__); - return FALSE; - } - - query_str = g_string_new(""); - g_string_printf(query_str, - "DELETE FROM record WHERE recordid=%d", schedule_id); - - msql_res = - gmyth_query_process_statement(scheduler->msqlquery, - query_str->str); - - - mysql_free_result(msql_res); - g_string_free(query_str, TRUE); - - // Notify the backend of the changes - return update_backend(scheduler, schedule_id); -} - -/* - * Add an exception program to be removed from the schedule list, when programs - * where scheduled with the GMYTH_SCHEDULE_ALL_OCCURRENCES option. - * @param scheduler the GMythScheduler instance. - * @param schedule_id the schedule id of the all occurrence schedule to be changed - * @param exception_info the ScheduleInfo to be removed from all schedule occurrences - * @return TRUE if success, FALSE if any error happens - */ -gboolean -gmyth_scheduler_add_exception (GMythScheduler *scheduler, gint schedule_id, - ScheduleInfo *exception_info) -{ - gboolean res; - - g_return_val_if_fail (scheduler != NULL, FALSE); - g_return_val_if_fail (exception_info != NULL, FALSE); - - exception_info->parentid = schedule_id; - res = gmyth_scheduler_add_schedule_full (scheduler, exception_info, GMYTH_SCHEDULE_EXCEPTION); - - return res; -} - -/** Requests the Mysql database in the backend to remove an existing recorded item. - * - * @param scheduler the GMythScheduler instance. - * @param record_id The recorded item id to be removed - * @return gboolean TRUE if success, FALSE if error - */ -gboolean -gmyth_scheduler_delete_recorded(GMythScheduler * scheduler, gint record_id) -{ - - MYSQL_RES *msql_res; - - GString *query_str = g_string_new(""); - - assert(scheduler); - - if (scheduler->msqlquery == NULL) { - g_warning("[%s] Scheduler db connection not initialized", - __FUNCTION__); - return FALSE; - } - // ======================================== - g_string_printf(query_str, - "DELETE FROM recorded WHERE recordid=%d", record_id); - - // FIXME: Mythtv implementation runs also: DELETE FROM oldfind WHERE - // recordid = x - - msql_res = - gmyth_query_process_statement(scheduler->msqlquery, - query_str->str); - - mysql_free_result(msql_res); - g_string_free(query_str, TRUE); - - // Notify the backend of the changes - return update_backend(scheduler, record_id); -} - - -gboolean gmyth_scheduler_was_recorded_before(GMythScheduler* scheduler, gint channel_id, - time_t start_time) -{ - MYSQL_RES *msql_res; - GString *query_str = g_string_new(""); - - assert(scheduler); - g_string_printf(query_str, "SELECT callsign FROM channel " - "WHERE chanid = \"%d\"", channel_id); - - msql_res = gmyth_query_process_statement(scheduler->msqlquery, query_str->str); - - if (msql_res) { - MYSQL_ROW msql_row = mysql_fetch_row(msql_res); - if (msql_row) { - GString* callsign = g_string_new(msql_row[0]); - GString* startts = gmyth_util_time_to_string(start_time); - g_string_printf(query_str, "SELECT * FROM oldrecorded " - "WHERE station = \"%s\" AND starttime = \"%s\"", - callsign->str, startts->str); - msql_res = gmyth_query_process_statement(scheduler->msqlquery, query_str->str); - g_string_free(callsign, TRUE); - g_string_free(startts, TRUE); - g_string_free(query_str, TRUE); - if (mysql_fetch_row(msql_res)) return TRUE; - } - } - return FALSE; -} - - -gboolean gmyth_scheduler_reactivate_schedule(GMythScheduler* scheduler, gint channel_id, - time_t start_time) - -{ - MYSQL_RES *msql_res; - GString *query_str = g_string_new(""); - - assert(scheduler); - g_string_printf(query_str, "SELECT callsign FROM channel " - "WHERE chanid = \"%d\"", channel_id); - - msql_res = gmyth_query_process_statement(scheduler->msqlquery, query_str->str); - if (msql_res) { - MYSQL_ROW msql_row = mysql_fetch_row(msql_res); - if (msql_row) { - GString* callsign = g_string_new(msql_row[0]); - GString* startts = gmyth_util_time_to_string(start_time); - g_string_printf(query_str, "UPDATE oldrecorded SET reactivate = 1 " - "WHERE station = \"%s\" AND starttime = \"%s\"", - callsign->str, startts->str); - gmyth_query_process_statement(scheduler->msqlquery, query_str->str); - g_string_free(callsign, TRUE); - g_string_free(startts, TRUE); - g_string_free(query_str, TRUE); - return TRUE; - } - - } - - return FALSE; -} - - -/* - * This should only be used in special situations. We do not know the time that - * the recording was set. We just know that it is an "ongoing" record and then - * we have to use this to get it's info. It's always the oldest one -> first on list - * - */ -GMythProgramInfo* -gmyth_scheduler_get_recorded_on_time(GMythScheduler* scheduler, - guint channel_id) -{ - MYSQL_RES *msql_res; - GMythProgramInfo *proginfo = NULL; - GString *query_str = g_string_new(""); - - assert(scheduler); - - g_string_printf(query_str, - "SELECT recorded.chanid,starttime,endtime,title," - "subtitle,description,channel.channum," - "channel.callsign,channel.name,channel.commfree," - "channel.outputfilters,seriesid,programid,filesize," - "lastmodified,stars,previouslyshown,originalairdate," - "hostname,recordid,transcoder,playgroup," - "recorded.recpriority,progstart,progend,basename,recgroup," - "category,findid,duplicate " - "FROM recorded " "LEFT JOIN channel " - "ON recorded.chanid = channel.chanid " - "WHERE recorded.chanid = %d " - "ORDER BY starttime DESC", channel_id); - - msql_res = - gmyth_query_process_statement(scheduler->msqlquery, query_str->str); - - if (msql_res) { - MYSQL_ROW msql_row = mysql_fetch_row(msql_res); - - if (msql_row) { - proginfo = gmyth_program_info_new(); - - proginfo->channel_id = (gint) g_ascii_strtoull (msql_row[0], NULL, 10); - proginfo->recstartts = gmyth_util_string_to_time_val(msql_row[1]); - proginfo->recendts = gmyth_util_string_to_time_val(msql_row[2]); - - proginfo->title = g_string_new(msql_row[3]); - proginfo->subtitle = g_string_new(msql_row[4]); - proginfo->description = g_string_new(msql_row[5]); - - proginfo->chanstr = g_string_new(msql_row[6]); - proginfo->chansign = g_string_new(msql_row[7]); - proginfo->channame = g_string_new(msql_row[8]); - proginfo->chancommfree = (gint) g_ascii_strtoull(msql_row[9], NULL, 10); - proginfo->chanOutputFilters = g_string_new(msql_row[10]); - proginfo->seriesid = g_string_new(msql_row[11]); - proginfo->program_id = g_string_new(msql_row[12]); - proginfo->filesize = g_ascii_strtoull(msql_row[13], NULL, 10); - - proginfo->lastmodified = gmyth_util_string_to_time_val(msql_row[14]); - proginfo->stars = g_ascii_strtod(msql_row[15], NULL); - proginfo->repeat = (gint)g_ascii_strtoull(msql_row[16], NULL, 10); - - if (msql_row[17] == NULL) { - proginfo->originalAirDate = 0; - proginfo->hasAirDate = FALSE; - } else { - proginfo->originalAirDate = gmyth_util_string_to_time_val(msql_row[17]); - proginfo->hasAirDate = TRUE; - } - - proginfo->hostname = g_string_new(msql_row[18]); - proginfo->recordid = (gint) g_ascii_strtoull(msql_row[19], NULL, 10); - proginfo->transcoder = (gint) g_ascii_strtoull(msql_row[20], NULL, 10); - - proginfo->playgroup = g_string_new(msql_row[21]); - proginfo->recpriority = (gint) g_ascii_strtoull(msql_row[22], NULL, 10); - - proginfo->startts = gmyth_util_string_to_time_val(msql_row[23]); - proginfo->endts = gmyth_util_string_to_time_val(msql_row[24]); - proginfo->pathname = g_string_new(g_strdup(msql_row[25])); - proginfo->recgroup = g_string_new(msql_row[26]); - proginfo->category = g_string_new(msql_row[27]); - proginfo->findid = (gint) g_ascii_strtoull(msql_row[28], NULL, 10); - - proginfo->recpriority2 = 0; - - g_string_printf(query_str, - "SELECT dupmethod,dupin,parentid,type " - "FROM record WHERE recordid = \"%d\"", proginfo->recordid); - - msql_res = - gmyth_query_process_statement(scheduler->msqlquery, - query_str->str); - - if (msql_res) { - MYSQL_ROW msql_row = mysql_fetch_row(msql_res); - - if (msql_row) { - proginfo->dupmethod = (gint) g_ascii_strtoull(msql_row[0], NULL, 10); - proginfo->dupin = (gint) g_ascii_strtoull(msql_row[1], NULL, 10); - proginfo->parentid = (gint) g_ascii_strtoull(msql_row[2], NULL, 10); - proginfo->rectype = 0; - } - } - - - g_string_printf(query_str, - "SELECT sourceid,cardid,cardinputid,shareable " - "FROM cardinput"); - - msql_res = - gmyth_query_process_statement(scheduler->msqlquery, - query_str->str); - - if (msql_res) { - MYSQL_ROW msql_row = mysql_fetch_row(msql_res); - - if (msql_row) { - proginfo->sourceid = 0; - proginfo->cardid = 0; - proginfo->inputid = 0; - if (msql_row[3] != NULL && g_ascii_strcasecmp("Y", msql_row[3]) == 0) - proginfo->shareable = 1; - else - proginfo->shareable = 0; - } - } - - - - } - } - - g_string_free(query_str, TRUE); - return proginfo; -} - -/** Retrieves an existing recorded item information from database. The information - * is used to fill the returned GMythProgramInfo. - * - * @param scheduler The GMythScheduler instance. - * @param channel The channel associated to the record - * @param starttime The record start time - * @return A GMythProgramInfo struct with the requested record item - * information, or NULL if error. - */ -GMythProgramInfo * -gmyth_scheduler_get_recorded(GMythScheduler * scheduler, - GString * channel, GTimeVal * starttime) -{ - MYSQL_RES *msql_res; - GMythProgramInfo *proginfo = NULL; - GString *query_str = g_string_new(""); - gchar *time_str = - gmyth_util_time_to_string_from_time_val(starttime); - - assert(scheduler); - - gmyth_debug("[%s] channel: %s", __FUNCTION__, channel->str); - - if (scheduler->msqlquery == NULL) { - g_warning("[%s] Scheduler db connection not initialized", - __FUNCTION__); - return NULL; - } - - g_string_printf(query_str, - "SELECT recorded.chanid,starttime,endtime,title, " - "subtitle,description,channel.channum, " - "channel.callsign,channel.name,channel.commfree, " - "channel.outputfilters,seriesid,programid,filesize, " - "lastmodified,stars,previouslyshown,originalairdate, " - "hostname,recordid,transcoder,playgroup, " - "recorded.recpriority,progstart,progend,basename,recgroup " - "FROM recorded " "LEFT JOIN channel " - "ON recorded.chanid = channel.chanid " - "WHERE recorded.chanid = \"%s\" " - "AND starttime = \"%s\" ;", channel->str, time_str); - - msql_res = - gmyth_query_process_statement(scheduler->msqlquery, - query_str->str); - - if (msql_res /* && query.size() > 0 */ ) { - MYSQL_ROW msql_row = mysql_fetch_row(msql_res); - - if (msql_row) { - proginfo = gmyth_program_info_new(); - - proginfo->channel_id = (gint) g_ascii_strtoull (msql_row[0], NULL, 10); - proginfo->startts = - gmyth_util_string_to_time_val(msql_row[23]); - proginfo->endts = gmyth_util_string_to_time_val(msql_row[24]); - proginfo->recstartts = - gmyth_util_string_to_time_val(msql_row[1]); - proginfo->recendts = - gmyth_util_string_to_time_val(msql_row[2]); - proginfo->title = g_string_new(msql_row[3]); - proginfo->subtitle = g_string_new(msql_row[4]); - proginfo->description = g_string_new(msql_row[5]); - - proginfo->chanstr = g_string_new(msql_row[6]); - proginfo->chansign = g_string_new(msql_row[7]); - proginfo->channame = g_string_new(msql_row[0]); - proginfo->chancommfree = - (gint) g_ascii_strtoull(msql_row[9], NULL, 10); - proginfo->chanOutputFilters = g_string_new(msql_row[10]); - proginfo->seriesid = g_string_new(msql_row[11]); - proginfo->program_id = g_string_new(msql_row[12]); - proginfo->filesize = g_ascii_strtoull(msql_row[13], NULL, 10); - - proginfo->lastmodified = - gmyth_util_string_to_time_val(msql_row[14]); - proginfo->stars = g_ascii_strtod(msql_row[15], NULL); - proginfo->repeat = - (gint) g_ascii_strtoull(msql_row[16], NULL, 10); - - if (msql_row[17] == NULL) { - proginfo->originalAirDate = 0; - proginfo->hasAirDate = FALSE; - } else { - proginfo->originalAirDate = - gmyth_util_string_to_time_val(msql_row[17]); - proginfo->hasAirDate = TRUE; - } - - proginfo->hostname = g_string_new(msql_row[18]); - proginfo->recordid = - (gint) g_ascii_strtoull(msql_row[19], NULL, 10); - proginfo->transcoder = - (gint) g_ascii_strtoull(msql_row[20], NULL, 10); - // proginfo->spread = -1; - // proginfo->programflags = proginfo->getProgramFlags(); - - proginfo->recgroup = g_string_new(msql_row[26]); - proginfo->playgroup = g_string_new(msql_row[21]); - proginfo->recpriority = - (gint) g_ascii_strtoull(msql_row[22], NULL, 10); - - proginfo->pathname = g_string_new(g_strdup(msql_row[25])); - - gmyth_debug("One program info loaded from mysql database\n"); - } - } - - mysql_free_result(msql_res); - g_string_free(query_str, TRUE); - g_free(time_str); - - return proginfo; -} - -gboolean -gmyth_scheduler_stop_recording (GMythScheduler * scheduler, - gint channel_id) -{ - GMythProgramInfo *program; - GMythSocket *socket; - gboolean res = FALSE; - GMythStringList *slist; - - socket = gmyth_backend_info_get_connected_socket (scheduler->backend_info); - program = gmyth_scheduler_get_recorded_on_time (scheduler, channel_id); - - if (program) { - slist = gmyth_string_list_new(); - gmyth_string_list_append_char_array(slist, "STOP_RECORDING"); - - gmyth_string_list_append_string(slist, program->title); /* 0 */ - gmyth_string_list_append_string(slist, program->subtitle); /* 1 */ - gmyth_string_list_append_string(slist, program->description); /* 2 */ - gmyth_string_list_append_string(slist, program->category); /* 3 */ - gmyth_string_list_append_int(slist, program->channel_id); /* 4 */ - gmyth_string_list_append_string(slist, program->chanstr); /* 5 */ - gmyth_string_list_append_string(slist, program->chansign); /* 6 */ - gmyth_string_list_append_string(slist, program->channame); /* 7 */ - gmyth_string_list_append_string(slist, program->pathname); /* 8 */ - gmyth_string_list_append_int64(slist, program->filesize); /* 9 */ - - if (program->startts) - gmyth_string_list_append_int(slist, program->startts->tv_sec); /* 10 */ - else - gmyth_string_list_append_int(slist, 0); - - if (program->endts) - gmyth_string_list_append_int(slist, program->endts->tv_sec); /* 11 */ - else - gmyth_string_list_append_int(slist, 0); - - gmyth_string_list_append_int(slist, program->duplicate); /* 12 */ - gmyth_string_list_append_int(slist, program->shareable); /* 13 */ - gmyth_string_list_append_int(slist, program->findid); /* 14 */ - gmyth_string_list_append_string(slist, program->hostname); /* 15 */ - gmyth_string_list_append_int(slist, program->sourceid); /* 16 */ - gmyth_string_list_append_int(slist, program->cardid); /* 17 */ - gmyth_string_list_append_int(slist, program->inputid); /* 18 */ - gmyth_string_list_append_int(slist, program->recpriority); /* 19 */ - - // recstatus == recording - gmyth_string_list_append_int(slist, -3); /* 20 */ - - gmyth_string_list_append_int(slist, program->recordid); /* 21 */ - gmyth_string_list_append_int(slist, program->rectype); /* 22 */ - gmyth_string_list_append_int(slist, program->dupin); /* 23 */ - gmyth_string_list_append_int(slist, program->dupmethod); /* 24 */ - - - //fixme - program->recstartts->tv_sec -= (60*60); - - gmyth_string_list_append_int(slist, - program->recstartts != NULL ? - program->recstartts->tv_sec : 0); /* 26 */ - - gmyth_string_list_append_int(slist, - program->recendts != NULL ? - program->recendts->tv_sec : 0); /* 27 */ - - gmyth_string_list_append_int(slist, program->repeat); /* 28 */ - gmyth_string_list_append_int(slist, program->programflags); /* 29 */ - - gmyth_string_list_append_char_array(slist, - program->recgroup != NULL ? - program->recgroup->str : "Default"); /* 30 */ - - gmyth_string_list_append_int(slist, program->chancommfree); /* 31 */ - gmyth_string_list_append_string(slist, program->chanOutputFilters); /* 32 */ - gmyth_string_list_append_string(slist, program->seriesid); /* 33 */ - gmyth_string_list_append_string(slist, program->program_id); /* 34 */ - - gmyth_string_list_append_int(slist, - program->lastmodified != NULL ? - program->lastmodified->tv_sec : 0); /* 35 */ - - gmyth_string_list_append_float(slist, program->stars); /* 36 */ - - gmyth_string_list_append_int(slist, - program->originalAirDate != NULL ? - program->originalAirDate->tv_sec : 0); /* 37 */ - - gmyth_string_list_append_int(slist, program->hasAirDate); /* 38 */ - - gmyth_string_list_append_char_array(slist, - program->playgroup != NULL ? - program->playgroup->str : "Default"); /* 39 */ - - gmyth_string_list_append_int(slist, program->recpriority2); /* 40 */ - gmyth_string_list_append_int(slist, program->recpriority2); /* 40 */ - - gmyth_socket_sendreceive_stringlist(socket, slist); - res = (gmyth_string_list_get_int(slist, 0) == 1); - - g_object_unref (program); - g_object_unref (slist); - } - - g_object_unref (socket); - return res; -} - - -/** Notifies the backend of an update in the db. - * - * @param record_id the id of the modified recording. - */ -// fixme: put void and discovery record_id inside -static gboolean -update_backend (GMythScheduler * scheduler, - gint record_id) -{ - GMythSocket *socket; - GMythStringList *strlist = gmyth_string_list_new(); - GString *datastr = g_string_new("RESCHEDULE_RECORDINGS "); - gboolean ret = FALSE; - - g_string_append_printf(datastr, "%d", record_id); - gmyth_string_list_append_string(strlist, datastr); - - socket = gmyth_backend_info_get_connected_socket (scheduler->backend_info); - if (socket != NULL) { - ret = (gmyth_socket_sendreceive_stringlist(socket, strlist) > 0); - g_object_unref (socket); - } else { - g_warning("[%s] Connection to backend failed!", __FUNCTION__); - } - - g_string_free(datastr, TRUE); - g_object_unref(strlist); - return ret; -} - -void -gmyth_scheduler_recorded_info_get_preview(RecordedInfo * info, - GByteArray * data) -{ -} - -void -gmyth_recorded_info_free(RecordedInfo * info) -{ - g_return_if_fail (info != NULL); - - if (info->program_id) - g_string_free (info->program_id, TRUE); - - if (info->title != NULL) - g_string_free(info->title, TRUE); - - if (info->subtitle != NULL) - g_string_free(info->subtitle, TRUE); - - if (info->description != NULL) - g_string_free(info->description, TRUE); - - if (info->category != NULL) - g_string_free(info->category, TRUE); - - if (info->basename != NULL) - g_string_free(info->basename, TRUE); - - if (info != NULL) - g_free(info->start_time); - - if (info != NULL) - g_free(info->end_time); - - g_free(info); -} - -static void -free_recorded_info_item(gpointer data, gpointer user_data) -{ - RecordedInfo *info = (RecordedInfo *) data; - - gmyth_recorded_info_free(info); -} - -void -gmyth_recorded_info_list_free(GList * list) -{ - g_return_if_fail(list != NULL); - - g_list_foreach(list, free_recorded_info_item, NULL); - g_list_free(list); -} - -void -gmyth_schedule_info_free(ScheduleInfo * info) -{ - - g_return_if_fail(info != NULL); - - if (info->program_id) - g_string_free (info->program_id, TRUE); - - if (info->title != NULL) - g_string_free(info->title, TRUE); - - if (info->subtitle != NULL) - g_string_free(info->subtitle, TRUE); - - if (info->description != NULL) - g_string_free(info->description, TRUE); - - if (info->category != NULL) - g_string_free(info->category, TRUE); - - if (info != NULL) - g_free(info->start_time); - - if (info != NULL) - g_free(info->end_time); - - g_free(info); -} - -static void -free_schedule_info_item(gpointer data, gpointer user_data) -{ - ScheduleInfo *info = (ScheduleInfo *) data; - - gmyth_schedule_info_free(info); -} - -void -gmyth_schedule_info_list_free(GList * list) -{ - g_return_if_fail(list != NULL); - - g_list_foreach(list, free_schedule_info_item, NULL); - g_list_free(list); -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_scheduler.h --- a/gmyth/src/gmyth_scheduler.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_scheduler.h - * - * @brief

The scheduler encapsulates all functions for browsing, scheduling - * and modifying the recorded content. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Alexsandro Jose Virginio dos Santos - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __GMYTH_SCHEDULER_H__ -#define __GMYTH_SCHEDULER_H__ - -#include -#include - -#include "gmyth_common.h" -#include "gmyth_query.h" -#include "gmyth_backendinfo.h" - -G_BEGIN_DECLS - -typedef enum { - GMYTH_SCHEDULE_ONE_OCCURRENCE, - GMYTH_SCHEDULE_ALL_OCCURRENCES, - GMYTH_SCHEDULE_EXCEPTION -} GMythScheduleType; - - -#define GMYTH_SCHEDULER_TYPE (gmyth_scheduler_get_type ()) -#define GMYTH_SCHEDULER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SCHEDULER_TYPE, GMythScheduler)) -#define GMYTH_SCHEDULER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SCHEDULER_TYPE, GMythSchedulerClass)) -#define IS_GMYTH_SCHEDULER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_SCHEDULER_TYPE)) -#define IS_GMYTH_SCHEDULER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SCHEDULER_TYPE)) -#define GMYTH_SCHEDULER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_SCHEDULER_TYPE, GMythSchedulerClass)) - -typedef struct _GMythScheduler GMythScheduler; -typedef struct _GMythSchedulerClass GMythSchedulerClass; - -struct _GMythSchedulerClass { - GObjectClass parent_class; -}; - -struct _GMythScheduler { - GObject parent; - - unsigned long recordid; - unsigned long type; - unsigned long search; - GString *profile; - - long dupin; - long dupmethod; - long autoexpire; - short int autotranscode; - long transcoder; - - short int autocommflag; - short int autouserjob1; - short int autouserjob2; - short int autouserjob3; - short int autouserjob4; - - long startoffset; - long endoffset; - long maxepisodes; - long maxnewest; - - long recpriority; - GString *recgroup; - GString *playgroup; - - long prefinput; - short int inactive; - - GString *search_type; - GString *search_what; - - GMythQuery *msqlquery; - GMythBackendInfo *backend_info; -}; - -typedef struct { - guint schedule_id; - gint channel_id; - GString *program_id; - - GTimeVal *start_time; - GTimeVal *end_time; - - GString *seriesid; - GString *title; - GString *subtitle; - GString *description; - GString *category; - - GMythScheduleType type; - - gint parentid; - -} ScheduleInfo; - -typedef struct { - guint record_id; - gint channel_id; - GString *program_id; - - GTimeVal *start_time; - GTimeVal *end_time; - - GString *seriesid; - GString *title; - GString *subtitle; - GString *description; - GString *category; - - GString *basename; - - guint64 filesize; - -} RecordedInfo; - - -GType gmyth_scheduler_get_type (void); - -GMythScheduler* gmyth_scheduler_new (void); -gboolean gmyth_scheduler_connect (GMythScheduler * scheduler, - GMythBackendInfo * backend_info); -gboolean gmyth_scheduler_connect_with_timeout (GMythScheduler * scheduler, - GMythBackendInfo * backend_info, - guint timeout); -gboolean gmyth_scheduler_disconnect (GMythScheduler * scheduler); -gint gmyth_scheduler_get_schedule_list (GMythScheduler * scheduler, - GList ** sched_list); -gint gmyth_scheduler_get_recorded_list (GMythScheduler * scheduler, - GList ** rec_list); -RecordedInfo* gmyth_scheduler_get_recorded_info (GMythScheduler *scheduler, - const char *basename); -gboolean gmyth_scheduler_was_recorded_before (GMythScheduler* scheduler, - gint channel_id, - time_t start_time); -gboolean gmyth_scheduler_reactivate_schedule (GMythScheduler* scheduler, - gint channel_id, - time_t start_time); -GMythProgramInfo* gmyth_scheduler_get_recorded_on_time (GMythScheduler* scheduler, - guint channel_id); -GMythProgramInfo* gmyth_scheduler_get_recorded (GMythScheduler * scheduler, - GString * channel, - GTimeVal * starttime); -ScheduleInfo* gmyth_scheduler_add_schedule_program (GMythScheduler * scheduler, - GMythProgramInfo *program, - GMythScheduleType type); -gint gmyth_scheduler_add_schedule (GMythScheduler * scheduler, - ScheduleInfo * schedule_info); -gboolean gmyth_scheduler_add_schedule_full (GMythScheduler * scheduler, - ScheduleInfo * schedule_info, - GMythScheduleType type); -gboolean gmyth_scheduler_add_exception (GMythScheduler *scheduler, - gint schedule_id, - ScheduleInfo *exception_info); -gboolean gmyth_scheduler_delete_schedule (GMythScheduler * scheduler, - gint record_id); -gint gmyth_scheduler_delete_recorded (GMythScheduler * scheduler, - gint record_id); -gboolean gmyth_scheduler_stop_recording (GMythScheduler * scheduler, - gint channel_id); -void gmyth_scheduler_recorded_info_get_preview(RecordedInfo * info, - GByteArray * data); - - -void gmyth_recorded_info_free (RecordedInfo * info); -void gmyth_schedule_info_free (ScheduleInfo * info); -void gmyth_recorded_info_list_free (GList * list); -void gmyth_schedule_info_list_free (GList * list); - -G_END_DECLS -#endif /* __GMYTH_SCHEDULER_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_socket.c --- a/gmyth/src/gmyth_socket.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1295 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_socket.c - * - * @brief

MythTV socket implementation, according to the MythTV Project - * (www.mythtv.org). - * - * This component provides basic socket functionalities to interact with - * the Mythtv backend. - *

- * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Rosfran Lins Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gmyth_socket.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "gmyth_stringlist.h" -#include "gmyth_uri.h" -#include "gmyth_debug.h" - -#define BUFLEN 512 -#define MYTH_SEPARATOR "[]:[]" -#define MYTH_PROTOCOL_FIELD_SIZE 8 - -/* - * max number of iterations - */ -#define MYTHTV_MAX_VERSION_CHECKS 40 - -// FIXME: put this in the right place -#define MYTHTV_VERSION_DEFAULT 31 - -/* - * static GStaticMutex mutex = G_STATIC_MUTEX_INIT; - */ - -/* - * static GStaticRWLock rwlock = G_STATIC_RW_LOCK_INIT; - */ - -static gchar *local_hostname = NULL; - -static void gmyth_socket_class_init(GMythSocketClass * klass); -static void gmyth_socket_init(GMythSocket * object); - -static void gmyth_socket_dispose(GObject * object); -static void gmyth_socket_finalize(GObject * object); - -G_DEFINE_TYPE(GMythSocket, gmyth_socket, G_TYPE_OBJECT) - static void gmyth_socket_class_init(GMythSocketClass * klass) -{ - GObjectClass *gobject_class; - - gobject_class = (GObjectClass *) klass; - - gobject_class->dispose = gmyth_socket_dispose; - gobject_class->finalize = gmyth_socket_finalize; -} - -static void -gmyth_socket_init(GMythSocket * gmyth_socket) -{ - - /* - * gmyth_socket->local_hostname = NULL; - */ - -} - -/** Gets the some important address translation info, from the client socket - * that will open a connection. - * - * @return gint that represents the error number from getaddrinfo(). - */ -static gint -gmyth_socket_toaddrinfo(const gchar * addr, gint port, - struct addrinfo **addrInfo) -{ - struct addrinfo hints; - gchar *portStr = NULL; - gint errorn = EADDRNOTAVAIL; - - g_return_val_if_fail(addr != NULL, -1); - - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - /* - * hints.ai_flags = AI_NUMERICHOST; - */ - - if (port != -1) - portStr = g_strdup_printf("%d", port); - else - portStr = NULL; - - gmyth_debug("Getting name resolution for: %s, %d\n", addr, port); - - if ((errorn = getaddrinfo(addr, portStr, &hints, addrInfo)) != 0) { - gmyth_debug("[%s] Socket ERROR: %s\n", __FUNCTION__, - gai_strerror(errorn)); - } - - g_free(portStr); - - return errorn; -} - -/* - * static gint gmyth_socket_find_match_address_uri( GMythURI* uri, gchar - * *address ) { if ( g_ascii_strcasecmp( gmyth_uri_get_host( uri ), - * address ) == 0 ) { //gmyth_debug( "Found URI: %s !!!\n", - * rui_uri_getvalue(uri) ); return 0; } else { return -1; } } - */ - -const gchar *PATH_PROC_NET_DEV = "/proc/net/dev"; - -/** Gets the list of all local network interfaces (using the /proc/net/dev directory). - * - * @param current_connections A list with all the network interfaces are valid, - * to be applied just like a filter. - * @return List with all the local net interfaces. - */ -GList * -gmyth_socket_get_local_addrs(GList * current_connections) -{ - - GList *local_addrs = NULL; - FILE *fd; - gint s; - gchar buffer[256 + 1]; - gchar ifaddr[20 + 1]; - gchar *ifname; - gchar *sep; - - s = socket(AF_INET, SOCK_DGRAM, 0); - if (s < 0) - return 0; - fd = fopen(PATH_PROC_NET_DEV, "r"); - fgets(buffer, sizeof(buffer) - 1, fd); - fgets(buffer, sizeof(buffer) - 1, fd); - while (!feof(fd)) { - ifname = buffer; - - if (fgets(buffer, sizeof(buffer) - 1, fd) == NULL) - break; - sep = strrchr(buffer, ':'); - if (sep) - *sep = 0; - while (*ifname == ' ') - ifname++; - struct ifreq req; - - strcpy(req.ifr_name, ifname); - if (ioctl(s, SIOCGIFFLAGS, &req) < 0) - continue; - if (!(req.ifr_flags & IFF_UP)) - continue; - if (req.ifr_flags & IFF_LOOPBACK) - continue; - if (ioctl(s, SIOCGIFADDR, &req) < 0) - continue; - g_strlcpy(ifaddr, - inet_ntoa(((struct sockaddr_in *) &req.ifr_addr)-> - sin_addr), sizeof(struct ifaddr) - 1); - local_addrs = g_list_append(local_addrs, g_strdup(ifaddr)); - - gmyth_debug - ("( from the /proc/net/dev) Interface name: %s, address: %s\n", - ifname, ifaddr); - } - fclose(fd); - close(s); - return local_addrs; -} - -/** - * Get only the local addresses from the primary interface - */ -gchar * -gmyth_socket_get_primary_addr(void) -{ - gchar *if_eth0 = g_new0(gchar, sizeof(struct ifaddr) - 1); - GList *if_tmp = NULL; - - GList *interfs = gmyth_socket_get_local_addrs(NULL); - - if (interfs != NULL && (g_list_length(interfs) > 0)) { - // get the first occurrence (primary interface) - if_tmp = g_list_first(interfs); - - if (if_tmp != NULL) - g_strlcpy(if_eth0, (gchar *) if_tmp->data, - sizeof(struct ifaddr) - 1); - - } - - if (interfs != NULL) - g_list_free(interfs); - - return if_eth0; -} - -/** This function retrieves the local hostname of the - * client machine. - * - * @return GString* get local hostname. - */ -GString * -gmyth_socket_get_local_hostname(void) -{ - char hname[50]; - gint res = gethostname(hname, 50); - - if (res == -1) { - gmyth_debug("Error while getting hostname"); - return g_string_new("default"); - } - - return g_string_new(hname); - -#if 0 - GString *str = NULL; - - if (local_hostname != NULL && strlen(local_hostname) > 0) - return g_string_new(local_hostname); - - gchar *localaddr = NULL; - gboolean found_addr = FALSE; - struct addrinfo *addr_info_data = NULL, - *addr_info0 = NULL; - struct sockaddr_in *sa = NULL; - gchar localhostname[MAXHOSTNAMELEN]; - - - if (gethostname(localhostname, MAXHOSTNAMELEN) != 0) { - gmyth_debug("Error on gethostname"); - } - localhostname[MAXHOSTNAMELEN - 1] = 0; - - gint err = - gmyth_socket_toaddrinfo(localhostname, -1, &addr_info_data); - - if (err == EADDRNOTAVAIL) { - gmyth_debug("[%s] Address (%s) not available. (reason = %d)\n", - __FUNCTION__, localhostname, err); - return str; - } - - g_mutex_lock(gmyth_socket->mutex); - - addr_info0 = addr_info_data; - - while (addr_info0 != NULL && addr_info0->ai_addr != NULL && - (sa = (struct sockaddr_in *) addr_info0->ai_addr) != NULL - && !found_addr) { - localaddr = inet_ntoa(sa->sin_addr); - - if (localaddr != NULL && (g_strrstr(localaddr, "127") == NULL)) { - str = g_string_new(localaddr); - found_addr = TRUE; - g_free(localaddr); - break; - } - /* - * if (localaddr != NULL) { g_free (localaddr); localaddr = NULL; - * } - */ - - addr_info0 = addr_info0->ai_next; - }; - - freeaddrinfo(addr_info_data); - addr_info_data = NULL; - - if (found_addr == FALSE) { - gchar *prim_addr = gmyth_socket_get_primary_addr(); - - if (prim_addr != NULL) { - gmyth_debug - ("[%s] Could not determine the local alphanumerical hostname. Setting to %s\n", - __FUNCTION__, prim_addr); - - str = g_string_new(prim_addr); - g_free(prim_addr); - } else { - str = g_string_new(localhostname); - } - } - - g_mutex_unlock(gmyth_socket->mutex); - - if (str != NULL && str->str != NULL) - local_hostname = g_strdup(str->str); - - return str; -#endif -} - -static void -gmyth_socket_dispose(GObject * object) -{ - GMythSocket *gmyth_socket = GMYTH_SOCKET(object); - - /* - * disconnect socket - */ - gmyth_socket_close_connection(gmyth_socket); - - g_free(gmyth_socket->hostname); - - g_free(local_hostname); - - local_hostname = NULL; - - if (gmyth_socket->mutex != NULL) { - g_mutex_free(gmyth_socket->mutex); - gmyth_socket->mutex = NULL; - } - - G_OBJECT_CLASS(gmyth_socket_parent_class)->dispose(object); -} - -static void -gmyth_socket_finalize(GObject * object) -{ - g_signal_handlers_destroy(object); - - G_OBJECT_CLASS(gmyth_socket_parent_class)->finalize(object); -} - -/** Creates a new instance of GMythSocket. - * - * @return a new instance of GMythSocket. - */ -GMythSocket * -gmyth_socket_new() -{ - GMythSocket *gmyth_socket = - GMYTH_SOCKET(g_object_new(GMYTH_SOCKET_TYPE, NULL)); - - gmyth_socket->mythtv_version = MYTHTV_VERSION_DEFAULT; - - gmyth_socket->mutex = g_mutex_new(); - - return gmyth_socket; -} - -/** Try to open an asynchronous connection to the MythTV backend. - * - * @param fd Socket descriptor. - * @param remote Remote address. - * @param len Newly created socket length field. - * @param timeout Timeval argument with the time interval to timeout before closing. - * @param err Error message number. - * @return Any numerical value below 0, if an error had been found. - */ -static gint -gmyth_socket_try_connect(gint fd, struct sockaddr *remote, gint len, - struct timeval *timeout, gint * err) -{ - /* - * g_return_val_if_fail( timeout != NULL, 0 ); - */ - gint saveflags, - ret, - back_err; - - fd_set fd_w; - - saveflags = fcntl(fd, F_GETFL, 0); - if (saveflags < 0) { - gmyth_debug("[%s] Problems when getting socket flags on fcntl.\n", - __FUNCTION__); - *err = errno; - return -1; - } - - /* - * Set non blocking - */ - if (fcntl(fd, F_SETFL, saveflags | O_NONBLOCK) < 0) { - gmyth_debug - ("[%s] Problems when setting non-blocking using fcntl.\n", - __FUNCTION__); - *err = errno; - return -1; - } - - /* - * This will return immediately - */ - *err = connect(fd, remote, len); - back_err = errno; - - /* - * restore flags - */ - if (fcntl(fd, F_SETFL, saveflags) < 0) { - gmyth_debug - ("[%s] Problems when trying to restore flags with fcntl.\n", - __FUNCTION__); - *err = errno; - return -1; - } - - /* - * return unless the connection was successful or the connect is still - * in progress. - */ - if (*err < 0 && back_err != EINPROGRESS) { - gmyth_debug - ("[%s] Connection unsucessfully (it is not in progress).\n", - __FUNCTION__); - *err = errno; - return -1; - } - - FD_ZERO(&fd_w); - FD_SET(fd, &fd_w); - - *err = select(FD_SETSIZE, NULL, &fd_w, NULL, timeout); - if (*err < 0) { - gmyth_debug("[%s] Connection unsucessfull (timed out).\n", - __FUNCTION__); - *err = errno; - return -1; - } - - /* - * 0 means it timeout out & no fds changed - */ - if (*err == 0) { - gmyth_debug - ("[%s] Connection unsucessfull [%d] - 0 means it timeout out & no fds changed\n", - __FUNCTION__, *err); - close(fd); - *err = ETIMEDOUT; - return -1; - } - - /* - * Get the return code from the connect - */ - len = sizeof(ret); - *err = getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, (socklen_t *) & len); - - if (*err < 0) { - gmyth_debug("[%s] Connection unsucessfull.\n", __FUNCTION__); - *err = errno; - return -1; - } - - /* - * ret=0 means success, otherwise it contains the errno - */ - if (ret) { - gmyth_debug - ("[%s] Connection unsucessfull - Couldn't connect to remote host!!!\n", - __FUNCTION__); - *err = ret; - return -1; - } - - *err = 0; - return 0; -} - -/** Connects to the backend. - * - * @param gmyth_socket The GMythSocket instance. - * @param hostname The backend hostname or IP address. - * @param port The backend port. - * @return TRUE if success, FALSE if error. - */ - - -gboolean -gmyth_socket_connect(GMythSocket * gmyth_socket, - const gchar * hostname, gint port) -{ - return gmyth_socket_connect_with_timeout(gmyth_socket, hostname, port, - 30); -} - -gboolean -gmyth_socket_connect_with_timeout(GMythSocket * gmyth_socket, - const gchar * hostname, gint port, - guint timeout) -{ - struct addrinfo *addr_info_data = NULL, - *addr_info0 = NULL; - struct linger ling; - gchar *tmp_str; - gint ret_code = 0; /* -1 */ - - /* - * FIXME: add as function parameter - */ - gint err; - gint errno; - gboolean ret = TRUE; - - gmyth_debug("CONNECTING %s:%d", hostname, port); - - if (hostname == NULL) - gmyth_debug("Invalid hostname parameter!\n"); - - /* - * store hostname and port number - */ - gmyth_debug("CONNECTING %s:%d", hostname, port); - - errno = gmyth_socket_toaddrinfo(hostname, port, &addr_info_data); - - g_return_val_if_fail(addr_info_data != NULL - && hostname != NULL, FALSE); - - /* - * hack to avoid deleting the hostname when gmyth_socket->hostname == - * hostname - */ - tmp_str = gmyth_socket->hostname; - - gmyth_socket->hostname = g_strdup(hostname); - gmyth_socket->port = port; - - g_free(tmp_str); - - for (addr_info0 = addr_info_data; addr_info0; - addr_info0 = addr_info_data->ai_next) { - /* - * init socket descriptor - */ - - g_debug ("FAMILY: %d, TYPE: %d, PROTOCOL: %d", - addr_info0->ai_family, - addr_info0->ai_socktype, - addr_info0->ai_protocol); - gmyth_socket->sd = - socket(addr_info0->ai_family, addr_info0->ai_socktype, - addr_info0->ai_protocol); - - if (gmyth_socket->sd < 0) - continue; - - struct timeval *timeout_val = g_new0(struct timeval, 1); - - if (timeout != 0) { - timeout_val->tv_sec = timeout; - timeout_val->tv_usec = 0; - } else { - timeout_val->tv_sec = 5; - timeout_val->tv_usec = 100; - } - - if (gmyth_socket_try_connect - (gmyth_socket->sd, (struct sockaddr *) addr_info0->ai_addr, - addr_info0->ai_addrlen, timeout_val, &ret_code) < 0) { - gmyth_debug("[%s] Error connecting to backend!\n", - __FUNCTION__); - if (ret_code == ETIMEDOUT) - gmyth_debug("[%s]\tBackend host unreachable!\n", - __FUNCTION__); - - close(gmyth_socket->sd); - gmyth_socket->sd = -1; - gmyth_debug("ERROR: %s\n", gai_strerror(ret_code)); - g_free(timeout_val); - continue; - } - - g_free(timeout_val); - - /* - * only will be reached if none of the error above occurred - */ - break; - } - - freeaddrinfo(addr_info_data); - addr_info_data = NULL; - - if (gmyth_socket->sd_io_ch != NULL) { - g_io_channel_unref(gmyth_socket->sd_io_ch); - gmyth_socket->sd_io_ch = NULL; - } - - - memset(&ling, 0, sizeof(struct linger)); - ling.l_onoff = TRUE; - ling.l_linger = 1; - - err = - setsockopt(gmyth_socket->sd, SOL_SOCKET, SO_LINGER, &ling, - sizeof(struct linger)); - - if (err < 0) { - gmyth_debug("[%s] Setting connection unsucessfull.\n", - __FUNCTION__); - err = errno; - ret = FALSE; - goto cleanup; - } - - gmyth_socket->sd_io_ch = g_io_channel_unix_new(gmyth_socket->sd); - - g_io_channel_set_close_on_unref(gmyth_socket->sd_io_ch, TRUE); - // g_io_channel_set_encoding (gmyth_socket->sd_io_ch, NULL, NULL ); - - GIOFlags flags = g_io_channel_get_flags(gmyth_socket->sd_io_ch); - - /* - * unset the nonblock flag - */ - flags &= ~G_IO_FLAG_NONBLOCK; - /* - * unset the nonblocking stuff for some time, because GNUTLS doesn't - * like that - */ - g_io_channel_set_flags(gmyth_socket->sd_io_ch, flags, NULL); - - ret = (ret_code == 0) ? TRUE : FALSE; - - cleanup: - if (!ret) - gmyth_debug("GMythSocket error - return code error!"); - - return ret; -} - -/** Gets the GIOChannel associated to the given GMythSocket. - * - * @param gmyth_socket The GMythSocket instance. - */ -GIOChannel * -gmyth_socket_get_io_channel(GMythSocket * gmyth_socket) -{ - g_return_val_if_fail(gmyth_socket != NULL, NULL); - - return gmyth_socket->sd_io_ch; -} - -/** Verifies if the socket is able to read. - * - * @param gmyth_socket The GMythSocket instance. - * @return TRUE if the socket is able to read, FALSE if not. - */ -gboolean -gmyth_socket_is_able_to_read(GMythSocket * gmyth_socket) -{ - gboolean ret = TRUE; - - /* - * verify if the input (read) buffer is ready to receive data - */ - GIOCondition io_cond = - g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch); - - if ((io_cond & G_IO_IN) == 0) { - gmyth_debug("[%s] IO channel is not able to send data!\n", - __FUNCTION__); - ret = FALSE; - } - - return ret; - -} - -/** Verifies if the socket is able to write. - * - * @param gmyth_socket The GMythSocket instance. - * @return TRUE if the socket is able to write, FALSE if not. - */ -gboolean -gmyth_socket_is_able_to_write(GMythSocket * gmyth_socket) -{ - gboolean ret = TRUE; - - /* - * verify if the input (read) buffer is ready to receive data - */ - GIOCondition io_cond = - g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch); - - if (((io_cond & G_IO_OUT) == 0) || ((io_cond & G_IO_HUP) == 0)) { - gmyth_debug("[%s] IO channel is not able to send data!\n", - __FUNCTION__); - ret = FALSE; - } - - return ret; - -} - -/** Sends a command to the backend. - * - * @param gmyth_socket the GMythSocket instance. - * @param command The string command to be sent. - */ -gboolean -gmyth_socket_send_command(GMythSocket * gmyth_socket, GString * command) -{ - gboolean ret = TRUE; - - GIOStatus io_status = G_IO_STATUS_NORMAL; - - // GIOCondition io_cond; - GError *error = NULL; - - gchar *buffer = NULL; - - gsize bytes_written = 0; - - g_return_val_if_fail(gmyth_socket->sd_io_ch != NULL, FALSE); - - if (command == NULL || (command->len <= 0) || command->str == NULL) { - gmyth_debug("[%s] Invalid NULL command parameter!\n", - __FUNCTION__); - ret = FALSE; - goto done; - } - - g_mutex_lock(gmyth_socket->mutex); - gmyth_debug("Sending command to backend: %s\n", command->str); - - buffer = g_strnfill(BUFLEN, ' '); - g_snprintf(buffer, MYTH_PROTOCOL_FIELD_SIZE + 1, "%-8d", command->len); - - command = g_string_prepend(command, buffer); - - /* - * write bytes to socket - */ - io_status = - g_io_channel_write_chars(gmyth_socket->sd_io_ch, command->str, - command->len, &bytes_written, &error); - - - if ((io_status == G_IO_STATUS_ERROR) || (bytes_written <= 0)) { - gmyth_debug("[%s] Error while writing to socket", __FUNCTION__); - ret = FALSE; - } else if (bytes_written < command->len) { - gmyth_debug("[%s] Not all data was written socket", __FUNCTION__); - ret = FALSE; - } - - io_status = g_io_channel_flush(gmyth_socket->sd_io_ch, &error); - - if ((bytes_written != command->len) - || (io_status == G_IO_STATUS_ERROR)) { - gmyth_debug - ("[%s] Some problem occurred when sending data to the socket\n", - __FUNCTION__); - - ret = TRUE; - } - - g_mutex_unlock(gmyth_socket->mutex); - done: - if (error != NULL) { - gmyth_debug - ("[%s] Error found reading data from IO channel: (%d, %s)\n", - __FUNCTION__, error->code, error->message); - ret = FALSE; - g_error_free(error); - } - - if (buffer != NULL) - g_free(buffer); - - return ret; -} - -/** Starts Mythtv protocol level connection. Checks Mythtv protocol version - * supported by the backend and send the "ANN" command. - * - * @param gmyth_socket the GMythSocket instance. - * @param hostname_backend The backend hostname or IP address. - * @param port The backend port to connect. - * @param blocking_client A flag to choose between blocking and non-blocking - * @param with_events Sets the connection flag to receive events. - * backend connection. - */ -static gboolean -gmyth_socket_connect_to_backend_and_events(GMythSocket * gmyth_socket, - const gchar * hostname_backend, - gint port, - gboolean blocking_client, - gboolean with_events) -{ - if (!gmyth_socket_connect(gmyth_socket, hostname_backend, port)) { - gmyth_debug("[%s] Could not open socket to backend machine [%s]\n", - __FUNCTION__, hostname_backend); - return FALSE; - } - - if (gmyth_socket_check_protocol_version(gmyth_socket)) { - GString *result; - GString *base_str = g_string_new(""); - GString *hostname = NULL; - - hostname = gmyth_socket_get_local_hostname(); - if (hostname == NULL) { - gmyth_debug - ("Hostname not available, setting to n800frontend\n"); - hostname = g_string_new("n800frontend"); - } - - g_string_printf(base_str, "ANN %s %s %u", - (blocking_client ? "Playback" : "Monitor"), - hostname->str, with_events); - - gmyth_socket_send_command(gmyth_socket, base_str); - result = gmyth_socket_receive_response(gmyth_socket); - - if (result != NULL) { - gmyth_debug("Response received from backend: %s", result->str); - g_string_free(result, TRUE); - } - - g_string_free(hostname, TRUE); - g_string_free(base_str, TRUE); - - return TRUE; - } else { - gmyth_debug("[%s] GMythSocket could not connect to the backend", - __FUNCTION__); - return FALSE; - } -} - -/** Starts Mythtv protocol level connection. Checks Mythtv protocol version - * supported by the backend and send the "ANN" command. - * - * @param gmyth_socket the GMythSocket instance. - * @param hostname_backend The backend hostname or IP address. - * @param port The backend port to connect. - * @param blocking_client A flag to choose between blocking and non-blocking - */ -gboolean -gmyth_socket_connect_to_backend(GMythSocket * gmyth_socket, - const gchar * hostname_backend, gint port, - gboolean blocking_client) -{ - if (!gmyth_socket_connect_to_backend_and_events - (gmyth_socket, hostname_backend, port, blocking_client, FALSE)) { - gmyth_debug("Could not open socket to backend machine [%s]\n", - hostname_backend); - return FALSE; - } - - return TRUE; - -} - -/** Starts Mythtv protocol level connection. Checks Mythtv protocol version - * supported by the backend and send the "ANN" command. - * - * @param gmyth_socket the GMythSocket instance. - * @param hostname_backend The backend hostname or IP address. - * @param port The backend port to connect. - * @param blocking_client A flag to choose between blocking and non-blocking - */ -gboolean -gmyth_socket_connect_to_backend_events(GMythSocket * gmyth_socket, - const gchar * hostname_backend, - gint port, gboolean blocking_client) -{ - if (!gmyth_socket_connect_to_backend_and_events - (gmyth_socket, hostname_backend, port, blocking_client, TRUE)) { - gmyth_debug - ("Could not open socket to backend machine in order to receive events [%s]\n", - hostname_backend); - return FALSE; - } - - return TRUE; -} - -/** Closes the socket connection to the backend. - * - * @param gmyth_socket The GMythSocket instance. - */ -void -gmyth_socket_close_connection(GMythSocket * gmyth_socket) -{ - /* - * if ( gmyth_socket->sd != -1 ) { close (gmyth_socket->sd); - * gmyth_socket->sd = -1; } - */ - - if (gmyth_socket->sd_io_ch != NULL) { - g_io_channel_shutdown(gmyth_socket->sd_io_ch, TRUE, NULL); - g_io_channel_unref(gmyth_socket->sd_io_ch); - gmyth_socket->sd_io_ch = NULL; - gmyth_socket->sd = -1; - } - -} - - -/** Try the MythTV version numbers, and get the version returned by - * the possible REJECT message, in order to contruct a new - * MythTV version request. - * - * @param gmyth_socket The GMythSocket instance. - * @param mythtv_version The Mythtv protocol version to be tested - * - * @return The actual MythTV the client is connected to. - */ -gint -gmyth_socket_check_protocol_version_number(GMythSocket * gmyth_socket, - gint mythtv_version) -{ - GString *response = NULL; - GString *payload = NULL; - gboolean res = TRUE; - gint mythtv_new_version = MYTHTV_CANNOT_NEGOTIATE_VERSION; - guint max_iterations = MYTHTV_MAX_VERSION_CHECKS; - - assert(gmyth_socket); - - try_new_version: - payload = g_string_new("MYTH_PROTO_VERSION"); - g_string_append_printf(payload, " %d", mythtv_version); - - gmyth_socket_send_command(gmyth_socket, payload); - response = gmyth_socket_receive_response(gmyth_socket); - - if (response == NULL) { - gmyth_debug("[%s] Check protocol version error! Not answered!", - __FUNCTION__); - res = FALSE; - goto done; - } - - res = g_str_has_prefix(response->str, "ACCEPT"); - if (!res) { - gmyth_debug("[%s] Protocol version request error: %s", - __FUNCTION__, response->str); - /* - * get the version number returned by the REJECT message - */ - if ((res = g_str_has_prefix(response->str, "REJECT")) == TRUE) { - gchar *new_version = NULL; - - new_version = g_strrstr(response->str, "]"); - if (new_version != NULL) { - ++new_version; /* skip ']' character */ - if (new_version != NULL) { - gmyth_debug("[%s] got MythTV version = %s.\n", - __FUNCTION__, new_version); - mythtv_version = - (gint) g_ascii_strtoull(new_version, NULL, 10); - /* - * do reconnection to the socket (socket is closed if - * the MythTV version was wrong) - */ - gmyth_socket_connect(gmyth_socket, - gmyth_socket->hostname, - gmyth_socket->port); - new_version = NULL; - if (--max_iterations > 0) { - g_string_free(payload, TRUE); - g_string_free(response, TRUE); - goto try_new_version; - } else - goto done; - } - } - } - } - - /* - * change the return value to a valid one - */ - if (res) { - mythtv_new_version = mythtv_version; - gmyth_socket->mythtv_version = mythtv_new_version; - } - - done: - g_string_free(payload, TRUE); - g_string_free(response, TRUE); - - return mythtv_new_version; -} - -/** Verifies if the Mythtv backend supported the GMyth supported version. - * - * @param gmyth_socket The GMythSocket instance. - * @return TRUE if supports, FALSE if not. - */ -gboolean -gmyth_socket_check_protocol_version(GMythSocket * gmyth_socket) -{ - return ((gmyth_socket->mythtv_version = - gmyth_socket_check_protocol_version_number(gmyth_socket, - MYTHTV_VERSION_DEFAULT)) - != MYTHTV_CANNOT_NEGOTIATE_VERSION); -} - -/** Returns the Mythtv backend supported version. - * - * @param gmyth_socket The GMythSocket instance. - * @return The actual MythTV version number. - */ -gint -gmyth_socket_get_protocol_version(GMythSocket * gmyth_socket) -{ - return gmyth_socket->mythtv_version; -} - -/** Receives a backend answer after a gmyth_socket_send_command_call (). - * - * @param gmyth_socket The GMythSocket instance. - * @return The response received, or NULL if error or nothing was received. - */ -GString * -gmyth_socket_receive_response(GMythSocket * gmyth_socket) -{ - GIOStatus io_status = G_IO_STATUS_NORMAL; - GError *error = NULL; - gchar *buffer = NULL; - - GString *str = NULL; - - gsize bytes_read = 0; - gint len = 0; - - if (gmyth_socket == NULL) - return NULL; - - GIOCondition io_cond; - - /* - * verify if the input (read) buffer is ready to receive data - */ - g_mutex_lock(gmyth_socket->mutex); - - buffer = g_strnfill(MYTH_PROTOCOL_FIELD_SIZE, ' '); - if (NULL == gmyth_socket->sd_io_ch) { - gmyth_socket_connect(gmyth_socket, gmyth_socket->hostname, - gmyth_socket->port); - } - - io_cond = g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch); - /* - * if ( NULL == gmyth_socket->sd_io_ch->read_buf || ( NULL == - * gmyth_socket->sd_io_ch->read_buf->str ) ) gmyth_socket->sd_io_ch = - * g_io_channel_unix_new( gmyth_socket->sd ); - */ - - if (gmyth_socket->sd_io_ch->is_readable /* && !( ( io_cond & G_IO_IN ) - * == 0 ) */ ) - io_status = - g_io_channel_read_chars(gmyth_socket->sd_io_ch, buffer, - MYTH_PROTOCOL_FIELD_SIZE, &bytes_read, - &error); - else - return g_string_new(""); - - /* - * verify if the input (read) buffer is ready to receive data - */ - io_cond = g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch); - - // if ( ( io_cond & G_IO_IN ) == 0 ) - // return NULL; - - gmyth_debug("[%s] Bytes read = %d\n", __FUNCTION__, bytes_read); - - if ((io_status == G_IO_STATUS_ERROR) || (bytes_read <= 0)) { - gmyth_debug("[%s] Error in mythprotocol response from backend\n", - __FUNCTION__); - str = NULL; - // return NULL; - } else if (buffer != NULL && strlen(buffer) > 0) { - - // io_status = g_io_channel_flush( gmyth_socket->sd_io_ch, &error - // ); - /* - * verify if the input (read) buffer is ready to receive data - */ - // io_cond = g_io_channel_get_buffer_condition( - // gmyth_socket->sd_io_ch ); - - // if ( ( io_cond & G_IO_IN ) != 0 ) { - // gchar *buffer_aux = NULL; - - /* - * removes trailing whitespace - */ - // buffer_aux = g_strstrip (buffer); - len = (gint) g_ascii_strtoull(g_strstrip(buffer), NULL, 10); - - g_free(buffer); - - /* - * if (buffer_aux != NULL) { g_free (buffer_aux); buffer_aux = - * NULL; } - */ - - buffer = g_new0(gchar, len + 1); - - bytes_read = 0; - if (!(gmyth_socket != NULL && gmyth_socket->sd_io_ch != NULL)) - return NULL; - - if (gmyth_socket->sd_io_ch->is_readable) - io_status = - g_io_channel_read_chars(gmyth_socket->sd_io_ch, buffer, - len, &bytes_read, &error); - else - return g_string_new(""); - - buffer[bytes_read] = '\0'; - // } - } - - g_mutex_unlock(gmyth_socket->mutex); - // g_static_rw_lock_reader_unlock (&rwlock); - - gmyth_debug("Response received from backend: ----- {%s}\n", buffer); - if ((bytes_read != len) || (io_status == G_IO_STATUS_ERROR)) - str = NULL; - else - str = g_string_new(buffer); - - if (error != NULL) { - gmyth_debug - ("[%s] Error found receiving response from the IO channel: (%d, %s)\n", - __FUNCTION__, error->code, error->message); - str = NULL; - g_error_free(error); - } - - g_free(buffer); - return str; -} - -/** Format a Mythtv command from the str_list entries and send it to backend. - * - * @param gmyth_socket The GMythSocket instance. - * @param str_list The string list to form the command - * @return TRUE if command was sent, FALSE if any error happens. - */ -gboolean -gmyth_socket_write_stringlist(GMythSocket * gmyth_socket, - GMythStringList * str_list) -{ - - GList *tmp_list = NULL; - GPtrArray *ptr_array = NULL; - gchar *str_array = NULL; - - g_mutex_lock(gmyth_socket->mutex); - // g_static_rw_lock_writer_lock (&rwlock); - - ptr_array = g_ptr_array_sized_new(g_list_length(str_list->glist)); - - // FIXME: change this implementation! - tmp_list = str_list->glist; - for (; tmp_list; tmp_list = tmp_list->next) { - if (tmp_list->data != NULL) { - g_ptr_array_add(ptr_array, ((GString *) tmp_list->data)->str); - } else { - g_ptr_array_add(ptr_array, ""); - } - } - g_ptr_array_add(ptr_array, NULL); // g_str_joinv() needs a NULL - // terminated string - - str_array = g_strjoinv(MYTH_SEPARATOR, (gchar **) (ptr_array->pdata)); - - g_mutex_unlock(gmyth_socket->mutex); - // g_static_rw_lock_writer_unlock (&rwlock); - - gmyth_debug("[%s] Sending socket request: %s\n", __FUNCTION__, - str_array); - - // Sends message to backend - // TODO: implement looping to send remaining data, and add timeout - // testing! - GString *command = g_string_new(str_array); - - gmyth_socket_send_command(gmyth_socket, command); - - g_string_free(command, TRUE); - - g_free(str_array); - - /* - * ptr_array is pointing to data inside str_list->glist - */ - g_ptr_array_free(ptr_array, TRUE); - - return TRUE; -} - -/* - * Receives a backend command response and split it into the given string - * list. @param gmyth_socket The GMythSocket instance. @param str_list - * the string list to be filled. @return The number of received strings. - */ -gint -gmyth_socket_read_stringlist(GMythSocket * gmyth_socket, - GMythStringList * str_list) -{ - GString *response; - gint i; - - gmyth_string_list_clear_all(str_list); - - response = gmyth_socket_receive_response(gmyth_socket); - if (response != NULL && response->str != NULL && response->len > 0) { - gchar **str_array; - - g_mutex_lock(gmyth_socket->mutex); - - str_array = g_strsplit(response->str, MYTH_SEPARATOR, -1); - - for (i = 0; i < g_strv_length(str_array); i++) { - // if ( str_array[i] != NULL && strlen( str_array[i] ) > 0 ) - gmyth_string_list_append_char_array(str_list, str_array[i]); - } - - g_mutex_unlock(gmyth_socket->mutex); - g_strfreev(str_array); - } - - g_string_free(response, TRUE); - - return gmyth_string_list_length(str_list); -} - -/** Formats a Mythtv protocol command based on str_list and sends it to - * the connected backend. The backend response is overwritten into str_list. - * - * @param gmyth_socket The GMythSocket instance. - * @param str_list The string list to be sent, and on which the answer - * will be written. - * @return TRUE if command was sent and an answer was received, FALSE if any - * error happens. - */ -gint -gmyth_socket_sendreceive_stringlist(GMythSocket * gmyth_socket, - GMythStringList * str_list) -{ - gmyth_socket_write_stringlist(gmyth_socket, str_list); - - return gmyth_socket_read_stringlist(gmyth_socket, str_list); -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_socket.h --- a/gmyth/src/gmyth_socket.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_socket.h - * - * @brief

MythTV socket implementation, according to the MythTV Project - * (www.mythtv.org). - * - * This component provides basic socket functionalities to interact with - * the Mythtv backend. - *

- * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Rosfran Lins Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __GMYTH_SOCKET_H__ -#define __GMYTH_SOCKET_H__ - -#include - -#include -#include -#include -#include -#include - -#include "gmyth_stringlist.h" - -G_BEGIN_DECLS -#define GMYTH_SOCKET_TYPE (gmyth_socket_get_type ()) -#define GMYTH_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SOCKET_TYPE, GMythSocket)) -#define GMYTH_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SOCKET_TYPE, GMythSocketClass)) -#define IS_GMYTH_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_SOCKET_TYPE)) -#define IS_GMYTH_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SOCKET_TYPE)) -#define GMYTH_SOCKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_SOCKET_TYPE, GMythSocketClass)) -typedef struct _GMythSocket GMythSocket; -typedef struct _GMythSocketClass GMythSocketClass; - -struct _GMythSocketClass { - GObjectClass parent_class; - - /* - * callbacks - */ - /* - * no one for now - */ -}; - -struct _GMythSocket { - GObject parent; - - GMutex *mutex; - - /* - * socket descriptor - */ - gint sd; - GIOChannel *sd_io_ch; - - gchar *hostname; - gint port; - gint mythtv_version; -}; - -/* - * used when no protocol version number was negotiated - */ -#define MYTHTV_CANNOT_NEGOTIATE_VERSION 0 - -GType gmyth_socket_get_type(void); - -GMythSocket *gmyth_socket_new(); - -GIOChannel *gmyth_socket_get_io_channel(GMythSocket * gmyth_socket); - -gboolean gmyth_socket_is_able_to_read(GMythSocket * gmyth_socket); -gboolean gmyth_socket_is_able_to_write(GMythSocket * gmyth_socket); - -gboolean gmyth_socket_send_command(GMythSocket * gmyth_socket, - GString * command); -GString *gmyth_socket_receive_response(GMythSocket * gmyth_socket); -gint gmyth_socket_sendreceive_stringlist(GMythSocket * - gmyth_socket, - GMythStringList * - str_list); - -gboolean gmyth_socket_connect(GMythSocket * gmyth_socket, - const gchar * hostname, gint port); -gboolean gmyth_socket_connect_with_timeout(GMythSocket * - gmyth_socket, - const gchar * hostname, - gint port, - guint timeout); - -gboolean gmyth_socket_connect_to_backend(GMythSocket * gmyth_socket, - const gchar * - hostname_backend, - gint port, - gboolean blocking_client); - -gboolean gmyth_socket_connect_to_backend_events(GMythSocket * - gmyth_socket, - const gchar * - hostname_backend, - gint port, - gboolean - blocking_client); - -gchar *gmyth_socket_get_primary_addr(void); - -GString *gmyth_socket_get_local_hostname(void); - -void gmyth_socket_close_connection(GMythSocket * gmyth_socket); - -gboolean gmyth_socket_check_protocol_version(GMythSocket * - gmyth_socket); -gint gmyth_socket_check_protocol_version_number(GMythSocket * - gmyth_socket, - gint - mythtv_version); - -gint gmyth_socket_get_protocol_version(GMythSocket * - gmyth_socket); - -gboolean gmyth_socket_write_stringlist(GMythSocket * gmyth_socket, - GMythStringList * str_list); -gint gmyth_socket_read_stringlist(GMythSocket * gmyth_socket, - GMythStringList * str_list); -G_END_DECLS -#endif /* __GMYTH_SOCKET_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_stringlist.c --- a/gmyth/src/gmyth_stringlist.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,454 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_stringlist.c - * - * @brief

This component contains functions for dealing with the stringlist - * format of the mythprotocol. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Hallyson Luiz de Morais Melo - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gmyth_stringlist.h" - -#include "gmyth_debug.h" - -static void gmyth_string_list_class_init(GMythStringListClass * klass); -static void gmyth_string_list_init(GMythStringList * object); - -static void gmyth_string_list_dispose(GObject * object); -static void gmyth_string_list_finalize(GObject * object); - -G_DEFINE_TYPE(GMythStringList, gmyth_string_list, G_TYPE_OBJECT) - static void gmyth_string_list_class_init(GMythStringListClass * - klass) -{ - GObjectClass *gobject_class; - - gobject_class = (GObjectClass *) klass; - - gobject_class->dispose = gmyth_string_list_dispose; - gobject_class->finalize = gmyth_string_list_finalize; -} - -static void -gmyth_string_list_init(GMythStringList * gmyth_string_list) -{ - gmyth_string_list->glist = NULL; -} - -static void -gmyth_string_list_dispose(GObject * object) -{ - GMythStringList *gmyth_string_list = GMYTH_STRING_LIST(object); - - gmyth_string_list_clear_all(gmyth_string_list); - - G_OBJECT_CLASS(gmyth_string_list_parent_class)->dispose(object); -} - -static void -gmyth_string_list_finalize(GObject * object) -{ - // GMythStringList *gmyth_string_list = GMYTH_STRING_LIST(object); - - g_signal_handlers_destroy(object); - - G_OBJECT_CLASS(gmyth_string_list_parent_class)->finalize(object); -} - -/** Creates a new instance of GStringList. - * - * @return a new instance of GStringList. - */ -GMythStringList * -gmyth_string_list_new() -{ - GMythStringList *gmyth_string_list = - GMYTH_STRING_LIST(g_object_new(GMYTH_STRING_LIST_TYPE, NULL)); - - return gmyth_string_list; -} - -/** Appends a guint64 to the string list. - * - * @param strlist The GMythStringList instance. - * @param value The guint64 to be appended. - * - * @return The appended guint64 converted to a GString object. - */ -GString * -gmyth_string_list_append_int(GMythStringList * strlist, const gint value) -{ - GString *value_str = g_string_new(""); - - g_string_printf(value_str, "%d", value); - - strlist->glist = g_list_append(strlist->glist, value_str); - - return value_str; -} - - -/** Appends a gdouble to the string list. - * - * @param strlist The GMythStringList instance. - * @param value The gdouble to be appended. - * - * @return The appended gdouble converted to a GString object. - */ -GString * -gmyth_string_list_append_float(GMythStringList * strlist, const gdouble value) -{ - GString *value_str = g_string_new(""); - g_string_printf(value_str, "%f", value); - strlist->glist = g_list_append(strlist->glist, value_str); - return value_str; -} - - -/** Appends a guint64 to the string list. - * - * @param strlist The GMythStringList instance. - * @param value The guint64 to be appended. - * - * @return The appended guint64 converted to a GString object. - */ -GString * -gmyth_string_list_append_uint64(GMythStringList * strlist, - const guint64 value) -{ - GString *tmp_str1 = g_string_new(""); - GString *tmp_str2 = g_string_new(""); - - gmyth_debug("value = %llu.\n", value); - - gulong l2 = ((guint64) value & 0xffffffff); - gulong l1 = ((guint64) value >> 32); - - /* - * high order part of guint64 value - */ - g_string_printf(tmp_str1, "%lu", l1); - - gmyth_debug("[%s] uint64 (high) = %s\n", __FUNCTION__, tmp_str1->str); - - strlist->glist = g_list_append(strlist->glist, tmp_str1); - - /* - * low order part of guint64 value - */ - g_string_printf(tmp_str2, "%lu", l2); - - gmyth_debug("[%s] uint64 (low) = %s\n", __FUNCTION__, tmp_str2->str); - - strlist->glist = g_list_append(strlist->glist, tmp_str2); - - return tmp_str2; -} - -/** Appends a gint64 to the string list. - * - * @param strlist The GMythStringList instance. - * @param value The gint64 to be appended. - * - * @return The appended gint64 converted to a GString object. - */ -GString * -gmyth_string_list_append_int64(GMythStringList * strlist, - const gint64 value) -{ - GString *tmp_str1 = g_string_new(""); - GString *tmp_str2 = g_string_new(""); - - gmyth_debug("value = %lld.\n", value); - - glong l2 = ((gint64) value & 0xffffffff); - glong l1 = ((gint64) value >> 32); - - /* - * high order part of gint64 value - */ - g_string_printf(tmp_str1, "%ld", l1); - - gmyth_debug("[%s] int64 (high) = %s\n", __FUNCTION__, tmp_str1->str); - - strlist->glist = g_list_append(strlist->glist, tmp_str1); - - /* - * low order part of gint64 value - */ - g_string_printf(tmp_str2, "%ld", l2); - - gmyth_debug("[%s] int64 (low) = %s\n", __FUNCTION__, tmp_str2->str); - - strlist->glist = g_list_append(strlist->glist, tmp_str2); - - return tmp_str2; -} - -/** Appends a char array to the string list. - * - * @param strlist The GMythStringList instance. - * @param value The char array to be appended. - * - * @return The appended char array converted to a GString object. - */ -GString * -gmyth_string_list_append_char_array(GMythStringList * strlist, - const gchar * value) -{ - GString *tmp_str = NULL; - - g_return_val_if_fail(strlist != NULL, NULL); - - tmp_str = g_string_new(value); - - strlist->glist = g_list_append(strlist->glist, tmp_str); - - return tmp_str; -} - -/** Appends a string to the string list. - * - * @param strlist The GMythStringList instance. - * @param value The string to be appended. - * - * @return The appended string itself. - */ -GString * -gmyth_string_list_append_string(GMythStringList * strlist, GString * value) -{ - g_return_val_if_fail(strlist != NULL, NULL); - - if (value != NULL) { - strlist->glist = - g_list_append(strlist->glist, g_string_new(value->str)); - } else { - strlist->glist = g_list_append(strlist->glist, NULL); - } - - return value; -} - -/** Gets an integer value from the string list at the given position. - * - * @param strlist The GMythStringList instance. - * @param index the integer position in the list, starting with zero. - * @return The integer value. - */ -gint -gmyth_string_list_get_int(GMythStringList * strlist, const gint index) -{ - // TODO: Create static method check_index() - GString *tmp_str = NULL; - - g_return_val_if_fail(strlist != NULL, 0); - - tmp_str = (GString *) g_list_nth_data(strlist->glist, index); - - if (NULL == tmp_str || NULL == tmp_str->str - || strlen(tmp_str->str) <= 0) - return 0; - - return (gint) ( /* 0x00000000ffffffffL & (gint64) */ - g_ascii_strtoull(tmp_str->str, NULL, 10)); -} - -/** Gets a guint64 value from the string list at the given position. - * According to the Mythtv protocol, the 64 bits value is formed by - * two strings. - * - * @param strlist The GMythStringList instance. - * @param index the index of the first string forming the 64 bits value. - * Index starts with zero. - * @return The guint64 value. - */ -guint64 -gmyth_string_list_get_uint64(GMythStringList * strlist, const gint index) -{ - // TODO: Create static method check_index() - guint64 ret_value = 0; - guint64 l2 = 0; - - g_return_val_if_fail(strlist != NULL, 0); - - const GString *tmp_str1 = - (GString *) g_list_nth_data(strlist->glist, index); - const GString *tmp_str2 = - (GString *) g_list_nth_data(strlist->glist, index + 1); - - if (tmp_str1 != NULL) - gmyth_debug("[%s] seek high bytes = %s\n", __FUNCTION__, - tmp_str1->str); - if (tmp_str2 == NULL || strlen(tmp_str2->str) > 0) { - } else { - gmyth_debug("[%s] seek low bytes = %s\n", __FUNCTION__, - tmp_str2->str); - } - - guint64 l1 = ((guint64) g_ascii_strtoull(tmp_str1->str, NULL, 10) /* & - * 0xffffffff - */ - ); - - if (tmp_str2 != NULL && tmp_str2->str != NULL - && strlen(tmp_str2->str) > 0) { - l2 = ((guint64) g_ascii_strtoull(tmp_str2->str, NULL, 10) - /* - * & 0xffffffff - */ - ); - } else { - l2 = l1; - l1 = 0; - } - - gmyth_debug("[%s]\t[l1 == %llu, l2 == %llu]\n", __FUNCTION__, l1, l2); - - ret_value = - ((guint64) (l2) /* & 0xffffffff */ ) | ((guint64) l1 << 32); - - gmyth_debug("[%s] returning uint64 value = %llu\n", __FUNCTION__, - ret_value); - - return ret_value; -} - -/** Gets a gint64 value from the string list at the given position. - * According to the Mythtv protocol, the 64 bits value is formed by - * two strings. - * - * @param strlist The GMythStringList instance. - * @param index the index of the first string forming the 64 bits value. - * Index starts with zero. - * @return The gint64 value. - */ -gint64 -gmyth_string_list_get_int64(GMythStringList * strlist, const gint index) -{ - // TODO: Create static method check_index() - gint64 ret_value = 0; - gint64 l2 = 0; - - g_return_val_if_fail(strlist != NULL, 0); - - const GString *tmp_str1 = - (GString *) g_list_nth_data(strlist->glist, index); - const GString *tmp_str2 = - (GString *) g_list_nth_data(strlist->glist, index + 1); - - if (tmp_str1 != NULL) - gmyth_debug("[%s] seek high bytes = %s\n", __FUNCTION__, - tmp_str1->str); - if (tmp_str2 == NULL || strlen(tmp_str2->str) > 0) { - } else { - gmyth_debug("[%s] seek low bytes = %s\n", __FUNCTION__, - tmp_str2->str); - } - - gint64 l1 = ((guint64) g_ascii_strtoull(tmp_str1->str, NULL, 10) /* & - * 0xffffffff - */ - ); - - if (tmp_str2 != NULL && tmp_str2->str != NULL - && strlen(tmp_str2->str) > 0) { - l2 = ((gint64) g_ascii_strtoull(tmp_str2->str, NULL, 10) - /* - * & 0xffffffff - */ - ); - } else { - l2 = l1; - l1 = 0; - } - - gmyth_debug("[%s]\t[l1 == %lld, l2 == %lld]\n", __FUNCTION__, l1, l2); - - ret_value = ((gint64) (l2) /* & 0xffffffff */ ) | ((gint64) l1 << 32); - - gmyth_debug("[%s] returning int64 value = %lld\n", __FUNCTION__, - ret_value); - - return ret_value; -} - - -/** Gets a string from the string list at the given position. The GString must be deallocated. - * - * @param strlist The GMythStringList instance. - * @param index the string position in the list, starting with zero. - * @return A pointer to the string data. - */ -GString * -gmyth_string_list_get_string(GMythStringList * strlist, const gint index) -{ - GString *ret; - - if (!strlist || !(strlist->glist)) { - gmyth_debug("%s received Null arguments", __FUNCTION__); - return NULL; - } - - ret = (GString *) g_list_nth_data(strlist->glist, index); - - return g_string_new(ret->str); -} - - -static void -gmyth_string_list_clear_element(GString * str_elem, void *data_aux) -{ - if (str_elem != NULL) - g_string_free(str_elem, TRUE); -} - -/** Removes all strings from the string list. - * - * @param strlist The GMythStringList instance. - */ -void -gmyth_string_list_clear_all(GMythStringList * strlist) -{ - if (strlist != NULL && strlist->glist) { - g_list_foreach(strlist->glist, - (GFunc) gmyth_string_list_clear_element, NULL); - g_list_free(strlist->glist); - strlist->glist = NULL; - } -} - -/** Retrieves the number of elements in the string list. - * - * @param strlist The GMythStringList instance. - * @return the string list length. - */ -gint -gmyth_string_list_length(GMythStringList * strlist) -{ - if (!(strlist != NULL && strlist->glist != NULL)) - return 0; - - return g_list_length(strlist->glist); -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_stringlist.h --- a/gmyth/src/gmyth_stringlist.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_stringlist.h - * - * @brief

This component contains functions for dealing with the stringlist - * format of the mythprotocol. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Hallyson Luiz de Morais Melo - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GMYTH_STRING_LIST_H_ -#define GMYTH_STRING_LIST_H_ - -#include - -#include -#include -#include -#include -#include -#include - -G_BEGIN_DECLS -#define GMYTH_STRING_LIST_TYPE (gmyth_string_list_get_type ()) -#define GMYTH_STRING_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_STRING_LIST_TYPE, GMythStringList)) -#define GMYTH_STRING_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_STRING_LIST_TYPE, GMythStringListClass)) -#define IS_GMYTH_STRING_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_STRING_LIST_TYPE)) -#define IS_GMYTH_STRING_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_STRING_LIST_TYPE)) -#define GMYTH_STRING_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_STRING_LIST_TYPE, GMythStringListClass)) -typedef struct _GMythStringList GMythStringList; -typedef struct _GMythStringListClass GMythStringListClass; - -struct _GMythStringListClass { - GObjectClass parent_class; - - /* - * callbacks - */ - /* - * no one for now - */ -}; - -struct _GMythStringList { - GObject parent; - - /* - * string list - */ - GList *glist; -}; - - -GType gmyth_string_list_get_type(void); - -GMythStringList *gmyth_string_list_new(void); - -void gmyth_string_list_clear_all(GMythStringList * strlist); -int gmyth_string_list_length(GMythStringList * strlist); - -GString *gmyth_string_list_append_float(GMythStringList * strlist, - const gdouble value); - -GString *gmyth_string_list_append_int(GMythStringList * strlist, - const gint value); -GString *gmyth_string_list_append_uint64(GMythStringList * strlist, - const guint64 value); - -GString *gmyth_string_list_append_int64(GMythStringList * strlist, - const gint64 value); - -GString *gmyth_string_list_append_char_array(GMythStringList * - strlist, - const char *value); -GString *gmyth_string_list_append_string(GMythStringList * strlist, - GString * value); - -int gmyth_string_list_get_int(GMythStringList * strlist, - const gint index); -guint64 gmyth_string_list_get_uint64(GMythStringList * strlist, - const gint index); -gint64 gmyth_string_list_get_int64(GMythStringList * strlist, - const gint index); -GString *gmyth_string_list_get_string(GMythStringList * strlist, - const gint index); - -#define gmyth_string_list_get_char_array(strlist, index) \ - (gmyth_string_list_get_string(strlist, index))->str - -G_END_DECLS -#endif /* GMYTH_STRING_LIST_H_ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_transcoder.c --- a/gmyth/src/gmyth_transcoder.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,272 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_transcoder.c - * - * @brief

This file contains the transcoder class. - * - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. - * @author Artur Duque de Souza - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "gmyth_util.h" -#include "gmyth_debug.h" - -#include "gmyth_jobqueue.h" -#include "gmyth_transcoder.h" - -static void gmyth_transcoder_class_init(GMythTranscoderClass * klass); -static void gmyth_transcoder_init(GMythTranscoder * object); - -static void gmyth_transcoder_dispose(GObject * object); -static void gmyth_transcoder_finalize(GObject * object); - -G_DEFINE_TYPE(GMythTranscoder, gmyth_transcoder, G_TYPE_OBJECT) - static void gmyth_transcoder_class_init(GMythTranscoderClass * - klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - gobject_class->dispose = gmyth_transcoder_dispose; - gobject_class->finalize = gmyth_transcoder_finalize; -} - -static void -gmyth_transcoder_init(GMythTranscoder * transcoder) -{ - transcoder->started = FALSE; -} - -static void -gmyth_transcoder_dispose(GObject * object) -{ - GMythTranscoder *transcoder = GMYTH_TRANSCODER(object); - - g_free(transcoder->output_filename); - g_free(transcoder->filename); - g_free(transcoder->profile); - g_free(transcoder->starttime); - - if (transcoder->backend_info) - g_object_unref(transcoder->backend_info); - - G_OBJECT_CLASS(gmyth_transcoder_parent_class)->dispose(object); -} - -static void -gmyth_transcoder_finalize(GObject * object) -{ - g_signal_handlers_destroy(object); - G_OBJECT_CLASS(gmyth_transcoder_parent_class)->finalize(object); -} - -/** - * Creates a new instance of GMythTranscoder. - * - * @return a new instance of GMythTranscoder. - **/ -GMythTranscoder * -gmyth_transcoder_new(GMythBackendInfo * backend_info) -{ - GMythTranscoder *transcoder = GMYTH_TRANSCODER - (g_object_new(GMYTH_TRANSCODER_TYPE, NULL)); - - if (backend_info != NULL) { - g_object_ref(backend_info); - transcoder->backend_info = backend_info; - } - - return transcoder; -} - -/** - * - * gmyth_transcoder_date_change_format - * @brief converts a string like YYYY-MM-DDTHH:MM:SS into YYYYMMDDHHMMSS (vice versa) - * @param date_s gchar* - * @return gchar* with file or iso format - * - **/ -static gchar * -gmyth_transcoder_date_change_format(gchar * date_s, int format) -{ - if (date_s != NULL) { - gint length = strlen(date_s); - - // create the right date format - gchar *src = (gchar *) g_malloc0(sizeof(gchar) * length); - - strncpy(src, date_s, length); - - gchar *dst; - - if (format == DATE_FILE) { - dst = (gchar *) g_malloc0(sizeof(gchar) * 16); - snprintf(dst, 16, "%.4s%.2s%.2s%.2s%.2s%.2s", src, src + 5, - src + 7, src + 9, src + 11, src + 13); - dst[15] = '\0'; - } else if (format == DATE_ISO) { - dst = (gchar *) g_malloc0(sizeof(gchar) * 20); - snprintf(dst, 20, "%.4s-%.2s-%.2sT%.2s:%.2s:%.2s", src, - src + 4, src + 6, src + 8, src + 10, src + 12); - dst[19] = '\0'; - } - - gchar *ret = g_strdup(dst); - - g_free(src); - g_free(dst); - - return ret; - } else - return NULL; -} - -/** - * gmyth_transcoder_set_output - * @brief set transcoder to use output - * @param value gboolean - * @param outfile filename of output - * @return void set's up the var to value - * - **/ -void -gmyth_transcoder_set_output(GMythTranscoder * transcoder, - gboolean value, const gchar * outputfile) -{ - transcoder->output = value; - transcoder->output_filename = g_strdup(outputfile); -} - -/** - * gmyth_transcoder_set_file - * @brief set the file to transcoder - * @param file filename - * @return void set's up the var to value - * - **/ -void -gmyth_transcoder_set_filename(GMythTranscoder * transcoder, - const gchar * file) -{ - // fixme: if this method is called twice, memory will not be - // dealocated - // one transcoder can be used only for one file request? - if (file != NULL) { - gchar **splited = g_strsplit(file, "_", 2); - - // Get chanid - sscanf(splited[0], "%d", &(transcoder->chanid)); - - // Get starttime - gchar **date = g_strsplit(splited[1], ".", 2); - - transcoder->starttime = - gmyth_transcoder_date_change_format(date[0], DATE_ISO); - - transcoder->filename = g_strdup(file); - } -} - - -/** - * - * gmyth_transcoder_set_profile - * @brief set transcoder's profile - * @param rec GMythTranscoder* - * @param value the value - * @return gint representing the result - * - **/ -gint -gmyth_transcoder_set_profile(GMythTranscoder * trans, const gchar * value) -{ - g_return_val_if_fail(value != NULL, -1); - - trans->profile = g_strndup(value, strlen(value)); - - return 0; -} - -gboolean -gmyth_transcoder_start(GMythTranscoder * trans) -{ - g_return_val_if_fail(trans != NULL, FALSE); - g_return_val_if_fail(trans->backend_info != NULL, FALSE); - g_return_val_if_fail(trans->filename != NULL, FALSE); - - if (trans->started == FALSE) { // not started yet - if (!gmyth_util_file_exists(trans->backend_info, trans->filename)) { - gmyth_debug("File %s does not exist", trans->filename); - } - trans->started = gmyth_jobqueue_add_job(trans, "JOB_TRANSCODE"); - if (trans->started == FALSE) - gmyth_debug("Error while starting GMythTranscoder to file: %s", - trans->output_filename); - } else { - gmyth_debug("GMythTransfer already started!"); - } - - return trans->started; -} - -gboolean -gmyth_transcoder_pause(GMythTranscoder * trans) -{ - g_return_val_if_fail(trans != NULL, FALSE); - g_return_val_if_fail(trans->started == TRUE, FALSE); - - return gmyth_jobqueue_change_cmd(trans, "PAUSE", "JOB_TRANSCODE"); -} - -gboolean -gmyth_transcoder_resume(GMythTranscoder * trans) -{ - g_return_val_if_fail(trans != NULL, FALSE); - - return gmyth_jobqueue_change_cmd(trans, "RESUME", "JOB_TRANSCODE"); -} - -gboolean -gmyth_transcoder_cancel(GMythTranscoder * trans) -{ - g_return_val_if_fail(trans != NULL, FALSE); - g_return_val_if_fail(trans->started == TRUE, FALSE); - - trans->started = FALSE; - - return gmyth_jobqueue_change_cmd(trans, "STOP", "JOB_TRANSCODE"); -} - -// fixme: implement this method -gint -gmyth_transcoder_get_progress(GMythTranscoder * trans) -{ - static int fixme = 0; - - return (fixme++) % 101; -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_transcoder.h --- a/gmyth/src/gmyth_transcoder.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_transcoder.h - * - * @brief

This file contains the transcoder class. - * - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. - * @author Artur Duque de Souza - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _GMYTH_TRANSCODER_H -#define _GMYTH_TRANSCODER_H - -#include -#include - -#include "gmyth_stringlist.h" -#include "gmyth_backendinfo.h" -#include "gmyth_socket.h" -#include "gmyth_http.h" -#include "gmyth_recprofile.h" - -G_BEGIN_DECLS -#define GMYTH_TRANSCODER_TYPE (gmyth_transcoder_get_type ()) -#define GMYTH_TRANSCODER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TRANSCODER_TYPE, GMythTranscoder)) -#define GMYTH_TRANSCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TRANSCODER_TYPE, GMythTranscoderClass)) -#define IS_GMYTH_TRANSCODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_TRANSCODER_TYPE)) -#define IS_GMYTH_TRANSCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TRANSCODER_TYPE)) -#define GMYTH_TRANSCODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_TRANSCODER_TYPE, GMythTranscoderClass)) -#define DATE_ISO 0 -#define DATE_FILE 1 -typedef struct _GMythTranscoder GMythTranscoder; -typedef struct _GMythTranscoderClass GMythTranscoderClass; - -struct _GMythTranscoderClass { - GObjectClass parent_class; - - /* - * callbacks - */ -}; - -/** - * The GMythTranscoder structure is a class to implement functions - * related to transcoding. - */ -struct _GMythTranscoder { - GObject parent; - - gboolean cutlist; - gboolean output; - gboolean started; - - /* - * private begin - */ - gchar *output_filename; - gchar *filename; - gchar *profile; - /* - * private end - */ - - gchar *starttime; - - gint chanid; - - GMythBackendInfo *backend_info; -}; - -GType gmyth_transcoder_type(void); - -GMythTranscoder *gmyth_transcoder_new(GMythBackendInfo * backend_info); -void gmyth_transcoder_set_output(GMythTranscoder * transcode, - gboolean value, - const gchar * outputfile); -void gmyth_transcoder_set_filename(GMythTranscoder * transcode, - const gchar * file); -gint gmyth_transcoder_set_profile(GMythTranscoder * trans, - const gchar * value); -gboolean gmyth_transcoder_start(GMythTranscoder * trans); -gboolean gmyth_transcoder_pause(GMythTranscoder * trans); -gboolean gmyth_transcoder_resume(GMythTranscoder * trans); -gboolean gmyth_transcoder_cancel(GMythTranscoder * trans); -gint gmyth_transcoder_get_progress(GMythTranscoder * trans); - - -G_END_DECLS -#endif /*_GMYTH_TRANSCODER_H*/ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_tvchain.c --- a/gmyth/src/gmyth_tvchain.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,620 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_tvchain.c - * - * @brief

This component contains functions for creating and accessing - * the tvchain functions for live tv playback. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Hallyson Luiz de Morais Melo - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gmyth_tvchain.h" - -#include -#include -#include -#include -#include - -#include "gmyth_epg.h" -#include "gmyth_util.h" -#include "gmyth_query.h" -#include "gmyth_scheduler.h" -#include "gmyth_debug.h" - -static void gmyth_tvchain_class_init(GMythTVChainClass * klass); -static void gmyth_tvchain_init(GMythTVChain * object); - -static void gmyth_tvchain_dispose(GObject * object); -static void gmyth_tvchain_finalize(GObject * object); - -static void free_tvchain_entry(gpointer data, gpointer user_data); - -G_DEFINE_TYPE(GMythTVChain, gmyth_tvchain, G_TYPE_OBJECT) - static void gmyth_tvchain_class_init(GMythTVChainClass * klass) -{ - GObjectClass *gobject_class; - - gobject_class = (GObjectClass *) klass; - - gobject_class->dispose = gmyth_tvchain_dispose; - gobject_class->finalize = gmyth_tvchain_finalize; -} - -static void -gmyth_tvchain_init(GMythTVChain * tvchain) -{ - tvchain->tvchain_id = NULL; - - tvchain->cur_chanid = g_string_new(""); - tvchain->cur_startts = NULL; - - tvchain->mutex = g_mutex_new(); -} - -GMythTVChain * -gmyth_tvchain_new() -{ - GMythTVChain *tvchain = - GMYTH_TVCHAIN(g_object_new(GMYTH_TVCHAIN_TYPE, NULL)); - - return tvchain; -} - -static void -gmyth_tvchain_dispose(GObject * object) -{ - GMythTVChain *tvchain = GMYTH_TVCHAIN(object); - - if (tvchain->tvchain_id != NULL) { - g_string_free(tvchain->tvchain_id, TRUE); - tvchain->tvchain_id = NULL; - } - - if (tvchain->mutex != NULL) { - g_mutex_free(tvchain->mutex); - tvchain->mutex = NULL; - } - - if (tvchain->tvchain_list != NULL) { - g_list_foreach(tvchain->tvchain_list, free_tvchain_entry, NULL); - g_list_free(tvchain->tvchain_list); - } - - if (tvchain->cur_chanid != NULL) { - g_string_free(tvchain->cur_chanid, TRUE); - tvchain->cur_chanid = NULL; - } - - if (tvchain->backend_info) { - g_object_unref(tvchain->backend_info); - tvchain->backend_info = NULL; - } - - - G_OBJECT_CLASS(gmyth_tvchain_parent_class)->dispose(object); -} - -static void -gmyth_tvchain_finalize(GObject * object) -{ - g_signal_handlers_destroy(object); - - G_OBJECT_CLASS(gmyth_tvchain_parent_class)->finalize(object); -} - -/** Initializes the tvchain and generates the tvchain id. - * - * @param tvchain The GMythTVChain instance. - * @param hostname The local hostname used to generate the tvchain id. - */ -gboolean -gmyth_tvchain_initialize(GMythTVChain * tvchain, - GMythBackendInfo * backend_info) -{ - const char *hostname; - - assert(tvchain); - g_return_val_if_fail(backend_info != NULL, FALSE); - - g_object_ref(backend_info); - tvchain->backend_info = backend_info; - - hostname = gmyth_backend_info_get_hostname(backend_info); - - if (tvchain->tvchain_id == NULL) { - gchar *isodate = NULL; - GTimeVal *cur_time = g_new0(GTimeVal, 1); - - // struct tm* gmyth_util_time_val_to_date ( const GTimeVal* time ) - - g_get_current_time(cur_time); - isodate = - gmyth_util_time_to_isoformat_from_time_val_fmt - ("%Y-%m-%dT%H:%M:%S", cur_time); - - tvchain->tvchain_id = - g_string_sized_new(7 + strlen(hostname) + strlen(isodate)); - g_string_printf(tvchain->tvchain_id, "live-%s-%s", hostname, - isodate); - - gmyth_debug("[%s] tv_chain_id: %s", __FUNCTION__, - tvchain->tvchain_id->str); - - g_free(isodate); - g_free(cur_time); - } else { - gmyth_debug("[%s] TVchain already initialized", __FUNCTION__); - } - - return TRUE; -} - -/** Gets the tvchain id. - * - * @param tvchain The GMythTVChain instance. - * @return The tvchain id. - */ -GString * -gmyth_tvchain_get_id(GMythTVChain * tvchain) -{ - g_return_val_if_fail(tvchain != NULL - && tvchain->tvchain_id != NULL, NULL); - - return tvchain->tvchain_id; -} - -/** Reloads all tvchain entries in the database. - * - * @param tvchain The GMythTVChain instance. - * @return TRUE if success, or FALSE if error. - */ -gboolean -gmyth_tvchain_reload_all(GMythTVChain * tvchain) -{ - MYSQL_ROW msql_row; - MYSQL_RES *msql_res = NULL; - GMythQuery *gmyth_query = NULL; - gboolean ret = TRUE; - GString *stmt_str = NULL; - - g_mutex_lock(tvchain->mutex); - - /* - * gets the initial size of the TVChain entries list - */ - guint prev_size = g_list_length(tvchain->tvchain_list); - - gmyth_debug("[%s] chainid: %s", __FUNCTION__, - tvchain->tvchain_id->str); - - if (tvchain != NULL && tvchain->tvchain_list != NULL) { - g_list_free(tvchain->tvchain_list); - tvchain->tvchain_list = NULL; - } - - /* - * TODO: Reuse gmyth_query already connected from context - */ - gmyth_query = gmyth_query_new(); - if (!gmyth_query_connect(gmyth_query, tvchain->backend_info)) { - gmyth_debug("[%s] Could not connect to db", __FUNCTION__); - g_mutex_unlock(tvchain->mutex); - ret = FALSE; - goto done; - } - - stmt_str = g_string_new(""); - g_string_printf(stmt_str, - "SELECT chanid, starttime, endtime, discontinuity, " - "chainpos, hostprefix, cardtype, channame, input " - "FROM tvchain " - "WHERE chainid = \"%s\" ORDER BY chainpos;", - tvchain->tvchain_id->str); - - msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str); - if (msql_res != NULL) { - - while ((msql_row = mysql_fetch_row(msql_res)) != NULL) { - struct LiveTVChainEntry *entry = - g_new0(struct LiveTVChainEntry, 1); - entry->chanid = g_string_new(msql_row[0]); - entry->starttime = - gmyth_util_string_to_time_val((const gchar *) msql_row[1]); - entry->endtime = - gmyth_util_string_to_time_val((const gchar *) msql_row[2]); - entry->discontinuity = - g_ascii_strtoull(msql_row[3], NULL, 10) != 0; - entry->hostprefix = g_string_new(msql_row[5]); - entry->cardtype = g_string_new(msql_row[6]); - entry->channum = g_string_new(msql_row[7]); - entry->inputname = g_string_new(msql_row[8]); - - // m_maxpos = query.value(4).toInt() + 1; - gmyth_debug - ("[%s] Reading TV chain entry (channel %s): [%s, %s, %s]\n", - __FUNCTION__, entry->channum->str, entry->chanid->str, - (gchar *) msql_row[1], (gchar *) msql_row[2]); - - /* - * add this to get the actual start timestamp of the last - * recording - */ - if (tvchain->cur_startts < entry->starttime) - tvchain->cur_startts = entry->starttime; - - tvchain->tvchain_list = - g_list_append(tvchain->tvchain_list, entry); - } - } else { - gmyth_debug("gmyth_tvchain_reload_all query error!\n"); - g_mutex_unlock(tvchain->mutex); - - ret = FALSE; - goto done; - } - - g_mutex_unlock(tvchain->mutex); - - tvchain->cur_pos = - gmyth_tvchain_program_is_at(tvchain, tvchain->cur_chanid, - tvchain->cur_startts); - gmyth_debug("[%s] TVChain current position = %d.\n", __FUNCTION__, - tvchain->cur_pos); - - if (tvchain->cur_pos < 0) - tvchain->cur_pos = 0; - - // if (m_switchid >= 0) - // m_switchid = - // ProgramIsAt(m_switchentry.chanid,m_switchentry.starttime); - - if (prev_size != g_list_length(tvchain->tvchain_list)) { - gmyth_debug("[%s] Added new recording", __FUNCTION__); - } - - done: - if (stmt_str != NULL) - g_string_free(stmt_str, TRUE); - - if (msql_res != NULL) - mysql_free_result(msql_res); - - if (gmyth_query != NULL) - g_object_unref(gmyth_query); - - return ret; -} - -/** - * Get all the program info entries in the database. - * - * @param tvchain The GMythTVChain instance. - * - * @return A program info listage. - */ -GList * -gmyth_tvchain_get_program_info_list(GMythTVChain * tvchain) -{ - GList *prog_list = NULL; - MYSQL_ROW msql_row; - MYSQL_RES *msql_res = NULL; - GMythQuery *gmyth_query = NULL; - GString *stmt_str = NULL; - - g_mutex_lock(tvchain->mutex); - - gmyth_query = gmyth_query_new(); - if (!gmyth_query_connect(gmyth_query, tvchain->backend_info)) { - gmyth_debug("Could not connect to db."); - goto done; - } - - stmt_str = g_string_new(""); - g_string_printf(stmt_str, - "SELECT channum, icon " "FROM channel " - "ORDER BY channum;"); - - msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str); - if (msql_res != NULL) { - - while ((msql_row = mysql_fetch_row(msql_res)) != NULL) { - GMythProgramInfo *entry = gmyth_program_info_new(); - - entry->channame = g_string_new(msql_row[0]); - entry->chansign = g_string_new(msql_row[1]); - - gmyth_debug - ("Reading TV program info entry (channel %s): [%s - {%s, %s}]\n", - entry->channame->str, entry->chansign->str, - (gchar *) msql_row[0], (gchar *) msql_row[1]); - - prog_list = g_list_append(prog_list, entry); - } - } else { - gmyth_debug - ("Query error when trying to get the channel list from database!\n"); - goto done; - } - - done: - g_mutex_unlock(tvchain->mutex); - - if (stmt_str != NULL) - g_string_free(stmt_str, TRUE); - - if (msql_res != NULL) - mysql_free_result(msql_res); - - if (gmyth_query != NULL) - g_object_unref(gmyth_query); - - return prog_list; -} - -/** - * Get all the program info entries in the database, given a channel name. - * - * @param tvchain The GMythTVChain instance. - * @param channel The channel name. - * - * @return A program info listage, based on a given channel name. - */ -GList * -gmyth_tvchain_get_program_info_from_channel(GMythTVChain * tvchain, - const gchar * channel) -{ - GList *prog_list = NULL; - MYSQL_ROW msql_row; - MYSQL_RES *msql_res = NULL; - GMythQuery *gmyth_query = NULL; - GString *stmt_str = NULL; - - g_mutex_lock(tvchain->mutex); - - gmyth_query = gmyth_query_new(); - if (!gmyth_query_connect(gmyth_query, tvchain->backend_info)) { - gmyth_debug("Could not connect to db."); - goto done; - } - - stmt_str = g_string_new(""); - g_string_printf(stmt_str, - "SELECT channum, icon " - "FROM channel " - "WHERE channum = \"%s\" ORDER BY channum;", channel); - - msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str); - if (msql_res != NULL) { - - while ((msql_row = mysql_fetch_row(msql_res)) != NULL) { - GMythProgramInfo *entry = gmyth_program_info_new(); - - entry->channame = g_string_new(msql_row[0]); - entry->chansign = g_string_new(msql_row[1]); - - gmyth_debug - ("Reading TV program info entry (channel %s): [%s - {%s, %s}]\n", - entry->channame->str, entry->chansign->str, - (gchar *) msql_row[0], (gchar *) msql_row[1]); - - prog_list = g_list_append(prog_list, entry); - } - } else { - gmyth_debug - ("Query error when trying to get the channel list from database!\n"); - goto done; - } - - done: - g_mutex_unlock(tvchain->mutex); - - if (stmt_str != NULL) - g_string_free(stmt_str, TRUE); - - if (msql_res != NULL) - mysql_free_result(msql_res); - - if (gmyth_query != NULL) - g_object_unref(gmyth_query); - - return prog_list; -} - -/** - * Returns the internal index for the TV chain related to the given - * channel and start time. - * - * @param tvchain The GMythTVChain instance. - * @param chanid The channel id. - * @param startts The program start time. - * - * @return The position of the related program info in the TV chain. - */ -gint -gmyth_tvchain_program_is_at(GMythTVChain * tvchain, GString * chanid, - GTimeVal * startts) -{ - gint count = 0; - struct LiveTVChainEntry *entry; - GList *tmp_list = tvchain->tvchain_list; - guint list_size = g_list_length(tvchain->tvchain_list); - - g_mutex_lock(tvchain->mutex); - - for (; tmp_list && (count < list_size); - tmp_list = tvchain->tvchain_list->next, count++) { - entry = (struct LiveTVChainEntry *) tmp_list->data; - if (!g_strncasecmp(entry->chanid->str, chanid->str, chanid->len) - && entry->starttime == startts) { - g_mutex_unlock(tvchain->mutex); - return count; - } - } - g_mutex_unlock(tvchain->mutex); - - return -1; -} - -/** Get the program info associated to the tvchain. - * - * @param tvchain The GMythTVChain instance. - * @param index The tvchain index. - * - * @return The program info structure. - */ -GMythProgramInfo * -gmyth_tvchain_get_program_at(GMythTVChain * tvchain, gint index) -{ - struct LiveTVChainEntry *entry; - - entry = gmyth_tvchain_get_entry_at(tvchain, index); - - if (entry) - return gmyth_tvchain_entry_to_program(tvchain, entry); - - return NULL; -} - -/** Gets a LiveTVChainEntry associated to the tvchain by its index. - * - * @param tvchain The GMythTVChain instance. - * @param index The tvchain entry index - * @return The LiveTVchainEntry structure. - */ -struct LiveTVChainEntry * -gmyth_tvchain_get_entry_at(GMythTVChain * tvchain, gint index) -{ - struct LiveTVChainEntry *chain_entry = NULL; - - g_return_val_if_fail(tvchain != NULL - && tvchain->tvchain_list != NULL, NULL); - - g_mutex_lock(tvchain->mutex); - - gint size = g_list_length(tvchain->tvchain_list); - gint new_index = (index < 0 - || index >= size) ? size - 1 : index; - - if (new_index >= 0) - chain_entry = - (struct LiveTVChainEntry *) g_list_nth_data(tvchain-> - tvchain_list, - new_index); - - g_mutex_unlock(tvchain->mutex); - - if (chain_entry != NULL) { - gmyth_debug("[%s] Got TV Chain entry at %d.\n", __FUNCTION__, - new_index); - - } else { - gmyth_debug("[%s] failed to get entry at index %d", __FUNCTION__, - index); - } - - return chain_entry; -} - -/** - * Gets the program info from backend database associated to the tv chain entry. - * - * @param tvchain The GMythTVChain instance. - * @param entry the LiveTVChainEntry to be converted. - * - * @return The program info. - */ -GMythProgramInfo * -gmyth_tvchain_entry_to_program(GMythTVChain * tvchain, - struct LiveTVChainEntry * entry) -{ - GMythProgramInfo *proginfo = NULL; - - g_return_val_if_fail(tvchain != NULL, NULL); - - if (!entry || !tvchain) { - gmyth_debug - ("gmyth_tvchain_entry_to_program() received NULL argument"); - return NULL; - } - - GMythScheduler *scheduler = gmyth_scheduler_new(); - - gmyth_scheduler_connect(scheduler, tvchain->backend_info); - proginfo = gmyth_scheduler_get_recorded(scheduler, - entry->chanid, - entry->starttime); - gmyth_scheduler_disconnect(scheduler); - - if (proginfo) { - proginfo->pathname = - g_string_prepend(proginfo->pathname, entry->hostprefix->str); - } else { - gmyth_debug - ("tvchain_entry_to_program( chan id = %s, starttime = %ld) failed!", - entry->chanid->str, entry->starttime->tv_sec); - } - - return proginfo; -} - -static void -free_tvchain_entry(gpointer data, gpointer user_data) -{ - struct LiveTVChainEntry *entry; - - g_return_if_fail(data != NULL); - - entry = (struct LiveTVChainEntry *) data; - - if (entry->chanid != NULL) { - g_string_free(entry->chanid, TRUE); - } - - if (entry->starttime != NULL) { - g_free(entry->starttime); - } - - if (entry->endtime != NULL) { - g_free(entry->endtime); - } - - if (entry->hostprefix) { - g_string_free(entry->hostprefix, TRUE); - } - - if (entry->cardtype) { - g_string_free(entry->cardtype, TRUE); - } - - if (entry->channum) { - g_string_free(entry->channum, TRUE); - } - - if (entry->inputname) { - g_string_free(entry->inputname, TRUE); - } - - g_free(entry); -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_tvchain.h --- a/gmyth/src/gmyth_tvchain.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_tvchain.h - * - * @brief

This component contains functions for creating and accessing - * the tvchain functions for live tv playback. - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Hallyson Luiz de Morais Melo - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef LIVETVCHAIN_H_ -#define LIVETVCHAIN_H_ - -#include -#include - -#include "gmyth_common.h" -#include "gmyth_backendinfo.h" - -G_BEGIN_DECLS -#define GMYTH_TVCHAIN_TYPE (gmyth_tvchain_get_type ()) -#define GMYTH_TVCHAIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TVCHAIN_TYPE, GMythTVChain)) -#define GMYTH_TVCHAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVCHAIN_TYPE, GMythTVChainClass)) -#define IS_GMYTH_TVCHAIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_TVCHAIN_TYPE)) -#define IS_GMYTH_TVCHAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVCHAIN_TYPE)) -#define GMYTH_TVCHAIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_TVCHAIN_TYPE, GMythTVChainClass)) -typedef struct _GMythTVChain GMythTVChain; -typedef struct _GMythTVChainClass GMythTVChainClass; - - -struct LiveTVChainEntry { - GString *chanid; - - GTimeVal *starttime; - GTimeVal *endtime; - - gboolean discontinuity; // if true, can't play smooth from - // last entry - GString *hostprefix; - GString *cardtype; - GString *channum; - GString *inputname; -}; - - -struct _GMythTVChainClass { - GObjectClass parent_class; - - /* - * callbacks - */ - /* - * no one for now - */ -}; - -struct _GMythTVChain { - GObject parent; - - GString *tvchain_id; - GList *tvchain_list; - - GTimeVal *cur_startts; - GString *cur_chanid; - gint cur_pos; - - GMythBackendInfo *backend_info; - - GMutex *mutex; -}; - -GType gmyth_tvchain_get_type(void); - -GMythTVChain *gmyth_tvchain_new(); - -gboolean gmyth_tvchain_initialize(GMythTVChain * tvchain, - GMythBackendInfo * backend_info); -gboolean gmyth_tvchain_reload_all(GMythTVChain * tvchain); -GString *gmyth_tvchain_get_id(GMythTVChain * tvchain); -gint gmyth_tvchain_program_is_at(GMythTVChain * tvchain, - GString * chanid, - GTimeVal * startts); - -struct LiveTVChainEntry *gmyth_tvchain_get_entry_at(GMythTVChain * tvchain, - gint index); - -GMythProgramInfo *gmyth_tvchain_entry_to_program(GMythTVChain * tvchain, struct LiveTVChainEntry - *entry); -GMythProgramInfo *gmyth_tvchain_get_program_at(GMythTVChain * tvchain, - gint index); - -GList *gmyth_tvchain_get_program_info_from_channel(GMythTVChain * - tvchain, - const gchar * - channel); - -GList *gmyth_tvchain_get_program_info_list(GMythTVChain * - tvchain); - -G_END_DECLS -#endif /* LIVETVCHAIN_H_ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_uri.c --- a/gmyth/src/gmyth_uri.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,604 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_uri.c - * - * @brief

GMythURI utils - * - Extracts and parses a URI char string, in according with the RFC 2396 - * [http://www.ietf.org/rfc/rfc2396.txt] - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Rosfran Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gmyth_uri.h" -#include "gmyth_socket.h" - -#include -#include -#include - -#include "gmyth_debug.h" - -/**************************************** -* Define -****************************************/ - -#define GMYTH_URI_KNKOWN_PORT (-1) -#define GMYTH_URI_DEFAULT_HTTP_PORT 80 -#define GMYTH_URI_DEFAULT_FTP_PORT 21 -#define GMYTH_URI_DEFAULT_MYTH_PORT 6543 -#define GMYTH_URI_DEFAULT_PATH "/" -#define GMYTH_URI_MAXLEN 256 - -#define GMYTH_URI_PROTOCOL_DELIM "://" -#define GMYTH_URI_USER_DELIM "@" -#define GMYTH_URI_COLON_DELIM ":" -#define GMYTH_URI_SLASH_DELIM "/" -#define GMYTH_URI_SBLACET_DELIM "[" -#define GMYTH_URI_EBLACET_DELIM "]" -#define GMYTH_URI_SHARP_DELIM "#" -#define GMYTH_URI_QUESTION_DELIM "?" -#define GMYTH_URI_E_DELIM "&" -#define GMYTH_URI_ESCAPING_CHAR "%" - -#define GMYTH_URI_PROTOCOL_MYTH "myth" -#define GMYTH_URI_PROTOCOL_HTTP "http" -#define GMYTH_URI_PROTOCOL_FTP "ftp" - - -static void gmyth_uri_class_init(GMythURIClass * klass); -static void gmyth_uri_init(GMythURI * object); - -static void gmyth_uri_dispose(GObject * object); -static void gmyth_uri_finalize(GObject * object); - -static void gmyth_uri_parser_setup_and_new(GMythURI * uri, - const gchar * value); -static gchar *gmyth_uri_print_field(const GString * field); - -G_DEFINE_TYPE(GMythURI, gmyth_uri, G_TYPE_OBJECT) - static void gmyth_uri_class_init(GMythURIClass * klass) -{ - GObjectClass *gobject_class; - - gobject_class = (GObjectClass *) klass; - - gobject_class->dispose = gmyth_uri_dispose; - gobject_class->finalize = gmyth_uri_finalize; -} - -static void -gmyth_uri_init(GMythURI * gmyth_uri) -{ -} - -static void -gmyth_uri_dispose(GObject * object) -{ - GMythURI *gmyth_uri = GMYTH_URI(object); - - if (gmyth_uri->host != NULL) { - g_string_free(gmyth_uri->host, TRUE); - gmyth_uri->host = NULL; - } - - if (gmyth_uri->protocol != NULL) { - g_string_free(gmyth_uri->protocol, TRUE); - gmyth_uri->protocol = NULL; - } - - if (gmyth_uri->path != NULL) { - g_string_free(gmyth_uri->path, TRUE); - gmyth_uri->path = NULL; - } - - if (gmyth_uri->fragment != NULL) { - g_string_free(gmyth_uri->fragment, TRUE); - gmyth_uri->fragment = NULL; - } - - if (gmyth_uri->user != NULL) { - g_string_free(gmyth_uri->user, TRUE); - gmyth_uri->user = NULL; - } - - if (gmyth_uri->password != NULL) { - g_string_free(gmyth_uri->password, TRUE); - gmyth_uri->password = NULL; - } - - if (gmyth_uri->query != NULL) { - g_string_free(gmyth_uri->query, TRUE); - gmyth_uri->query = NULL; - } - - if (gmyth_uri->uri != NULL) { - g_string_free(gmyth_uri->uri, TRUE); - gmyth_uri->uri = NULL; - } - - - G_OBJECT_CLASS(gmyth_uri_parent_class)->dispose(object); -} - -static void -gmyth_uri_finalize(GObject * object) -{ - // GMythURI *gmyth_uri = GMYTH_URI(object); - - g_signal_handlers_destroy(object); - - G_OBJECT_CLASS(gmyth_uri_parent_class)->finalize(object); -} - -/** - * Creates a new instance of GMythURI. - * - * @return a new instance of GMythURI. - */ -GMythURI * -gmyth_uri_new(void) -{ - GMythURI *gmyth_uri = - GMYTH_URI(g_object_new(GMYTH_URI_TYPE, NULL)); - - return gmyth_uri; -} - -/** - * Creates a new instance of GMythURI. - * - * @param uri_str The URI string representing this URI instance. - * - * @return a new instance of GMythURI. - */ -GMythURI * -gmyth_uri_new_with_value(const gchar * uri_str) -{ - GMythURI *gmyth_uri = - GMYTH_URI(g_object_new(GMYTH_URI_TYPE, NULL)); - - gmyth_uri_parser_setup_and_new(gmyth_uri, uri_str); - - return gmyth_uri; -} - -/** - * Gets the starting offset of a substring inside a given string. - * - * @param haystack The given string to be searched for patterns. - * @param needle The substring that should be matched over the haystack. - * - * @return The starting offset to the given substring, or -1 if the - * haystack function parameter doesn't contains the needle string argument. - */ -static gint -gmyth_strstr(const gchar * haystack, const gchar * needle) -{ - - gchar *strPos; - - if (haystack == NULL || needle == NULL) - return -1; - strPos = strstr(haystack, needle); - if (strPos == NULL) - return -1; - - return (strPos - haystack); - -} - -/** - * Checks if a URI is absolute. - * - * @param uri The GMythURI instance. - * - * @return true, if the URI is absolute. - */ -static gboolean -gmyth_uri_isabsolute(const GMythURI * uri) -{ - gboolean ret = FALSE; - - g_return_val_if_fail(uri != NULL && uri->uri != NULL - && uri->protocol != NULL, FALSE); - - if (gmyth_strstr(uri->uri->str, GMYTH_URI_PROTOCOL_DELIM) == 0 - || strlen(uri->protocol->str) > 0) - ret = TRUE; - - return ret; -} - -/** - * Searches for the first reverse character occurrence, from a given - * list of characters, inside a given string. - * - * @param str The given string to be searched for characters occurrence. - * @param chars The characters list. If this string returns 4 on strlen, there are - * four possible characters to be matched. - * @param nchars The number of characters to be matched, which has at most - * strlen(chars). - * - * @return The starting offset to the first character occurrence, - * or -1 if the no character of the list could be found. - */ -static gint -gmyth_strrchr(const gchar * str, const gchar * chars, const gint nchars) -{ - - gint strLen; - gint i, - j; - - if (str == NULL || chars == NULL) - return -1; - - strLen = strlen(str); - for (i = (strLen - 1); 0 <= i; i--) { - for (j = 0; j < nchars; j++) { - if (str[i] == chars[j]) - return i; - } - } - - return -1; - -} - -static gchar * -gmyth_uri_print_field(const GString * field) -{ - if (field != NULL && field->str != NULL && strlen(field->str) > 0) - return field->str; - else - return ""; -} - -static gint -gmyth_uri_get_default_port (GMythURI * uri) -{ - const gchar *protocol = gmyth_uri_get_protocol(uri); - - if (strcmp(protocol, GMYTH_URI_PROTOCOL_HTTP) == 0) - return GMYTH_URI_DEFAULT_HTTP_PORT; - if (strcmp(protocol, GMYTH_URI_PROTOCOL_FTP) == 0) - return GMYTH_URI_DEFAULT_FTP_PORT; - if (strcmp(protocol, GMYTH_URI_PROTOCOL_MYTH) == 0) - return GMYTH_URI_DEFAULT_MYTH_PORT; - - return GMYTH_URI_KNKOWN_PORT; -} - -/** - * Parses a URI string into a GMythURI instance. - * - * @param uri The GMythURI instance. - * @param value The URI string to be parsed. - * - */ -static void -gmyth_uri_parser_setup_and_new(GMythURI * uri, const gchar * value) -{ - - gint uriLen; - gint currIdx; - gint protoIdx; - gint atIdx; - gint colonIdx; - gint shashIdx; - gint eIdx; - gchar *host; - gint eblacketIdx; - gint hostLen; - gint sharpIdx; - - /* - * gint questionIdx; gint queryLen; - */ - - uriLen = strlen(value); - uri->uri = g_string_new(value); - - currIdx = 0; - - /*** Protocol ****/ - protoIdx = gmyth_strstr(value, GMYTH_URI_PROTOCOL_DELIM); - if (0 < protoIdx) { - uri->protocol = g_string_new_len(value, protoIdx); - currIdx += protoIdx + strlen(GMYTH_URI_PROTOCOL_DELIM); - } - - /*** User (Password) ****/ - atIdx = gmyth_strstr(value + currIdx, GMYTH_URI_USER_DELIM); - if (0 < atIdx) { - colonIdx = gmyth_strstr(value + currIdx, GMYTH_URI_COLON_DELIM); - - if (0 < colonIdx && colonIdx < atIdx) { - uri->user = g_string_new_len(value + currIdx, colonIdx); - uri->password = - g_string_new_len(value + currIdx + colonIdx + 1, - atIdx - (colonIdx + 1)); - } else - uri->user = g_string_new_len(value + currIdx, atIdx - currIdx); - currIdx += atIdx + 1; - } - - /*** Host (Port) ****/ - shashIdx = gmyth_strstr(value + currIdx, GMYTH_URI_SLASH_DELIM); - if (0 < shashIdx) - uri->host = g_string_new_len(value + currIdx, shashIdx); - else if (gmyth_uri_isabsolute(uri) == TRUE) - uri->host = - g_string_new_len(value + currIdx, strlen(value) - currIdx); - - host = gmyth_uri_get_host(uri); - colonIdx = gmyth_strrchr(host, GMYTH_URI_COLON_DELIM, 1); - eblacketIdx = gmyth_strrchr(host, GMYTH_URI_EBLACET_DELIM, 1); - if ((0 < colonIdx) && (eblacketIdx < colonIdx)) { - GString *portStr = NULL; - GString *hostStr = g_string_new(host != NULL ? host : ""); - - hostLen = hostStr->len; - /**** host ****/ - uri->host = g_string_erase(uri->host, 0, hostLen); - uri->host = - g_string_insert_len(uri->host, 0, hostStr->str, colonIdx); - if (0 < hostLen) { - if (host[0] == '[' && host[hostLen - 1] == ']') - uri->host = - g_string_new_len(hostStr->str + 1, colonIdx - 2); - } - - /**** port ****/ - portStr = g_string_new_len(hostStr->str + colonIdx + 1, - hostLen - colonIdx - 1); - uri->port = (gint) g_ascii_strtoull(portStr->str, NULL, 10); - g_string_free(portStr, TRUE); - g_string_free(hostStr, TRUE); - } else { - uri->port = gmyth_uri_get_default_port (uri); - } - - if (shashIdx > 0) - currIdx += shashIdx; - - /* - * Handle relative URL - */ - if (gmyth_uri_isabsolute(uri) == FALSE) { - - if (shashIdx != 0) { - /* - * Add slash delimiter at the beginning of the URL, if it - * doesn't exist - */ - uri->path = g_string_new(GMYTH_URI_SLASH_DELIM); - } - uri->path = g_string_append(uri->path, value); - - } else { - /* - * First set path simply to the rest of URI - */ - uri->path = g_string_new_len(value + currIdx, uriLen - currIdx); - } - - // gmyth_debug( "uri value: %s", value ); - uri->query = - g_string_new(g_strstr_len - (value, strlen(value), GMYTH_URI_QUESTION_DELIM)); - - eIdx = gmyth_strstr(value + currIdx, GMYTH_URI_QUESTION_DELIM); - - if (0 < eIdx) { - uri->query = - g_string_new(g_strstr_len - (value, strlen(value), GMYTH_URI_QUESTION_DELIM)); - gmyth_debug("query = %s", uri->query->str); - } - - /**** Path (Query/Fragment) ****/ - sharpIdx = gmyth_strstr(value + currIdx, GMYTH_URI_E_DELIM); - if (0 < sharpIdx) { - uri->path = - g_string_append_len(uri->path, value + currIdx, sharpIdx); - uri->fragment = - g_string_new_len(value + currIdx + sharpIdx + 1, - uriLen - (currIdx + sharpIdx + 1)); - } - - gmyth_debug - ("[%s] GMythURI: host = %s, port = %d, path = %s, query = %s, fragment = %s, " - "user = %s, password = %s.\n", __FUNCTION__, - gmyth_uri_print_field(uri->host), uri->port, - gmyth_uri_print_field(uri->path), - gmyth_uri_print_field(uri->query), - gmyth_uri_print_field(uri->fragment), - gmyth_uri_print_field(uri->user), - gmyth_uri_print_field(uri->password)); - -} - -/** - * Compares 2 URI instances, and checks them for equality. - * - * @param uri The first GMythURI instance for comparison. - * @param uri The second GMythURI instance for comparison. - * - * @return true, if these two URI instances are equals. - */ -gboolean -gmyth_uri_is_equals(GMythURI * uri1, GMythURI * uri2) -{ - return (g_ascii_strcasecmp - (gmyth_uri_get_host(uri1), gmyth_uri_get_host(uri2)) == 0 - && gmyth_uri_get_port(uri1) == gmyth_uri_get_port(uri2)); -} - -/** - * Checks if the URI instance represents a LiveTV recording. - * - * @param uri The GMythURI instance. - * - * @return true, if the URI points to LiveTV content. - */ -gboolean -gmyth_uri_is_livetv(GMythURI * uri) -{ - gboolean ret = TRUE; - - g_return_val_if_fail(uri != NULL, FALSE); - g_return_val_if_fail(uri->uri != NULL, FALSE); - g_return_val_if_fail(uri->uri->str != NULL, FALSE); - - if ((strstr(uri->uri->str, "channel=") == NULL) && - (strstr(uri->uri->str, "livetv") == NULL)) - ret = FALSE; - - if (ret) - gmyth_debug("This URI is a LiveTV recording..."); - else - gmyth_debug("This URI is a stored remote recording."); - - return ret; - -} - -/** - * Gets the channel name fro a URI instance. - * - * @param uri The GMythURI instance. - * - * @return The channel name, got from the substring "?channel=[channel_name]" - * of the URI string. - */ -gchar * -gmyth_uri_get_channel_name(GMythURI * uri) -{ - gchar *channel = NULL; - - g_return_val_if_fail(uri != NULL && uri->uri != NULL - && uri->uri->str != NULL, FALSE); - - gchar *channel_query = g_strstr_len(gmyth_uri_get_query(uri), - strlen(gmyth_uri_get_query - (uri)), - "channel"); - - if (channel_query != NULL) { - gchar **chan_key_value = - g_strsplit(gmyth_uri_get_query(uri), "=", 2); - - /* - * gmyth_debug( "Channel tuple is [ %s, %s ]", chan_key_value[0], - * chan_key_value[1] ); - */ - - if (chan_key_value[1] != NULL && strlen(chan_key_value[1]) > 0) { - channel = g_strdup(chan_key_value[1]); - } - - if (chan_key_value != NULL) - g_strfreev(chan_key_value); - } - - gmyth_debug("Got channel decimal value from the URI: %s", channel); - - return channel; - -} - -/** - * Gets the channel number from a URI instance. - * - * @param uri The GMythURI instance. - * - * @return The channel number, got from the substring "?channel=[channel_number]" - * of the URI string, or -1 it if couldn't be converted. - */ -gint -gmyth_uri_get_channel_num(GMythURI * uri) -{ - gchar *channel_name = gmyth_uri_get_channel_name(uri); - - if (channel_name != NULL) { - return g_ascii_strtoull(channel_name, NULL, 10); - } - - return -1; - -} - -/** - * Checks if the URI instance represents a reference to a local file. - * - * @param uri The GMythURI instance. - * - * @return true, if the URI points to a local file. - */ -gboolean -gmyth_uri_is_local_file(const GMythURI * uri) -{ - gboolean ret = FALSE; - gint len = -1; - - GString *hostname = gmyth_socket_get_local_hostname(); - - g_return_val_if_fail(uri != NULL, FALSE); - - len = strlen(gmyth_uri_get_host(uri)); - - // gmyth_debug("URI: host = %s, hostname = %s.", uri->host->str, - // hostname != NULL ? hostname->str : "[no hostname]"); - - ret = (NULL != hostname && (g_ascii_strncasecmp(uri->host->str, (hostname)->str, len) == 0) /* || - * ( - * g_ascii_strncasecmp( - * gmyth_uri_get_host(uri), - * gmyth_socket_get_primary_addr(), - * len - * ) - * == - * 0 - * ) - */ - ); - - if (ret) - gmyth_debug("This URI is a local file..."); - else - gmyth_debug("This URI is NOT a local file..."); - - return ret; - -} - -char * -gmyth_uri_to_string(const GMythURI * uri) -{ - g_return_val_if_fail(uri != NULL, NULL); - g_return_val_if_fail(uri->uri != NULL, NULL); - - return g_strdup(uri->uri->str); -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_uri.h --- a/gmyth/src/gmyth_uri.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_uri.h - * - * @brief

GMythURI utils - * - Extracts and parses a URI char string, in according with the RFC 2396 - * [http://www.ietf.org/rfc/rfc2396.txt] - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Rosfran Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _GMYTH_URI_H_ -#define _GMYTH_URI_H_ - -#include -#include - -#include -#include -#include - -G_BEGIN_DECLS -#define GMYTH_URI_TYPE (gmyth_uri_get_type ()) -#define GMYTH_URI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_URI_TYPE, GMythURI)) -#define GMYTH_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_URI_TYPE, GMythURIClass)) -#define IS_GMYTH_URI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_URI_TYPE)) -#define IS_GMYTH_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_URI_TYPE)) -#define GMYTH_URI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_URI_TYPE, GMythURIClass)) -typedef struct _GMythURI GMythURI; -typedef struct _GMythURIClass GMythURIClass; - - - /**************************************** - * Data Type - ****************************************/ - -struct _GMythURIClass { - GObjectClass parent_class; - - /* - * callbacks - */ - /* - * no one for now - */ -}; - -struct _GMythURI { - - GObject parent; - - GString *uri; - GString *host; - gint port; - GString *protocol; - GString *path; - GString *fragment; - GString *user; - GString *password; - GString *query; - -}; - -GType gmyth_uri_get_type(void); -GMythURI *gmyth_uri_new(void); -GMythURI *gmyth_uri_new_with_value(const gchar * value); -gboolean gmyth_uri_is_equals(GMythURI * uri1, GMythURI * uri2); -gboolean gmyth_uri_is_livetv(GMythURI * uri); -gint gmyth_uri_get_channel_num(GMythURI * uri); -gchar *gmyth_uri_get_channel_name(GMythURI * uri); -char *gmyth_uri_to_string(const GMythURI * uri); -gboolean gmyth_uri_is_local_file(const GMythURI * uri); - -#define gmyth_uri_get_host(urip) ( urip->host != NULL ? urip->host->str : "" ) -#define gmyth_uri_get_port(urip) ( urip->port ) -#define gmyth_uri_get_protocol(urip) ( urip->protocol != NULL ? urip->protocol->str : "" ) -#define gmyth_uri_get_path(urip) ( urip->path != NULL ? urip->path->str : "" ) -#define gmyth_uri_get_user(urip) ( urip->user != NULL ? urip->user->str : "" ) -#define gmyth_uri_get_password(urip) ( urip->password != NULL ? urip->password->str : "" ) -#define gmyth_uri_get_fragment(urip) ( urip->fragment != NULL ? urip->fragment->str : "" ) -#define gmyth_uri_get_query(urip) ( urip->query != NULL ? urip->query->str : "" ) - -G_END_DECLS -#endif /* _GMYTH_URI_H_ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_util.c --- a/gmyth/src/gmyth_util.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,957 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_util.c - * - * @brief

This component provides utility functions - * (dealing with dates, time, string formatting, etc.). - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Hallyson Luiz de Morais Melo - * @author Rosfran Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _XOPEN_SOURCE -#define _XOPEN_SOURCE_EXTENDED -#define __USE_MISC - -#include -#include -#include -#include -#include - -#include "gmyth_socket.h" -#include "gmyth_recorder.h" -#include "gmyth_common.h" -#include "gmyth_debug.h" - -#include "gmyth_util.h" - -#if !GLIB_CHECK_VERSION (2, 10, 0) -gchar *g_time_val_to_iso8601(GTimeVal * time_); -gboolean g_time_val_from_iso8601(const gchar * iso_date, - GTimeVal * time_); -void g_date_set_time_val(GDate * date, GTimeVal * timeval); - -#endif - -/** Converts a time_t struct in a GString at ISO standard format - * (e.g. 2006-07-20T09:56:41). - * - * The returned GString memory should be deallocated from - * the calling function. - * - * @param time_value the time value to be converted - * @return GString* the converted isoformat string - */ -GString * -gmyth_util_time_to_isoformat(time_t time_value) -{ - struct tm tm_time; - GString *result; - - if (localtime_r(&time_value, &tm_time) == NULL) { - gmyth_debug("gmyth_util_time_to_isoformat convertion error!\n"); - return NULL; - } - - result = g_string_sized_new(20); - g_string_printf(result, "%04d-%02d-%02dT%02d:%02d:%02d", - tm_time.tm_year + 1900, tm_time.tm_mon + 1, - tm_time.tm_mday, tm_time.tm_hour, tm_time.tm_min, - tm_time.tm_sec); - - gmyth_debug("Result (ISO 8601) = %s", result->str); - - return result; -} - -/** Converts a time_t struct in a GString at ISO standard format - * (e.g. 2006-07-20T09:56:41). - * - * The returned GString memory should be deallocated from - * the calling function. - * - * @param time_value the GTimeValue to be converted - * @return GString* the converted isoformat string - */ -gchar * -gmyth_util_time_to_isoformat_from_time_val_fmt(const gchar * fmt_string, - const GTimeVal * time_val) -{ - gchar *result = NULL; - struct tm *tm_time = NULL; - time_t time; - - gint buffer_len = 0; - - g_return_val_if_fail(fmt_string != NULL, NULL); - - g_return_val_if_fail(time_val != NULL, NULL); - - time = time_val->tv_sec; // + (gint)( time_val->tv_usec / - // G_USEC_PER_SEC ); - - tm_time = g_malloc0(sizeof(struct tm)); - - if (NULL == localtime_r(&time, tm_time)) { - gmyth_debug("gmyth_util_time_to_isoformat convertion error!\n"); - } else { - /* - * we first check the return of strftime to allocate a buffer of - * the correct size - */ - buffer_len = strftime(NULL, SSIZE_MAX, fmt_string, tm_time); - if (buffer_len > 0) { - result = g_malloc0(buffer_len + 1); - if (result == NULL) { - gmyth_debug - ("gmyth_util_time_to_isoformat convertion error!\n"); - return NULL; - } - strftime(result, buffer_len + 1, fmt_string, tm_time); - gmyth_debug("Dateline (ISO result): %s", result); - } - } /* if */ - - gmyth_debug("Result (strftime) = %s", result); - - // strptime( result, "%Y-%m-%dT%H:%M:%SZ", tm_time ); - - // strftime( result, strlen(result), fmt_string, tm_time ); - - g_free(tm_time); - - gmyth_debug("Result (ISO 8601) = %s", result); - - return result; -} - -/** Converts a time_t struct in a GString at ISO standard format - * (e.g. 2006-07-20 09:56:41). - * - * The returned GString memory should be deallocated from - * the calling function. - * - * @param time_value the GTimeValue to be converted - * @return GString* the converted isoformat string - */ -gchar * -gmyth_util_time_to_isoformat_from_time_val(const GTimeVal * time) -{ - gchar *result = - gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%d %H:%M:%S", - time); - - // result[10] = ' '; - // result[ strlen(result) - 1] = '\0'; - - return result; -} - -/** Converts a time_t struct in a GString at ISO standard format 2 - * (e.g. 2006-07-20T09:56:41). - * - * The returned GString memory should be deallocated from - * the calling function. - * - * @param time_value the GTimeValue to be converted - * @return GString* the converted isoformat string - */ -gchar * -gmyth_util_time_to_mythformat_from_time_val(const GTimeVal * time) -{ - gchar *result = - gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%dT%H:%M:%S", - time); - - return result; -} - -/** Converts a time_t struct in a GString at ISO standard format - * (e.g. 2006-07-20T09:56:41). - * - * The returned GString memory should be deallocated from - * the calling function. - * - * @param time_value the GTimeValue to be converted - * @return GString* the converted isoformat string - */ -gchar * -gmyth_util_time_to_string_only_date(const GTimeVal * time) -{ - gchar *result = - gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%d", time); - // result[10] = ' '; - // result[ strlen(result) - 1] = '\0'; - return result; -} - -/** Converts a time_t struct in a GString at ISO standard format - * (e.g. 2006-07-20T09:56:41). - * - * The returned GString memory should be deallocated from - * the calling function. - * - * @param time_value the GTimeValue to be converted - * @return GString* the converted isoformat string - */ -gchar * -gmyth_util_time_to_string_only_time(const GTimeVal * time) -{ - gchar *result = - gmyth_util_time_to_isoformat_from_time_val_fmt("%H:%M:%S", time); - // result[10] = ' '; - // result[ strlen(result) - 1] = '\0'; - return result; -} - -/** Converts a time_t struct in a GString to the following - * format (e.g. 2006-07-20 09:56:41). - * - * The returned GString memory should be deallocated from - * the calling function. - * - * @param time_value the time value to be converted - * @return GString* the converted string - */ -GString * -gmyth_util_time_to_string(time_t time_value) -{ - GString *result = gmyth_util_time_to_isoformat(time_value); - - result->str[10] = ' '; - result->str[strlen(result->str) - 1] = '\0'; - - return result; -} - -/** Converts a time_t struct in a GString to the following - * format (e.g. 2006-07-20 09:56:41). - * - * The returned GString memory should be deallocated from - * the calling function. - * - * @param time_value the time value to be converted - * @return GString* the converted string - */ -gchar * -gmyth_util_time_to_string_from_time_val(const GTimeVal * time_val) -{ - gchar *result = - gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%d %H:%M:%S", - time_val); - - // result[10] = ' '; - - return result; -} - -/** Converts a GString in the following format - * (e.g. 2006-07-20 09:56:41) to a time_t struct. - * - * @param time_str the string to be converted - * @return time_t the time converted value - */ -time_t -gmyth_util_string_to_time(GString * time_str) -{ - gint year, - month, - day, - hour, - min, - sec; - - gmyth_debug("[%s] time_str = %s. [%s]", __FUNCTION__, - time_str != - NULL ? time_str->str : "[time string is NULL!]", - time_str->str); - - if (sscanf(time_str->str, "%04d-%02d-%02d %02d:%02d:%02d", - &year, &month, &day, &hour, &min, &sec) < 3) { - gmyth_debug("GMythUtil: isoformat_to_time converter error!\n"); - return 0; - } - - struct tm *tm_time = g_malloc0(sizeof(struct tm)); - - tm_time->tm_year = year - 1900; - tm_time->tm_mon = month - 1; - tm_time->tm_mday = day; - tm_time->tm_hour = hour; - tm_time->tm_min = min; - tm_time->tm_sec = sec; - - return mktime(tm_time); -} - -/** Converts a GString in the following format - * (e.g. 2006-07-20 09:56:41) to a time_t struct. - * - * @param time_str the string to be converted - * @return time_t the time converted value - */ -struct tm * -gmyth_util_time_val_to_date(const GTimeVal * time) -{ - struct tm *date = g_malloc0(sizeof(struct tm)); - time_t time_micros = time->tv_sec; // + (gint)( time->tv_usec - // - // - // / G_USEC_PER_SEC ); - - if (NULL == date) { - gmyth_debug - ("GMythUtil: GDate *gmyth_util_time_val_to_date (GTimeVal* time) - converter error!\n"); - return NULL; - } - - if (NULL == localtime_r(&time_micros, date)) { - gmyth_debug("gmyth_util_time_to_isoformat convertion error!\n"); - return NULL; - } - - gmyth_debug("Converted from GTimeVal == %s to GDate", asctime(date)); - - return date; -} - -/** Converts a GString in the following format - * (e.g. 2006-07-20 09:56:41) to a time_t struct. - * - * @param time_str the string to be converted - * @return time_t the time converted value - */ -GTimeVal * -gmyth_util_string_to_time_val_fmt(const gchar * fmt_string, - const gchar * time_str) -{ - GTimeVal *time = g_new0(GTimeVal, 1); - struct tm *tm_time = NULL; - time_t time_micros; - gchar *result; - - gmyth_debug("[%s] time_str = %s. [%s]", time_str, time_str != NULL ? - time_str : "[time string is NULL!]", time_str); - - if (NULL == time_str) { - gmyth_debug("GMythUtil: isoformat_to_time converter error!\n"); - return NULL; - } - - tm_time = g_malloc0(sizeof(struct tm)); - - /* - * we first check the return of strftime to allocate a buffer of the - * correct size - */ - result = strptime(time_str, "%Y-%m-%dT%H:%M:%S", tm_time); - if (NULL == result) { - /* - * we first check the return of strftime to allocate a buffer of - * the correct size - */ - result = strptime(time_str, "%Y-%m-%dT%H:%M:%SZ", tm_time); - if (NULL == result) { - /* - * we first check the return of strftime to allocate a buffer - * of the correct size - */ - result = strptime(time_str, "%Y-%m-%d %H:%M:%S", tm_time); - if (NULL == result) { - result = strptime(time_str, "%Y-%m-%dT%H:%M", tm_time); - if (NULL == result) { - gmyth_debug("Dateline (ISO result): %s", result); - g_free(tm_time); - return NULL; - // goto done; - } - } - } - } - - time_micros = mktime(tm_time); - - time->tv_sec = time_micros; // + (gint)( time_val->tv_usec / - // G_USEC_PER_SEC ); - - gmyth_debug("After mktime call... = %s", asctime(tm_time)); - - g_free(tm_time); - - return time; -} - -/** Converts a GString in the following format - * (e.g. 2006-07-20 09:56:41) to a time_t struct. - * - * @param time_str the string to be converted - * @return time_t the time converted value - */ -GTimeVal * -gmyth_util_string_to_time_val(const gchar * time_str) -{ - GTimeVal *time = - gmyth_util_string_to_time_val_fmt("%Y-%m-%d %H:%M:%S", time_str); - - return time; -} - -/** - * Checks if the given remote file exists. - * - * @param backend_info The GMythBackendInfo instance. - * @param filename The file name of the remote file. - * - * @return true, if the remote file exists. - */ -gboolean -gmyth_util_file_exists(GMythBackendInfo * backend_info, - const gchar * filename) -{ - GMythSocket *socket; - gboolean res = FALSE; - - gmyth_debug("Check if file %s exists", filename); - - g_return_val_if_fail(backend_info != NULL, FALSE); - g_return_val_if_fail(filename != NULL, FALSE); - - socket = gmyth_backend_info_get_connected_socket (backend_info); - if (socket != NULL) { - res = gmyth_util_file_exists_from_socket (socket, filename); - g_object_unref(socket); - } - return res; -} - -gboolean -gmyth_util_file_exists_from_socket (GMythSocket *sock, - const gchar *filename) -{ - gboolean res = FALSE; - gint length = 0; - GMythStringList *slist; - GMythProgramInfo *program = NULL; - - program = gmyth_program_info_new(); - program->pathname = g_string_new(filename); - - slist = gmyth_string_list_new(); - gmyth_string_list_append_char_array(slist, "QUERY_CHECKFILE"); - gmyth_program_info_to_string_list(program, slist); - - length = gmyth_socket_sendreceive_stringlist (sock, slist); - if (length > 0) - res = (gmyth_string_list_get_int(slist, 0) == 1); - - g_object_unref(program); - g_object_unref(slist); - - return res; -} - -gboolean -gmyth_util_get_backend_details (GMythSocket *sock, GMythBackendDetails **details) -{ - gboolean res = FALSE; - gint length = 0; - GMythStringList *slist; - - slist = gmyth_string_list_new(); - gmyth_string_list_append_char_array(slist, "QUERY_FREE_SPACE"); - - length = gmyth_socket_sendreceive_stringlist (sock, slist); - if (length >= 8) { - *details = g_new0 (GMythBackendDetails, 1); - (*details)->total_space = gmyth_string_list_get_uint64 (slist, 4) * 1024; - (*details)->used_space = gmyth_string_list_get_uint64 (slist, 6) * 1024; - res = TRUE; - } - - g_object_unref(slist); - - return res; -} - -void -gmyth_util_backend_details_free (GMythBackendDetails *details) -{ - g_free (details); -} - - -/** - * Checks if the given remote file exists, and gets its remote directory. - * - * @param backend_info The GMythBackendInfo instance. - * @param filename The file name of the remote file. - * @param current_dir String pointer to the directory where the remote file is stored. - * - * @return true, if the remote file exists. - */ -gboolean -gmyth_util_file_exists_and_get_remote_dir(GMythBackendInfo * backend_info, - const gchar * filename, - gchar ** current_dir) -{ - GMythSocket *socket; - gboolean res; - - *current_dir = NULL; - - socket = gmyth_socket_new(); - res = gmyth_socket_connect_to_backend(socket, backend_info->hostname, - backend_info->port, TRUE); - - if (res == TRUE) { - GMythStringList *slist; - GMythProgramInfo *program = NULL; - - program = gmyth_program_info_new(); - program->pathname = g_string_new(filename); - - slist = gmyth_string_list_new(); - gmyth_string_list_append_char_array(slist, "QUERY_CHECKFILE"); - - gmyth_program_info_to_string_list(program, slist); - - gmyth_socket_sendreceive_stringlist(socket, slist); - - res = (gmyth_string_list_get_int(slist, 0) == 1); - - if ((gmyth_string_list_length(slist) > 1) && - gmyth_string_list_get_char_array(slist, 1) != NULL) - *current_dir = - g_strdup(gmyth_string_list_get_char_array(slist, 1)); - - if (*current_dir != NULL) - gmyth_debug("Current directory = %s.", (*current_dir != NULL) - ? *current_dir : "[directory not found]"); - - g_object_unref(program); - - g_object_unref(slist); - - gmyth_socket_close_connection(socket); - } - g_object_unref(socket); - return res; -} - -/** - * Creates a file name to a possible existing remote file, - * based on some fields of the LiveTV/recorded program info. - * - * @param chan_id The channel ID number. - * @param start_time The start time of the recording. - * - * @return The string representing the file name. - */ -gchar * -gmyth_util_create_filename(const gint chan_id, const GTimeVal * start_time) -{ - gchar *basename = NULL; - - g_return_val_if_fail(start_time != NULL, NULL); - - gchar *isodate = - gmyth_util_time_to_isoformat_from_time_val_fmt("%Y%m%d%H%M%S", - start_time); - - basename = g_strdup_printf("%d_%s", chan_id, isodate); - - gmyth_debug("Basename (from chan_id and start_time): %s", basename); - - if (isodate) - g_free(isodate); - - return basename; -} - -/** - * Gets the channel list. - * - * @param backend_info The GMythBackendInfo instance. - * - * @return a pointer to a GList with all the channels. - */ -GList * -gmyth_util_get_channel_list(GMythBackendInfo * backend_info) -{ - GMythRecorder *recorder; - GList *channel_list = NULL; - gboolean res = FALSE; - - gmyth_debug("Gets channel list."); - - g_return_val_if_fail(backend_info != NULL, FALSE); - - recorder = - gmyth_recorder_new(1, - g_string_new(gmyth_backend_info_get_hostname - (backend_info)), - gmyth_backend_info_get_port(backend_info)); - res = gmyth_recorder_setup(recorder); - - if (res == TRUE) { - // GList* channel_list = gmyth_recorder_get_channel_list( recorder - // - // - // ); - gmyth_debug("Yeah, got channel list!!!"); - GList *ch = NULL; - GMythChannelInfo *channel_info = NULL; - - for (ch = gmyth_recorder_get_channel_list(recorder); ch != NULL;) { - channel_info = g_malloc0(sizeof(GMythChannelInfo)); - channel_info->channel_ID = 0; - channel_info->channel_num = - g_string_new(g_strdup((gchar *) ch->data)); - channel_info->channel_name = g_string_new(""); - gmyth_debug("Printing channel info... (%s)", - channel_info->channel_num->str); - channel_list = - g_list_append(channel_list, - g_memdup(channel_info, - sizeof(GMythChannelInfo))); - - ch = g_list_next(ch); - - if (channel_info != NULL) - g_free(channel_info); - } - - } /* if */ - else { - gmyth_debug("No, couldn't get the channel list!!!"); - } - - gmyth_debug("Got %d channels!!!", g_list_length(channel_list)); - - - g_object_unref(recorder); - - return channel_list; -} - -/** - * Gets all the recordings from remote encoder. - * - * @param backend_info The GMythBackendInfo instance. - * - * @return The program info's listage. - */ -GSList * -gmyth_util_get_all_recordings(GMythBackendInfo * backend_info) -{ - GSList *program_list = NULL; - GMythSocket *socket; - gboolean res; - - socket = gmyth_socket_new(); - res = gmyth_socket_connect_to_backend(socket, backend_info->hostname, - backend_info->port, TRUE); - - if (res == TRUE) { - GMythStringList *slist = gmyth_string_list_new(); - guint pos = 0; - - gmyth_string_list_append_char_array(slist, - "QUERY_RECORDINGS Play"); - - gmyth_socket_sendreceive_stringlist(socket, slist); - - if (slist != NULL && (gmyth_string_list_length(slist) > 0)) { - GMythProgramInfo *program = NULL; - - gmyth_debug("OK! Got the program list [size=%d].", - gmyth_string_list_length(slist)); - - do { - program = - gmyth_program_info_from_string_list_from_pos(slist, - pos); - - if (program != NULL) { - pos += 41; - - program_list = g_slist_append(program_list, program); - } else - break; - - } - while (gmyth_string_list_length(slist) > pos); - - } - /* - * if - */ - g_object_unref(slist); - - gmyth_socket_close_connection(socket); - } - g_object_unref(socket); - - return program_list; -} - -/** - * Checks if the given remote file exists, and gets its remote directory. - * - * @param backend_info The GMythBackendInfo instance. - * @param channel The channel name of the program info. - * - * @return The requested program info. - */ -GMythProgramInfo * -gmyth_util_get_recording_from_channel(GMythBackendInfo * backend_info, - const gchar * channel) -{ - GSList *program_list = NULL; - GMythProgramInfo *program = NULL; - - program_list = gmyth_util_get_all_recordings(backend_info); - - if (program_list != NULL && g_slist_length(program_list) > 0) { - GMythProgramInfo *program = NULL; - guint pos = 0; - - gmyth_debug("OK! Got the program list [size=%d].", - g_slist_length(program_list)); - - while (pos < g_slist_length(program_list)) { - program = - (GMythProgramInfo *) g_slist_nth_data(program_list, pos); - - if (program != NULL && program->channame != NULL && - g_ascii_strncasecmp(program->channame->str, channel, - strlen(channel)) == 0) { - break; - } - - ++pos; - - } /* while */ - - } - /* - * if - */ - return program; -} - -#if !GLIB_CHECK_VERSION (2, 10, 0) - -/* - * Hacked from glib 2.10 - */ - -static time_t -mktime_utc(struct tm *tm) -{ - time_t retval; - -#ifndef HAVE_TIMEGM - static const gint days_before[] = { - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 - }; -#endif - -#ifndef HAVE_TIMEGM - if (tm->tm_mon < 0 || tm->tm_mon > 11) - return (time_t) - 1; - - retval = (tm->tm_year - 70) * 365; - retval += (tm->tm_year - 68) / 4; - retval += days_before[tm->tm_mon] + tm->tm_mday - 1; - - if (tm->tm_year % 4 == 0 && tm->tm_mon < 2) - retval -= 1; - - retval = - ((((retval * 24) + tm->tm_hour) * 60) + tm->tm_min) * 60 + - tm->tm_sec; -#else - retval = timegm(tm); -#endif /* !HAVE_TIMEGM */ - - return retval; -} - -gboolean -g_time_val_from_iso8601(const gchar * iso_date, GTimeVal * time_) -{ - struct tm tm; - long val; - - g_return_val_if_fail(iso_date != NULL, FALSE); - g_return_val_if_fail(time_ != NULL, FALSE); - - val = strtoul(iso_date, (char **) &iso_date, 10); - if (*iso_date == '-') { - /* - * YYYY-MM-DD - */ - tm.tm_year = val - 1900; - iso_date++; - tm.tm_mon = strtoul(iso_date, (char **) &iso_date, 10) - 1; - - if (*iso_date++ != '-') - return FALSE; - - tm.tm_mday = strtoul(iso_date, (char **) &iso_date, 10); - } else { - /* - * YYYYMMDD - */ - tm.tm_mday = val % 100; - tm.tm_mon = (val % 10000) / 100 - 1; - tm.tm_year = val / 10000 - 1900; - } - - if (*iso_date++ != 'T') - return FALSE; - - val = strtoul(iso_date, (char **) &iso_date, 10); - if (*iso_date == ':') { - /* - * hh:mm:ss - */ - tm.tm_hour = val; - iso_date++; - tm.tm_min = strtoul(iso_date, (char **) &iso_date, 10); - - if (*iso_date++ != ':') - return FALSE; - - tm.tm_sec = strtoul(iso_date, (char **) &iso_date, 10); - } else { - /* - * hhmmss - */ - tm.tm_sec = val % 100; - tm.tm_min = (val % 10000) / 100; - tm.tm_hour = val / 10000; - } - - time_->tv_sec = mktime_utc(&tm); - time_->tv_usec = 1; - - if (*iso_date == '.') - time_->tv_usec = strtoul(iso_date + 1, (char **) &iso_date, 10); - - if (*iso_date == '+' || *iso_date == '-') { - gint sign = (*iso_date == '+') ? -1 : 1; - - val = 60 * strtoul(iso_date + 1, (char **) &iso_date, 10); - - if (*iso_date == ':') - val = 60 * val + strtoul(iso_date + 1, NULL, 10); - else - val = 60 * (val / 100) + (val % 100); - - time_->tv_sec += (time_t) (val * sign); - } - - return TRUE; -} - - -gchar * -g_time_val_to_iso8601(GTimeVal * time_) -{ - gchar *retval; - - g_return_val_if_fail(time_->tv_usec >= 0 - && time_->tv_usec < G_USEC_PER_SEC, NULL); - -#define ISO_8601_LEN 21 -#define ISO_8601_FORMAT "%Y-%m-%dT%H:%M:%SZ" - retval = g_new0(gchar, ISO_8601_LEN + 1); - - strftime(retval, ISO_8601_LEN, ISO_8601_FORMAT, - gmtime(&(time_->tv_sec))); - - return retval; -} - - -/* - * Hacked from glib 2.10 - */ - -void -g_date_set_time_t(GDate * date, time_t timet) -{ - struct tm tm; - - g_return_if_fail(date != NULL); - -#ifdef HAVE_LOCALTIME_R - localtime_r(&timet, &tm); -#else - { - struct tm *ptm = localtime(&timet); - - if (ptm == NULL) { - /* - * Happens at least in Microsoft's C library if you pass a - * negative time_t. Use 2000-01-01 as default date. - */ -#ifndef G_DISABLE_CHECKS - g_return_if_fail_warning(G_LOG_DOMAIN, "g_date_set_time", - "ptm != NULL"); -#endif - - tm.tm_mon = 0; - tm.tm_mday = 1; - tm.tm_year = 100; - } else - memcpy((void *) &tm, (void *) ptm, sizeof(struct tm)); - } -#endif - - date->julian = FALSE; - - date->month = tm.tm_mon + 1; - date->day = tm.tm_mday; - date->year = tm.tm_year + 1900; - - g_return_if_fail(g_date_valid_dmy(date->day, date->month, date->year)); - - date->dmy = TRUE; -} - - -void -g_date_set_time_val(GDate * date, GTimeVal * timeval) -{ - g_date_set_time_t(date, (time_t) timeval->tv_sec); -} - - - - -#endif diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_util.h --- a/gmyth/src/gmyth_util.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_util.h - * - * @brief

This component provides utility functions - * (dealing with dates, time, string formatting, etc.). - * - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia. - * @author Hallyson Luiz de Morais Melo - * @author Rosfran Borges - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GMYTH_UTIL_H_ -#define GMYTH_UTIL_H_ - -#include -#include - -#include "gmyth_stringlist.h" -#include "gmyth_backendinfo.h" -#include "gmyth_programinfo.h" - -G_BEGIN_DECLS - -typedef struct { - guint64 total_space; - guint64 used_space; -} GMythBackendDetails; - - -GString* gmyth_util_time_to_isoformat (time_t time_value); -GString* gmyth_util_time_to_string (time_t time_value); -time_t gmyth_util_string_to_time (GString *time_str); -gchar* gmyth_util_time_to_isoformat_from_time_val_fmt - (const gchar *fmt_string, - const GTimeVal *time_val); -GTimeVal* gmyth_util_string_to_time_val_fmt (const gchar *fmt_string, - const gchar *time_str); -GTimeVal* gmyth_util_string_to_time_val (const gchar *time_str); -gchar* gmyth_util_time_to_isoformat_from_time_val (const GTimeVal *time); -gchar* gmyth_util_time_to_mythformat_from_time_val (const GTimeVal *time); -gchar* gmyth_util_time_to_string_only_date (const GTimeVal *time); -gchar* gmyth_util_time_to_string_only_time (const GTimeVal *time); -gchar* gmyth_util_time_to_string_from_time_val (const GTimeVal *time_val); -struct tm* gmyth_util_time_val_to_date (const GTimeVal * time); - -gboolean gmyth_util_get_backend_details (GMythSocket *sock, GMythBackendDetails **details); -void gmyth_util_backend_details_free (GMythBackendDetails *details); - -gboolean gmyth_util_file_exists (GMythBackendInfo *backend_info, - const gchar * filename); -gboolean gmyth_util_file_exists_from_socket (GMythSocket *sock, - const gchar *filename); -gboolean gmyth_util_file_exists_and_get_remote_dir (GMythBackendInfo *backend_info, - const gchar *filename, - gchar **current_dir); -gchar* gmyth_util_create_filename (const gint chan_id, - const GTimeVal * start_time); -GList* gmyth_util_get_channel_list (GMythBackendInfo *backend_info); -GSList* gmyth_util_get_all_recordings (GMythBackendInfo *backend_info); -GMythProgramInfo* - gmyth_util_get_recording_from_channel (GMythBackendInfo *backend_info, - const gchar *channel); - -G_END_DECLS -#endif /* GMYTH_UTIL_H_ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_vlc.c --- a/gmyth/src/gmyth_vlc.c Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,290 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_vlc.c - * - * @brief

GMythVLC library provides functions that - * interact with a VLC server running telnet interface. - * - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. - * @author Artur Duque de Souza - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include "gmyth_vlc.h" -#include "gmyth_debug.h" -#include "gmyth_socket.h" - -/* - * static functions - */ -static int _socket_send(int socket, gchar * msg); -static int _socket_recv(int socket, gchar * buf); - -/** Primitive function to send a message through the socket - * - * @param socket - * @param msg the message itself - * @return 0 if success - */ -static int -_socket_send(int socket, gchar * msg) -{ - size_t size = strlen(msg) + 2; // (\n + \0) - gchar *final = (gchar *) g_malloc0(sizeof(gchar) * size); - - g_snprintf(final, size, "%s\n", msg); - - if (send(socket, final, strlen(final), 0) == -1) - perror("GMyth_VLC: send error"); - - g_free(final); - return 0; -} - - -/** Primitive function to receive a message through the socket - * - * @param socket - * @param buf Buffer to put the message - * @return 0 if success - */ -static int -_socket_recv(int socket, gchar * buf) -{ - int numbytes = 0; - - if ((numbytes = recv(socket, buf, BUFFER - 1, 0)) == -1) { - perror("GMyth_VLC: recv error"); - return -1; - } - - buf[numbytes - 1] = '\0'; - return numbytes; -} - - -/** Function that adds options to the output media - * - * @param vlc structure with options for vlc - * @param output the number of the output media - * @param kind the type of option we'll change - * @param the params for the option - * @return 0 if success - */ -int -gmyth_vlc_setup_output(GMythVlc * vlc, int output, gchar * kind, - gchar * opts) -{ - int ret; - - size_t size = strlen(opts) + 25; - gchar *msg = g_malloc0(sizeof(gchar) * size); - - g_snprintf(msg, size, "setup output%d %s %s", output, kind, opts); - - ret = _socket_send(vlc->sockfd, msg); - - g_free(msg); - return ret; -} - - -/** Function to clean the playlist - * - * @param vlc structure with options for vlc - * @param output the number of the output media - * @param file the file we want to insert in the playlist - * @return 0 if success - */ -int -gmyth_vlc_clean_playlist(GMythVlc * vlc) -{ - return _socket_send(vlc->sockfd, "del all"); -} - - -/** Function to control the playlist - * - * @param vlc structure with options for vlc - * @param output the number of the output media - * @param command play, stop or pause(just for vod) - * @return 0 if success - */ -int -gmyth_vlc_control_input(GMythVlc * vlc, int output, gchar * command) -{ - size_t size = 25; - gchar *msg = g_malloc0(sizeof(gchar) * size); - - g_snprintf(msg, size, "control output%d %s", output, command); - - int ret = _socket_send(vlc->sockfd, msg); - - g_free(msg); - return ret; -} - - - -/** Function to insert an item in the playlist - * - * @param vlc structure with options for vlc - * @param output the number of the output media - * @param file the file we want to insert in the playlist - * @return 0 if success - */ -int -gmyth_vlc_create_input(GMythVlc * vlc, int output, gchar * file) -{ - return gmyth_vlc_setup_output(vlc, output, "input", file); -} - - -/** Function to create a channel in vlc - * - * @param vlc structure with options for vlc - * @param type the type of channel (broadcast, vod...) - * @param port - * @return 0 if success - */ -int -gmyth_vlc_create_channel(GMythVlc * vlc, gchar * type, int port, - int vcodec) -{ - int ret; - size_t size = 40; - gchar *msg = (gchar *) g_malloc0(sizeof(gchar) * size); - - g_snprintf(msg, size, "new output%d %s enabled loop", vlc->n_outputs, - type); - - ret = _socket_send(vlc->sockfd, msg); - - if (ret > -1) { - gmyth_vlc_setup_output(vlc, vlc->n_outputs, "option", - "sout-keep=1"); - - g_free(msg); - size = 256; - msg = (gchar *) g_malloc0(sizeof(gchar) * size); - - if (vcodec == MPEG1) - // Best transcode option for N800 (MP1V) - g_snprintf(msg, size, "#transcode{vcodec=mp1v,vb=384," - "fps=25.0,scale=1,acodec=mpga," - "ab=64,channels=1}:duplicate{dst=" - "std{access=http,mux=mpeg1,dst=" ":%d}}", port); - else - // Best transcode option for N800 (THEORA) - g_snprintf(msg, size, "#transcode{vcodec=theo,vb=384," - "fps=25.0,scale=1,acodec=vorb," - "ab=64,channels=1}:duplicate{dst=" - "std{access=http,mux=ogg,dst=" ":%d}}", port); - - ret = gmyth_vlc_setup_output(vlc, vlc->n_outputs, "output", msg); - - vlc->n_outputs++; - } - - g_free(msg); - - return ret; -} - - -/** Function to connect to vlc on the backend - * - * @param vlc structure with options for vlc - * @param backend_info infos about the backend - * @param passwd the password for telnet interface - * @return 0 if success - */ -int -gmyth_vlc_connect(GMythVlc * vlc, GMythBackendInfo * backend_info, - gchar * passwd, int port) -{ - int numbytes; - - if ((vlc->he = gethostbyname(backend_info->hostname)) == NULL) { - herror("GMyth_VLC: gethostbyname error"); - return -1; - } - - if ((vlc->sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { - perror("GMyth_VLC: socket error"); - return -1; - } - // Socket properties - vlc->their_addr.sin_family = AF_INET; - vlc->their_addr.sin_port = htons(port); - vlc->their_addr.sin_addr = *((struct in_addr *) vlc->he->h_addr); - memset(&(vlc->their_addr.sin_zero), '\0', 8); - - if (connect(vlc->sockfd, (struct sockaddr *) &(vlc->their_addr), - sizeof(struct sockaddr)) == -1) { - perror("GMyth_VLC: connect error. Check VLC's telnet interface"); - return -1; - } - // Receive the Password's Prompt - numbytes = _socket_recv(vlc->sockfd, vlc->buf); - - // Send the Password. We don't have to - // care about passwords being sent in plain text - // because telnet protocol does it. - _socket_send(vlc->sockfd, passwd); - - // Receive the Welcome msg - numbytes = _socket_recv(vlc->sockfd, vlc->buf); - if (numbytes > -1) - if (strncmp(vlc->buf, "\r\nWrong password.", 17) == 0) { - perror("Gmyth_VLC: passwd error. Check your passwd"); - return -2; - } - - - return 0; -} - - -/** Function to disconnect from vlc - * - * @param vlc structure with options for vlc - * @param backend_info infos about the backend - * @return 0 if success - */ -int -gmyth_vlc_disconnect(GMythVlc * vlc) -{ - - int ret; - - ret = gmyth_vlc_clean_playlist(vlc); - - if (ret > -1) { - vlc->n_outputs = 0; - vlc->n_inputs = 0; - } - - return close(vlc->sockfd); -} diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gmyth_vlc.h --- a/gmyth/src/gmyth_vlc.h Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_vlc.h - * - * @brief

GMythVLC library provides functions that - * interact with a VLC server running telnet interface. - * - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia. - * @author Artur Duque de Souza - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __GMYTH_VLC_H__ -#define __GMYTH_VLC_H__ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "gmyth_backendinfo.h" -#include "gmyth_util.h" - -G_BEGIN_DECLS -#define VLC_TELNET_PORT 4212 -#define BUFFER 512 -#define MPEG1 0 -#define THEORA 1 -typedef struct _GMythVlc GMythVlc; - -struct _GMythVlc { - int sockfd; - - // Number of outputs used - int n_outputs; - - // Number of inputs - int n_inputs; - - // Socket vars - struct hostent *he; - struct sockaddr_in their_addr; - - char buf[BUFFER]; -}; - - - -int gmyth_vlc_setup_output(GMythVlc * vlc, int output, - gchar * kind, gchar * opts); - - -int gmyth_vlc_clean_playlist(GMythVlc * vlc); - - -int gmyth_vlc_control_input(GMythVlc * vlc, int output, - gchar * command); - -int gmyth_vlc_create_input(GMythVlc * vlc, int output, - gchar * file); - -int gmyth_vlc_create_channel(GMythVlc * vlc, gchar * type, - int port, int vcodec); - -int gmyth_vlc_connect(GMythVlc * vlc, - GMythBackendInfo * backend_info, - gchar * passwd, int port); - -int gmyth_vlc_disconnect(GMythVlc * vlc); - -G_END_DECLS -#endif /* __GMYTH_VLC_H__ */ diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/src/gst-indent.sh --- a/gmyth/src/gst-indent.sh Mon Feb 25 17:45:36 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -#!/bin/sh -indent \ - --braces-on-if-line \ - --blank-lines-after-declarations \ - --case-brace-indentation0 \ - --case-indentation4 \ - --braces-after-struct-decl-line \ - --line-length80 \ - --no-tabs \ - --cuddle-else \ - --dont-line-up-parentheses \ - --continuation-indentation4 \ - --honour-newlines \ - --tab-size4 \ - --indent-level4 \ - $* diff -r c39c60fcfec8 -r 4a8d56080089 gmyth/tests/Makefile.am --- a/gmyth/tests/Makefile.am Mon Feb 25 17:45:36 2008 +0000 +++ b/gmyth/tests/Makefile.am Mon Feb 25 17:51:43 2008 +0000 @@ -1,5 +1,5 @@ LDADD = \ - $(top_srcdir)/src/libgmyth.la + $(top_srcdir)/gmyth/libgmyth.la AM_LDFLAGS = \ @GLIB_LIBS@ @GOBJECT_LIBS@ @GTHREAD_LIBS@ @LIBCURL_LIBS@ @@ -7,8 +7,8 @@ INCLUDES = \ -I$(top_srcdir) \ -I$(top_builddir) \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/src \ + -I$(top_srcdir)/gmyth \ + -I$(top_builddir)/gmyth \ $(MYSQL_CFLAGS) \ $(GLIB_CFLAGS) \ $(GOBJECT_CFLAGS) \