# HG changeset patch # User renatofilho # Date 1159454466 -3600 # Node ID 79f6da40f6e99c7730da387795f0314ca2efdb63 # Parent b45e9fe9f593c16494ad8e1fa6b901944c5f1b49 [svn r19] - splited libgmyth; diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/Makefile.am --- a/gmyth/Makefile.am Wed Sep 27 00:08:03 2006 +0100 +++ b/gmyth/Makefile.am Thu Sep 28 15:41:06 2006 +0100 @@ -1,4 +1,4 @@ -SUBDIRS= src pixmaps +SUBDIRS= src ### all of the standard pc files we need to generate pcfiles = gmyth-@GMYTH_MAJORMINOR@.pc diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/configure.ac --- a/gmyth/configure.ac Wed Sep 27 00:08:03 2006 +0100 +++ b/gmyth/configure.ac Thu Sep 28 15:41:06 2006 +0100 @@ -111,45 +111,10 @@ AC_SUBST(GOBJECT_CFLAGS) AC_SUBST(GOBJECT_LIBS) -# Check for GTK+-2.0 -PKG_CHECK_MODULES(GTK, gtk+-2.0, HAVE_GTK=yes,HAVE_GTK=no) - -# Give error and exit if we don't have gtk -if test "x$HAVE_GTK" = "xyes"; then - AC_DEFINE(WITH_GTK, 1, [build with GTK+ related stuff]) - dnl AC_MSG_ERROR(you need gtk+-2.0 installed) -else - AC_MSG_RESULT(no) -fi - -AM_CONDITIONAL(WITH_GTK, test "x$HAVE_GTK" = "xyes" ) - -# make GTK_CFLAGS and GTK_LIBS available -AC_SUBST(GTK_CFLAGS) -AC_SUBST(GTK_LIBS) - -dnl ========== Check for Hildon Libraries -PKG_CHECK_MODULES(HILDON, - hildon-lgpl libosso hildon-status-bar-lib libhildonmenu hildon-base-lib hildon-control-panel hildon-libs, - HAVE_HILDON=yes, HAVE_HILDON=no) - -if test "x$HAVE_HILDON" = "xyes"; then - AC_DEFINE(MAEMO_PLATFORM, 1, [build with hildon libs]) - HILDON_CFLAGS="$HILDON_CFLAGS -DMAEMO_PLATFORM=1" -else - AC_MSG_RESULT(no) -fi - -AM_CONDITIONAL(MAEMO_PLATFORM, test "x$HAVE_HILDON" = "xyes") - -dnl make HILDON_CFLAGS and HILDON_LIBS available -AC_SUBST(HILDON_CFLAGS) -AC_SUBST(HILDON_LIBS) - # Check for libxml-2.0 PKG_CHECK_MODULES(LIBXML, libxml-2.0, HAVE_LIBXML=yes,HAVE_LIBXML=no) -# Give error and exit if we don't have gtk +# Give error and exit if we don't have libxml if test "x$HAVE_LIBXML" = "xno"; then AC_MSG_ERROR(you need libxml-2.0 installed) fi @@ -216,9 +181,6 @@ AC_CONFIG_FILES([Makefile - pixmaps/Makefile src/Makefile - src/libgmyth/Makefile - src/gui/Makefile - gmyth.pc]) + gmyth.pc]) AC_OUTPUT diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/m4/Makefile.am --- a/gmyth/m4/Makefile.am Wed Sep 27 00:08:03 2006 +0100 +++ b/gmyth/m4/Makefile.am Thu Sep 28 15:41:06 2006 +0100 @@ -1,7 +1,10 @@ -EXTRA_DIST = \ - ac_doxygen.m4 \ - as-compiler-flag.m4 \ - as-expand.m4 \ - as-version.m4 \ - as-gtk-doc.m4 +SUBDIRS= src pixmaps +include aminclude.am + +EXTRA_DIST = \ + autogen.sh \ + AUTHORS \ + COPYING \ + README + diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/pixmaps/Makefile.am --- a/gmyth/pixmaps/Makefile.am Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -# Adding the application icon -#icondir = $(datadir)/mmyth/pixmaps -#icon_DATA = \ -# mmyth.png - - -# Adding the application resources -pixmapdir = $(pkgdatadir)/pixmaps -pixmap_DATA = mmyth_logo.png - -EXTRA_DIST = $(pixmap_DATA) diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/pixmaps/mmyth_logo.png Binary file gmyth/pixmaps/mmyth_logo.png has changed diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/Makefile.am --- a/gmyth/src/Makefile.am Wed Sep 27 00:08:03 2006 +0100 +++ b/gmyth/src/Makefile.am Thu Sep 28 15:41:06 2006 +0100 @@ -1,29 +1,56 @@ -SUBDIRS = libgmyth gui . +SUBDIRS = . -bin_PROGRAMS = mmyth +lib_LTLIBRARIES = libgmyth.la -mmyth_SOURCES = mmyth_main.c +libgmyth_la_SOURCES = \ + gmyth_common.c \ + gmyth_context.c \ + gmyth_epg.c \ + gmyth_remote_encoder.c \ + gmyth_remote_util.c \ + gmyth_settings.c \ + gmyth_tvchain.c \ + gmyth_scheduler.c \ + gmyth_util.c \ + gmyth_query.c \ + gmyth_socket.c \ + gmyth_stringlist.c -mmyth_CFLAGS = \ - $(GTK_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(GST_CFLAGS) \ - $(MYSQL_CFLAGS) \ - -g3 -O0 \ - -I$(top_srcdir)/src/libgmyth \ - -I$(top_srcdir)/src/gui \ - -DDATA_DIR=\""$(pkgdatadir)"\" \ - -DPIX_DIR=\""$(pkgdatadir)/pixmaps/"\" \ - -DESG_DIR=\""$(pkgdatadir)/pixmaps/"\" \ - -DICON_DIR=\""$(pkgdatadir)/pixmaps/"\" +libgmyth_la_CFLAGS = \ + -DDATADIR=\"$(pkgdatadir)\" \ + $(GLIB_CFLAGS) \ + $(GOBJECT_CFLAGS) \ + $(GST_CFLAGS) \ + $(GSTBASE_CFLAGS) \ + $(MYSQL_CFLAGS) \ + -g3 -O0 -mmyth_LDFLAGS = +#libgmyth_la_LIBADD = \ +# $(MYSQL_LIBS) -mmyth_LDADD = \ - $(GTK_LIBS) \ - $(GLIB_LIBS) \ - $(GST_LIBS) \ - $(GSTBASE_LIBS) \ - $(HILDON_LIBS) \ - $(top_srcdir)/src/libgmyth/libgmyth.la \ - $(top_srcdir)/src/gui/libmmythgui.la +libgmyth_la_LDFLAGS = \ + -export-dynamic \ + -lgstinterfaces-0.10 \ + $(MYSQL_LIBS) \ + $(GST_LIBS) \ + $(GSTBASE_LIBS) + +libgmyth_includedir = \ + $(pkgincludedir) + +libgmyth_include_HEADERS = \ + gmyth_common.h \ + gmyth_context.h \ + gmyth_epg.h \ + gmyth_remote_encoder.h \ + gmyth_scheduler.h \ + gmyth_settings.h \ + gmyth_tvchain.h \ + gmyth_util.h \ + gmyth_query.h \ + gmyth_socket.h \ + gmyth_remote_util.h \ + gmyth_stringlist.h + +CLEANFILES = $(BUILT_SOURCES) + diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_common.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_common.c Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,85 @@ +/** + * 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 + * + *//* + * + * 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 + */ + +#include "gmyth_common.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) +{ + if (list == NULL) { + g_warning ("%s received null GList as parameter", __FUNCTION__); + return; + } + + 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) +{ + if (list == NULL) { + g_warning ("%s received null GList as parameter", __FUNCTION__); + return; + } + + g_list_foreach (list, free_program_data, NULL); + + g_list_free (list); +} + + +static void +free_channel_data(gpointer data, gpointer user_data) +{ + if(data) + g_free((GMythChannelInfo*) data); +} + +static void +free_program_data(gpointer data, gpointer user_data) +{ + if(data) + g_free((GMythProgramInfo*) data); +} + diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_common.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_common.h Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,159 @@ +/** + * 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 + * + *//* + * + * 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 + +G_BEGIN_DECLS + +/** + * The GMythChannelInfo structure represents the channel information + * stored in the backend database. + */ +typedef struct { + /** The channel ID in backend database */ + int channel_ID; + + /** The channel name in backend database */ + GString *channel_name; + +} GMythChannelInfo; + + +/** + * 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. + */ +typedef struct { + + /** The channel unique ID. */ + GString *chanid; + + /** The program start time. */ + time_t startts; + /** The program end time. */ + time_t endts; + /** The recording schedule start time. */ + time_t recstartts; + /** The recording schedule end time */ + time_t 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; + int chancommfree; + GString *chanOutputFilters; + + GString *seriesid; + /** The program unique id. */ + GString *programid; + GString * catType; + + GString * sortTitle; + + /** A flag informing if the program has video or not. */ + gboolean isVideo; + int lenMins; + + GString *year; + double stars; + int repeat; + + time_t originalAirDate; + time_t lastmodified; + time_t lastInUseTime; + + gboolean hasAirDate; + + int spread; + int startCol; + +// enum RecStatusType recstatus; +// enum RecStatusType oldrecstatus; +// enum RecStatusType savedrecstatus; + int recpriority2; + int reactivate; + + int recordid; + int parentid; + //enum RecordingType rectype; + //enum RecordingDupInType dupin; + //enum RecordingDupMethodType dupmethod; + + /** The backend video source id associated to this program.*/ + int sourceid; + /** the backend input id associated to this program.*/ + int inputid; + /** The backend card id associated to this program.*/ + int cardid; + gboolean shareable; + gboolean duplicate; + + GString * schedulerid; + int findid; + + int programflags; + int transcoder; + + //proginfo->spread = -1; + //proginfo->programflags = proginfo->getProgramFlags(); + + GString *recgroup; + GString *playgroup; + int recpriority; + + /** The file size of the recorded program.*/ + long long filesize; + /** The file name of the recorded program.*/ + GString *pathname; + GString *hostname; + + /* AvailableStatusType availableStatus;*/ + +} GMythProgramInfo; + + +void gmyth_free_channel_list(GList *list); +void gmyth_free_program_list(GList *list); + +G_END_DECLS + +#endif /* GMYTH_COMMON_H_ */ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_context.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_context.c Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,312 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_context.c + * + * @brief

GMythContext class contains general attributes and functions + * that express the connection state of each mythtvfrontend. + * + * 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 + */ + +#include "gmyth_context.h" + +#include +#include +#include +#include +#include +#include + +#include "gmyth_query.h" +#include "gmyth_socket.h" + +static void gmyth_context_class_init (GMythContextClass *klass); +static void gmyth_context_init (GMythContext *object); + +static void gmyth_context_dispose (GObject *object); +static void gmyth_context_finalize (GObject *object); + + +G_DEFINE_TYPE(GMythContext, gmyth_context, G_TYPE_OBJECT) + +static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + +static GMythContext *gcontext = NULL; + +static void +gmyth_context_class_init (GMythContextClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_context_dispose; + gobject_class->finalize = gmyth_context_finalize; +} + +static void +gmyth_context_init (GMythContext *gmyth_context) +{ + +} + +static void +gmyth_context_dispose (GObject *object) +{ + GMythContext *gmyth_context = GMYTH_CONTEXT(object); + + if ( gmyth_context->gmyth_settings != NULL ) { + g_object_unref (gmyth_context->gmyth_settings); + gmyth_context->gmyth_settings = NULL; + } + + if ( gmyth_context->localhostname != NULL ) { + g_string_free ( gmyth_context->localhostname, TRUE ); + gmyth_context->localhostname = NULL; + } + + if (gmyth_context->server_socket != NULL) { + g_object_unref (gmyth_context->server_socket); + gmyth_context->server_socket = NULL; + } + + G_OBJECT_CLASS (gmyth_context_parent_class)->dispose (object); +} + +static void +gmyth_context_finalize (GObject *object) +{ + g_signal_handlers_destroy (object); + + G_OBJECT_CLASS (gmyth_context_parent_class)->finalize (object); +} + +/** Gets the some important address translation info, + * from the client socket that will open a connection. + * + * @return gint error number + */ +static gint +myth_context_toaddrinfo( gchar *addr, gint port, struct addrinfo **addrInfo ) +{ + struct addrinfo hints; + gchar *portStr = g_strnfill( 32, ' ' ); + gint errorn = EADDRNOTAVAIL; + + memset( &hints, 0, sizeof(hints) ); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + + /* hints.ai_flags = AI_NUMERICHOST; */ + if ( port != -1 ) + sprintf(portStr, "%d", port); + else + portStr = NULL; + + g_debug( "[%s] Address: %s, port: %s\n", __FUNCTION__, addr, portStr ); + if ( ( errorn = getaddrinfo(addr, portStr, &hints, addrInfo) ) != 0 ) { + g_printerr( "[%s] Socket ERROR: %s\n", __FUNCTION__, gai_strerror(errorn) ); + } + + return errorn; + +} + +/** Initializes the GMythContext object. It reads local system information + * load gmyth user settings and start connection to the database. + * + * @return TRUE if initialization was successfull, + * FALSE if any error happens. + */ +gboolean +gmyth_context_initialize () +{ + GString *localhost = NULL; + + if (gcontext == NULL) { + gcontext = GMYTH_CONTEXT ( g_object_new (GMYTH_CONTEXT_TYPE, FALSE)); + } + + localhost = gmyth_socket_get_local_hostname( ); + + if (localhost==NULL || localhost->len <=0 ) { + g_warning ("[%s] Could not determine local hostname. Setting to 127.0.0.1", __FUNCTION__); + gcontext->localhostname = g_string_new ("127.0.0.1"); + } else { + gcontext->localhostname = localhost; + } + + if (gcontext->gmyth_settings) { + g_object_unref (gcontext->gmyth_settings); + gcontext->gmyth_settings = NULL; + } + + gcontext->gmyth_settings = gmyth_settings_new (); + if (!gmyth_settings_load (gcontext->gmyth_settings)) { + g_warning ("GMythContext: Settings file not opened!\n"); + } else { + g_debug ("GMythContext: Settings file loaded"); + } + + if (gcontext->server_socket != NULL) { + g_object_unref (gcontext->server_socket); + gcontext->server_socket = NULL; + } + + GString *server_hostname = + gmyth_settings_get_backend_hostname(gcontext->gmyth_settings); + int server_port = gmyth_settings_get_backend_port(gcontext->gmyth_settings); + + gcontext->server_socket = gmyth_socket_new (); + if (!gmyth_socket_connect_to_backend (gcontext->server_socket, + server_hostname->str, server_port, FALSE)) { + g_warning ("[%s] Socket connection to backend error!", __FUNCTION__); + g_object_unref (gcontext->server_socket); + gcontext->server_socket = NULL; + return FALSE; + } + + return TRUE; +} + +/** Formats a Mythtv protocol command based on strlist and sends it to + * the connected backend. The backend response is overwritten into strlist. + * + * @param strlist 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. + */ +gboolean +gmyth_context_send_receive_stringlist (GMythStringList *strlist) +{ + gint ok = -1; + + if (!gcontext || !(gcontext->server_socket)) { + g_warning ("[%s] GMythContext not initialized", __FUNCTION__); + return FALSE; + } + + //g_static_mutex_lock( &mutex ); + + ok = gmyth_socket_sendreceive_stringlist (gcontext->server_socket, strlist); + + //g_static_mutex_unlock( &mutex ); + + if (!ok) { + g_warning ("Connection to backend server lost"); + } + + return (ok ? TRUE : FALSE); +} + +/** Gets the GMythSettings object associated to this context. + * + * @return The GMythSettings object currently valid or NULL if the settings + * were not opened. + */ +GMythSettings* +gmyth_context_get_settings () +{ + if (!gcontext) { + g_warning ("[%s] GMythContext not initialized\n", __FUNCTION__); + return NULL; + } + + return gcontext->gmyth_settings; +} + +/** Gets the machine local hostname. + * + * @param hostname a valid GString object to be overwritten with the local + * hostname. + * @return true if the hostname was read, false if any error happened. + */ +gboolean +gmyth_context_get_local_hostname (GString *hostname) +{ + if (!hostname) { + g_warning ("[%s] Received null argument", __FUNCTION__); + return FALSE; + } + + g_string_assign (hostname, gcontext->localhostname->str); + + return TRUE; +} + +/** Gets a setting information from the backend mysql database. + * + * @param key The setting key to be retrieved. + * @param host the hostname associated to the desired setting. + * @param default_value the default setting value if could not query from + * backend database. + * @return The setting value loaded from database, or the given default value + * if the query fails. + */ +GString* +gmyth_context_get_setting_onhost (GString *key, GString *host, GString *default_value) +{ + GString *query_str; + + // TODO: Reuse msql query in gmyth_context + GMythQuery *gmyth_query = gmyth_query_new (); + + if (gmyth_query_connect (gmyth_query)) { + MYSQL_RES *msql_res; + MYSQL_ROW msql_row; + + query_str = g_string_new (""); + g_string_printf (query_str, "SELECT data FROM settings WHERE value = \"%s\" " + "AND hostname = \"%s\" ;", key->str, host->str); + + msql_res = gmyth_query_process_statement (gmyth_query, query_str->str); + if (msql_res) { + msql_row = mysql_fetch_row (msql_res); + if (msql_row != NULL) { + return g_string_new (msql_row[0]); + } + } + + g_object_unref (gmyth_query); + } else { + g_warning ("Database not open while trying to load setting: %s", key->str); + } + + + return default_value; +} + +/** Verify if the context is currently connected to a backend. + * + * @return true if connection was opened, false if not. + */ +gboolean +gmyth_context_check_connection () +{ + // FIXME: Check this based on socket states + if (!gcontext) { + g_warning ("[%s] GMythContext not initialized", __FUNCTION__); + return FALSE; + } + + return (gcontext->server_socket != NULL); +} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_context.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_context.h Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,88 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_context.h + * + * @brief

GMythContext class contains general attributes and functions + * that express the connection state of each mythtvfrontend. + * + * 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_CONTEXT_H__ +#define __GMYTH_CONTEXT_H__ + +#include + +#include "gmyth_settings.h" +#include "gmyth_socket.h" +#include "gmyth_stringlist.h" + +G_BEGIN_DECLS + +#define GMYTH_CONTEXT_TYPE (gmyth_context_get_type ()) +#define GMYTH_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_CONTEXT_TYPE, GMythContext)) +#define GMYTH_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_CONTEXT_TYPE, GMythContextClass)) +#define IS_GMYTH_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_CONTEXT_TYPE)) +#define IS_GMYTH_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_CONTEXT_TYPE)) +#define GMYTH_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_CONTEXT_TYPE, GMythContextClass)) + +#define MYTHTV_VERSION_DEFAULT 30 + +typedef struct _GMythContext GMythContext; +typedef struct _GMythContextClass GMythContextClass; + +struct _GMythContextClass +{ + GObjectClass parent_class; + + /* callbacks */ + /* no one for now */ +}; + +struct _GMythContext +{ + GObject parent; + + GMythSettings *gmyth_settings; + GMythSocket *server_socket; + + GString *localhostname; +}; + + +GType gmyth_context_get_type (void); +void gmyth_context_create(); + +gboolean gmyth_context_initialize (); +gboolean gmyth_context_check_connection (); +GMythSettings* gmyth_context_get_settings (); + +gboolean gmyth_context_send_receive_stringlist (GMythStringList *strlist); + +GString* gmyth_context_get_setting_onhost (GString *key, GString *host, GString *default_value); +gboolean gmyth_context_get_local_hostname (GString *hostname); + +GString* gmyth_context_get_setting_onhost (GString *key, GString *host, GString *default_value); + + +G_END_DECLS + +#endif /* __GMYTH_CONTEXT_H__ */ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_epg.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_epg.c Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,278 @@ +/** + * 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 + */ + +#include +#include +#include +#include + +#include "gmyth_epg.h" +#include "gmyth_util.h" + +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; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_epg_dispose; + gobject_class->finalize = gmyth_epg_finalize; +} + +static void +gmyth_epg_init (GMythEPG *gmyth_epg) +{ + gmyth_epg->sqlquery = gmyth_query_new (); +} + +static void +gmyth_epg_dispose (GObject *object) +{ + //GMythEPG *gmyth_epg = GMYTH_EPG(object); + + 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) +{ + assert(gmyth_epg); + + if (gmyth_epg->sqlquery == NULL) { + g_warning ("[%s] GMythEPG not initialized", __FUNCTION__); + return FALSE; + } + + if (!gmyth_query_connect(gmyth_epg->sqlquery)) { + g_warning ("[%s] Error while connecting to db", __FUNCTION__); + return FALSE; + } + + 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) +{ + assert(gmyth_epg); + + if (gmyth_epg->sqlquery != NULL) { + g_object_unref (gmyth_epg->sqlquery); + } + + return TRUE; +} + +/** Retrieves the available list of channels from the backend Mysql database. + * + * @param gmyth_epg the GMythEPG instance. + * @param glist_ptr the GList 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; + + assert(gmyth_epg); + + msql_res = gmyth_query_process_statement (gmyth_epg->sqlquery, + "SELECT chanid,name FROM channel;"); + + (*glist_ptr) = NULL; + + if (msql_res == NULL) { + g_warning ("[%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 = atoi (row[0]); + channel_info->channel_name = g_string_new (row[1]); + + (*glist_ptr) = g_list_append ((*glist_ptr), channel_info); + } + } + mysql_free_result (msql_res); + return (!(*glist_ptr)) ? 0 : g_list_length (*glist_ptr); +} + +/** + * Retrieves the available list of channels from the backend Mysql database. + * + * @param gmyth_epg the GMythEPG instance. + * @param proglist the GList 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, time_t starttime, time_t endtime) +{ + GString *startts = gmyth_util_time_to_string(starttime); + GString *endts = gmyth_util_time_to_string(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, oldrecstatus.recordid, " + " oldrecstatus.rectype, oldrecstatus.recstatus, " + " oldrecstatus.findid " + "FROM program " + "LEFT JOIN channel ON program.chanid = channel.chanid " + "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->str, endts->str); + + 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) { + g_warning ("[%s] msql query returned NULL MYSQL_RES", __FUNCTION__); + return -1; + } + + (*proglist) = NULL; + while ((row = mysql_fetch_row (res_set)) != NULL) { + + GMythProgramInfo *p = g_new0 (GMythProgramInfo, 1); + p->chanid = g_string_new (row[0]); + + p->startts = gmyth_util_string_to_time (g_string_new (row[1])); + p->endts = gmyth_util_string_to_time (g_string_new (row[2])); + + p->recstartts = p->startts; + p->recendts = p->endts; + p->lastmodified = p->startts; + + 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 = atoi(row[10]); + p->chancommfree = atoi(row[11]); + p->chanOutputFilters = g_string_new (row[12]); + p->seriesid = g_string_new (row[13]); + p->programid = g_string_new (row[14]); + p->year = g_string_new (row[15]); + p->stars = atof(row[16]); + + if (!row[17] || !strcmp(row[17], "")) { + p->originalAirDate = 0; + p->hasAirDate = FALSE; + } else { + p->originalAirDate = gmyth_util_string_to_time (g_string_new (row[17])); + p->hasAirDate = TRUE; + } + + p->catType = g_string_new (row[18]); + + *proglist = g_list_append((*proglist), p); + } + + /* deallocate */ + mysql_free_result (res_set); + g_string_free(querystr, TRUE); + + return TRUE; +} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_epg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_epg.h Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,75 @@ +/** + * 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_CAST ((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; +}; + +GType gmyth_epg_get_type (void); + +GMythEPG* gmyth_epg_new (void); + +gboolean gmyth_epg_connect (GMythEPG *gmyth_epg); +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, + const gint chanNum, time_t starttime, time_t endtime); + +#endif /*GMYTH_EPG_H_*/ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_query.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_query.c Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,221 @@ +/** + * 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 + */ + +#include +#include +#include + +#include "gmyth_query.h" +#include "gmyth_settings.h" +#include "gmyth_context.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) +{ + GMythSettings *gmyth_settings = gmyth_context_get_settings (); + + gmyth_query->opt_host_name = gmyth_settings_get_backend_hostname(gmyth_settings); + gmyth_query->opt_user_name = gmyth_settings_get_username(gmyth_settings); + gmyth_query->opt_password = gmyth_settings_get_password(gmyth_settings); + gmyth_query->opt_db_name = gmyth_settings_get_dbname(gmyth_settings); + + /* 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); + + /* disconnect from server */ + gmyth_query_disconnect (gmyth_query); + + 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; +} + +/** Connects to the Mysql database in the backend. The backend address + * is loaded from the GMythSettings 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) +{ + char *opt_host_name; + char *opt_user_name; + char *opt_password; + char *opt_db_name; + + assert(gmyth_query); + + opt_host_name = (gmyth_query->opt_host_name ? gmyth_query->opt_host_name->str : NULL); + opt_db_name = (gmyth_query->opt_db_name ? gmyth_query->opt_db_name->str : NULL); + opt_user_name = (gmyth_query->opt_user_name ? gmyth_query->opt_user_name->str : NULL); + opt_password = (gmyth_query->opt_password ? gmyth_query->opt_password->str : NULL); + + + if (gmyth_query->conn == NULL) { + gmyth_query_print_error (NULL, "mysql_init() failed (probably out of memory)"); + return FALSE; + } + + /* connect to server */ + if (mysql_real_connect (gmyth_query->conn, opt_host_name, + opt_user_name, opt_password, opt_db_name, + 0, NULL, 0) == NULL) { + + gmyth_query_print_error (gmyth_query->conn, "mysql_real_connect() failed"); + return FALSE; + } + + g_debug ("[%s] Connection to Mysql server succeeded!", __FUNCTION__); + + 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) +{ + assert(gmyth_query); + + /* TODO: Check how to return error */ + g_debug ("[%s] Closing gmyth_query->conn", __FUNCTION__); + mysql_close (gmyth_query->conn); + + return TRUE; +} + +static void +gmyth_query_print_error (MYSQL *conn, char *message) +{ + fprintf (stderr, "%s\n", message); + + if (conn != NULL) { +#if MYSQL_VERSION_ID >= 40101 + fprintf (stderr, "Error %u (%s): %s\n", + mysql_errno (conn), mysql_sqlstate(conn), mysql_error (conn)); +#else + fprintf (stderr, "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) +{ + MYSQL_RES *res_set; + + assert(gmyth_query); + + g_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 */ + res_set = mysql_store_result (gmyth_query->conn); + if (res_set) { + return res_set; + } else if (mysql_field_count (gmyth_query->conn) == 0) { + g_debug ("%lu rows affected\n", + (unsigned long) mysql_affected_rows (gmyth_query->conn)); + } else { + gmyth_query_print_error (gmyth_query->conn, "Could not retrieve result set"); + } + + return NULL; +} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_query.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_query.h Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,84 @@ +/** + * 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 + +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_CAST ((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; + + GString *opt_host_name; /* server host (default=localhost) */ + GString *opt_user_name; /* username (default=login name) */ + GString *opt_password; /* password (default=none) */ + unsigned int opt_port_num; /* port number (use built-in value) */ + GString *opt_socket_name; /* socket name (use built-in value) */ + GString *opt_db_name; /* database name (default=none) */ + unsigned int opt_flags; /* connection flags (none) */ + MYSQL *conn; /* pointer to connection handler */ +}; + + +GType gmyth_query_get_type (void); + +GMythQuery* gmyth_query_new (); +MYSQL_RES * gmyth_query_process_statement + (GMythQuery *gmyth_query, char *stmt_str); + +gboolean gmyth_query_connect (GMythQuery *gmyth_query); +gboolean gmyth_query_disconnect (GMythQuery *gmyth_query); + +G_END_DECLS + +#endif /* __GMYTH_QUERY_H__ */ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_remote_encoder.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_remote_encoder.c Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,207 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_remote_encoder.c + * + * @brief

GMythRemoteEncoder class 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 + * + *//* + * + * 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 + */ + +#include "gmyth_remote_encoder.h" + +#include + +#include "gmyth_stringlist.h" + +static void gmyth_remote_encoder_class_init (GMythRemoteEncoderClass *klass); +static void gmyth_remote_encoder_init (GMythRemoteEncoder *object); + +static void gmyth_remote_encoder_dispose (GObject *object); +static void gmyth_remote_encoder_finalize (GObject *object); + +G_DEFINE_TYPE(GMythRemoteEncoder, gmyth_remote_encoder, G_TYPE_OBJECT) + +static void +gmyth_remote_encoder_class_init (GMythRemoteEncoderClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_remote_encoder_dispose; + gobject_class->finalize = gmyth_remote_encoder_finalize; +} + +static void +gmyth_remote_encoder_init (GMythRemoteEncoder *gmyth_remote_encoder) +{ +} + +static void +gmyth_remote_encoder_dispose (GObject *object) +{ + // GMythRemoteEncoder *gmyth_remote_encoder = GMYTH_REMOTE_ENCODER(object); + + G_OBJECT_CLASS (gmyth_remote_encoder_parent_class)->dispose (object); +} + + +static void +gmyth_remote_encoder_finalize (GObject *object) +{ + g_signal_handlers_destroy (object); + + GMythRemoteEncoder *remote_encoder = GMYTH_REMOTE_ENCODER(object); + + g_debug ("[%s] Closing control socket", __FUNCTION__); + gmyth_socket_close_connection(remote_encoder->myth_socket); + g_object_unref (remote_encoder->myth_socket); + + G_OBJECT_CLASS (gmyth_remote_encoder_parent_class)->finalize (object); +} + +/** Creates a new instance of GMythRemoteEncoder. + * + * @return a new instance of GMythRemoteEncoder. + */ +GMythRemoteEncoder* +gmyth_remote_encoder_new (int num, GString *hostname, gshort port) +{ + GMythRemoteEncoder *encoder = GMYTH_REMOTE_ENCODER ( g_object_new ( + GMYTH_REMOTE_ENCODER_TYPE, FALSE )); + + encoder->recorder_num = num; + encoder->hostname = g_string_new (hostname->str); + encoder->port = port; + + return encoder; +} + +/** Configures the remote encoder instance connecting it to Mythtv backend. + * + * @param remote_encoder the GMythRemoteEncoder instance. + * @return TRUE if successfull, FALSE if any error happens. + */ +gboolean +gmyth_remote_encoder_setup (GMythRemoteEncoder *remote_encoder) +{ + assert (remote_encoder); + g_debug ("[%s] Creating socket and connecting to backend", __FUNCTION__); + + if (remote_encoder->myth_socket == NULL) { + + remote_encoder->myth_socket = gmyth_socket_new (); + + if (!gmyth_socket_connect_to_backend (remote_encoder->myth_socket, remote_encoder->hostname->str, + remote_encoder->port, TRUE) ) { + g_warning ("GMythRemoteEncoder: Connection to backend failed"); + return FALSE; + } + + } else { + g_warning("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 remote_encoder The GMythRemoteEncoder instance. + * @param tvchain_id The tvchain unique id. + * @return true if success, false if any error happens. + */ +gboolean +gmyth_remote_encoder_spawntv (GMythRemoteEncoder *remote_encoder, GString *tvchain_id) +{ + GMythStringList *str_list; + GString *tmp_str; + + g_debug ("[%s] Spawntv with tvchain_id = %s", __FUNCTION__, tvchain_id->str); + + str_list = gmyth_string_list_new (); + + tmp_str = g_string_new ("QUERY_RECORDER "); + g_string_append_printf (tmp_str, "%d", remote_encoder->recorder_num); + + gmyth_string_list_append_string (str_list, tmp_str); + gmyth_string_list_append_string (str_list, g_string_new ("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 (remote_encoder->myth_socket, str_list); + + g_string_free (tmp_str, TRUE); + + tmp_str = gmyth_string_list_get_string (str_list, 0); + if (tmp_str == NULL) { + g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str); + return FALSE; + } + + if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) { + g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str); + g_object_unref (str_list); + return FALSE; + } + + g_object_unref (str_list); + return TRUE; + +} + +/** Sends the command STOP_LIVETV to Mythtv backend. + * + * @param remote_encoder the GMythRemoteEncoder instance. + * @return true if success, false if any error happens. + */ +gboolean +gmyth_remote_encoder_stop_livetv (GMythRemoteEncoder *remote_encoder) +{ + GMythStringList *str_list; + GString *tmp_str; + + g_debug ("[%s]", __FUNCTION__); + + str_list = gmyth_string_list_new (); + + tmp_str = g_string_new ("QUERY_RECORDER "); + g_string_append_printf (tmp_str, "%d", remote_encoder->recorder_num); + gmyth_string_list_append_string (str_list, g_string_new ("STOP_LIVETV")); + + gmyth_socket_sendreceive_stringlist (remote_encoder->myth_socket, str_list); + + g_string_free (tmp_str, TRUE); + + tmp_str = gmyth_string_list_get_string (str_list, 0); + if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) { + g_warning ("[%s] Stop livetv request returned %s", __FUNCTION__, tmp_str->str); + g_object_unref (str_list); + return FALSE; + } + + g_object_unref (str_list); + return TRUE; + +} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_remote_encoder.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_remote_encoder.h Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,89 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_remote_encoder.h + * + * @brief

GMythRemoteEncoder class defines functions for playing live tv. + * + * 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_REMOTE_ENCODER_H__ +#define __GMYTH_REMOTE_ENCODER_H__ + +#include + +#include "gmyth_socket.h" + +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GMYTH_REMOTE_ENCODER_TYPE (gmyth_remote_encoder_get_type ()) +#define GMYTH_REMOTE_ENCODER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_REMOTE_ENCODER_TYPE, GMythRemoteEncoder)) +#define GMYTH_REMOTE_ENCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_REMOTE_ENCODER_TYPE, GMythRemoteEncoderClass)) +#define IS_GMYTH_REMOTE_ENCODER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_REMOTE_ENCODER_TYPE)) +#define IS_GMYTH_REMOTE_ENCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_REMOTE_ENCODER_TYPE)) +#define GMYTH_REMOTE_ENCODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_REMOTE_ENCODER_TYPE, GMythRemoteEncoderClass)) + + +typedef struct _GMythRemoteEncoder GMythRemoteEncoder; +typedef struct _GMythRemoteEncoderClass GMythRemoteEncoderClass; + +struct _GMythRemoteEncoderClass +{ + GObjectClass parent_class; + + /* callbacks */ + /* no one for now */ +}; + +struct _GMythRemoteEncoder +{ + GObject parent; + + /* socket descriptor */ + GMythSocket *myth_socket; + + int recorder_num; + GString *hostname; + int port; +}; + + +GType gmyth_remote_encoder_get_type (void); + +GMythRemoteEncoder* gmyth_remote_encoder_new (int num, + GString *hostname, + gshort port); + +gboolean gmyth_remote_encoder_setup (GMythRemoteEncoder *encoder); +gboolean gmyth_remote_encoder_spawntv (GMythRemoteEncoder *remote_encoder, + GString *tvchain_id); +gboolean gmyth_remote_encoder_stop_livetv (GMythRemoteEncoder *remote_encoder); + +G_END_DECLS + +#endif /* __GMYTH_REMOTE_ENCODER_H__ */ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_remote_util.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_remote_util.c Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,70 @@ +/** + * 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 + * + *//* + * + * 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 + */ + +#include "gmyth_remote_util.h" + +#include "gmyth_context.h" +#include "gmyth_remote_encoder.h" +#include "gmyth_stringlist.h" + +/** Requests the Mythtv backend for a free remote recorder. + * + * @param curr The recorder index, or -1 to consider the first one. + * @return the remote encoder instance available, or NULL if any error happens. + */ +GMythRemoteEncoder* +remote_request_next_free_recorder (int curr) +{ + GMythRemoteEncoder *encoder; + GString *hostname; + int num, port; + + GMythStringList *strlist = gmyth_string_list_new(); + + g_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_context_send_receive_stringlist(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); + + g_debug ("[%s] Free recorder info received: num: %d, hostname: %s, port: %d", + __FUNCTION__, num, hostname->str, port); + + encoder = gmyth_remote_encoder_new (num, hostname, port); + + g_object_unref (strlist); + + return encoder; +} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_remote_util.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_remote_util.h Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,40 @@ +/** + * 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_remote_encoder.h" + +G_BEGIN_DECLS + +GMythRemoteEncoder* remote_request_next_free_recorder (int curr); + +G_END_DECLS + +#endif diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_scheduler.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_scheduler.c Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,610 @@ +/** + * 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 + */ + +#include + +#include "gmyth_scheduler.h" + +#include "gmyth_context.h" +#include "gmyth_util.h" +#include "gmyth_query.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 gint get_record_id_from_database (GMythScheduler *scheduler); +static void update_backend (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 = 0; + sched->playgroup = 0; + + sched->prefinput = 0; + sched->inactive = 0; + + sched->searchType = g_string_new(""); + sched->searchForWhat = g_string_new(""); + + sched->msqlquery = gmyth_query_new (); +} + +static void +gmyth_scheduler_dispose (GObject *object) +{ + 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; +} + +/** 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 (GMythScheduler *scheduler) +{ + assert(scheduler); + + if (scheduler->msqlquery == NULL) { + g_warning ("[%s] MMythScheduler not initialized", __FUNCTION__); + return FALSE; + } + + if (!gmyth_query_connect(scheduler->msqlquery)) { + 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) { + g_object_unref (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 (""); + GString *date_time = g_string_new (""); + + assert(scheduler); + + g_string_printf (query_str, + "SELECT recordid,programid,chanid,starttime,startdate," + "endtime,enddate,title,subtitle,description,category 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); + + schedule->record_id = atoi (row[0]); + schedule->program_id = atoi (row[1]); + schedule->channel_id = atoi (row[2]); + + /* generate a time_t from a time and a date db field */ + g_string_printf (date_time, "%s %s", row[4], row[3]); + + schedule->start_time = gmyth_util_string_to_time (date_time); + + /* generate a time_t from a time and a date db field */ + g_string_printf (date_time, "%s %s", row[6], row[5]); + + schedule->end_time = gmyth_util_string_to_time (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]); + + (*schedule_list) = g_list_append (*(schedule_list), schedule); + } + } + + mysql_free_result (msql_res); + g_string_free(query_str, TRUE); + g_string_free(date_time, 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 (""); + GString *date_time = g_string_new (""); + + assert(scheduler); + + g_string_printf (query_str, + "SELECT recordid,programid,chanid,starttime,progstart," + "endtime,progend,title,subtitle,description,category,basename FROM recorded;"); + + 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 = atoi (row[0]); + record->program_id = atoi (row[1]); + record->channel_id = atoi (row[2]); + + /* the db field time already contains the date. therefore + * we are not using the date field */ + /* generate a time_t from a time and a date db field */ + /* g_string_printf (date_time, "%s %s", row[4], row[3]); */ + g_string_printf (date_time, "%s", row[3]); + + record->start_time = gmyth_util_string_to_time (date_time); + + /* the db field time already contains the date. therefore + * we are not using the date field */ + /* generate a time_t from a time and a date db field */ + /* g_string_printf (date_time, "%s %s", row[6], row[5]); */ + g_string_printf (date_time, "%s", row[5]); + + record->end_time = gmyth_util_string_to_time (date_time); + + 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->basename = g_string_new (row[11]); + + *recorded_list = g_list_append (*recorded_list, record); + } + } + + mysql_free_result (msql_res); + g_string_free(query_str, TRUE); + g_string_free(date_time, TRUE); + + return (*recorded_list == NULL) ? 0 : g_list_length (*recorded_list); +} + +/** 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) +{ + struct tm start_tm; + struct tm end_tm; + + 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 0; + } + + /* manipulating time */ + if(localtime_r(&schedule_info->start_time, &start_tm) == NULL) { + g_warning ("localtime_r error in libgmyth scheduler!\n"); + return FALSE; + } + + if(localtime_r(&schedule_info->end_time, &end_tm) == NULL) { + g_warning ("localtime_r error in libgmyth scheduler!\n"); + return FALSE; + } + + //TODO: verify if this funtion realy does what it should do! + g_string_printf (query_str, "REPLACE INTO record " + "(recordid, type, chanid, starttime, " + "startdate, endtime, enddate, title," + "profile, recpriority, maxnewest, inactive, " + "maxepisodes, autoexpire, startoffset, endoffset, " + "recgroup, dupmethod, dupin, station, " + "autocommflag, findday, findtime, findid, " + "search, autotranscode, transcoder, tsdefault, " + "autouserjob1, autouserjob2, autouserjob3, autouserjob4) " + " values ( %d, 1, %d, \"%02d:%02d:00\"," //recordid, type, chanid, starttime + " \"%d-%02d-%02d\", \"%02d:%02d:00\", \"%04d-%02d-%02d\", \"%s\"," + //startdate, endtime, enddate, title + "DEFAULT, 0, 0, 0, " //profile, recpriority, maxnewest, inactive + "0, 1, 0, 0, " //maxepisodes, autoexpire, startoffset, endoffset + "DEFAULT, 6, 15, %d, " //recgroup, dupmethod, dupin, station + "1, %d, \"%02d:%02d:00\", %d, " //autocommflag, findday, findtime, findid + "5, 0, 29, 1, " //search, autotranscode, transcoder, tsdefault + "0, 0, 0, 0 );", //autouserjob1, autouserjob2, autouserjob3, autouserjob4 + schedule_info->record_id, schedule_info->channel_id, + start_tm.tm_hour, start_tm.tm_min, + start_tm.tm_year+1900, start_tm.tm_mon+1, + start_tm.tm_mday, + end_tm.tm_hour, end_tm.tm_min, + end_tm.tm_year+1900, end_tm.tm_mon+1, + end_tm.tm_mday, schedule_info->title->str, //title + schedule_info->channel_id,//station + start_tm.tm_wday+1, //findday + start_tm.tm_hour, start_tm.tm_min, //findtime + (gint)(schedule_info->start_time/60/60/24 + 719528)//findid + ); + + msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); + + /* FIXME: currently no way to detect db error in UPDATE, REPLACES! + if (msql_res == NULL) { + g_warning ("DB retrieval of recording list failed"); + return -1; + }*/ + + /* TODO: verify record_id = -1 semantics */ + if (schedule_info->record_id <= 0) + schedule_info->record_id = get_record_id_from_database(scheduler); + + /* Notify the backend of changes */ + update_backend(schedule_info->record_id); + + /* free allocated memory */ + mysql_free_result (msql_res); + g_string_free(query_str, TRUE); + + return 1; +} + +/** Requests the Mysql database in the backend to remove an existing schedule. + * + * @param scheduler the GMythScheduler instance. + * @param record_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 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 record WHERE recordid=%d", record_id); + + msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); + + if (msql_res == NULL) { + g_warning ("[%s] Error while trying to delete a schedule in the database", __FUNCTION__); + return FALSE; + } + + update_backend(record_id);// Notify the backend of the changes + + mysql_free_result (msql_res); + g_string_free(query_str, TRUE); + + return TRUE; +} + +/** 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); + + msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); + + update_backend(record_id);// Notify the backend of the changes + + mysql_free_result (msql_res); + g_string_free(query_str, TRUE); + + return TRUE; +} + +/** 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, time_t starttime) +{ + MYSQL_RES *msql_res; + GMythProgramInfo *proginfo = NULL; + GString *query_str = g_string_new(""); + GString *time_str = gmyth_util_time_to_string (starttime); + + assert(scheduler); + + 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->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 = g_new0 (GMythProgramInfo, 1); + + proginfo->chanid = g_string_new (msql_row[0]); + proginfo->startts = gmyth_util_string_to_time (g_string_new (msql_row[23])); + proginfo->endts = gmyth_util_string_to_time (g_string_new (msql_row[24])); + proginfo->recstartts = gmyth_util_string_to_time (g_string_new (msql_row[1])); + proginfo->recendts = gmyth_util_string_to_time (g_string_new (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 = atoi (msql_row[9]); + proginfo->chanOutputFilters = g_string_new (msql_row[10]); + proginfo->seriesid = g_string_new (msql_row[11]); + proginfo->programid = g_string_new (msql_row[12]); + proginfo->filesize = atoll (msql_row[13]); + + proginfo->lastmodified = gmyth_util_string_to_time (g_string_new (msql_row[14])); + + proginfo->stars = atof (msql_row[15]); + proginfo->repeat = atoi (msql_row[16]); + + if (msql_row[17] == NULL) { + proginfo->originalAirDate = 0; + proginfo->hasAirDate = FALSE; + } else { + proginfo->originalAirDate = gmyth_util_string_to_time (g_string_new (msql_row[17])); + proginfo->hasAirDate = TRUE; + } + + proginfo->hostname = g_string_new (msql_row[18]); + proginfo->recordid = atoi (msql_row[19]); + proginfo->transcoder = atoi (msql_row[20]); + + //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 = atoi (msql_row[22]); + + proginfo->pathname = g_string_new (msql_row[25]); + + g_debug ("One program info loaded from mysql database\n"); + } + } + + mysql_free_result (msql_res); + g_string_free(query_str, TRUE); + g_string_free(time_str, TRUE); + + return proginfo; +} + +/** Retrieves the next record id. + * + * @param scheduler The GMythScheduler instance. + * @return gint record_id if success, -1 otherwise + */ +static gint +get_record_id_from_database (GMythScheduler *scheduler) +{ + gint record_id; + + assert(scheduler); + + if (scheduler->msqlquery == NULL) { + g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__); + return 0; + } + + record_id = mysql_insert_id (scheduler->msqlquery->conn); + + return record_id; +} + +/** Notifies the backend of an update in the db. + * + * @param record_id the id of the modified recording. + */ +static void +update_backend(gint record_id)//fixme: put void and discovery record_id inside +{ + GMythStringList *strlist = gmyth_string_list_new (); + GString *datastr = g_string_new ("RESCHEDULE_RECORDINGS "); + + g_string_append_printf (datastr, "%d", record_id); + gmyth_string_list_append_string (strlist, datastr); + + gmyth_context_send_receive_stringlist (strlist); + + g_string_free(datastr, TRUE); + g_object_unref(strlist); +} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_scheduler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_scheduler.h Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,156 @@ +/** + * 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" + +G_BEGIN_DECLS + +#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_CAST ((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; + + /* callbacks */ + /* no one for now */ +}; + +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 *searchType; + GString *searchForWhat; + + GMythQuery *msqlquery; +}; + +typedef struct { + gint record_id; + gint program_id; + gint channel_id; + + time_t start_time; + time_t end_time; + + GString *title; + GString *subtitle; + GString *description; + GString *category; + +} ScheduleInfo; + +typedef struct { + gint record_id; + gint program_id; + gint channel_id; + + time_t start_time; + time_t end_time; + + GString *title; + GString *subtitle; + GString *description; + GString *category; + + GString *basename; + +} RecordedInfo; + + +GType gmyth_scheduler_get_type (void); + +GMythScheduler* gmyth_scheduler_new (); +gboolean gmyth_scheduler_connect (GMythScheduler *scheduler); +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); + +GMythProgramInfo* gmyth_scheduler_get_recorded (GMythScheduler *scheduler, + GString *channel, time_t starttime); + +gint gmyth_scheduler_add_schedule(GMythScheduler *scheduler, + ScheduleInfo *schedule_info); + +gint gmyth_scheduler_delete_schedule (GMythScheduler *scheduler, + gint record_id); +gint gmyth_scheduler_delete_recorded (GMythScheduler *scheduler, + gint record_id); + +G_END_DECLS + +#endif /* __GMYTH_SCHEDULER_H__ */ + diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_settings.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_settings.c Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,417 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_settings.c + * + * @brief

This component contains functions acessing and modifying + * user and program settings. + * + * The standard settings file is created in the user home folder, in the + * file ~/.mmyth/settings.dat. + * + * 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 + */ + +#include "gmyth_settings.h" + +#include +#include +#include +#include + +#include +#include +#include + +#define GMYTH_SETTINGS_FILE_NAME "settings.dat" +#define GMYTH_SETTINGS_DIR ".mmyth" + +static void gmyth_settings_class_init (GMythSettingsClass *klass); +static void gmyth_settings_init (GMythSettings *object); + +static void gmyth_settings_dispose (GObject *object); +static void gmyth_settings_finalize (GObject *object); + +static void fill_settings_data(GMythSettings *gmyth_settings, char* line); + +G_DEFINE_TYPE(GMythSettings, gmyth_settings, G_TYPE_OBJECT) + +static void +gmyth_settings_class_init (GMythSettingsClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_settings_dispose; + gobject_class->finalize = gmyth_settings_finalize; +} + +static void +gmyth_settings_init (GMythSettings *gmyth_settings) +{ + + gmyth_settings->settings_file = NULL; + + gmyth_settings->backend_hostname = g_string_new("127.0.0.1"); + gmyth_settings->backend_port = 6543; + gmyth_settings->mysql_dbname = g_string_new("mythconverg"); + gmyth_settings->mysql_username = g_string_new("mythtv"); + gmyth_settings->mysql_password = g_string_new("mythtv"); + gmyth_settings->database_type = g_string_new("mysql"); + +} + + +static void +gmyth_settings_dispose (GObject *object) +{ + GMythSettings *gmyth_settings = GMYTH_SETTINGS(object); + + if ( gmyth_settings->backend_hostname != NULL ) + g_string_free( gmyth_settings->backend_hostname, TRUE ); + if ( gmyth_settings->mysql_dbname != NULL ) + g_string_free( gmyth_settings->mysql_dbname, TRUE ); + if ( gmyth_settings->mysql_username != NULL ) + g_string_free( gmyth_settings->mysql_username, TRUE ); + if ( gmyth_settings->mysql_password != NULL ) + g_string_free( gmyth_settings->mysql_password, TRUE ); + if ( gmyth_settings->database_type != NULL ) + g_string_free( gmyth_settings->database_type, TRUE ); + + G_OBJECT_CLASS (gmyth_settings_parent_class)->dispose (object); +} + +static void +gmyth_settings_finalize (GObject *object) +{ + g_signal_handlers_destroy (object); + + G_OBJECT_CLASS (gmyth_settings_parent_class)->finalize (object); +} + +/** Creates a new instance of GMythSettings. + * + * @return a new instance of GMythSettings. + */ +GMythSettings* +gmyth_settings_new (void) +{ + GMythSettings *gmyth_settings = GMYTH_SETTINGS (g_object_new(GMYTH_SETTINGS_TYPE, NULL)); + + return gmyth_settings; +} + +static gboolean +gmyth_settings_ensure_dir_exists (const gchar *dir) +{ + + g_debug ("[%s] \tdir = %s\n", __FUNCTION__, dir); + + if (g_file_test (dir, G_FILE_TEST_IS_DIR) == FALSE) { + if (g_file_test (dir, G_FILE_TEST_EXISTS) == TRUE) { + g_warning ("%s exists, please move it out of the way.", dir); + return FALSE; + } + + if (mkdir (dir, 488) != 0) { + g_warning ("Failed to create directory %s.", dir); + return FALSE; + } + } + + return TRUE; +} + +static gboolean +gmyth_settings_ensure_file_exists (const gchar *file_name) { + + int file = 0; + + if ( g_file_test( file_name, G_FILE_TEST_EXISTS ) == FALSE ) { + g_debug ( "\n\tCreating %s file...\n", file_name ); + file = creat( file_name, S_IRWXU | S_IRWXO | S_IRWXG ); + + if ( close( file ) == -1 ) + return FALSE; + } + + return TRUE; +} + +/** Loads the GMyth settings from the given file. + * + * @param gmyth_settings the GMythSettings instance. + * @param filename The desired file to be opened. + * @return TRUE if success, FALSE if error. + */ +gboolean +gmyth_settings_load_from_file (GMythSettings *gmyth_settings, GString *filename) +{ + FILE *file_desc; + char line[100]; + + g_debug ("[%s] Loading GMyth settings file: %s", __FUNCTION__, filename->str); + + file_desc = fopen(filename->str, "r"); + if( file_desc == NULL) { + g_warning ("[%s] Settings file %s could not be opened", __FUNCTION__, filename->str); + return FALSE; + } + + gmyth_settings->settings_file = g_string_new (filename->str); + + while(fgets(line, 100, file_desc)) { + int i; + + /* Removes the new line characters from the end of line */ + for ( i = strlen(line)-1; i >= 0; i--) { + if ( !g_ascii_iscntrl (line[i]) ) { + line[i+1] = '\0'; + break; + } + } + + fill_settings_data(gmyth_settings, line); + } + + fclose (file_desc); + + return TRUE; +} + +/** Loads the GMyth settings from the standard settings file + * (~/.mmyth/settings.dat). + * + * @param gmyth_settings the GMythSettings instance. + * @return TRUE if success, FALSE if error. + */ +gboolean +gmyth_settings_load (GMythSettings *gmyth_settings) +{ + GString* file_full_path = g_string_new( g_build_filename( g_get_home_dir(), + GMYTH_SETTINGS_DIR, GMYTH_SETTINGS_FILE_NAME, NULL ) ); + + gmyth_settings->settings_file = file_full_path; + + gmyth_settings_ensure_dir_exists( g_build_filename( g_get_home_dir(), GMYTH_SETTINGS_DIR, NULL ) ); + + // Verifies if the file already exist + if ( g_file_test( file_full_path->str, G_FILE_TEST_EXISTS ) == FALSE ) { + g_debug ("[%s] Settings file does not exist. A new one will be created.\n", __FUNCTION__); + + if ( gmyth_settings_ensure_file_exists( file_full_path->str ) == FALSE ) + return FALSE; + + // Creates the file with default values (see _init function) + return gmyth_settings_save (gmyth_settings); + + } else { + g_debug ("[%s] Opening settings from file %s", __FUNCTION__, file_full_path->str); + + return gmyth_settings_load_from_file (gmyth_settings, file_full_path); + } +} + +/** Saves the current gmyth_settings to the settings file related to the + * given instance. + * + * @param gmyth_settings the GMythSettings instance. + * @return TRUE if success, FALSE if error. + */ +gboolean +gmyth_settings_save (GMythSettings *gmyth_settings) +{ + FILE *file_desc; + + if (gmyth_settings->settings_file == NULL) { + g_warning ("[%s] Settings were not loaded from file, could not save!", __FUNCTION__); + } + + file_desc = fopen(gmyth_settings->settings_file->str, "w"); + if( file_desc == NULL) { + g_warning ("GMYTH_SETTINGS: settings file %s not found", gmyth_settings->settings_file->str); + return FALSE; + } + + g_fprintf(file_desc, "#Maemo-Myth Settings\n"); + + g_fprintf(file_desc, "#General settings related with mythtv database\n"); + g_fprintf(file_desc, "dbname=%s\n", gmyth_settings->mysql_dbname->str); + g_fprintf(file_desc, "username=%s\n", gmyth_settings->mysql_username->str); + g_fprintf(file_desc, "password=%s\n", gmyth_settings->mysql_password->str); + + g_fprintf(file_desc, "\n#General settings related with mythtv backend\n"); + g_fprintf(file_desc, "hostname=%s\n", gmyth_settings->backend_hostname->str); + g_fprintf(file_desc, "backend_port=%d\n", gmyth_settings->backend_port); + + fclose (file_desc); + + g_debug ("[%s] Settings file saved", __FUNCTION__); + return TRUE; +} + +/** Gets the backend hostname from the settings. + * + * @param gmyth_settings the GMythSettings instance. + * @return The loaded backend hostname, or the default value "127.0.0.1" if settings + * file was not opened. + */ +GString* +gmyth_settings_get_backend_hostname (GMythSettings *gmyth_settings) +{ + return g_string_new (gmyth_settings->backend_hostname->str); +} + +/** Sets the backend hostname to the settings. + * + * @param gmyth_settings the GMythSettings instance. + * @param new_hostname The new hostname. + */ +void +gmyth_settings_set_backend_hostname (GMythSettings *gmyth_settings, GString *new_hostname) +{ + g_string_assign (gmyth_settings->backend_hostname, new_hostname->str); +} + +/** Gets the user name to connect to backend database. + * + * @param gmyth_settings the GMythSettings instance. + * @return The loaded user name, or the default value "mythtv" if settings + * file was not opened. + */ +GString* +gmyth_settings_get_username (GMythSettings *gmyth_settings) +{ + return g_string_new (gmyth_settings->mysql_username->str); +} + +/** Sets the username to connect to backend database. + * + * @param gmyth_settings the GMythSettings instance. + * @param new_username The new username. + */ +void +gmyth_settings_set_username (GMythSettings *gmyth_settings, GString *new_username) +{ + g_string_assign (gmyth_settings->mysql_username, new_username->str); +} + +/** Gets the database password from the settings file. + * + * @param gmyth_settings the GMythSettings instance. + * @return The loaded password, or the default value "mythtv" if settings + * file was not opened. + */ +GString* +gmyth_settings_get_password (GMythSettings *gmyth_settings) +{ + return g_string_new (gmyth_settings->mysql_password->str); +} + +/** Sets the database password. + * + * @param gmyth_settings the GMythSettings instance. + * @param new_password The new password. + */ + +void +gmyth_settings_set_password (GMythSettings *gmyth_settings, GString *new_password) +{ + g_string_assign (gmyth_settings->mysql_password, new_password->str); +} + +/** Gets the backend database name from the settings file. + * + * @param gmyth_settings the GMythSettings instance. + * @return The loaded database name, or the default value "mythconverg" if settings + * file was not opened. + */ +GString* +gmyth_settings_get_dbname (GMythSettings *gmyth_settings) +{ + return g_string_new (gmyth_settings->mysql_dbname->str); +} + +/** Sets the Mythtv database name to the settings. + * + * @param gmyth_settings the GMythSettings instance. + * @param new_dbname The new database name. + */ + +void +gmyth_settings_set_dbname (GMythSettings *gmyth_settings, GString *new_dbname) +{ + g_string_assign (gmyth_settings->mysql_dbname, new_dbname->str); +} + +/** Gets the backend port from the settings. + * + * @param gmyth_settings the GMythSettings instance. + * @return The loaded backend port, or the default value "6543" if settings + * file was not opened. + */ +int +gmyth_settings_get_backend_port (GMythSettings *gmyth_settings) +{ + return gmyth_settings->backend_port; +} + +/** Sets the backend port. + * + * @param gmyth_settings the GMythSettings instance. + * @param new_port The new port. + */ +void +gmyth_settings_set_backend_port (GMythSettings *gmyth_settings, gint new_port) +{ + gmyth_settings->backend_port = new_port; +} + + +static void +fill_settings_data(GMythSettings *gmyth_settings, char* line) +{ + gchar** str_splited; + + GString *gstr_splited; + gstr_splited = g_string_new(""); + str_splited = g_strsplit (line, "=", -1); + + if(!(strcmp(str_splited[0], "hostname"))){ + g_string_assign(gstr_splited, str_splited[1]); + gmyth_settings_set_backend_hostname(gmyth_settings, gstr_splited); + } + else if (!(strcmp(str_splited[0], "dbname"))){ + g_string_assign(gstr_splited, str_splited[1]); + gmyth_settings_set_dbname(gmyth_settings, gstr_splited); + } + else if (!(strcmp(str_splited[0], "username"))){ + g_string_assign(gstr_splited, str_splited[1]); + gmyth_settings_set_username(gmyth_settings, gstr_splited); + } + else if (!(strcmp(str_splited[0], "password"))){ + g_string_assign(gstr_splited, str_splited[1]); + gmyth_settings_set_password(gmyth_settings, gstr_splited); + } + else if (!(strcmp(str_splited[0], "backend_port"))){ + gmyth_settings_set_backend_port(gmyth_settings, atoi(str_splited[1])); + } +} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_settings.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_settings.h Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,103 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_settings.h + * + * @brief

This component contains functions acessing and modifying + * user and program settings. + * + * The standard settings file is created in the user home folder, in the + * file ~/.mmyth/settings.dat. + * + * 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_SETTINGS_H__ +#define __GMYTH_SETTINGS_H__ + +#include + +//#include +//#include +//#include +//#include +//#include +//#include + +G_BEGIN_DECLS + +#define GMYTH_SETTINGS_TYPE (gmyth_settings_get_type ()) +#define GMYTH_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SETTINGS_TYPE, GMythSettings)) +#define GMYTH_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SETTINGS_TYPE, GMythSettingsClass)) +#define IS_GMYTH_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SETTINGS_TYPE)) +#define IS_GMYTH_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SETTINGS_TYPE)) +#define GMYTH_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_SETTINGS_TYPE, GMythSettingsClass)) + + +typedef struct _GMythSettings GMythSettings; +typedef struct _GMythSettingsClass GMythSettingsClass; + +struct _GMythSettingsClass +{ + GObjectClass parent_class; + + /* callbacks */ + /* no one for now */ +}; + +struct _GMythSettings +{ + GObject parent; + + GString *settings_file; + + GString *backend_hostname; + int backend_port; + + GString *mysql_dbname; + GString *mysql_username; + GString *mysql_password; + // FIXME: Why do we need database_type? Do we intend to support other dbs? + GString *database_type; +}; + + +GType gmyth_settings_get_type (void); + +GMythSettings* gmyth_settings_new (void); +gboolean gmyth_settings_load_from_file (GMythSettings *gmyth_settings, GString *filename); +gboolean gmyth_settings_load (GMythSettings *msettings); +gboolean gmyth_settings_save (GMythSettings *gmyth_settings); + +GString* gmyth_settings_get_backend_hostname (GMythSettings *gmyth_settings); +void gmyth_settings_set_backend_hostname (GMythSettings *gmyth_settings, GString *new_hostname); +GString* gmyth_settings_get_username (GMythSettings *gmyth_settings); +void gmyth_settings_set_username (GMythSettings *gmyth_settings, GString *new_username); +GString* gmyth_settings_get_password (GMythSettings *gmyth_settings); +void gmyth_settings_set_password (GMythSettings *gmyth_settings, GString *new_password); +GString* gmyth_settings_get_dbname (GMythSettings *gmyth_settings); +void gmyth_settings_set_dbname (GMythSettings *gmyth_settings, GString *new_dbname); +int gmyth_settings_get_backend_port (GMythSettings *gmyth_settings); +void gmyth_settings_set_backend_port (GMythSettings *gmyth_settings, gint new_port); + + +G_END_DECLS + +#endif /* __GMYTH_SETTINGS_H__ */ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_socket.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_socket.c Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,708 @@ +/** + * 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 + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "gmyth_socket.h" +#include "gmyth_stringlist.h" +#include "gmyth_context.h" + +#define BUFLEN 512 +#define MYTH_SEPARATOR "[]:[]" +#define MYTH_PROTOCOL_FIELD_SIZE 8 + +static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + +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) +{ +} + +/** 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( gchar *addr, gint port, struct addrinfo **addrInfo ) +{ + struct addrinfo hints; + gchar *portStr = g_strnfill( 32, ' ' ); + gint errorn = EADDRNOTAVAIL; + + memset( &hints, 0, sizeof(hints) ); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + /* hints.ai_flags = AI_NUMERICHOST; */ + if ( port != -1 ) + sprintf(portStr, "%d", port); + else + portStr = NULL; + + g_debug( "[%s] Address: %s, port: %s\n", __FUNCTION__, addr, portStr ); + if ( ( errorn = getaddrinfo(addr, portStr, &hints, addrInfo) ) != 0 ) { + g_printerr( "[%s] Socket ERROR: %s\n", __FUNCTION__, gai_strerror(errorn) ); + } + + return errorn; +} + +/** This function retrieves the local hostname of the + * client machine. + * + * @return GString* get local hostname. + */ +GString * +gmyth_socket_get_local_hostname( ) +{ + GString *str = g_string_new(""); + + gchar *localhostname = g_strnfill( 1024, ' ' ); + gchar *localaddr = g_strdup( "127.0.0.1" ); + + gboolean found_addr = FALSE; + + struct addrinfo* addr_info_data = NULL, *addr_info0 = NULL; + + struct sockaddr_in* sa = NULL; + + g_static_mutex_lock( &mutex ); + + gethostname(localhostname, 1024); + + gint err = gmyth_socket_toaddrinfo( localhostname, -1, &addr_info_data ); + + 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_print( "[%s] localaddr = %s\n", __FUNCTION__, localaddr ); + + if ( localaddr != NULL && ( g_strrstr( localaddr, "127" ) == NULL ) ) { + g_print( "[%s] Trying the address %s (err = %d).\n", + __FUNCTION__, localaddr, err ); + g_print( "[%s] Found local address %s!\n", __FUNCTION__, localaddr ); + str = g_string_assign( str, g_strdup( localaddr ) ); + found_addr = TRUE; + break; + } + addr_info0 = addr_info0->ai_next; + }; + + if ( found_addr == FALSE ) { + g_warning("[%s] Could not determine the local hostname address. Setting to %s\n", + __FUNCTION__, localaddr ); + if ( localaddr != NULL ) + str = g_string_assign( str, localaddr ); + else + str = g_string_assign( str, "127.0.0.1" ); + } + + g_static_mutex_unlock( &mutex ); + + if (localhostname!=NULL) + g_free( localhostname ); + + return str; +} + +static void +gmyth_socket_dispose (GObject *object) +{ + GMythSocket *gmyth_socket = GMYTH_SOCKET(object); + + gmyth_socket_close_connection (gmyth_socket); + /* disconnect socket */ + 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->sd_io_ch = NULL; + + gmyth_socket->hostname = g_strdup(""); + + gmyth_socket->port = 6543; + + return gmyth_socket; +} + +/** 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, + gchar *hostname, gint port) +{ + struct addrinfo *addr_info_data = NULL, *addr_info0 = NULL; + gint ret_code = -1; + gint errno; + gboolean ret = TRUE; + + if ( hostname == NULL ) + g_printerr ( "[%s] Invalid hostname parameter!\n", __FUNCTION__ ); + + errno = gmyth_socket_toaddrinfo( hostname, port, &addr_info_data ); + + g_return_val_if_fail( addr_info_data != NULL, FALSE ); + + /* store hostname and port number */ + (*gmyth_socket)->hostname = g_strdup( hostname ); + (*gmyth_socket)->port = port; + + for ( addr_info0 = addr_info_data; addr_info0; addr_info0 = addr_info_data->ai_next ) { + + struct sockaddr_in *sa = (struct sockaddr_in*)addr_info0->ai_addr; + /* init socket descriptor */ + (*gmyth_socket)->sd = socket( addr_info0->ai_family, addr_info0->ai_socktype, + addr_info0->ai_protocol ); + + if ( (*gmyth_socket)->sd < 0 ) + continue; + + g_debug( "[%s] hostname = %s, sock_fd = %d, addr = %s, addr_len = %d, \ + ai_family = %d, ai_protocol = %d\n", + __FUNCTION__, hostname, (*gmyth_socket)->sd, inet_ntoa( sa->sin_addr ), + addr_info0->ai_addrlen, addr_info0->ai_family, addr_info0->ai_protocol ); + + if ( ( ret_code = connect( (*gmyth_socket)->sd, (struct sockaddr *)addr_info0->ai_addr, + addr_info0->ai_addrlen ) ) < 0 ) + { + g_printerr( "[%s] Error connecting to backend!\n", __FUNCTION__ ); + if ( ret_code == ETIMEDOUT ) + g_printerr( "[%s]\tBackend host unreachable!\n", __FUNCTION__ ); + + g_printerr( "ERROR: %s\n", gai_strerror(ret_code) ); + continue; + } + + /* only will be reached if none of the error above occurred */ + break; + + } + + (*gmyth_socket)->sd_io_ch = g_io_channel_unix_new( (*gmyth_socket)->sd ); + + //if (addr_info_data != NULL ) + //freeaddrinfo( addr_info_data ); + + ret = ( ret_code == 0 ) ? TRUE : FALSE ; + + 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 ) { + g_warning ("[%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 ) ) { + g_warning ("[%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; + + if( command == NULL || ( command->len <= 0 ) ) { + g_warning ("[%s] Invalid NULL command parameter!\n", __FUNCTION__); + ret = FALSE; + goto done; + } + + g_static_mutex_lock( &mutex ); + g_debug ("[%s] Sending command to backend: %s\n", __FUNCTION__, command->str); + + /* + io_cond = g_io_channel_get_buffer_condition( gmyth_socket->sd_io_ch ); + + if ( ( io_cond & G_IO_IN ) == 0 ) { + g_warning ("[%s] IO channel is not able to send data!\n", __FUNCTION__); + ret = FALSE; + goto done; + } + */ + + buffer = g_strnfill( BUFLEN, ' ' ); + snprintf( buffer, MYTH_PROTOCOL_FIELD_SIZE+1, "%-8d", command->len); + g_print( "[%s] buffer = [%s]\n", __FUNCTION__, buffer ); + + command = g_string_prepend(command, buffer); + + g_print( "[%s] command = [%s]\n", __FUNCTION__, command->str ); + + /* 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 ) ) { + g_warning ("[%s] Error while writing to socket", __FUNCTION__); + ret = FALSE; + } else if ( bytes_written < command->len ) { + g_warning ("[%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 ) ) + { + g_warning ("[%s] Some problem occurred when sending data to the socket\n", __FUNCTION__); + + ret = TRUE; + } + + g_static_mutex_unlock( &mutex ); +done: + if ( error != NULL ) { + g_printerr( "[%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 + * backend connection. + */ +gboolean +gmyth_socket_connect_to_backend (GMythSocket *gmyth_socket, + gchar *hostname_backend, int port, gboolean blocking_client) +{ + if (!gmyth_socket_connect (&gmyth_socket, hostname_backend, port)) { + g_warning ("[%s] Could not open socket to backend machine", __FUNCTION__); + 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(); + + g_string_printf(base_str, "ANN %s %s 0", + (blocking_client ? "Playback" : "Monitor"), + hostname->str); + + g_debug ("[%s] Connection command sent to backend: %s", __FUNCTION__, base_str->str); + + gmyth_socket_send_command (gmyth_socket, base_str); + result = gmyth_socket_receive_response(gmyth_socket); + + if (result != NULL) { + g_debug ("[%s] Response received from backend: %s", __FUNCTION__, result->str); + g_string_free (result, TRUE); + } + + g_string_free (hostname, TRUE); + g_string_free (base_str, TRUE); + + return TRUE; + } else { + g_warning ("[%s] GMythSocket could not connect to the backend", __FUNCTION__); + return FALSE; + } + +} + +/** Closes the socket connection to the backend. + * + * @param gmyth_socket The GMythSocket instance. + */ +void +gmyth_socket_close_connection (GMythSocket *gmyth_socket) +{ + close (gmyth_socket->sd); +} + + +/** 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 + */ +gboolean +gmyth_socket_check_protocol_version_number (GMythSocket *gmyth_socket, gint mythtv_version) +{ + GString *response; + GString *payload; + gchar *new_version = g_strdup(""); + gboolean res = TRUE; + +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) { + g_warning ("[%s] Check protocol version error! Not answered!", __FUNCTION__); + res = FALSE; + goto done; + } + + res = g_str_has_prefix (response->str, "ACCEPT"); + if (!res) { + g_warning ("[%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 ) { + new_version = g_strrstr( response->str, "]" ); + if (new_version!=NULL) { + ++new_version; /* skip ']' character */ + if ( new_version != NULL ) { + g_print( "[%s] got MythTV version = %s\n", __FUNCTION__, new_version ); + mythtv_version = g_ascii_strtoull( g_strdup( 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 ); + /* g_free( new_version ); */ + goto try_new_version; + } + } + } + } + +done: + if ( payload != NULL ) + g_string_free (payload, TRUE); + if ( response != NULL ) + g_string_free (response, TRUE); +// if (new_version!=NULL) +// g_free( new_version ); + + return res; +} + +/** 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_check_protocol_version_number( gmyth_socket, MYTHTV_VERSION_DEFAULT ); +} + +/** 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; + GIOCondition io_cond; + + g_return_val_if_fail( gmyth_socket != NULL, NULL ); + + /* verify if the input (read) buffer is ready to receive data */ + + buffer = g_strnfill( BUFLEN, ' ' ); + + g_static_mutex_lock( &mutex ); + + io_status = g_io_channel_read_chars( gmyth_socket->sd_io_ch, buffer, MYTH_PROTOCOL_FIELD_SIZE, &bytes_read, &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 ); + + g_print ( "[%s] Bytes read = %d\n", __FUNCTION__, bytes_read ); + + if( (io_status == G_IO_STATUS_ERROR) || (bytes_read <= 0) ) { + g_warning ("[%s] Error in mythprotocol response from backend\n", __FUNCTION__); + str = NULL; + //return NULL; + } else { + + 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 ) { + + snprintf( buffer, MYTH_PROTOCOL_FIELD_SIZE+1, "%-8s", g_strdup(buffer)); + g_print( "[%s] buffer = [%s]\n", __FUNCTION__, buffer ); + + /* removes trailing whitespace */ + buffer = g_strstrip( buffer ); + + len = (gint)strtoull ( buffer, NULL, 10 ); + + bytes_read = 0; + io_status = g_io_channel_read_chars( gmyth_socket->sd_io_ch, buffer, len, &bytes_read, &error ); + buffer[bytes_read] = '\0'; + } + } + + g_static_mutex_unlock( &mutex ); + + g_debug ("[%s] Response received from backend: {%s}\n", __FUNCTION__, buffer); + + if ( ( bytes_read != len ) || ( io_status == G_IO_STATUS_ERROR ) ) + str = NULL; + else + str = g_string_new( buffer ); + + if ( buffer != NULL ) + g_free( buffer ); + + if ( error != NULL ) { + g_printerr( "[%s] Error found receiving response from the IO channel: (%d, %s)\n", __FUNCTION__, error->code, error->message ); + str = NULL; + g_error_free( error ); + } + + 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; + GPtrArray *ptr_array; + gchar *str_array; + + g_static_mutex_lock( &mutex ); + + ptr_array = g_ptr_array_sized_new(g_list_length(str_list->glist)); + + g_print( "[%s] Number of parameters = %d\n", __FUNCTION__, 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); + } + 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_static_mutex_unlock( &mutex ); + + // Sends message to backend + // TODO: implement looping to send remaining data, and add timeout testing! + gmyth_socket_send_command(gmyth_socket, g_string_new(str_array)); + + g_free (str_array); + 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; + gchar **str_array; + gint i; + + response = gmyth_socket_receive_response(gmyth_socket); + g_static_mutex_lock( &mutex ); + + gmyth_string_list_clear_all (str_list); + str_array = g_strsplit (response->str, MYTH_SEPARATOR, -1); + + for (i=0; i< g_strv_length (str_array); i++) { + gmyth_string_list_append_string (str_list, g_string_new (str_array[i])); + } + g_static_mutex_unlock( &mutex ); + + g_string_free (response, TRUE); + g_strfreev (str_array); + + 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 b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_socket.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_socket.h Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,116 @@ +/** + * 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_CAST ((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; + + /* socket descriptor */ + int sd; + GIOChannel *sd_io_ch; + + gchar *hostname; + gint port; +}; + + +GType gmyth_socket_get_type (void); + +GMythSocket * gmyth_socket_new (void); + +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); +int gmyth_socket_sendreceive_stringlist (GMythSocket * gmyth_socket, + GMythStringList *str_list); + +gboolean gmyth_socket_connect (GMythSocket **gmyth_socket, + gchar *hostname, gint port); +gboolean gmyth_socket_connect_to_backend (GMythSocket *gmyth_socket, + gchar *hostname_backend, int port, + gboolean blocking_client); + +GString * gmyth_socket_get_local_hostname (void); + +void gmyth_socket_close_connection (GMythSocket *gmyth_socket); + +gboolean gmyth_socket_check_protocol_version (GMythSocket *gmyth_socket); +gboolean gmyth_socket_check_protocol_version_number (GMythSocket *gmyth_socket, + gint mythtv_version); + +gboolean gmyth_socket_write_stringlist(GMythSocket *gmyth_socket, + GMythStringList* str_list); +int gmyth_socket_read_stringlist(GMythSocket *gmyth_socket, + GMythStringList* str_list); + +G_END_DECLS + +#endif /* __GMYTH_SOCKET_H__ */ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_stringlist.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_stringlist.c Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,272 @@ +/** + * 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 + */ + +#include "gmyth_stringlist.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); + + if (gmyth_string_list->glist) + 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 *tmp_str = g_string_new (""); + + g_string_printf (tmp_str, "%d", value); + + gmyth_string_list_append_string (strlist, tmp_str); + + return tmp_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_str = g_string_new (""); + + glong l2 = ( (guint64)(value) & 0xffffffffLL ); + glong l1 = ( ((guint64)(value) >> 32 ) & 0xffffffffLL ); + + /* high order part of guint64 value */ + g_string_printf (tmp_str, "%ld", l1); + + g_debug( "[%s] uint64 (high) = %s\n", __FUNCTION__, tmp_str->str ); + + gmyth_string_list_append_string (strlist, tmp_str); + + /* low order part of guint64 value */ + g_string_printf (tmp_str, "%ld", l2); + + g_debug( "[%s] uint64 (low) = %s\n", __FUNCTION__, tmp_str->str ); + + gmyth_string_list_append_string (strlist, tmp_str); + + return tmp_str; +} + +/** 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); + + g_return_val_if_fail( tmp_str != NULL, NULL ); + + gmyth_string_list_append_string (strlist, 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 ); + + strlist->glist = g_list_append (strlist->glist, value); + + 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); + + g_return_val_if_fail( tmp_str != NULL && tmp_str->str != NULL, 0 ); + + return (gint) ( 0x00000000ffffffffL & g_ascii_strtoull ( tmp_str->str, NULL, 0 ) ); +} + +/** 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; + + 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); + + glong l1 = (glong)g_ascii_strtoull (tmp_str1->str, NULL, 10); + glong l2 = (glong)g_ascii_strtoull (tmp_str2->str, NULL, 10); + + ret_value = ((guint64)(l2) & 0xffffffffLL) | ((guint64)(l1) << 32); + + g_debug( "[%s] returning uint64 value = %llu\n", __FUNCTION__, ret_value ); + + return ret_value; +} + +/** Gets a string from the string list at the given position. + * + * @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 ) +{ + if (!strlist || !(strlist->glist)) { + g_warning ("%s received Null arguments", __FUNCTION__); + return NULL; + } + + return (GString *) g_list_nth_data (strlist->glist, index); +} + +/** 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_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 ) +{ + g_return_val_if_fail( strlist != NULL && strlist->glist != NULL, 0 ); + + return g_list_length (strlist->glist); +} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_stringlist.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_stringlist.h Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,97 @@ +/** + * 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_CAST ((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 gmyth_string_list_clear_all (GMythStringList *strlist); +int gmyth_string_list_length (GMythStringList *strlist); + +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_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); +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 b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_tvchain.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_tvchain.c Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,355 @@ +/** + * 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 + */ + +#include +#include +#include +#include + +#include "gmyth_epg.h" +#include "gmyth_tvchain.h" +#include "gmyth_util.h" +#include "gmyth_query.h" +#include "gmyth_scheduler.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); + +G_DEFINE_TYPE(GMythTVChain, gmyth_tvchain, G_TYPE_OBJECT) + +static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + +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 = 0; +} + +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->tvchain_list != NULL ) { + g_list_free( tvchain->tvchain_list ); + tvchain->tvchain_list = NULL; + } + + if ( tvchain->cur_chanid != NULL ) { + g_string_free( tvchain->cur_chanid, TRUE ); + tvchain->cur_chanid = 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. + */ +void +gmyth_tvchain_initialize (GMythTVChain *tvchain, GString *hostname) +{ + if (tvchain->tvchain_id == NULL) { + GString *isodate; + time_t cur_time; + + time(&cur_time); + isodate = gmyth_util_time_to_isoformat (cur_time); + + tvchain->tvchain_id = g_string_sized_new(7 + hostname->len + isodate->len); + g_string_printf(tvchain->tvchain_id, + "live-%s-%s", hostname->str, isodate->str); + + g_print("tv_chain_id: %s\n", tvchain->tvchain_id->str); + + g_string_free(isodate, TRUE); + + } else { + g_warning ("[%s] TVchain already initialized", __FUNCTION__); + } +} + +/** 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 g_string_new (tvchain->tvchain_id->str); +} + +/** 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; + GMythQuery *gmyth_query; + gboolean ret = TRUE; + + GString *stmt_str; + + g_static_mutex_lock( &mutex ); + + guint prev_size = g_list_length (tvchain->tvchain_list); + + g_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)) { + g_warning ("[%s] Could not connect to db", __FUNCTION__); + g_static_mutex_unlock( &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 (g_string_new ((gchar*)msql_row[1])); + entry->endtime = gmyth_util_string_to_time (g_string_new (msql_row[2])); + entry->discontinuity = atoi (msql_row[3]) != 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; + + tvchain->tvchain_list = g_list_append (tvchain->tvchain_list, entry); + } + } else { + g_warning ("gmyth_tvchain_reload_all query error!\n"); + g_static_mutex_unlock( &mutex ); + + ret = FALSE; + goto done; + } + + g_static_mutex_unlock( &mutex ); + + tvchain->cur_pos = gmyth_tvchain_program_is_at (tvchain, tvchain->cur_chanid, tvchain->cur_startts); + + 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)) { + g_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; +} + +/** 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. + */ +int +gmyth_tvchain_program_is_at (GMythTVChain *tvchain, GString *chanid, time_t startts) +{ + int count = 0; + struct LiveTVChainEntry *entry; + GList *tmp_list = tvchain->tvchain_list; + + g_static_mutex_lock( &mutex ); + + for (; tmp_list; 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_static_mutex_unlock( &mutex ); + return count; + } + } + g_static_mutex_unlock( &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, int 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, int index) +{ + struct LiveTVChainEntry* chain_entry = NULL; + + g_return_val_if_fail( tvchain != NULL && tvchain->tvchain_list != NULL, NULL ); + + g_static_mutex_lock( &mutex ); + + int size = g_list_length (tvchain->tvchain_list); + int 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_static_mutex_unlock( &mutex ); + + if ( chain_entry != NULL ) { + g_debug ("[%s] Got TV Chain entry at %d.\n", __FUNCTION__, new_index ); + + } else { + g_warning ("[%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 progrma 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) { + g_warning ("gmyth_tvchain_entry_to_program() received NULL argument"); + return NULL; + } + + GMythScheduler *scheduler = gmyth_scheduler_new (); + + gmyth_scheduler_connect( scheduler ); + 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 { + g_warning ("tvchain_entry_to_program(%s, %ld) failed!", entry->chanid->str, entry->starttime); + } + + return proginfo; +} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_tvchain.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_tvchain.h Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,105 @@ +/** + * 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" + +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_CAST ((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; + + time_t starttime; + time_t 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; + + time_t cur_startts; + GString *cur_chanid; + int cur_pos; +}; + + +GType gmyth_tvchain_get_type (void); + +void gmyth_tvchain_initialize (GMythTVChain *tvchain, + GString *hostname); +gboolean gmyth_tvchain_reload_all (GMythTVChain *tvchain); +GString* gmyth_tvchain_get_id (GMythTVChain *tvchain); +int gmyth_tvchain_program_is_at (GMythTVChain *tvchain, + GString *chanid, time_t 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); + +G_END_DECLS + +#endif /*LIVETVCHAIN_H_*/ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_tvplayer.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_tvplayer.c Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,684 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_tvplayer.c + * + * @brief

This component provides playback of the remote A/V using + * GStreamer. + * + * 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 + */ + +#include "gmyth_tvplayer.h" + +#include + +#include "gmyth_context.h" +#include "gmyth_remote_util.h" + +typedef struct _GstPlayerWindowStateChange +{ + GstElement *play; + GstState old_state, new_state; + GMythTVPlayer *tvplayer; +} GstPlayerWindowStateChange; + +typedef struct _GstPlayerWindowTagFound +{ + GstElement *play; + GstTagList *taglist; + GMythTVPlayer *tvplayer; +} GstPlayerWindowTagFound; + +/* +static gboolean idle_state (gpointer data); +*/ +static gboolean bus_call (GstBus * bus, GstMessage * msg, gpointer data); + +static void gmyth_tvplayer_class_init (GMythTVPlayerClass *klass); +static void gmyth_tvplayer_init (GMythTVPlayer *object); + +static void gmyth_tvplayer_dispose (GObject *object); +static void gmyth_tvplayer_finalize (GObject *object); + +G_DEFINE_TYPE(GMythTVPlayer, gmyth_tvplayer, G_TYPE_OBJECT) + +static gboolean gmyth_tvplayer_create_pipeline (GMythTVPlayer* tvplayer); +static void new_pad_cb (GstElement *element, + GstPad *pad, gpointer data); + +static gboolean expose_cb (GtkWidget * widget, + GdkEventExpose * event, + gpointer user_data); + +static void +gmyth_tvplayer_class_init (GMythTVPlayerClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gmyth_tvplayer_dispose; + gobject_class->finalize = gmyth_tvplayer_finalize; +} + +static void +new_pad_cb (GstElement *element, GstPad *pad, gpointer data) +{ + GMythTVPlayer *tvplayer = GMYTH_TVPLAYER (data); + GstPadLinkReturn ret; + char *s; + + s = gst_caps_to_string (pad->caps); + + if ( s[0] == 'a') { + ret = gst_pad_link (pad, gst_element_get_pad (tvplayer->audioqueue, "sink")); + } else { + ret = gst_pad_link (pad, gst_element_get_pad (tvplayer->videoqueue, "sink")); + } + + g_free(s); +} + +static gboolean +expose_cb (GtkWidget * widget, GdkEventExpose * event, gpointer user_data) +{ + GMythTVPlayer *tvplayer = GMYTH_TVPLAYER (user_data); + + if (tvplayer && tvplayer->videow) { + gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (tvplayer->gst_videosink), + GDK_WINDOW_XWINDOW (widget->window)); + return TRUE; + } + + g_warning ("GMythTVPlayer expose called before setting video window\n"); + + return FALSE; +} + +static void +gmyth_tvplayer_init (GMythTVPlayer *tvplayer) +{ + tvplayer->gst_pipeline = NULL; + tvplayer->gst_source = NULL; + tvplayer->gst_videodec = NULL; + tvplayer->gst_videosink = NULL; + tvplayer->videoqueue = NULL; + tvplayer->audioqueue = NULL; + + /* GTKWidget for rendering the video */ + tvplayer->videow = NULL; + tvplayer->expose_handler = 0; + + tvplayer->backend_hostname = NULL; + tvplayer->backend_port = 0; + tvplayer->local_hostname = NULL; + + tvplayer->remote_encoder = NULL; + tvplayer->tvchain = NULL; + tvplayer->proginfo = NULL; +} + +static void +gmyth_tvplayer_dispose (GObject *object) +{ + + G_OBJECT_CLASS (gmyth_tvplayer_parent_class)->dispose (object); +} + +static void +gmyth_tvplayer_finalize (GObject *object) +{ + g_signal_handlers_destroy (object); + + GMythTVPlayer *tvplayer = GMYTH_TVPLAYER (object); + + g_debug ("[%s] Finalizing tvplayer", __FUNCTION__); + + if (tvplayer->videow != NULL) { + if (g_signal_handler_is_connected (tvplayer->videow, + tvplayer->expose_handler)) { + g_signal_handler_disconnect (tvplayer->videow, + tvplayer->expose_handler); + } + g_object_unref (tvplayer->videow); + } + + if ( tvplayer->remote_encoder != NULL ) + g_object_unref (tvplayer->remote_encoder); + if ( tvplayer->tvchain != NULL ) + g_object_unref (tvplayer->tvchain); + if ( tvplayer->proginfo != NULL ) + g_object_unref (tvplayer->proginfo); + + // Release Gstreamer elements + if ( tvplayer->gst_pipeline != NULL ) + g_object_unref (tvplayer->gst_pipeline); + if ( tvplayer->gst_source != NULL ) + g_object_unref (tvplayer->gst_source); + if ( tvplayer->gst_videodec != NULL ) + g_object_unref (tvplayer->gst_videodec); + if ( tvplayer->gst_videosink != NULL ) + g_object_unref (tvplayer->gst_videosink); + if ( tvplayer->videoqueue != NULL ) + g_object_unref (tvplayer->videoqueue); + if ( tvplayer->audioqueue != NULL ) + g_object_unref (tvplayer->audioqueue); + + G_OBJECT_CLASS (gmyth_tvplayer_parent_class)->finalize (object); +} + +/** Creates a new instance of GMythTVPlayer. + * + * @return a new instance of GMythTVPlayer. + */ +GMythTVPlayer * +gmyth_tvplayer_new () +{ + GMythTVPlayer *tvplayer = + GMYTH_TVPLAYER (g_object_new(GMYTH_TVPLAYER_TYPE, NULL)); + + return tvplayer; +} + +/** Initializes the tv player. + * + * @param tvplayer the object instance. + * @return gboolean TRUE if the pipeline was created + * successfully, FALSE otherwise. + */ +gboolean +gmyth_tvplayer_initialize (GMythTVPlayer *tvplayer) +{ + + if (!gmyth_tvplayer_create_pipeline (tvplayer)) { + g_warning ("[%s] Error while creating pipeline. TV Player not initialized", __FUNCTION__); + return FALSE; + } else { + g_debug ("[%s] GStreamer pipeline created", __FUNCTION__); + } + + return TRUE; +} + +/** Creates the GStreamer pipeline used by the player. + * + * @param tvplayer the object instance. + * @return gboolean TRUE if the pipeline was created + * successfully, FALSE otherwise. + */ +static gboolean +gmyth_tvplayer_create_pipeline (GMythTVPlayer* tvplayer) +{ + GstElement *pipeline; + GstElement *source, *parser; + GstElement *videodec, *videosink; +#ifndef MAEMO_PLATFORM + GstElement *audiodec, *audioconv; +#endif + GstElement *audiosink; + GstElement *videoqueue, *audioqueue; + + g_debug ("GMythTVPlayer: Setting the Gstreamer pipeline\n"); + + pipeline = gst_pipeline_new ("video-player"); + source = gst_element_factory_make ("mythtvsrc", "myth-source"); + parser = gst_element_factory_make ("ffdemux_nuv", "nuv-demux"); + + /* Gstreamer Video elements */ + videoqueue = gst_element_factory_make ("queue", "video-queue"); + videodec = gst_element_factory_make ("ffdec_mpeg4", "video-decoder"); +#ifdef MAEMO_PLATFORM + videosink = gst_element_factory_make ("sdlvideosink", "image-output"); +#else + videosink = gst_element_factory_make ("xvimagesink", "image-output"); +#endif + + /* Gstreamer Audio elements */ + audioqueue = gst_element_factory_make ("queue", "audio-queue"); +#ifdef MAEMO_PLATFORM + audiosink = gst_element_factory_make ("dspmp3sink", "audio-output"); +#else + audiodec = gst_element_factory_make ("ffdec_mp3", "audio-decoder"); + audioconv = gst_element_factory_make ("audioconvert", "audio-converter"); + audiosink = gst_element_factory_make ("alsasink", "audio-output"); +#endif + + if (!(pipeline && source && parser && videodec && videosink) || + !(videoqueue && audioqueue && audiosink)) { + /* FIXME: hanlde the error correctly */ + /* video_alignment is not being created (below) + and is causing problems to the ui */ + + tvplayer->gst_pipeline = NULL; + tvplayer->gst_videodec = NULL; + tvplayer->gst_videosink = NULL; + + g_warning ("GstElement creation error!\n"); + return FALSE; + } + +#ifndef MAEMO_PLATFORM + if (!(audiodec && audioconv)) { + g_warning ("GstElement for audio stream creation error!"); + return FALSE; + } +#endif + + + tvplayer->gst_pipeline = pipeline; + tvplayer->gst_source = source; + tvplayer->gst_videodec = videodec; + tvplayer->gst_videosink = videosink; + g_object_ref (tvplayer->gst_pipeline); + g_object_ref (tvplayer->gst_source); + g_object_ref (tvplayer->gst_videodec); + g_object_ref (tvplayer->gst_videosink); + + tvplayer->videoqueue = videoqueue; + tvplayer->audioqueue = audioqueue; + g_object_ref (tvplayer->videoqueue); + g_object_ref (tvplayer->audioqueue); + + g_object_set (G_OBJECT (videosink), "sync", TRUE, NULL); + g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL); + + gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (tvplayer->gst_pipeline)), + bus_call, tvplayer); + + gst_bin_add_many (GST_BIN (pipeline), source, parser, videoqueue, + videodec, videosink, audioqueue, audiodec, audioconv, audiosink, NULL); + + { +// GstCaps *rtpcaps = gst_caps_new_simple ("application/x-rtp", NULL); +// gst_element_link_filtered(source, parser, rtpcaps); + } + + gst_element_link (source, parser); + gst_element_link_many (videoqueue, videodec, videosink, NULL); + gst_element_link_many (audioqueue, audiodec, audioconv, audiosink, NULL); + + g_signal_connect (parser, "pad-added", G_CALLBACK (new_pad_cb), tvplayer); + + return TRUE; +} + +/** Configures the backend and the tv player + * for playing the recorded content A/V. + * + * FIXME: Change filename to program info or other structure about the recorded + * + * @param tvplayer the object instance. + * @param filename the file uri of the recorded content to be played. + * @return TRUE if successfull, FALSE if any error happens. + */ +gboolean +gmyth_tvplayer_record_setup (GMythTVPlayer *tvplayer, gchar *filename) +{ + GMythSettings *msettings = gmyth_context_get_settings(); + + // FIXME: we should receive the uri instead of filename + GString *hostname = gmyth_settings_get_backend_hostname (msettings); + int port = gmyth_settings_get_backend_port(msettings); + + GString *fullpath = g_string_new ("myth://"); + g_string_append_printf (fullpath, "%s:%d/%s", hostname->str, port, filename); + + tvplayer->is_livetv = FALSE; + + g_debug ("[%s] Setting record uri to gstreamer pipeline to %s", __FUNCTION__, fullpath->str); + + g_object_set (G_OBJECT (tvplayer->gst_source), "location", + fullpath->str, NULL); + + return TRUE; +} + +/** Configures the backend and the tv player + * for playing the live tv. + * + * @param tvplayer the object instance. + * @return TRUE if successfull, FALSE if any error happens. + */ +gboolean +gmyth_tvplayer_livetv_setup (GMythTVPlayer *tvplayer) +{ + GMythSettings *msettings = gmyth_context_get_settings (); + gboolean res = TRUE; + + res = gmyth_context_check_connection(); + if (!res) { + g_warning ("[%s] LiveTV can not connect to backend", __FUNCTION__); + res = FALSE; + goto error; + } + + tvplayer->backend_hostname = gmyth_settings_get_backend_hostname(msettings); + tvplayer->backend_port = gmyth_settings_get_backend_port (msettings); + + tvplayer->local_hostname = g_string_new(""); + gmyth_context_get_local_hostname (tvplayer->local_hostname); + + if ( tvplayer->local_hostname == NULL ) { + res = FALSE; + goto error; + } + + // Gets the remote encoder num + tvplayer->remote_encoder = remote_request_next_free_recorder (-1); + + if ( tvplayer->remote_encoder == NULL ) { + g_warning ("[%s] None remote encoder available", __FUNCTION__); + res = FALSE; + goto error; + } + + // Creates livetv chain handler + tvplayer->tvchain = GMYTH_TVCHAIN ( g_object_new(GMYTH_TVCHAIN_TYPE, NULL) ); + gmyth_tvchain_initialize ( tvplayer->tvchain, tvplayer->local_hostname ); + + if ( tvplayer->tvchain == NULL || tvplayer->tvchain->tvchain_id == NULL ) { + res = FALSE; + goto error; + } + + // Init remote encoder. Opens its control socket. + res = gmyth_remote_encoder_setup(tvplayer->remote_encoder); + if ( !res ) { + g_warning ("[%s] Fail while setting remote encoder\n", __FUNCTION__); + res = FALSE; + goto error; + } + // Spawn live tv. Uses the socket to send mythprotocol data to start livetv in the backend (remotelly) + res = gmyth_remote_encoder_spawntv ( tvplayer->remote_encoder, + gmyth_tvchain_get_id(tvplayer->tvchain) ); + if (!res) { + g_warning ("[%s] Fail while spawn tv\n", __FUNCTION__); + res = FALSE; + goto error; + } + + // Reload all TV chain from Mysql database. + gmyth_tvchain_reload_all (tvplayer->tvchain); + + if ( tvplayer->tvchain == NULL ) { + res = FALSE; + goto error; + } + + // Get program info from database using chanid and starttime + tvplayer->proginfo = gmyth_tvchain_get_program_at (tvplayer->tvchain, -1); + if ( tvplayer->proginfo == NULL ) { + g_warning ("[%s] LiveTV not successfully started.\n", __FUNCTION__ ); + res = FALSE; + goto error; + } else { + g_debug ("[%s] MythLiveTV: All requests to backend to start TV were OK.\n", __FUNCTION__ ); + } + + return res; + +error: + if ( tvplayer->backend_hostname != NULL ) { + g_string_free( tvplayer->backend_hostname, TRUE ); + res = FALSE; + } + + if ( tvplayer->local_hostname != NULL ) { + g_string_free( tvplayer->local_hostname, TRUE ); + res = FALSE; + } + + if ( tvplayer->remote_encoder != NULL ) { + g_object_unref (tvplayer->remote_encoder); + tvplayer->remote_encoder = NULL; + } + + if ( tvplayer->tvchain != NULL ) { + g_object_unref (tvplayer->tvchain); + tvplayer->tvchain = NULL; + } + + if ( tvplayer->proginfo != NULL ) { + g_object_unref (tvplayer->proginfo); + tvplayer->proginfo = NULL; + } + + return res; + +} + +/** Sets the GTK video widget for the tv player. + * + * @param tvplayer the object instance. + * @param videow the GTK video window. + * @return TRUE if successfull, FALSE if any error happens. + */ +gboolean +gmyth_tvplayer_set_widget (GMythTVPlayer *tvplayer, GtkWidget *videow) +{ + tvplayer->videow = videow; + g_object_ref (videow); + + g_debug ("[%s] Setting widget for tv player render", __FUNCTION__); + + tvplayer->expose_handler = g_signal_connect (tvplayer->videow, "expose-event", + G_CALLBACK (expose_cb), tvplayer); + + //g_signal_connect(miptv_ui->videow, "size_request", G_CALLBACK(cb_preferred_video_size), miptv_ui); + + return TRUE; +} + +static gboolean +bus_call (GstBus * bus, GstMessage * msg, gpointer data) +{ + //GMythTVPlayer *tvplayer = GMYTH_TVPLAYER ( data ); + //GMainLoop *loop = tvplayer->loop; + + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_EOS: + printf ("End of stream\n"); + //g_idle_add ((GSourceFunc) idle_eos, data); + gst_element_set_state ( GST_ELEMENT (GST_MESSAGE_SRC (msg)), GST_STATE_NULL ); + gst_element_set_locked_state ( GST_ELEMENT (GST_MESSAGE_SRC (msg)), FALSE ); + break; + case GST_MESSAGE_ERROR: + { + gchar *debug; + GError *err; + + gst_message_parse_error (msg, &err, &debug); + g_free (debug); + + printf ("Error: %s\n", err->message); + g_error_free (err); + + //g_main_loop_quit (loop); + } + break; + default: + printf (gst_message_type_get_name (GST_MESSAGE_TYPE (msg))); + printf ("\n"); + break; + } + + return TRUE; +} + + +#if 0 +static gboolean +idle_state (gpointer data) +{ + GstPlayerWindowStateChange *st = data; + + if (st->old_state == GST_STATE_PLAYING) { + if (st->miptv_ui->idle_id != 0) { + g_source_remove (st->miptv_ui->idle_id); + st->miptv_ui->idle_id = 0; + } + } + else if (st->new_state == GST_STATE_PLAYING) { + if (st->miptv_ui->idle_id != 0) + g_source_remove (st->miptv_ui->idle_id); + + st->miptv_ui->idle_id = g_idle_add (cb_iterate, st->miptv_ui); + } + + /* new movie loaded? */ + if (st->old_state == GST_STATE_READY && st->new_state > GST_STATE_READY) { + + /* gboolean have_video = FALSE; */ + + gtk_widget_show (st->miptv_ui->videow); + + gtk_window_resize (GTK_WINDOW (st->miptv_ui->main_window), 1, 1); + + } + + /* discarded movie? */ + if (st->old_state > GST_STATE_READY && st->new_state == GST_STATE_READY) { + + if (st->miptv_ui->tagcache) { + gst_tag_list_free (st->miptv_ui->tagcache); + st->miptv_ui->tagcache = NULL; + } + } + + gst_object_unref (GST_OBJECT (st->play)); + //g_object_unref (G_OBJECT (st->win)); + g_free (st); + + /* once */ + return FALSE; +} + +#endif + +/** Stops playing the current A/V. + * + * FIXME: How to proceed differently between livetv + * and recorded content? + * + * @param tvplayer the object instance. + * @return void + */ +void +gmyth_tvplayer_stop_playing (GMythTVPlayer *tvplayer) +{ + g_debug ("[%s] Setting gstreamer pipeline state to NULL", __FUNCTION__); + + gst_element_set_state (tvplayer->gst_pipeline, GST_STATE_NULL); + + if (tvplayer->is_livetv) { + if (!gmyth_remote_encoder_stop_livetv (tvplayer->remote_encoder)) { + g_warning ("[%s] Error while stoping remote encoder", __FUNCTION__); + } + } +} + +/** Queries if the tvplayer is active playing A/V content. + * + * @param tvplayer the object instance. + * @return TRUE if the tvplayer is active, FALSE otherwise. + */ +gboolean +gmyth_tvplayer_is_playing (GMythTVPlayer *tvplayer) +{ + return (GST_STATE (tvplayer->gst_pipeline) == GST_STATE_PLAYING); +} + +/** Static function that sets the tvplayer state to PLAYING. + * + * @param tvplayer the object instance. + * @return TRUE if the tvplayer is active, FALSE otherwise. + */ +static gboolean +idle_play (gpointer data) +{ + GMythTVPlayer *tvplayer = GMYTH_TVPLAYER (data); + + g_debug ("GMythTVPlayer: Setting pipeline state to PLAYING\n"); + + gst_element_set_state (tvplayer->gst_pipeline, GST_STATE_PLAYING); + + return FALSE; +} + +/** Start playing A/V with the tvplayer attributes. + * + * @param tvplayer the object instance. + */ +void +gmyth_tvplayer_start_playing (GMythTVPlayer *tvplayer) +{ + + // FIXME: Move this to livetv_setup?? + if (tvplayer->is_livetv) { + + #if 0 + if (!tvplayer || !(tvplayer->proginfo) || !(tvplayer->local_hostname) + || !(tvplayer->gst_source)) { + g_warning ("GMythtvPlayer not ready to start playing\n"); + } + + if (!(tvplayer->proginfo->pathname)) { + g_warning ("[%s] Playback url is null, could not play the myth content", __FUNCTION__); + return; + } + + g_debug ("GMythTVPlayer: Start playing %s", tvplayer->proginfo->pathname->str); +#endif + g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-live", + TRUE, NULL); +#if 0 + if ( tvplayer->tvchain != NULL ) { + GString *str_chainid = gmyth_tvchain_get_id(tvplayer->tvchain); + g_print( "[%s]\tCHAIN ID: %s\n", __FUNCTION__, str_chainid->str ); + + g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-live-chainid", + g_strdup( str_chainid->str ), NULL); + if ( str_chainid!=NULL) + g_string_free( str_chainid, FALSE ); + } + + if ( tvplayer->remote_encoder != NULL ) + g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-live-id", + tvplayer->remote_encoder->recorder_num, NULL ); + g_debug ("[%s] Setting location to %s", __FUNCTION__, + tvplayer->proginfo->pathname->str); + + /* Sets the gstreamer properties acording to the service access address */ + g_object_set (G_OBJECT (tvplayer->gst_source), "location", + tvplayer->proginfo->pathname->str, NULL); +#endif + } + + g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-version", + MYTHTV_VERSION_DEFAULT, NULL); + + g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-debug", + TRUE, NULL); + + g_idle_add (idle_play, tvplayer); + +} + diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_tvplayer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_tvplayer.h Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,112 @@ +/** + * GMyth Library + * + * @file gmyth/gmyth_tvplayer.h + * + * @brief

This component provides playback of the remote A/V using + * GStreamer. + * + * 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_TVPLAYER_H_ +#define GMYTH_TVPLAYER_H_ + +#include +#include + +/* GStreamer includes */ +#include +#include + +#include "gmyth_remote_encoder.h" +#include "gmyth_tvchain.h" +#include "gmyth_common.h" + +G_BEGIN_DECLS + +#define GMYTH_TVPLAYER_TYPE (gmyth_tvplayer_get_type ()) +#define GMYTH_TVPLAYER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TVPLAYER_TYPE, GMythTVPlayer)) +#define GMYTH_TVPLAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVPLAYER_TYPE, GMythTVPlayerClass)) +#define IS_GMYTH_TVPLAYER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TVPLAYER_TYPE)) +#define IS_GMYTH_TVPLAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVPLAYER_TYPE)) +#define GMYTH_TVPLAYER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_TVPLAYER_TYPE, GMythTVPlayerClass)) + + +typedef struct _GMythTVPlayer GMythTVPlayer; +typedef struct _GMythTVPlayerClass GMythTVPlayerClass; + +struct _GMythTVPlayerClass +{ + GObjectClass parent_class; + + /* callbacks */ + /* no one for now */ +}; + +struct _GMythTVPlayer +{ + GObject parent; + + GstElement *gst_pipeline; + GstElement *gst_source; + GstElement *gst_videodec; + GstElement *gst_videosink; + GstElement *videoqueue; + GstElement *audioqueue; + + gulong expose_handler; +// GMainLoop *loop; + + GtkWidget *videow; + + /* Backend connection related variables */ + GString *backend_hostname; + gint backend_port; + GString *local_hostname; + + GMythRemoteEncoder *remote_encoder; + GMythTVChain *tvchain; + GMythProgramInfo *proginfo; + + gboolean is_livetv; +}; + + +GType gmyth_tvplayer_get_type (void); + +GMythTVPlayer* gmyth_tvplayer_new (); +gboolean gmyth_tvplayer_initialize (GMythTVPlayer *tvplayer); + +void gmyth_tvplayer_start_playing (GMythTVPlayer *tvplayer); +void gmyth_tvplayer_stop_playing (GMythTVPlayer *tvplayer); + +gboolean gmyth_tvplayer_set_widget (GMythTVPlayer *tvplayer, + GtkWidget *videow); + +gboolean gmyth_tvplayer_is_playing (GMythTVPlayer *tvplayer); + +gboolean gmyth_tvplayer_record_setup (GMythTVPlayer *tvplayer, + gchar *filename); +gboolean gmyth_tvplayer_livetv_setup (GMythTVPlayer *tvplayer); + +G_END_DECLS + +#endif /*GMYTH_TVPLAYER_H_*/ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_util.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_util.c Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,138 @@ +/** +* GMyth Library +* +* @file gmyth/gmyth_util.c +* +* @brief

This component provides utility functions. +* +* 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 +*/ + +#include "gmyth_util.h" + +#include +#include + +/** 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) { + g_warning ("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); + + 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] = ' '; + + 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) +{ + int year, month, day, hour, min, sec; + + g_debug( "[%s] time_str = %s.\n", __FUNCTION__, time_str != NULL ? time_str->str : "[time string is NULL!]" ); + + if (sscanf (time_str->str, "%04d-%02d-%02d %02d:%02d:%02d", + &year, &month, &day, &hour, &min, &sec) < 3) { /* At least date */ + g_warning ("GMythUtil: isoformat_to_time converter error!\n"); + return 0; + } else { + struct tm tm_time; + 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); + } +} + +/** Decodes a long long variable from the string list + * format of the myhtprotocol. + * + * @param strlist the string list of mythprotocol values + * @param offset the list node offset of the long long variable + * @return guint64 the long long converted value + */ +guint64 +gmyth_util_decode_long_long(GMythStringList *strlist, guint offset) +{ + + guint64 ret_value = 0LL; + + g_return_val_if_fail( strlist != NULL, ret_value ); + + if ( offset < gmyth_string_list_length( strlist )) + g_printerr( "[%s] Offset is lower than the Stringlist (offset = %d)!\n", + __FUNCTION__, offset ); + + g_return_val_if_fail( offset < gmyth_string_list_length( strlist ), ret_value ); + + gint l1 = gmyth_string_list_get_int( strlist, offset ); + gint l2 = gmyth_string_list_get_int( strlist, offset + 1 ); + + ret_value = ((guint64)(l2) & 0xffffffffLL) | ((guint64)(l1) << 32); + + return ret_value; + +} + diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gmyth_util.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmyth/src/gmyth_util.h Thu Sep 28 15:41:06 2006 +0100 @@ -0,0 +1,45 @@ +/** +* GMyth Library +* +* @file gmyth/gmyth_util.h +* +* @brief

This component provides utility functions. +* +* 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_UTIL_H_ +#define GMYTH_UTIL_H_ + +#include +#include + +#include "gmyth_stringlist.h" + +G_BEGIN_DECLS + +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); +guint64 gmyth_util_decode_long_long (GMythStringList *strlist, + guint offset); +G_END_DECLS + +#endif /*GMYTH_UTIL_H_*/ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gui/Makefile.am --- a/gmyth/src/gui/Makefile.am Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -noinst_LTLIBRARIES = libmmythgui.la - -libmmythgui_la_SOURCES = \ - mmyth_ui.c \ - mmyth_uicommon.c \ - mmyth_epg_grid_view.c \ - mmyth_epg_grid_widget.c \ - mmyth_recordui.c \ - mmyth_uisettings.c \ - mmyth_schedulerui.c - -libmmythgui_la_CFLAGS = \ - $(GTK_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(GST_CFLAGS) \ - $(MYSQL_CFLAGS) \ - -I$(top_srcdir)/src/libgmyth \ - -I$(top_srcdir)/src \ - -DDATA_DIR=\""$(pkgdatadir)"\" \ - -DPIX_DIR=\""$(pkgdatadir)/pixmaps/"\" \ - -DICON_DIR=\""$(datadir)/pixmaps/"\" \ - -g3 -O0 - -libmmythgui_la_LIBADD = \ - $(top_srcdir)/src/libgmyth/libgmyth.la - -libmmythgui_la_LDFLAGS = -export-dynamic - - diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gui/mmyth_epg_grid_view.c --- a/gmyth/src/gui/mmyth_epg_grid_view.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,213 +0,0 @@ -#include -#include -#include -#include -#include - -#include "mmyth_epg_grid_view.h" -#include "mmyth_epg_grid_widget.h" - -/* Service genre */ -#define GENRE_MIN 0 -#define GENRE_MAX 10 -#define GENRE_UNDEFINED 0 -#define GENRE_MOVIE 1 -#define GENRE_NEWS 2 -#define GENRE_SHOW 3 -#define GENRE_SPORTS 4 -#define GENRE_CHILDREN 5 -#define GENRE_MUSIC 6 -#define GENRE_CULTURE 7 -#define GENRE_SOCIAL 8 -#define GENRE_EDUCATION 9 -#define GENRE_LEISURE 10 - -#define NRO_HOURS 3 - -/* Function prototypes*/ -static void update_service_details(MMythEpgGridWidget *object, - gpointer arg1, gpointer user_data); -static gboolean key_press_epg_grid_view(GtkWidget * widget, - GdkEventKey * event, - gpointer user_data); - -static GtkWidget *mmyth_epg_grid_widget = NULL; - -/* is a GtkEventBox */ -static GtkWidget *program_details_area = NULL; -static GtkWidget *details_main_hbox = NULL; -static GtkWidget *details_vbox = NULL; -static GtkWidget *details_logo_vbox = NULL; - -/* update signal callback from MMythEpgGridWidget */ -static void -update_service_details(MMythEpgGridWidget *object, gpointer arg1, gpointer user_data) -{ - g_return_if_fail(arg1 != NULL); - - EpgGridItem *epg_grid_item = (EpgGridItem *) arg1; - - gchar sel_prog_desc[100] = ""; - gchar time_buffer[50]; - - /* FIXME: get first content from content_list*/ - GMythProgramInfo *proginfo = (GMythProgramInfo *) epg_grid_item->proginfo; - - if(proginfo) { - GString *prog_name = proginfo->title; - GString *service_name = proginfo->chanid; - - if(details_vbox != NULL) - gtk_container_remove (GTK_CONTAINER (details_main_hbox), details_vbox); - - /* update service description */ - strcat(sel_prog_desc, service_name->str); - strcat(sel_prog_desc, ""); - - GtkWidget *fst_line_lbl = gtk_label_new(NULL); - gtk_misc_set_alignment (GTK_MISC(fst_line_lbl), 0.0, 0.0); - gtk_label_set_markup(GTK_LABEL(fst_line_lbl), sel_prog_desc); - - /* freeing char[] */ - sel_prog_desc[0] = 0; - strcat(sel_prog_desc, "\t"); - strcat(sel_prog_desc, prog_name->str); - - struct tm loctime_start, loctime_end; - - // Convert it to local time representation. - /* FIXME: conversion from time to localtime is different - in different machines */ - long int schedule_start_time = proginfo->startts; - long int schedule_end_time = proginfo->endts; - - if (localtime_r(&schedule_start_time, &loctime_start) == NULL) { - g_warning ("localtime_r error in mmyth_epg_grid_view!\n"); - } - - #if 0 - fprintf (stderr, asctime (loctime_start)); - #endif - - strftime (time_buffer, 100, " %H:%M - ", &loctime_start); - strcat(sel_prog_desc, time_buffer ); - - if (localtime_r(&schedule_end_time, &loctime_end) == NULL) { - g_warning ("localtime_r error in mmyth_epg_grid_view!\n"); - } - - #if 0 - fprintf (stderr, asctime (loctime_end)); - #endif - - strftime (time_buffer, 100, "%H:%M\n", &loctime_end); - strcat(sel_prog_desc, time_buffer ); - - GtkWidget *snd_line_lbl = gtk_label_new(NULL); - gtk_misc_set_alignment (GTK_MISC(snd_line_lbl), 0.0, 0.0); - gtk_label_set_markup(GTK_LABEL(snd_line_lbl), sel_prog_desc); - - // add the current selected program description to the label - details_vbox = gtk_vbox_new(FALSE, 0); - GtkWidget *fst_line_hbox = gtk_hbox_new(FALSE, 0); - - gtk_box_pack_start (GTK_BOX (fst_line_hbox), - fst_line_lbl, FALSE, FALSE, 6); - gtk_box_pack_start (GTK_BOX (details_vbox), - fst_line_hbox, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (details_vbox), - snd_line_lbl, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (details_main_hbox), - details_vbox, FALSE, FALSE, 0); - - gtk_widget_show_all(details_main_hbox); - } -} - -/* Callback for hardware keys */ -static gboolean -key_press_epg_grid_view(GtkWidget * widget, - GdkEventKey * event, gpointer user_data) -{ - MMythEpgGridWidget *mmyth_epg_grid_widget = (MMythEpgGridWidget *) user_data; - - return mmyth_epg_grid_widget_key_press(mmyth_epg_grid_widget, widget, event); -} - -GtkWidget * -epg_grid_view_new (MMythUi* mmyth_ui) -{ - GtkWidget *scrolled_window; - scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - - gtk_widget_modify_bg(scrolled_window, GTK_STATE_NORMAL, &main_bg_color); - - GtkWidget *main_vbox = gtk_vbox_new (FALSE, 0); - //gtk_container_set_border_width(main_vbox, 4); - - GtkWidget *details_event_box = gtk_event_box_new(); - gtk_widget_modify_bg(details_event_box, GTK_STATE_NORMAL, &main_bg_color); - - program_details_area = gtk_vbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (details_event_box), - program_details_area); - gtk_container_set_border_width(GTK_CONTAINER (program_details_area), 4); - - details_main_hbox = gtk_hbox_new (FALSE, 10); - - gtk_box_pack_start (GTK_BOX (program_details_area), - details_main_hbox, FALSE, FALSE, 0); - - details_logo_vbox = gtk_vbox_new (FALSE, 0); - - GtkWidget *details_desc_vbox = gtk_vbox_new (FALSE, 0); - - gtk_box_pack_start (GTK_BOX (details_main_hbox), - details_desc_vbox, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (details_main_hbox), - details_logo_vbox, FALSE, FALSE, 0); - - gtk_widget_set_size_request (program_details_area, -1, 120); - - mmyth_epg_grid_widget = mmyth_epg_grid_widget_new(); - g_signal_connect(mmyth_epg_grid_widget, "selection_updated", - G_CALLBACK (update_service_details), NULL); - - /* select by default the first service */ - /* depends on mount services */ - if (MMYTH_EPG_GRID_WIDGET(mmyth_epg_grid_widget)->epg_view_model) { - GList *fst_service = (GList *) - MMYTH_EPG_GRID_WIDGET(mmyth_epg_grid_widget)->epg_view_model->data; - mmyth_epg_grid_widget_update_service(MMYTH_EPG_GRID_WIDGET(mmyth_epg_grid_widget), - fst_service); - } - - gtk_box_pack_start (GTK_BOX (main_vbox), - details_event_box, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (main_vbox), - gtk_hseparator_new(), FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (main_vbox), - mmyth_epg_grid_widget, FALSE, FALSE, 0); - - gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), - main_vbox); - - /* Add hardware button listener to application */ - g_signal_connect(mmyth_ui->main_window, "key_press_event", - G_CALLBACK (key_press_epg_grid_view), mmyth_epg_grid_widget); - - gtk_widget_show_all (scrolled_window); - - return scrolled_window; -} - -/* -DVBHScheduleEvent * -mmyth_epg_grid_view_get_selected_schedule() -{ - return mmyth_epg_grid_get_selected_schedule - (MMYTH_EPG_GRID_WIDGET(mmyth_epg_grid_widget)); -} -*/ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gui/mmyth_epg_grid_view.h --- a/gmyth/src/gui/mmyth_epg_grid_view.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -#ifndef MMYTH_ESG_GRID_VIEW_H_ -#define MMYTH_ESG_GRID_VIEW_H_ - -#include "mmyth_ui.h" - -GtkWidget *epg_grid_view_new(MMythUi * mmyth_ui); - -#endif /* MMYTH_ESG_GRID_VIEW_H_ */ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gui/mmyth_epg_grid_widget.c --- a/gmyth/src/gui/mmyth_epg_grid_widget.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,622 +0,0 @@ -#include -#include -#include - -#include "mmyth_uicommon.h" -#include "mmyth_epg_grid_widget.h" - -#include "gmyth_util.h" -#include "gmyth_epg.h" - -#define PIXELS_HOUR 105 -#define PROGRAM_SEPARATION 2 - -enum { - SELECTION_UPDATED_SIGNAL, - LAST_SIGNAL -}; - -struct _MMythEpgGridWidgetPrivate { - /* private widget components */ - GtkWidget *epg_channels_vbox; - GtkWidget *epg_programs_vbox; - - GHashTable *service_model_hash; - - /* guidegrid attributes */ - gboolean show_favorites; - gint current_start_channel_id; - - time_t current_start_time; - time_t current_end_time; - - guint selected_channel_index; - - /* GList of ProgramInfo for each Channel */ - GList * program_list[MAX_DISPLAY_CHANS]; - GList * channel_list; - - GMythEPG *mmyth_epg; - - gint DISPLAY_CHANS; -}; - -static void mmyth_epg_grid_widget_class_init (MMythEpgGridWidgetClass *klass); -static void mmyth_epg_grid_widget_init (MMythEpgGridWidget *object); -static void mmyth_epg_grid_widget_private_init (MMythEpgGridWidgetPrivate *private); -static void mmyth_epg_grid_widget_mount_services (MMythEpgGridWidget *object, - int start_time, int end_time); -static void mmyth_epg_grid_widget_mount_header (MMythEpgGridWidget *object); -static void mmyth_epg_grid_widget_clicked (GtkWidget* widget, - GdkEventExpose *event, - gpointer data); -static GtkWidget *create_event_box_lbl (gchar *str, int width, - const GdkColor *bg_color, - const GdkColor *fg_color); - -static void mmyth_epg_grid_widget_fill_programinfos(MMythEpgGridWidgetPrivate *private); -static void mmyth_epg_grid_widget_fill_program_row_infos( - MMythEpgGridWidgetPrivate *private, - unsigned int chanNum, unsigned int row); - -static gint mmyth_epg_grid_widget_signals[LAST_SIGNAL] = { 0 }; - -G_DEFINE_TYPE(MMythEpgGridWidget, mmyth_epg_grid_widget, GTK_TYPE_EVENT_BOX) - -static void -mmyth_epg_grid_widget_class_init (MMythEpgGridWidgetClass *klass) -{ - g_type_class_add_private (klass, sizeof (MMythEpgGridWidgetPrivate)); - - mmyth_epg_grid_widget_signals[SELECTION_UPDATED_SIGNAL] = g_signal_new ( - "selection_updated", - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, - 1, - G_TYPE_POINTER); -} - -static void -mmyth_epg_grid_widget_private_init (MMythEpgGridWidgetPrivate *private) -{ - time_t cur_time; - - g_return_if_fail(private != NULL); - - private->epg_channels_vbox = NULL; - private->epg_programs_vbox = NULL; - private->service_model_hash = NULL; - - private->show_favorites = FALSE; - private->current_start_channel_id = -1; - - /* Selected the first diplayable channel initially */ - private->selected_channel_index = 0; - - /* TODO fix the current start/end time */ - private->current_start_time = time(&cur_time); - private->current_end_time = time(&cur_time) + 10800; - - private->DISPLAY_CHANS = MAX_DISPLAY_CHANS; - - // TODO: Close the epg and unref it in dispose call - private->mmyth_epg = gmyth_epg_new (); - if (!gmyth_epg_connect (private->mmyth_epg)) { - g_warning ("[%s] Could not connect mysql handler to db", __FUNCTION__); - g_object_unref (private->mmyth_epg); - private->mmyth_epg = NULL; - } -} - -static void -mmyth_epg_grid_widget_init (MMythEpgGridWidget *mmyth_epg_grid_widget) -{ - MMythEpgGridWidgetPrivate *private = - MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(mmyth_epg_grid_widget); - - /* init private fields */ - mmyth_epg_grid_widget_private_init(private); - - mmyth_epg_grid_widget->epg_view_model = NULL; - mmyth_epg_grid_widget->selected_grid_item = NULL; - - GtkWidget *epg_event_box = GTK_WIDGET(mmyth_epg_grid_widget); - gtk_widget_modify_bg(epg_event_box, GTK_STATE_NORMAL, &main_bg_color); - gtk_widget_set_size_request (epg_event_box, 0, 125); - - GtkWidget *epg_main_hbox = gtk_hbox_new (FALSE, 10); - gtk_container_set_border_width(GTK_CONTAINER (epg_main_hbox), 10); - - gtk_container_add (GTK_CONTAINER (epg_event_box), - epg_main_hbox); - - /* channels vbox */ - GtkWidget *epg_channels_vbox = gtk_vbox_new (FALSE, 3); - private->epg_channels_vbox = epg_channels_vbox; - - /* programs vbox */ - GtkWidget *epg_programs_vbox = gtk_vbox_new (FALSE, 3); - private->epg_programs_vbox = epg_programs_vbox; - - /* packing start */ - gtk_box_pack_start (GTK_BOX (epg_main_hbox), - epg_channels_vbox, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (epg_main_hbox), - epg_programs_vbox, FALSE, FALSE, 0); - - /* table header (first line) */ - mmyth_epg_grid_widget_mount_header(mmyth_epg_grid_widget); - - /* service programs */ - /* mount service programs with current time */ - mmyth_epg_grid_widget_mount_services(mmyth_epg_grid_widget, - private->current_start_time, - private->current_end_time); -} - -GtkWidget* -mmyth_epg_grid_widget_new () -{ - return GTK_WIDGET ( gtk_type_new (mmyth_epg_grid_widget_get_type ())); -} - -static void -mmyth_epg_grid_widget_mount_services(MMythEpgGridWidget *mmyth_epg_grid_widget, - int start_time, int end_time) -{ - GList *proglist; - GList *channel_list = NULL; - GMythChannelInfo *channel_info; - - int chanid; - MMythEpgGridWidgetPrivate *private = - MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(mmyth_epg_grid_widget); - - // update view_model - /* FIXME shallow free or recursive? */ - if(mmyth_epg_grid_widget->epg_view_model != NULL) { - g_list_free(mmyth_epg_grid_widget->epg_view_model); - mmyth_epg_grid_widget->epg_view_model = NULL; - } - - if(private->service_model_hash != NULL) { - g_hash_table_destroy(private->service_model_hash); - } - - private->service_model_hash = g_hash_table_new(NULL, NULL); - - /* fill program infos from db */ - mmyth_epg_grid_widget_fill_programinfos(private); - - channel_list = private->channel_list; - - /* for each channel get_programs() */ - for (chanid=0; channel_list && - chanid < private->DISPLAY_CHANS; chanid++) { - proglist = (GList *) private->program_list[chanid]; - - channel_info = (GMythChannelInfo *) channel_list->data; - channel_list = g_list_next(channel_list); - - /* Service Title*/ - GString *name = NULL; - if (channel_info->channel_name) - name = g_string_new (channel_info->channel_name->str); - - GdkColor title_bg_color; - title_bg_color.red = 5000; - title_bg_color.green = 9000; - title_bg_color.blue = 40000; - - GdkColor title_fg_color; - title_fg_color.red = 60000; - title_fg_color.green = 60000; - title_fg_color.blue = 60000; - - GtkWidget *event_box_channel = create_event_box_lbl( - name->str, 90, - &title_bg_color, - &title_fg_color); - - gtk_box_pack_start (GTK_BOX (private->epg_channels_vbox), - event_box_channel, FALSE, FALSE, 0); - - GtkWidget *epg_line_hbox = gtk_hbox_new (FALSE, 0); - - GdkColor bg_color; - bg_color.red = 5000; - bg_color.green = 30000; - bg_color.blue = 60000; - - GdkColor fg_color; - fg_color.red = 60000; - fg_color.green = 60000; - fg_color.blue = 60000; - - /* Content parsing */ - GList *epg_grid_list = NULL; - - GMythProgramInfo *proginfo; - int pixel_count = 0; - for (; proglist; proglist = proglist->next) { - proginfo = (GMythProgramInfo *) proglist->data; - - GString *content_name = proginfo->title; - - int initial_time, last_time, duration; - - int schedule_start_time = proginfo->startts; - int schedule_end_time = proginfo->endts; - - initial_time = - (schedule_start_time < start_time) ? start_time : schedule_start_time; - last_time = (schedule_end_time > end_time) ? end_time : schedule_end_time; - duration = last_time - initial_time; - - // Verify program time - #if 0 - g_debug ("ServiceID: %d, ScheduleID: %d\n", service->id, schedule->id); - fprintf (stderr, "program time\nfrom = %d, to = %d\n", - schedule->validFrom, schedule->validTo); - - struct tm loctime; - - /* Convert it to local time representation. */ - if (localtime_r((time_t *)&schedule->validFrom, &loctime) == NULL) { - g_warning ("localtime_r error in mmyth_epg_grid_widget!\n"); - return NULL; - } - fprintf (stderr, asctime (&loctime)); - - if (localtime_r((time_t *)&schedule->validTo, &loctime) == NULL) { - g_warning ("localtime_r error in mmyth_epg_grid_widget!\n"); - return NULL; - } - fprintf (stderr, asctime (&loctime)); - #endif - - /* fprintf(stderr, "duration = %d\n", duration); */ - double duration_hour = duration / (double) 3600.0; - /* fprintf(stderr, "duration_hour = %lf\n", duration_hour); */ - - int size = PIXELS_HOUR * duration_hour; - - /* complete hour */ - /* FIXME: UGLY WRONG HACK TO ALIGN PROGRAM TIME!!!*/ - if(last_time%3600 != 0) { - size -= PROGRAM_SEPARATION; - } - if(initial_time%3600 != 0) { - size -= PROGRAM_SEPARATION; - } - - pixel_count += size + PROGRAM_SEPARATION; - GtkWidget *event_box = create_event_box_lbl(content_name->str, - size, &bg_color, - &fg_color); - gtk_widget_add_events(event_box, - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); - - /* create EpgGridItem */ - EpgGridItem *epg_grid_item = g_new(EpgGridItem, 1); - epg_grid_item->proginfo = proginfo; - epg_grid_item->event_box = event_box; - epg_grid_item->object = mmyth_epg_grid_widget; - - epg_grid_list = g_list_prepend(epg_grid_list, (gpointer) epg_grid_item); - - gtk_box_pack_start (GTK_BOX (epg_line_hbox), - event_box, FALSE, FALSE, PROGRAM_SEPARATION); - - g_signal_connect (G_OBJECT (event_box), "button-press-event", - G_CALLBACK (mmyth_epg_grid_widget_clicked), - (gpointer*) epg_grid_list); - } -#if 0 - printf("chaind = %d!!!!" chanid);fflush(stdout); -#endif - - if(!epg_grid_list) { - /* No programs for current channel */ - /* FIXME: size HARDCODED */ - GtkWidget *event_box = create_event_box_lbl("No program list available", - PIXELS_HOUR * 3, &bg_color, - &fg_color); - gtk_widget_add_events(event_box, - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); - - /* create EpgGridItem */ - EpgGridItem *epg_grid_item = g_new(EpgGridItem, 1); - epg_grid_item->proginfo = NULL; - epg_grid_item->event_box = event_box; - epg_grid_item->object = mmyth_epg_grid_widget; - - epg_grid_list = g_list_prepend(epg_grid_list, (gpointer) epg_grid_item); - - gtk_box_pack_start (GTK_BOX (epg_line_hbox), - event_box, FALSE, FALSE, PROGRAM_SEPARATION); - - g_signal_connect (G_OBJECT (event_box), "button-press-event", - G_CALLBACK (mmyth_epg_grid_widget_clicked), - (gpointer*) epg_grid_list); - } - - epg_grid_list = g_list_reverse(epg_grid_list); - mmyth_epg_grid_widget->epg_view_model = - g_list_append(mmyth_epg_grid_widget->epg_view_model, epg_grid_list); - - gtk_box_pack_start (GTK_BOX (private->epg_programs_vbox), - epg_line_hbox, FALSE, FALSE, 0); - } -} - -static void -mmyth_epg_grid_widget_mount_header(MMythEpgGridWidget *mmyth_epg_grid_widget) -{ - MMythEpgGridWidgetPrivate *private = - MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(mmyth_epg_grid_widget); - - struct tm hour_tm; - const gchar name_title[] = "Today"; - GtkWidget * lbl_title = gtk_label_new(name_title); - - gtk_misc_set_alignment (GTK_MISC(lbl_title), 0.0, 0.5); - - gtk_box_pack_start (GTK_BOX (private->epg_channels_vbox), - lbl_title, FALSE, FALSE, 0); - - /* hours title line */ - GtkWidget *epg_programs_hours_hbox = gtk_hbox_new (TRUE, 0); - - if (localtime_r((time_t *)&private->current_start_time, &hour_tm) == NULL) { - g_warning ("localtime_r error in mmyth_epg_grid_widget!\n"); - return NULL; - } - - if (hour_tm.tm_min>30) { - hour_tm.tm_min = 30; - } else if (hour_tm.tm_min>0) { - hour_tm.tm_min = 0; - } - - gchar hour1_str[10]; - strftime(hour1_str, 8, "%H:%M", &hour_tm); - GtkWidget * lbl_hour1 = gtk_label_new(hour1_str); - gtk_misc_set_alignment (GTK_MISC(lbl_hour1), 0.0, 0.5); - - hour_tm.tm_hour++; - gchar hour2_str[10]; - strftime(hour2_str, 8, "%H:%M", &hour_tm); - GtkWidget * lbl_hour2 = gtk_label_new(hour2_str); - gtk_misc_set_alignment (GTK_MISC(lbl_hour2), 0.0, 0.5); - - hour_tm.tm_hour++; - gchar hour3_str[10]; - strftime(hour3_str, 8, "%H:%M", &hour_tm); - GtkWidget * lbl_hour3 = gtk_label_new(hour3_str); - gtk_misc_set_alignment (GTK_MISC(lbl_hour3), 0.0, 0.5); - - gtk_box_pack_start (GTK_BOX (epg_programs_hours_hbox), - lbl_hour1, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (epg_programs_hours_hbox), - lbl_hour2, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (epg_programs_hours_hbox), - lbl_hour3, TRUE, TRUE, 0); - - gtk_box_pack_start (GTK_BOX (private->epg_programs_vbox), - epg_programs_hours_hbox, FALSE, FALSE, 0); -} - -/****************************************************************************** - * INTERNAL CALLBACKS FOR STATE CHANGE * - *****************************************************************************/ -static void -mmyth_epg_grid_widget_deselect_service(MMythEpgGridWidget *mmyth_epg_grid_widget) -{ - EpgGridItem *epg_grid_item; - - /* deselect*/ - if(mmyth_epg_grid_widget->selected_grid_item != NULL) { - epg_grid_item = - (EpgGridItem*) mmyth_epg_grid_widget->selected_grid_item->data; - gtk_widget_set_state(GTK_WIDGET(epg_grid_item->event_box), GTK_STATE_NORMAL); - } -} - -static void -mmyth_epg_grid_widget_clicked (GtkWidget* widget, - GdkEventExpose *event, gpointer data) -{ - g_return_if_fail(data != NULL); - - GList *epg_grid_item_list = (GList *) data; - EpgGridItem *epg_grid_item = (EpgGridItem *) epg_grid_item_list->data; - - /* update the selected service */ - mmyth_epg_grid_widget_update_service( epg_grid_item->object, (GList*) data ); -} - -void -mmyth_epg_grid_widget_update_service(MMythEpgGridWidget * object, - GList *selected_grid_list) -{ - g_return_if_fail(object != NULL); - g_return_if_fail(selected_grid_list != NULL); - - EpgGridItem *epg_grid_item = (EpgGridItem *) selected_grid_list->data; - - mmyth_epg_grid_widget_deselect_service(epg_grid_item->object); - - /* updating current selected schedule_item and schedule_list*/ - object->selected_grid_item = selected_grid_list; - - /* set state of the event box */ - gtk_widget_set_state(GTK_WIDGET(epg_grid_item->event_box), GTK_STATE_SELECTED); - /* emit update signal for listeners */ - g_signal_emit(object, - mmyth_epg_grid_widget_signals[SELECTION_UPDATED_SIGNAL], - 0, - (gpointer) epg_grid_item); -} - -static GtkWidget * -create_event_box_lbl(gchar *str, int width, const GdkColor *bg_color, - const GdkColor *fg_color) -{ - GtkWidget *event_box = gtk_event_box_new(); - GtkWidget *lbl = gtk_label_new(str); - gtk_label_set_ellipsize(GTK_LABEL(lbl), PANGO_ELLIPSIZE_END); - - gtk_widget_modify_bg(event_box, GTK_STATE_NORMAL, bg_color); - gtk_widget_modify_fg(lbl, GTK_STATE_NORMAL, fg_color); - - /* selected colors are const*/ - GdkColor selected_bg_color; - selected_bg_color.red = 100; - selected_bg_color.green = 40000; - selected_bg_color.blue = 100; - - GdkColor selected_fg_color; - selected_fg_color.red = 100; - selected_fg_color.green = 100; - selected_fg_color.blue = 100; - - gtk_widget_modify_bg(event_box, GTK_STATE_SELECTED, &selected_bg_color); - gtk_widget_modify_fg(lbl, GTK_STATE_SELECTED, &selected_fg_color); - - gtk_misc_set_alignment (GTK_MISC(lbl), 0.0, 0.5); - gtk_container_add (GTK_CONTAINER (event_box), - lbl); - gtk_widget_set_size_request(event_box, width, -1); - - return event_box; -} - -/****************************************************************************** - * METHODS * - *****************************************************************************/ - -/* Callback for hardware keys */ -gboolean -mmyth_epg_grid_widget_key_press (MMythEpgGridWidget * object, - GtkWidget * widget, GdkEventKey * event) -{ - MMythEpgGridWidgetPrivate *private = - MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(object); - - EpgGridItem *epg_grid_item; - GList *tmp; - - /* List of selected_grid_item */ - GList *selected_view_model; - - gint channel_index; - - if(object->selected_grid_item == NULL) { - g_warning ("No program selected"); - return FALSE; - } - - epg_grid_item = (EpgGridItem*) object->selected_grid_item->data; - - channel_index = private->selected_channel_index; - - switch (event->keyval) { - case GDK_Up: - selected_view_model = g_list_nth( object->epg_view_model, channel_index - 1 ); - if(selected_view_model != NULL) { - private->selected_channel_index = channel_index - 1; - tmp = (GList *) selected_view_model->data; - /* TODO: select a better centralized item - currently is picking the 1st or last item */ - if(g_list_next(object->selected_grid_item) == NULL && - g_list_previous(object->selected_grid_item) != NULL) { - /* in this case the new selected will be the last */ - tmp = g_list_last(tmp); - } - - /* update the selected service */ - mmyth_epg_grid_widget_update_service( object, tmp ); - } - return TRUE; - case GDK_Down: - selected_view_model = g_list_nth( object->epg_view_model, channel_index + 1 ); - if(selected_view_model != NULL) { - private->selected_channel_index = channel_index + 1; - tmp = (GList *) selected_view_model->data; - /* TODO: select a better centralized item - currently is picking the 1st or last item */ - if(g_list_next(object->selected_grid_item) == NULL && - g_list_previous(object->selected_grid_item) != NULL) { - /* in this case the new selected will be the last */ - tmp = g_list_last(tmp); - } - - /* update the selected service */ - mmyth_epg_grid_widget_update_service( object, tmp ); - } - return TRUE; - case GDK_Left: - tmp = g_list_previous( object->selected_grid_item ); - if(tmp != NULL) { - /* update the selected service */ - mmyth_epg_grid_widget_update_service( object, tmp ); - } - return TRUE; - case GDK_Right: - tmp = g_list_next( object->selected_grid_item ); - if(tmp != NULL) { - /* update the selected service */ - mmyth_epg_grid_widget_update_service( object, tmp ); - } - return TRUE; - default: - return TRUE; - } - - return FALSE; -} - -static void -mmyth_epg_grid_widget_fill_programinfos (MMythEpgGridWidgetPrivate *private) -{ - GList *channels_list = NULL; - int y; - - if ((private->mmyth_epg != NULL) && - (gmyth_epg_get_channel_list (private->mmyth_epg, &channels_list) < 0 )) { - private->channel_list = NULL; - return; - } - - private->channel_list = channels_list; - - for (y = 0; y < private->DISPLAY_CHANS && channels_list; y++) { - GMythChannelInfo *channel_info = (GMythChannelInfo *) channels_list->data; - - mmyth_epg_grid_widget_fill_program_row_infos( - private, channel_info->channel_ID, y); - - channels_list = g_list_next (channels_list); - } -} - -static void -mmyth_epg_grid_widget_fill_program_row_infos(MMythEpgGridWidgetPrivate *private, - guint chanNum, guint row) -{ - gint res = gmyth_epg_get_program_list (private->mmyth_epg, - &(private->program_list[row]), - chanNum, private->current_start_time, - private->current_end_time); - - if (res < 0) { - g_warning ("[%s] Error while retrieving epg programs", __FUNCTION__); - } -} - diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gui/mmyth_epg_grid_widget.h --- a/gmyth/src/gui/mmyth_epg_grid_widget.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -#ifndef __MMYTH_EPG_GRID_WIDGET_H__ -#define __MMYTH_EPG_GRID_WIDGET_H__ - -#include -#include -#include -#include - -#include "gmyth_common.h" - -#define MAX_DISPLAY_CHANS 4 - -G_BEGIN_DECLS - -#define MMYTH_EPG_GRID_WIDGET_TYPE (mmyth_epg_grid_widget_get_type ()) -#define MMYTH_EPG_GRID_WIDGET(obj) (GTK_CHECK_CAST ((obj), MMYTH_EPG_GRID_WIDGET_TYPE, MMythEpgGridWidget)) -#define MMYTH_EPG_GRID_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), MMYTH_EPG_GRID_WIDGET_TYPE, MMythEpgGridWidgetClass)) -#define IS_MMYTH_EPG_GRID_WIDGET(obj) (GTK_CHECK_TYPE ((obj), MMYTH_EPG_GRID_WIDGET_TYPE)) -#define IS_MMYTH_EPG_GRID_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), MMYTH_EPG_GRID_WIDGET_TYPE)) -#define MMYTH_EPG_GRID_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MMYTH_EPG_GRID_WIDGET_TYPE, MMythEpgGridWidgetClass)) -#define MMYTH_EPG_GRID_WIDGET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), MMYTH_EPG_GRID_WIDGET_TYPE, MMythEpgGridWidgetPrivate)) - - -typedef struct _MMythEpgGridWidget MMythEpgGridWidget; -typedef struct _MMythEpgGridWidgetClass MMythEpgGridWidgetClass; -typedef struct _MMythEpgGridWidgetPrivate MMythEpgGridWidgetPrivate; - -struct _MMythEpgGridWidgetClass -{ - GtkEventBoxClass parent_class; - - /* callbacks */ - /* no one for now */ -}; - -struct _MMythEpgGridWidget -{ - GtkEventBox event_box; - - /* Selected Widgets Logic*/ - /* List os Service Model in the current view - * the data of this list are GList for the programs - * of each service */ - GList *epg_view_model; - - /* Selected Schedule Item*/ - GList *selected_grid_item; -}; - - -GType mmyth_epg_grid_widget_get_type (void); -GtkWidget* mmyth_epg_grid_widget_new (void); -/*DVBHScheduleEvent* mmyth_epg_grid_get_selected_schedule (MMythEpgGridWidget * object);*/ -void mmyth_epg_grid_widget_update_service (MMythEpgGridWidget * object, - GList *epg_grid_item_node); -gboolean mmyth_epg_grid_widget_key_press (MMythEpgGridWidget * object, - GtkWidget * widget, - GdkEventKey * event); - -typedef struct _EpgGridItem EpgGridItem; - -/* FIXME: auxiliary struct */ -struct _EpgGridItem { - - GMythProgramInfo *proginfo; - GtkWidget *event_box; - - /* for callback purposes */ - MMythEpgGridWidget *object; -}; - -G_END_DECLS - -#endif /* __MMYTH_EPG_GRID_WIDGET_H__ */ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gui/mmyth_recordui.c --- a/gmyth/src/gui/mmyth_recordui.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,332 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mmyth_ui.h" -#include "mmyth_recordui.h" - -/* GMyth library includes */ -#include "gmyth_scheduler.h" -#include "gmyth_util.h" - -enum { - START_DATE_COLUMN = 0, - TITLE_COLUMN, - CHAN_ID_COLUMN, - END_TIME_COLUMN, - RECORD_ID_COLUMN, - BASENAME_COLUMN, - N_COLUMNS -}; - -gboolean -mmyth_recordui_reload_all (MMythRecordUI *recordui) -{ - gboolean res = FALSE; - - res = mmyth_recordui_reload_schedule (recordui); - - res = res & mmyth_recordui_reload_record (recordui); - - - if (!res) - g_warning ("[%s] Error while reloading schedule and recording content", __FUNCTION__); - - return res; -} - -gboolean -mmyth_recordui_reload_schedule (MMythRecordUI *recordui) -{ - gint new_row = 0; - ScheduleInfo *schedule_info; - GList *schedule_list; - GtkTreeIter iter; - GString *start_date_time = NULL; - GString *end_date_time = NULL; - GString *str_aux = g_string_new(""); - gint res; - - gtk_tree_store_clear(recordui->sch_tree_store); - - res = gmyth_scheduler_get_schedule_list(recordui->scheduler, &(schedule_list)); - if (res < 0) { - g_warning ("[%s] Retrieved NULL list of scheduled data from database", - __FUNCTION__); - return FALSE; - } - - for ( ; schedule_list; schedule_list = schedule_list->next) { - schedule_info = (ScheduleInfo*) schedule_list->data; - - gtk_tree_store_insert(recordui->sch_tree_store, &iter, NULL, new_row++); - - start_date_time = gmyth_util_time_to_string(schedule_info->start_time); - end_date_time = gmyth_util_time_to_string(schedule_info->end_time); - - g_string_printf(str_aux, "%d", schedule_info->channel_id); - - gtk_tree_store_set(recordui->sch_tree_store, &iter, - START_DATE_COLUMN, start_date_time->str, - TITLE_COLUMN, schedule_info->title->str, - CHAN_ID_COLUMN, str_aux->str, - END_TIME_COLUMN, end_date_time->str, //It doesn't appear - RECORD_ID_COLUMN, schedule_info->record_id, - -1); //the last line is a hidden item to be used in searching tasks - } - - g_debug ("[%s] %d lines added to schedule list UI", __FUNCTION__, new_row); - - /* free allocated memory */ - if(!start_date_time) - g_string_free(start_date_time, FALSE); - if(!end_date_time) - g_string_free(end_date_time, FALSE); - g_string_free(str_aux, FALSE); - - return TRUE; -} - -gboolean -mmyth_recordui_reload_record (MMythRecordUI *recordui) -{ - gint new_row = 0; - RecordedInfo *recorded_info; - GList *record_list = NULL; - GtkTreeIter iter; - GString *start_date_time = NULL; - GString *end_date_time = NULL; - GString *str_aux = g_string_new(""); - gint res; - - gtk_tree_store_clear(recordui->rec_tree_store); - - res = gmyth_scheduler_get_recorded_list(recordui->scheduler, &record_list); - if (res < 0) { - g_warning ("[%s] Retrieved NULL list of recorded data from database", __FUNCTION__); - return FALSE; - } - - for (; record_list; record_list = record_list->next) { - recorded_info = (RecordedInfo*) record_list->data; - - gtk_tree_store_insert(recordui->rec_tree_store, &iter, NULL, new_row++); - - start_date_time = gmyth_util_time_to_string(recorded_info->start_time); - end_date_time = gmyth_util_time_to_string(recorded_info->end_time); - - g_string_printf(str_aux, "%d", recorded_info->channel_id); - - gtk_tree_store_set(recordui->rec_tree_store, &iter, - START_DATE_COLUMN, start_date_time->str, - TITLE_COLUMN, recorded_info->title->str, - CHAN_ID_COLUMN, str_aux->str, - END_TIME_COLUMN, end_date_time->str, //It doesn't appear - RECORD_ID_COLUMN, recorded_info->record_id, - BASENAME_COLUMN, recorded_info->basename->str, -1); - //the last line is a hidden item to be used in searching tasks - } - - g_debug ("[%s] %d lines added to record list UI", __FUNCTION__, new_row); - - return TRUE; -} - - -MMythRecordUI* -mmyth_recordui_new(void) -{ - MMythRecordUI *recordui = g_new0 (MMythRecordUI, 1); - - recordui->scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (recordui->scrolled_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - - recordui->viewport = gtk_viewport_new (NULL, NULL); - gtk_container_add (GTK_CONTAINER (recordui->scrolled_window), recordui->viewport); - - recordui->notebook = gtk_notebook_new (); - gtk_container_set_border_width (GTK_CONTAINER (recordui->notebook), 1); - gtk_notebook_set_scrollable (GTK_NOTEBOOK (recordui->notebook), TRUE); - gtk_notebook_popup_enable (GTK_NOTEBOOK (recordui->notebook)); - gtk_container_add (GTK_CONTAINER (recordui->viewport), recordui->notebook); - gtk_notebook_popup_disable(GTK_NOTEBOOK (recordui->notebook)); - - /* Schedule tab */ - recordui->sch_scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_container_add (GTK_CONTAINER (recordui->notebook), recordui->sch_scrolled_window); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (recordui->sch_scrolled_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (recordui->sch_scrolled_window), - GTK_SHADOW_IN); - - /* The basename column in the sched_tree_store is not being used*/ - recordui->sch_tree_store = - gtk_tree_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING ); - - recordui->sch_treeview = - gtk_tree_view_new_with_model(GTK_TREE_MODEL(recordui->sch_tree_store)); - gtk_container_add (GTK_CONTAINER (recordui->sch_scrolled_window), - recordui->sch_treeview); - recordui->sch_renderer = gtk_cell_renderer_text_new(); - //g_object_set(G_OBJECT(renderer1), "foreground", "green", "background", "black", NULL); - recordui->sch_column1 = - gtk_tree_view_column_new_with_attributes("Start time", recordui->sch_renderer, - "text", START_DATE_COLUMN, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(recordui->sch_treeview), - recordui->sch_column1); - recordui->sch_column2 = - gtk_tree_view_column_new_with_attributes("Title", recordui->sch_renderer, - "text", TITLE_COLUMN, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(recordui->sch_treeview), - recordui->sch_column2); - recordui->sch_column3 = - gtk_tree_view_column_new_with_attributes("Channel", recordui->sch_renderer, - "text", CHAN_ID_COLUMN, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(recordui->sch_treeview), - recordui->sch_column3); - gtk_tree_view_column_set_resizable(recordui->sch_column1, TRUE); - gtk_tree_view_column_set_resizable(recordui->sch_column2, TRUE); - gtk_tree_view_column_set_resizable(recordui->sch_column3, TRUE); - gtk_tree_view_column_set_reorderable(recordui->sch_column1, TRUE); - gtk_tree_view_column_set_reorderable(recordui->sch_column2, TRUE); - gtk_tree_view_column_set_reorderable(recordui->sch_column3, TRUE); -// recordui->sch_column4 = -// gtk_tree_view_column_new_with_attributes("", recordui->sch_renderer, "text", END_TIME_COLUMN, NULL); -// gtk_tree_view_append_column(GTK_TREE_VIEW(recordui->sch_treeview), -// recordui->sch_column4); - - recordui->sch_label = gtk_label_new (("Schedule")); - gtk_notebook_set_tab_label (GTK_NOTEBOOK (recordui->notebook), - gtk_notebook_get_nth_page ( - GTK_NOTEBOOK (recordui->notebook), 0), - recordui->sch_label); - - // Record items tab - // g_object_set(G_OBJECT(renderer2), "foreground", "blue", NULL); - recordui->rec_scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_container_add (GTK_CONTAINER (recordui->notebook), - recordui->rec_scrolled_window); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (recordui->rec_scrolled_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (recordui->rec_scrolled_window), - GTK_SHADOW_IN); - - recordui->rec_tree_store = - gtk_tree_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING); - recordui->rec_treeview = - gtk_tree_view_new_with_model(GTK_TREE_MODEL(recordui->rec_tree_store)); - gtk_container_add (GTK_CONTAINER (recordui->rec_scrolled_window), - recordui->rec_treeview); - recordui->rec_renderer = gtk_cell_renderer_text_new(); - //g_object_set(G_OBJECT(renderer1), "foreground", "green", "background", "black", NULL); - - recordui->rec_column1 = - gtk_tree_view_column_new_with_attributes("Start time", recordui->rec_renderer, - "text", START_DATE_COLUMN, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(recordui->rec_treeview), - recordui->rec_column1); - recordui->rec_column2 = - gtk_tree_view_column_new_with_attributes("Title", recordui->rec_renderer, - "text", TITLE_COLUMN, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(recordui->rec_treeview), - recordui->rec_column2); - recordui->rec_column3 = - gtk_tree_view_column_new_with_attributes("Channel", recordui->rec_renderer, - "text", CHAN_ID_COLUMN, NULL); - gtk_tree_view_append_column(GTK_TREE_VIEW(recordui->rec_treeview), - recordui->rec_column3); - gtk_tree_view_column_set_resizable(recordui->rec_column1, TRUE); - gtk_tree_view_column_set_resizable(recordui->rec_column2, TRUE); - gtk_tree_view_column_set_resizable(recordui->rec_column3, TRUE); - gtk_tree_view_column_set_reorderable(recordui->rec_column1, TRUE); - gtk_tree_view_column_set_reorderable(recordui->rec_column2, TRUE); - gtk_tree_view_column_set_reorderable(recordui->rec_column3, TRUE); -// recordui->rec_column4 = gtk_tree_view_column_new_with_attributes("", recordui->rec_renderer, "text", END_TIME_COLUMN, NULL); -// gtk_tree_view_append_column(GTK_TREE_VIEW(recordui->rec_treeview), recordui->rec_column4); - - recordui->rec_label = gtk_label_new (("Recorded")); - gtk_notebook_set_tab_label (GTK_NOTEBOOK (recordui->notebook), - gtk_notebook_get_nth_page ( - GTK_NOTEBOOK (recordui->notebook), 1), - recordui->rec_label); - - // Gets the mmyth scheduler manager - recordui->scheduler = gmyth_scheduler_new (); - - /* init connection to the backend */ - gmyth_scheduler_connect (recordui->scheduler); - - return recordui; -} - -void -mmyth_recordui_free (MMythRecordUI *recordui) -{ - // FIXME: Release memory here! - /* close connection to the backend */ - gmyth_scheduler_disconnect (recordui->scheduler); -} - -void -mmyth_recordui_delete_selected (GtkButton *button, MMythRecordUI *recordui) -{ - GtkTreeSelection *selection; - GtkTreeModel *list_store; - GtkTreeIter iter; - int index; - int curr_page = 0; - - curr_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(recordui->notebook)); - - if ( curr_page == 0) { - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(recordui->sch_treeview)); - if (selection != NULL) { - gtk_tree_selection_get_selected(selection, &list_store, &iter); - gtk_tree_model_get(list_store, &iter, RECORD_ID_COLUMN, &index, -1); - gmyth_scheduler_delete_schedule(recordui->scheduler, index); - mmyth_recordui_reload_schedule (recordui); - return; - } - - } else if (curr_page == 1) { - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(recordui->rec_treeview)); - if (selection != NULL) { - gtk_tree_selection_get_selected(selection, &list_store, &iter); - gtk_tree_model_get(list_store, &iter, RECORD_ID_COLUMN, &index, -1); - gmyth_scheduler_delete_recorded(recordui->scheduler, index); - mmyth_recordui_reload_record (recordui); - return; - } - } - - g_warning ("[%s] None element was removed from the list", __FUNCTION__); -} - -/* FIXME: change this function name, it is returning the - * basename_column that represents the nuv filename of - * the recorded content */ -gchar* -mmyth_recordui_get_selected_recorded (MMythRecordUI *recordui) -{ - GtkTreeSelection *selection = NULL; - GtkTreeModel *list_store = NULL; - GtkTreeIter iter; - gchar *path = NULL; - - /* returning nuv filename, basename_column */ - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(recordui->rec_treeview)); - if (gtk_tree_selection_get_selected (selection, &list_store, &iter)) { - gtk_tree_model_get(list_store, &iter, BASENAME_COLUMN, &path, -1); - } - - // FIXME: MOVE THIS TO OTHER PLACE - return path; -} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gui/mmyth_recordui.h --- a/gmyth/src/gui/mmyth_recordui.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -#ifndef MMYTH_RECORD_H_ -#define MMYTH_RECORD_H_ - -#include "gmyth_scheduler.h" - -typedef struct _MMythRecordUI -{ - GtkWidget *scrolled_window; - GtkWidget *viewport; - GtkWidget *notebook; - - GtkWidget *rec_scrolled_window; - GtkWidget *sch_scrolled_window; - GtkWidget *rec_treeview; - GtkWidget *sch_treeview; - GtkWidget *rec_label; - GtkWidget *sch_label; - - GtkTreeViewColumn *rec_column1; - GtkTreeViewColumn *rec_column2; - GtkTreeViewColumn *rec_column3; - GtkTreeViewColumn *rec_column4; - GtkTreeViewColumn *sch_column1; - GtkTreeViewColumn *sch_column2; - GtkTreeViewColumn *sch_column3; - GtkTreeViewColumn *sch_column4; - - GtkCellRenderer *rec_renderer; - GtkCellRenderer *sch_renderer; - - GtkTreeStore *sch_tree_store; - GtkTreeStore *rec_tree_store; - - GMythScheduler *scheduler; - -} MMythRecordUI; - -MMythRecordUI* mmyth_recordui_new(void); -void mmyth_recordui_free (MMythRecordUI *recordui); - -void mmyth_recordui_delete_selected (GtkButton *button, MMythRecordUI *recordui); -gboolean mmyth_recordui_reload_all (MMythRecordUI *recordui); -gboolean mmyth_recordui_reload_schedule (MMythRecordUI *recordui); -gboolean mmyth_recordui_reload_record (MMythRecordUI *recordui); - -gchar* mmyth_recordui_get_selected_recorded (MMythRecordUI *recordui); - -#endif /*MMYTH_RECORD_H_*/ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gui/mmyth_schedulerui.c --- a/gmyth/src/gui/mmyth_schedulerui.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,368 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mmyth_ui.h" -#include "mmyth_uicommon.h" -#include "mmyth_recordui.h" -#include "mmyth_schedulerui.h" - -/* GMyth library includes */ -#include "gmyth_scheduler.h" -#include "gmyth_common.h" -#include "gmyth_epg.h" - -static void run_calendar_dialog (GtkButton *button, gpointer data); - -static void add_channel_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox); -static void add_time_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox); -static void add_date_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox); -static void add_duration_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox); -static void add_frequency_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox); -static void add_title_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox); - -MMythSchedulerUI* -mmyth_schedulerui_new (void) -{ - GtkWidget *scrolledwindow; - GtkWidget *viewport; - GtkWidget *head_hbox; - GtkWidget *fields_vbox; - GtkWidget *hseparator; - GtkWidget *label; - - MMythSchedulerUI *scheduler_ui = g_new0 (MMythSchedulerUI, 1); - - scrolledwindow = gtk_scrolled_window_new (NULL, NULL); - scheduler_ui->main_widget = scrolledwindow; - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - - //Is this needed? - viewport = gtk_viewport_new (NULL, NULL); - gtk_container_add (GTK_CONTAINER (scrolledwindow), viewport); - - //Is this needed? - head_hbox = gtk_hbox_new (FALSE, 0); - gtk_container_add (GTK_CONTAINER (viewport), head_hbox); - - fields_vbox = gtk_vbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (head_hbox), fields_vbox, TRUE, TRUE, 0); - gtk_container_set_border_width (GTK_CONTAINER (fields_vbox), 10); - - label = gtk_label_new_with_mnemonic (("Manual Schedule Recording")); - gtk_box_pack_start (GTK_BOX (fields_vbox), label, FALSE, FALSE, 0); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - - hseparator = gtk_hseparator_new (); - gtk_box_pack_start (GTK_BOX (fields_vbox), hseparator, FALSE, TRUE, 0); - - add_channel_field (scheduler_ui, fields_vbox); - add_time_field (scheduler_ui, fields_vbox); - add_date_field (scheduler_ui, fields_vbox); - add_duration_field (scheduler_ui, fields_vbox); - add_frequency_field (scheduler_ui, fields_vbox); - add_title_field (scheduler_ui, fields_vbox); - - return scheduler_ui; -} - -static void -set_date_from_calendar (GtkCalendar *calendar, gpointer data) -{ - char sched_date[24]; - - MMythSchedulerUI *scheduler_ui = (MMythSchedulerUI*) data; - - // FIXME: Change this, save another value instead of month_temp, day_temp, ... - gtk_calendar_get_date(GTK_CALENDAR(calendar), - &(scheduler_ui->year_temp), &(scheduler_ui->month_temp), &(scheduler_ui->day_temp)); - - sched_date[23]='\0'; - g_sprintf(sched_date, "%04d %02d %02d (yyyy mm dd)", - scheduler_ui->year_temp, scheduler_ui->month_temp+1, scheduler_ui->day_temp); - - gtk_button_set_label(GTK_BUTTON(scheduler_ui->date_button), sched_date); - - gtk_widget_destroy(scheduler_ui->calendar_dialog); - scheduler_ui->calendar_dialog = NULL; - scheduler_ui->calendar = NULL; -} - -//calendar -static void -run_calendar_dialog (GtkButton *button, gpointer data) -{ - - GtkWidget *dialog_vbox; - MMythSchedulerUI *scheduler_ui = (MMythSchedulerUI*) data; - - // calendar_dialog and calendar are been released at set_date_from_calendar () - scheduler_ui->calendar_dialog = gtk_dialog_new (); - gtk_container_set_border_width (GTK_CONTAINER (scheduler_ui->calendar_dialog), 1); - gtk_window_set_title (GTK_WINDOW (scheduler_ui->calendar_dialog), "Select starting date"); - gtk_window_set_position (GTK_WINDOW (scheduler_ui->calendar_dialog), GTK_WIN_POS_CENTER); - gtk_window_set_decorated (GTK_WINDOW (scheduler_ui->calendar_dialog), FALSE); - - dialog_vbox = GTK_DIALOG (scheduler_ui->calendar_dialog)->vbox; - - scheduler_ui->calendar = gtk_calendar_new (); - - gtk_box_pack_start (GTK_BOX (dialog_vbox), scheduler_ui->calendar, TRUE, TRUE, 0); - gtk_calendar_display_options (GTK_CALENDAR (scheduler_ui->calendar), - GTK_CALENDAR_SHOW_HEADING | GTK_CALENDAR_SHOW_DAY_NAMES); - - gtk_widget_show_all (scheduler_ui->calendar_dialog); - - g_signal_connect (G_OBJECT (scheduler_ui->calendar), "day-selected-double-click", - G_CALLBACK (set_date_from_calendar), data); -} - - -gboolean -mmyth_schedulerui_save (MMythSchedulerUI *scheduler_ui) -{ - GMythScheduler *scheduler; - ScheduleInfo *schedule_info; - GMythChannelInfo *channel_info; - - GList *clist; - gint index, duration; - gint frequency; - struct tm start_tm; - - schedule_info = g_new0(ScheduleInfo, 1); - if(schedule_info == NULL) { - g_warning ("Error allocating memory"); - return FALSE; - } - - clist = scheduler_ui->channel_list; - - index = gtk_combo_box_get_active(GTK_COMBO_BOX(scheduler_ui->channel_combobox)); - - if (clist != NULL) - clist = g_list_nth(clist, index); - - if (clist) { - g_debug ("[%s] New schedule: %d", __FUNCTION__, index); - } else { - g_warning ("[%s] Error when adding new schedule", __FUNCTION__); - return FALSE; - } - - channel_info = clist->data; - - /* initialize schedule_info */ - schedule_info->channel_id = channel_info->channel_ID; - - start_tm.tm_hour = - (int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(scheduler_ui->hour_spinbutton)); - start_tm.tm_min = - (int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(scheduler_ui->min_spinbutton)); - start_tm.tm_sec = 0; - - start_tm.tm_mday = (gint)scheduler_ui->day_temp; - start_tm.tm_mon = (gint)scheduler_ui->month_temp; - start_tm.tm_year = (gint)scheduler_ui->year_temp - 1900; //years since 1900 - - schedule_info->start_time = timelocal(&start_tm); - if (schedule_info->start_time == (time_t)(-1)) { - g_warning ("timelocal error!\n"); - return FALSE; - } - - duration = (gint) gtk_spin_button_get_value( - GTK_SPIN_BUTTON(scheduler_ui->duration_spinbutton)); - schedule_info->end_time = schedule_info->start_time + (duration*60); - - /* TODO: frequency is not implemented yet */ - frequency = gtk_combo_box_get_active(GTK_COMBO_BOX(scheduler_ui->freq_combobox)); - - schedule_info->title = g_string_new(""); - g_string_printf(schedule_info->title, "%s", - gtk_entry_get_text(GTK_ENTRY(scheduler_ui->title_entry))); - - /* FIXME: Architecture change to reuse the scheduler created in the recordui! */ - scheduler = gmyth_scheduler_new (); - - gmyth_scheduler_connect(scheduler); - - /* FIXME: set record_id = -1 to add a new schedule */ - schedule_info->record_id = -1; - gmyth_scheduler_add_schedule (scheduler, schedule_info); - - gmyth_scheduler_disconnect(scheduler); - - /* free allocated memory */ - g_object_unref (scheduler); - g_free (schedule_info); - - return TRUE; -} - -static GtkWidget* -add_line (GtkWidget *vbox, const gchar *str) -{ - GtkWidget *label; - GtkWidget *hbox = gtk_hbox_new (FALSE, 0); - - gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); - gtk_container_set_border_width (GTK_CONTAINER (hbox), 3); - - label = gtk_label_new (str); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - - return hbox; -} - -static void -add_channel_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox) -{ - GtkWidget *combobox; - - GtkWidget *hbox = add_line (vbox, "Channel: "); - - combobox = gtk_combo_box_new_text (); - - scheduler_ui->channel_combobox = combobox; - gtk_box_pack_start (GTK_BOX (hbox), combobox, FALSE, FALSE, 0); - - GMythEPG *mmyth_epg = gmyth_epg_new (); - if (!gmyth_epg_connect (mmyth_epg)) { - // FIXME: Without this list the scheduler UI should not be shown! - g_warning ("[%s] Error when getting list of channels", __FUNCTION__); - } - - if (gmyth_epg_get_channel_list (mmyth_epg, &(scheduler_ui->channel_list)) < 0) { - g_debug ("[%s] Error while trying to retrieve channel list", __FUNCTION__); - } else { - GList *clist = scheduler_ui->channel_list; - GMythChannelInfo *channel_info; - - while (clist != NULL) { - channel_info = clist->data; - clist = clist->next; - gtk_combo_box_append_text (GTK_COMBO_BOX (scheduler_ui->channel_combobox), - (channel_info->channel_name->str)); - } - - gtk_combo_box_set_active(GTK_COMBO_BOX (scheduler_ui->channel_combobox), 0); - } -} - -static void -add_time_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox) -{ - GtkWidget *label; - GtkObject *spinbutton_adj; - GtkWidget *hbox = add_line (vbox, "Time: "); - - time_t real_time; - struct tm sched_time; - - time(&real_time); - - if (localtime_r((time_t *)&real_time, &sched_time) == NULL) { - g_warning ("localtime_r error in mmyth_epg_grid_view!\n"); - return NULL; - } - - if (sched_time.tm_min>30){ - sched_time.tm_hour = sched_time.tm_hour+1; - sched_time.tm_min = 0; - } else if (sched_time.tm_min>0) { - sched_time.tm_min = 30; - } - - scheduler_ui->year_temp = (guint)sched_time.tm_year + 1900; - scheduler_ui->month_temp = (guint)sched_time.tm_mon; - scheduler_ui->day_temp = (guint)sched_time.tm_mday; - - //hour entry - spinbutton_adj = gtk_adjustment_new (sched_time.tm_hour, 00, 23, 1, 10, 10); - scheduler_ui->hour_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_adj), 1, 0); - gtk_box_pack_start (GTK_BOX (hbox), scheduler_ui->hour_spinbutton, FALSE, FALSE, 0); - - label = gtk_label_new ((" : ")); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - - //minute entry - spinbutton_adj = gtk_adjustment_new (sched_time.tm_min, 0, 59, 1, 10, 10); - scheduler_ui->min_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_adj), 1, 0); - gtk_box_pack_start (GTK_BOX (hbox), scheduler_ui->min_spinbutton, FALSE, FALSE, 0); - - label = gtk_label_new ((" (hh:mm)")); - - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); - -} - -static void -add_date_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox) -{ - char sched_date[24]; - GtkWidget *hbox = add_line (vbox, "Date: "); - - //sched_date = ctime(&real_time); - g_sprintf (sched_date, "%04d %02d %02d (yyyy mm dd)", scheduler_ui->year_temp, scheduler_ui->month_temp+1, scheduler_ui->day_temp); - sched_date[23]='\0'; - - scheduler_ui->date_button = gtk_button_new_with_label (sched_date); - gtk_box_pack_start (GTK_BOX (hbox), scheduler_ui->date_button, FALSE, FALSE, 0); - gtk_button_set_relief (GTK_BUTTON (scheduler_ui->date_button), GTK_RELIEF_NONE); - - g_signal_connect (G_OBJECT (scheduler_ui->date_button), "clicked", - G_CALLBACK (run_calendar_dialog), scheduler_ui); - -} - -static void -add_duration_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox) -{ - GtkWidget *hbox = add_line (vbox, "Duration: "); - GtkWidget *label; - GtkObject *spinbutton_adj; - - spinbutton_adj = gtk_adjustment_new (60, 5, 360, 5, 60, 60); - scheduler_ui->duration_spinbutton = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton_adj), 1, 0); - gtk_box_pack_start (GTK_BOX (hbox), scheduler_ui->duration_spinbutton, FALSE, TRUE, 0); - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (scheduler_ui->duration_spinbutton), TRUE); - - label = gtk_label_new ((" (minutes) ")); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); -} - -static void -add_frequency_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox) -{ - - GtkWidget *hbox = add_line (vbox, "Frequency: "); - - scheduler_ui->freq_combobox = gtk_combo_box_new_text (); - gtk_box_pack_start (GTK_BOX (hbox), scheduler_ui->freq_combobox, FALSE, FALSE, 0); - gtk_combo_box_append_text (GTK_COMBO_BOX (scheduler_ui->freq_combobox), ("Only this day ")); - gtk_combo_box_append_text (GTK_COMBO_BOX (scheduler_ui->freq_combobox), ("Daily ")); - gtk_combo_box_append_text (GTK_COMBO_BOX (scheduler_ui->freq_combobox), ("Weekly ")); - gtk_combo_box_set_active(GTK_COMBO_BOX (scheduler_ui->freq_combobox), 0); - -} - -static void -add_title_field (MMythSchedulerUI *scheduler_ui, GtkWidget *vbox) -{ - GtkWidget *hbox = add_line (vbox, "Title: "); - - scheduler_ui->title_entry = gtk_entry_new (); - gtk_box_pack_start (GTK_BOX (hbox), scheduler_ui->title_entry, FALSE, FALSE, 0); - gtk_entry_set_text (GTK_ENTRY (scheduler_ui->title_entry), "(Optional)"); - -} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gui/mmyth_schedulerui.h --- a/gmyth/src/gui/mmyth_schedulerui.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -#ifndef MMYTH_SCHEDULERECORDING_H_ -#define MMYTH_SCHEDULERECORDING_H_ - -#include - -typedef struct _MMythSchedulerUI { - - GList *channel_list; - - GtkWidget *main_widget; - - GtkWidget *channel_combobox; - GtkWidget *freq_combobox; - GtkWidget *hour_spinbutton; - GtkWidget *min_spinbutton; - GtkWidget *duration_spinbutton; - GtkWidget *title_entry; - GtkWidget *date_button; - - GtkWidget *calendar_dialog; - GtkWidget *calendar; - - guint year_temp, month_temp, day_temp; -} MMythSchedulerUI; - -typedef struct { - long int channel_id; - - struct tm start_tm; - - int duration; - int frequency; - - GString *title; - -} ScheduleEntry; - -MMythSchedulerUI* mmyth_schedulerui_new (void); - -gboolean mmyth_schedulerui_save (MMythSchedulerUI *scheduler_ui); - -void mmyth_schedulerui_cb_schedule_button (GtkButton * button, gpointer user_data); - - -#endif /*MMYTH_SCHEDULERECORDING_H_*/ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gui/mmyth_ui.c --- a/gmyth/src/gui/mmyth_ui.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,814 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mmyth_ui.h" -#include "mmyth_uicommon.h" -#include "mmyth_schedulerui.h" -#include "mmyth_recordui.h" -#include "mmyth_uisettings.h" -#include "mmyth_epg_grid_view.h" - -/* GMyth library includes */ -#include "gmyth_context.h" -#include "gmyth_tvplayer.h" - -#ifndef MAEMO_PLATFORM -static gint button_press_handler (GtkWidget *widget, GdkEvent *event); -#endif - -static MMythUiCommon *create_main_view (MMythUi * mmyth_ui); -static MMythUiCommon *create_video_view (MMythUi * mmyth_ui); -static MMythUiCommon *create_epg_grid_view (MMythUi * mmyth_ui); -static MMythUiCommon *create_record_view (MMythUi * mmyth_ui); -static MMythUiCommon *create_schedule_view (MMythUi * mmyth_ui); - -static void cb_video_close_button (GtkButton * button, gpointer user_data); -static void cb_record_button (GtkButton * button, gpointer user_data); -static void cb_menu_item_settings (GtkMenuItem *menuitem, gpointer user_data); - -/* main box from button box separator*/ -static GtkWidget *main_vseparator = NULL; - -GdkPixbuf *icon_sports, *icon_news, - *icon_movies, *icon_shows, *icon_default; - -#ifndef MAEMO_PLATFORM -/* FIXME: */ -static MMythUi *popup_mmyth_ui; -#endif - -MMythUi * -mmyth_ui_initialize ( -#ifdef MAEMO_PLATFORM - HildonProgram *program, -#endif - GtkWidget * main_window) -{ - MMythUi *mmyth_ui; - - mmyth_ui = g_new0 (MMythUi, 1); - - mmyth_ui->main_window = main_window; - mmyth_ui->videow = NULL; - mmyth_ui->mmyth_recordui = NULL; - mmyth_ui->mmyth_schedulerui = NULL; - - /* Horizontal box that divides the view into control and video area */ - mmyth_ui->main_hbox = gtk_hbox_new (FALSE, 0); - gtk_widget_show (mmyth_ui->main_hbox); - g_object_ref (mmyth_ui->main_hbox); - - main_bg_color.red = 65000; - main_bg_color.green = 65000; - main_bg_color.blue = 65000; - - -#ifndef MAEMO_PLATFORM - /* Popup menu */ - popup_mmyth_ui = mmyth_ui; - g_signal_connect (G_OBJECT (mmyth_ui->main_hbox), "event", - G_CALLBACK (button_press_handler), - G_OBJECT (mmyth_ui->main_hbox)); - -#else // #ifdef MAEMO - - mmyth_ui->main_menu = GTK_MENU(gtk_menu_new()); - hildon_program_set_common_menu(program, mmyth_ui->main_menu); - - mmyth_ui->menu_setup = gtk_menu_item_new_with_label("Setup"); - gtk_widget_set_size_request (GTK_WIDGET (mmyth_ui->menu_setup), 150, 40); - gtk_menu_append(mmyth_ui->main_menu, mmyth_ui->menu_setup); - - g_signal_connect(G_OBJECT(mmyth_ui->menu_setup), "activate", G_CALLBACK(cb_menu_item_settings), mmyth_ui); - - gtk_widget_show_all (GTK_WIDGET (mmyth_ui->main_menu)); -#endif - - // Main widget is mmyth_ui->main_hbox - mmyth_ui->main_uicommon = create_main_view (mmyth_ui); - - gtk_container_add (GTK_CONTAINER (mmyth_ui->main_window), - mmyth_ui->main_hbox); - - mmyth_ui_set_widget (mmyth_ui, mmyth_ui->main_uicommon); - - return mmyth_ui; -} - -void -mmyth_ui_finalize (MMythUi * mmyth_ui) -{ - if (mmyth_ui != NULL) { - if (mmyth_ui->main_uicommon) - mmyth_uicommon_free (mmyth_ui->main_uicommon); - if (mmyth_ui->video_uicommon) - mmyth_uicommon_free (mmyth_ui->video_uicommon); - if (mmyth_ui->epg_grid_uicommon) - mmyth_uicommon_free (mmyth_ui->epg_grid_uicommon); - if (mmyth_ui->record_uicommon) - mmyth_uicommon_free (mmyth_ui->record_uicommon); - if (mmyth_ui->schedule_uicommon) - mmyth_uicommon_free (mmyth_ui->schedule_uicommon); - - g_free (mmyth_ui); - } -} - -void -mmyth_ui_set_widget (MMythUi * mmyth_ui, MMythUiCommon * new_uicommon) -{ - if (new_uicommon == NULL) { - g_warning ("MMythUI setting a NULL UI_Common as current display\n"); - return; - } - - if (mmyth_ui->current_uicommon) { - if (mmyth_ui->current_uicommon == mmyth_ui->video_uicommon) { - gtk_widget_hide (mmyth_ui->current_uicommon->main_widget); - gtk_widget_hide (mmyth_ui->videow); - } - else { - gtk_container_remove (GTK_CONTAINER (mmyth_ui->main_hbox), - mmyth_ui->current_uicommon->main_widget); - } - - gtk_container_remove (GTK_CONTAINER (mmyth_ui->main_hbox), - mmyth_ui->current_uicommon->event_box); - gtk_container_remove (GTK_CONTAINER (mmyth_ui->main_hbox), - main_vseparator); - - } - - if (new_uicommon->main_widget == mmyth_ui->video_alignment) { - //gst_player_video_show (GST_PLAYER_VIDEO(mmyth_ui->videow)); - gtk_widget_show (mmyth_ui->video_alignment); - gtk_widget_show (mmyth_ui->videow); - } - else { - /* FIXME: Fst call is NULL when mmyth_player_init fails */ - if(mmyth_ui->video_alignment != NULL) - gtk_widget_hide (mmyth_ui->video_alignment); - /* FIXME: Fst call is NULL when mmyth_player_init fails */ - if(mmyth_ui->videow != NULL) - gtk_widget_hide (mmyth_ui->videow); - - gtk_box_pack_start (GTK_BOX (mmyth_ui->main_hbox), - new_uicommon->main_widget, TRUE, TRUE, 0); - } - - if(main_vseparator == NULL) { - /* FIXME: should free this variable*/ - main_vseparator = gtk_vseparator_new(); - g_object_ref (main_vseparator); - } - gtk_box_pack_start (GTK_BOX (mmyth_ui->main_hbox), - main_vseparator, FALSE, FALSE, 0); - gtk_widget_show (main_vseparator); - - gtk_box_pack_end (GTK_BOX (mmyth_ui->main_hbox), new_uicommon->event_box, FALSE, - FALSE, 0); - - mmyth_ui->current_uicommon = new_uicommon; - -} - -/* The close callback is the same for all windows*/ -static void -cb_not_impl_button (GtkButton * button, gpointer user_data) -{ - MMythUi *mmyth_ui = (MMythUi *) user_data; - - GtkWidget *msg_dialog = gtk_message_dialog_new ( - GTK_WINDOW(mmyth_ui->main_window), - GTK_DIALOG_MODAL | - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_INFO, - GTK_BUTTONS_OK, - "Feature not implemented"); - gtk_widget_set_size_request (msg_dialog, 350, 120); - - gtk_dialog_run (GTK_DIALOG (msg_dialog)); - - gtk_widget_destroy(GTK_WIDGET(msg_dialog)); -} - -/****************************************************************************** - * POPUP MENU WIDGET METHODS * - *****************************************************************************/ - -static void -cb_menu_item_settings (GtkMenuItem *menuitem, - gpointer user_data) -{ - - MMythUi *mmyth_ui = (MMythUi*) user_data; - - if (mmyth_uisettings_run (GTK_WINDOW (mmyth_ui->main_window))) { - // If user changes the settings, we restart the context - g_debug ("[%s] Restarting mmyth_context to new settings", __FUNCTION__); - gmyth_context_initialize(); - } -} - -#ifndef MAEMO_PLATFORM - -static void -detacher (GtkWidget *attach_widget,GtkMenu *menu) -{ - -} - -static void -do_popup_menu (GtkWidget *my_widget, GdkEventButton *event) -{ - GtkWidget *popup; - - int button, event_time; - - GtkWidget *item_general; - GtkWidget *image; - - popup = gtk_menu_new (); - - item_general = gtk_image_menu_item_new_with_mnemonic ("Setup"); - gtk_widget_show (item_general); - gtk_container_add (GTK_CONTAINER (popup), item_general); - - image = gtk_image_new_from_stock ("gtk-edit", GTK_ICON_SIZE_MENU); - gtk_widget_show (image); - gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item_general), image); - - g_signal_connect (G_OBJECT(item_general), "activate", G_CALLBACK (cb_menu_item_settings), popup_mmyth_ui); - - if (event) { - button = event->button; - event_time = event->time; - } else { - button = 0; - event_time = gtk_get_current_event_time (); - } - - gtk_menu_attach_to_widget (GTK_MENU (popup), my_widget, detacher); - gtk_menu_popup (GTK_MENU (popup), NULL, NULL, NULL, NULL, - button, event_time); - gtk_widget_show_all(popup); -} - -/* Respond to a button-press by posting a menu passed in as widget. - * - * Note that the "widget" argument is the menu being posted, NOT - * the button that was pressed. - */ -static gint -button_press_handler (GtkWidget *widget, GdkEvent *event) -{ - - if (event->type == GDK_BUTTON_PRESS) { - GdkEventButton *bevent = (GdkEventButton *) event; - /* Ignore double-clicks and triple-clicks */ - if (bevent->button == 3) - { - do_popup_menu (widget, bevent); - return TRUE; - } - } - - /* Tell calling code that we have not handled this event; pass it on. */ - return FALSE; -} -#endif - -/****************************************************************************** - * MAIN APP VIEW METHODS * - *****************************************************************************/ - -static void -cb_close_button (GtkButton * button, gpointer user_data) -{ - MMythUi *mmyth_ui = (MMythUi *) user_data; - - mmyth_ui_set_widget (mmyth_ui, mmyth_ui->main_uicommon); -} - -static void -cb_watch_tv_button (GtkButton * button, gpointer user_data) -{ - MMythUi *mmyth_ui = (MMythUi *) user_data; - gboolean res = FALSE; - - if (!(mmyth_ui->video_uicommon)) - mmyth_ui->video_uicommon = create_video_view (mmyth_ui); - - // Creates the tv player that will retrieve the mythtv content, decode and show it - mmyth_ui->tvplayer = gmyth_tvplayer_new (); - /* choose here if this is a LiveTV session */ - mmyth_ui->tvplayer->is_livetv = TRUE; - - res = gmyth_tvplayer_initialize (mmyth_ui->tvplayer); - - if (!res) { - g_warning ("[%s] Could not initialize tvplayer", __FUNCTION__); - - g_object_unref (mmyth_ui->tvplayer); - mmyth_ui->tvplayer = NULL; - - GtkWidget *dialog = gtk_message_dialog_new ( - GTK_WINDOW(mmyth_ui->main_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "MMyth found errors while starting TV Player, please check " - "the GStreamer installation"); - - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - - return; - } - //res = mmyth_tvplayer_livetv_setup (mmyth_ui->tvplayer); - // - if (mmyth_ui && mmyth_ui->tvplayer && res) { - gmyth_tvplayer_set_widget (mmyth_ui->tvplayer, mmyth_ui->videow); - gmyth_tvplayer_start_playing (mmyth_ui->tvplayer); - } else { - // TODO: Show Alert with error description! - g_warning ("[%s] MMythUI can't initialize tv_player", __FUNCTION__); - g_object_unref (mmyth_ui->tvplayer); - mmyth_ui->tvplayer = NULL; - // FIXME: Show the exact error that happened - GtkWidget *dialog = gtk_message_dialog_new ( - GTK_WINDOW(mmyth_ui->main_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "Error while starting TV Player, please check if the backend" - " is running properly and a tv card is available!"); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - return; - } - mmyth_ui_set_widget (mmyth_ui, mmyth_ui->video_uicommon); - -} - -static void -cb_epg_button (GtkButton * button, gpointer user_data) -{ - MMythUi *mmyth_ui = (MMythUi *) user_data; - - if (!(mmyth_ui->epg_grid_uicommon)) - mmyth_ui->epg_grid_uicommon = create_epg_grid_view(mmyth_ui); - - mmyth_ui_set_widget (mmyth_ui, mmyth_ui->epg_grid_uicommon); -} - -static MMythUiCommon * -create_main_view (MMythUi * mmyth_ui) -{ - MMythUiCommon *ui_common; - GtkWidget *main_widget; - GtkWidget *image; - - g_debug ("Creating Main UI Common"); - - // FIXME: file path -#ifdef MMYTH_DEV - image = gtk_image_new_from_file ("../pixmaps/mmyth_logo.png"); -#else - image = gtk_image_new_from_file ( PIX_DIR "mmyth_logo.png"); -#endif - - main_widget = gtk_event_box_new(); - - gtk_container_add (GTK_CONTAINER (main_widget), - image); - - - gtk_widget_show_all (main_widget); - g_object_ref (main_widget); - - ui_common = mmyth_uicommon_new (main_widget, - "Watch TV", "EPG", "Recording"); - - /* Button signals */ - // FIXME - g_signal_connect (G_OBJECT (ui_common->button1), "clicked", - G_CALLBACK (cb_watch_tv_button), mmyth_ui); - g_signal_connect (G_OBJECT (ui_common->button2), "clicked", - G_CALLBACK (cb_epg_button), mmyth_ui); - g_signal_connect (G_OBJECT (ui_common->button3), "clicked", - G_CALLBACK (cb_record_button), mmyth_ui); - - return ui_common; - -} - -/****************************************************************************** - * epg GRID VIEW METHODS * - *****************************************************************************/ - -static MMythUiCommon * -create_epg_grid_view (MMythUi * mmyth_ui) -{ - MMythUiCommon *ui_common; - - g_debug ("Creating EPG Grid UI Common"); - - GtkWidget *epg_grid_view = GTK_WIDGET (epg_grid_view_new (mmyth_ui)); - - ui_common = mmyth_uicommon_new (epg_grid_view, - "Play", "Record", - "Close"); - - /* Button signals */ - g_signal_connect (G_OBJECT (ui_common->button1), "clicked", - G_CALLBACK (cb_not_impl_button), mmyth_ui); - g_signal_connect (G_OBJECT (ui_common->button2), "clicked", - G_CALLBACK (cb_record_button), mmyth_ui); - g_signal_connect (G_OBJECT (ui_common->button3), "clicked", - G_CALLBACK (cb_close_button), mmyth_ui); - - return ui_common; -} -/****************************************************************************** - * SCHEDULE VIEW METHODS * - ******************************************************************************/ - -static void -cb_save_new_schedule (GtkButton *button, gpointer user_data) -{ - MMythUi *mmyth_ui = (MMythUi *) user_data; - - if (!(mmyth_ui->schedule_uicommon)) - mmyth_ui->schedule_uicommon = create_schedule_view(mmyth_ui); - - mmyth_schedulerui_save (mmyth_ui->mmyth_schedulerui); - - mmyth_recordui_reload_schedule (mmyth_ui->mmyth_recordui); - - mmyth_ui_set_widget (mmyth_ui, mmyth_ui->record_uicommon); - -} - -static void -cb_edit_scheduled (GtkTreeView * tree_view, GtkTreePath *path, - GtkTreeViewColumn *column, gpointer user_data) -{ - MMythUi *mmyth_ui = (MMythUi *) user_data; - GtkTreeSelection *selection; - GtkTreeModel *list_store; - GtkTreeIter iter; - int index; - //gint new_row = 0, record_id = 0; - ScheduleInfo *schedule_info; - GList *schedule_list; - //GtkTreeIter iter; - gint res; - - //gtk_tree_store_clear(recordui->sch_tree_store); - - res = gmyth_scheduler_get_schedule_list(mmyth_ui->mmyth_recordui->scheduler, &(schedule_list)); - if (res < 0) { - g_warning ("[%s] Retrieved NULL list of scheduled data from database", __FUNCTION__); - //return FALSE; - } - printf("\nX %d", res); fflush(stdout); - - selection = - gtk_tree_view_get_selection(GTK_TREE_VIEW(mmyth_ui->mmyth_recordui->sch_treeview)); - - gtk_tree_selection_get_selected(selection, &list_store, &iter); - gtk_tree_model_get(list_store, &iter, 4, &index, -1); - - mmyth_ui_set_widget (mmyth_ui, mmyth_ui->schedule_uicommon); - - if (!(mmyth_ui->schedule_uicommon)) - mmyth_ui->schedule_uicommon = create_schedule_view(mmyth_ui); - - schedule_list = g_list_nth(schedule_list, atoi(gtk_tree_path_to_string(path))); - schedule_info = (ScheduleInfo*) schedule_list->data; - - printf("\nstarttime: %ld", schedule_info->start_time); fflush(stdout); -} - -static MMythUiCommon * -create_schedule_view (MMythUi * mmyth_ui) -{ - MMythUiCommon *ui_common; - GtkWidget *schedule_widget; - - g_debug ("Creating Schedule UI Common"); - - mmyth_ui->mmyth_schedulerui = mmyth_schedulerui_new (); - if (mmyth_ui->mmyth_schedulerui == NULL) { - g_warning ("[%s] Error while creating scheduler ui", __FUNCTION__); - return NULL; - } - - schedule_widget = mmyth_ui->mmyth_schedulerui->main_widget; - - gtk_widget_show_all (schedule_widget); - g_object_ref (schedule_widget); - - ui_common = mmyth_uicommon_new (schedule_widget, - "Save", "Clear", - "Cancel"); - - /* Button signals */ - g_signal_connect (G_OBJECT (ui_common->button1), "clicked", - G_CALLBACK (cb_save_new_schedule), mmyth_ui); - g_signal_connect (G_OBJECT (ui_common->button2), "clicked", - G_CALLBACK (cb_not_impl_button), mmyth_ui); - g_signal_connect (G_OBJECT (ui_common->button3), "clicked", - G_CALLBACK (cb_record_button), mmyth_ui); - - return ui_common; -} -/****************************************************************************** - * RECORD VIEW METHODS * - ******************************************************************************/ -static void -cb_record_button (GtkButton * button, gpointer user_data) -{ - MMythUi *mmyth_ui = (MMythUi *) user_data; - - if (!(mmyth_ui->record_uicommon)) { - mmyth_ui->record_uicommon = create_record_view (mmyth_ui); - mmyth_ui->schedule_uicommon = create_schedule_view (mmyth_ui); - } - - mmyth_recordui_reload_all (mmyth_ui->mmyth_recordui); - - mmyth_ui_set_widget (mmyth_ui, mmyth_ui->record_uicommon); - -} - -static void -cb_record_close_button (GtkButton * button, gpointer user_data) -{ - MMythUi *mmyth_ui = (MMythUi *) user_data; - - mmyth_ui_set_widget(mmyth_ui, mmyth_ui->main_uicommon); - - mmyth_recordui_free(mmyth_ui->mmyth_recordui); - - if (mmyth_ui->record_uicommon) { - gtk_widget_destroy (mmyth_ui->record_uicommon->main_widget); - mmyth_uicommon_free(mmyth_ui->record_uicommon); - mmyth_ui->record_uicommon = NULL; - } - - if (mmyth_ui->schedule_uicommon) { - // mmyth_uicommon_free(mmyth_ui->schedule_uicommon); - } -} - - - - -static void -play_selected_recorded (gpointer user_data) -{ - MMythUi *mmyth_ui = (MMythUi *) user_data; - gboolean res = FALSE; - - gchar *path = mmyth_recordui_get_selected_recorded (mmyth_ui->mmyth_recordui); - - if (path == NULL) { - // This should never happens. Play button is just activated when - // a recording is selected. - g_warning ("[%s] Play button pressed while none recorded is selected", __FUNCTION__); - return; - } - - if (!(mmyth_ui->video_uicommon)) - mmyth_ui->video_uicommon = create_video_view (mmyth_ui); - - // Creates the tv player that will retrieve the mythtv content, decode and show it - mmyth_ui->tvplayer = gmyth_tvplayer_new (); - g_debug ("[%s] New TV Player created: %d\n", __FUNCTION__, (int) (mmyth_ui->tvplayer)); - res = gmyth_tvplayer_initialize (mmyth_ui->tvplayer); - if (!res) { - g_warning ("[%s] Could not initialize tvplayer", __FUNCTION__); - - g_object_unref (mmyth_ui->tvplayer); - mmyth_ui->tvplayer = NULL; - - GtkWidget *dialog = gtk_message_dialog_new ( - GTK_WINDOW(mmyth_ui->main_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "MMyth found errors while starting TV Player, please check " - "the GStreamer installation"); - - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - - return; - } - - res = gmyth_tvplayer_record_setup (mmyth_ui->tvplayer, path); - - if (mmyth_ui && mmyth_ui->tvplayer && res) { - gmyth_tvplayer_set_widget (mmyth_ui->tvplayer, mmyth_ui->videow); - gmyth_tvplayer_start_playing (mmyth_ui->tvplayer); - } else { - // TODO: Show Alert with error description! - g_warning ("[%s] MMythUI can't initialize tv_player", __FUNCTION__); - g_object_unref (mmyth_ui->tvplayer); - mmyth_ui->tvplayer = NULL; - // FIXME: Show the exact error that happened - GtkWidget *dialog = gtk_message_dialog_new ( - GTK_WINDOW(mmyth_ui->main_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "Error while starting TV Player, please check if the backend" - " is running properly and a tv card is available!"); - gtk_dialog_run (GTK_DIALOG (dialog)); - gtk_widget_destroy (dialog); - return; - } - - mmyth_ui_set_widget (mmyth_ui, mmyth_ui->video_uicommon); -} - -static void -cb_play_clicked_recorded (GtkTreeView * tree_view, GtkTreePath *path, - GtkTreeViewColumn *column, gpointer user_data) -{ - play_selected_recorded (user_data); -} - -static void -cb_play_selected (GtkButton * button, gpointer user_data) -{ - play_selected_recorded (user_data); -} - -static void -cb_schedule_button (GtkButton * button, gpointer user_data) -{ - MMythUi *mmyth_ui = (MMythUi *) user_data; - - mmyth_ui_set_widget (mmyth_ui, mmyth_ui->schedule_uicommon); -} - -void -cb_switch_page (GtkNotebook *notebook, GtkNotebookPage *page, - guint page_num, gpointer user_data) -{ - MMythUi *mmyth_ui = (MMythUi *) user_data; - MMythUiCommon *ui_common; - - assert (mmyth_ui); - assert (mmyth_ui->record_uicommon); - - ui_common = mmyth_ui->record_uicommon; - - if (page_num == 0) { // Switched to Schedule list - gtk_button_set_label (GTK_BUTTON (ui_common->button1), "New"); - g_signal_handlers_disconnect_by_func ( - G_OBJECT (ui_common->button1), G_CALLBACK (cb_play_selected), mmyth_ui); - g_signal_connect (G_OBJECT (ui_common->button1), "clicked", - G_CALLBACK (cb_schedule_button), mmyth_ui); - } else if (page_num == 1) { - gtk_button_set_label (GTK_BUTTON (ui_common->button1), "Play"); - g_signal_handlers_disconnect_by_func ( - G_OBJECT (ui_common->button1), G_CALLBACK (cb_schedule_button), mmyth_ui); - g_signal_connect (G_OBJECT (ui_common->button1), "clicked", - G_CALLBACK (cb_play_selected), mmyth_ui); - } -} - - -static MMythUiCommon * -create_record_view (MMythUi * mmyth_ui) -{ - MMythUiCommon *ui_common; - - g_debug ("Creating Record UI Common"); - - mmyth_ui->mmyth_recordui = mmyth_recordui_new (); - - // FIXME: Change MMythRecordUI to a GtkWidget child and avoid this call! - gtk_widget_show_all (mmyth_ui->mmyth_recordui->scrolled_window); - - ui_common = mmyth_uicommon_new (mmyth_ui->mmyth_recordui->scrolled_window, "New", "Delete", "<mmyth_recordui->scrolled_window); - - /* Button signals */ - g_signal_connect (G_OBJECT (ui_common->button1), "clicked", - G_CALLBACK (cb_schedule_button), mmyth_ui); - g_signal_connect (G_OBJECT (ui_common->button2), "clicked", - G_CALLBACK (mmyth_recordui_delete_selected), mmyth_ui->mmyth_recordui); - g_signal_connect (G_OBJECT (ui_common->button3), "clicked", - G_CALLBACK (cb_record_close_button), mmyth_ui); - g_signal_connect (G_OBJECT (mmyth_ui->mmyth_recordui->notebook), - "switch-page", G_CALLBACK (cb_switch_page), mmyth_ui); - g_signal_connect (G_OBJECT (mmyth_ui->mmyth_recordui->rec_treeview), - "row-activated", G_CALLBACK (cb_play_clicked_recorded), mmyth_ui); - g_signal_connect (G_OBJECT (mmyth_ui->mmyth_recordui->sch_treeview), - "row-activated", G_CALLBACK (cb_edit_scheduled), mmyth_ui); - return ui_common; -} - - -/****************************************************************************** - * GST VIDEO WIDGET METHODS * - *****************************************************************************/ - -static void -cb_video_close_button (GtkButton * button, gpointer user_data) -{ - MMythUi *mmyth_ui = (MMythUi *) user_data; - - g_debug ("MMythUI video close button pressed"); - - if (mmyth_ui && mmyth_ui->tvplayer) { - gmyth_tvplayer_stop_playing (mmyth_ui->tvplayer); - - g_object_unref (mmyth_ui->tvplayer); - mmyth_ui->tvplayer = NULL; - } else { - g_warning ("cb_video_close_button called with NULL pointer\n"); - } - - mmyth_ui_set_widget (mmyth_ui, mmyth_ui->main_uicommon); -} - - -static MMythUiCommon * -create_video_view (MMythUi * mmyth_ui) -{ - - MMythUiCommon *ui_common; - - g_debug ("Creating Video UI Common"); - - /* Creates widget to be user by MMythTVPlayer to draw the video */ - mmyth_ui->videow = gtk_drawing_area_new (); - // FIXME: Get the widget size from settings - gtk_widget_set_size_request (mmyth_ui->videow, 300, 240); - - //mmiptv_ui->logo = gdk_pixbuf_new_from_file ("logo.png", NULL); - - // Creates an alignment to place the video widget inside - mmyth_ui->video_alignment = gtk_alignment_new (0.5, 0.5, 1, 1); - gtk_widget_hide (mmyth_ui->video_alignment); - - gtk_container_add (GTK_CONTAINER (mmyth_ui->video_alignment), - mmyth_ui->videow); - - /* Add the gst video widget to hbox. It should never be removed. */ - /* FIXME: mmyth_ui->video_alignment == NULL when mmyth_player_init fails */ - if((mmyth_ui->main_hbox != NULL) && (mmyth_ui->video_alignment != NULL)) { - gtk_box_pack_start (GTK_BOX (mmyth_ui->main_hbox), - mmyth_ui->video_alignment, TRUE, TRUE, 0); - } else { - g_warning ("[%s] Error while adding video_alignment to main widget", __FUNCTION__); - } - - g_object_ref (mmyth_ui->videow); - g_object_ref (mmyth_ui->video_alignment); - - ui_common = mmyth_uicommon_new (mmyth_ui->video_alignment, - " Full\nScreen", "Other\nServices", - "Close"); - - - g_signal_connect (G_OBJECT (ui_common->button1), "clicked", - G_CALLBACK (cb_not_impl_button), mmyth_ui); - g_signal_connect (G_OBJECT (ui_common->button2), "clicked", - G_CALLBACK (cb_not_impl_button), mmyth_ui); - g_signal_connect (G_OBJECT (ui_common->button3), "clicked", - G_CALLBACK (cb_video_close_button), mmyth_ui); - - if (ui_common) - g_debug ("Video UI_Common sucessfull created"); - - return ui_common; -} - - - -GtkWidget* -mmyth_ui_get_video_widget (MMythUi *mmyth_ui) { - - if (mmyth_ui && mmyth_ui->videow) { - - return mmyth_ui->videow; - } - - return NULL; -} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gui/mmyth_ui.h --- a/gmyth/src/gui/mmyth_ui.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -#ifndef MMYTH_UI_H_ -#define MMYTH_UI_H_ - -#include -#include - -#include "config.h" - -#ifdef MAEMO_PLATFORM -#include "hildon-widgets/hildon-program.h" -#include "hildon-widgets/hildon-window.h" -#endif - -#include "mmyth_uicommon.h" -#include "mmyth_recordui.h" -#include "mmyth_schedulerui.h" - -/* GMyth library includes */ -#include "gmyth_tvplayer.h" - -typedef struct _MMythUi -{ - - /* The main application window */ - GtkWidget *main_window; - MMythUiCommon *current_uicommon; - - /* Main widget components */ - GtkWidget *main_hbox; - GtkWidget *video_alignment; - GdkPixbuf *logo; - - /* Main widgets grouping */ - MMythUiCommon *main_uicommon; - MMythUiCommon *video_uicommon; - MMythUiCommon *epg_grid_uicommon; - MMythUiCommon *record_uicommon; - MMythUiCommon *schedule_uicommon; - - GtkWidget *videow; - int idle_id; - //GstTagList *tagcache; - - MMythRecordUI *mmyth_recordui; - MMythSchedulerUI *mmyth_schedulerui; - -#ifdef MAEMO_PLATFORM - HildonProgram *program; - GtkMenu *main_menu; - GtkWidget *menu_setup; -#endif - - GMythTVPlayer *tvplayer; - -} MMythUi; - -GdkPixbuf *icon_sports, *icon_news, *icon_movies, *icon_shows; -GdkColor main_bg_color; - -void mmyth_set_main_widget (MMythUi * mmyth_ui, MMythUiCommon * new_ui); -//void mmyth_play_selected(GtkButton * button, gpointer user_data); - -#ifdef MAEMO_PLATFORM -MMythUi *mmyth_ui_initialize (HildonProgram *program, GtkWidget * main_window); -#else -MMythUi *mmyth_ui_initialize (GtkWidget * main_window); -#endif - -void mmyth_ui_finalize (MMythUi * mmyth_ui); - -void mmyth_ui_set_widget (MMythUi * mmyth_ui, MMythUiCommon * new_uicommon); - -GtkWidget* mmyth_ui_get_video_widget (MMythUi *mmyth_ui); - -#endif /* MMYTH_UI_H_ */ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gui/mmyth_uicommon.c --- a/gmyth/src/gui/mmyth_uicommon.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ - -#include -#include -#include - -#include "mmyth_uicommon.h" -#include "mmyth_ui.h" - -static void -refresh_time_on_screen (GtkWidget *label) -{ - time_t real_time; - struct tm sched_time; - GString *time_showed; - - time_showed = g_string_new(""); - time(&real_time); - - if (localtime_r((time_t *)&real_time, &sched_time) == NULL) { - g_error ("localtime_r error in mmyth_epg_grid_view!\n"); - return NULL; - } - - g_string_printf(time_showed, "%d:%02d:%02d", - sched_time.tm_hour, - sched_time.tm_min, - sched_time.tm_sec); - - gtk_label_set_text (GTK_LABEL(label), time_showed->str); -} - -MMythUiCommon * -mmyth_uicommon_new (GtkWidget * main_widget, const gchar * label1, - const gchar * label2, const gchar * label3) -{ - - MMythUiCommon *ui_common = g_new0 (MMythUiCommon, 1); - - if (!main_widget) { - g_warning ("MMythUICommon created with a NULL main widget\n"); - } - - ui_common->main_widget = main_widget; - - ui_common->event_box = gtk_event_box_new(); - - /* Vertical box that divides the control area into two (buttons + clock) */ - ui_common->vbox = gtk_vbox_new (FALSE, 0); /* spacing */ - gtk_container_set_border_width(GTK_CONTAINER (ui_common->vbox), 4); - - gtk_container_add (GTK_CONTAINER (ui_common->event_box), - ui_common->vbox); - gtk_widget_modify_bg(ui_common->event_box, GTK_STATE_NORMAL, &main_bg_color); - - /* Vertical box that divides the control area into four */ - ui_common->button_vbox = gtk_vbox_new (TRUE, 0); /* spacing */ - - gtk_container_set_border_width (GTK_CONTAINER (ui_common->button_vbox), 0); - - /* The button 1 */ - ui_common->button1 = gtk_button_new_with_label (label1); - gtk_widget_modify_bg(ui_common->button1, GTK_STATE_NORMAL, &main_bg_color); - gtk_widget_set_size_request (ui_common->button1, BUTTON_WIDTH, - BUTTON_HEIGHT); - - /* The button 2 */ - ui_common->button2 = gtk_button_new_with_label (label2); - gtk_widget_modify_bg(ui_common->button2, GTK_STATE_NORMAL, &main_bg_color); - gtk_widget_set_size_request (ui_common->button2, BUTTON_WIDTH, - BUTTON_HEIGHT); - - /* The button 3 */ - ui_common->button3 = gtk_button_new_with_label (label3); - gtk_widget_modify_bg(ui_common->button3, GTK_STATE_NORMAL, &main_bg_color); - gtk_widget_set_size_request (ui_common->button3, BUTTON_WIDTH, - BUTTON_HEIGHT); - - /* The clock label */ - ui_common->label = gtk_label_new ("Starting..."); - gtk_widget_show (ui_common->label); - ui_common->source_id = g_timeout_add(500, (GSourceFunc) refresh_time_on_screen, ui_common->label); - - /* Packing components */ - gtk_box_pack_start (GTK_BOX (ui_common->vbox), - ui_common->button_vbox, TRUE, TRUE, 0); - - gtk_box_pack_start (GTK_BOX (ui_common->vbox), - ui_common->label, FALSE, FALSE, 0); - - gtk_box_pack_start (GTK_BOX (ui_common->button_vbox), - ui_common->button1, FALSE, FALSE, 0); - - gtk_box_pack_start (GTK_BOX (ui_common->button_vbox), - ui_common->button2, FALSE, FALSE, 0); - - gtk_box_pack_start (GTK_BOX (ui_common->button_vbox), - ui_common->button3, FALSE, FALSE, 0); - - gtk_widget_show_all (ui_common->event_box); - - /* FIXME: mmyth_ui->video_alignment == NULL when mmyth_player_init fails */ - if(ui_common->main_widget != NULL) - g_object_ref (ui_common->main_widget); - - g_object_ref (ui_common->vbox); - g_object_ref (ui_common->button_vbox); - g_object_ref (ui_common->label); - g_object_ref (ui_common->button1); - g_object_ref (ui_common->button2); - g_object_ref (ui_common->button3); - g_object_ref (ui_common->event_box); - return ui_common; -} - -void -mmyth_uicommon_free (MMythUiCommon *ui_common) -{ - g_debug ("[%s] Clean uicommon used memory", __FUNCTION__); - - g_source_remove (ui_common->source_id); - - g_object_unref (ui_common->main_widget); - g_object_unref (ui_common->vbox); - g_object_unref (ui_common->button_vbox); - g_object_unref (ui_common->label); - g_object_unref (ui_common->button1); - g_object_unref (ui_common->button2); - g_object_unref (ui_common->button3); - g_object_unref (ui_common->event_box); - - g_free (ui_common); -} - - diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gui/mmyth_uicommon.h --- a/gmyth/src/gui/mmyth_uicommon.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -#ifndef MMYTH_UICOMMON_H_ -#define MMYTH_UICOMMON_H_ - -#include "config.h" - -#include -#include - -#ifndef MAEMO_PLATFORM -#define BUTTON_HEIGHT 50 -#define BUTTON_WIDTH 100 -#else -#define BUTTON_HEIGHT 80 -#define BUTTON_WIDTH 150 -#endif - -#define MAIN_WINDOW_WIDTH 550 -#define MAIN_WINDOW_HEIGHT 250 - -#define CHANNELS_DIALOG_WIDTH 300 -#define CHANNELS_DIALOG_HEIGHT 200 - -#define SETTINGS_DIALOG_WIDTH 300 -#define SETTINGS_DIALOG_HEIGHT 120 - -extern GdkColor main_bg_color; - -typedef struct _MMythUiCommon -{ - GtkWidget *main_widget; - - /* event box to set the background color*/ - GtkWidget *event_box; - - GtkWidget *vbox; - GtkWidget *button_vbox; - GtkWidget *label; - - GtkWidget *button1; - GtkWidget *button2; - GtkWidget *button3; - - gint source_id; -} MMythUiCommon; - -MMythUiCommon *mmyth_uicommon_new (GtkWidget * main_widget, - const gchar * label1, const gchar * label2, - const gchar * label3); -void mmyth_uicommon_free (MMythUiCommon *ui_common); - -#endif /* MMYTH_UICOMMON_H_ */ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gui/mmyth_uisettings.c --- a/gmyth/src/gui/mmyth_uisettings.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,169 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mmyth_uisettings.h" - -#include "gmyth_context.h" - -static GtkWidget *settings_dialog; -static GtkWidget *entry_hostname; -static GtkWidget *entry_dbname; -static GtkWidget *entry_username; -static GtkWidget *entry_passwd; -static GtkWidget *entry_port; - -static void settings_dialog_update_data (void); -static GtkWidget* add_entry_to_table (GtkWidget *table, GString *init_str, - guint pos_left, guint pos_right, guint pos_top, guint pos_bottom); -static GtkWidget* add_label_to_table (GtkWidget *table, const gchar *str, - guint pos_left, guint pos_right, guint pos_top, guint pos_bottom); - - -gboolean -mmyth_uisettings_run (GtkWindow *main_window) -{ - - GtkWidget *settings_table; - GtkWidget *label_hostname, *label_dbname; - GtkWidget *label_username, *label_passwd, *label_port; - - GMythSettings *msettings = gmyth_context_get_settings(); - - settings_dialog = gtk_dialog_new_with_buttons ("Settings", - main_window, - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_STOCK_OK, - GTK_RESPONSE_ACCEPT, - GTK_STOCK_CANCEL, - GTK_RESPONSE_REJECT, - NULL); - - gtk_widget_set_size_request (settings_dialog, 400, 244); - -/* scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL); - gtk_widget_show (scrolledwindow1); - gtk_container_add (GTK_CONTAINER (window1), scrolledwindow1); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER); - - viewport1 = gtk_viewport_new (NULL, NULL); - gtk_widget_show (viewport1); - gtk_container_add (GTK_CONTAINER (scrolledwindow1), viewport1); - gtk_viewport_set_shadow_type (GTK_VIEWPORT (viewport1), GTK_SHADOW_NONE); -*/ - - // Creates the table and attach it to the settings dialog - settings_table = gtk_table_new (5, 2, FALSE); - gtk_widget_show (settings_table); - gtk_box_pack_start (GTK_BOX (GTK_DIALOG(settings_dialog)->vbox), settings_table, FALSE, TRUE, 0); - gtk_container_set_border_width (GTK_CONTAINER (settings_table), 3); - gtk_table_set_row_spacings (GTK_TABLE (settings_table), 5); - gtk_table_set_col_spacings (GTK_TABLE (settings_table), 10); - - label_hostname = add_label_to_table (settings_table, "Host Name:", 0, 1, 0, 1); - label_dbname = add_label_to_table (settings_table, "Database Name:", 0, 1, 1, 2); - label_username = add_label_to_table (settings_table, "Username:", 0, 1, 2, 3); - label_passwd = add_label_to_table (settings_table, "Password:", 0, 1, 3, 4); - label_port = add_label_to_table (settings_table, "Server port:", 0, 1, 4, 5); - - entry_hostname = add_entry_to_table (settings_table, - gmyth_settings_get_backend_hostname (msettings), - 1, 2, 0, 1); - entry_dbname = add_entry_to_table (settings_table, - gmyth_settings_get_dbname (msettings), - 1, 2, 1, 2 ); - entry_username = add_entry_to_table (settings_table, - gmyth_settings_get_username (msettings), - 1, 2, 2, 3 ); - entry_passwd = add_entry_to_table (settings_table, - gmyth_settings_get_password (msettings), - 1, 2, 3, 4 ); - - GString *str_port = g_string_new (""); - g_string_printf (str_port, "%d", - gmyth_settings_get_backend_port (msettings)); - entry_port = add_entry_to_table (settings_table, str_port, - 1, 2, 4, 5 ); - g_string_free (str_port, TRUE); - - if (gtk_dialog_run (GTK_DIALOG (settings_dialog)) == GTK_RESPONSE_ACCEPT) { - settings_dialog_update_data (); - gtk_widget_destroy (settings_dialog); - return TRUE; - } - - gtk_widget_destroy (settings_dialog); - - return FALSE; - -} - -static GtkWidget* -add_label_to_table (GtkWidget *table, const gchar *str, guint pos_left, guint pos_right, - guint pos_top, guint pos_bottom ) -{ - GtkWidget *tmp_label = gtk_label_new (str); - - gtk_widget_show (tmp_label); - gtk_table_attach (GTK_TABLE (table), tmp_label, - pos_left, pos_right, pos_top, pos_bottom, - (GtkAttachOptions) (GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - gtk_misc_set_alignment (GTK_MISC (tmp_label), 0, 0.5); - - return tmp_label; -} - -static GtkWidget* -add_entry_to_table (GtkWidget *table, GString *init_str, guint pos_left, guint pos_right, - guint pos_top, guint pos_bottom) -{ - GtkWidget *tmp_entry = gtk_entry_new (); - gtk_widget_show (tmp_entry); - gtk_table_attach (GTK_TABLE (table), tmp_entry, - pos_left, pos_right, pos_top, pos_bottom, - (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), - (GtkAttachOptions) (0), 0, 0); - if (init_str) - gtk_entry_set_text (GTK_ENTRY (tmp_entry), (init_str->str)); - - //gtk_entry_set_invisible_char (GTK_ENTRY (entry_port), 9679); - - return tmp_entry; -} - -static void -settings_dialog_update_data (void) -{ - GString *tmp_entry_text; - GMythSettings *msettings = gmyth_context_get_settings(); - - if (!msettings) { - g_warning ("[%s] Could not get GMythSettings instance from context\n", __FUNCTION__); - return; - } - - tmp_entry_text = g_string_new(""); - g_string_printf(tmp_entry_text, "%s", gtk_entry_get_text( GTK_ENTRY(entry_hostname))); - gmyth_settings_set_backend_hostname(msettings, tmp_entry_text); - - g_string_printf(tmp_entry_text, "%s", gtk_entry_get_text( GTK_ENTRY(entry_dbname))); - gmyth_settings_set_dbname(msettings, tmp_entry_text); - - g_string_printf(tmp_entry_text, "%s", gtk_entry_get_text( GTK_ENTRY(entry_username))); - gmyth_settings_set_username(msettings, tmp_entry_text); - - g_string_printf(tmp_entry_text, "%s", gtk_entry_get_text( GTK_ENTRY(entry_passwd))); - gmyth_settings_set_password(msettings, tmp_entry_text); - - g_string_printf(tmp_entry_text, "%s", gtk_entry_get_text( GTK_ENTRY(entry_port))); - gmyth_settings_set_backend_port(msettings, atoi(tmp_entry_text->str)); - - gmyth_settings_save (msettings); - -} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gui/mmyth_uisettings.h --- a/gmyth/src/gui/mmyth_uisettings.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -#ifndef MMYTH_SETTINGS_H_ -#define MMYTH_SETTINGS_H_ - -gboolean mmyth_uisettings_run (GtkWindow *main_window); - -#endif /*MMYTH_SETTINGS_H_*/ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gui/mmyth_videoplayer.c --- a/gmyth/src/gui/mmyth_videoplayer.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,369 +0,0 @@ - -#include -#include -#include -#include -#include - -#include "mmyth_ui.h" -#include "mmyth_videoplayer.h" -#include "mmyth_sdpreader.h" - -#include "esg_database.h" - -#include "ipd_demux.h" -#include "ipd_network.h" - -#ifdef INDT_IP_DECAPSULATOR -#include -#include -#endif - -/* Global flag/semaphore to control IP decapsulator threads */ -gboolean state_keep_running = 0; - - -typedef struct _GstPlayerWindowStateChange -{ - GstElement *play; - GstState old_state, new_state; - MMythUi *mmyth_ui; -} GstPlayerWindowStateChange; - -typedef struct _GstPlayerWindowTagFound -{ - GstElement *play; - GstTagList *taglist; - MMythUi *mmyth_ui; -} GstPlayerWindowTagFound; - - -GstElement *gst_pipeline, *gst_decoder, *gst_videosink; - -static gboolean idle_state (gpointer data); - -static gboolean -bus_call (GstBus * bus, GstMessage * msg, gpointer data) -{ - MMythUi *mmyth_ui = (MMythUi *) data; - GMainLoop *loop = mmyth_ui->loop; - - switch (GST_MESSAGE_TYPE (msg)) { - case GST_MESSAGE_EOS: - - if (mmyth_ui->idle_id != 0) { - g_source_remove (mmyth_ui->idle_id); - mmyth_ui->idle_id = 0; - } - - //g_idle_add ((GSourceFunc) idle_eos, data); - gst_element_set_state (GST_ELEMENT (GST_MESSAGE_SRC (msg)), - GST_STATE_READY); - break; - case GST_MESSAGE_ERROR:{ - gchar *debug; - GError *err; - - gst_message_parse_error (msg, &err, &debug); - g_free (debug); - - printf ("Error: %s\n", err->message); - g_error_free (err); - - g_main_loop_quit (loop); - } - break; - case GST_MESSAGE_STATE_CHANGED:{ - GstState oldstate; - GstState newstate; - GstState pending; - GstPlayerWindowStateChange *st = - g_new (GstPlayerWindowStateChange, 1); - - gst_message_parse_state_changed (msg, - &oldstate, - &newstate, &pending); - - st->play = mmyth_ui->play; - gst_object_ref (GST_OBJECT (mmyth_ui->play)); - st->old_state = oldstate; - st->new_state = newstate; - - st->mmyth_ui = mmyth_ui; - - /* State debug messages */ - printf ("oldstate = %s, newstate = %s, pendingstate = %s\n", - gst_element_state_get_name (oldstate), - gst_element_state_get_name (newstate), - gst_element_state_get_name (pending)); - - g_idle_add ((GSourceFunc) idle_state, st); - - } - break; - default: - printf (gst_message_type_get_name (GST_MESSAGE_TYPE (msg))); - printf ("\n"); - break; - } - - return TRUE; -} - - -static gboolean -cb_iterate (gpointer data) -{ - MMythUi *mmyth_ui = (MMythUi *) data; - //gboolean res; - - g_main_loop_run (mmyth_ui->loop); -/* - if (!GST_FLAG_IS_SET (mmyth_ui->play, GST_BIN_SELF_SCHEDULABLE)) { - res = gst_bin_iterate (GST_BIN (mmyth_ui->play)); - } else { - g_usleep (100); - res = (gst_element_get_state (mmyth_ui->play) == GST_STATE_PLAYING); - } - - if (!res) - mmyth_ui->idle_id = 0; - - return res; -*/ - return FALSE; - -} - -static gboolean -idle_state (gpointer data) -{ - GstPlayerWindowStateChange *st = data; - - if (st->old_state == GST_STATE_PLAYING) { - if (st->mmyth_ui->idle_id != 0) { - g_source_remove (st->mmyth_ui->idle_id); - st->mmyth_ui->idle_id = 0; - } - } - else if (st->new_state == GST_STATE_PLAYING) { - if (st->mmyth_ui->idle_id != 0) - g_source_remove (st->mmyth_ui->idle_id); - - st->mmyth_ui->idle_id = g_idle_add (cb_iterate, st->mmyth_ui); - } - - /* new movie loaded? */ - if (st->old_state == GST_STATE_READY && st->new_state > GST_STATE_READY) { - - /* gboolean have_video = FALSE; */ - - gtk_widget_show (st->mmyth_ui->videow); - - gtk_window_resize (GTK_WINDOW (st->mmyth_ui->main_window), 1, 1); - - } - - /* discarded movie? */ - if (st->old_state > GST_STATE_READY && st->new_state == GST_STATE_READY) { - - if (st->mmyth_ui->tagcache) { - gst_tag_list_free (st->mmyth_ui->tagcache); - st->mmyth_ui->tagcache = NULL; - } - } - - gst_object_unref (GST_OBJECT (st->play)); - //g_object_unref (G_OBJECT (st->win)); - g_free (st); - - /* once */ - return FALSE; -} - - - -static gboolean -expose (GtkWidget * widget, GdkEventExpose * event, gpointer user_data) -{ - MMythUi *mmyth_ui = (MMythUi *) user_data; - - gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (mmyth_ui->videosink), - GDK_WINDOW_XWINDOW (mmyth_ui->videow-> - window)); - return TRUE; -} - - -void -mmyth_player_init (MMythUi * mmyth_ui) -{ - GstElement *play; - GstElement *source, *parser, *decoder, *videosink; - - play = gst_pipeline_new ("video-player"); - source = gst_element_factory_make ("udpsrc", "file-source"); - parser = gst_element_factory_make ("rtph263pdepay", "rtp-demux"); - decoder = gst_element_factory_make ("ffdec_h263", "mpeg-decoder"); - videosink = gst_element_factory_make ("xvimagesink", "image-output"); - gst_pipeline = play; - gst_decoder = decoder; - gst_videosink = videosink; - - if (!(gst_pipeline && source && parser && decoder && videosink)) { - /* FIXME: hanlde the error correctly */ - /* video_alignment is not being created (below) - and is causing problems to the ui */ - g_print ("GstElement creation error!\n"); - return; - } - - g_object_set (G_OBJECT (videosink), "sync", FALSE, NULL); - - gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (gst_pipeline)), - bus_call, mmyth_ui); - - gst_bin_add_many (GST_BIN (gst_pipeline), source, parser, decoder, - videosink, NULL); - - { - GstCaps *rtpcaps = gst_caps_new_simple ("application/x-rtp", NULL); - gst_element_link_filtered(source, parser, rtpcaps); - } - - gst_element_link_many (/*source,*/ parser, decoder, videosink, NULL); - - /* actual window */ - mmyth_ui->play = play; - mmyth_ui->videosink = videosink; - mmyth_ui->udpsource = source; - - g_object_ref (mmyth_ui->play); - g_object_ref (mmyth_ui->videosink); - - /* video widget */ - //mmyth_ui->videow = gst_player_video_new (videosink, play); - mmyth_ui->videow = gtk_drawing_area_new (); - gtk_widget_set_size_request (mmyth_ui->videow, 300, 240); - - mmyth_ui->logo = gdk_pixbuf_new_from_file ("logo.png", NULL); - - - mmyth_ui->video_alignment = gtk_alignment_new (0.5, 0.5, 0, 0); - gtk_widget_hide (mmyth_ui->video_alignment); - - gtk_container_add (GTK_CONTAINER (mmyth_ui->video_alignment), - mmyth_ui->videow); - - g_signal_connect (mmyth_ui->videow, "expose-event", G_CALLBACK (expose), - mmyth_ui); - //g_signal_connect(mmyth_ui->videow, "size_request", G_CALLBACK(cb_preferred_video_size), mmyth_ui); - - - g_object_ref (mmyth_ui->videow); - g_object_ref (mmyth_ui->video_alignment); - - //gnome_app_set_contents (app, videow); - //gtk_widget_show (mmyth_ui->videow); - -//fail: -// gst_object_unref (GST_OBJECT (play)); -// return NULL; - -} - -void -mmyth_player_stop (MMythUi * mmyth_ui) -{ - gst_element_set_state (mmyth_ui->play, GST_STATE_NULL); - - if(mmyth_ui->videow != NULL) - gtk_widget_hide (mmyth_ui->videow); - - /* Disable IP Decapsulator playing threads */ - state_keep_running = FALSE; - -} - -static gboolean -idle_play (gpointer data) -{ - MMythUi *mmyth_ui = (MMythUi *) data; - - sleep (2); - - gst_element_set_state (mmyth_ui->play, GST_STATE_PLAYING); - - return FALSE; -} - - -/* Run IP decapsulator play function in a new thread. The thread is finished setting the - * semaphore "state_keep_running" to FALSE*/ -gpointer -run_ipd(gpointer data) -{ - GString *ip_addr = (GString*) data; - - state_keep_running = TRUE; - - printf("Inside thread\n"); - - ipd_mpe_play_section (ip_addr->str, &state_keep_running); - - return 0; -} - -void -mmyth_play_channel (MMythUi * mmyth_ui, gint service_number) -{ - ESGDatabase *esg_db; - DVBHService *service; - SDPData sdp_data; - GString *service_ip_addr; - - /* First verifies if there is a tuned network */ - if ( !ipd_network_is_tuned() ) { - /* FIXME: show alert and handle this error */ - g_warning ("Play not possible, network not tuned"); - return; - } - - esg_db = esg_database_get_instance(); - /* Gets the service structure */ - service = (DVBHService *) esg_database_get_service_from_number - (esg_db, service_number); - - /* Verifies if sdp fragment exists to this service */ - if ( service->sdp_file == NULL ) { - /* FIXME: Implement error handling */ - g_warning ("SDP fragment not available to access service"); - return; - } - - /* Parses the sdp to get ipv6 address and port */ - mmyth_sdp_parse_file (service->sdp_file->str, &sdp_data); - - /* Sets the gstreamer properties acording to the service access address */ - /* FIXME: Develop sdp_bin in gstreamer to give sdp file as pipeline config */ - g_object_set (G_OBJECT (mmyth_ui->udpsource), "multicast_group", - sdp_data.ip_addr->str, NULL); - g_object_set (G_OBJECT (mmyth_ui->udpsource), "port", sdp_data.video_port, NULL); - - /* Shows the video widget on screen */ - mmyth_ui_set_widget (mmyth_ui, mmyth_ui->video_uicommon); - - gtk_widget_show (mmyth_ui->videow); - gtk_widget_queue_draw (mmyth_ui->videow); - -#ifdef INDT_IP_DECAPSULATOR - /* Will be dealocated in run_ipd */ - service_ip_addr = g_string_new (sdp_data.ip_addr->str); - - /* Requests the IP decapsulator to play the channel stream*/ - g_thread_create (run_ipd, (gpointer) service_ip_addr, FALSE, NULL); -#endif - - //gst_element_set_state (mmyth_ui->play, GST_STATE_PLAYING); - g_idle_add (idle_play, mmyth_ui); -} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/gui/mmyth_videoplayer.h --- a/gmyth/src/gui/mmyth_videoplayer.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -#ifndef MMYTH_VIDEOPLAYER_H_ -#define MMYTH_VIDEOPLAYER_H_ - -#include "mmyth_ui.h" - -void mmyth_player_init (MMythUi * mmyth_ui); -void mmyth_player_stop (MMythUi * mmyth_ui); - -void mmyth_play_channel (MMythUi * mmyth_ui, gint service_id); - - -#endif /* MMYTH_VIDEOPLAYER_H_ */ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_common.c --- a/gmyth/src/libgmyth/gmyth_common.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +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 - * - *//* - * - * 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 - */ - -#include "gmyth_common.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) -{ - if (list == NULL) { - g_warning ("%s received null GList as parameter", __FUNCTION__); - return; - } - - 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) -{ - if (list == NULL) { - g_warning ("%s received null GList as parameter", __FUNCTION__); - return; - } - - g_list_foreach (list, free_program_data, NULL); - - g_list_free (list); -} - - -static void -free_channel_data(gpointer data, gpointer user_data) -{ - if(data) - g_free((GMythChannelInfo*) data); -} - -static void -free_program_data(gpointer data, gpointer user_data) -{ - if(data) - g_free((GMythProgramInfo*) data); -} - diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_common.h --- a/gmyth/src/libgmyth/gmyth_common.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,159 +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 - * - *//* - * - * 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 - -G_BEGIN_DECLS - -/** - * The GMythChannelInfo structure represents the channel information - * stored in the backend database. - */ -typedef struct { - /** The channel ID in backend database */ - int channel_ID; - - /** The channel name in backend database */ - GString *channel_name; - -} GMythChannelInfo; - - -/** - * 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. - */ -typedef struct { - - /** The channel unique ID. */ - GString *chanid; - - /** The program start time. */ - time_t startts; - /** The program end time. */ - time_t endts; - /** The recording schedule start time. */ - time_t recstartts; - /** The recording schedule end time */ - time_t 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; - int chancommfree; - GString *chanOutputFilters; - - GString *seriesid; - /** The program unique id. */ - GString *programid; - GString * catType; - - GString * sortTitle; - - /** A flag informing if the program has video or not. */ - gboolean isVideo; - int lenMins; - - GString *year; - double stars; - int repeat; - - time_t originalAirDate; - time_t lastmodified; - time_t lastInUseTime; - - gboolean hasAirDate; - - int spread; - int startCol; - -// enum RecStatusType recstatus; -// enum RecStatusType oldrecstatus; -// enum RecStatusType savedrecstatus; - int recpriority2; - int reactivate; - - int recordid; - int parentid; - //enum RecordingType rectype; - //enum RecordingDupInType dupin; - //enum RecordingDupMethodType dupmethod; - - /** The backend video source id associated to this program.*/ - int sourceid; - /** the backend input id associated to this program.*/ - int inputid; - /** The backend card id associated to this program.*/ - int cardid; - gboolean shareable; - gboolean duplicate; - - GString * schedulerid; - int findid; - - int programflags; - int transcoder; - - //proginfo->spread = -1; - //proginfo->programflags = proginfo->getProgramFlags(); - - GString *recgroup; - GString *playgroup; - int recpriority; - - /** The file size of the recorded program.*/ - long long filesize; - /** The file name of the recorded program.*/ - GString *pathname; - GString *hostname; - - /* AvailableStatusType availableStatus;*/ - -} GMythProgramInfo; - - -void gmyth_free_channel_list(GList *list); -void gmyth_free_program_list(GList *list); - -G_END_DECLS - -#endif /* GMYTH_COMMON_H_ */ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_context.c --- a/gmyth/src/libgmyth/gmyth_context.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,312 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_context.c - * - * @brief

GMythContext class contains general attributes and functions - * that express the connection state of each mythtvfrontend. - * - * 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 - */ - -#include "gmyth_context.h" - -#include -#include -#include -#include -#include -#include - -#include "gmyth_query.h" -#include "gmyth_socket.h" - -static void gmyth_context_class_init (GMythContextClass *klass); -static void gmyth_context_init (GMythContext *object); - -static void gmyth_context_dispose (GObject *object); -static void gmyth_context_finalize (GObject *object); - - -G_DEFINE_TYPE(GMythContext, gmyth_context, G_TYPE_OBJECT) - -static GStaticMutex mutex = G_STATIC_MUTEX_INIT; - -static GMythContext *gcontext = NULL; - -static void -gmyth_context_class_init (GMythContextClass *klass) -{ - GObjectClass *gobject_class; - - gobject_class = (GObjectClass *) klass; - - gobject_class->dispose = gmyth_context_dispose; - gobject_class->finalize = gmyth_context_finalize; -} - -static void -gmyth_context_init (GMythContext *gmyth_context) -{ - -} - -static void -gmyth_context_dispose (GObject *object) -{ - GMythContext *gmyth_context = GMYTH_CONTEXT(object); - - if ( gmyth_context->gmyth_settings != NULL ) { - g_object_unref (gmyth_context->gmyth_settings); - gmyth_context->gmyth_settings = NULL; - } - - if ( gmyth_context->localhostname != NULL ) { - g_string_free ( gmyth_context->localhostname, TRUE ); - gmyth_context->localhostname = NULL; - } - - if (gmyth_context->server_socket != NULL) { - g_object_unref (gmyth_context->server_socket); - gmyth_context->server_socket = NULL; - } - - G_OBJECT_CLASS (gmyth_context_parent_class)->dispose (object); -} - -static void -gmyth_context_finalize (GObject *object) -{ - g_signal_handlers_destroy (object); - - G_OBJECT_CLASS (gmyth_context_parent_class)->finalize (object); -} - -/** Gets the some important address translation info, - * from the client socket that will open a connection. - * - * @return gint error number - */ -static gint -myth_context_toaddrinfo( gchar *addr, gint port, struct addrinfo **addrInfo ) -{ - struct addrinfo hints; - gchar *portStr = g_strnfill( 32, ' ' ); - gint errorn = EADDRNOTAVAIL; - - memset( &hints, 0, sizeof(hints) ); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - - /* hints.ai_flags = AI_NUMERICHOST; */ - if ( port != -1 ) - sprintf(portStr, "%d", port); - else - portStr = NULL; - - g_debug( "[%s] Address: %s, port: %s\n", __FUNCTION__, addr, portStr ); - if ( ( errorn = getaddrinfo(addr, portStr, &hints, addrInfo) ) != 0 ) { - g_printerr( "[%s] Socket ERROR: %s\n", __FUNCTION__, gai_strerror(errorn) ); - } - - return errorn; - -} - -/** Initializes the GMythContext object. It reads local system information - * load gmyth user settings and start connection to the database. - * - * @return TRUE if initialization was successfull, - * FALSE if any error happens. - */ -gboolean -gmyth_context_initialize () -{ - GString *localhost = NULL; - - if (gcontext == NULL) { - gcontext = GMYTH_CONTEXT ( g_object_new (GMYTH_CONTEXT_TYPE, FALSE)); - } - - localhost = gmyth_socket_get_local_hostname( ); - - if (localhost==NULL || localhost->len <=0 ) { - g_warning ("[%s] Could not determine local hostname. Setting to 127.0.0.1", __FUNCTION__); - gcontext->localhostname = g_string_new ("127.0.0.1"); - } else { - gcontext->localhostname = localhost; - } - - if (gcontext->gmyth_settings) { - g_object_unref (gcontext->gmyth_settings); - gcontext->gmyth_settings = NULL; - } - - gcontext->gmyth_settings = gmyth_settings_new (); - if (!gmyth_settings_load (gcontext->gmyth_settings)) { - g_warning ("GMythContext: Settings file not opened!\n"); - } else { - g_debug ("GMythContext: Settings file loaded"); - } - - if (gcontext->server_socket != NULL) { - g_object_unref (gcontext->server_socket); - gcontext->server_socket = NULL; - } - - GString *server_hostname = - gmyth_settings_get_backend_hostname(gcontext->gmyth_settings); - int server_port = gmyth_settings_get_backend_port(gcontext->gmyth_settings); - - gcontext->server_socket = gmyth_socket_new (); - if (!gmyth_socket_connect_to_backend (gcontext->server_socket, - server_hostname->str, server_port, FALSE)) { - g_warning ("[%s] Socket connection to backend error!", __FUNCTION__); - g_object_unref (gcontext->server_socket); - gcontext->server_socket = NULL; - return FALSE; - } - - return TRUE; -} - -/** Formats a Mythtv protocol command based on strlist and sends it to - * the connected backend. The backend response is overwritten into strlist. - * - * @param strlist 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. - */ -gboolean -gmyth_context_send_receive_stringlist (GMythStringList *strlist) -{ - gint ok = -1; - - if (!gcontext || !(gcontext->server_socket)) { - g_warning ("[%s] GMythContext not initialized", __FUNCTION__); - return FALSE; - } - - //g_static_mutex_lock( &mutex ); - - ok = gmyth_socket_sendreceive_stringlist (gcontext->server_socket, strlist); - - //g_static_mutex_unlock( &mutex ); - - if (!ok) { - g_warning ("Connection to backend server lost"); - } - - return (ok ? TRUE : FALSE); -} - -/** Gets the GMythSettings object associated to this context. - * - * @return The GMythSettings object currently valid or NULL if the settings - * were not opened. - */ -GMythSettings* -gmyth_context_get_settings () -{ - if (!gcontext) { - g_warning ("[%s] GMythContext not initialized\n", __FUNCTION__); - return NULL; - } - - return gcontext->gmyth_settings; -} - -/** Gets the machine local hostname. - * - * @param hostname a valid GString object to be overwritten with the local - * hostname. - * @return true if the hostname was read, false if any error happened. - */ -gboolean -gmyth_context_get_local_hostname (GString *hostname) -{ - if (!hostname) { - g_warning ("[%s] Received null argument", __FUNCTION__); - return FALSE; - } - - g_string_assign (hostname, gcontext->localhostname->str); - - return TRUE; -} - -/** Gets a setting information from the backend mysql database. - * - * @param key The setting key to be retrieved. - * @param host the hostname associated to the desired setting. - * @param default_value the default setting value if could not query from - * backend database. - * @return The setting value loaded from database, or the given default value - * if the query fails. - */ -GString* -gmyth_context_get_setting_onhost (GString *key, GString *host, GString *default_value) -{ - GString *query_str; - - // TODO: Reuse msql query in gmyth_context - GMythQuery *gmyth_query = gmyth_query_new (); - - if (gmyth_query_connect (gmyth_query)) { - MYSQL_RES *msql_res; - MYSQL_ROW msql_row; - - query_str = g_string_new (""); - g_string_printf (query_str, "SELECT data FROM settings WHERE value = \"%s\" " - "AND hostname = \"%s\" ;", key->str, host->str); - - msql_res = gmyth_query_process_statement (gmyth_query, query_str->str); - if (msql_res) { - msql_row = mysql_fetch_row (msql_res); - if (msql_row != NULL) { - return g_string_new (msql_row[0]); - } - } - - g_object_unref (gmyth_query); - } else { - g_warning ("Database not open while trying to load setting: %s", key->str); - } - - - return default_value; -} - -/** Verify if the context is currently connected to a backend. - * - * @return true if connection was opened, false if not. - */ -gboolean -gmyth_context_check_connection () -{ - // FIXME: Check this based on socket states - if (!gcontext) { - g_warning ("[%s] GMythContext not initialized", __FUNCTION__); - return FALSE; - } - - return (gcontext->server_socket != NULL); -} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_context.h --- a/gmyth/src/libgmyth/gmyth_context.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_context.h - * - * @brief

GMythContext class contains general attributes and functions - * that express the connection state of each mythtvfrontend. - * - * 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_CONTEXT_H__ -#define __GMYTH_CONTEXT_H__ - -#include - -#include "gmyth_settings.h" -#include "gmyth_socket.h" -#include "gmyth_stringlist.h" - -G_BEGIN_DECLS - -#define GMYTH_CONTEXT_TYPE (gmyth_context_get_type ()) -#define GMYTH_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_CONTEXT_TYPE, GMythContext)) -#define GMYTH_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_CONTEXT_TYPE, GMythContextClass)) -#define IS_GMYTH_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_CONTEXT_TYPE)) -#define IS_GMYTH_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_CONTEXT_TYPE)) -#define GMYTH_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_CONTEXT_TYPE, GMythContextClass)) - -#define MYTHTV_VERSION_DEFAULT 30 - -typedef struct _GMythContext GMythContext; -typedef struct _GMythContextClass GMythContextClass; - -struct _GMythContextClass -{ - GObjectClass parent_class; - - /* callbacks */ - /* no one for now */ -}; - -struct _GMythContext -{ - GObject parent; - - GMythSettings *gmyth_settings; - GMythSocket *server_socket; - - GString *localhostname; -}; - - -GType gmyth_context_get_type (void); -void gmyth_context_create(); - -gboolean gmyth_context_initialize (); -gboolean gmyth_context_check_connection (); -GMythSettings* gmyth_context_get_settings (); - -gboolean gmyth_context_send_receive_stringlist (GMythStringList *strlist); - -GString* gmyth_context_get_setting_onhost (GString *key, GString *host, GString *default_value); -gboolean gmyth_context_get_local_hostname (GString *hostname); - -GString* gmyth_context_get_setting_onhost (GString *key, GString *host, GString *default_value); - - -G_END_DECLS - -#endif /* __GMYTH_CONTEXT_H__ */ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_epg.c --- a/gmyth/src/libgmyth/gmyth_epg.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,278 +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 - */ - -#include -#include -#include -#include - -#include "gmyth_epg.h" -#include "gmyth_util.h" - -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; - - gobject_class = (GObjectClass *) klass; - - gobject_class->dispose = gmyth_epg_dispose; - gobject_class->finalize = gmyth_epg_finalize; -} - -static void -gmyth_epg_init (GMythEPG *gmyth_epg) -{ - gmyth_epg->sqlquery = gmyth_query_new (); -} - -static void -gmyth_epg_dispose (GObject *object) -{ - //GMythEPG *gmyth_epg = GMYTH_EPG(object); - - 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) -{ - assert(gmyth_epg); - - if (gmyth_epg->sqlquery == NULL) { - g_warning ("[%s] GMythEPG not initialized", __FUNCTION__); - return FALSE; - } - - if (!gmyth_query_connect(gmyth_epg->sqlquery)) { - g_warning ("[%s] Error while connecting to db", __FUNCTION__); - return FALSE; - } - - 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) -{ - assert(gmyth_epg); - - if (gmyth_epg->sqlquery != NULL) { - g_object_unref (gmyth_epg->sqlquery); - } - - return TRUE; -} - -/** Retrieves the available list of channels from the backend Mysql database. - * - * @param gmyth_epg the GMythEPG instance. - * @param glist_ptr the GList 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; - - assert(gmyth_epg); - - msql_res = gmyth_query_process_statement (gmyth_epg->sqlquery, - "SELECT chanid,name FROM channel;"); - - (*glist_ptr) = NULL; - - if (msql_res == NULL) { - g_warning ("[%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 = atoi (row[0]); - channel_info->channel_name = g_string_new (row[1]); - - (*glist_ptr) = g_list_append ((*glist_ptr), channel_info); - } - } - mysql_free_result (msql_res); - return (!(*glist_ptr)) ? 0 : g_list_length (*glist_ptr); -} - -/** - * Retrieves the available list of channels from the backend Mysql database. - * - * @param gmyth_epg the GMythEPG instance. - * @param proglist the GList 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, time_t starttime, time_t endtime) -{ - GString *startts = gmyth_util_time_to_string(starttime); - GString *endts = gmyth_util_time_to_string(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, oldrecstatus.recordid, " - " oldrecstatus.rectype, oldrecstatus.recstatus, " - " oldrecstatus.findid " - "FROM program " - "LEFT JOIN channel ON program.chanid = channel.chanid " - "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->str, endts->str); - - 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) { - g_warning ("[%s] msql query returned NULL MYSQL_RES", __FUNCTION__); - return -1; - } - - (*proglist) = NULL; - while ((row = mysql_fetch_row (res_set)) != NULL) { - - GMythProgramInfo *p = g_new0 (GMythProgramInfo, 1); - p->chanid = g_string_new (row[0]); - - p->startts = gmyth_util_string_to_time (g_string_new (row[1])); - p->endts = gmyth_util_string_to_time (g_string_new (row[2])); - - p->recstartts = p->startts; - p->recendts = p->endts; - p->lastmodified = p->startts; - - 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 = atoi(row[10]); - p->chancommfree = atoi(row[11]); - p->chanOutputFilters = g_string_new (row[12]); - p->seriesid = g_string_new (row[13]); - p->programid = g_string_new (row[14]); - p->year = g_string_new (row[15]); - p->stars = atof(row[16]); - - if (!row[17] || !strcmp(row[17], "")) { - p->originalAirDate = 0; - p->hasAirDate = FALSE; - } else { - p->originalAirDate = gmyth_util_string_to_time (g_string_new (row[17])); - p->hasAirDate = TRUE; - } - - p->catType = g_string_new (row[18]); - - *proglist = g_list_append((*proglist), p); - } - - /* deallocate */ - mysql_free_result (res_set); - g_string_free(querystr, TRUE); - - return TRUE; -} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_epg.h --- a/gmyth/src/libgmyth/gmyth_epg.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +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_CAST ((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; -}; - -GType gmyth_epg_get_type (void); - -GMythEPG* gmyth_epg_new (void); - -gboolean gmyth_epg_connect (GMythEPG *gmyth_epg); -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, - const gint chanNum, time_t starttime, time_t endtime); - -#endif /*GMYTH_EPG_H_*/ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_query.c --- a/gmyth/src/libgmyth/gmyth_query.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,221 +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 - */ - -#include -#include -#include - -#include "gmyth_query.h" -#include "gmyth_settings.h" -#include "gmyth_context.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) -{ - GMythSettings *gmyth_settings = gmyth_context_get_settings (); - - gmyth_query->opt_host_name = gmyth_settings_get_backend_hostname(gmyth_settings); - gmyth_query->opt_user_name = gmyth_settings_get_username(gmyth_settings); - gmyth_query->opt_password = gmyth_settings_get_password(gmyth_settings); - gmyth_query->opt_db_name = gmyth_settings_get_dbname(gmyth_settings); - - /* 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); - - /* disconnect from server */ - gmyth_query_disconnect (gmyth_query); - - 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; -} - -/** Connects to the Mysql database in the backend. The backend address - * is loaded from the GMythSettings 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) -{ - char *opt_host_name; - char *opt_user_name; - char *opt_password; - char *opt_db_name; - - assert(gmyth_query); - - opt_host_name = (gmyth_query->opt_host_name ? gmyth_query->opt_host_name->str : NULL); - opt_db_name = (gmyth_query->opt_db_name ? gmyth_query->opt_db_name->str : NULL); - opt_user_name = (gmyth_query->opt_user_name ? gmyth_query->opt_user_name->str : NULL); - opt_password = (gmyth_query->opt_password ? gmyth_query->opt_password->str : NULL); - - - if (gmyth_query->conn == NULL) { - gmyth_query_print_error (NULL, "mysql_init() failed (probably out of memory)"); - return FALSE; - } - - /* connect to server */ - if (mysql_real_connect (gmyth_query->conn, opt_host_name, - opt_user_name, opt_password, opt_db_name, - 0, NULL, 0) == NULL) { - - gmyth_query_print_error (gmyth_query->conn, "mysql_real_connect() failed"); - return FALSE; - } - - g_debug ("[%s] Connection to Mysql server succeeded!", __FUNCTION__); - - 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) -{ - assert(gmyth_query); - - /* TODO: Check how to return error */ - g_debug ("[%s] Closing gmyth_query->conn", __FUNCTION__); - mysql_close (gmyth_query->conn); - - return TRUE; -} - -static void -gmyth_query_print_error (MYSQL *conn, char *message) -{ - fprintf (stderr, "%s\n", message); - - if (conn != NULL) { -#if MYSQL_VERSION_ID >= 40101 - fprintf (stderr, "Error %u (%s): %s\n", - mysql_errno (conn), mysql_sqlstate(conn), mysql_error (conn)); -#else - fprintf (stderr, "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) -{ - MYSQL_RES *res_set; - - assert(gmyth_query); - - g_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 */ - res_set = mysql_store_result (gmyth_query->conn); - if (res_set) { - return res_set; - } else if (mysql_field_count (gmyth_query->conn) == 0) { - g_debug ("%lu rows affected\n", - (unsigned long) mysql_affected_rows (gmyth_query->conn)); - } else { - gmyth_query_print_error (gmyth_query->conn, "Could not retrieve result set"); - } - - return NULL; -} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_query.h --- a/gmyth/src/libgmyth/gmyth_query.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +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 - -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_CAST ((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; - - GString *opt_host_name; /* server host (default=localhost) */ - GString *opt_user_name; /* username (default=login name) */ - GString *opt_password; /* password (default=none) */ - unsigned int opt_port_num; /* port number (use built-in value) */ - GString *opt_socket_name; /* socket name (use built-in value) */ - GString *opt_db_name; /* database name (default=none) */ - unsigned int opt_flags; /* connection flags (none) */ - MYSQL *conn; /* pointer to connection handler */ -}; - - -GType gmyth_query_get_type (void); - -GMythQuery* gmyth_query_new (); -MYSQL_RES * gmyth_query_process_statement - (GMythQuery *gmyth_query, char *stmt_str); - -gboolean gmyth_query_connect (GMythQuery *gmyth_query); -gboolean gmyth_query_disconnect (GMythQuery *gmyth_query); - -G_END_DECLS - -#endif /* __GMYTH_QUERY_H__ */ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_remote_encoder.c --- a/gmyth/src/libgmyth/gmyth_remote_encoder.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,207 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_remote_encoder.c - * - * @brief

GMythRemoteEncoder class 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 - * - *//* - * - * 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 - */ - -#include "gmyth_remote_encoder.h" - -#include - -#include "gmyth_stringlist.h" - -static void gmyth_remote_encoder_class_init (GMythRemoteEncoderClass *klass); -static void gmyth_remote_encoder_init (GMythRemoteEncoder *object); - -static void gmyth_remote_encoder_dispose (GObject *object); -static void gmyth_remote_encoder_finalize (GObject *object); - -G_DEFINE_TYPE(GMythRemoteEncoder, gmyth_remote_encoder, G_TYPE_OBJECT) - -static void -gmyth_remote_encoder_class_init (GMythRemoteEncoderClass *klass) -{ - GObjectClass *gobject_class; - - gobject_class = (GObjectClass *) klass; - - gobject_class->dispose = gmyth_remote_encoder_dispose; - gobject_class->finalize = gmyth_remote_encoder_finalize; -} - -static void -gmyth_remote_encoder_init (GMythRemoteEncoder *gmyth_remote_encoder) -{ -} - -static void -gmyth_remote_encoder_dispose (GObject *object) -{ - // GMythRemoteEncoder *gmyth_remote_encoder = GMYTH_REMOTE_ENCODER(object); - - G_OBJECT_CLASS (gmyth_remote_encoder_parent_class)->dispose (object); -} - - -static void -gmyth_remote_encoder_finalize (GObject *object) -{ - g_signal_handlers_destroy (object); - - GMythRemoteEncoder *remote_encoder = GMYTH_REMOTE_ENCODER(object); - - g_debug ("[%s] Closing control socket", __FUNCTION__); - gmyth_socket_close_connection(remote_encoder->myth_socket); - g_object_unref (remote_encoder->myth_socket); - - G_OBJECT_CLASS (gmyth_remote_encoder_parent_class)->finalize (object); -} - -/** Creates a new instance of GMythRemoteEncoder. - * - * @return a new instance of GMythRemoteEncoder. - */ -GMythRemoteEncoder* -gmyth_remote_encoder_new (int num, GString *hostname, gshort port) -{ - GMythRemoteEncoder *encoder = GMYTH_REMOTE_ENCODER ( g_object_new ( - GMYTH_REMOTE_ENCODER_TYPE, FALSE )); - - encoder->recorder_num = num; - encoder->hostname = g_string_new (hostname->str); - encoder->port = port; - - return encoder; -} - -/** Configures the remote encoder instance connecting it to Mythtv backend. - * - * @param remote_encoder the GMythRemoteEncoder instance. - * @return TRUE if successfull, FALSE if any error happens. - */ -gboolean -gmyth_remote_encoder_setup (GMythRemoteEncoder *remote_encoder) -{ - assert (remote_encoder); - g_debug ("[%s] Creating socket and connecting to backend", __FUNCTION__); - - if (remote_encoder->myth_socket == NULL) { - - remote_encoder->myth_socket = gmyth_socket_new (); - - if (!gmyth_socket_connect_to_backend (remote_encoder->myth_socket, remote_encoder->hostname->str, - remote_encoder->port, TRUE) ) { - g_warning ("GMythRemoteEncoder: Connection to backend failed"); - return FALSE; - } - - } else { - g_warning("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 remote_encoder The GMythRemoteEncoder instance. - * @param tvchain_id The tvchain unique id. - * @return true if success, false if any error happens. - */ -gboolean -gmyth_remote_encoder_spawntv (GMythRemoteEncoder *remote_encoder, GString *tvchain_id) -{ - GMythStringList *str_list; - GString *tmp_str; - - g_debug ("[%s] Spawntv with tvchain_id = %s", __FUNCTION__, tvchain_id->str); - - str_list = gmyth_string_list_new (); - - tmp_str = g_string_new ("QUERY_RECORDER "); - g_string_append_printf (tmp_str, "%d", remote_encoder->recorder_num); - - gmyth_string_list_append_string (str_list, tmp_str); - gmyth_string_list_append_string (str_list, g_string_new ("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 (remote_encoder->myth_socket, str_list); - - g_string_free (tmp_str, TRUE); - - tmp_str = gmyth_string_list_get_string (str_list, 0); - if (tmp_str == NULL) { - g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str); - return FALSE; - } - - if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) { - g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str); - g_object_unref (str_list); - return FALSE; - } - - g_object_unref (str_list); - return TRUE; - -} - -/** Sends the command STOP_LIVETV to Mythtv backend. - * - * @param remote_encoder the GMythRemoteEncoder instance. - * @return true if success, false if any error happens. - */ -gboolean -gmyth_remote_encoder_stop_livetv (GMythRemoteEncoder *remote_encoder) -{ - GMythStringList *str_list; - GString *tmp_str; - - g_debug ("[%s]", __FUNCTION__); - - str_list = gmyth_string_list_new (); - - tmp_str = g_string_new ("QUERY_RECORDER "); - g_string_append_printf (tmp_str, "%d", remote_encoder->recorder_num); - gmyth_string_list_append_string (str_list, g_string_new ("STOP_LIVETV")); - - gmyth_socket_sendreceive_stringlist (remote_encoder->myth_socket, str_list); - - g_string_free (tmp_str, TRUE); - - tmp_str = gmyth_string_list_get_string (str_list, 0); - if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) { - g_warning ("[%s] Stop livetv request returned %s", __FUNCTION__, tmp_str->str); - g_object_unref (str_list); - return FALSE; - } - - g_object_unref (str_list); - return TRUE; - -} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_remote_encoder.h --- a/gmyth/src/libgmyth/gmyth_remote_encoder.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_remote_encoder.h - * - * @brief

GMythRemoteEncoder class defines functions for playing live tv. - * - * 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_REMOTE_ENCODER_H__ -#define __GMYTH_REMOTE_ENCODER_H__ - -#include - -#include "gmyth_socket.h" - -#include -#include -#include -#include -#include -#include - -G_BEGIN_DECLS - -#define GMYTH_REMOTE_ENCODER_TYPE (gmyth_remote_encoder_get_type ()) -#define GMYTH_REMOTE_ENCODER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_REMOTE_ENCODER_TYPE, GMythRemoteEncoder)) -#define GMYTH_REMOTE_ENCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_REMOTE_ENCODER_TYPE, GMythRemoteEncoderClass)) -#define IS_GMYTH_REMOTE_ENCODER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_REMOTE_ENCODER_TYPE)) -#define IS_GMYTH_REMOTE_ENCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_REMOTE_ENCODER_TYPE)) -#define GMYTH_REMOTE_ENCODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_REMOTE_ENCODER_TYPE, GMythRemoteEncoderClass)) - - -typedef struct _GMythRemoteEncoder GMythRemoteEncoder; -typedef struct _GMythRemoteEncoderClass GMythRemoteEncoderClass; - -struct _GMythRemoteEncoderClass -{ - GObjectClass parent_class; - - /* callbacks */ - /* no one for now */ -}; - -struct _GMythRemoteEncoder -{ - GObject parent; - - /* socket descriptor */ - GMythSocket *myth_socket; - - int recorder_num; - GString *hostname; - int port; -}; - - -GType gmyth_remote_encoder_get_type (void); - -GMythRemoteEncoder* gmyth_remote_encoder_new (int num, - GString *hostname, - gshort port); - -gboolean gmyth_remote_encoder_setup (GMythRemoteEncoder *encoder); -gboolean gmyth_remote_encoder_spawntv (GMythRemoteEncoder *remote_encoder, - GString *tvchain_id); -gboolean gmyth_remote_encoder_stop_livetv (GMythRemoteEncoder *remote_encoder); - -G_END_DECLS - -#endif /* __GMYTH_REMOTE_ENCODER_H__ */ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_remote_util.c --- a/gmyth/src/libgmyth/gmyth_remote_util.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +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 - * - *//* - * - * 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 - */ - -#include "gmyth_remote_util.h" - -#include "gmyth_context.h" -#include "gmyth_remote_encoder.h" -#include "gmyth_stringlist.h" - -/** Requests the Mythtv backend for a free remote recorder. - * - * @param curr The recorder index, or -1 to consider the first one. - * @return the remote encoder instance available, or NULL if any error happens. - */ -GMythRemoteEncoder* -remote_request_next_free_recorder (int curr) -{ - GMythRemoteEncoder *encoder; - GString *hostname; - int num, port; - - GMythStringList *strlist = gmyth_string_list_new(); - - g_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_context_send_receive_stringlist(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); - - g_debug ("[%s] Free recorder info received: num: %d, hostname: %s, port: %d", - __FUNCTION__, num, hostname->str, port); - - encoder = gmyth_remote_encoder_new (num, hostname, port); - - g_object_unref (strlist); - - return encoder; -} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_remote_util.h --- a/gmyth/src/libgmyth/gmyth_remote_util.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +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_remote_encoder.h" - -G_BEGIN_DECLS - -GMythRemoteEncoder* remote_request_next_free_recorder (int curr); - -G_END_DECLS - -#endif diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_scheduler.c --- a/gmyth/src/libgmyth/gmyth_scheduler.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,610 +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 - */ - -#include - -#include "gmyth_scheduler.h" - -#include "gmyth_context.h" -#include "gmyth_util.h" -#include "gmyth_query.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 gint get_record_id_from_database (GMythScheduler *scheduler); -static void update_backend (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 = 0; - sched->playgroup = 0; - - sched->prefinput = 0; - sched->inactive = 0; - - sched->searchType = g_string_new(""); - sched->searchForWhat = g_string_new(""); - - sched->msqlquery = gmyth_query_new (); -} - -static void -gmyth_scheduler_dispose (GObject *object) -{ - 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; -} - -/** 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 (GMythScheduler *scheduler) -{ - assert(scheduler); - - if (scheduler->msqlquery == NULL) { - g_warning ("[%s] MMythScheduler not initialized", __FUNCTION__); - return FALSE; - } - - if (!gmyth_query_connect(scheduler->msqlquery)) { - 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) { - g_object_unref (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 (""); - GString *date_time = g_string_new (""); - - assert(scheduler); - - g_string_printf (query_str, - "SELECT recordid,programid,chanid,starttime,startdate," - "endtime,enddate,title,subtitle,description,category 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); - - schedule->record_id = atoi (row[0]); - schedule->program_id = atoi (row[1]); - schedule->channel_id = atoi (row[2]); - - /* generate a time_t from a time and a date db field */ - g_string_printf (date_time, "%s %s", row[4], row[3]); - - schedule->start_time = gmyth_util_string_to_time (date_time); - - /* generate a time_t from a time and a date db field */ - g_string_printf (date_time, "%s %s", row[6], row[5]); - - schedule->end_time = gmyth_util_string_to_time (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]); - - (*schedule_list) = g_list_append (*(schedule_list), schedule); - } - } - - mysql_free_result (msql_res); - g_string_free(query_str, TRUE); - g_string_free(date_time, 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 (""); - GString *date_time = g_string_new (""); - - assert(scheduler); - - g_string_printf (query_str, - "SELECT recordid,programid,chanid,starttime,progstart," - "endtime,progend,title,subtitle,description,category,basename FROM recorded;"); - - 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 = atoi (row[0]); - record->program_id = atoi (row[1]); - record->channel_id = atoi (row[2]); - - /* the db field time already contains the date. therefore - * we are not using the date field */ - /* generate a time_t from a time and a date db field */ - /* g_string_printf (date_time, "%s %s", row[4], row[3]); */ - g_string_printf (date_time, "%s", row[3]); - - record->start_time = gmyth_util_string_to_time (date_time); - - /* the db field time already contains the date. therefore - * we are not using the date field */ - /* generate a time_t from a time and a date db field */ - /* g_string_printf (date_time, "%s %s", row[6], row[5]); */ - g_string_printf (date_time, "%s", row[5]); - - record->end_time = gmyth_util_string_to_time (date_time); - - 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->basename = g_string_new (row[11]); - - *recorded_list = g_list_append (*recorded_list, record); - } - } - - mysql_free_result (msql_res); - g_string_free(query_str, TRUE); - g_string_free(date_time, TRUE); - - return (*recorded_list == NULL) ? 0 : g_list_length (*recorded_list); -} - -/** 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) -{ - struct tm start_tm; - struct tm end_tm; - - 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 0; - } - - /* manipulating time */ - if(localtime_r(&schedule_info->start_time, &start_tm) == NULL) { - g_warning ("localtime_r error in libgmyth scheduler!\n"); - return FALSE; - } - - if(localtime_r(&schedule_info->end_time, &end_tm) == NULL) { - g_warning ("localtime_r error in libgmyth scheduler!\n"); - return FALSE; - } - - //TODO: verify if this funtion realy does what it should do! - g_string_printf (query_str, "REPLACE INTO record " - "(recordid, type, chanid, starttime, " - "startdate, endtime, enddate, title," - "profile, recpriority, maxnewest, inactive, " - "maxepisodes, autoexpire, startoffset, endoffset, " - "recgroup, dupmethod, dupin, station, " - "autocommflag, findday, findtime, findid, " - "search, autotranscode, transcoder, tsdefault, " - "autouserjob1, autouserjob2, autouserjob3, autouserjob4) " - " values ( %d, 1, %d, \"%02d:%02d:00\"," //recordid, type, chanid, starttime - " \"%d-%02d-%02d\", \"%02d:%02d:00\", \"%04d-%02d-%02d\", \"%s\"," - //startdate, endtime, enddate, title - "DEFAULT, 0, 0, 0, " //profile, recpriority, maxnewest, inactive - "0, 1, 0, 0, " //maxepisodes, autoexpire, startoffset, endoffset - "DEFAULT, 6, 15, %d, " //recgroup, dupmethod, dupin, station - "1, %d, \"%02d:%02d:00\", %d, " //autocommflag, findday, findtime, findid - "5, 0, 29, 1, " //search, autotranscode, transcoder, tsdefault - "0, 0, 0, 0 );", //autouserjob1, autouserjob2, autouserjob3, autouserjob4 - schedule_info->record_id, schedule_info->channel_id, - start_tm.tm_hour, start_tm.tm_min, - start_tm.tm_year+1900, start_tm.tm_mon+1, - start_tm.tm_mday, - end_tm.tm_hour, end_tm.tm_min, - end_tm.tm_year+1900, end_tm.tm_mon+1, - end_tm.tm_mday, schedule_info->title->str, //title - schedule_info->channel_id,//station - start_tm.tm_wday+1, //findday - start_tm.tm_hour, start_tm.tm_min, //findtime - (gint)(schedule_info->start_time/60/60/24 + 719528)//findid - ); - - msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); - - /* FIXME: currently no way to detect db error in UPDATE, REPLACES! - if (msql_res == NULL) { - g_warning ("DB retrieval of recording list failed"); - return -1; - }*/ - - /* TODO: verify record_id = -1 semantics */ - if (schedule_info->record_id <= 0) - schedule_info->record_id = get_record_id_from_database(scheduler); - - /* Notify the backend of changes */ - update_backend(schedule_info->record_id); - - /* free allocated memory */ - mysql_free_result (msql_res); - g_string_free(query_str, TRUE); - - return 1; -} - -/** Requests the Mysql database in the backend to remove an existing schedule. - * - * @param scheduler the GMythScheduler instance. - * @param record_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 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 record WHERE recordid=%d", record_id); - - msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); - - if (msql_res == NULL) { - g_warning ("[%s] Error while trying to delete a schedule in the database", __FUNCTION__); - return FALSE; - } - - update_backend(record_id);// Notify the backend of the changes - - mysql_free_result (msql_res); - g_string_free(query_str, TRUE); - - return TRUE; -} - -/** 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); - - msql_res = gmyth_query_process_statement (scheduler->msqlquery, query_str->str); - - update_backend(record_id);// Notify the backend of the changes - - mysql_free_result (msql_res); - g_string_free(query_str, TRUE); - - return TRUE; -} - -/** 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, time_t starttime) -{ - MYSQL_RES *msql_res; - GMythProgramInfo *proginfo = NULL; - GString *query_str = g_string_new(""); - GString *time_str = gmyth_util_time_to_string (starttime); - - assert(scheduler); - - 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->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 = g_new0 (GMythProgramInfo, 1); - - proginfo->chanid = g_string_new (msql_row[0]); - proginfo->startts = gmyth_util_string_to_time (g_string_new (msql_row[23])); - proginfo->endts = gmyth_util_string_to_time (g_string_new (msql_row[24])); - proginfo->recstartts = gmyth_util_string_to_time (g_string_new (msql_row[1])); - proginfo->recendts = gmyth_util_string_to_time (g_string_new (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 = atoi (msql_row[9]); - proginfo->chanOutputFilters = g_string_new (msql_row[10]); - proginfo->seriesid = g_string_new (msql_row[11]); - proginfo->programid = g_string_new (msql_row[12]); - proginfo->filesize = atoll (msql_row[13]); - - proginfo->lastmodified = gmyth_util_string_to_time (g_string_new (msql_row[14])); - - proginfo->stars = atof (msql_row[15]); - proginfo->repeat = atoi (msql_row[16]); - - if (msql_row[17] == NULL) { - proginfo->originalAirDate = 0; - proginfo->hasAirDate = FALSE; - } else { - proginfo->originalAirDate = gmyth_util_string_to_time (g_string_new (msql_row[17])); - proginfo->hasAirDate = TRUE; - } - - proginfo->hostname = g_string_new (msql_row[18]); - proginfo->recordid = atoi (msql_row[19]); - proginfo->transcoder = atoi (msql_row[20]); - - //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 = atoi (msql_row[22]); - - proginfo->pathname = g_string_new (msql_row[25]); - - g_debug ("One program info loaded from mysql database\n"); - } - } - - mysql_free_result (msql_res); - g_string_free(query_str, TRUE); - g_string_free(time_str, TRUE); - - return proginfo; -} - -/** Retrieves the next record id. - * - * @param scheduler The GMythScheduler instance. - * @return gint record_id if success, -1 otherwise - */ -static gint -get_record_id_from_database (GMythScheduler *scheduler) -{ - gint record_id; - - assert(scheduler); - - if (scheduler->msqlquery == NULL) { - g_warning ("[%s] Scheduler db connection not initialized", __FUNCTION__); - return 0; - } - - record_id = mysql_insert_id (scheduler->msqlquery->conn); - - return record_id; -} - -/** Notifies the backend of an update in the db. - * - * @param record_id the id of the modified recording. - */ -static void -update_backend(gint record_id)//fixme: put void and discovery record_id inside -{ - GMythStringList *strlist = gmyth_string_list_new (); - GString *datastr = g_string_new ("RESCHEDULE_RECORDINGS "); - - g_string_append_printf (datastr, "%d", record_id); - gmyth_string_list_append_string (strlist, datastr); - - gmyth_context_send_receive_stringlist (strlist); - - g_string_free(datastr, TRUE); - g_object_unref(strlist); -} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_scheduler.h --- a/gmyth/src/libgmyth/gmyth_scheduler.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +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" - -G_BEGIN_DECLS - -#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_CAST ((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; - - /* callbacks */ - /* no one for now */ -}; - -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 *searchType; - GString *searchForWhat; - - GMythQuery *msqlquery; -}; - -typedef struct { - gint record_id; - gint program_id; - gint channel_id; - - time_t start_time; - time_t end_time; - - GString *title; - GString *subtitle; - GString *description; - GString *category; - -} ScheduleInfo; - -typedef struct { - gint record_id; - gint program_id; - gint channel_id; - - time_t start_time; - time_t end_time; - - GString *title; - GString *subtitle; - GString *description; - GString *category; - - GString *basename; - -} RecordedInfo; - - -GType gmyth_scheduler_get_type (void); - -GMythScheduler* gmyth_scheduler_new (); -gboolean gmyth_scheduler_connect (GMythScheduler *scheduler); -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); - -GMythProgramInfo* gmyth_scheduler_get_recorded (GMythScheduler *scheduler, - GString *channel, time_t starttime); - -gint gmyth_scheduler_add_schedule(GMythScheduler *scheduler, - ScheduleInfo *schedule_info); - -gint gmyth_scheduler_delete_schedule (GMythScheduler *scheduler, - gint record_id); -gint gmyth_scheduler_delete_recorded (GMythScheduler *scheduler, - gint record_id); - -G_END_DECLS - -#endif /* __GMYTH_SCHEDULER_H__ */ - diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_settings.c --- a/gmyth/src/libgmyth/gmyth_settings.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,417 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_settings.c - * - * @brief

This component contains functions acessing and modifying - * user and program settings. - * - * The standard settings file is created in the user home folder, in the - * file ~/.mmyth/settings.dat. - * - * 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 - */ - -#include "gmyth_settings.h" - -#include -#include -#include -#include - -#include -#include -#include - -#define GMYTH_SETTINGS_FILE_NAME "settings.dat" -#define GMYTH_SETTINGS_DIR ".mmyth" - -static void gmyth_settings_class_init (GMythSettingsClass *klass); -static void gmyth_settings_init (GMythSettings *object); - -static void gmyth_settings_dispose (GObject *object); -static void gmyth_settings_finalize (GObject *object); - -static void fill_settings_data(GMythSettings *gmyth_settings, char* line); - -G_DEFINE_TYPE(GMythSettings, gmyth_settings, G_TYPE_OBJECT) - -static void -gmyth_settings_class_init (GMythSettingsClass *klass) -{ - GObjectClass *gobject_class; - - gobject_class = (GObjectClass *) klass; - - gobject_class->dispose = gmyth_settings_dispose; - gobject_class->finalize = gmyth_settings_finalize; -} - -static void -gmyth_settings_init (GMythSettings *gmyth_settings) -{ - - gmyth_settings->settings_file = NULL; - - gmyth_settings->backend_hostname = g_string_new("127.0.0.1"); - gmyth_settings->backend_port = 6543; - gmyth_settings->mysql_dbname = g_string_new("mythconverg"); - gmyth_settings->mysql_username = g_string_new("mythtv"); - gmyth_settings->mysql_password = g_string_new("mythtv"); - gmyth_settings->database_type = g_string_new("mysql"); - -} - - -static void -gmyth_settings_dispose (GObject *object) -{ - GMythSettings *gmyth_settings = GMYTH_SETTINGS(object); - - if ( gmyth_settings->backend_hostname != NULL ) - g_string_free( gmyth_settings->backend_hostname, TRUE ); - if ( gmyth_settings->mysql_dbname != NULL ) - g_string_free( gmyth_settings->mysql_dbname, TRUE ); - if ( gmyth_settings->mysql_username != NULL ) - g_string_free( gmyth_settings->mysql_username, TRUE ); - if ( gmyth_settings->mysql_password != NULL ) - g_string_free( gmyth_settings->mysql_password, TRUE ); - if ( gmyth_settings->database_type != NULL ) - g_string_free( gmyth_settings->database_type, TRUE ); - - G_OBJECT_CLASS (gmyth_settings_parent_class)->dispose (object); -} - -static void -gmyth_settings_finalize (GObject *object) -{ - g_signal_handlers_destroy (object); - - G_OBJECT_CLASS (gmyth_settings_parent_class)->finalize (object); -} - -/** Creates a new instance of GMythSettings. - * - * @return a new instance of GMythSettings. - */ -GMythSettings* -gmyth_settings_new (void) -{ - GMythSettings *gmyth_settings = GMYTH_SETTINGS (g_object_new(GMYTH_SETTINGS_TYPE, NULL)); - - return gmyth_settings; -} - -static gboolean -gmyth_settings_ensure_dir_exists (const gchar *dir) -{ - - g_debug ("[%s] \tdir = %s\n", __FUNCTION__, dir); - - if (g_file_test (dir, G_FILE_TEST_IS_DIR) == FALSE) { - if (g_file_test (dir, G_FILE_TEST_EXISTS) == TRUE) { - g_warning ("%s exists, please move it out of the way.", dir); - return FALSE; - } - - if (mkdir (dir, 488) != 0) { - g_warning ("Failed to create directory %s.", dir); - return FALSE; - } - } - - return TRUE; -} - -static gboolean -gmyth_settings_ensure_file_exists (const gchar *file_name) { - - int file = 0; - - if ( g_file_test( file_name, G_FILE_TEST_EXISTS ) == FALSE ) { - g_debug ( "\n\tCreating %s file...\n", file_name ); - file = creat( file_name, S_IRWXU | S_IRWXO | S_IRWXG ); - - if ( close( file ) == -1 ) - return FALSE; - } - - return TRUE; -} - -/** Loads the GMyth settings from the given file. - * - * @param gmyth_settings the GMythSettings instance. - * @param filename The desired file to be opened. - * @return TRUE if success, FALSE if error. - */ -gboolean -gmyth_settings_load_from_file (GMythSettings *gmyth_settings, GString *filename) -{ - FILE *file_desc; - char line[100]; - - g_debug ("[%s] Loading GMyth settings file: %s", __FUNCTION__, filename->str); - - file_desc = fopen(filename->str, "r"); - if( file_desc == NULL) { - g_warning ("[%s] Settings file %s could not be opened", __FUNCTION__, filename->str); - return FALSE; - } - - gmyth_settings->settings_file = g_string_new (filename->str); - - while(fgets(line, 100, file_desc)) { - int i; - - /* Removes the new line characters from the end of line */ - for ( i = strlen(line)-1; i >= 0; i--) { - if ( !g_ascii_iscntrl (line[i]) ) { - line[i+1] = '\0'; - break; - } - } - - fill_settings_data(gmyth_settings, line); - } - - fclose (file_desc); - - return TRUE; -} - -/** Loads the GMyth settings from the standard settings file - * (~/.mmyth/settings.dat). - * - * @param gmyth_settings the GMythSettings instance. - * @return TRUE if success, FALSE if error. - */ -gboolean -gmyth_settings_load (GMythSettings *gmyth_settings) -{ - GString* file_full_path = g_string_new( g_build_filename( g_get_home_dir(), - GMYTH_SETTINGS_DIR, GMYTH_SETTINGS_FILE_NAME, NULL ) ); - - gmyth_settings->settings_file = file_full_path; - - gmyth_settings_ensure_dir_exists( g_build_filename( g_get_home_dir(), GMYTH_SETTINGS_DIR, NULL ) ); - - // Verifies if the file already exist - if ( g_file_test( file_full_path->str, G_FILE_TEST_EXISTS ) == FALSE ) { - g_debug ("[%s] Settings file does not exist. A new one will be created.\n", __FUNCTION__); - - if ( gmyth_settings_ensure_file_exists( file_full_path->str ) == FALSE ) - return FALSE; - - // Creates the file with default values (see _init function) - return gmyth_settings_save (gmyth_settings); - - } else { - g_debug ("[%s] Opening settings from file %s", __FUNCTION__, file_full_path->str); - - return gmyth_settings_load_from_file (gmyth_settings, file_full_path); - } -} - -/** Saves the current gmyth_settings to the settings file related to the - * given instance. - * - * @param gmyth_settings the GMythSettings instance. - * @return TRUE if success, FALSE if error. - */ -gboolean -gmyth_settings_save (GMythSettings *gmyth_settings) -{ - FILE *file_desc; - - if (gmyth_settings->settings_file == NULL) { - g_warning ("[%s] Settings were not loaded from file, could not save!", __FUNCTION__); - } - - file_desc = fopen(gmyth_settings->settings_file->str, "w"); - if( file_desc == NULL) { - g_warning ("GMYTH_SETTINGS: settings file %s not found", gmyth_settings->settings_file->str); - return FALSE; - } - - g_fprintf(file_desc, "#Maemo-Myth Settings\n"); - - g_fprintf(file_desc, "#General settings related with mythtv database\n"); - g_fprintf(file_desc, "dbname=%s\n", gmyth_settings->mysql_dbname->str); - g_fprintf(file_desc, "username=%s\n", gmyth_settings->mysql_username->str); - g_fprintf(file_desc, "password=%s\n", gmyth_settings->mysql_password->str); - - g_fprintf(file_desc, "\n#General settings related with mythtv backend\n"); - g_fprintf(file_desc, "hostname=%s\n", gmyth_settings->backend_hostname->str); - g_fprintf(file_desc, "backend_port=%d\n", gmyth_settings->backend_port); - - fclose (file_desc); - - g_debug ("[%s] Settings file saved", __FUNCTION__); - return TRUE; -} - -/** Gets the backend hostname from the settings. - * - * @param gmyth_settings the GMythSettings instance. - * @return The loaded backend hostname, or the default value "127.0.0.1" if settings - * file was not opened. - */ -GString* -gmyth_settings_get_backend_hostname (GMythSettings *gmyth_settings) -{ - return g_string_new (gmyth_settings->backend_hostname->str); -} - -/** Sets the backend hostname to the settings. - * - * @param gmyth_settings the GMythSettings instance. - * @param new_hostname The new hostname. - */ -void -gmyth_settings_set_backend_hostname (GMythSettings *gmyth_settings, GString *new_hostname) -{ - g_string_assign (gmyth_settings->backend_hostname, new_hostname->str); -} - -/** Gets the user name to connect to backend database. - * - * @param gmyth_settings the GMythSettings instance. - * @return The loaded user name, or the default value "mythtv" if settings - * file was not opened. - */ -GString* -gmyth_settings_get_username (GMythSettings *gmyth_settings) -{ - return g_string_new (gmyth_settings->mysql_username->str); -} - -/** Sets the username to connect to backend database. - * - * @param gmyth_settings the GMythSettings instance. - * @param new_username The new username. - */ -void -gmyth_settings_set_username (GMythSettings *gmyth_settings, GString *new_username) -{ - g_string_assign (gmyth_settings->mysql_username, new_username->str); -} - -/** Gets the database password from the settings file. - * - * @param gmyth_settings the GMythSettings instance. - * @return The loaded password, or the default value "mythtv" if settings - * file was not opened. - */ -GString* -gmyth_settings_get_password (GMythSettings *gmyth_settings) -{ - return g_string_new (gmyth_settings->mysql_password->str); -} - -/** Sets the database password. - * - * @param gmyth_settings the GMythSettings instance. - * @param new_password The new password. - */ - -void -gmyth_settings_set_password (GMythSettings *gmyth_settings, GString *new_password) -{ - g_string_assign (gmyth_settings->mysql_password, new_password->str); -} - -/** Gets the backend database name from the settings file. - * - * @param gmyth_settings the GMythSettings instance. - * @return The loaded database name, or the default value "mythconverg" if settings - * file was not opened. - */ -GString* -gmyth_settings_get_dbname (GMythSettings *gmyth_settings) -{ - return g_string_new (gmyth_settings->mysql_dbname->str); -} - -/** Sets the Mythtv database name to the settings. - * - * @param gmyth_settings the GMythSettings instance. - * @param new_dbname The new database name. - */ - -void -gmyth_settings_set_dbname (GMythSettings *gmyth_settings, GString *new_dbname) -{ - g_string_assign (gmyth_settings->mysql_dbname, new_dbname->str); -} - -/** Gets the backend port from the settings. - * - * @param gmyth_settings the GMythSettings instance. - * @return The loaded backend port, or the default value "6543" if settings - * file was not opened. - */ -int -gmyth_settings_get_backend_port (GMythSettings *gmyth_settings) -{ - return gmyth_settings->backend_port; -} - -/** Sets the backend port. - * - * @param gmyth_settings the GMythSettings instance. - * @param new_port The new port. - */ -void -gmyth_settings_set_backend_port (GMythSettings *gmyth_settings, gint new_port) -{ - gmyth_settings->backend_port = new_port; -} - - -static void -fill_settings_data(GMythSettings *gmyth_settings, char* line) -{ - gchar** str_splited; - - GString *gstr_splited; - gstr_splited = g_string_new(""); - str_splited = g_strsplit (line, "=", -1); - - if(!(strcmp(str_splited[0], "hostname"))){ - g_string_assign(gstr_splited, str_splited[1]); - gmyth_settings_set_backend_hostname(gmyth_settings, gstr_splited); - } - else if (!(strcmp(str_splited[0], "dbname"))){ - g_string_assign(gstr_splited, str_splited[1]); - gmyth_settings_set_dbname(gmyth_settings, gstr_splited); - } - else if (!(strcmp(str_splited[0], "username"))){ - g_string_assign(gstr_splited, str_splited[1]); - gmyth_settings_set_username(gmyth_settings, gstr_splited); - } - else if (!(strcmp(str_splited[0], "password"))){ - g_string_assign(gstr_splited, str_splited[1]); - gmyth_settings_set_password(gmyth_settings, gstr_splited); - } - else if (!(strcmp(str_splited[0], "backend_port"))){ - gmyth_settings_set_backend_port(gmyth_settings, atoi(str_splited[1])); - } -} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_settings.h --- a/gmyth/src/libgmyth/gmyth_settings.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_settings.h - * - * @brief

This component contains functions acessing and modifying - * user and program settings. - * - * The standard settings file is created in the user home folder, in the - * file ~/.mmyth/settings.dat. - * - * 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_SETTINGS_H__ -#define __GMYTH_SETTINGS_H__ - -#include - -//#include -//#include -//#include -//#include -//#include -//#include - -G_BEGIN_DECLS - -#define GMYTH_SETTINGS_TYPE (gmyth_settings_get_type ()) -#define GMYTH_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SETTINGS_TYPE, GMythSettings)) -#define GMYTH_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SETTINGS_TYPE, GMythSettingsClass)) -#define IS_GMYTH_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SETTINGS_TYPE)) -#define IS_GMYTH_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SETTINGS_TYPE)) -#define GMYTH_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_SETTINGS_TYPE, GMythSettingsClass)) - - -typedef struct _GMythSettings GMythSettings; -typedef struct _GMythSettingsClass GMythSettingsClass; - -struct _GMythSettingsClass -{ - GObjectClass parent_class; - - /* callbacks */ - /* no one for now */ -}; - -struct _GMythSettings -{ - GObject parent; - - GString *settings_file; - - GString *backend_hostname; - int backend_port; - - GString *mysql_dbname; - GString *mysql_username; - GString *mysql_password; - // FIXME: Why do we need database_type? Do we intend to support other dbs? - GString *database_type; -}; - - -GType gmyth_settings_get_type (void); - -GMythSettings* gmyth_settings_new (void); -gboolean gmyth_settings_load_from_file (GMythSettings *gmyth_settings, GString *filename); -gboolean gmyth_settings_load (GMythSettings *msettings); -gboolean gmyth_settings_save (GMythSettings *gmyth_settings); - -GString* gmyth_settings_get_backend_hostname (GMythSettings *gmyth_settings); -void gmyth_settings_set_backend_hostname (GMythSettings *gmyth_settings, GString *new_hostname); -GString* gmyth_settings_get_username (GMythSettings *gmyth_settings); -void gmyth_settings_set_username (GMythSettings *gmyth_settings, GString *new_username); -GString* gmyth_settings_get_password (GMythSettings *gmyth_settings); -void gmyth_settings_set_password (GMythSettings *gmyth_settings, GString *new_password); -GString* gmyth_settings_get_dbname (GMythSettings *gmyth_settings); -void gmyth_settings_set_dbname (GMythSettings *gmyth_settings, GString *new_dbname); -int gmyth_settings_get_backend_port (GMythSettings *gmyth_settings); -void gmyth_settings_set_backend_port (GMythSettings *gmyth_settings, gint new_port); - - -G_END_DECLS - -#endif /* __GMYTH_SETTINGS_H__ */ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_socket.c --- a/gmyth/src/libgmyth/gmyth_socket.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,708 +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 - */ - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "gmyth_socket.h" -#include "gmyth_stringlist.h" -#include "gmyth_context.h" - -#define BUFLEN 512 -#define MYTH_SEPARATOR "[]:[]" -#define MYTH_PROTOCOL_FIELD_SIZE 8 - -static GStaticMutex mutex = G_STATIC_MUTEX_INIT; - -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) -{ -} - -/** 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( gchar *addr, gint port, struct addrinfo **addrInfo ) -{ - struct addrinfo hints; - gchar *portStr = g_strnfill( 32, ' ' ); - gint errorn = EADDRNOTAVAIL; - - memset( &hints, 0, sizeof(hints) ); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - /* hints.ai_flags = AI_NUMERICHOST; */ - if ( port != -1 ) - sprintf(portStr, "%d", port); - else - portStr = NULL; - - g_debug( "[%s] Address: %s, port: %s\n", __FUNCTION__, addr, portStr ); - if ( ( errorn = getaddrinfo(addr, portStr, &hints, addrInfo) ) != 0 ) { - g_printerr( "[%s] Socket ERROR: %s\n", __FUNCTION__, gai_strerror(errorn) ); - } - - return errorn; -} - -/** This function retrieves the local hostname of the - * client machine. - * - * @return GString* get local hostname. - */ -GString * -gmyth_socket_get_local_hostname( ) -{ - GString *str = g_string_new(""); - - gchar *localhostname = g_strnfill( 1024, ' ' ); - gchar *localaddr = g_strdup( "127.0.0.1" ); - - gboolean found_addr = FALSE; - - struct addrinfo* addr_info_data = NULL, *addr_info0 = NULL; - - struct sockaddr_in* sa = NULL; - - g_static_mutex_lock( &mutex ); - - gethostname(localhostname, 1024); - - gint err = gmyth_socket_toaddrinfo( localhostname, -1, &addr_info_data ); - - 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_print( "[%s] localaddr = %s\n", __FUNCTION__, localaddr ); - - if ( localaddr != NULL && ( g_strrstr( localaddr, "127" ) == NULL ) ) { - g_print( "[%s] Trying the address %s (err = %d).\n", - __FUNCTION__, localaddr, err ); - g_print( "[%s] Found local address %s!\n", __FUNCTION__, localaddr ); - str = g_string_assign( str, g_strdup( localaddr ) ); - found_addr = TRUE; - break; - } - addr_info0 = addr_info0->ai_next; - }; - - if ( found_addr == FALSE ) { - g_warning("[%s] Could not determine the local hostname address. Setting to %s\n", - __FUNCTION__, localaddr ); - if ( localaddr != NULL ) - str = g_string_assign( str, localaddr ); - else - str = g_string_assign( str, "127.0.0.1" ); - } - - g_static_mutex_unlock( &mutex ); - - if (localhostname!=NULL) - g_free( localhostname ); - - return str; -} - -static void -gmyth_socket_dispose (GObject *object) -{ - GMythSocket *gmyth_socket = GMYTH_SOCKET(object); - - gmyth_socket_close_connection (gmyth_socket); - /* disconnect socket */ - 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->sd_io_ch = NULL; - - gmyth_socket->hostname = g_strdup(""); - - gmyth_socket->port = 6543; - - return gmyth_socket; -} - -/** 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, - gchar *hostname, gint port) -{ - struct addrinfo *addr_info_data = NULL, *addr_info0 = NULL; - gint ret_code = -1; - gint errno; - gboolean ret = TRUE; - - if ( hostname == NULL ) - g_printerr ( "[%s] Invalid hostname parameter!\n", __FUNCTION__ ); - - errno = gmyth_socket_toaddrinfo( hostname, port, &addr_info_data ); - - g_return_val_if_fail( addr_info_data != NULL, FALSE ); - - /* store hostname and port number */ - (*gmyth_socket)->hostname = g_strdup( hostname ); - (*gmyth_socket)->port = port; - - for ( addr_info0 = addr_info_data; addr_info0; addr_info0 = addr_info_data->ai_next ) { - - struct sockaddr_in *sa = (struct sockaddr_in*)addr_info0->ai_addr; - /* init socket descriptor */ - (*gmyth_socket)->sd = socket( addr_info0->ai_family, addr_info0->ai_socktype, - addr_info0->ai_protocol ); - - if ( (*gmyth_socket)->sd < 0 ) - continue; - - g_debug( "[%s] hostname = %s, sock_fd = %d, addr = %s, addr_len = %d, \ - ai_family = %d, ai_protocol = %d\n", - __FUNCTION__, hostname, (*gmyth_socket)->sd, inet_ntoa( sa->sin_addr ), - addr_info0->ai_addrlen, addr_info0->ai_family, addr_info0->ai_protocol ); - - if ( ( ret_code = connect( (*gmyth_socket)->sd, (struct sockaddr *)addr_info0->ai_addr, - addr_info0->ai_addrlen ) ) < 0 ) - { - g_printerr( "[%s] Error connecting to backend!\n", __FUNCTION__ ); - if ( ret_code == ETIMEDOUT ) - g_printerr( "[%s]\tBackend host unreachable!\n", __FUNCTION__ ); - - g_printerr( "ERROR: %s\n", gai_strerror(ret_code) ); - continue; - } - - /* only will be reached if none of the error above occurred */ - break; - - } - - (*gmyth_socket)->sd_io_ch = g_io_channel_unix_new( (*gmyth_socket)->sd ); - - //if (addr_info_data != NULL ) - //freeaddrinfo( addr_info_data ); - - ret = ( ret_code == 0 ) ? TRUE : FALSE ; - - 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 ) { - g_warning ("[%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 ) ) { - g_warning ("[%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; - - if( command == NULL || ( command->len <= 0 ) ) { - g_warning ("[%s] Invalid NULL command parameter!\n", __FUNCTION__); - ret = FALSE; - goto done; - } - - g_static_mutex_lock( &mutex ); - g_debug ("[%s] Sending command to backend: %s\n", __FUNCTION__, command->str); - - /* - io_cond = g_io_channel_get_buffer_condition( gmyth_socket->sd_io_ch ); - - if ( ( io_cond & G_IO_IN ) == 0 ) { - g_warning ("[%s] IO channel is not able to send data!\n", __FUNCTION__); - ret = FALSE; - goto done; - } - */ - - buffer = g_strnfill( BUFLEN, ' ' ); - snprintf( buffer, MYTH_PROTOCOL_FIELD_SIZE+1, "%-8d", command->len); - g_print( "[%s] buffer = [%s]\n", __FUNCTION__, buffer ); - - command = g_string_prepend(command, buffer); - - g_print( "[%s] command = [%s]\n", __FUNCTION__, command->str ); - - /* 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 ) ) { - g_warning ("[%s] Error while writing to socket", __FUNCTION__); - ret = FALSE; - } else if ( bytes_written < command->len ) { - g_warning ("[%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 ) ) - { - g_warning ("[%s] Some problem occurred when sending data to the socket\n", __FUNCTION__); - - ret = TRUE; - } - - g_static_mutex_unlock( &mutex ); -done: - if ( error != NULL ) { - g_printerr( "[%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 - * backend connection. - */ -gboolean -gmyth_socket_connect_to_backend (GMythSocket *gmyth_socket, - gchar *hostname_backend, int port, gboolean blocking_client) -{ - if (!gmyth_socket_connect (&gmyth_socket, hostname_backend, port)) { - g_warning ("[%s] Could not open socket to backend machine", __FUNCTION__); - 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(); - - g_string_printf(base_str, "ANN %s %s 0", - (blocking_client ? "Playback" : "Monitor"), - hostname->str); - - g_debug ("[%s] Connection command sent to backend: %s", __FUNCTION__, base_str->str); - - gmyth_socket_send_command (gmyth_socket, base_str); - result = gmyth_socket_receive_response(gmyth_socket); - - if (result != NULL) { - g_debug ("[%s] Response received from backend: %s", __FUNCTION__, result->str); - g_string_free (result, TRUE); - } - - g_string_free (hostname, TRUE); - g_string_free (base_str, TRUE); - - return TRUE; - } else { - g_warning ("[%s] GMythSocket could not connect to the backend", __FUNCTION__); - return FALSE; - } - -} - -/** Closes the socket connection to the backend. - * - * @param gmyth_socket The GMythSocket instance. - */ -void -gmyth_socket_close_connection (GMythSocket *gmyth_socket) -{ - close (gmyth_socket->sd); -} - - -/** 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 - */ -gboolean -gmyth_socket_check_protocol_version_number (GMythSocket *gmyth_socket, gint mythtv_version) -{ - GString *response; - GString *payload; - gchar *new_version = g_strdup(""); - gboolean res = TRUE; - -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) { - g_warning ("[%s] Check protocol version error! Not answered!", __FUNCTION__); - res = FALSE; - goto done; - } - - res = g_str_has_prefix (response->str, "ACCEPT"); - if (!res) { - g_warning ("[%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 ) { - new_version = g_strrstr( response->str, "]" ); - if (new_version!=NULL) { - ++new_version; /* skip ']' character */ - if ( new_version != NULL ) { - g_print( "[%s] got MythTV version = %s\n", __FUNCTION__, new_version ); - mythtv_version = g_ascii_strtoull( g_strdup( 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 ); - /* g_free( new_version ); */ - goto try_new_version; - } - } - } - } - -done: - if ( payload != NULL ) - g_string_free (payload, TRUE); - if ( response != NULL ) - g_string_free (response, TRUE); -// if (new_version!=NULL) -// g_free( new_version ); - - return res; -} - -/** 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_check_protocol_version_number( gmyth_socket, MYTHTV_VERSION_DEFAULT ); -} - -/** 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; - GIOCondition io_cond; - - g_return_val_if_fail( gmyth_socket != NULL, NULL ); - - /* verify if the input (read) buffer is ready to receive data */ - - buffer = g_strnfill( BUFLEN, ' ' ); - - g_static_mutex_lock( &mutex ); - - io_status = g_io_channel_read_chars( gmyth_socket->sd_io_ch, buffer, MYTH_PROTOCOL_FIELD_SIZE, &bytes_read, &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 ); - - g_print ( "[%s] Bytes read = %d\n", __FUNCTION__, bytes_read ); - - if( (io_status == G_IO_STATUS_ERROR) || (bytes_read <= 0) ) { - g_warning ("[%s] Error in mythprotocol response from backend\n", __FUNCTION__); - str = NULL; - //return NULL; - } else { - - 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 ) { - - snprintf( buffer, MYTH_PROTOCOL_FIELD_SIZE+1, "%-8s", g_strdup(buffer)); - g_print( "[%s] buffer = [%s]\n", __FUNCTION__, buffer ); - - /* removes trailing whitespace */ - buffer = g_strstrip( buffer ); - - len = (gint)strtoull ( buffer, NULL, 10 ); - - bytes_read = 0; - io_status = g_io_channel_read_chars( gmyth_socket->sd_io_ch, buffer, len, &bytes_read, &error ); - buffer[bytes_read] = '\0'; - } - } - - g_static_mutex_unlock( &mutex ); - - g_debug ("[%s] Response received from backend: {%s}\n", __FUNCTION__, buffer); - - if ( ( bytes_read != len ) || ( io_status == G_IO_STATUS_ERROR ) ) - str = NULL; - else - str = g_string_new( buffer ); - - if ( buffer != NULL ) - g_free( buffer ); - - if ( error != NULL ) { - g_printerr( "[%s] Error found receiving response from the IO channel: (%d, %s)\n", __FUNCTION__, error->code, error->message ); - str = NULL; - g_error_free( error ); - } - - 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; - GPtrArray *ptr_array; - gchar *str_array; - - g_static_mutex_lock( &mutex ); - - ptr_array = g_ptr_array_sized_new(g_list_length(str_list->glist)); - - g_print( "[%s] Number of parameters = %d\n", __FUNCTION__, 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); - } - 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_static_mutex_unlock( &mutex ); - - // Sends message to backend - // TODO: implement looping to send remaining data, and add timeout testing! - gmyth_socket_send_command(gmyth_socket, g_string_new(str_array)); - - g_free (str_array); - 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; - gchar **str_array; - gint i; - - response = gmyth_socket_receive_response(gmyth_socket); - g_static_mutex_lock( &mutex ); - - gmyth_string_list_clear_all (str_list); - str_array = g_strsplit (response->str, MYTH_SEPARATOR, -1); - - for (i=0; i< g_strv_length (str_array); i++) { - gmyth_string_list_append_string (str_list, g_string_new (str_array[i])); - } - g_static_mutex_unlock( &mutex ); - - g_string_free (response, TRUE); - g_strfreev (str_array); - - 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 b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_socket.h --- a/gmyth/src/libgmyth/gmyth_socket.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +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_CAST ((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; - - /* socket descriptor */ - int sd; - GIOChannel *sd_io_ch; - - gchar *hostname; - gint port; -}; - - -GType gmyth_socket_get_type (void); - -GMythSocket * gmyth_socket_new (void); - -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); -int gmyth_socket_sendreceive_stringlist (GMythSocket * gmyth_socket, - GMythStringList *str_list); - -gboolean gmyth_socket_connect (GMythSocket **gmyth_socket, - gchar *hostname, gint port); -gboolean gmyth_socket_connect_to_backend (GMythSocket *gmyth_socket, - gchar *hostname_backend, int port, - gboolean blocking_client); - -GString * gmyth_socket_get_local_hostname (void); - -void gmyth_socket_close_connection (GMythSocket *gmyth_socket); - -gboolean gmyth_socket_check_protocol_version (GMythSocket *gmyth_socket); -gboolean gmyth_socket_check_protocol_version_number (GMythSocket *gmyth_socket, - gint mythtv_version); - -gboolean gmyth_socket_write_stringlist(GMythSocket *gmyth_socket, - GMythStringList* str_list); -int gmyth_socket_read_stringlist(GMythSocket *gmyth_socket, - GMythStringList* str_list); - -G_END_DECLS - -#endif /* __GMYTH_SOCKET_H__ */ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_stringlist.c --- a/gmyth/src/libgmyth/gmyth_stringlist.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,272 +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 - */ - -#include "gmyth_stringlist.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); - - if (gmyth_string_list->glist) - 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 *tmp_str = g_string_new (""); - - g_string_printf (tmp_str, "%d", value); - - gmyth_string_list_append_string (strlist, tmp_str); - - return tmp_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_str = g_string_new (""); - - glong l2 = ( (guint64)(value) & 0xffffffffLL ); - glong l1 = ( ((guint64)(value) >> 32 ) & 0xffffffffLL ); - - /* high order part of guint64 value */ - g_string_printf (tmp_str, "%ld", l1); - - g_debug( "[%s] uint64 (high) = %s\n", __FUNCTION__, tmp_str->str ); - - gmyth_string_list_append_string (strlist, tmp_str); - - /* low order part of guint64 value */ - g_string_printf (tmp_str, "%ld", l2); - - g_debug( "[%s] uint64 (low) = %s\n", __FUNCTION__, tmp_str->str ); - - gmyth_string_list_append_string (strlist, tmp_str); - - return tmp_str; -} - -/** 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); - - g_return_val_if_fail( tmp_str != NULL, NULL ); - - gmyth_string_list_append_string (strlist, 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 ); - - strlist->glist = g_list_append (strlist->glist, value); - - 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); - - g_return_val_if_fail( tmp_str != NULL && tmp_str->str != NULL, 0 ); - - return (gint) ( 0x00000000ffffffffL & g_ascii_strtoull ( tmp_str->str, NULL, 0 ) ); -} - -/** 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; - - 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); - - glong l1 = (glong)g_ascii_strtoull (tmp_str1->str, NULL, 10); - glong l2 = (glong)g_ascii_strtoull (tmp_str2->str, NULL, 10); - - ret_value = ((guint64)(l2) & 0xffffffffLL) | ((guint64)(l1) << 32); - - g_debug( "[%s] returning uint64 value = %llu\n", __FUNCTION__, ret_value ); - - return ret_value; -} - -/** Gets a string from the string list at the given position. - * - * @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 ) -{ - if (!strlist || !(strlist->glist)) { - g_warning ("%s received Null arguments", __FUNCTION__); - return NULL; - } - - return (GString *) g_list_nth_data (strlist->glist, index); -} - -/** 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_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 ) -{ - g_return_val_if_fail( strlist != NULL && strlist->glist != NULL, 0 ); - - return g_list_length (strlist->glist); -} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_stringlist.h --- a/gmyth/src/libgmyth/gmyth_stringlist.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +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_CAST ((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 gmyth_string_list_clear_all (GMythStringList *strlist); -int gmyth_string_list_length (GMythStringList *strlist); - -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_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); -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 b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_tvchain.c --- a/gmyth/src/libgmyth/gmyth_tvchain.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,355 +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 - */ - -#include -#include -#include -#include - -#include "gmyth_epg.h" -#include "gmyth_tvchain.h" -#include "gmyth_util.h" -#include "gmyth_query.h" -#include "gmyth_scheduler.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); - -G_DEFINE_TYPE(GMythTVChain, gmyth_tvchain, G_TYPE_OBJECT) - -static GStaticMutex mutex = G_STATIC_MUTEX_INIT; - -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 = 0; -} - -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->tvchain_list != NULL ) { - g_list_free( tvchain->tvchain_list ); - tvchain->tvchain_list = NULL; - } - - if ( tvchain->cur_chanid != NULL ) { - g_string_free( tvchain->cur_chanid, TRUE ); - tvchain->cur_chanid = 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. - */ -void -gmyth_tvchain_initialize (GMythTVChain *tvchain, GString *hostname) -{ - if (tvchain->tvchain_id == NULL) { - GString *isodate; - time_t cur_time; - - time(&cur_time); - isodate = gmyth_util_time_to_isoformat (cur_time); - - tvchain->tvchain_id = g_string_sized_new(7 + hostname->len + isodate->len); - g_string_printf(tvchain->tvchain_id, - "live-%s-%s", hostname->str, isodate->str); - - g_print("tv_chain_id: %s\n", tvchain->tvchain_id->str); - - g_string_free(isodate, TRUE); - - } else { - g_warning ("[%s] TVchain already initialized", __FUNCTION__); - } -} - -/** 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 g_string_new (tvchain->tvchain_id->str); -} - -/** 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; - GMythQuery *gmyth_query; - gboolean ret = TRUE; - - GString *stmt_str; - - g_static_mutex_lock( &mutex ); - - guint prev_size = g_list_length (tvchain->tvchain_list); - - g_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)) { - g_warning ("[%s] Could not connect to db", __FUNCTION__); - g_static_mutex_unlock( &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 (g_string_new ((gchar*)msql_row[1])); - entry->endtime = gmyth_util_string_to_time (g_string_new (msql_row[2])); - entry->discontinuity = atoi (msql_row[3]) != 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; - - tvchain->tvchain_list = g_list_append (tvchain->tvchain_list, entry); - } - } else { - g_warning ("gmyth_tvchain_reload_all query error!\n"); - g_static_mutex_unlock( &mutex ); - - ret = FALSE; - goto done; - } - - g_static_mutex_unlock( &mutex ); - - tvchain->cur_pos = gmyth_tvchain_program_is_at (tvchain, tvchain->cur_chanid, tvchain->cur_startts); - - 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)) { - g_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; -} - -/** 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. - */ -int -gmyth_tvchain_program_is_at (GMythTVChain *tvchain, GString *chanid, time_t startts) -{ - int count = 0; - struct LiveTVChainEntry *entry; - GList *tmp_list = tvchain->tvchain_list; - - g_static_mutex_lock( &mutex ); - - for (; tmp_list; 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_static_mutex_unlock( &mutex ); - return count; - } - } - g_static_mutex_unlock( &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, int 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, int index) -{ - struct LiveTVChainEntry* chain_entry = NULL; - - g_return_val_if_fail( tvchain != NULL && tvchain->tvchain_list != NULL, NULL ); - - g_static_mutex_lock( &mutex ); - - int size = g_list_length (tvchain->tvchain_list); - int 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_static_mutex_unlock( &mutex ); - - if ( chain_entry != NULL ) { - g_debug ("[%s] Got TV Chain entry at %d.\n", __FUNCTION__, new_index ); - - } else { - g_warning ("[%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 progrma 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) { - g_warning ("gmyth_tvchain_entry_to_program() received NULL argument"); - return NULL; - } - - GMythScheduler *scheduler = gmyth_scheduler_new (); - - gmyth_scheduler_connect( scheduler ); - 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 { - g_warning ("tvchain_entry_to_program(%s, %ld) failed!", entry->chanid->str, entry->starttime); - } - - return proginfo; -} diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_tvchain.h --- a/gmyth/src/libgmyth/gmyth_tvchain.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +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" - -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_CAST ((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; - - time_t starttime; - time_t 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; - - time_t cur_startts; - GString *cur_chanid; - int cur_pos; -}; - - -GType gmyth_tvchain_get_type (void); - -void gmyth_tvchain_initialize (GMythTVChain *tvchain, - GString *hostname); -gboolean gmyth_tvchain_reload_all (GMythTVChain *tvchain); -GString* gmyth_tvchain_get_id (GMythTVChain *tvchain); -int gmyth_tvchain_program_is_at (GMythTVChain *tvchain, - GString *chanid, time_t 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); - -G_END_DECLS - -#endif /*LIVETVCHAIN_H_*/ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_tvplayer.c --- a/gmyth/src/libgmyth/gmyth_tvplayer.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,684 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_tvplayer.c - * - * @brief

This component provides playback of the remote A/V using - * GStreamer. - * - * 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 - */ - -#include "gmyth_tvplayer.h" - -#include - -#include "gmyth_context.h" -#include "gmyth_remote_util.h" - -typedef struct _GstPlayerWindowStateChange -{ - GstElement *play; - GstState old_state, new_state; - GMythTVPlayer *tvplayer; -} GstPlayerWindowStateChange; - -typedef struct _GstPlayerWindowTagFound -{ - GstElement *play; - GstTagList *taglist; - GMythTVPlayer *tvplayer; -} GstPlayerWindowTagFound; - -/* -static gboolean idle_state (gpointer data); -*/ -static gboolean bus_call (GstBus * bus, GstMessage * msg, gpointer data); - -static void gmyth_tvplayer_class_init (GMythTVPlayerClass *klass); -static void gmyth_tvplayer_init (GMythTVPlayer *object); - -static void gmyth_tvplayer_dispose (GObject *object); -static void gmyth_tvplayer_finalize (GObject *object); - -G_DEFINE_TYPE(GMythTVPlayer, gmyth_tvplayer, G_TYPE_OBJECT) - -static gboolean gmyth_tvplayer_create_pipeline (GMythTVPlayer* tvplayer); -static void new_pad_cb (GstElement *element, - GstPad *pad, gpointer data); - -static gboolean expose_cb (GtkWidget * widget, - GdkEventExpose * event, - gpointer user_data); - -static void -gmyth_tvplayer_class_init (GMythTVPlayerClass *klass) -{ - GObjectClass *gobject_class; - - gobject_class = (GObjectClass *) klass; - - gobject_class->dispose = gmyth_tvplayer_dispose; - gobject_class->finalize = gmyth_tvplayer_finalize; -} - -static void -new_pad_cb (GstElement *element, GstPad *pad, gpointer data) -{ - GMythTVPlayer *tvplayer = GMYTH_TVPLAYER (data); - GstPadLinkReturn ret; - char *s; - - s = gst_caps_to_string (pad->caps); - - if ( s[0] == 'a') { - ret = gst_pad_link (pad, gst_element_get_pad (tvplayer->audioqueue, "sink")); - } else { - ret = gst_pad_link (pad, gst_element_get_pad (tvplayer->videoqueue, "sink")); - } - - g_free(s); -} - -static gboolean -expose_cb (GtkWidget * widget, GdkEventExpose * event, gpointer user_data) -{ - GMythTVPlayer *tvplayer = GMYTH_TVPLAYER (user_data); - - if (tvplayer && tvplayer->videow) { - gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (tvplayer->gst_videosink), - GDK_WINDOW_XWINDOW (widget->window)); - return TRUE; - } - - g_warning ("GMythTVPlayer expose called before setting video window\n"); - - return FALSE; -} - -static void -gmyth_tvplayer_init (GMythTVPlayer *tvplayer) -{ - tvplayer->gst_pipeline = NULL; - tvplayer->gst_source = NULL; - tvplayer->gst_videodec = NULL; - tvplayer->gst_videosink = NULL; - tvplayer->videoqueue = NULL; - tvplayer->audioqueue = NULL; - - /* GTKWidget for rendering the video */ - tvplayer->videow = NULL; - tvplayer->expose_handler = 0; - - tvplayer->backend_hostname = NULL; - tvplayer->backend_port = 0; - tvplayer->local_hostname = NULL; - - tvplayer->remote_encoder = NULL; - tvplayer->tvchain = NULL; - tvplayer->proginfo = NULL; -} - -static void -gmyth_tvplayer_dispose (GObject *object) -{ - - G_OBJECT_CLASS (gmyth_tvplayer_parent_class)->dispose (object); -} - -static void -gmyth_tvplayer_finalize (GObject *object) -{ - g_signal_handlers_destroy (object); - - GMythTVPlayer *tvplayer = GMYTH_TVPLAYER (object); - - g_debug ("[%s] Finalizing tvplayer", __FUNCTION__); - - if (tvplayer->videow != NULL) { - if (g_signal_handler_is_connected (tvplayer->videow, - tvplayer->expose_handler)) { - g_signal_handler_disconnect (tvplayer->videow, - tvplayer->expose_handler); - } - g_object_unref (tvplayer->videow); - } - - if ( tvplayer->remote_encoder != NULL ) - g_object_unref (tvplayer->remote_encoder); - if ( tvplayer->tvchain != NULL ) - g_object_unref (tvplayer->tvchain); - if ( tvplayer->proginfo != NULL ) - g_object_unref (tvplayer->proginfo); - - // Release Gstreamer elements - if ( tvplayer->gst_pipeline != NULL ) - g_object_unref (tvplayer->gst_pipeline); - if ( tvplayer->gst_source != NULL ) - g_object_unref (tvplayer->gst_source); - if ( tvplayer->gst_videodec != NULL ) - g_object_unref (tvplayer->gst_videodec); - if ( tvplayer->gst_videosink != NULL ) - g_object_unref (tvplayer->gst_videosink); - if ( tvplayer->videoqueue != NULL ) - g_object_unref (tvplayer->videoqueue); - if ( tvplayer->audioqueue != NULL ) - g_object_unref (tvplayer->audioqueue); - - G_OBJECT_CLASS (gmyth_tvplayer_parent_class)->finalize (object); -} - -/** Creates a new instance of GMythTVPlayer. - * - * @return a new instance of GMythTVPlayer. - */ -GMythTVPlayer * -gmyth_tvplayer_new () -{ - GMythTVPlayer *tvplayer = - GMYTH_TVPLAYER (g_object_new(GMYTH_TVPLAYER_TYPE, NULL)); - - return tvplayer; -} - -/** Initializes the tv player. - * - * @param tvplayer the object instance. - * @return gboolean TRUE if the pipeline was created - * successfully, FALSE otherwise. - */ -gboolean -gmyth_tvplayer_initialize (GMythTVPlayer *tvplayer) -{ - - if (!gmyth_tvplayer_create_pipeline (tvplayer)) { - g_warning ("[%s] Error while creating pipeline. TV Player not initialized", __FUNCTION__); - return FALSE; - } else { - g_debug ("[%s] GStreamer pipeline created", __FUNCTION__); - } - - return TRUE; -} - -/** Creates the GStreamer pipeline used by the player. - * - * @param tvplayer the object instance. - * @return gboolean TRUE if the pipeline was created - * successfully, FALSE otherwise. - */ -static gboolean -gmyth_tvplayer_create_pipeline (GMythTVPlayer* tvplayer) -{ - GstElement *pipeline; - GstElement *source, *parser; - GstElement *videodec, *videosink; -#ifndef MAEMO_PLATFORM - GstElement *audiodec, *audioconv; -#endif - GstElement *audiosink; - GstElement *videoqueue, *audioqueue; - - g_debug ("GMythTVPlayer: Setting the Gstreamer pipeline\n"); - - pipeline = gst_pipeline_new ("video-player"); - source = gst_element_factory_make ("mythtvsrc", "myth-source"); - parser = gst_element_factory_make ("ffdemux_nuv", "nuv-demux"); - - /* Gstreamer Video elements */ - videoqueue = gst_element_factory_make ("queue", "video-queue"); - videodec = gst_element_factory_make ("ffdec_mpeg4", "video-decoder"); -#ifdef MAEMO_PLATFORM - videosink = gst_element_factory_make ("sdlvideosink", "image-output"); -#else - videosink = gst_element_factory_make ("xvimagesink", "image-output"); -#endif - - /* Gstreamer Audio elements */ - audioqueue = gst_element_factory_make ("queue", "audio-queue"); -#ifdef MAEMO_PLATFORM - audiosink = gst_element_factory_make ("dspmp3sink", "audio-output"); -#else - audiodec = gst_element_factory_make ("ffdec_mp3", "audio-decoder"); - audioconv = gst_element_factory_make ("audioconvert", "audio-converter"); - audiosink = gst_element_factory_make ("alsasink", "audio-output"); -#endif - - if (!(pipeline && source && parser && videodec && videosink) || - !(videoqueue && audioqueue && audiosink)) { - /* FIXME: hanlde the error correctly */ - /* video_alignment is not being created (below) - and is causing problems to the ui */ - - tvplayer->gst_pipeline = NULL; - tvplayer->gst_videodec = NULL; - tvplayer->gst_videosink = NULL; - - g_warning ("GstElement creation error!\n"); - return FALSE; - } - -#ifndef MAEMO_PLATFORM - if (!(audiodec && audioconv)) { - g_warning ("GstElement for audio stream creation error!"); - return FALSE; - } -#endif - - - tvplayer->gst_pipeline = pipeline; - tvplayer->gst_source = source; - tvplayer->gst_videodec = videodec; - tvplayer->gst_videosink = videosink; - g_object_ref (tvplayer->gst_pipeline); - g_object_ref (tvplayer->gst_source); - g_object_ref (tvplayer->gst_videodec); - g_object_ref (tvplayer->gst_videosink); - - tvplayer->videoqueue = videoqueue; - tvplayer->audioqueue = audioqueue; - g_object_ref (tvplayer->videoqueue); - g_object_ref (tvplayer->audioqueue); - - g_object_set (G_OBJECT (videosink), "sync", TRUE, NULL); - g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL); - - gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (tvplayer->gst_pipeline)), - bus_call, tvplayer); - - gst_bin_add_many (GST_BIN (pipeline), source, parser, videoqueue, - videodec, videosink, audioqueue, audiodec, audioconv, audiosink, NULL); - - { -// GstCaps *rtpcaps = gst_caps_new_simple ("application/x-rtp", NULL); -// gst_element_link_filtered(source, parser, rtpcaps); - } - - gst_element_link (source, parser); - gst_element_link_many (videoqueue, videodec, videosink, NULL); - gst_element_link_many (audioqueue, audiodec, audioconv, audiosink, NULL); - - g_signal_connect (parser, "pad-added", G_CALLBACK (new_pad_cb), tvplayer); - - return TRUE; -} - -/** Configures the backend and the tv player - * for playing the recorded content A/V. - * - * FIXME: Change filename to program info or other structure about the recorded - * - * @param tvplayer the object instance. - * @param filename the file uri of the recorded content to be played. - * @return TRUE if successfull, FALSE if any error happens. - */ -gboolean -gmyth_tvplayer_record_setup (GMythTVPlayer *tvplayer, gchar *filename) -{ - GMythSettings *msettings = gmyth_context_get_settings(); - - // FIXME: we should receive the uri instead of filename - GString *hostname = gmyth_settings_get_backend_hostname (msettings); - int port = gmyth_settings_get_backend_port(msettings); - - GString *fullpath = g_string_new ("myth://"); - g_string_append_printf (fullpath, "%s:%d/%s", hostname->str, port, filename); - - tvplayer->is_livetv = FALSE; - - g_debug ("[%s] Setting record uri to gstreamer pipeline to %s", __FUNCTION__, fullpath->str); - - g_object_set (G_OBJECT (tvplayer->gst_source), "location", - fullpath->str, NULL); - - return TRUE; -} - -/** Configures the backend and the tv player - * for playing the live tv. - * - * @param tvplayer the object instance. - * @return TRUE if successfull, FALSE if any error happens. - */ -gboolean -gmyth_tvplayer_livetv_setup (GMythTVPlayer *tvplayer) -{ - GMythSettings *msettings = gmyth_context_get_settings (); - gboolean res = TRUE; - - res = gmyth_context_check_connection(); - if (!res) { - g_warning ("[%s] LiveTV can not connect to backend", __FUNCTION__); - res = FALSE; - goto error; - } - - tvplayer->backend_hostname = gmyth_settings_get_backend_hostname(msettings); - tvplayer->backend_port = gmyth_settings_get_backend_port (msettings); - - tvplayer->local_hostname = g_string_new(""); - gmyth_context_get_local_hostname (tvplayer->local_hostname); - - if ( tvplayer->local_hostname == NULL ) { - res = FALSE; - goto error; - } - - // Gets the remote encoder num - tvplayer->remote_encoder = remote_request_next_free_recorder (-1); - - if ( tvplayer->remote_encoder == NULL ) { - g_warning ("[%s] None remote encoder available", __FUNCTION__); - res = FALSE; - goto error; - } - - // Creates livetv chain handler - tvplayer->tvchain = GMYTH_TVCHAIN ( g_object_new(GMYTH_TVCHAIN_TYPE, NULL) ); - gmyth_tvchain_initialize ( tvplayer->tvchain, tvplayer->local_hostname ); - - if ( tvplayer->tvchain == NULL || tvplayer->tvchain->tvchain_id == NULL ) { - res = FALSE; - goto error; - } - - // Init remote encoder. Opens its control socket. - res = gmyth_remote_encoder_setup(tvplayer->remote_encoder); - if ( !res ) { - g_warning ("[%s] Fail while setting remote encoder\n", __FUNCTION__); - res = FALSE; - goto error; - } - // Spawn live tv. Uses the socket to send mythprotocol data to start livetv in the backend (remotelly) - res = gmyth_remote_encoder_spawntv ( tvplayer->remote_encoder, - gmyth_tvchain_get_id(tvplayer->tvchain) ); - if (!res) { - g_warning ("[%s] Fail while spawn tv\n", __FUNCTION__); - res = FALSE; - goto error; - } - - // Reload all TV chain from Mysql database. - gmyth_tvchain_reload_all (tvplayer->tvchain); - - if ( tvplayer->tvchain == NULL ) { - res = FALSE; - goto error; - } - - // Get program info from database using chanid and starttime - tvplayer->proginfo = gmyth_tvchain_get_program_at (tvplayer->tvchain, -1); - if ( tvplayer->proginfo == NULL ) { - g_warning ("[%s] LiveTV not successfully started.\n", __FUNCTION__ ); - res = FALSE; - goto error; - } else { - g_debug ("[%s] MythLiveTV: All requests to backend to start TV were OK.\n", __FUNCTION__ ); - } - - return res; - -error: - if ( tvplayer->backend_hostname != NULL ) { - g_string_free( tvplayer->backend_hostname, TRUE ); - res = FALSE; - } - - if ( tvplayer->local_hostname != NULL ) { - g_string_free( tvplayer->local_hostname, TRUE ); - res = FALSE; - } - - if ( tvplayer->remote_encoder != NULL ) { - g_object_unref (tvplayer->remote_encoder); - tvplayer->remote_encoder = NULL; - } - - if ( tvplayer->tvchain != NULL ) { - g_object_unref (tvplayer->tvchain); - tvplayer->tvchain = NULL; - } - - if ( tvplayer->proginfo != NULL ) { - g_object_unref (tvplayer->proginfo); - tvplayer->proginfo = NULL; - } - - return res; - -} - -/** Sets the GTK video widget for the tv player. - * - * @param tvplayer the object instance. - * @param videow the GTK video window. - * @return TRUE if successfull, FALSE if any error happens. - */ -gboolean -gmyth_tvplayer_set_widget (GMythTVPlayer *tvplayer, GtkWidget *videow) -{ - tvplayer->videow = videow; - g_object_ref (videow); - - g_debug ("[%s] Setting widget for tv player render", __FUNCTION__); - - tvplayer->expose_handler = g_signal_connect (tvplayer->videow, "expose-event", - G_CALLBACK (expose_cb), tvplayer); - - //g_signal_connect(miptv_ui->videow, "size_request", G_CALLBACK(cb_preferred_video_size), miptv_ui); - - return TRUE; -} - -static gboolean -bus_call (GstBus * bus, GstMessage * msg, gpointer data) -{ - //GMythTVPlayer *tvplayer = GMYTH_TVPLAYER ( data ); - //GMainLoop *loop = tvplayer->loop; - - switch (GST_MESSAGE_TYPE (msg)) { - case GST_MESSAGE_EOS: - printf ("End of stream\n"); - //g_idle_add ((GSourceFunc) idle_eos, data); - gst_element_set_state ( GST_ELEMENT (GST_MESSAGE_SRC (msg)), GST_STATE_NULL ); - gst_element_set_locked_state ( GST_ELEMENT (GST_MESSAGE_SRC (msg)), FALSE ); - break; - case GST_MESSAGE_ERROR: - { - gchar *debug; - GError *err; - - gst_message_parse_error (msg, &err, &debug); - g_free (debug); - - printf ("Error: %s\n", err->message); - g_error_free (err); - - //g_main_loop_quit (loop); - } - break; - default: - printf (gst_message_type_get_name (GST_MESSAGE_TYPE (msg))); - printf ("\n"); - break; - } - - return TRUE; -} - - -#if 0 -static gboolean -idle_state (gpointer data) -{ - GstPlayerWindowStateChange *st = data; - - if (st->old_state == GST_STATE_PLAYING) { - if (st->miptv_ui->idle_id != 0) { - g_source_remove (st->miptv_ui->idle_id); - st->miptv_ui->idle_id = 0; - } - } - else if (st->new_state == GST_STATE_PLAYING) { - if (st->miptv_ui->idle_id != 0) - g_source_remove (st->miptv_ui->idle_id); - - st->miptv_ui->idle_id = g_idle_add (cb_iterate, st->miptv_ui); - } - - /* new movie loaded? */ - if (st->old_state == GST_STATE_READY && st->new_state > GST_STATE_READY) { - - /* gboolean have_video = FALSE; */ - - gtk_widget_show (st->miptv_ui->videow); - - gtk_window_resize (GTK_WINDOW (st->miptv_ui->main_window), 1, 1); - - } - - /* discarded movie? */ - if (st->old_state > GST_STATE_READY && st->new_state == GST_STATE_READY) { - - if (st->miptv_ui->tagcache) { - gst_tag_list_free (st->miptv_ui->tagcache); - st->miptv_ui->tagcache = NULL; - } - } - - gst_object_unref (GST_OBJECT (st->play)); - //g_object_unref (G_OBJECT (st->win)); - g_free (st); - - /* once */ - return FALSE; -} - -#endif - -/** Stops playing the current A/V. - * - * FIXME: How to proceed differently between livetv - * and recorded content? - * - * @param tvplayer the object instance. - * @return void - */ -void -gmyth_tvplayer_stop_playing (GMythTVPlayer *tvplayer) -{ - g_debug ("[%s] Setting gstreamer pipeline state to NULL", __FUNCTION__); - - gst_element_set_state (tvplayer->gst_pipeline, GST_STATE_NULL); - - if (tvplayer->is_livetv) { - if (!gmyth_remote_encoder_stop_livetv (tvplayer->remote_encoder)) { - g_warning ("[%s] Error while stoping remote encoder", __FUNCTION__); - } - } -} - -/** Queries if the tvplayer is active playing A/V content. - * - * @param tvplayer the object instance. - * @return TRUE if the tvplayer is active, FALSE otherwise. - */ -gboolean -gmyth_tvplayer_is_playing (GMythTVPlayer *tvplayer) -{ - return (GST_STATE (tvplayer->gst_pipeline) == GST_STATE_PLAYING); -} - -/** Static function that sets the tvplayer state to PLAYING. - * - * @param tvplayer the object instance. - * @return TRUE if the tvplayer is active, FALSE otherwise. - */ -static gboolean -idle_play (gpointer data) -{ - GMythTVPlayer *tvplayer = GMYTH_TVPLAYER (data); - - g_debug ("GMythTVPlayer: Setting pipeline state to PLAYING\n"); - - gst_element_set_state (tvplayer->gst_pipeline, GST_STATE_PLAYING); - - return FALSE; -} - -/** Start playing A/V with the tvplayer attributes. - * - * @param tvplayer the object instance. - */ -void -gmyth_tvplayer_start_playing (GMythTVPlayer *tvplayer) -{ - - // FIXME: Move this to livetv_setup?? - if (tvplayer->is_livetv) { - - #if 0 - if (!tvplayer || !(tvplayer->proginfo) || !(tvplayer->local_hostname) - || !(tvplayer->gst_source)) { - g_warning ("GMythtvPlayer not ready to start playing\n"); - } - - if (!(tvplayer->proginfo->pathname)) { - g_warning ("[%s] Playback url is null, could not play the myth content", __FUNCTION__); - return; - } - - g_debug ("GMythTVPlayer: Start playing %s", tvplayer->proginfo->pathname->str); -#endif - g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-live", - TRUE, NULL); -#if 0 - if ( tvplayer->tvchain != NULL ) { - GString *str_chainid = gmyth_tvchain_get_id(tvplayer->tvchain); - g_print( "[%s]\tCHAIN ID: %s\n", __FUNCTION__, str_chainid->str ); - - g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-live-chainid", - g_strdup( str_chainid->str ), NULL); - if ( str_chainid!=NULL) - g_string_free( str_chainid, FALSE ); - } - - if ( tvplayer->remote_encoder != NULL ) - g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-live-id", - tvplayer->remote_encoder->recorder_num, NULL ); - g_debug ("[%s] Setting location to %s", __FUNCTION__, - tvplayer->proginfo->pathname->str); - - /* Sets the gstreamer properties acording to the service access address */ - g_object_set (G_OBJECT (tvplayer->gst_source), "location", - tvplayer->proginfo->pathname->str, NULL); -#endif - } - - g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-version", - MYTHTV_VERSION_DEFAULT, NULL); - - g_object_set (G_OBJECT (tvplayer->gst_source), "mythtv-debug", - TRUE, NULL); - - g_idle_add (idle_play, tvplayer); - -} - diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_tvplayer.h --- a/gmyth/src/libgmyth/gmyth_tvplayer.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -/** - * GMyth Library - * - * @file gmyth/gmyth_tvplayer.h - * - * @brief

This component provides playback of the remote A/V using - * GStreamer. - * - * 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_TVPLAYER_H_ -#define GMYTH_TVPLAYER_H_ - -#include -#include - -/* GStreamer includes */ -#include -#include - -#include "gmyth_remote_encoder.h" -#include "gmyth_tvchain.h" -#include "gmyth_common.h" - -G_BEGIN_DECLS - -#define GMYTH_TVPLAYER_TYPE (gmyth_tvplayer_get_type ()) -#define GMYTH_TVPLAYER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TVPLAYER_TYPE, GMythTVPlayer)) -#define GMYTH_TVPLAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVPLAYER_TYPE, GMythTVPlayerClass)) -#define IS_GMYTH_TVPLAYER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TVPLAYER_TYPE)) -#define IS_GMYTH_TVPLAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVPLAYER_TYPE)) -#define GMYTH_TVPLAYER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_TVPLAYER_TYPE, GMythTVPlayerClass)) - - -typedef struct _GMythTVPlayer GMythTVPlayer; -typedef struct _GMythTVPlayerClass GMythTVPlayerClass; - -struct _GMythTVPlayerClass -{ - GObjectClass parent_class; - - /* callbacks */ - /* no one for now */ -}; - -struct _GMythTVPlayer -{ - GObject parent; - - GstElement *gst_pipeline; - GstElement *gst_source; - GstElement *gst_videodec; - GstElement *gst_videosink; - GstElement *videoqueue; - GstElement *audioqueue; - - gulong expose_handler; -// GMainLoop *loop; - - GtkWidget *videow; - - /* Backend connection related variables */ - GString *backend_hostname; - gint backend_port; - GString *local_hostname; - - GMythRemoteEncoder *remote_encoder; - GMythTVChain *tvchain; - GMythProgramInfo *proginfo; - - gboolean is_livetv; -}; - - -GType gmyth_tvplayer_get_type (void); - -GMythTVPlayer* gmyth_tvplayer_new (); -gboolean gmyth_tvplayer_initialize (GMythTVPlayer *tvplayer); - -void gmyth_tvplayer_start_playing (GMythTVPlayer *tvplayer); -void gmyth_tvplayer_stop_playing (GMythTVPlayer *tvplayer); - -gboolean gmyth_tvplayer_set_widget (GMythTVPlayer *tvplayer, - GtkWidget *videow); - -gboolean gmyth_tvplayer_is_playing (GMythTVPlayer *tvplayer); - -gboolean gmyth_tvplayer_record_setup (GMythTVPlayer *tvplayer, - gchar *filename); -gboolean gmyth_tvplayer_livetv_setup (GMythTVPlayer *tvplayer); - -G_END_DECLS - -#endif /*GMYTH_TVPLAYER_H_*/ diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_util.c --- a/gmyth/src/libgmyth/gmyth_util.c Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,138 +0,0 @@ -/** -* GMyth Library -* -* @file gmyth/gmyth_util.c -* -* @brief

This component provides utility functions. -* -* 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 -*/ - -#include "gmyth_util.h" - -#include -#include - -/** 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) { - g_warning ("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); - - 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] = ' '; - - 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) -{ - int year, month, day, hour, min, sec; - - g_debug( "[%s] time_str = %s.\n", __FUNCTION__, time_str != NULL ? time_str->str : "[time string is NULL!]" ); - - if (sscanf (time_str->str, "%04d-%02d-%02d %02d:%02d:%02d", - &year, &month, &day, &hour, &min, &sec) < 3) { /* At least date */ - g_warning ("GMythUtil: isoformat_to_time converter error!\n"); - return 0; - } else { - struct tm tm_time; - 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); - } -} - -/** Decodes a long long variable from the string list - * format of the myhtprotocol. - * - * @param strlist the string list of mythprotocol values - * @param offset the list node offset of the long long variable - * @return guint64 the long long converted value - */ -guint64 -gmyth_util_decode_long_long(GMythStringList *strlist, guint offset) -{ - - guint64 ret_value = 0LL; - - g_return_val_if_fail( strlist != NULL, ret_value ); - - if ( offset < gmyth_string_list_length( strlist )) - g_printerr( "[%s] Offset is lower than the Stringlist (offset = %d)!\n", - __FUNCTION__, offset ); - - g_return_val_if_fail( offset < gmyth_string_list_length( strlist ), ret_value ); - - gint l1 = gmyth_string_list_get_int( strlist, offset ); - gint l2 = gmyth_string_list_get_int( strlist, offset + 1 ); - - ret_value = ((guint64)(l2) & 0xffffffffLL) | ((guint64)(l1) << 32); - - return ret_value; - -} - diff -r b45e9fe9f593 -r 79f6da40f6e9 gmyth/src/libgmyth/gmyth_util.h --- a/gmyth/src/libgmyth/gmyth_util.h Wed Sep 27 00:08:03 2006 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/** -* GMyth Library -* -* @file gmyth/gmyth_util.h -* -* @brief

This component provides utility functions. -* -* 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_UTIL_H_ -#define GMYTH_UTIL_H_ - -#include -#include - -#include "gmyth_stringlist.h" - -G_BEGIN_DECLS - -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); -guint64 gmyth_util_decode_long_long (GMythStringList *strlist, - guint offset); -G_END_DECLS - -#endif /*GMYTH_UTIL_H_*/