1.1 --- a/gmyth/Makefile.am Mon Feb 25 17:45:36 2008 +0000
1.2 +++ b/gmyth/Makefile.am Mon Feb 25 17:51:43 2008 +0000
1.3 @@ -1,4 +1,4 @@
1.4 -SUBDIRS= src samples tests
1.5 +SUBDIRS= gmyth samples tests
1.6
1.7 pkgconfigdir = $(libdir)/pkgconfig
1.8 pkgconfig_DATA = gmyth.pc
2.1 --- a/gmyth/configure.ac Mon Feb 25 17:45:36 2008 +0000
2.2 +++ b/gmyth/configure.ac Mon Feb 25 17:51:43 2008 +0000
2.3 @@ -121,7 +121,7 @@
2.4
2.5 AC_OUTPUT(
2.6 Makefile
2.7 -src/Makefile
2.8 +gmyth/Makefile
2.9 samples/Makefile
2.10 tests/Makefile
2.11 gmyth.pc)
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/gmyth/gmyth/Makefile.am Mon Feb 25 17:51:43 2008 +0000
3.3 @@ -0,0 +1,98 @@
3.4 +lib_LTLIBRARIES = libgmyth.la
3.5 +
3.6 +INCLUDES = -I$(top_srcdir) -I$(top_builddir)/gmyth @GLIB_CFLAGS@ @GOBJECT_CFLAGS@
3.7 +
3.8 +BUILT_SOURCES = \
3.9 + gmyth_marshal.c \
3.10 + gmyth_marshal.h
3.11 +
3.12 +libgmyth_la_SOURCES = \
3.13 + gmyth_common.c \
3.14 + gmyth_debug.c \
3.15 + gmyth_epg.c \
3.16 + gmyth_recorder.c \
3.17 + gmyth_remote_util.c \
3.18 + gmyth_tvchain.c \
3.19 + gmyth_scheduler.c \
3.20 + gmyth_util.c \
3.21 + gmyth_query.c \
3.22 + gmyth_socket.c \
3.23 + gmyth_stringlist.c \
3.24 + gmyth_monitor_handler.c \
3.25 + gmyth_file_transfer.c \
3.26 + gmyth_livetv.c \
3.27 + gmyth_backendinfo.c \
3.28 + gmyth_programinfo.c \
3.29 + gmyth_uri.c \
3.30 + gmyth_http.c \
3.31 + gmyth_vlc.c \
3.32 + gmyth_jobqueue.c \
3.33 + gmyth_transcoder.c \
3.34 + gmyth_recprofile.c \
3.35 + gmyth_file.c \
3.36 + gmyth_file_local.c \
3.37 + $(BUILT_SOURCES)
3.38 +
3.39 +EXTRA_libgmyth_la_SOURCES = gmyth_marshal.list
3.40 +
3.41 +gmyth_marshal.h: gmyth_marshal.list
3.42 + glib-genmarshal --header --prefix=gmyth_marshal gmyth_marshal.list > gmyth_marshal.h.tmp
3.43 + mv gmyth_marshal.h.tmp gmyth_marshal.h
3.44 +
3.45 +gmyth_marshal.c: gmyth_marshal.list gmyth_marshal.h
3.46 + echo "#include \"glib-object.h\"" > gmyth_marshal.c.tmp
3.47 + echo "#include \"gmyth_marshal.h\"" >> gmyth_marshal.c.tmp
3.48 + glib-genmarshal --body --prefix=gmyth_marshal $(srcdir)/gmyth_marshal.list >> gmyth_marshal.c.tmp
3.49 + mv gmyth_marshal.c.tmp gmyth_marshal.c
3.50 +
3.51 +libgmyth_la_CFLAGS = \
3.52 + -DDATADIR=\"$(pkgdatadir)\" \
3.53 + $(GLIB_CFLAGS) \
3.54 + $(GOBJECT_CFLAGS) \
3.55 + $(GST_CFLAGS) \
3.56 + $(GSTBASE_CFLAGS) \
3.57 + $(GSTPLUGINSBASE_CFLAGS) \
3.58 + $(MYSQL_CFLAGS) \
3.59 + $(LIBXML_CFLAGS)
3.60 +
3.61 +libgmyth_la_LDFLAGS = \
3.62 + -export-dynamic \
3.63 + $(GLIB_CFLAGS) \
3.64 + $(GOBJECT_CFLAGS) \
3.65 + $(MYSQL_LIBS) \
3.66 + $(GST_LIBS) \
3.67 + $(GSTBASE_LIBS) \
3.68 + $(GSTPLUGINS_LIBS) \
3.69 + $(LIBXML_LIBS)
3.70 +
3.71 +libgmyth_includedir = \
3.72 + $(pkgincludedir)
3.73 +
3.74 +libgmyth_include_HEADERS = \
3.75 + gmyth.h \
3.76 + gmyth_common.h \
3.77 + gmyth_debug.h \
3.78 + gmyth_epg.h \
3.79 + gmyth_recorder.h \
3.80 + gmyth_scheduler.h \
3.81 + gmyth_tvchain.h \
3.82 + gmyth_util.h \
3.83 + gmyth_query.h \
3.84 + gmyth_socket.h \
3.85 + gmyth_remote_util.h \
3.86 + gmyth_stringlist.h \
3.87 + gmyth_monitor_handler.h \
3.88 + gmyth_file_transfer.h \
3.89 + gmyth_livetv.h \
3.90 + gmyth_backendinfo.h \
3.91 + gmyth_programinfo.h \
3.92 + gmyth_uri.h \
3.93 + gmyth_http.h \
3.94 + gmyth_vlc.h \
3.95 + gmyth_jobqueue.h \
3.96 + gmyth_transcoder.h \
3.97 + gmyth_recprofile.h \
3.98 + gmyth_file.h \
3.99 + gmyth_file_local.h
3.100 +
3.101 +CLEANFILES = $(BUILT_SOURCES)
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/gmyth/gmyth/gmyth-indent.sh Mon Feb 25 17:51:43 2008 +0000
4.3 @@ -0,0 +1,25 @@
4.4 +#!/bin/sh
4.5 +indent \
4.6 + -gnu \
4.7 + -i4 \
4.8 + -l80 \
4.9 + -bfda \
4.10 + -nut \
4.11 + -pcs \
4.12 + -psl \
4.13 + -bli0 \
4.14 + -cs \
4.15 + -cli0 \
4.16 + -nbfda \
4.17 + -sai \
4.18 + -saw \
4.19 + -saf \
4.20 + -sbi4 \
4.21 + -npro \
4.22 + -nfca \
4.23 + -nsc \
4.24 + -ts4 \
4.25 + -prs \
4.26 + -bap \
4.27 + $*
4.28 +
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/gmyth/gmyth/gmyth.h Mon Feb 25 17:51:43 2008 +0000
5.3 @@ -0,0 +1,57 @@
5.4 +/**
5.5 + * GMyth Library
5.6 + *
5.7 + * @file gmyth/gmyth.h
5.8 + *
5.9 + *
5.10 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
5.11 + * @author Renato Filho <renato.filho@indt.org.br>
5.12 + *
5.13 + *//*
5.14 + *
5.15 + * This program is free software; you can redistribute it and/or modify
5.16 + * it under the terms of the GNU Lesser General Public License as published by
5.17 + * the Free Software Foundation; either version 2 of the License, or
5.18 + * (at your option) any later version.
5.19 + *
5.20 + * This program is distributed in the hope that it will be useful,
5.21 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.22 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.23 + * GNU General Public License for more details.
5.24 + *
5.25 + * You should have received a copy of the GNU Lesser General Public License
5.26 + * along with this program; if not, write to the Free Software
5.27 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5.28 + */
5.29 +
5.30 +
5.31 +
5.32 +#ifndef _GMYTH_H_
5.33 +#define _GMYTH_H_
5.34 +
5.35 +#include <gmyth/gmyth_backendinfo.h>
5.36 +#include <gmyth/gmyth_common.h>
5.37 +#include <gmyth/gmyth_debug.h>
5.38 +#include <gmyth/gmyth_epg.h>
5.39 +#include <gmyth/gmyth_file.h>
5.40 +#include <gmyth/gmyth_file_local.h>
5.41 +#include <gmyth/gmyth_file_transfer.h>
5.42 +#include <gmyth/gmyth_livetv.h>
5.43 +#include <gmyth/gmyth_monitor_handler.h>
5.44 +#include <gmyth/gmyth_programinfo.h>
5.45 +#include <gmyth/gmyth_query.h>
5.46 +#include <gmyth/gmyth_recorder.h>
5.47 +#include <gmyth/gmyth_remote_util.h>
5.48 +#include <gmyth/gmyth_scheduler.h>
5.49 +#include <gmyth/gmyth_socket.h>
5.50 +#include <gmyth/gmyth_stringlist.h>
5.51 +#include <gmyth/gmyth_tvchain.h>
5.52 +#include <gmyth/gmyth_uri.h>
5.53 +#include <gmyth/gmyth_util.h>
5.54 +#include <gmyth/gmyth_http.h>
5.55 +#include <gmyth/gmyth_vlc.h>
5.56 +#include <gmyth/gmyth_jobqueue.h>
5.57 +#include <gmyth/gmyth_transcoder.h>
5.58 +#include <gmyth/gmyth_recprofile.h>
5.59 +
5.60 +#endif /* _GMYTH_H_ */
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/gmyth/gmyth/gmyth_backendinfo.c Mon Feb 25 17:51:43 2008 +0000
6.3 @@ -0,0 +1,395 @@
6.4 +/**
6.5 + * GMyth Library
6.6 + *
6.7 + * @file gmyth/gmyth_backend_info.c
6.8 + *
6.9 + * @brief <p> This component represents all the MythTV backend server
6.10 + * configuration information.
6.11 + *
6.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
6.13 + * @author Hallyson Melo <hallyson.melo@indt.org.br>
6.14 + * @author Rosfran Borges <rosfran.borges@indt.org.br>
6.15 + *
6.16 + *
6.17 + * This program is free software; you can redistribute it and/or modify
6.18 + * it under the terms of the GNU Lesser General Public License as published by
6.19 + * the Free Software Foundation; either version 2 of the License, or
6.20 + * (at your option) any later version.
6.21 + *
6.22 + * This program is distributed in the hope that it will be useful,
6.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.25 + * GNU General Public License for more details.
6.26 + *
6.27 + * You should have received a copy of the GNU Lesser General Public License
6.28 + * along with this program; if not, write to the Free Software
6.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
6.30 + */
6.31 +
6.32 +#ifdef HAVE_CONFIG_H
6.33 +#include "config.h"
6.34 +#endif
6.35 +
6.36 +#include "gmyth_backendinfo.h"
6.37 +#include "gmyth_uri.h"
6.38 +#include "gmyth_debug.h"
6.39 +
6.40 +static void gmyth_backend_info_class_init(GMythBackendInfoClass *
6.41 + klass);
6.42 +static void gmyth_backend_info_init(GMythBackendInfo * object);
6.43 +
6.44 +static void gmyth_backend_info_dispose(GObject * object);
6.45 +static void gmyth_backend_info_finalize(GObject * object);
6.46 +
6.47 +G_DEFINE_TYPE(GMythBackendInfo, gmyth_backend_info, G_TYPE_OBJECT);
6.48 +static void gmyth_backend_info_class_init(GMythBackendInfoClass *
6.49 + klass)
6.50 +{
6.51 + GObjectClass *gobject_class;
6.52 +
6.53 + gobject_class = (GObjectClass *) klass;
6.54 +
6.55 + gobject_class->dispose = gmyth_backend_info_dispose;
6.56 + gobject_class->finalize = gmyth_backend_info_finalize;
6.57 +}
6.58 +
6.59 +static void
6.60 +gmyth_backend_info_init(GMythBackendInfo * backend_info)
6.61 +{
6.62 + backend_info->hostname = NULL;
6.63 + backend_info->port = -1;
6.64 + backend_info->username = NULL;
6.65 + backend_info->password = NULL;
6.66 + backend_info->db_name = NULL;
6.67 + backend_info->db_port = 0;
6.68 + backend_info->status_port = -1;
6.69 +}
6.70 +
6.71 +static void
6.72 +gmyth_backend_info_dispose(GObject * object)
6.73 +{
6.74 + GMythBackendInfo *backend_info = GMYTH_BACKEND_INFO(object);
6.75 +
6.76 + g_free(backend_info->hostname);
6.77 + g_free(backend_info->username);
6.78 + g_free(backend_info->password);
6.79 + g_free(backend_info->db_name);
6.80 +
6.81 + if (backend_info->sock)
6.82 + g_object_unref (backend_info->sock);
6.83 +
6.84 + backend_info->hostname = NULL;
6.85 + backend_info->port = -1;
6.86 + backend_info->username = NULL;
6.87 + backend_info->password = NULL;
6.88 + backend_info->db_name = NULL;
6.89 + backend_info->db_port = 0;
6.90 + backend_info->status_port = -1;
6.91 + backend_info->sock = NULL;
6.92 +
6.93 + G_OBJECT_CLASS(gmyth_backend_info_parent_class)->dispose(object);
6.94 +}
6.95 +
6.96 +static void
6.97 +gmyth_backend_info_finalize(GObject * object)
6.98 +{
6.99 + g_signal_handlers_destroy(object);
6.100 +
6.101 + G_OBJECT_CLASS(gmyth_backend_info_parent_class)->finalize(object);
6.102 +}
6.103 +
6.104 +/**
6.105 + * Creates a new instance of GMythBackendInfo.
6.106 + *
6.107 + * @return a new instance of GMythBackendInfo.
6.108 + */
6.109 +GMythBackendInfo *
6.110 +gmyth_backend_info_new()
6.111 +{
6.112 + GMythBackendInfo *backend_info =
6.113 + GMYTH_BACKEND_INFO(g_object_new(GMYTH_BACKEND_INFO_TYPE, NULL));
6.114 +
6.115 + return backend_info;
6.116 +}
6.117 +
6.118 +/**
6.119 + * Creates a new instance of GMythBackendInfo, based on a given set of
6.120 + * configuration parameters.
6.121 + *
6.122 + * @param hostname The hostname to the MythTV backend server.
6.123 + * @param username The user name to the MythTV backend MySQL server.
6.124 + * @param password The password to the user of the MythTV backend MySQL server.
6.125 + * @param db_name The database name of the MythTV backend, stored on the MySQL server.
6.126 + * @param port The port number of the MythTV backend server (commonly is 6543).
6.127 + *
6.128 + * @return a new instance of GMythBackendInfo.
6.129 + */
6.130 +GMythBackendInfo *
6.131 +gmyth_backend_info_new_full(const gchar * hostname, const gchar * username,
6.132 + const gchar * password, const gchar * db_name,
6.133 + gint port)
6.134 +{
6.135 + GMythBackendInfo *backend_info =
6.136 + GMYTH_BACKEND_INFO(g_object_new(GMYTH_BACKEND_INFO_TYPE, NULL));
6.137 +
6.138 + gmyth_backend_info_set_hostname(backend_info, hostname);
6.139 + gmyth_backend_info_set_username(backend_info, username);
6.140 + gmyth_backend_info_set_password(backend_info, password);
6.141 + gmyth_backend_info_set_db_name(backend_info, db_name);
6.142 + gmyth_backend_info_set_port(backend_info, port);
6.143 +
6.144 + return backend_info;
6.145 +}
6.146 +
6.147 +/**
6.148 + * Creates a new instance of GMythBackendInfo, based on the
6.149 + * MythTV's backend server URI string.
6.150 + *
6.151 + * @param uri_str The URI string pointing to the MythTV backend server.
6.152 + *
6.153 + * @return a new instance of GMythBackendInfo.
6.154 + */
6.155 +GMythBackendInfo *
6.156 +gmyth_backend_info_new_with_uri(const gchar * uri_str)
6.157 +{
6.158 + GMythBackendInfo *backend_info;
6.159 + GMythURI *uri;
6.160 + gchar **path_parts;
6.161 + gchar *db;
6.162 +
6.163 + backend_info = GMYTH_BACKEND_INFO(g_object_new(GMYTH_BACKEND_INFO_TYPE, NULL));
6.164 + uri = gmyth_uri_new_with_value (uri_str);
6.165 + path_parts = g_strsplit(gmyth_uri_get_path(uri), "&", -1);
6.166 + gmyth_backend_info_set_hostname(backend_info, gmyth_uri_get_host(uri));
6.167 + gmyth_backend_info_set_username(backend_info, gmyth_uri_get_user(uri));
6.168 + gmyth_backend_info_set_password(backend_info,
6.169 + gmyth_uri_get_password(uri));
6.170 +
6.171 + /*
6.172 + * gets the path info to database name, from the URI, and removes the
6.173 + * trash chars
6.174 + */
6.175 + if ((path_parts != NULL) && (strlen (path_parts[0]) > 0))
6.176 + {
6.177 + db = path_parts[0]+2;
6.178 + }
6.179 + else
6.180 + {
6.181 + db = gmyth_uri_get_path(uri);
6.182 + }
6.183 +
6.184 + gmyth_backend_info_set_db_name(backend_info, db);
6.185 +
6.186 + gmyth_backend_info_set_port(backend_info, gmyth_uri_get_port(uri));
6.187 +
6.188 + g_object_unref(uri);
6.189 + g_strfreev(path_parts);
6.190 +
6.191 + return backend_info;
6.192 +}
6.193 +
6.194 +void
6.195 +gmyth_backend_info_set_hostname(GMythBackendInfo * backend_info,
6.196 + const gchar * hostname)
6.197 +{
6.198 + g_return_if_fail(backend_info != NULL);
6.199 +
6.200 + if (NULL == hostname || strlen(hostname) <= 0) {
6.201 + gmyth_debug("Error trying to set a hostname equals to NULL.");
6.202 + } else {
6.203 + backend_info->hostname = g_strdup(hostname);
6.204 + }
6.205 +}
6.206 +
6.207 +void
6.208 +gmyth_backend_info_set_username(GMythBackendInfo * backend_info,
6.209 + const gchar * username)
6.210 +{
6.211 + g_return_if_fail(backend_info != NULL);
6.212 +
6.213 + backend_info->username = g_strdup(username);
6.214 +}
6.215 +
6.216 +void
6.217 +gmyth_backend_info_set_password(GMythBackendInfo * backend_info,
6.218 + const gchar * password)
6.219 +{
6.220 + g_return_if_fail(backend_info != NULL);
6.221 +
6.222 + backend_info->password = g_strdup(password);
6.223 +}
6.224 +
6.225 +void
6.226 +gmyth_backend_info_set_db_name(GMythBackendInfo * backend_info,
6.227 + const gchar * db_name)
6.228 +{
6.229 + g_return_if_fail(backend_info != NULL);
6.230 +
6.231 + backend_info->db_name = g_strdup(db_name);
6.232 +}
6.233 +
6.234 +void
6.235 +gmyth_backend_info_set_db_port(GMythBackendInfo * backend_info, gint db_port)
6.236 +{
6.237 + g_return_if_fail(backend_info != NULL);
6.238 +
6.239 + if (db_port <= 0) {
6.240 + gmyth_debug("Error trying to set a port less than 0.");
6.241 + } else {
6.242 + backend_info->db_port = db_port;
6.243 + }
6.244 +}
6.245 +
6.246 +void
6.247 +gmyth_backend_info_set_port(GMythBackendInfo * backend_info, gint port)
6.248 +{
6.249 + g_return_if_fail(backend_info != NULL);
6.250 +
6.251 + if (port <= 0) {
6.252 + gmyth_debug("Error trying to set a port less than 0.");
6.253 + } else {
6.254 + backend_info->port = port;
6.255 + }
6.256 +}
6.257 +
6.258 +void
6.259 +gmyth_backend_info_set_status_port(GMythBackendInfo * backend_info,
6.260 + gint port)
6.261 +{
6.262 + g_return_if_fail(backend_info != NULL);
6.263 +
6.264 + if (port <= 0) {
6.265 + gmyth_debug
6.266 + ("Error trying to set the status port to less than zero.");
6.267 + } else {
6.268 + backend_info->status_port = port;
6.269 + }
6.270 +}
6.271 +
6.272 +const gchar *
6.273 +gmyth_backend_info_get_hostname(GMythBackendInfo * backend_info)
6.274 +{
6.275 + g_return_val_if_fail(backend_info != NULL, NULL);
6.276 +
6.277 + return backend_info->hostname;
6.278 +}
6.279 +
6.280 +const gchar *
6.281 +gmyth_backend_info_get_username(GMythBackendInfo * backend_info)
6.282 +{
6.283 + g_return_val_if_fail(backend_info != NULL, NULL);
6.284 +
6.285 + return backend_info->username;
6.286 +}
6.287 +
6.288 +const gchar *
6.289 +gmyth_backend_info_get_password(GMythBackendInfo * backend_info)
6.290 +{
6.291 + g_return_val_if_fail(backend_info != NULL, NULL);
6.292 +
6.293 + return backend_info->password;
6.294 +}
6.295 +
6.296 +const gchar *
6.297 +gmyth_backend_info_get_db_name(GMythBackendInfo * backend_info)
6.298 +{
6.299 + g_return_val_if_fail(backend_info != NULL, NULL);
6.300 +
6.301 + return backend_info->db_name;
6.302 +}
6.303 +
6.304 +gint
6.305 +gmyth_backend_info_get_idb_port(GMythBackendInfo * backend_info)
6.306 +{
6.307 + g_return_val_if_fail(backend_info != NULL, -1);
6.308 +
6.309 + return backend_info->db_port;
6.310 +}
6.311 +
6.312 +
6.313 +gint
6.314 +gmyth_backend_info_get_port(GMythBackendInfo * backend_info)
6.315 +{
6.316 + g_return_val_if_fail(backend_info != NULL, -1);
6.317 +
6.318 + return backend_info->port;
6.319 +}
6.320 +
6.321 +/**
6.322 + * Creates a new instance of GMythURI, based on the GMythBackendInfo instance to the
6.323 + * MythTV's backend server.
6.324 + *
6.325 + * @param backend_info The GMythBackendInfo instance.
6.326 + *
6.327 + * @return an instance of GMythURI, created from a GMythBackendInfo.
6.328 + */
6.329 +GMythURI *
6.330 +gmyth_backend_info_get_uri(GMythBackendInfo * backend_info)
6.331 +{
6.332 + GMythURI *uri = NULL;
6.333 + gchar *uri_str = NULL;
6.334 + gchar *user_info = NULL;
6.335 + gchar *db_data = NULL;
6.336 +
6.337 + if ((backend_info->username != NULL
6.338 + && strlen(backend_info->username) > 0))
6.339 + user_info =
6.340 + g_strdup_printf("%s:%s@", backend_info->username,
6.341 + backend_info->password);
6.342 +
6.343 + if (backend_info->db_name != NULL && strlen(backend_info->db_name) > 0) {
6.344 + if ((g_strrstr(backend_info->db_name, "_") != NULL))
6.345 + db_data = g_strdup(backend_info->db_name);
6.346 + else
6.347 + db_data = g_strdup_printf("?%s&", backend_info->db_name);
6.348 + }
6.349 + // else if ( ( ( g_strrstr( backend_info->path, "livetv" ) != NULL )
6.350 + // ||
6.351 + // ( g_strrstr( backend_info->path, "/?" ) != NULL ) )
6.352 +
6.353 + uri_str = g_strdup_printf("myth://%s%s:%d/%s", user_info != NULL
6.354 + && strlen(user_info) > 0 ? user_info : "",
6.355 + backend_info->hostname, backend_info->port,
6.356 + db_data != NULL
6.357 + && strlen(db_data) > 0 ? db_data : "");
6.358 + uri = gmyth_uri_new_with_value(uri_str);
6.359 +
6.360 + if (user_info != NULL)
6.361 + g_free(user_info);
6.362 +
6.363 + if (db_data != NULL)
6.364 + g_free(db_data);
6.365 +
6.366 + g_free(uri_str);
6.367 +
6.368 + return uri;
6.369 +}
6.370 +
6.371 +gboolean
6.372 +gmyth_backend_info_is_local_file(GMythBackendInfo * backend_info)
6.373 +{
6.374 + g_return_val_if_fail(backend_info != NULL, FALSE);
6.375 +
6.376 + return
6.377 + gmyth_uri_is_local_file(gmyth_backend_info_get_uri(backend_info));
6.378 +}
6.379 +
6.380 +GMythSocket*
6.381 +gmyth_backend_info_get_connected_socket (GMythBackendInfo *backend_info)
6.382 +{
6.383 + if (backend_info->sock == NULL) {
6.384 + gboolean res;
6.385 + backend_info->sock = gmyth_socket_new ();
6.386 + res = gmyth_socket_connect_to_backend (backend_info->sock,
6.387 + backend_info->hostname,
6.388 + backend_info->port,
6.389 + TRUE);
6.390 + if (res == FALSE) {
6.391 + g_object_unref (backend_info->sock);
6.392 + backend_info->sock = NULL;
6.393 + return NULL;
6.394 + }
6.395 + }
6.396 +
6.397 + return g_object_ref (backend_info->sock);
6.398 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/gmyth/gmyth/gmyth_backendinfo.h Mon Feb 25 17:51:43 2008 +0000
7.3 @@ -0,0 +1,121 @@
7.4 +/**
7.5 + * GMyth Library
7.6 + *
7.7 + * @file gmyth/gmyth_backend_info.h
7.8 + *
7.9 + * @brief <p> This component represents all the MythTV backend server
7.10 + * configuration information.
7.11 + *
7.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
7.13 + * @author Hallyson Melo <hallyson.melo@indt.org.br>
7.14 + * @author Rosfran Borges <rosfran.borges@indt.org.br>
7.15 + *
7.16 +*
7.17 +* This program is free software; you can redistribute it and/or modify
7.18 +* it under the terms of the GNU Lesser General Public License as published by
7.19 +* the Free Software Foundation; either version 2 of the License, or
7.20 +* (at your option) any later version.
7.21 +*
7.22 +* This program is distributed in the hope that it will be useful,
7.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7.25 + * GNU General Public License for more details.
7.26 + *
7.27 + * You should have received a copy of the GNU Lesser General Public License
7.28 + * along with this program; if not, write to the Free Software
7.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
7.30 + */
7.31 +
7.32 +#ifndef __GMYTH_BACKEND_INFO_H__
7.33 +#define __GMYTH_BACKEND_INFO_H__
7.34 +
7.35 +#include <glib-object.h>
7.36 +
7.37 +#include "gmyth_uri.h"
7.38 +#include "gmyth_socket.h"
7.39 +
7.40 +G_BEGIN_DECLS
7.41 +#define GMYTH_BACKEND_INFO_TYPE \
7.42 + (gmyth_backend_info_get_type ())
7.43 +#define GMYTH_BACKEND_INFO(obj) \
7.44 + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_BACKEND_INFO_TYPE, GMythBackendInfo))
7.45 +#define GMYTH_BACKEND_INFO_CLASS(klass) \
7.46 + (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_BACKEND_INFO_TYPE, GMythBackendInfoClass))
7.47 +#define IS_GMYTH_BACKEND_INFO(obj) \
7.48 + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_BACKEND_INFO_TYPE))
7.49 +#define IS_GMYTH_BACKEND_INFO_CLASS(klass) \
7.50 + (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_BACKEND_INFO_TYPE))
7.51 +#define GMYTH_BACKEND_INFO_GET_CLASS(obj) \
7.52 + (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_BACKEND_INFO_TYPE, GMythBackendInfoClass))
7.53 +
7.54 +typedef struct _GMythBackendInfo GMythBackendInfo;
7.55 +typedef struct _GMythBackendInfoClass GMythBackendInfoClass;
7.56 +
7.57 +struct _GMythBackendInfoClass {
7.58 + GObjectClass parent_class;
7.59 +
7.60 + /*
7.61 + * callbacks
7.62 + */
7.63 + /*
7.64 + * no one for now
7.65 + */
7.66 +};
7.67 +
7.68 +struct _GMythBackendInfo {
7.69 + GObject parent;
7.70 + /** The backend hostname or ip address. */
7.71 + gchar *hostname;
7.72 + /** The backend port. */
7.73 + gint port;
7.74 + /** The username to connect to the mysql server. */
7.75 + gchar *username;
7.76 + /** The password to connect to the mysql server. */
7.77 + gchar *password;
7.78 + /** The mythtv's mysql database name. */
7.79 + gchar *db_name;
7.80 + /** The mysql database port */
7.81 + gint db_port;
7.82 + /** The backend status port for http connection */
7.83 + gint status_port;
7.84 +
7.85 + /* Private */
7.86 + GMythSocket *sock;
7.87 +};
7.88 +
7.89 +
7.90 +GType gmyth_backend_info_get_type (void) G_GNUC_CONST;
7.91 +GMythBackendInfo* gmyth_backend_info_new (void);
7.92 +GMythBackendInfo* gmyth_backend_info_new_full (const gchar *hostname,
7.93 + const gchar *username,
7.94 + const gchar *password,
7.95 + const gchar *db_name,
7.96 + gint port);
7.97 +GMythBackendInfo* gmyth_backend_info_new_with_uri (const gchar *uri_str);
7.98 +void gmyth_backend_info_set_hostname (GMythBackendInfo *backend_info,
7.99 + const gchar *hostname);
7.100 +void gmyth_backend_info_set_username (GMythBackendInfo *backend_info,
7.101 + const gchar *username);
7.102 +void gmyth_backend_info_set_password (GMythBackendInfo *backend_info,
7.103 + const gchar *password);
7.104 +void gmyth_backend_info_set_db_name (GMythBackendInfo *backend_info,
7.105 + const gchar *db_name);
7.106 +void gmyth_backend_info_set_db_port (GMythBackendInfo *backend_info,
7.107 + gint db_port);
7.108 +void gmyth_backend_info_set_port (GMythBackendInfo *backend_info,
7.109 + gint port);
7.110 +void gmyth_backend_info_set_status_port (GMythBackendInfo *backend_info,
7.111 + gint port);
7.112 +const gchar* gmyth_backend_info_get_hostname (GMythBackendInfo *backend_info);
7.113 +const gchar* gmyth_backend_info_get_username (GMythBackendInfo *backend_info);
7.114 +const gchar* gmyth_backend_info_get_password (GMythBackendInfo *backend_info);
7.115 +const gchar* gmyth_backend_info_get_db_name (GMythBackendInfo *backend_info);
7.116 +gint gmyth_backend_info_get_db_port (GMythBackendInfo *backend_info);
7.117 +gint gmyth_backend_info_get_port (GMythBackendInfo *backend_info);
7.118 +GMythURI* gmyth_backend_info_get_uri (GMythBackendInfo *backend_info);
7.119 +gboolean gmyth_backend_info_is_local_file (GMythBackendInfo *backend_info);
7.120 +GMythSocket* gmyth_backend_info_get_connected_socket
7.121 + (GMythBackendInfo *backend_info);
7.122 +
7.123 +G_END_DECLS
7.124 +#endif /* __GMYTH_BACKEND_INFO_H__ */
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/gmyth/gmyth/gmyth_common.c Mon Feb 25 17:51:43 2008 +0000
8.3 @@ -0,0 +1,154 @@
8.4 +/**
8.5 + * GMyth Library
8.6 + *
8.7 + * @file gmyth/gmyth_common.c
8.8 + *
8.9 + * @brief <p> This file contains basic common functions for the gmyth library.
8.10 + *
8.11 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
8.12 + * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
8.13 + * @author Rosfran Borges <rosfran.borges@indt.org.br>
8.14 + *
8.15 + *
8.16 + * This program is free software; you can redistribute it and/or modify
8.17 + * it under the terms of the GNU Lesser General Public License as published by
8.18 + * the Free Software Foundation; either version 2 of the License, or
8.19 + * (at your option) any later version.
8.20 + *
8.21 + * This program is distributed in the hope that it will be useful,
8.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8.24 + * GNU General Public License for more details.
8.25 + *
8.26 + * You should have received a copy of the GNU Lesser General Public License
8.27 + * along with this program; if not, write to the Free Software
8.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
8.29 + */
8.30 +
8.31 +#ifdef HAVE_CONFIG_H
8.32 +#include "config.h"
8.33 +#endif
8.34 +
8.35 +#include "gmyth_common.h"
8.36 +#include "gmyth_debug.h"
8.37 +#include "gmyth_util.h"
8.38 +
8.39 +static void free_channel_data(gpointer data, gpointer user_data);
8.40 +static void free_program_data(gpointer data, gpointer user_data);
8.41 +
8.42 +/**
8.43 +* Frees the memory allocated to the GMythChannelInfo objects inside list.
8.44 +* The list memory is also released by g_list_free(). If LIST is NULL it
8.45 +* simply returns.
8.46 +*
8.47 +* @param list the GList containing a list of GMythChannelInfo to free.
8.48 +*/
8.49 +void
8.50 +gmyth_free_channel_list(GList * list)
8.51 +{
8.52 + g_return_if_fail(list != NULL);
8.53 +
8.54 + g_list_foreach(list, free_channel_data, NULL);
8.55 + g_list_free(list);
8.56 +}
8.57 +
8.58 +/**
8.59 + * Frees the memory allocated to the GMythProgramInfo objects inside list.
8.60 + * The list memory is also released by g_list_free(). If list is NULL it
8.61 + * simply returns.
8.62 + *
8.63 + * @param list the GList containing a list of GMythProgramInfo to free.
8.64 + */
8.65 +void
8.66 +gmyth_free_program_list(GList * list)
8.67 +{
8.68 + g_return_if_fail(list != NULL);
8.69 +
8.70 + g_list_foreach(list, free_program_data, NULL);
8.71 + g_list_free(list);
8.72 +}
8.73 +
8.74 +void
8.75 +gmyth_channel_info_free(GMythChannelInfo * channel)
8.76 +{
8.77 + g_return_if_fail(channel != NULL);
8.78 +
8.79 + if (channel->channel_num)
8.80 + g_string_free(channel->channel_num, TRUE);
8.81 +
8.82 + if (channel->channel_name)
8.83 + g_string_free(channel->channel_name, TRUE);
8.84 +
8.85 + if (channel->channel_icon)
8.86 + g_string_free(channel->channel_icon, TRUE);
8.87 +
8.88 + g_free(channel);
8.89 +}
8.90 +
8.91 +/**
8.92 + * Prints the channel info to the standard output. The gmyth debug must be enabled.
8.93 + * @param channel_info the GMythChannelInfo instance
8.94 + */
8.95 +void
8.96 +gmyth_channel_info_print(GMythChannelInfo * channel_info)
8.97 +{
8.98 +#ifdef GMYTH_USE_DEBUG
8.99 + if (channel_info != NULL) {
8.100 + g_return_if_fail(channel_info->channel_name != NULL);
8.101 + g_return_if_fail(channel_info->channel_num != NULL);
8.102 +
8.103 + gmyth_debug("ChannelInfo (Name, Num, ID) = (%s, %s, %d)",
8.104 + channel_info->channel_name->str,
8.105 + channel_info->channel_num->str,
8.106 + channel_info->channel_ID);
8.107 +
8.108 + }
8.109 +#endif
8.110 +}
8.111 +
8.112 +/**
8.113 + * Prints the program info to the standard output. The gmyth debug must be enabled.
8.114 + * @param channel_info the GMythProgramInfo instance
8.115 + */
8.116 +void
8.117 +gmyth_program_info_print(GMythProgramInfo * program_info)
8.118 +{
8.119 +#ifdef GMYTH_USE_DEBUG
8.120 + g_return_if_fail(program_info);
8.121 +
8.122 + gmyth_debug("ProgramInfo\n\tTitle = %s\n\t"
8.123 + "Description = %s\n\t"
8.124 + "Start time= %s\t"
8.125 + "End time = %s\n"
8.126 + "Path name = %s\n"
8.127 + "File size = %lld\n",
8.128 + program_info->title ? program_info->title->str : "NULL",
8.129 + program_info->description ? program_info->description->
8.130 + str : "NULL",
8.131 + gmyth_util_time_to_string_from_time_val(program_info->
8.132 + startts),
8.133 + gmyth_util_time_to_string_from_time_val(program_info->
8.134 + endts),
8.135 + program_info->pathname ? program_info->pathname->
8.136 + str : "NULL", program_info->filesize);
8.137 +#endif
8.138 +}
8.139 +
8.140 +static void
8.141 +free_channel_data(gpointer data, gpointer user_data)
8.142 +{
8.143 + /*
8.144 + * Frees the GMythChannelInfo structure
8.145 + */
8.146 + GMythChannelInfo *channel = (GMythChannelInfo *) data;
8.147 +
8.148 + gmyth_channel_info_free(channel);
8.149 +}
8.150 +
8.151 +static void
8.152 +free_program_data(gpointer data, gpointer user_data)
8.153 +{
8.154 + g_return_if_fail(data != NULL);
8.155 +
8.156 + g_object_unref((GMythProgramInfo *) data);
8.157 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/gmyth/gmyth/gmyth_common.h Mon Feb 25 17:51:43 2008 +0000
9.3 @@ -0,0 +1,62 @@
9.4 +/**
9.5 + * GMyth Library
9.6 + *
9.7 + * @file gmyth/gmyth_common.h
9.8 + *
9.9 + * @brief <p> This file contains basic common functions for the gmyth library.
9.10 + *
9.11 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
9.12 + * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
9.13 + * @author Rosfran Borges <rosfran.borges@indt.org.br>
9.14 + *
9.15 + *
9.16 + * This program is free software; you can redistribute it and/or modify
9.17 + * it under the terms of the GNU Lesser General Public License as published by
9.18 + * the Free Software Foundation; either version 2 of the License, or
9.19 + * (at your option) any later version.
9.20 + *
9.21 + * This program is distributed in the hope that it will be useful,
9.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
9.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9.24 + * GNU General Public License for more details.
9.25 + *
9.26 + * You should have received a copy of the GNU Lesser General Public License
9.27 + * along with this program; if not, write to the Free Software
9.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9.29 + */
9.30 +
9.31 +#ifndef GMYTH_COMMON_H_
9.32 +#define GMYTH_COMMON_H_
9.33 +
9.34 +#include <glib.h>
9.35 +#include <time.h>
9.36 +
9.37 +#include "gmyth_programinfo.h"
9.38 +
9.39 +G_BEGIN_DECLS
9.40 + /**
9.41 + * The GMythChannelInfo structure represents the channel information
9.42 + * stored in the backend database.
9.43 + */
9.44 + typedef struct {
9.45 + /** The channel ID in backend database */
9.46 + gint channel_ID;
9.47 +
9.48 + /** The channel number */
9.49 + GString *channel_num;
9.50 +
9.51 + /** The channel name in backend database */
9.52 + GString *channel_name;
9.53 +
9.54 + /** The channel icon path in the backend database */
9.55 + GString *channel_icon;
9.56 +} GMythChannelInfo;
9.57 +
9.58 +void gmyth_free_channel_list (GList *list);
9.59 +void gmyth_free_program_list (GList *list);
9.60 +void gmyth_channel_info_free (GMythChannelInfo *channel_info);
9.61 +void gmyth_channel_info_print (GMythChannelInfo *channel_info);
9.62 +void gmyth_program_info_print (GMythProgramInfo *program_info);
9.63 +
9.64 +G_END_DECLS
9.65 +#endif /* GMYTH_COMMON_H_ */
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/gmyth/gmyth/gmyth_debug.c Mon Feb 25 17:51:43 2008 +0000
10.3 @@ -0,0 +1,54 @@
10.4 +/**
10.5 + * GMyth Library
10.6 + *
10.7 + * @file gmyth/gmyth_debug.c
10.8 + *
10.9 + *
10.10 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
10.11 + * @author Renato Filho <renato.filho@indt.org.br>
10.12 + *
10.13 + *
10.14 + * This program is free software; you can redistribute it and/or modify
10.15 + * it under the terms of the GNU Lesser General Public License as published by
10.16 + * the Free Software Foundation; either version 2 of the License, or
10.17 + * (at your option) any later version.
10.18 + *
10.19 + * This program is distributed in the hope that it will be useful,
10.20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
10.21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10.22 + * GNU General Public License for more details.
10.23 + *
10.24 + * You should have received a copy of the GNU Lesser General Public License
10.25 + * along with this program; if not, write to the Free Software
10.26 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
10.27 + */
10.28 +
10.29 +#ifdef HAVE_CONFIG_H
10.30 +#include "config.h"
10.31 +#endif
10.32 +
10.33 +#include "gmyth_debug.h"
10.34 +
10.35 +void
10.36 +gmyth_debug_real(const char *func,
10.37 + const char *file, const int line, gboolean newline,
10.38 + const char *format, ...)
10.39 +{
10.40 + va_list args;
10.41 + char buffer[1025];
10.42 + char str_time[255];
10.43 + time_t the_time;
10.44 +
10.45 + va_start(args, format);
10.46 +
10.47 + g_vsnprintf(buffer, 1024, format, args);
10.48 +
10.49 + va_end(args);
10.50 +
10.51 + time(&the_time);
10.52 + strftime(str_time, 254, "%H:%M:%S", localtime(&the_time));
10.53 +
10.54 + g_printerr(newline ? "(%s) [%p] [%s] %s:%d: %s\n" :
10.55 + "(%s) [%p] [%s] %s:%d: %s", str_time, g_thread_self(), func,
10.56 + file, line, buffer);
10.57 +}
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/gmyth/gmyth/gmyth_debug.h Mon Feb 25 17:51:43 2008 +0000
11.3 @@ -0,0 +1,46 @@
11.4 +/**
11.5 + * GMyth Library
11.6 + *
11.7 + * @file gmyth/gmyth_debug.h
11.8 + *
11.9 + *
11.10 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
11.11 + * @author Renato Filho <renato.filho@indt.org.br>
11.12 + *
11.13 +*
11.14 +* This program is free software; you can redistribute it and/or modify
11.15 +* it under the terms of the GNU Lesser General Public License as published by
11.16 +* the Free Software Foundation; either version 2 of the License, or
11.17 +* (at your option) any later version.
11.18 +*
11.19 +* This program is distributed in the hope that it will be useful,
11.20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
11.21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11.22 + * GNU General Public License for more details.
11.23 + *
11.24 + * You should have received a copy of the GNU Lesser General Public License
11.25 + * along with this program; if not, write to the Free Software
11.26 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
11.27 + */
11.28 +
11.29 +#ifndef __GMYTH_DEBUG_H__
11.30 +#define __GMYTH_DEBUG_H__
11.31 +
11.32 +#include <stdarg.h>
11.33 +#include <glib.h>
11.34 +#include <time.h>
11.35 +
11.36 +G_BEGIN_DECLS
11.37 +#ifdef GMYTH_USE_DEBUG
11.38 +#define gmyth_debug(...) gmyth_debug_real (__FUNCTION__, __FILE__, __LINE__, TRUE, __VA_ARGS__)
11.39 +#else
11.40 +#define gmyth_debug(...)
11.41 +#endif
11.42 + void
11.43 +gmyth_debug_real(const char *func,
11.44 + const char *file, int line, gboolean newline,
11.45 + const char *format, ...)
11.46 +G_GNUC_PRINTF(5, 6);
11.47 +
11.48 +G_END_DECLS
11.49 +#endif
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/gmyth/gmyth/gmyth_epg.c Mon Feb 25 17:51:43 2008 +0000
12.3 @@ -0,0 +1,446 @@
12.4 +/**
12.5 + * GMyth Library
12.6 + *
12.7 + * @file gmyth/gmyth_epg.c
12.8 + *
12.9 + * @brief <p> GMythEPG class provides access to the program and channel data
12.10 + * from the Electronic Program Guide (EPG) of the Mythtv backend.
12.11 + *
12.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
12.13 + * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
12.14 + *
12.15 + * This program is free software; you can redistribute it and/or modify
12.16 + * it under the terms of the GNU Lesser General Public License as published by
12.17 + * the Free Software Foundation; either version 2 of the License, or
12.18 + * (at your option) any later version.
12.19 + *
12.20 + * This program is distributed in the hope that it will be useful,
12.21 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
12.22 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12.23 + * GNU General Public License for more details.
12.24 + *
12.25 + * You should have received a copy of the GNU Lesser General Public License
12.26 + * along with this program; if not, write to the Free Software
12.27 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
12.28 + */
12.29 +
12.30 +#ifdef HAVE_CONFIG_H
12.31 +#include "config.h"
12.32 +#endif
12.33 +
12.34 +#include <mysql/mysql.h>
12.35 +#include <stdlib.h>
12.36 +#include <string.h>
12.37 +#include <assert.h>
12.38 +
12.39 +#include "gmyth_epg.h"
12.40 +#include "gmyth_programinfo.h"
12.41 +#include "gmyth_util.h"
12.42 +#include "gmyth_file_transfer.h"
12.43 +#include "gmyth_debug.h"
12.44 +
12.45 +#define CONNECT_TIMEOUT 6
12.46 +
12.47 +static void gmyth_epg_class_init(GMythEPGClass * klass);
12.48 +static void gmyth_epg_init(GMythEPG * object);
12.49 +
12.50 +static void gmyth_epg_dispose(GObject * object);
12.51 +static void gmyth_epg_finalize(GObject * object);
12.52 +
12.53 +G_DEFINE_TYPE(GMythEPG, gmyth_epg, G_TYPE_OBJECT)
12.54 + static void gmyth_epg_class_init(GMythEPGClass * klass)
12.55 +{
12.56 + GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
12.57 +
12.58 + gobject_class->dispose = gmyth_epg_dispose;
12.59 + gobject_class->finalize = gmyth_epg_finalize;
12.60 +}
12.61 +
12.62 +static void
12.63 +gmyth_epg_init(GMythEPG * gmyth_epg)
12.64 +{
12.65 +
12.66 +}
12.67 +
12.68 +static void
12.69 +gmyth_epg_dispose(GObject * object)
12.70 +{
12.71 + GMythEPG *gmyth_epg = GMYTH_EPG(object);
12.72 +
12.73 + if (gmyth_epg->sqlquery != NULL) {
12.74 + g_object_unref(gmyth_epg->sqlquery);
12.75 + gmyth_epg->sqlquery = NULL;
12.76 + }
12.77 +
12.78 + G_OBJECT_CLASS(gmyth_epg_parent_class)->dispose(object);
12.79 +}
12.80 +
12.81 +static void
12.82 +gmyth_epg_finalize(GObject * object)
12.83 +{
12.84 + g_signal_handlers_destroy(object);
12.85 +
12.86 + G_OBJECT_CLASS(gmyth_epg_parent_class)->finalize(object);
12.87 +}
12.88 +
12.89 +/**
12.90 + * Creates a new instance of GMythEPG.
12.91 + *
12.92 + * @return a new instance of GMythEPG.
12.93 + */
12.94 +GMythEPG *
12.95 +gmyth_epg_new(void)
12.96 +{
12.97 + GMythEPG *epg = GMYTH_EPG(g_object_new(GMYTH_EPG_TYPE, NULL));
12.98 +
12.99 + return epg;
12.100 +}
12.101 +
12.102 +/** Connects to the Mysql database in the backend. The backend address
12.103 + * is loaded from the GMythSettings instance.
12.104 + *
12.105 + * @param gmyth_epg the GMythEPG instance to be connected.
12.106 + * @return true if connection was success, false if failed.
12.107 + */
12.108 +gboolean
12.109 +gmyth_epg_connect(GMythEPG * gmyth_epg, GMythBackendInfo * backend_info)
12.110 +{
12.111 + g_return_val_if_fail(gmyth_epg != NULL, FALSE);
12.112 +
12.113 + if (gmyth_epg->sqlquery == NULL) {
12.114 + gmyth_debug("[%s] Creating gmyth_query", __FUNCTION__);
12.115 + gmyth_epg->sqlquery = gmyth_query_new();
12.116 + }
12.117 +
12.118 + if (!gmyth_query_connect_with_timeout(gmyth_epg->sqlquery,
12.119 + backend_info, CONNECT_TIMEOUT)) {
12.120 + gmyth_debug("[%s] Error while connecting to db", __FUNCTION__);
12.121 + return FALSE;
12.122 + }
12.123 +
12.124 + gmyth_epg->backend_info = backend_info;
12.125 + g_object_ref(backend_info);
12.126 +
12.127 + return TRUE;
12.128 +}
12.129 +
12.130 +/** Disconnects from the Mysql database in the backend.
12.131 + *
12.132 + * @param gmyth_epg the GMythEPG instance to be disconnected
12.133 + * @return true if disconnection was success, false if failed.
12.134 + */
12.135 +gboolean
12.136 +gmyth_epg_disconnect(GMythEPG * gmyth_epg)
12.137 +{
12.138 + g_return_val_if_fail(gmyth_epg != NULL, FALSE);
12.139 +
12.140 + if (gmyth_epg->sqlquery != NULL) {
12.141 + gmyth_query_disconnect(gmyth_epg->sqlquery);
12.142 + g_object_unref(gmyth_epg->sqlquery);
12.143 + gmyth_epg->sqlquery = NULL;
12.144 + }
12.145 +
12.146 + if (gmyth_epg->backend_info != NULL) {
12.147 + g_object_unref(gmyth_epg->backend_info);
12.148 + gmyth_epg->backend_info = NULL;
12.149 + }
12.150 +
12.151 + return TRUE;
12.152 +}
12.153 +
12.154 +/** Retrieves the available list of channels from the backend Mysql database.
12.155 + *
12.156 + * @param gmyth_epg the GMythEPG instance.
12.157 + * @param glist_ptr the GSList pointer to be filled with the loaded list address.
12.158 + * @return The amount of channels retrieved from database, or -1 if error.
12.159 + */
12.160 +gint
12.161 +gmyth_epg_get_channel_list(GMythEPG * gmyth_epg, GList ** glist_ptr)
12.162 +{
12.163 + MYSQL_RES *msql_res;
12.164 +
12.165 + g_return_val_if_fail(gmyth_epg != NULL, -1);
12.166 +
12.167 + msql_res = gmyth_query_process_statement(gmyth_epg->sqlquery,
12.168 + "SELECT chanid, channum, name, icon FROM channel;");
12.169 +
12.170 + (*glist_ptr) = NULL;
12.171 +
12.172 + if (msql_res == NULL) {
12.173 + gmyth_debug("[%s] msql query returned NULL MYSQL_RES",
12.174 + __FUNCTION__);
12.175 + return -1;
12.176 + } else {
12.177 + MYSQL_ROW row;
12.178 + GMythChannelInfo *channel_info;
12.179 +
12.180 + while ((row = mysql_fetch_row(msql_res)) != NULL) {
12.181 +
12.182 + channel_info = g_new0(GMythChannelInfo, 1);
12.183 + channel_info->channel_ID =
12.184 + (gint) g_ascii_strtoull(row[0], NULL, 10);
12.185 + channel_info->channel_num = g_string_new(row[1]);
12.186 + channel_info->channel_name = g_string_new(row[2]);
12.187 + channel_info->channel_icon = g_string_new(row[3]);
12.188 +#ifdef GMYTH_USE_DEBUG
12.189 + gmyth_channel_info_print(channel_info);
12.190 +#endif
12.191 + (*glist_ptr) = g_list_append((*glist_ptr), channel_info);
12.192 + }
12.193 + }
12.194 + mysql_free_result(msql_res);
12.195 +
12.196 + return (!(*glist_ptr)) ? 0 : g_list_length(*glist_ptr);
12.197 +}
12.198 +
12.199 +GMythChannelInfo *
12.200 +gmyth_epg_get_channel_info(GMythEPG * gmyth_epg, gint channel_id)
12.201 +{
12.202 + GMythChannelInfo *channel_info = NULL;
12.203 + MYSQL_RES *msql_res;
12.204 + gchar *query_str;
12.205 +
12.206 + g_return_val_if_fail(gmyth_epg != NULL, NULL);
12.207 +
12.208 + query_str =
12.209 + g_strdup_printf
12.210 + ("SELECT channum, name, icon FROM channel WHERE chanid=%d;",
12.211 + channel_id);
12.212 + msql_res =
12.213 + gmyth_query_process_statement(gmyth_epg->sqlquery, query_str);
12.214 +
12.215 + if (msql_res == NULL) {
12.216 + gmyth_debug("[%s] msql query returned NULL MYSQL_RES",
12.217 + __FUNCTION__);
12.218 + return NULL;
12.219 + } else {
12.220 + MYSQL_ROW row;
12.221 +
12.222 + if ((row = mysql_fetch_row(msql_res)) != NULL) {
12.223 +
12.224 + channel_info = g_new0(GMythChannelInfo, 1);
12.225 + channel_info->channel_ID = channel_id;
12.226 + channel_info->channel_num = g_string_new(row[0]);
12.227 + channel_info->channel_name = g_string_new(row[1]);
12.228 + channel_info->channel_icon = g_string_new(row[2]);
12.229 +#ifdef GMYTH_USE_DEBUG
12.230 + gmyth_channel_info_print(channel_info);
12.231 +#endif
12.232 + }
12.233 + }
12.234 + mysql_free_result(msql_res);
12.235 +
12.236 + return channel_info;
12.237 +}
12.238 +
12.239 +/**
12.240 + * Retrieves the available list of channels from the backend Mysql database.
12.241 + *
12.242 + * @param gmyth_epg the GMythEPG instance.
12.243 + * @param proglist the GSList pointer to be filled with the loaded list.
12.244 + * @param chan_num the channel num on which to search for program.
12.245 + * @param starttime the start time to search for programs.
12.246 + * @param endtime the end time to search for programs.
12.247 + * @return The amount of channels retrieved from database, or -1 if error.
12.248 + */
12.249 +gint
12.250 +gmyth_epg_get_program_list(GMythEPG * gmyth_epg, GList ** proglist,
12.251 + const gint chan_num, GTimeVal * starttime,
12.252 + GTimeVal * endtime)
12.253 +{
12.254 +
12.255 + gchar *startts =
12.256 + gmyth_util_time_to_string_from_time_val(starttime);
12.257 + gchar *endts =
12.258 + gmyth_util_time_to_string_from_time_val(endtime);
12.259 + MYSQL_ROW row;
12.260 + GString *querystr;
12.261 +
12.262 + assert(gmyth_epg);
12.263 +
12.264 + querystr =
12.265 + g_string_new
12.266 + ("SELECT DISTINCT program.chanid, program.starttime, program.endtime, "
12.267 + " program.title, program.subtitle, program.description, "
12.268 + " program.category, channel.channum, channel.callsign, "
12.269 + " channel.name, program.previouslyshown, channel.commfree, "
12.270 + " channel.outputfilters, program.seriesid, program.programid, "
12.271 + " program.airdate, program.stars, program.originalairdate, "
12.272 + " program.category_type, record.recordid, "
12.273 + " oldrecstatus.rectype, oldrecstatus.recstatus, "
12.274 + " oldrecstatus.findid "
12.275 + "FROM program "
12.276 + "LEFT JOIN channel ON program.chanid = channel.chanid "
12.277 + "LEFT JOIN record ON "
12.278 + " program.chanid = record.chanid AND "
12.279 + " DATE (program.starttime) = record.startdate AND "
12.280 + " TIME (program.starttime) = record.starttime AND "
12.281 + " DATE (program.endtime) = record.enddate AND "
12.282 + " TIME (program.endtime) = record.endtime "
12.283 + "LEFT JOIN oldrecorded AS oldrecstatus ON "
12.284 + " program.title = oldrecstatus.title AND "
12.285 + " channel.callsign = oldrecstatus.station AND "
12.286 + " program.starttime = oldrecstatus.starttime ");
12.287 +
12.288 + g_string_append_printf(querystr,
12.289 + "WHERE program.chanid = %d "
12.290 + " AND program.endtime >= '%s' "
12.291 + " AND program.starttime <= '%s' "
12.292 + " AND program.manualid = 0 ", chan_num,
12.293 + startts, endts);
12.294 +
12.295 + if (!g_strrstr(querystr->str, " GROUP BY "))
12.296 + querystr = g_string_append(querystr,
12.297 + " GROUP BY program.starttime, channel.channum, "
12.298 + " channel.callsign, program.title ");
12.299 +
12.300 + if (!g_strrstr(querystr->str, " LIMIT "))
12.301 + querystr = g_string_append(querystr, " LIMIT 1000 ");
12.302 +
12.303 + MYSQL_RES *res_set =
12.304 + gmyth_query_process_statement(gmyth_epg->sqlquery, querystr->str);
12.305 +
12.306 + if (res_set == NULL) {
12.307 + gmyth_debug("[%s] msql query returned NULL MYSQL_RES",
12.308 + __FUNCTION__);
12.309 + return -1;
12.310 + }
12.311 +
12.312 + *proglist = NULL;
12.313 + while ((row = mysql_fetch_row(res_set)) != NULL) {
12.314 +
12.315 + GMythProgramInfo *p = gmyth_program_info_new();
12.316 +
12.317 + p->channel_id = (int) g_ascii_strtoull (row[0], NULL, 10);
12.318 +
12.319 + p->startts = gmyth_util_string_to_time_val(row[1]);
12.320 + p->endts = gmyth_util_string_to_time_val(row[2]);
12.321 +
12.322 + p->recstartts = g_new0(GTimeVal, 1);
12.323 + p->recstartts->tv_sec = p->startts->tv_sec;
12.324 + p->recstartts->tv_usec = p->startts->tv_usec;
12.325 +
12.326 + p->recendts = g_new0(GTimeVal, 1);
12.327 + p->recendts->tv_sec = p->endts->tv_sec;
12.328 + p->recendts->tv_usec = p->endts->tv_usec;
12.329 +
12.330 + p->lastmodified = g_new0(GTimeVal, 1);
12.331 + p->lastmodified->tv_sec = p->startts->tv_sec;
12.332 + p->lastmodified->tv_usec = p->startts->tv_usec;
12.333 +
12.334 +
12.335 + p->title = g_string_new(row[3]);
12.336 + p->subtitle = g_string_new(row[4]);
12.337 + p->description = g_string_new(row[5]);
12.338 + p->category = g_string_new(row[6]);
12.339 + p->chanstr = g_string_new(row[7]);
12.340 + p->chansign = g_string_new(row[8]);
12.341 + p->channame = g_string_new(row[9]);
12.342 + p->repeat = g_ascii_strtoull(row[10], NULL, 10);
12.343 + p->chancommfree = g_ascii_strtoull(row[11], NULL, 10);
12.344 + p->chanOutputFilters = g_string_new(row[12]);
12.345 + p->seriesid = g_string_new(row[13]);
12.346 + p->program_id = g_string_new(row[14]);
12.347 + p->year = g_string_new(row[15]);
12.348 + p->stars = g_ascii_strtod(row[16], NULL);
12.349 +
12.350 + if (!row[17] || !strcmp(row[17], "")) {
12.351 + p->originalAirDate = 0;
12.352 + p->hasAirDate = FALSE;
12.353 + } else {
12.354 + p->originalAirDate = gmyth_util_string_to_time_val(row[17]);
12.355 + p->hasAirDate = TRUE;
12.356 + }
12.357 +
12.358 + p->catType = g_string_new(row[18]);
12.359 + if (row[19] != NULL)
12.360 + p->recordid = g_ascii_strtoull(row[19], NULL, 10);
12.361 +
12.362 + *proglist = g_list_append(*proglist, p);
12.363 +
12.364 +#ifdef GMYTH_USE_DEBUG
12.365 + gmyth_program_info_print(p);
12.366 +#endif
12.367 + }
12.368 +
12.369 + /*
12.370 + * deallocate
12.371 + */
12.372 + mysql_free_result(res_set);
12.373 + g_string_free(querystr, TRUE);
12.374 +
12.375 + return g_list_length (*proglist);
12.376 +}
12.377 +
12.378 +gboolean
12.379 +gmyth_epg_channel_has_icon(GMythEPG * gmyth_epg,
12.380 + GMythChannelInfo * channel_info)
12.381 +{
12.382 + gboolean res = FALSE;
12.383 +
12.384 + g_return_val_if_fail(gmyth_epg != NULL, FALSE);
12.385 + g_return_val_if_fail(channel_info != NULL, FALSE);
12.386 +
12.387 + if (channel_info->channel_icon != NULL) {
12.388 + res = gmyth_util_file_exists(gmyth_epg->backend_info,
12.389 + channel_info->channel_icon->str);
12.390 + }
12.391 +
12.392 + return res;
12.393 +
12.394 +}
12.395 +
12.396 +/**
12.397 + *
12.398 + * @param data the data pointer to be filled with icon binary data. It must be freed by the calling function.
12.399 + * @return TRUE if success, FALSE if any error happens.
12.400 + */
12.401 +gboolean
12.402 +gmyth_epg_channel_get_icon(GMythEPG * gmyth_epg,
12.403 + GMythChannelInfo * channel_info, guint8 ** data,
12.404 + guint * length)
12.405 +{
12.406 + gboolean res = FALSE;
12.407 +
12.408 + g_return_val_if_fail(gmyth_epg != NULL, FALSE);
12.409 + g_return_val_if_fail(channel_info != NULL, FALSE);
12.410 +
12.411 + if (gmyth_epg_channel_has_icon(gmyth_epg, channel_info)) {
12.412 + GMythFileTransfer *transfer =
12.413 + gmyth_file_transfer_new(gmyth_epg->backend_info);
12.414 +
12.415 + GMythFileReadResult gmyth_res;
12.416 + GByteArray *icon_data;
12.417 + guint64 icon_length = 0;
12.418 +
12.419 + res = gmyth_file_transfer_open(transfer,
12.420 + channel_info->channel_icon->str);
12.421 + if (!res) {
12.422 + gmyth_debug("Channel icon could not be opened");
12.423 + return FALSE;
12.424 + }
12.425 +
12.426 + icon_length = gmyth_file_transfer_get_filesize(transfer);
12.427 + if (icon_length <= 0) {
12.428 + gmyth_debug("Channel icon file size is zero or negative");
12.429 + return FALSE;
12.430 + }
12.431 +
12.432 + icon_data = g_byte_array_new();
12.433 + gmyth_res = gmyth_file_transfer_read(transfer,
12.434 + icon_data,
12.435 + icon_length, FALSE);
12.436 + if (gmyth_res == GMYTH_FILE_READ_EOF) {
12.437 + *length = icon_length;
12.438 + *data = icon_data->data;
12.439 + g_byte_array_free(icon_data, FALSE);
12.440 + res = TRUE;
12.441 + } else {
12.442 + *length = 0;
12.443 + *data = NULL;
12.444 + g_byte_array_free(icon_data, TRUE);
12.445 + }
12.446 + }
12.447 +
12.448 + return res;
12.449 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/gmyth/gmyth/gmyth_epg.h Mon Feb 25 17:51:43 2008 +0000
13.3 @@ -0,0 +1,85 @@
13.4 +/**
13.5 + * GMyth Library
13.6 + *
13.7 + * @file gmyth/gmyth_epg.h
13.8 + *
13.9 + * @brief <p> GMythEPG class provides access to the program and channel data
13.10 + * from the Electronic Program Guide (EPG) of the Mythtv backend.
13.11 + *
13.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
13.13 + * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
13.14 + *
13.15 + * This program is free software; you can redistribute it and/or modify
13.16 + * it under the terms of the GNU Lesser General Public License as published by
13.17 + * the Free Software Foundation; either version 2 of the License, or
13.18 + * (at your option) any later version.
13.19 + *
13.20 + * This program is distributed in the hope that it will be useful,
13.21 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
13.22 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13.23 + * GNU General Public License for more details.
13.24 + *
13.25 + * You should have received a copy of the GNU Lesser General Public License
13.26 + * along with this program; if not, write to the Free Software
13.27 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
13.28 + */
13.29 +
13.30 +#ifndef GMYTH_EPG_H_
13.31 +#define GMYTH_EPG_H_
13.32 +
13.33 +#include <glib-object.h>
13.34 +
13.35 +#include "gmyth_query.h"
13.36 +#include "gmyth_common.h"
13.37 +
13.38 +G_BEGIN_DECLS
13.39 +#define GMYTH_EPG_TYPE (gmyth_epg_get_type ())
13.40 +#define GMYTH_EPG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_EPG_TYPE, GMythEPG))
13.41 +#define GMYTH_EPG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_EPG_TYPE, GMythEPGClass))
13.42 +#define IS_GMYTH_EPG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_EPG_TYPE))
13.43 +#define IS_GMYTH_EPG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_EPG_TYPE))
13.44 +#define GMYTH_EPG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_EPG_TYPE, GMythEPGClass))
13.45 +typedef struct _GMythEPG GMythEPG;
13.46 +typedef struct _GMythEPGClass GMythEPGClass;
13.47 +
13.48 +struct _GMythEPGClass {
13.49 + GObjectClass parent_class;
13.50 +
13.51 + /*
13.52 + * callbacks
13.53 + */
13.54 + /*
13.55 + * no one for now
13.56 + */
13.57 +};
13.58 +
13.59 +struct _GMythEPG {
13.60 + GObject parent;
13.61 +
13.62 + GMythQuery *sqlquery;
13.63 + GMythBackendInfo *backend_info;
13.64 +};
13.65 +
13.66 +GType gmyth_epg_get_type (void) G_GNUC_CONST;;
13.67 +GMythEPG* gmyth_epg_new (void);
13.68 +gboolean gmyth_epg_connect (GMythEPG *gmyth_epg,
13.69 + GMythBackendInfo *backend_info);
13.70 +gboolean gmyth_epg_disconnect (GMythEPG *gmyth_epg);
13.71 +gint gmyth_epg_get_channel_list (GMythEPG *gmyth_epg,
13.72 + GList **glist_ptr);
13.73 +gint gmyth_epg_get_program_list (GMythEPG *gmyth_epg,
13.74 + GList **proglist,
13.75 + gint chanNum,
13.76 + GTimeVal *starttime,
13.77 + GTimeVal *endtime);
13.78 +GMythChannelInfo*gmyth_epg_get_channel_info (GMythEPG *gmyth_epg,
13.79 + gint channel_id);
13.80 +gboolean gmyth_epg_channel_has_icon (GMythEPG *gmyth_epg,
13.81 + GMythChannelInfo *channel);
13.82 +gboolean gmyth_epg_channel_get_icon (GMythEPG *gmyth_epg,
13.83 + GMythChannelInfo *channel,
13.84 + guint8 **data,
13.85 + guint *length);
13.86 +
13.87 +G_END_DECLS
13.88 +#endif /* GMYTH_EPG_H_ */
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/gmyth/gmyth/gmyth_file.c Mon Feb 25 17:51:43 2008 +0000
14.3 @@ -0,0 +1,515 @@
14.4 +/**
14.5 + * GMyth Library
14.6 + *
14.7 + * @file gmyth/gmyth_file.c
14.8 + *
14.9 + * @brief <p> GMythFile deals with the file streaming media remote/local
14.10 + * transfering to the MythTV frontend.
14.11 + *
14.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
14.13 + * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
14.14 + *
14.15 + *
14.16 + * This program is free software; you can redistribute it and/or modify
14.17 + * it under the terms of the GNU Lesser General Public License as published by
14.18 + * the Free Software Foundation; either version 2 of the License, or
14.19 + * (at your option) any later version.
14.20 + *
14.21 + * This program is distributed in the hope that it will be useful,
14.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
14.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14.24 + * GNU General Public License for more details.
14.25 + *
14.26 + * You should have received a copy of the GNU Lesser General Public License
14.27 + * along with this program; if not, write to the Free Software
14.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14.29 + */
14.30 +
14.31 +#ifdef HAVE_CONFIG_H
14.32 +#include "config.h"
14.33 +#endif
14.34 +
14.35 +#include "gmyth_file.h"
14.36 +#include "gmyth_recorder.h"
14.37 +#include "gmyth_util.h"
14.38 +#include "gmyth_socket.h"
14.39 +#include "gmyth_stringlist.h"
14.40 +#include "gmyth_debug.h"
14.41 +#include "gmyth_uri.h"
14.42 +#include "gmyth_marshal.h"
14.43 +
14.44 +#include <unistd.h>
14.45 +#include <glib.h>
14.46 +
14.47 +#include <arpa/inet.h>
14.48 +#include <sys/types.h>
14.49 +#include <sys/socket.h>
14.50 +#include <netdb.h>
14.51 +#include <errno.h>
14.52 +#include <stdlib.h>
14.53 +#include <assert.h>
14.54 +
14.55 +#define GMYTH_FILE_GET_PRIVATE(obj) \
14.56 + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_TYPE, GMythFilePrivate))
14.57 +
14.58 +struct _GMythFilePrivate {
14.59 + gboolean disposed;
14.60 + gint64 offset;
14.61 + guint64 filesize;
14.62 +
14.63 + GMythBackendInfo *backend_info;
14.64 +
14.65 + /*
14.66 + * Myth URI structure
14.67 + */
14.68 + gchar *filename;
14.69 +
14.70 + gint file_id;
14.71 +};
14.72 +
14.73 +enum {
14.74 + PROP_GMYTH_FILE_DUMMY,
14.75 + PROP_GMYTH_FILE_FILENAME,
14.76 + PROP_GMYTH_FILE_OFFSET,
14.77 + PROP_GMYTH_FILE_FILESIZE,
14.78 + PROP_GMYTH_FILE_BACKEND_INFO,
14.79 + PROP_GMYTH_FILE_FILEID
14.80 +};
14.81 +
14.82 +static void gmyth_file_set_property(GObject * object, guint prop_id,
14.83 + const GValue * value,
14.84 + GParamSpec * pspec);
14.85 +static void gmyth_file_get_property(GObject * object, guint prop_id,
14.86 + GValue * value,
14.87 + GParamSpec * pspec);
14.88 +
14.89 +static void gmyth_file_class_init(GMythFileClass * klass);
14.90 +static void gmyth_file_init(GMythFile * object);
14.91 +static void gmyth_file_dispose(GObject * object);
14.92 +static void gmyth_file_finalize(GObject * object);
14.93 +
14.94 +G_DEFINE_TYPE(GMythFile, gmyth_file, G_TYPE_OBJECT)
14.95 + static void gmyth_file_class_init(GMythFileClass * klass)
14.96 +{
14.97 + GObjectClass *gobject_class;
14.98 + GMythFileClass *gtransfer_class;
14.99 +
14.100 + gobject_class = (GObjectClass *) klass;
14.101 + gtransfer_class = (GMythFileClass *) gobject_class;
14.102 +
14.103 + gobject_class->dispose = gmyth_file_dispose;
14.104 + gobject_class->finalize = gmyth_file_finalize;
14.105 +
14.106 + gobject_class->set_property = gmyth_file_set_property;
14.107 + gobject_class->get_property = gmyth_file_get_property;
14.108 +
14.109 + g_object_class_install_property
14.110 + (gobject_class, PROP_GMYTH_FILE_FILENAME,
14.111 + g_param_spec_string("filename", "filename",
14.112 + "The file name.",
14.113 + "",
14.114 + G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
14.115 + G_PARAM_STATIC_BLURB | G_PARAM_READABLE |
14.116 + G_PARAM_WRITABLE));
14.117 +
14.118 + g_object_class_install_property
14.119 + (gobject_class, PROP_GMYTH_FILE_OFFSET,
14.120 + g_param_spec_int64("file-offset", "file-offset",
14.121 + "The offset (position) of this file", 0,
14.122 + G_MAXINT64, 0,
14.123 + G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
14.124 + G_PARAM_STATIC_BLURB | G_PARAM_READABLE |
14.125 + G_PARAM_WRITABLE));
14.126 +
14.127 + g_object_class_install_property
14.128 + (gobject_class, PROP_GMYTH_FILE_FILESIZE,
14.129 + g_param_spec_uint64("file-size", "file-size",
14.130 + "The file size in bytes",
14.131 + 0, G_MAXUINT64, 0,
14.132 + G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
14.133 + G_PARAM_STATIC_BLURB | G_PARAM_READABLE |
14.134 + G_PARAM_WRITABLE));
14.135 +
14.136 + g_object_class_install_property
14.137 + (gobject_class, PROP_GMYTH_FILE_BACKEND_INFO,
14.138 + g_param_spec_object("backend-info", "backend-info",
14.139 + "The Backend Information about the remote server",
14.140 + G_TYPE_OBJECT,
14.141 + G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
14.142 + G_PARAM_STATIC_BLURB | G_PARAM_READABLE |
14.143 + G_PARAM_WRITABLE));
14.144 +
14.145 + g_object_class_install_property
14.146 + (gobject_class, PROP_GMYTH_FILE_FILEID,
14.147 + g_param_spec_int("file-id", "file-id",
14.148 + "The file ID", 0, G_MAXINT, 0,
14.149 + G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
14.150 + G_PARAM_STATIC_BLURB | G_PARAM_READABLE |
14.151 + G_PARAM_WRITABLE));
14.152 +
14.153 + g_type_class_add_private(gobject_class, sizeof(GMythFilePrivate));
14.154 +
14.155 +}
14.156 +
14.157 +static void
14.158 +gmyth_file_init(GMythFile * file)
14.159 +{
14.160 + g_return_if_fail(file != NULL);
14.161 +
14.162 + file->priv = GMYTH_FILE_GET_PRIVATE(file);
14.163 +}
14.164 +
14.165 +static void
14.166 +gmyth_file_dispose(GObject * object)
14.167 +{
14.168 + GMythFilePrivate *priv;
14.169 + GMythFile *file = GMYTH_FILE(object);
14.170 +
14.171 + g_return_if_fail(file != NULL);
14.172 +
14.173 + priv = GMYTH_FILE_GET_PRIVATE(file);
14.174 +
14.175 + if (priv->disposed) {
14.176 + /*
14.177 + * If dispose did already run, return.
14.178 + */
14.179 + return;
14.180 + }
14.181 +
14.182 + /*
14.183 + * Make sure dispose does not run twice.
14.184 + */
14.185 + priv->disposed = TRUE;
14.186 +
14.187 + if (priv->backend_info != NULL) {
14.188 + g_object_unref(priv->backend_info);
14.189 + priv->backend_info = NULL;
14.190 + }
14.191 +
14.192 + if (priv->filename != NULL) {
14.193 + g_free(priv->filename);
14.194 + priv->filename = NULL;
14.195 + }
14.196 +
14.197 + G_OBJECT_CLASS(gmyth_file_parent_class)->dispose(object);
14.198 +}
14.199 +
14.200 +static void
14.201 +gmyth_file_finalize(GObject * object)
14.202 +{
14.203 + g_signal_handlers_destroy(object);
14.204 +
14.205 + G_OBJECT_CLASS(gmyth_file_parent_class)->finalize(object);
14.206 +}
14.207 +
14.208 +/**
14.209 + * Creates a new instance of GMythFile.
14.210 + *
14.211 + * @param backend_info The BackendInfo instance, with all the MythTV network
14.212 + * configuration data.
14.213 + *
14.214 + * @return a new instance of the File Transfer.
14.215 + */
14.216 +GMythFile *
14.217 +gmyth_file_new(GMythBackendInfo * backend_info)
14.218 +{
14.219 + GMythFile *file = NULL;
14.220 +
14.221 + g_return_val_if_fail(backend_info != NULL, NULL);
14.222 +
14.223 + GParameter *__params = g_new0(GParameter, 1);
14.224 + GParameter *__params_it = __params;
14.225 +
14.226 + (__params_it->name =
14.227 + "backend-info", g_value_init(&__params_it->value, G_TYPE_OBJECT),
14.228 + g_value_set_object(&__params_it->value, backend_info), __params_it++);
14.229 + file =
14.230 + g_object_newv(GMYTH_FILE_TYPE, __params_it - __params, __params);
14.231 +
14.232 + return file;
14.233 +}
14.234 +
14.235 +gchar *
14.236 +gmyth_file_get_file_name(GMythFile * file)
14.237 +{
14.238 + GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(file);
14.239 +
14.240 + g_return_val_if_fail(file != NULL, NULL);
14.241 +
14.242 + return priv->filename;
14.243 +}
14.244 +
14.245 +void
14.246 +gmyth_file_set_file_name(GMythFile * file, const gchar * filename)
14.247 +{
14.248 + g_return_if_fail(file != NULL);
14.249 + g_return_if_fail(filename != NULL);
14.250 +
14.251 + gchar *__temp2 = NULL;
14.252 + const gchar *__temp1 = NULL;
14.253 +
14.254 + file->priv->filename = (__temp2 =
14.255 + (__temp1 =
14.256 + filename,
14.257 + (__temp1 == NULL ? NULL : g_strdup(__temp1))),
14.258 + (file->priv->filename ==
14.259 + NULL ? NULL : (file->priv->filename =
14.260 + (g_free(file->priv->filename),
14.261 + NULL))), __temp2);
14.262 +}
14.263 +
14.264 +/**
14.265 + * Creates a new instance of GMythFile.
14.266 + *
14.267 + * @param uri_str The URI poiting to the MythTV backend server.
14.268 + *
14.269 + * @return a new instance of the File Transfer.
14.270 + */
14.271 +GMythFile *
14.272 +gmyth_file_new_with_uri(const gchar * uri_str)
14.273 +{
14.274 + GMythFile *file = GMYTH_FILE(g_object_new(GMYTH_FILE_TYPE, NULL));
14.275 + GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(file);
14.276 +
14.277 + priv->backend_info = gmyth_backend_info_new_with_uri(uri_str);
14.278 + return file;
14.279 +}
14.280 +
14.281 +/**
14.282 + * Open a File Transfer connection in order to get a remote file.
14.283 + *
14.284 + * @param file The actual File Transfer instance.
14.285 + * @param filename The file name of the remote file to be transfered to the client.
14.286 + *
14.287 + * @return <code>true</code>, if the connection opening had been done successfully.
14.288 + */
14.289 +gboolean
14.290 +gmyth_file_setup(GMythFile * file, const gchar * filename)
14.291 +{
14.292 + gboolean ret = TRUE;
14.293 + GMythFilePrivate *priv;
14.294 +
14.295 + g_return_val_if_fail(file != NULL, FALSE);
14.296 + g_return_val_if_fail(filename != NULL && strlen(filename) > 0, FALSE);
14.297 +
14.298 + priv = GMYTH_FILE_GET_PRIVATE(file);
14.299 +
14.300 + if (priv->filename != NULL) {
14.301 + gmyth_file_close(file);
14.302 + }
14.303 +
14.304 + priv->filename = g_strdup(filename);
14.305 +
14.306 + return ret;
14.307 +}
14.308 +
14.309 +/**
14.310 + * Closes a remote File Transfer connection.
14.311 + *
14.312 + * @param file The actual File Transfer instance.
14.313 + */
14.314 +void
14.315 +gmyth_file_close(GMythFile * file)
14.316 +{
14.317 + GMythFilePrivate *priv;
14.318 +
14.319 + priv = GMYTH_FILE_GET_PRIVATE(file);
14.320 +
14.321 + if (priv->filename) {
14.322 + g_free(priv->filename);
14.323 + priv->filename = NULL;
14.324 + }
14.325 +
14.326 +}
14.327 +
14.328 +/**
14.329 + * Gets the actual file size of the binary content.
14.330 + *
14.331 + * @param file The actual File Transfer instance.
14.332 + *
14.333 + * @return The actual file size in bytes.
14.334 + */
14.335 +guint64
14.336 +gmyth_file_get_filesize(GMythFile * file)
14.337 +{
14.338 + GMythFilePrivate *priv;
14.339 +
14.340 + g_return_val_if_fail(file != NULL, 0);
14.341 +
14.342 + priv = GMYTH_FILE_GET_PRIVATE(file);
14.343 + return priv->filesize;
14.344 +}
14.345 +
14.346 +/**
14.347 + * Sets the actual file size.
14.348 + *
14.349 + * @param file The actual File Transfer instance.
14.350 + * @param filesize The actual File Transfer size, in bytes.
14.351 + */
14.352 +void
14.353 +gmyth_file_set_filesize(GMythFile * file, guint64 filesize)
14.354 +{
14.355 + GMythFilePrivate *priv;
14.356 +
14.357 + priv = GMYTH_FILE_GET_PRIVATE(file);
14.358 +
14.359 + priv->filesize = filesize;
14.360 +}
14.361 +
14.362 +/**
14.363 + * Gets the actual offset of the binary content.
14.364 + *
14.365 + * @param file The actual File Transfer instance.
14.366 + *
14.367 + * @return The actual file offset in bytes.
14.368 + */
14.369 +gint64
14.370 +gmyth_file_get_offset(GMythFile * file)
14.371 +{
14.372 + g_return_val_if_fail(file != NULL, 0);
14.373 +
14.374 + return file->priv->offset;
14.375 +}
14.376 +
14.377 +/**
14.378 + * Sets the actual file offset.
14.379 + *
14.380 + * @param file The actual File instance.
14.381 + * @param filesize The actual File offset, in bytes.
14.382 + */
14.383 +void
14.384 +gmyth_file_set_offset(GMythFile * file, gint64 offset)
14.385 +{
14.386 + GMythFilePrivate *priv;
14.387 +
14.388 + priv = GMYTH_FILE_GET_PRIVATE(file);
14.389 +
14.390 + priv->offset = offset;
14.391 +}
14.392 +
14.393 +gchar *
14.394 +gmyth_file_get_uri(GMythFile * file)
14.395 +{
14.396 + GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(file);
14.397 + gchar *uri = NULL;
14.398 +
14.399 + g_return_val_if_fail(file != NULL, NULL);
14.400 +
14.401 + if (g_strstr_len(priv->filename, strlen(priv->filename), "://") !=
14.402 + NULL)
14.403 + uri = g_strdup(priv->filename);
14.404 + else
14.405 + uri =
14.406 + g_strdup_printf("myth://%s:%d/%s",
14.407 + gmyth_backend_info_get_hostname(priv->
14.408 + backend_info),
14.409 + gmyth_backend_info_get_port(priv->
14.410 + backend_info),
14.411 + priv->filename);
14.412 +
14.413 + return uri;
14.414 +}
14.415 +
14.416 +static void
14.417 +gmyth_file_set_property(GObject * object, guint prop_id,
14.418 + const GValue * value, GParamSpec * pspec)
14.419 +{
14.420 + GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(GMYTH_FILE(object));
14.421 +
14.422 + switch (prop_id) {
14.423 + case PROP_GMYTH_FILE_FILENAME:
14.424 + {
14.425 + if (!g_value_get_string(value)) {
14.426 + break;
14.427 + }
14.428 +
14.429 + if (priv->filename != NULL) {
14.430 + g_free(priv->filename);
14.431 + priv->filename = NULL;
14.432 + }
14.433 +
14.434 + priv->filename = g_value_dup_string(value);
14.435 + gmyth_debug("Changed the filename to [%s]!", priv->filename);
14.436 + break;
14.437 + }
14.438 + case PROP_GMYTH_FILE_OFFSET:
14.439 + {
14.440 + priv->offset = g_value_get_int64(value);
14.441 + break;
14.442 + }
14.443 + case PROP_GMYTH_FILE_FILESIZE:
14.444 + {
14.445 + priv->filesize = g_value_get_uint64(value);
14.446 + break;
14.447 + }
14.448 + case PROP_GMYTH_FILE_BACKEND_INFO:
14.449 + {
14.450 + if (!g_value_get_object(value)) {
14.451 + break;
14.452 + }
14.453 +
14.454 + if (priv->backend_info != NULL) {
14.455 + g_object_unref(priv->backend_info);
14.456 + priv->backend_info = NULL;
14.457 + }
14.458 +
14.459 + priv->backend_info = g_value_get_object(value);
14.460 + gmyth_debug("Changed the backend info to [%s]!",
14.461 + gmyth_backend_info_get_hostname(priv->
14.462 + backend_info));
14.463 + break;
14.464 + }
14.465 + case PROP_GMYTH_FILE_FILEID:
14.466 + {
14.467 + priv->file_id = g_value_get_int(value);
14.468 + break;
14.469 + }
14.470 +
14.471 + default:
14.472 + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
14.473 + break;
14.474 + }
14.475 +
14.476 +}
14.477 +
14.478 +static void
14.479 +gmyth_file_get_property(GObject * object, guint prop_id,
14.480 + GValue * value, GParamSpec * pspec)
14.481 +{
14.482 + GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(GMYTH_FILE(object));
14.483 +
14.484 + switch (prop_id) {
14.485 + case PROP_GMYTH_FILE_FILENAME:
14.486 + {
14.487 + gmyth_debug("Got the filename to [%s]!", priv->filename);
14.488 + g_value_set_string(value, priv->filename);
14.489 + break;
14.490 + }
14.491 + case PROP_GMYTH_FILE_OFFSET:
14.492 + {
14.493 + g_value_set_int64(value, priv->offset);
14.494 + break;
14.495 + }
14.496 + case PROP_GMYTH_FILE_FILESIZE:
14.497 + {
14.498 + g_value_set_uint64(value, priv->filesize);
14.499 + break;
14.500 + }
14.501 + case PROP_GMYTH_FILE_BACKEND_INFO:
14.502 + {
14.503 + g_value_set_object(value, priv->backend_info);
14.504 + break;
14.505 + }
14.506 + case PROP_GMYTH_FILE_FILEID:
14.507 + {
14.508 + g_value_set_int(value, priv->file_id);
14.509 + break;
14.510 + }
14.511 + default:
14.512 + {
14.513 + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
14.514 + break;
14.515 + }
14.516 + }
14.517 +
14.518 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/gmyth/gmyth/gmyth_file.h Mon Feb 25 17:51:43 2008 +0000
15.3 @@ -0,0 +1,90 @@
15.4 +/**
15.5 + * GMyth Library
15.6 + *
15.7 + * @file gmyth/gmyth_file.h
15.8 + *
15.9 + * @brief <p> GMythFile is the parent GMObject that deals with the file streaming
15.10 + * media remote/local transfering to the MythTV frontend.
15.11 + *
15.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
15.13 + * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
15.14 + *
15.15 + *
15.16 + * This program is free software; you can redistribute it and/or modify
15.17 + * it under the terms of the GNU Lesser General Public License as published by
15.18 + * the Free Software Foundation; either version 2 of the License, or
15.19 + * (at your option) any later version.
15.20 + *
15.21 + * This program is distributed in the hope that it will be useful,
15.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
15.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15.24 + * GNU General Public License for more details.
15.25 + *
15.26 + * You should have received a copy of the GNU Lesser General Public License
15.27 + * along with this program; if not, write to the Free Software
15.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15.29 + */
15.30 +
15.31 +#ifndef __GMYTH_FILE_H__
15.32 +#define __GMYTH_FILE_H__
15.33 +
15.34 +#include <glib-object.h>
15.35 +#include <glib.h>
15.36 +
15.37 +#include "gmyth_uri.h"
15.38 +#include "gmyth_backendinfo.h"
15.39 +
15.40 +#include <stdio.h>
15.41 +#include <stdlib.h>
15.42 +#include <string.h>
15.43 +#include <netdb.h>
15.44 +#include <sys/socket.h>
15.45 +#include <unistd.h>
15.46 +
15.47 +G_BEGIN_DECLS
15.48 +#define GMYTH_FILE_TYPE (gmyth_file_get_type ())
15.49 +#define GMYTH_FILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_FILE_TYPE, GMythFile))
15.50 +#define GMYTH_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TYPE, GMythFileClass))
15.51 +#define IS_GMYTH_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_FILE_TYPE))
15.52 +#define IS_GMYTH_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TYPE))
15.53 +#define GMYTH_FILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_FILE_TYPE, GMythFileClass))
15.54 +
15.55 +typedef enum {
15.56 + GMYTH_FILE_READ_OK = 0,
15.57 + GMYTH_FILE_READ_NEXT_PROG_CHAIN = 1,
15.58 + GMYTH_FILE_READ_ERROR = 2,
15.59 + GMYTH_FILE_READ_EOF = 3
15.60 +} GMythFileReadResult;
15.61 +
15.62 +typedef struct _GMythFile GMythFile;
15.63 +typedef struct _GMythFileClass GMythFileClass;
15.64 +typedef struct _GMythFilePrivate GMythFilePrivate;
15.65 +
15.66 +struct _GMythFile {
15.67 + GObject parent;
15.68 + GMythFilePrivate *priv;
15.69 +};
15.70 +
15.71 +struct _GMythFileClass {
15.72 + GObjectClass parent_class;
15.73 +};
15.74 +
15.75 +GType gmyth_file_get_type (void);
15.76 +GMythFile *gmyth_file_new (GMythBackendInfo *backend_info);
15.77 +gchar *gmyth_file_get_file_name (GMythFile *file);
15.78 +void gmyth_file_set_file_name (GMythFile *file,
15.79 + const gchar *filename);
15.80 +gboolean gmyth_file_setup (GMythFile *file,
15.81 + const gchar *filename);
15.82 +void gmyth_file_close (GMythFile *file);
15.83 +gboolean gmyth_file_is_open (GMythFile *file);
15.84 +guint64 gmyth_file_get_filesize (GMythFile *file);
15.85 +void gmyth_file_set_filesize (GMythFile *file,
15.86 + guint64 filesize);
15.87 +gint64 gmyth_file_get_offset (GMythFile *file);
15.88 +void gmyth_file_set_offset (GMythFile *file,
15.89 + gint64 offset);
15.90 +gchar *gmyth_file_get_uri (GMythFile *file);
15.91 +
15.92 +G_END_DECLS
15.93 +#endif /* __GMYTH_FILE_H__ */
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/gmyth/gmyth/gmyth_file_local.c Mon Feb 25 17:51:43 2008 +0000
16.3 @@ -0,0 +1,464 @@
16.4 +/**
16.5 + * GMyth Library
16.6 + *
16.7 + * @file_local gmyth/gmyth_file_local.c
16.8 + *
16.9 + * @brief <p> GMythFileLocal deals with the file_local streaming media remote/local
16.10 + * transfering to the MythTV frontend.
16.11 + *
16.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
16.13 + * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
16.14 + *
16.15 + *
16.16 + * This program is free software; you can redistribute it and/or modify
16.17 + * it under the terms of the GNU Lesser General Public License as published by
16.18 + * the Free Software Foundation; either version 2 of the License, or
16.19 + * (at your option) any later version.
16.20 + *
16.21 + * This program is distributed in the hope that it will be useful,
16.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
16.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16.24 + * GNU General Public License for more details.
16.25 + *
16.26 + * You should have received a copy of the GNU Lesser General Public License
16.27 + * along with this program; if not, write to the Free Software
16.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16.29 + */
16.30 +
16.31 +#ifdef HAVE_CONFIG_H
16.32 +#include "config.h"
16.33 +#endif
16.34 +
16.35 +#include "gmyth_file_local.h"
16.36 +#include "gmyth_recorder.h"
16.37 +#include "gmyth_util.h"
16.38 +#include "gmyth_socket.h"
16.39 +#include "gmyth_stringlist.h"
16.40 +#include "gmyth_debug.h"
16.41 +#include "gmyth_uri.h"
16.42 +#include "gmyth_marshal.h"
16.43 +
16.44 +#include <unistd.h>
16.45 +#include <glib.h>
16.46 +
16.47 +#include <arpa/inet.h>
16.48 +#include <sys/types.h>
16.49 +#include <sys/socket.h>
16.50 +#include <netdb.h>
16.51 +#include <errno.h>
16.52 +#include <stdlib.h>
16.53 +#include <assert.h>
16.54 +
16.55 +#define GMYTH_FILE_LOCAL_GET_PRIVATE(obj) \
16.56 + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_LOCAL_TYPE, GMythFileLocalPrivate))
16.57 +
16.58 +struct _GMythFileLocalPrivate {
16.59 +
16.60 + gboolean disposed;
16.61 +
16.62 + GMutex *mutex;
16.63 +
16.64 + gint fd;
16.65 +
16.66 + GIOChannel *file_io;
16.67 +
16.68 +};
16.69 +
16.70 +static void gmyth_file_local_class_init(GMythFileLocalClass * klass);
16.71 +static void gmyth_file_local_init(GMythFileLocal * object);
16.72 +static void gmyth_file_local_dispose(GObject * object);
16.73 +static void gmyth_file_local_finalize(GObject * object);
16.74 +
16.75 +static gboolean _control_acquire_context(GMythFileLocal * file_local,
16.76 + gboolean do_wait);
16.77 +
16.78 +static gboolean _control_release_context(GMythFileLocal * file_local);
16.79 +
16.80 +G_DEFINE_TYPE(GMythFileLocal, gmyth_file_local, GMYTH_FILE_TYPE)
16.81 + static void gmyth_file_local_class_init(GMythFileLocalClass *
16.82 + klass)
16.83 +{
16.84 + GObjectClass *gobject_class;
16.85 + GMythFileLocalClass *gtransfer_class;
16.86 +
16.87 + gobject_class = (GObjectClass *) klass;
16.88 + gtransfer_class = (GMythFileLocalClass *) gobject_class;
16.89 +
16.90 + gobject_class->dispose = gmyth_file_local_dispose;
16.91 + gobject_class->finalize = gmyth_file_local_finalize;
16.92 +
16.93 + g_type_class_add_private(gobject_class, sizeof(GMythFileLocalPrivate));
16.94 +
16.95 +}
16.96 +
16.97 +static void
16.98 +gmyth_file_local_init(GMythFileLocal * file_local)
16.99 +{
16.100 + GMythFileLocalPrivate *priv;
16.101 +
16.102 + g_return_if_fail(file_local != NULL);
16.103 +
16.104 + priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
16.105 +
16.106 + priv->mutex = g_mutex_new();
16.107 +}
16.108 +
16.109 +static void
16.110 +gmyth_file_local_dispose(GObject * object)
16.111 +{
16.112 + GMythFileLocalPrivate *priv;
16.113 + GMythFileLocal *file_local = GMYTH_FILE_LOCAL(object);
16.114 +
16.115 + g_return_if_fail(file_local != NULL);
16.116 +
16.117 + priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
16.118 +
16.119 + if (priv->disposed) {
16.120 + /*
16.121 + * If dispose did already run, return.
16.122 + */
16.123 + return;
16.124 + }
16.125 +
16.126 + /*
16.127 + * Make sure dispose does not run twice.
16.128 + */
16.129 + priv->disposed = TRUE;
16.130 +
16.131 + if (priv->mutex != NULL) {
16.132 + g_mutex_free(priv->mutex);
16.133 + priv->mutex = NULL;
16.134 + }
16.135 +
16.136 + if (priv->file_io != NULL) {
16.137 + g_io_channel_unref(priv->file_io);
16.138 + priv->file_io = NULL;
16.139 + }
16.140 +
16.141 + G_OBJECT_CLASS(gmyth_file_local_parent_class)->dispose(object);
16.142 +}
16.143 +
16.144 +static void
16.145 +gmyth_file_local_finalize(GObject * object)
16.146 +{
16.147 + g_signal_handlers_destroy(object);
16.148 +
16.149 + G_OBJECT_CLASS(gmyth_file_local_parent_class)->finalize(object);
16.150 +}
16.151 +
16.152 +/**
16.153 + * Creates a new instance of GMythFileLocal.
16.154 + *
16.155 + * @param backend_info The BackendInfo instance, with all the MythTV network
16.156 + * configuration data.
16.157 + *
16.158 + * @return a new instance of the File Transfer.
16.159 + */
16.160 +GMythFileLocal *
16.161 +gmyth_file_local_new(GMythBackendInfo * backend_info)
16.162 +{
16.163 + GMythFileLocal *file_local =
16.164 + GMYTH_FILE_LOCAL(g_object_new(GMYTH_FILE_LOCAL_TYPE, NULL));
16.165 +
16.166 + g_object_set(GMYTH_FILE(file_local), "backend-info", &backend_info,
16.167 + NULL);
16.168 +
16.169 + return file_local;
16.170 +}
16.171 +
16.172 +/**
16.173 + * Creates a new instance of GMythFileLocal.
16.174 + *
16.175 + * @param uri_str The URI poiting to the MythTV backend server.
16.176 + *
16.177 + * @return a new instance of the File Transfer.
16.178 + */
16.179 +GMythFileLocal *
16.180 +gmyth_file_local_new_with_uri(const gchar * uri_str)
16.181 +{
16.182 + GMythFileLocal *file_local =
16.183 + GMYTH_FILE_LOCAL(g_object_new(GMYTH_FILE_LOCAL_TYPE, NULL));
16.184 + GMythURI *uri = gmyth_uri_new_with_value(uri_str);
16.185 +
16.186 + gmyth_debug("GMythURI path segment = %s", gmyth_uri_get_path(uri));
16.187 +
16.188 + g_object_set(GMYTH_FILE(file_local),
16.189 + "backend-info", gmyth_backend_info_new_with_uri(uri_str),
16.190 + "filename", g_strdup(gmyth_uri_get_path(uri)), NULL);
16.191 +
16.192 + g_object_unref(uri);
16.193 +
16.194 + return file_local;
16.195 +}
16.196 +
16.197 +gchar *
16.198 +gmyth_file_local_get_file_name(GMythFileLocal * file_local)
16.199 +{
16.200 + return gmyth_file_get_file_name(GMYTH_FILE(file_local));
16.201 +}
16.202 +
16.203 +void
16.204 +gmyth_file_local_set_file_name(GMythFileLocal * file_local,
16.205 + const gchar * filename)
16.206 +{
16.207 + gmyth_file_set_file_name(GMYTH_FILE(file_local), filename);
16.208 +}
16.209 +
16.210 +/**
16.211 + * Open a File in order to get a local file.
16.212 + *
16.213 + * @param file_local The actual File Transfer instance.
16.214 + *
16.215 + * @return <code>true</code>, if the connection opening had been done successfully.
16.216 + */
16.217 +gboolean
16.218 +gmyth_file_local_open(GMythFileLocal * file_local)
16.219 +{
16.220 + gboolean ret = TRUE;
16.221 + GMythFileLocalPrivate *priv;
16.222 + gchar *file_name_uri = NULL;
16.223 +
16.224 + g_return_val_if_fail(file_local != NULL, FALSE);
16.225 +
16.226 + priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
16.227 + file_name_uri = gmyth_file_local_get_file_name(file_local);
16.228 +
16.229 + if (file_name_uri != NULL) {
16.230 + priv->file_io =
16.231 + g_io_channel_new_file(g_strdup(file_name_uri), "r+", NULL);
16.232 + g_free(file_name_uri);
16.233 + }
16.234 +
16.235 + if (priv->file_io < 0)
16.236 + ret = FALSE;
16.237 +
16.238 + return ret;
16.239 +}
16.240 +
16.241 +/**
16.242 + * Closes a remote File Transfer connection.
16.243 + *
16.244 + * @param file_local The actual File Transfer instance.
16.245 + */
16.246 +void
16.247 +gmyth_file_local_close(GMythFileLocal * file_local)
16.248 +{
16.249 + g_return_if_fail(file_local != NULL);
16.250 +}
16.251 +
16.252 +/**
16.253 + * Acquire access to a local file read/write pointer.
16.254 + *
16.255 + * @param transfer The actual File Local instance.
16.256 + * @param do_wait Waits or not on a GCond, when trying to read from the remote socket.
16.257 + *
16.258 + * @return <code>true</code>, if the acquire had been got.
16.259 + */
16.260 +static gboolean
16.261 +_control_acquire_context(GMythFileLocal * file_local, gboolean do_wait)
16.262 +{
16.263 + gboolean ret = TRUE;
16.264 + GMythFileLocalPrivate *priv;
16.265 +
16.266 + g_return_val_if_fail(file_local != NULL, FALSE);
16.267 + priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
16.268 +
16.269 + g_mutex_lock(priv->mutex);
16.270 + return ret;
16.271 +}
16.272 +
16.273 +/**
16.274 + * Release access to a local file read/write pointer.
16.275 + *
16.276 + * @param transfer The actual File Transfer instance.
16.277 + *
16.278 + * @return <code>true</code>, if the local file read/write permissions had been releaseds.
16.279 + */
16.280 +static gboolean
16.281 +_control_release_context(GMythFileLocal * file_local)
16.282 +{
16.283 + gboolean ret = TRUE;
16.284 + GMythFileLocalPrivate *priv;
16.285 +
16.286 + g_return_val_if_fail(file_local != NULL, FALSE);
16.287 + priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
16.288 +
16.289 + g_mutex_unlock(priv->mutex);
16.290 +
16.291 + return ret;
16.292 +}
16.293 +
16.294 +/**
16.295 + * Reads a block from a remote file.
16.296 + *
16.297 + * @param transfer The actual File Transfer instance.
16.298 + * @param data A GByteArray instance, where all the binary data representing
16.299 + * the remote file will be stored.
16.300 + * @param size The block size, in bytes, to be requested from a remote file.
16.301 + * @param read_unlimited Tells the backend to read indefinitely (LiveTV), or only
16.302 + * gets the actual size
16.303 + *
16.304 + * @return The actual block size (in bytes) returned by REQUEST_BLOCK message,
16.305 + * or the error code.
16.306 + */
16.307 +GMythFileReadResult
16.308 +gmyth_file_local_read(GMythFileLocal * file_local, GByteArray * data,
16.309 + gint size, gboolean read_unlimited)
16.310 +{
16.311 + gsize bytes_read = 0;
16.312 + gint64 total_read = 0;
16.313 + GMythFileReadResult retval = GMYTH_FILE_READ_OK;
16.314 + GMythFileLocalPrivate *priv;
16.315 +
16.316 + GError *error = NULL;
16.317 +
16.318 + GIOCondition io_cond;
16.319 + GIOStatus io_status = G_IO_STATUS_NORMAL;
16.320 +
16.321 + g_return_val_if_fail(file_local != NULL, FALSE);
16.322 + g_return_val_if_fail(data != NULL, GMYTH_FILE_READ_ERROR);
16.323 +
16.324 + priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
16.325 +
16.326 + io_status = g_io_channel_set_encoding(priv->file_io, NULL, &error);
16.327 + if (io_status == G_IO_STATUS_NORMAL)
16.328 + gmyth_debug("Setting encoding to binary file data stream.\n");
16.329 +
16.330 + io_cond = g_io_channel_get_buffer_condition(priv->file_io);
16.331 +
16.332 + _control_acquire_context(file_local, TRUE);
16.333 +
16.334 + if (size > 0) {
16.335 + gchar *data_buffer = g_new0(gchar, size);
16.336 +
16.337 + io_status = g_io_channel_read_chars(priv->file_io,
16.338 + data_buffer, (gsize) size,
16.339 + &bytes_read, &error);
16.340 +
16.341 + if (io_status != G_IO_STATUS_NORMAL) {
16.342 + gmyth_debug("Error on io_channel");
16.343 + g_free(data_buffer);
16.344 + retval = GMYTH_FILE_READ_ERROR;
16.345 + goto error;
16.346 + }
16.347 +
16.348 + /*
16.349 + * append new data to the increasing byte array
16.350 + */
16.351 + data =
16.352 + g_byte_array_append(data, (const guint8 *) data_buffer,
16.353 + bytes_read);
16.354 + total_read += bytes_read;
16.355 +
16.356 + if (!read_unlimited
16.357 + && (gmyth_file_local_get_filesize(file_local) > 0)
16.358 + && (gmyth_file_local_get_offset(file_local) ==
16.359 + gmyth_file_local_get_filesize(file_local))) {
16.360 + retval = GMYTH_FILE_READ_EOF;
16.361 + goto error;
16.362 + }
16.363 +
16.364 + g_free(data_buffer);
16.365 + } else {
16.366 + retval = GMYTH_FILE_READ_ERROR;
16.367 + }
16.368 +
16.369 + error:
16.370 + _control_release_context(file_local);
16.371 +
16.372 + if (error != NULL) {
16.373 + gmyth_debug("Cleaning-up ERROR: [msg = %s, code = %d]\n",
16.374 + error->message, error->code);
16.375 + g_error_free(error);
16.376 + }
16.377 +
16.378 + if (total_read > 0)
16.379 + gmyth_file_local_set_offset(file_local,
16.380 + (gmyth_file_local_get_offset
16.381 + (file_local) + total_read));
16.382 +
16.383 + return retval;
16.384 +}
16.385 +
16.386 +gint64
16.387 +gmyth_file_local_seek(GMythFileLocal * file_local, gint64 pos,
16.388 + GSeekType whence)
16.389 +{
16.390 + GMythFileLocalPrivate *priv;
16.391 +
16.392 + GError *error;
16.393 +
16.394 + GIOStatus io_status = G_IO_STATUS_NORMAL;
16.395 +
16.396 + g_return_val_if_fail(file_local != NULL, -1);
16.397 +
16.398 + priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
16.399 +
16.400 + io_status =
16.401 + g_io_channel_seek_position(priv->file_io, pos, whence, &error);
16.402 +
16.403 + if (io_status == G_IO_STATUS_ERROR)
16.404 + pos = -1;
16.405 +
16.406 + return pos;
16.407 +
16.408 +}
16.409 +
16.410 +/**
16.411 + * Gets the actual file_local size of the binary content.
16.412 + *
16.413 + * @param file_local The actual File Transfer instance.
16.414 + *
16.415 + * @return The actual file_local size in bytes.
16.416 + */
16.417 +guint64
16.418 +gmyth_file_local_get_filesize(GMythFileLocal * file_local)
16.419 +{
16.420 + g_return_val_if_fail(file_local != NULL, 0);
16.421 +
16.422 + return gmyth_file_get_filesize(GMYTH_FILE(file_local));
16.423 +}
16.424 +
16.425 +/**
16.426 + * Sets the actual file_local size.
16.427 + *
16.428 + * @param file_local The actual File Transfer instance.
16.429 + * @param filesize The actual File Transfer size, in bytes.
16.430 + */
16.431 +void
16.432 +gmyth_file_local_set_filesize(GMythFileLocal * file_local,
16.433 + guint64 filesize)
16.434 +{
16.435 + g_return_if_fail(file_local != NULL);
16.436 +
16.437 + gmyth_file_set_filesize(GMYTH_FILE(file_local), filesize);
16.438 +}
16.439 +
16.440 +/**
16.441 + * Gets the actual file offset of the binary content.
16.442 + *
16.443 + * @param file_local The actual File Transfer instance.
16.444 + *
16.445 + * @return The actual file offset in bytes.
16.446 + */
16.447 +gint64
16.448 +gmyth_file_local_get_offset(GMythFileLocal * file_local)
16.449 +{
16.450 + g_return_val_if_fail(file_local != NULL, 0);
16.451 +
16.452 + return gmyth_file_get_offset(GMYTH_FILE(file_local));
16.453 +}
16.454 +
16.455 +/**
16.456 + * Sets the actual file offset.
16.457 + *
16.458 + * @param file_local The actual File Local instance.
16.459 + * @param offset The actual File Local offset, in bytes.
16.460 + */
16.461 +void
16.462 +gmyth_file_local_set_offset(GMythFileLocal * file_local, gint64 offset)
16.463 +{
16.464 + g_return_if_fail(file_local != NULL);
16.465 +
16.466 + gmyth_file_set_offset(GMYTH_FILE(file_local), offset);
16.467 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/gmyth/gmyth/gmyth_file_local.h Mon Feb 25 17:51:43 2008 +0000
17.3 @@ -0,0 +1,93 @@
17.4 +/**
17.5 + * GMyth Library
17.6 + *
17.7 + * @file gmyth/gmyth_file_local_local.h
17.8 + *
17.9 + * @brief <p> GMythFileLocal is the parent GMythFile that deals with the file streaming
17.10 + * media local transfering from the MythTV backend.
17.11 + *
17.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
17.13 + * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
17.14 + *
17.15 + *
17.16 + * This program is free software; you can redistribute it and/or modify
17.17 + * it under the terms of the GNU Lesser General Public License as published by
17.18 + * the Free Software Foundation; either version 2 of the License, or
17.19 + * (at your option) any later version.
17.20 + *
17.21 + * This program is distributed in the hope that it will be useful,
17.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17.24 + * GNU General Public License for more details.
17.25 + *
17.26 + * You should have received a copy of the GNU Lesser General Public License
17.27 + * along with this program; if not, write to the Free Software
17.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17.29 + */
17.30 +
17.31 +#ifndef __GMYTH_FILE_LOCAL_H__
17.32 +#define __GMYTH_FILE_LOCAL_H__
17.33 +
17.34 +#include <glib-object.h>
17.35 +#include <glib.h>
17.36 +
17.37 +#include "gmyth_file.h"
17.38 +#include "gmyth_uri.h"
17.39 +#include "gmyth_backendinfo.h"
17.40 +
17.41 +#include <stdio.h>
17.42 +#include <stdlib.h>
17.43 +#include <string.h>
17.44 +#include <netdb.h>
17.45 +#include <sys/socket.h>
17.46 +#include <unistd.h>
17.47 +
17.48 +G_BEGIN_DECLS
17.49 +#define GMYTH_FILE_LOCAL_TYPE (gmyth_file_local_get_type ())
17.50 +#define GMYTH_FILE_LOCAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_FILE_LOCAL_TYPE, GMythFileLocal))
17.51 +#define GMYTH_FILE_LOCAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_LOCAL_TYPE, GMythFileLocalClass))
17.52 +#define IS_GMYTH_FILE_LOCAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_FILE_LOCAL_TYPE))
17.53 +#define IS_GMYTH_FILE_LOCAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_LOCAL_TYPE))
17.54 +#define GMYTH_FILE_LOCAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_FILE_LOCAL_TYPE, GMythFileLocalClass))
17.55 +typedef struct _GMythFileLocal GMythFileLocal;
17.56 +typedef struct _GMythFileLocalClass GMythFileLocalClass;
17.57 +typedef struct _GMythFileLocalPrivate GMythFileLocalPrivate;
17.58 +
17.59 +struct _GMythFileLocal {
17.60 + GMythFile parent;
17.61 +};
17.62 +
17.63 +struct _GMythFileLocalClass {
17.64 + GMythFileClass parent_class;
17.65 +};
17.66 +
17.67 +
17.68 +GType gmyth_file_local_get_type(void);
17.69 +GMythFileLocal *gmyth_file_local_new(GMythBackendInfo * backend_info);
17.70 +GMythFileLocal *gmyth_file_local_new_with_uri(const gchar * uri);
17.71 +gchar *gmyth_file_local_get_file_name(GMythFileLocal *
17.72 + file_local);
17.73 +void gmyth_file_local_set_file_name(GMythFileLocal * file_local,
17.74 + const gchar * filename);
17.75 +gboolean gmyth_file_local_open(GMythFileLocal * file_local);
17.76 +void gmyth_file_local_close(GMythFileLocal * file_local);
17.77 +gboolean gmyth_file_local_is_open(GMythFileLocal * file_local);
17.78 +
17.79 +GMythFileReadResult
17.80 +gmyth_file_local_read(GMythFileLocal * file_local,
17.81 + GByteArray * data, gint size,
17.82 + gboolean read_unlimited);
17.83 +
17.84 +gint64 gmyth_file_local_seek(GMythFileLocal * file_local,
17.85 + gint64 pos, GSeekType whence);
17.86 +
17.87 +guint64 gmyth_file_local_get_filesize(GMythFileLocal * file_local);
17.88 +void gmyth_file_local_set_filesize(GMythFileLocal * file,
17.89 + guint64 filesize);
17.90 +
17.91 +gint64 gmyth_file_local_get_offset(GMythFileLocal * file_local);
17.92 +void gmyth_file_local_set_offset(GMythFileLocal * file_local,
17.93 + gint64 offset);
17.94 +
17.95 +G_END_DECLS
17.96 +#endif /* __GMYTH_FILE_LOCAL_H__ */
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/gmyth/gmyth/gmyth_file_transfer.c Mon Feb 25 17:51:43 2008 +0000
18.3 @@ -0,0 +1,1014 @@
18.4 +/**
18.5 + * GMyth Library
18.6 + *
18.7 + * @file gmyth/gmyth_file_transfer.c
18.8 + *
18.9 + * @brief <p> GMythFileTransfer deals with the file streaming media remote/local
18.10 + * transfering to the MythTV frontend.
18.11 + *
18.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
18.13 + * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
18.14 + *
18.15 + *
18.16 + * This program is free software; you can redistribute it and/or modify
18.17 + * it under the terms of the GNU Lesser General Public License as published by
18.18 + * the Free Software Foundation; either version 2 of the License, or
18.19 + * (at your option) any later version.
18.20 + *
18.21 + * This program is distributed in the hope that it will be useful,
18.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
18.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18.24 + * GNU General Public License for more details.
18.25 + *
18.26 + * You should have received a copy of the GNU Lesser General Public License
18.27 + * along with this program; if not, write to the Free Software
18.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18.29 + *
18.30 + * GStreamer MythTV plug-in properties:
18.31 + * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv]
18.32 + * - path (qurl - remote file to be opened)
18.33 + * - port number *
18.34 + */
18.35 +
18.36 +#ifdef HAVE_CONFIG_H
18.37 +#include "config.h"
18.38 +#endif
18.39 +
18.40 +#include "gmyth_file_transfer.h"
18.41 +#include "gmyth_recorder.h"
18.42 +#include "gmyth_util.h"
18.43 +#include "gmyth_socket.h"
18.44 +#include "gmyth_stringlist.h"
18.45 +#include "gmyth_debug.h"
18.46 +#include "gmyth_uri.h"
18.47 +#include "gmyth_marshal.h"
18.48 +
18.49 +#include <unistd.h>
18.50 +#include <glib.h>
18.51 +
18.52 +#include <arpa/inet.h>
18.53 +#include <sys/types.h>
18.54 +#include <sys/socket.h>
18.55 +#include <netdb.h>
18.56 +#include <errno.h>
18.57 +#include <stdlib.h>
18.58 +#include <assert.h>
18.59 +
18.60 +#define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER "
18.61 +
18.62 +
18.63 +#define GMYTH_FILE_TRANSFER_GET_PRIVATE(obj) \
18.64 + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferPrivate))
18.65 +
18.66 +enum myth_sock_types {
18.67 + GMYTH_PLAYBACK_TYPE = 0,
18.68 + GMYTH_MONITOR_TYPE,
18.69 + GMYTH_FILETRANSFER_TYPE,
18.70 + GMYTH_RINGBUFFER_TYPE
18.71 +};
18.72 +
18.73 +struct _GMythFileTransferPrivate {
18.74 + GMythRecorder *recorder;
18.75 +
18.76 + gboolean do_next_program_chain;
18.77 + gboolean disposed;
18.78 + gboolean livetv_wait;
18.79 +
18.80 + /*
18.81 + * MythTV version number
18.82 + */
18.83 + gint mythtv_version;
18.84 +
18.85 + /*
18.86 + * socket descriptors
18.87 + */
18.88 + GMythSocket *control_sock;
18.89 + GMythSocket *sock;
18.90 + GMutex *mutex;
18.91 + gint file_id;
18.92 +};
18.93 +
18.94 +static void gmyth_file_transfer_class_init(GMythFileTransferClass *
18.95 + klass);
18.96 +static void gmyth_file_transfer_init(GMythFileTransfer * object);
18.97 +static void gmyth_file_transfer_dispose(GObject * object);
18.98 +static void gmyth_file_transfer_finalize(GObject * object);
18.99 +static void _file_transfer_program_info_changed(GMythFileTransfer *
18.100 + transfer,
18.101 + gint msg_code,
18.102 + gpointer
18.103 + livetv_recorder);
18.104 +static gboolean _connect_to_backend(GMythFileTransfer * transfer);
18.105 +static gboolean _control_acquire_context(GMythFileTransfer * transfer,
18.106 + gboolean do_wait);
18.107 +static gboolean _control_release_context(GMythFileTransfer * transfer);
18.108 +
18.109 +G_DEFINE_TYPE(GMythFileTransfer, gmyth_file_transfer, GMYTH_FILE_TYPE)
18.110 + static void gmyth_file_transfer_class_init(GMythFileTransferClass *
18.111 + klass)
18.112 +{
18.113 + GObjectClass *gobject_class;
18.114 + GMythFileTransferClass *gtransfer_class;
18.115 +
18.116 + gobject_class = (GObjectClass *) klass;
18.117 + gtransfer_class = (GMythFileTransferClass *) gobject_class;
18.118 +
18.119 + gobject_class->dispose = gmyth_file_transfer_dispose;
18.120 + gobject_class->finalize = gmyth_file_transfer_finalize;
18.121 +
18.122 + g_type_class_add_private(gobject_class,
18.123 + sizeof(GMythFileTransferPrivate));
18.124 +
18.125 + gtransfer_class->program_info_changed_handler =
18.126 + _file_transfer_program_info_changed;
18.127 +
18.128 + gtransfer_class->program_info_changed_handler_signal_id =
18.129 + g_signal_new("program-info-changed",
18.130 + G_TYPE_FROM_CLASS(gtransfer_class),
18.131 + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE |
18.132 + G_SIGNAL_NO_HOOKS, 0, NULL, NULL,
18.133 + gmyth_marshal_VOID__INT_POINTER, G_TYPE_NONE, 2,
18.134 + G_TYPE_INT, G_TYPE_POINTER);
18.135 +
18.136 +}
18.137 +
18.138 +static void
18.139 +gmyth_file_transfer_init(GMythFileTransfer * transfer)
18.140 +{
18.141 + g_return_if_fail(transfer != NULL);
18.142 +
18.143 + transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
18.144 + transfer->priv->mutex = g_mutex_new();
18.145 +
18.146 + g_signal_connect(G_OBJECT(transfer), "program-info-changed",
18.147 + (GCallback) (GMYTH_FILE_TRANSFER_GET_CLASS
18.148 + (transfer)->program_info_changed_handler),
18.149 + NULL);
18.150 +}
18.151 +
18.152 +static void
18.153 +gmyth_file_transfer_dispose(GObject * object)
18.154 +{
18.155 + GMythFileTransferPrivate *priv;
18.156 + GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER(object);
18.157 +
18.158 + g_return_if_fail(transfer != NULL);
18.159 +
18.160 + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
18.161 +
18.162 + if (priv->disposed) {
18.163 + /*
18.164 + * If dispose did already run, return.
18.165 + */
18.166 + return;
18.167 + }
18.168 +
18.169 + /*
18.170 + * Make sure dispose does not run twice.
18.171 + */
18.172 + priv->disposed = TRUE;
18.173 +
18.174 + if (priv->mutex != NULL) {
18.175 + g_mutex_free(priv->mutex);
18.176 + priv->mutex = NULL;
18.177 + }
18.178 +
18.179 + if (priv->control_sock != NULL) {
18.180 + g_object_unref(priv->control_sock);
18.181 + priv->control_sock = NULL;
18.182 + }
18.183 +
18.184 + if (priv->sock != NULL) {
18.185 + g_object_unref(priv->sock);
18.186 + priv->sock = NULL;
18.187 + }
18.188 +
18.189 + if (priv->recorder != NULL) {
18.190 + g_object_unref(priv->recorder);
18.191 + priv->recorder = NULL;
18.192 + }
18.193 +
18.194 + G_OBJECT_CLASS(gmyth_file_transfer_parent_class)->dispose(object);
18.195 +}
18.196 +
18.197 +static void
18.198 +gmyth_file_transfer_finalize(GObject * object)
18.199 +{
18.200 + g_signal_handlers_destroy(object);
18.201 +
18.202 + G_OBJECT_CLASS(gmyth_file_transfer_parent_class)->finalize(object);
18.203 +}
18.204 +
18.205 +/**
18.206 + * Creates a new instance of GMythFileTransfer.
18.207 + *
18.208 + * @param backend_info The BackendInfo instance, with all the MythTV network
18.209 + * configuration data.
18.210 + *
18.211 + * @return a new instance of the File Transfer.
18.212 + */
18.213 +GMythFileTransfer *
18.214 +gmyth_file_transfer_new(GMythBackendInfo * backend_info)
18.215 +{
18.216 + GMythFileTransfer *transfer = g_object_new(GMYTH_FILE_TRANSFER_TYPE,
18.217 + "backend-info",
18.218 + backend_info,
18.219 + NULL);
18.220 +
18.221 + // GValue val = {0,};
18.222 + // backend_info = g_object_ref( backend_info );
18.223 + gmyth_debug("Creating FileTransfer BackendInfo hostname = %s",
18.224 + gmyth_backend_info_get_hostname(backend_info));
18.225 + // GMythBackendInfo *backend_info = gmyth_backend_info_new_with_uri
18.226 + // (uri_str);
18.227 + // g_value_init (&val, G_TYPE_OBJECT);
18.228 + // g_value_set_object (&val, backend_info);
18.229 + // g_object_set (G_OBJECT (transfer), "backend-info", &val, NULL);
18.230 +
18.231 + return transfer;
18.232 +}
18.233 +
18.234 +gchar *
18.235 +gmyth_file_transfer_get_file_name(GMythFileTransfer * transfer)
18.236 +{
18.237 + gchar *filename;
18.238 +
18.239 + g_object_get(G_OBJECT(transfer), "filename", &filename, NULL);
18.240 +
18.241 + return filename;
18.242 +}
18.243 +
18.244 +/**
18.245 + * Creates a new instance of GMythFileTransfer.
18.246 + *
18.247 + * @param uri_str The URI poiting to the MythTV backend server.
18.248 + *
18.249 + * @return a new instance of the File Transfer.
18.250 + */
18.251 +GMythFileTransfer *
18.252 +gmyth_file_transfer_new_with_uri(const gchar * uri_str)
18.253 +{
18.254 + GMythFileTransfer *transfer =
18.255 + GMYTH_FILE_TRANSFER(g_object_new(GMYTH_FILE_TRANSFER_TYPE, NULL));
18.256 + gmyth_debug("URI str = %s", uri_str);
18.257 + // GMythBackendInfo *backend_info = gmyth_backend_info_new_with_uri
18.258 + // (uri_str);
18.259 + GValue val = { 0, };
18.260 + g_value_init(&val, G_TYPE_OBJECT);
18.261 + g_value_set_object(&val, gmyth_backend_info_new_with_uri(uri_str));
18.262 + g_object_set(G_OBJECT(transfer), "backend-info", &val, NULL);
18.263 +
18.264 + return transfer;
18.265 +}
18.266 +
18.267 +/**
18.268 + * Open a File Transfer connection in order to get a remote file.
18.269 + *
18.270 + * @param transfer The actual File Transfer instance.
18.271 + * @param filename The file name of the remote file to be transferred to the client.
18.272 + *
18.273 + * @return <code>true</code>, if the connection opening had been done successfully.
18.274 + */
18.275 +gboolean
18.276 +gmyth_file_transfer_open(GMythFileTransfer * transfer,
18.277 + const gchar * filename)
18.278 +{
18.279 + gboolean ret = TRUE;
18.280 + GMythFileTransferPrivate *priv;
18.281 +
18.282 + g_return_val_if_fail(transfer != NULL, FALSE);
18.283 + g_return_val_if_fail(filename != NULL && strlen(filename) > 0, FALSE);
18.284 +
18.285 + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
18.286 +
18.287 + gmyth_debug("Opening the FileTransfer... (%s)", filename);
18.288 +
18.289 + g_object_set(GMYTH_FILE(transfer), "filename", filename, NULL);
18.290 +
18.291 + /*
18.292 + * configure the control socket
18.293 + */
18.294 + if (TRUE /* priv->control_sock == NULL */ ) {
18.295 + if (!_connect_to_backend(transfer)) {
18.296 + gmyth_debug("Connection to backend failed (Control Socket).");
18.297 + ret = FALSE;
18.298 + }
18.299 +
18.300 + if (priv->do_next_program_chain) {
18.301 + priv->do_next_program_chain = FALSE; // fixme
18.302 + gmyth_debug
18.303 + ("New file available before the current file was opened");
18.304 + GMythProgramInfo *prog_info =
18.305 + gmyth_recorder_get_current_program_info(priv->recorder);
18.306 +
18.307 + if (prog_info != NULL && prog_info->pathname != NULL
18.308 + && strlen(prog_info->pathname->str) > 0
18.309 + && g_ascii_strcasecmp(prog_info->pathname->str,
18.310 + gmyth_file_get_file_name(GMYTH_FILE
18.311 + (transfer)))
18.312 + != 0)
18.313 + ret =
18.314 + gmyth_file_transfer_open(transfer,
18.315 + g_strrstr(prog_info->
18.316 + pathname->str,
18.317 + "/"));
18.318 +
18.319 + if (prog_info != NULL)
18.320 + g_object_unref(prog_info);
18.321 +
18.322 + if (!ret)
18.323 + gmyth_debug("Cannot change to the next program info!");
18.324 + else
18.325 + gmyth_debug("OK!!! MOVED to the next program info [%s]!",
18.326 + gmyth_file_get_file_name(GMYTH_FILE
18.327 + (transfer)));
18.328 +
18.329 + } else {
18.330 + gmyth_debug
18.331 + ("None new file found. We continue with the same file opened before");
18.332 + }
18.333 +
18.334 + } else {
18.335 + gmyth_debug("Remote transfer control socket already created.");
18.336 + }
18.337 +
18.338 + gmyth_debug("Got file with size = %lld.\n",
18.339 + gmyth_file_get_filesize(GMYTH_FILE(transfer)));
18.340 +
18.341 + return ret;
18.342 +}
18.343 +
18.344 +/**
18.345 + * Connect a File Transfer binary client socket to a remote file.
18.346 + *
18.347 + * @param transfer The actual File Transfer instance.
18.348 + *
18.349 + * @return <code>true</code>, if the connection had been configured successfully.
18.350 + */
18.351 +static gboolean
18.352 +_connect_to_backend(GMythFileTransfer * transfer)
18.353 +{
18.354 + GString *base_str = NULL;
18.355 + GString *hostname = NULL;
18.356 + GMythStringList *strlist = NULL;
18.357 + gboolean ret = TRUE;
18.358 + GMythFileTransferPrivate *priv;
18.359 + GMythBackendInfo *backend_info;
18.360 +
18.361 + g_return_val_if_fail(transfer != NULL, FALSE);
18.362 +
18.363 + g_object_get(GMYTH_FILE(transfer), "backend-info", &backend_info,
18.364 + NULL);
18.365 +
18.366 + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
18.367 + _control_acquire_context(transfer, TRUE);
18.368 +
18.369 + /*
18.370 + * Creates the control socket
18.371 + */
18.372 +
18.373 + if (priv->control_sock != NULL) {
18.374 + g_object_unref(priv->control_sock);
18.375 + priv->control_sock = NULL;
18.376 + }
18.377 +
18.378 + base_str = g_string_new("");
18.379 +
18.380 + priv->control_sock = gmyth_socket_new();
18.381 + // Connects the socket, send Mythtv ANN command and verify Mythtv
18.382 + // protocol version
18.383 + if (!gmyth_socket_connect_to_backend(priv->control_sock,
18.384 + backend_info->hostname,
18.385 + backend_info->port, TRUE)) {
18.386 +
18.387 + _control_release_context(transfer);
18.388 + g_object_unref(priv->control_sock);
18.389 + priv->control_sock = NULL;
18.390 + return FALSE;
18.391 + }
18.392 +
18.393 + /*
18.394 + * Creates the data socket
18.395 + */
18.396 + if (priv->sock != NULL) {
18.397 + g_object_unref(priv->sock);
18.398 + priv->sock = NULL;
18.399 + }
18.400 +
18.401 + priv->sock = gmyth_socket_new();
18.402 + gmyth_socket_connect(priv->sock, backend_info->hostname,
18.403 + backend_info->port);
18.404 + gmyth_debug("Connecting file transfer... (%s, %d)",
18.405 + backend_info->hostname, backend_info->port);
18.406 +
18.407 + strlist = gmyth_string_list_new();
18.408 + hostname = gmyth_socket_get_local_hostname();
18.409 + gmyth_debug("[%s] MythTV version (from backend) = %d.\n", __FUNCTION__,
18.410 + priv->control_sock->mythtv_version);
18.411 + if (priv->control_sock->mythtv_version > 26)
18.412 + g_string_printf(base_str, "ANN FileTransfer %s 1 -1",
18.413 + hostname->str);
18.414 + else
18.415 + g_string_printf(base_str, "ANN FileTransfer %s", hostname->str);
18.416 +
18.417 + gmyth_string_list_append_string(strlist, base_str);
18.418 + gmyth_string_list_append_char_array(strlist,
18.419 + gmyth_file_get_file_name(GMYTH_FILE
18.420 + (transfer)));
18.421 +
18.422 + gmyth_socket_write_stringlist(priv->sock, strlist);
18.423 +
18.424 + /*
18.425 + * MONITOR Handler - DVB TV Chain update messages!!!
18.426 + */
18.427 +
18.428 + gmyth_socket_read_stringlist(priv->sock, strlist);
18.429 +
18.430 + /*
18.431 + * file identification used in future file transfer requests to
18.432 + * backend
18.433 + */
18.434 + priv->file_id = gmyth_string_list_get_int(strlist, 1);
18.435 +
18.436 + /*
18.437 + * Myth URI stream file size - decoded using two 8-bytes sequences (64
18.438 + * bits/long long types)
18.439 + */
18.440 + gmyth_file_set_filesize(GMYTH_FILE(transfer),
18.441 + gmyth_string_list_get_int64(strlist, 2));
18.442 +
18.443 + gmyth_debug("***** Received: recordernum = %d, filesize = %"
18.444 + G_GUINT64_FORMAT "\n", priv->file_id,
18.445 + gmyth_file_get_filesize(GMYTH_FILE(transfer)));
18.446 +
18.447 + if (gmyth_file_get_filesize(GMYTH_FILE(transfer)) < 0) {
18.448 + gmyth_debug
18.449 + ("Got filesize equals to %llu is lesser than 0 [invalid stream file]\n",
18.450 + gmyth_file_get_filesize(GMYTH_FILE(transfer)));
18.451 + g_object_unref(priv->sock);
18.452 + priv->sock = NULL;
18.453 + ret = FALSE;
18.454 + }
18.455 +
18.456 + _control_release_context(transfer);
18.457 +
18.458 + if (strlist != NULL)
18.459 + g_object_unref(strlist);
18.460 +
18.461 + if (base_str != NULL)
18.462 + g_string_free(base_str, TRUE);
18.463 +
18.464 + if (hostname != NULL)
18.465 + g_string_free(hostname, TRUE);
18.466 +
18.467 + return ret;
18.468 +}
18.469 +
18.470 +/**
18.471 + * Receives a GObject signal coming from a LiveTV instance, all the time a
18.472 + * program info changes.
18.473 + *
18.474 + * @param transfer The actual File Transfer instance.
18.475 + * @param msg_code The MythTV backend message status code.
18.476 + * @param live_tv A pointer to the LiveTV instance. *
18.477 + */
18.478 +void
18.479 +gmyth_file_transfer_emit_program_info_changed_signal(GMythFileTransfer *
18.480 + transfer,
18.481 + gint msg_code,
18.482 + gpointer
18.483 + live_tv_recorder)
18.484 +{
18.485 + gmyth_debug("Calling signal handler... [FILE_TRANSFER]");
18.486 +
18.487 + g_signal_emit(transfer, GMYTH_FILE_TRANSFER_GET_CLASS(transfer)->program_info_changed_handler_signal_id, 0, /* details
18.488 + */
18.489 + msg_code, live_tv_recorder);
18.490 +
18.491 +}
18.492 +
18.493 +/**
18.494 + * Checks if the actual File Transfer connection is open.
18.495 + *
18.496 + * @param transfer The actual File Transfer instance.
18.497 + *
18.498 + * @return <code>true</code>, if the File Transfer connection is opened.
18.499 + */
18.500 +gboolean
18.501 +gmyth_file_transfer_is_open(GMythFileTransfer * transfer)
18.502 +{
18.503 + GMythStringList *strlist;
18.504 + GMythFileTransferPrivate *priv;
18.505 + GString *query;
18.506 +
18.507 + g_return_val_if_fail(transfer != NULL, FALSE);
18.508 +
18.509 + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
18.510 + g_return_val_if_fail(priv->control_sock != NULL, FALSE);
18.511 + g_return_val_if_fail(priv->sock != NULL, FALSE);
18.512 +
18.513 + _control_acquire_context(transfer, TRUE);
18.514 +
18.515 + strlist = gmyth_string_list_new();
18.516 + query = g_string_new(GMYTHTV_QUERY_HEADER);
18.517 + g_string_append_printf(query, "%d", priv->file_id);
18.518 +
18.519 + gmyth_string_list_append_string(strlist, query);
18.520 + gmyth_string_list_append_char_array(strlist, "IS_OPEN");
18.521 +
18.522 + gmyth_socket_write_stringlist(priv->control_sock, strlist);
18.523 + gmyth_socket_read_stringlist(priv->control_sock, strlist);
18.524 +
18.525 + _control_release_context(transfer);
18.526 +
18.527 + g_string_free(query, TRUE);
18.528 + g_object_unref(strlist);
18.529 +
18.530 + return (strlist != NULL && gmyth_string_list_get_int(strlist, 0) == 1);
18.531 +}
18.532 +
18.533 +/**
18.534 + * Closes a remote File Transfer connection.
18.535 + *
18.536 + * @param transfer The actual File Transfer instance.
18.537 + */
18.538 +void
18.539 +gmyth_file_transfer_close(GMythFileTransfer * transfer)
18.540 +{
18.541 + GMythStringList *strlist;
18.542 + GMythFileTransferPrivate *priv;
18.543 + GString *query;
18.544 +
18.545 + g_return_if_fail(transfer != NULL);
18.546 +
18.547 + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
18.548 +
18.549 + if (priv->control_sock == NULL)
18.550 + return;
18.551 +
18.552 + _control_acquire_context(transfer, TRUE);
18.553 +
18.554 + strlist = gmyth_string_list_new();
18.555 + query = g_string_new(GMYTHTV_QUERY_HEADER);
18.556 + g_string_append_printf(query, "%d", priv->file_id);
18.557 +
18.558 + gmyth_string_list_append_string(strlist, query);
18.559 + gmyth_string_list_append_char_array(strlist, "DONE");
18.560 +
18.561 + if (gmyth_socket_sendreceive_stringlist(priv->control_sock, strlist) <=
18.562 + 0) {
18.563 + // fixme: time out???
18.564 + gmyth_debug("Remote file timeout.\n");
18.565 + }
18.566 +
18.567 + g_string_free(query, TRUE);
18.568 + g_object_unref(strlist);
18.569 +
18.570 + if (priv->sock) {
18.571 + g_object_unref(priv->sock);
18.572 + priv->sock = NULL;
18.573 + }
18.574 +
18.575 + if (priv->control_sock) {
18.576 + g_object_unref(priv->control_sock);
18.577 + priv->control_sock = NULL;
18.578 + }
18.579 +
18.580 + _control_release_context(transfer);
18.581 +}
18.582 +
18.583 +/**
18.584 + * Do a seek operation (moves the read/write file pointer) on a remote file.
18.585 + *
18.586 + * @param transfer The actual File Transfer instance.
18.587 + * @param pos The position to be moved in the remote file.
18.588 + * @param whence Tells to what direction seek movement should be done.
18.589 + *
18.590 + * @return The actual position on the remote file (after seek has been done).
18.591 + */
18.592 +gint64
18.593 +gmyth_file_transfer_seek(GMythFileTransfer * transfer, guint64 pos,
18.594 + gint whence)
18.595 +{
18.596 + GMythStringList *strlist = gmyth_string_list_new();
18.597 + GMythFileTransferPrivate *priv;
18.598 + GString *query;
18.599 +
18.600 + g_return_val_if_fail(transfer != NULL, FALSE);
18.601 + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
18.602 +
18.603 + g_return_val_if_fail(priv->sock != NULL, -1);
18.604 + g_return_val_if_fail(priv->control_sock != NULL, -1);
18.605 +
18.606 + strlist = gmyth_string_list_new();
18.607 + query = g_string_new(GMYTHTV_QUERY_HEADER);
18.608 + g_string_append_printf(query, "%d", priv->file_id);
18.609 +
18.610 + /*
18.611 + * myth_control_acquire_context( transfer, TRUE );
18.612 + */
18.613 +
18.614 + gmyth_string_list_append_string(strlist, query);
18.615 + gmyth_string_list_append_char_array(strlist, "SEEK");
18.616 + gmyth_string_list_append_uint64(strlist, pos);
18.617 +
18.618 + gmyth_string_list_append_int(strlist, whence);
18.619 +
18.620 + if (pos > 0)
18.621 + gmyth_string_list_append_uint64(strlist, pos);
18.622 + else
18.623 + gmyth_string_list_append_uint64(strlist,
18.624 + gmyth_file_get_offset(GMYTH_FILE
18.625 + (transfer)));
18.626 +
18.627 + gmyth_socket_sendreceive_stringlist(priv->control_sock, strlist);
18.628 +
18.629 + gint64 retval = gmyth_string_list_get_int64(strlist, 0);
18.630 +
18.631 + gmyth_file_set_offset(GMYTH_FILE(transfer), retval);
18.632 + gmyth_debug("Got reading position pointer from the streaming = %lld\n",
18.633 + retval);
18.634 +
18.635 + g_object_unref(strlist);
18.636 + g_string_free(query, TRUE);
18.637 +
18.638 + /*
18.639 + * myth_control_release_context( transfer );
18.640 + */
18.641 +
18.642 + return retval;
18.643 +}
18.644 +
18.645 +/**
18.646 + * Acquire access to a remote file socket read/write pointer.
18.647 + *
18.648 + * @param transfer The actual File Transfer instance.
18.649 + * @param do_wait Waits or not on a GCond, when trying to read from the remote socket.
18.650 + *
18.651 + * @return <code>true</code>, if the acquire had been got.
18.652 + */
18.653 +static gboolean
18.654 +_control_acquire_context(GMythFileTransfer * transfer, gboolean do_wait)
18.655 +{
18.656 + gboolean ret = TRUE;
18.657 + GMythFileTransferPrivate *priv;
18.658 +
18.659 + g_return_val_if_fail(transfer != NULL, FALSE);
18.660 + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
18.661 +
18.662 + g_mutex_lock(priv->mutex);
18.663 + return ret;
18.664 +}
18.665 +
18.666 +/**
18.667 + * Release access to a remote file socket read/write pointer.
18.668 + *
18.669 + * @param transfer The actual File Transfer instance.
18.670 + *
18.671 + * @return <code>true</code>, if the socket read/write permissions had been releaseds.
18.672 + */
18.673 +static gboolean
18.674 +_control_release_context(GMythFileTransfer * transfer)
18.675 +{
18.676 + gboolean ret = TRUE;
18.677 + GMythFileTransferPrivate *priv;
18.678 +
18.679 + g_return_val_if_fail(transfer != NULL, FALSE);
18.680 + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
18.681 +
18.682 + g_mutex_unlock(priv->mutex);
18.683 +
18.684 + return ret;
18.685 +}
18.686 +
18.687 +/**
18.688 + * Reads a block from a remote file.
18.689 + *
18.690 + * @param transfer The actual File Transfer instance.
18.691 + * @param data A GByteArray instance, where all the binary data representing
18.692 + * the remote file will be stored.
18.693 + * @param size The block size, in bytes, to be requested from a remote file.
18.694 + * @param read_unlimited Tells the backend to read indefinitely (LiveTV), or only
18.695 + * gets the actual size
18.696 + *
18.697 + * @return The actual block size (in bytes) returned by REQUEST_BLOCK message,
18.698 + * or the error code.
18.699 + */
18.700 +GMythFileReadResult
18.701 +gmyth_file_transfer_read(GMythFileTransfer * transfer, GByteArray * data,
18.702 + gint size, gboolean read_unlimited)
18.703 +{
18.704 + gint bytes_sent = 0;
18.705 + gsize bytes_read = 0;
18.706 + gint64 total_read = 0;
18.707 + GMythFileReadResult retval = GMYTH_FILE_READ_OK;
18.708 + GMythFileTransferPrivate *priv;
18.709 +
18.710 + GError *error = NULL;
18.711 +
18.712 + GIOChannel *io_channel;
18.713 + GIOChannel *io_channel_control;
18.714 +
18.715 + GIOCondition io_cond;
18.716 + GIOCondition io_cond_control;
18.717 + GIOStatus io_status = G_IO_STATUS_NORMAL;
18.718 + GIOStatus io_status_control = G_IO_STATUS_NORMAL;
18.719 +
18.720 + GMythStringList *strlist;
18.721 + GMythStringList *ret_strlist = NULL;
18.722 + gboolean ret = TRUE;
18.723 + GString *query;
18.724 +
18.725 + g_return_val_if_fail(transfer != NULL, FALSE);
18.726 + g_return_val_if_fail(data != NULL, GMYTH_FILE_READ_ERROR);
18.727 +
18.728 + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
18.729 +
18.730 + strlist = gmyth_string_list_new();
18.731 +
18.732 + io_channel = priv->sock->sd_io_ch;
18.733 + io_channel_control = priv->control_sock->sd_io_ch;
18.734 +
18.735 + io_status = g_io_channel_set_encoding(io_channel, NULL, &error);
18.736 + if (io_status == G_IO_STATUS_NORMAL)
18.737 + gmyth_debug("[%s] Setting encoding to binary data socket).\n",
18.738 + __FUNCTION__);
18.739 +
18.740 + io_cond = g_io_channel_get_buffer_condition(io_channel);
18.741 +
18.742 + io_cond_control = g_io_channel_get_buffer_condition(io_channel);
18.743 + if (priv->sock == NULL || (io_status == G_IO_STATUS_ERROR)) {
18.744 + g_printerr
18.745 + ("gmyth_file_transfer_read(): Called with no raw socket.\n");
18.746 + return GMYTH_FILE_READ_ERROR;
18.747 + }
18.748 +
18.749 + if (priv->control_sock == NULL
18.750 + || (io_status_control == G_IO_STATUS_ERROR)) {
18.751 + g_printerr
18.752 + ("gmyth_file_transfer_read(): Called with no control socket.\n");
18.753 + return GMYTH_FILE_READ_ERROR;
18.754 + }
18.755 +
18.756 + query = g_string_new(GMYTHTV_QUERY_HEADER);
18.757 + g_string_append_printf(query, "%d", priv->file_id);
18.758 + gmyth_debug("[%s] Transfer_query = %s\n", __FUNCTION__, query->str);
18.759 +
18.760 + _control_acquire_context(transfer, TRUE);
18.761 + // Do Read
18.762 + gmyth_string_list_append_char_array(strlist, query->str);
18.763 + gmyth_string_list_append_char_array(strlist, "REQUEST_BLOCK");
18.764 + gmyth_string_list_append_int(strlist, size - total_read);
18.765 +
18.766 + guint iter_count = 3;
18.767 +
18.768 + do {
18.769 + bytes_sent = 0;
18.770 +
18.771 + // Request the block to the backend
18.772 + gmyth_socket_write_stringlist(priv->control_sock, strlist);
18.773 +
18.774 + if (ret_strlist != NULL)
18.775 + g_object_unref(ret_strlist);
18.776 +
18.777 + ret_strlist = gmyth_string_list_new();
18.778 + // Receives the backand answer
18.779 + gmyth_socket_read_stringlist(priv->control_sock, ret_strlist);
18.780 +
18.781 + if (ret_strlist != NULL
18.782 + && gmyth_string_list_length(ret_strlist) > 0) {
18.783 + bytes_sent = gmyth_string_list_get_int(ret_strlist, 0); // -1
18.784 + // on
18.785 + // backend
18.786 + // error
18.787 + gmyth_debug("[%s] got SENT buffer message = %d\n",
18.788 + __FUNCTION__, bytes_sent);
18.789 + }
18.790 +
18.791 + if (read_unlimited && (bytes_sent == 0)) {
18.792 + g_usleep(300);
18.793 + }
18.794 +
18.795 + --iter_count;
18.796 +
18.797 + }
18.798 + while (read_unlimited && (bytes_sent == 0) && iter_count > 0);
18.799 +
18.800 + if (bytes_sent > 0) {
18.801 + gchar *data_buffer = g_new0(gchar, bytes_sent);
18.802 +
18.803 + io_status = g_io_channel_read_chars(io_channel,
18.804 + data_buffer,
18.805 + (gsize) bytes_sent,
18.806 + &bytes_read, &error);
18.807 +
18.808 + if (io_status != G_IO_STATUS_NORMAL) {
18.809 + gmyth_debug("Error on io_channel");
18.810 + g_free(data_buffer);
18.811 + g_object_unref(strlist);
18.812 + retval = GMYTH_FILE_READ_ERROR;
18.813 + goto error;
18.814 + }
18.815 +
18.816 + /*
18.817 + * append new data to the increasing byte array
18.818 + */
18.819 + data =
18.820 + g_byte_array_append(data, (const guint8 *) data_buffer,
18.821 + bytes_read);
18.822 + gmyth_file_set_offset(GMYTH_FILE(transfer),
18.823 + gmyth_file_get_offset(GMYTH_FILE(transfer)) +
18.824 + bytes_read);
18.825 +
18.826 + if (!read_unlimited
18.827 + && (gmyth_file_get_filesize(GMYTH_FILE(transfer)) > 0)
18.828 + && (gmyth_file_get_offset(GMYTH_FILE(transfer)) ==
18.829 + gmyth_file_get_filesize(GMYTH_FILE(transfer)))) {
18.830 + retval = GMYTH_FILE_READ_EOF;
18.831 + goto error;
18.832 + }
18.833 +
18.834 + g_free(data_buffer);
18.835 + } else {
18.836 + retval = GMYTH_FILE_READ_ERROR;
18.837 + }
18.838 +
18.839 + if (strlist != NULL) {
18.840 + g_object_unref(strlist);
18.841 + strlist = NULL;
18.842 + }
18.843 +
18.844 + if (ret_strlist != NULL) {
18.845 + g_object_unref(ret_strlist);
18.846 + ret_strlist = NULL;
18.847 + }
18.848 +
18.849 + if (read_unlimited && (bytes_sent == 0)) {
18.850 + gmyth_debug("Trying to move to the next program chain...");
18.851 + if (priv->recorder != NULL && priv->do_next_program_chain) {
18.852 + priv->do_next_program_chain = FALSE;
18.853 + retval = GMYTH_FILE_READ_NEXT_PROG_CHAIN;
18.854 + GMythProgramInfo *prog_info =
18.855 + gmyth_recorder_get_current_program_info(priv->recorder);
18.856 +
18.857 + gmyth_debug
18.858 + ("Comparing if the current prog. info = %s [strlen == %d] is equals to "
18.859 + " %s [strlen == %d]...", prog_info->pathname->str,
18.860 + strlen(prog_info->pathname->str),
18.861 + gmyth_file_get_file_name(GMYTH_FILE(transfer)),
18.862 + strlen(gmyth_file_get_file_name(GMYTH_FILE(transfer))));
18.863 +
18.864 + if (prog_info != NULL && prog_info->pathname != NULL
18.865 + && strlen(prog_info->pathname->str) > 0
18.866 + && (NULL ==
18.867 + g_strstr_len(prog_info->pathname->str,
18.868 + strlen(prog_info->pathname->str),
18.869 + gmyth_file_get_file_name(GMYTH_FILE
18.870 + (transfer))))) {
18.871 + /*
18.872 + * releasing context got at this function starting...
18.873 + */
18.874 + _control_release_context(transfer);
18.875 + ret =
18.876 + gmyth_file_transfer_open(transfer,
18.877 + g_strrstr(prog_info->
18.878 + pathname->str,
18.879 + "/"));
18.880 + _control_acquire_context(transfer, TRUE);
18.881 + /*
18.882 + * acquiring context released at this function stopping...
18.883 + */
18.884 +
18.885 + if (prog_info != NULL)
18.886 + g_object_unref(prog_info);
18.887 +
18.888 + if (!ret)
18.889 + gmyth_debug("Cannot change to the next program info!");
18.890 + else
18.891 + gmyth_debug
18.892 + ("OK!!! MOVED to the next program info [%s]!",
18.893 + gmyth_file_get_file_name(GMYTH_FILE(transfer)));
18.894 + }
18.895 +
18.896 + }
18.897 +
18.898 + }
18.899 + /*
18.900 + * if
18.901 + */
18.902 + error:
18.903 +
18.904 + _control_release_context(transfer);
18.905 + g_string_free(query, TRUE);
18.906 +
18.907 + if (error != NULL) {
18.908 + gmyth_debug("Cleaning-up ERROR: %s [msg = %s, code = %d]\n",
18.909 + __FUNCTION__, error->message, error->code);
18.910 + g_error_free(error);
18.911 + }
18.912 +
18.913 + if (total_read > 0)
18.914 + gmyth_file_set_offset(GMYTH_FILE(transfer),
18.915 + gmyth_file_get_offset(GMYTH_FILE
18.916 + (transfer)) +
18.917 + total_read);
18.918 +
18.919 + return retval;
18.920 +}
18.921 +
18.922 +static void
18.923 +_file_transfer_program_info_changed(GMythFileTransfer * transfer,
18.924 + gint msg_code,
18.925 + gpointer livetv_recorder)
18.926 +{
18.927 + GMythRecorder *recorder;
18.928 + GMythFileTransferPrivate *priv;
18.929 +
18.930 + g_return_if_fail(transfer != NULL);
18.931 +
18.932 + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
18.933 +
18.934 + recorder = GMYTH_RECORDER(livetv_recorder);
18.935 + gmyth_debug
18.936 + ("Program info changed! ( file transfer orig. = %p, ptr. = [%s] )",
18.937 + transfer, livetv_recorder != NULL ? "[NOT NULL]" : "[NULL]");
18.938 +
18.939 + if (NULL != recorder) {
18.940 + gmyth_debug
18.941 + ("YES, the requested program info movement on the LiveTV transfer is authentical!");
18.942 + }
18.943 +
18.944 + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
18.945 + g_object_ref(recorder);
18.946 + priv->recorder = recorder;
18.947 + priv->do_next_program_chain = TRUE;
18.948 +}
18.949 +
18.950 +/**
18.951 + * Sets the timeout flag of a file being transfered.
18.952 + *
18.953 + * @param transfer The actual File Transfer instance.
18.954 + * @param fast If this is <code>true</code>, sets the remote timeout to be as fast
18.955 + * as possible.
18.956 + *
18.957 + * @return <code>true</code>, if the acquire had been got.
18.958 + */
18.959 +gboolean
18.960 +gmyth_file_transfer_settimeout(GMythFileTransfer * transfer, gboolean fast)
18.961 +{
18.962 + GMythFileTransferPrivate *priv;
18.963 + GMythStringList *strlist = NULL;
18.964 +
18.965 + g_return_val_if_fail(transfer != NULL, FALSE);
18.966 +
18.967 + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
18.968 +
18.969 + g_return_val_if_fail(priv->sock != NULL, FALSE);
18.970 + g_return_val_if_fail(priv->control_sock != NULL, FALSE);
18.971 +
18.972 + _control_acquire_context(transfer, TRUE);
18.973 +
18.974 + strlist = gmyth_string_list_new();
18.975 + gmyth_string_list_append_char_array(strlist, GMYTHTV_QUERY_HEADER);
18.976 + gmyth_string_list_append_char_array(strlist, "SET_TIMEOUT");
18.977 + gmyth_string_list_append_int(strlist, fast);
18.978 +
18.979 + gint strlist_len =
18.980 + gmyth_socket_sendreceive_stringlist(priv->control_sock,
18.981 + strlist);
18.982 +
18.983 + if (strlist_len > 0)
18.984 + gmyth_debug("Yes, timeout was changed: %s.",
18.985 + gmyth_string_list_get_char_array(strlist, 0));
18.986 + else
18.987 + gmyth_debug("Timeout cannot be changed!");
18.988 +
18.989 + _control_release_context(transfer);
18.990 +
18.991 + gmyth_debug("%s setting timeout flag of this file transfer = %s\n",
18.992 + strlist_len > 0 ? "Yes," : "NOT",
18.993 + fast ? "FAST" : "NOT FAST");
18.994 +
18.995 + g_object_unref(strlist);
18.996 +
18.997 + return TRUE;
18.998 +}
18.999 +
18.1000 +/**
18.1001 + * Gets the actual file size of the binary content.
18.1002 + *
18.1003 + * @param transfer The actual File Transfer instance.
18.1004 + *
18.1005 + * @return The actual file size in bytes.
18.1006 + */
18.1007 +guint64
18.1008 +gmyth_file_transfer_get_filesize(GMythFileTransfer * transfer)
18.1009 +{
18.1010 + guint64 filesize;
18.1011 +
18.1012 + g_return_val_if_fail(transfer != NULL, 0);
18.1013 +
18.1014 + g_object_get(GMYTH_FILE(transfer), "file-size", &filesize, NULL);
18.1015 +
18.1016 + return filesize;
18.1017 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/gmyth/gmyth/gmyth_file_transfer.h Mon Feb 25 17:51:43 2008 +0000
19.3 @@ -0,0 +1,111 @@
19.4 +/**
19.5 + * GMyth Library
19.6 + *
19.7 + * @file gmyth/gmyth_file_transfer.h
19.8 + *
19.9 + * @brief <p> GMythFileTransfer deals with the file streaming media remote/local
19.10 + * transfering to the MythTV frontend.
19.11 + *
19.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
19.13 + * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
19.14 + *
19.15 + *
19.16 + * This program is free software; you can redistribute it and/or modify
19.17 + * it under the terms of the GNU Lesser General Public License as published by
19.18 + * the Free Software Foundation; either version 2 of the License, or
19.19 + * (at your option) any later version.
19.20 + *
19.21 + * This program is distributed in the hope that it will be useful,
19.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
19.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19.24 + * GNU General Public License for more details.
19.25 + *
19.26 + * You should have received a copy of the GNU Lesser General Public License
19.27 + * along with this program; if not, write to the Free Software
19.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19.29 + */
19.30 +
19.31 +#ifndef __GMYTH_FILE_TRANSFER_H__
19.32 +#define __GMYTH_FILE_TRANSFER_H__
19.33 +
19.34 +#include <glib-object.h>
19.35 +#include <glib.h>
19.36 +
19.37 +#include "gmyth_file.h"
19.38 +#include "gmyth_socket.h"
19.39 +#include "gmyth_uri.h"
19.40 +#include "gmyth_backendinfo.h"
19.41 +
19.42 +#include <stdio.h>
19.43 +#include <stdlib.h>
19.44 +#include <string.h>
19.45 +#include <netdb.h>
19.46 +#include <sys/socket.h>
19.47 +#include <unistd.h>
19.48 +
19.49 +G_BEGIN_DECLS
19.50 +#define GMYTH_FILE_TRANSFER_TYPE (gmyth_file_transfer_get_type ())
19.51 +#define GMYTH_FILE_TRANSFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransfer))
19.52 +#define GMYTH_FILE_TRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferClass))
19.53 +#define IS_GMYTH_FILE_TRANSFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_FILE_TRANSFER_TYPE))
19.54 +#define IS_GMYTH_FILE_TRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TRANSFER_TYPE))
19.55 +#define GMYTH_FILE_TRANSFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferClass))
19.56 +typedef struct _GMythFileTransfer GMythFileTransfer;
19.57 +typedef struct _GMythFileTransferClass GMythFileTransferClass;
19.58 +typedef struct _GMythFileTransferPrivate GMythFileTransferPrivate;
19.59 +
19.60 +struct _GMythFileTransfer {
19.61 + GMythFile parent;
19.62 + GMythFileTransferPrivate *priv;
19.63 +};
19.64 +
19.65 +struct _GMythFileTransferClass {
19.66 + GMythFileClass parent_class;
19.67 +
19.68 + /*
19.69 + * callbacks
19.70 + */
19.71 + guint program_info_changed_handler_signal_id;
19.72 +
19.73 + /*
19.74 + * signal default handlers
19.75 + */
19.76 + void (*program_info_changed_handler) (GMythFileTransfer *
19.77 + transfer,
19.78 + gint msg_code,
19.79 + gpointer
19.80 + livetv_recorder);
19.81 +};
19.82 +
19.83 +
19.84 +GType gmyth_file_transfer_get_type(void);
19.85 +GMythFileTransfer *gmyth_file_transfer_new(GMythBackendInfo *
19.86 + backend_info);
19.87 +gchar *gmyth_file_transfer_get_file_name(GMythFileTransfer *
19.88 + transfer);
19.89 +gboolean gmyth_file_transfer_open(GMythFileTransfer * transfer,
19.90 + const gchar * filename);
19.91 +void gmyth_file_transfer_close(GMythFileTransfer * transfer);
19.92 +gboolean gmyth_file_transfer_is_open(GMythFileTransfer * transfer);
19.93 +
19.94 +GMythFileReadResult
19.95 +gmyth_file_transfer_read(GMythFileTransfer * transfer,
19.96 + GByteArray * data, gint size,
19.97 + gboolean read_unlimited);
19.98 +gint64 gmyth_file_transfer_seek(GMythFileTransfer * transfer,
19.99 + guint64 pos, gint whence);
19.100 +gboolean gmyth_file_transfer_settimeout(GMythFileTransfer *
19.101 + transfer, gboolean fast);
19.102 +guint64 gmyth_file_transfer_get_filesize(GMythFileTransfer *
19.103 + transfer);
19.104 +
19.105 +void
19.106 + gmyth_file_transfer_emit_program_info_changed_signal(GMythFileTransfer *
19.107 + transfer,
19.108 + gint
19.109 + msg_code,
19.110 + gpointer
19.111 + live_tv_recorder);
19.112 +
19.113 +G_END_DECLS
19.114 +#endif /* __GMYTH_FILE_TRANSFER_H__ */
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/gmyth/gmyth/gmyth_http.c Mon Feb 25 17:51:43 2008 +0000
20.3 @@ -0,0 +1,1037 @@
20.4 +/**
20.5 + * GMyth Library
20.6 + *
20.7 + * @file gmyth/gmyth_http.c
20.8 + *
20.9 + * @brief <p> GMythHttp library provides a wrapper to access
20.10 + * data from the database using http+xml
20.11 + *
20.12 + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
20.13 + * @author Artur Duque de Souza <artur.souza@indt.org.br>
20.14 + *
20.15 + *
20.16 + * This program is free software; you can redistribute it and/or modify
20.17 + * it under the terms of the GNU Lesser General Public License as published by
20.18 + * the Free Software Foundation; either version 2 of the License, or
20.19 + * (at your option) any later version.
20.20 + *
20.21 + * This program is distributed in the hope that it will be useful,
20.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
20.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20.24 + * GNU General Public License for more details.
20.25 + *
20.26 + * You should have received a copy of the GNU Lesser General Public License
20.27 + * along with this program; if not, write to the Free Software
20.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20.29 + */
20.30 +
20.31 +#ifdef HAVE_CONFIG_H
20.32 +#include "config.h"
20.33 +#endif
20.34 +
20.35 +#include <assert.h>
20.36 +#include <libxml/parser.h>
20.37 +#include <libxml/tree.h>
20.38 +#include <libxml/xpath.h>
20.39 +#include <libxml/uri.h>
20.40 +
20.41 +#include "gmyth_http.h"
20.42 +#include "gmyth_debug.h"
20.43 +#include "gmyth_socket.h"
20.44 +
20.45 +xmlXPathObjectPtr
20.46 +getnodeset(xmlDocPtr doc, xmlChar * xpath)
20.47 +{
20.48 +
20.49 + xmlXPathContextPtr context;
20.50 + xmlXPathObjectPtr result;
20.51 +
20.52 + context = xmlXPathNewContext(doc);
20.53 + result = xmlXPathEvalExpression(xpath, context);
20.54 +
20.55 + if (xmlXPathNodeSetIsEmpty(result->nodesetval)) {
20.56 + g_fprintf(stderr, "Error: No result at XPath\n");
20.57 + return NULL;
20.58 + }
20.59 +
20.60 + xmlXPathFreeContext(context);
20.61 + return result;
20.62 +}
20.63 +
20.64 +
20.65 +xmlDocPtr
20.66 +XMLParse(const char *content, int length)
20.67 +{
20.68 + xmlDocPtr doc; /* the resulting document tree */
20.69 +
20.70 + doc = xmlReadMemory(content, length, NULL, NULL, 0);
20.71 + if (doc == NULL) {
20.72 + g_fprintf(stderr, "Error: Failed to parse XML document\n");
20.73 + return NULL;
20.74 + }
20.75 +
20.76 + return doc;
20.77 +}
20.78 +
20.79 +xmlXPathObjectPtr
20.80 +getXPath(xmlChar * xpath, xmlDocPtr doc)
20.81 +{
20.82 + xmlXPathObjectPtr result;
20.83 +
20.84 + result = getnodeset(doc, xpath);
20.85 + return result;
20.86 +}
20.87 +
20.88 +
20.89 +/** Retrieves the Progam List from the Channel
20.90 + *
20.91 + * @param nodeTab A pointer to a node inside the XML
20.92 + * @return A GSList containing a list of all the programs
20.93 + */
20.94 +GSList *
20.95 +get_Program_List(xmlNodePtr node)
20.96 +{
20.97 + GSList *program_list = NULL;
20.98 +
20.99 + while (node != NULL) {
20.100 + if (g_ascii_strcasecmp((char *) node->name, "text") != 0) {
20.101 + GMythProgram *program = (GMythProgram *)
20.102 + g_malloc(sizeof(struct _GMythProgram));
20.103 +
20.104 + program->title = g_strdup((char *)
20.105 + xmlGetProp(node,
20.106 + (xmlChar *) "title"));
20.107 +
20.108 + program->subtitle = g_strdup((char *)
20.109 + xmlGetProp(node, (xmlChar *)
20.110 + "subtitle"));
20.111 +
20.112 + program->catType = g_strdup((char *)
20.113 + xmlGetProp(node, (xmlChar *)
20.114 + "catType"));
20.115 +
20.116 + program->category = g_strdup((char *)
20.117 + xmlGetProp(node, (xmlChar *)
20.118 + "category"));
20.119 +
20.120 + sscanf((char *) xmlGetProp(node, (xmlChar *) "repeat"),
20.121 + "%d", &(program->repeat));
20.122 +
20.123 + program->startTime = gmyth_util_string_to_time_val
20.124 + ((char *) xmlGetProp(node, (xmlChar *) "startTime"));
20.125 +
20.126 + program->endTime = gmyth_util_string_to_time_val
20.127 + ((char *) xmlGetProp(node, (xmlChar *) "endTime"));
20.128 +
20.129 + program_list = g_slist_append(program_list, program);
20.130 + }
20.131 +
20.132 + node = node->next;
20.133 + }
20.134 +
20.135 + return program_list;
20.136 +}
20.137 +
20.138 +/** Retrieves the Channel List from the ProgramGuide
20.139 + *
20.140 + * @param node A pointer to a node inside the XML
20.141 + * @param epg The struct where is the current epg
20.142 + * @return The epg from "param" updated
20.143 + */
20.144 +void
20.145 +get_Channel_List(xmlNodePtr node, GMythEpg * epg)
20.146 +{
20.147 + epg->channelList = NULL;
20.148 +
20.149 + while (node != NULL) {
20.150 +
20.151 + if (g_ascii_strcasecmp((char *) node->name, "text") != 0) {
20.152 + GMythChannel *channel = (GMythChannel *) g_malloc
20.153 + (sizeof(struct _GMythChannel));
20.154 +
20.155 + channel->channelName = g_strdup((char *)
20.156 + xmlGetProp(node, (xmlChar *)
20.157 + "channelName"));
20.158 +
20.159 + channel->chanNum = g_strdup((char *)
20.160 + xmlGetProp(node, (xmlChar *)
20.161 + "chanNum"));
20.162 +
20.163 + sscanf((char *) xmlGetProp(node, (xmlChar *) "chanId"),
20.164 + "%d", &(channel->chanId));
20.165 +
20.166 + sscanf((char *) xmlGetProp(node, (xmlChar *) "callSign"),
20.167 + "%d", &(channel->callSign));
20.168 +
20.169 + channel->programList = get_Program_List(node->children);
20.170 +
20.171 + epg->channelList = g_slist_append(epg->channelList, channel);
20.172 +
20.173 + }
20.174 +
20.175 + node = node->next;
20.176 + }
20.177 +}
20.178 +
20.179 +/** Retrieves the properties from the ProgramGuide
20.180 + *
20.181 + * @param nodeTab A pointer to a node inside the XML
20.182 + * @param epg The struct where is the current epg
20.183 + * @return The epg from "param" updated
20.184 + */
20.185 +void
20.186 +get_ProgramGuide_Properties(xmlNodePtr nodeTab, GMythEpg * epg)
20.187 +{
20.188 +
20.189 + xmlNode *ptr = nodeTab->children->next->children;
20.190 +
20.191 + epg->startTime = gmyth_util_string_to_time_val((char *) ptr->content);
20.192 +
20.193 + ptr = ptr->parent->next->next->children;
20.194 + epg->endTime = gmyth_util_string_to_time_val((char *) ptr->content);
20.195 +
20.196 + ptr = ptr->parent->next->next->children;
20.197 + sscanf((char *) ptr->content, "%d", &(epg->startChanId));
20.198 +
20.199 + ptr = ptr->parent->next->next->children;
20.200 + sscanf((char *) ptr->content, "%d", &(epg->endChanId));
20.201 +
20.202 + ptr = ptr->parent->next->next->children;
20.203 + sscanf((char *) ptr->content, "%d", &(epg->numOfChannels));
20.204 +
20.205 + ptr = ptr->parent->next->next->children;
20.206 + sscanf((char *) ptr->content, "%d", &(epg->details));
20.207 +
20.208 + ptr = ptr->parent->next->next->children;
20.209 + sscanf((char *) ptr->content, "%d", &(epg->totalCount));
20.210 +
20.211 + ptr = ptr->parent->next->next->children;
20.212 + epg->asOf = gmyth_util_string_to_time_val((char *) ptr->content);
20.213 +
20.214 + ptr = ptr->parent->next->next->children;
20.215 + epg->version = g_strdup((char *) ptr->content);
20.216 +
20.217 + ptr = ptr->parent->next->next->children;
20.218 + sscanf((char *) ptr->content, "%d", &(epg->protoVer));
20.219 +
20.220 + ptr = ptr->parent->next->next->children;
20.221 + // go to Channel section and retrieve Channels and Programs
20.222 + if (epg->numOfChannels > 0)
20.223 + get_Channel_List(ptr, epg);
20.224 + else
20.225 + epg->channelList = NULL;
20.226 +}
20.227 +
20.228 +/** Aux function to retrieve the Eletronic Program Guide
20.229 + *
20.230 + * @param doc An XML document (xmlDocPtr)
20.231 + * @return The epg
20.232 + */
20.233 +void
20.234 +getEpg(xmlDocPtr doc, GMythEpg * epg)
20.235 +{
20.236 + xmlXPathObjectPtr result;
20.237 + xmlNodeSetPtr nodeset;
20.238 + xmlChar *keyword;
20.239 +
20.240 + int i;
20.241 +
20.242 + result = getXPath((xmlChar *) "/*", doc);
20.243 +
20.244 + if (result) {
20.245 + nodeset = result->nodesetval;
20.246 + for (i = 0; i < nodeset->nodeNr; i++) {
20.247 + keyword = (xmlChar *) nodeset->nodeTab[i]->name;
20.248 + if (g_ascii_strcasecmp
20.249 + ((char *) keyword, "GetProgramGuideResponse") == 0) {
20.250 + get_ProgramGuide_Properties(nodeset->nodeTab[i], epg);
20.251 + break;
20.252 + }
20.253 + }
20.254 + xmlXPathFreeObject(result);
20.255 + }
20.256 +
20.257 +}
20.258 +
20.259 +
20.260 +
20.261 +/** Retrieves the Eletronic Program Guide from the backend
20.262 + *
20.263 + * @param doc An XML document (xmlDocPtr)
20.264 + * @return The epg
20.265 + */
20.266 +GMythEpg
20.267 +gmyth_http_retrieve_epg(GMythBackendInfo * backend_info,
20.268 + GTimeVal * StartTime, GTimeVal * EndTime,
20.269 + gint StartChanId, gint NumOfChannels,
20.270 + gchar * Details)
20.271 +{
20.272 + GMythEpg epg;
20.273 + MemoryStruct chunk;
20.274 +
20.275 + chunk.memory = NULL; /* we expect realloc(NULL, size) to work */
20.276 + chunk.size = 0; /* no data at this point */
20.277 +
20.278 + gchar *starttime;
20.279 +
20.280 + starttime = (gchar *) xmlURIEscapeStr((const xmlChar *)
20.281 + gmyth_util_time_to_mythformat_from_time_val
20.282 + (StartTime), NULL);
20.283 +
20.284 + gchar *endtime;
20.285 +
20.286 + endtime = (gchar *) xmlURIEscapeStr((const xmlChar *)
20.287 + gmyth_util_time_to_mythformat_from_time_val
20.288 + (EndTime), NULL);
20.289 +
20.290 + GString *command = g_string_new("");
20.291 +
20.292 + g_string_printf(command,
20.293 + "GetProgramGuide?StartTime=%s&EndTime=%s&StartChanId=%d"
20.294 + "&NumOfChannels=%d&Details=%s", starttime, endtime,
20.295 + StartChanId, NumOfChannels, Details);
20.296 + gmyth_debug("HTTP Request command = %s\n", command->str);
20.297 +
20.298 + chunk = gmyth_http_request(backend_info, command);
20.299 + if (chunk.memory != NULL) {
20.300 + xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory));
20.301 +
20.302 + getEpg(doc, &epg);
20.303 + free(chunk.memory);
20.304 + }
20.305 +
20.306 + return epg;
20.307 +}
20.308 +
20.309 +
20.310 +GMythRecorded_Recording
20.311 +retrieve_recorded_recording(xmlNodePtr node)
20.312 +{
20.313 + GMythRecorded_Recording recording;
20.314 +
20.315 + if (g_ascii_strcasecmp((char *) node->name, "text") != 0) {
20.316 +
20.317 + sscanf((char *) xmlGetProp(node, (xmlChar *) "dupInType"),
20.318 + "%d", &(recording.dupInType));
20.319 +
20.320 + sscanf((char *) xmlGetProp(node, (xmlChar *) "dupMethod"),
20.321 + "%d", &(recording.dupMethod));
20.322 +
20.323 + sscanf((char *) xmlGetProp(node, (xmlChar *) "recStatus"),
20.324 + "%d", &(recording.recStatus));
20.325 +
20.326 + sscanf((char *) xmlGetProp(node, (xmlChar *) "encoderId"),
20.327 + "%d", &(recording.encoderId));
20.328 +
20.329 + sscanf((char *) xmlGetProp(node, (xmlChar *) "recordId"),
20.330 + "%d", &(recording.recordId));
20.331 +
20.332 + sscanf((char *) xmlGetProp(node, (xmlChar *) "recType"),
20.333 + "%d", &(recording.recType));
20.334 +
20.335 + recording.playGroup = g_strdup((char *)
20.336 + xmlGetProp(node, (xmlChar *)
20.337 + "playGroup"));
20.338 +
20.339 + recording.recGroup = g_strdup((char *)
20.340 + xmlGetProp(node,
20.341 + (xmlChar *) "recGroup"));
20.342 +
20.343 + recording.recProfile = g_strdup((char *)
20.344 + xmlGetProp(node, (xmlChar *)
20.345 + "recProfile"));
20.346 +
20.347 + sscanf((char *) xmlGetProp(node, (xmlChar *) "recPriority"),
20.348 + "%d", &(recording.recPriority));
20.349 +
20.350 + recording.recStartTs = gmyth_util_string_to_time_val
20.351 + ((char *) xmlGetProp(node, (xmlChar *) "recStartTs"));
20.352 +
20.353 + recording.recEndTs = gmyth_util_string_to_time_val
20.354 + ((char *) xmlGetProp(node, (xmlChar *) "recEndTs"));
20.355 + }
20.356 +
20.357 + return recording;
20.358 +}
20.359 +
20.360 +
20.361 +GMythRecorded_Channel
20.362 +retrieve_recorded_channel(xmlNodePtr node)
20.363 +{
20.364 + GMythRecorded_Channel channel;
20.365 +
20.366 + if (g_ascii_strcasecmp((char *) node->name, "text") != 0) {
20.367 +
20.368 + channel.chanFilters = g_strdup((char *)
20.369 + xmlGetProp(node, (xmlChar *)
20.370 + "chanFilters"));
20.371 +
20.372 + channel.channelName = g_strdup((char *)
20.373 + xmlGetProp(node, (xmlChar *)
20.374 + "channelName"));
20.375 +
20.376 + sscanf((char *) xmlGetProp(node, (xmlChar *) "chanNum"),
20.377 + "%d", &(channel.chanNum));
20.378 +
20.379 + sscanf((char *) xmlGetProp(node, (xmlChar *) "sourceId"),
20.380 + "%d", &(channel.sourceId));
20.381 +
20.382 + sscanf((char *) xmlGetProp(node, (xmlChar *) "commFree"),
20.383 + "%d", &(channel.commFree));
20.384 +
20.385 + sscanf((char *) xmlGetProp(node, (xmlChar *) "inputId"),
20.386 + "%d", &(channel.inputId));
20.387 +
20.388 + sscanf((char *) xmlGetProp(node, (xmlChar *) "chanId"),
20.389 + "%d", &(channel.chanId));
20.390 +
20.391 + sscanf((char *) xmlGetProp(node, (xmlChar *) "callSign"),
20.392 + "%d", &(channel.callSign));
20.393 + }
20.394 +
20.395 + return channel;
20.396 +}
20.397 +
20.398 +
20.399 +
20.400 +/** Retrieves all the programs from Recorded XML
20.401 + *
20.402 + * @param nodeTab A pointer to a node inside the XML
20.403 + * @param recorded The struct where is the current epg
20.404 + * @return list with all the recorded programs
20.405 + */
20.406 +GSList *
20.407 +get_Recorded_Programs(xmlNodePtr node)
20.408 +{
20.409 + GSList *programList = NULL;
20.410 +
20.411 + while (node != NULL) {
20.412 +
20.413 + if (g_ascii_strcasecmp((char *) node->name, "text") != 0) {
20.414 +
20.415 + GMythRecorded_Program *program = (GMythRecorded_Program *)
20.416 + g_malloc(sizeof(struct _GMythRecorded_Program));
20.417 +
20.418 + sscanf((char *)
20.419 + xmlGetProp(node, (xmlChar *) "programFlags"), "%d",
20.420 + &(program->programFlags));
20.421 +
20.422 + program->title = g_strdup((char *)
20.423 + xmlGetProp(node,
20.424 + (xmlChar *) "title"));
20.425 +
20.426 + sscanf((char *) xmlGetProp(node, (xmlChar *) "programId"),
20.427 + "%d", &(program->programId));
20.428 +
20.429 + program->catType = g_strdup((char *)
20.430 + xmlGetProp(node, (xmlChar *)
20.431 + "catType"));
20.432 +
20.433 + program->category = g_strdup((char *)
20.434 + xmlGetProp(node, (xmlChar *)
20.435 + "category"));
20.436 +
20.437 + sscanf((char *) xmlGetProp(node, (xmlChar *) "seriesId"),
20.438 + "%d", &(program->seriesId));
20.439 +
20.440 +
20.441 + program->startTime = gmyth_util_string_to_time_val
20.442 + ((char *) xmlGetProp(node, (xmlChar *) "startTime"));
20.443 +
20.444 + program->endTime = gmyth_util_string_to_time_val
20.445 + ((char *) xmlGetProp(node, (xmlChar *) "endTime"));
20.446 +
20.447 + program->lastModified = gmyth_util_string_to_time_val((char *)
20.448 + xmlGetProp
20.449 + (node,
20.450 + (xmlChar
20.451 + *)
20.452 + "lastModified"));
20.453 +
20.454 + /*
20.455 + * TODO: FIX ME at gmyth_util program->asOf =
20.456 + * gmyth_util_string_to_time_val\ ((char *)xmlGetProp(node,
20.457 + * (xmlChar *)"airdate"));
20.458 + */
20.459 +
20.460 + program->subTitle = g_strdup((char *)
20.461 + xmlGetProp(node, (xmlChar *)
20.462 + "subTitle"));
20.463 +
20.464 + sscanf((char *) xmlGetProp(node, (xmlChar *) "stars"),
20.465 + "%d", &(program->stars));
20.466 +
20.467 + sscanf((char *) xmlGetProp(node, (xmlChar *) "repeat"),
20.468 + "%d", &(program->repeat));
20.469 +
20.470 + sscanf((char *) xmlGetProp(node, (xmlChar *) "fileSize"),
20.471 + "%d", &(program->repeat));
20.472 +
20.473 + program->hostname = g_strdup((char *)
20.474 + xmlGetProp(node, (xmlChar *)
20.475 + "hostname"));
20.476 +
20.477 + program->channel = retrieve_recorded_channel(node->children);
20.478 +
20.479 + // Skip the \n
20.480 + program->recording =
20.481 + retrieve_recorded_recording(node->children->next->next);
20.482 +
20.483 + // add to the list
20.484 + programList = g_slist_append(programList, program);
20.485 + }
20.486 +
20.487 + node = node->next;
20.488 + }
20.489 +
20.490 + return programList;
20.491 +}
20.492 +
20.493 +/** Retrieves the properties from Recorded XML
20.494 + *
20.495 + * @param nodeTab A pointer to a node inside the XML
20.496 + * @param recorded The struct where is the current epg
20.497 + * @return "recorded" from "param" updated
20.498 + */
20.499 +void
20.500 +get_Recorded_Properties(xmlNodePtr nodeTab, GMythRecorded * recorded)
20.501 +{
20.502 + xmlNode *ptr = nodeTab->children->next->children;
20.503 +
20.504 + sscanf((char *) ptr->content, "%d", &(recorded->totalCount));
20.505 +
20.506 +
20.507 + ptr = ptr->parent->next->next->children;
20.508 + recorded->asOf = gmyth_util_string_to_time_val((char *) ptr->content);
20.509 +
20.510 + ptr = ptr->parent->next->next->children;
20.511 + recorded->version = g_strdup((char *) ptr->content);
20.512 +
20.513 + ptr = ptr->parent->next->next->children;
20.514 + sscanf((char *) ptr->content, "%d", &(recorded->protoVer));
20.515 +
20.516 + ptr = ptr->parent->next->next->children;
20.517 + if (recorded->totalCount > 0)
20.518 + recorded->programList = get_Recorded_Programs(ptr->children);
20.519 +
20.520 +}
20.521 +
20.522 +
20.523 +/** Aux function to retrieve Recorded programs
20.524 + *
20.525 + * @param doc An XML document (xmlDocPtr)
20.526 + * @return The recorded var updated
20.527 + */
20.528 +void
20.529 +getRecorded(xmlDocPtr doc, GMythRecorded * recorded)
20.530 +{
20.531 + xmlXPathObjectPtr result;
20.532 + xmlNodeSetPtr nodeset;
20.533 + xmlChar *keyword;
20.534 +
20.535 + int i;
20.536 +
20.537 + result = getXPath((xmlChar *) "/*", doc);
20.538 +
20.539 + if (result) {
20.540 + nodeset = result->nodesetval;
20.541 + for (i = 0; i < nodeset->nodeNr; i++) {
20.542 + keyword = (xmlChar *) nodeset->nodeTab[i]->name;
20.543 + if (g_ascii_strcasecmp
20.544 + ((char *) keyword, "GetRecordedResponse") == 0) {
20.545 + get_Recorded_Properties(nodeset->nodeTab[i], recorded);
20.546 + break;
20.547 + }
20.548 + }
20.549 + xmlXPathFreeObject(result);
20.550 + }
20.551 +
20.552 +}
20.553 +
20.554 +
20.555 +/** Function to retrieve the files that are recorded
20.556 + *
20.557 + */
20.558 +GMythRecorded
20.559 +gmyth_http_retrieve_recorded(GMythBackendInfo * backend_info)
20.560 +{
20.561 + GMythRecorded recorded;
20.562 + MemoryStruct chunk;
20.563 +
20.564 + chunk.memory = NULL;
20.565 + chunk.size = 0;
20.566 +
20.567 + GString *command = g_string_new("");
20.568 +
20.569 + g_string_printf(command, "GetRecorded");
20.570 +
20.571 + chunk = gmyth_http_request(backend_info, command);
20.572 + if (chunk.memory != NULL) {
20.573 + xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory));
20.574 +
20.575 + getRecorded(doc, &recorded);
20.576 + free(chunk.memory);
20.577 + }
20.578 +
20.579 + return recorded;
20.580 +}
20.581 +
20.582 +
20.583 +
20.584 +/** Function to retrieve jobqueue status
20.585 + *
20.586 + */
20.587 +gint
20.588 +gmyth_http_retrieve_job_status(GMythBackendInfo * backend_info,
20.589 + gint chanid, GTimeVal * start)
20.590 +{
20.591 + gint status = 0;
20.592 + gint count = 0;
20.593 + gint temp_chanid = 0;
20.594 + GTimeVal *temp_start = NULL;
20.595 + int i;
20.596 +
20.597 + xmlXPathObjectPtr result;
20.598 + xmlNodeSetPtr nodeset;
20.599 + xmlNodePtr node;
20.600 + MemoryStruct chunk;
20.601 +
20.602 + chunk.memory = NULL;
20.603 + chunk.size = 0;
20.604 +
20.605 + GString *command = g_string_new("");
20.606 +
20.607 + g_string_printf(command, "GetStatus");
20.608 +
20.609 + chunk = gmyth_http_request(backend_info, command);
20.610 +
20.611 + if (chunk.memory != NULL) {
20.612 + xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory));
20.613 +
20.614 + result = getXPath((xmlChar *) "/Status/JobQueue", doc);
20.615 + if (result) {
20.616 + nodeset = result->nodesetval;
20.617 + node = nodeset->nodeTab[0];
20.618 + sscanf((char *) xmlGetProp(node, (xmlChar *) "count"),
20.619 + "%d", &count);
20.620 +
20.621 + if (count > 0) {
20.622 +
20.623 + // Get the first child
20.624 + node = node->children->next;
20.625 +
20.626 + for (i = 0; i < count; i++) {
20.627 +
20.628 + sscanf((char *)
20.629 + xmlGetProp(node, (xmlChar *) "chanId"), "%d",
20.630 + &temp_chanid);
20.631 +
20.632 + if (chanid == temp_chanid) {
20.633 + temp_start = gmyth_util_string_to_time_val((char *)
20.634 + xmlGetProp
20.635 + (node,
20.636 + (xmlChar
20.637 + *)
20.638 + "startTime"));
20.639 +
20.640 + if ((temp_start->tv_sec == start->tv_sec) &&
20.641 + (temp_start->tv_usec == start->tv_usec))
20.642 + sscanf((char *)
20.643 + xmlGetProp(node,
20.644 + (xmlChar *) "status"),
20.645 + "%d", &status);
20.646 + }
20.647 + // Escape "text" node
20.648 + node = node->next->next;
20.649 + }
20.650 + }
20.651 +
20.652 + }
20.653 +
20.654 + xmlXPathFreeObject(result);
20.655 + free(chunk.memory);
20.656 +
20.657 + }
20.658 +
20.659 + return status;
20.660 +}
20.661 +
20.662 +
20.663 +
20.664 +/** Function to retrieve settings on the backend
20.665 + *
20.666 + * @param backend_info infos about the backend
20.667 + * @param key the key you want to retrieve
20.668 + * @param hostname the hostname that the key is set up
20.669 + * @return the value of the key
20.670 + */
20.671 +gchar *
20.672 +gmyth_http_retrieve_setting(GMythBackendInfo * backend_info,
20.673 + gchar * key, gchar * hostname)
20.674 +{
20.675 + xmlXPathObjectPtr result;
20.676 + xmlNodeSetPtr nodeset;
20.677 + xmlChar *keyword;
20.678 + MemoryStruct chunk;
20.679 + gchar *value = NULL;
20.680 +
20.681 + chunk.memory = NULL;
20.682 + chunk.size = 0;
20.683 +
20.684 + GString *command = g_string_new("");
20.685 +
20.686 + g_string_printf(command, "GetSetting?Key=%s&HostName=%s&Default=NULL",
20.687 + key, hostname);
20.688 +
20.689 + chunk = gmyth_http_request(backend_info, command);
20.690 +
20.691 + if (chunk.memory != NULL) {
20.692 + xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory));
20.693 +
20.694 + result = getXPath((xmlChar *) "/GetSettingResponse/Values/*", doc);
20.695 +
20.696 + if (result) {
20.697 + nodeset = result->nodesetval;
20.698 + keyword = (xmlChar *) nodeset->nodeTab[0]->name;
20.699 + if (g_ascii_strcasecmp((char *) keyword, "Value") == 0) {
20.700 + // Here we have the value
20.701 + value = (gchar *) nodeset->nodeTab[0]->children->content;
20.702 + }
20.703 + xmlXPathFreeObject(result);
20.704 + }
20.705 +
20.706 + free(chunk.memory);
20.707 + }
20.708 +
20.709 + return value;
20.710 +}
20.711 +
20.712 +/** Common steps for rec_profile's functions
20.713 + *
20.714 + * @param backend_info infos about the backend
20.715 + * @param id the profile's id that you want to delete
20.716 + * @return 0 if OK
20.717 + */
20.718 +gint
20.719 +rec_profile_common(GMythBackendInfo * backend_info, GString * command)
20.720 +{
20.721 + xmlXPathObjectPtr result;
20.722 + xmlNodeSetPtr nodeset;
20.723 + xmlChar *keyword;
20.724 + MemoryStruct chunk;
20.725 +
20.726 + chunk.memory = NULL;
20.727 + chunk.size = 0;
20.728 +
20.729 + int ret = -1;
20.730 +
20.731 + chunk = gmyth_http_request(backend_info, command);
20.732 +
20.733 + if (chunk.memory != NULL) {
20.734 + xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory));
20.735 +
20.736 + result = getXPath((xmlChar *) "/*", doc);
20.737 +
20.738 + if (result) {
20.739 + nodeset = result->nodesetval;
20.740 + keyword = (xmlChar *) nodeset->nodeTab[0]->name;
20.741 +
20.742 + if (g_ascii_strcasecmp((char *) keyword, "Success") == 0)
20.743 + ret = 0;
20.744 +
20.745 + xmlXPathFreeObject(result);
20.746 + }
20.747 +
20.748 + free(chunk.memory);
20.749 + }
20.750 +
20.751 + return ret;
20.752 +}
20.753 +
20.754 +
20.755 +/** Function to delete recording profiles
20.756 + *
20.757 + * @param backend_info infos about the backend
20.758 + * @param id the profile's id that you want to delete
20.759 + * @return 0 if OK
20.760 + */
20.761 +gint
20.762 +gmyth_http_del_rec_profile(GMythBackendInfo * backend_info, gint id)
20.763 +{
20.764 +
20.765 + GString *command = g_string_new("");
20.766 +
20.767 + g_string_printf(command, "delRecProfiles?id=%d", id);
20.768 +
20.769 +
20.770 + return rec_profile_common(backend_info, command);
20.771 +}
20.772 +
20.773 +/** Function to create recording profiles
20.774 + *
20.775 + * @param backend_info infos about the backend
20.776 + * @param profilename the name of profile you want to use
20.777 + * @param groupname the name of groupname you want to use
20.778 + * @param vcodec the name of the video codec you want to use
20.779 + * @param acodec the name of the audo codec you want to use
20.780 + * @return 0 if OK
20.781 + */
20.782 +gint
20.783 +gmyth_http_create_rec_profile(GMythBackendInfo * backend_info,
20.784 + GMythRecProfile * profile)
20.785 +{
20.786 +
20.787 + if (profile->name != NULL && profile->group != NULL &&
20.788 + profile->vcodec && profile->acodec && profile->options != NULL) {
20.789 + GString *command = g_string_new("");
20.790 +
20.791 + g_string_printf(command, "createRecProfiles?profilename=%s&"
20.792 + "groupname=%s&vcodec=%s&acodec=%s&"
20.793 + "transcodelossless=%d&transcoderesize=%d&"
20.794 + "width=%d&height=%d&rtjpegquality=%d&"
20.795 + "rtjpeglumafilter=%d&rtjpegchromafilter=%d&"
20.796 + "mpeg4bitrate=%d&mpeg4maxquality=%d&"
20.797 + "mpeg4minquality=%d&mpeg4qualdiff=%d&"
20.798 + "mpeg4scalebitrate=%d&mpeg4optionvhq=%d&"
20.799 + "mpeg4option4mv=%d&mpeg4optionidct=%d&"
20.800 + "mpeg4optionime=%d&hardwaremjpegquality=%d&"
20.801 + "hardwaremjpeghdecimation=%d&hardwaremjpegvdecimation=%d&"
20.802 + "mpeg2streamtype=%s&mpeg2aspectratio=%s&"
20.803 + "mpeg2bitrate=%d&mpeg2maxbitrate=%d&"
20.804 + "samplerate=%d&mp3quality=%d&"
20.805 + "volume=%d&mpeg2audtype=%s&"
20.806 + "mpeg2audbitratel1=%d&mpeg2audbitratel2=%d&"
20.807 + "mpeg2audvolume=%d",
20.808 + profile->name, profile->group,
20.809 + profile->vcodec, profile->acodec,
20.810 + profile->options->transcodelossless,
20.811 + profile->options->transcoderesize,
20.812 + profile->options->width,
20.813 + profile->options->height,
20.814 + profile->options->rtjpegquality,
20.815 + profile->options->rtjpeglumafilter,
20.816 + profile->options->rtjpegchromafilter,
20.817 + profile->options->mpeg4bitrate,
20.818 + profile->options->mpeg4maxquality,
20.819 + profile->options->mpeg4minquality,
20.820 + profile->options->mpeg4qualdiff,
20.821 + profile->options->mpeg4scalebitrate,
20.822 + profile->options->mpeg4optionvhq,
20.823 + profile->options->mpeg4option4mv,
20.824 + profile->options->mpeg4optionidct,
20.825 + profile->options->mpeg4optionime,
20.826 + profile->options->hardwaremjpegquality,
20.827 + profile->options->hardwaremjpeghdecimation,
20.828 + profile->options->hardwaremjpegvdecimation,
20.829 + profile->options->mpeg2streamtype,
20.830 + profile->options->mpeg2aspectratio,
20.831 + profile->options->mpeg2bitrate,
20.832 + profile->options->mpeg2maxbitrate,
20.833 + profile->options->samplerate,
20.834 + profile->options->mp3quality,
20.835 + profile->options->volume,
20.836 + profile->options->mpeg2audtype,
20.837 + profile->options->mpeg2audbitratel1,
20.838 + profile->options->mpeg2audbitratel2,
20.839 + profile->options->mpeg2audvolume);
20.840 +
20.841 +
20.842 + return rec_profile_common(backend_info, command);
20.843 + } else
20.844 + return -1;
20.845 +}
20.846 +
20.847 +/** Function to retrieve recording profiles
20.848 + *
20.849 + * @param backend_info infos about the backend
20.850 + * @param groupname the name of group you want to retrieve
20.851 + * @return the list of profiles
20.852 + */
20.853 +GSList *
20.854 +gmyth_http_retrieve_rec_profiles(GMythBackendInfo * backend_info,
20.855 + gchar * groupname)
20.856 +{
20.857 + xmlXPathObjectPtr result;
20.858 + xmlNodeSetPtr nodeset;
20.859 + xmlChar *keyword;
20.860 + MemoryStruct chunk;
20.861 + GSList *profiles = NULL;
20.862 +
20.863 + chunk.memory = NULL;
20.864 + chunk.size = 0;
20.865 +
20.866 + GString *command = g_string_new("");
20.867 +
20.868 + g_string_printf(command, "GetRecProfiles?groupname=%s", groupname);
20.869 +
20.870 + chunk = gmyth_http_request(backend_info, command);
20.871 +
20.872 + if (chunk.memory != NULL) {
20.873 + xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory));
20.874 +
20.875 + result = getXPath((xmlChar *) "/*", doc);
20.876 +
20.877 + if (result) {
20.878 + nodeset = result->nodesetval;
20.879 + keyword = (xmlChar *) nodeset->nodeTab[0]->name;
20.880 +
20.881 + if (g_ascii_strcasecmp((char *) keyword, "Profiles") == 0) {
20.882 + xmlNodePtr node = nodeset->nodeTab[0]->children->next;
20.883 + GMythRecProfile *profile;
20.884 +
20.885 + while (node != NULL) {
20.886 + if (g_ascii_strcasecmp((char *) node->name, "text") !=
20.887 + 0) {
20.888 + profile = gmyth_recprofile_new();
20.889 +
20.890 + sscanf((char *) xmlGetProp(node, (xmlChar *)
20.891 + "id"), "%d",
20.892 + &(profile->id));
20.893 +
20.894 + profile->name = g_strdup((char *)
20.895 + xmlGetProp(node,
20.896 + (xmlChar *)
20.897 + "name"));
20.898 +
20.899 + profile->vcodec = g_strdup((char *)
20.900 + xmlGetProp(node,
20.901 + (xmlChar *)
20.902 + "vcodec"));
20.903 +
20.904 + profile->acodec = g_strdup((char *)
20.905 + xmlGetProp(node,
20.906 + (xmlChar *)
20.907 + "acodec"));
20.908 +
20.909 + profile->group = g_strdup(groupname);
20.910 +
20.911 + profiles = g_slist_append(profiles, profile);
20.912 + }
20.913 + node = node->next;
20.914 + }
20.915 +
20.916 + }
20.917 + xmlXPathFreeObject(result);
20.918 + }
20.919 +
20.920 + free(chunk.memory);
20.921 + }
20.922 +
20.923 + return profiles;
20.924 +}
20.925 +
20.926 +
20.927 +
20.928 +/*
20.929 + * Aux functions got from libcurl
20.930 + */
20.931 +void *
20.932 +myrealloc(void *ptr, size_t size)
20.933 +{
20.934 + /*
20.935 + * There might be a realloc() out there that doesn't like reallocing
20.936 + * NULL pointers, so we take care of it here
20.937 + */
20.938 + if (ptr)
20.939 + return realloc(ptr, size);
20.940 + else
20.941 + return malloc(size);
20.942 +}
20.943 +
20.944 +size_t
20.945 +WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
20.946 +{
20.947 + size_t realsize = size * nmemb;
20.948 + MemoryStruct *mem = (struct _MemoryStruct *) data;
20.949 +
20.950 + mem->memory =
20.951 + (char *) myrealloc(mem->memory, mem->size + realsize + 1);
20.952 + if (mem->memory) {
20.953 + memcpy(&(mem->memory[mem->size]), ptr, realsize);
20.954 + mem->size += realsize;
20.955 + mem->memory[mem->size] = 0;
20.956 + }
20.957 +
20.958 + return realsize;
20.959 +}
20.960 +
20.961 +
20.962 +/** Send HTTP Command and receives the result of it
20.963 + *
20.964 + * @return A string with the response from the server
20.965 + * NULL if there is no response.
20.966 + */
20.967 +MemoryStruct
20.968 +gmyth_http_request(GMythBackendInfo * backend_info, GString * command)
20.969 +{
20.970 + LIBXML_TEST_VERSION
20.971 + size_t size =
20.972 + strlen(backend_info->hostname) + strlen(command->str) + 20;
20.973 +
20.974 + gchar *URL = (gchar *) g_malloc(sizeof(gchar) * size);
20.975 + gchar *mid = (gchar *) g_malloc(sizeof(gchar) * 6);
20.976 +
20.977 + mid = "";
20.978 +
20.979 + if (g_ascii_strcasecmp(command->str, "GetStatus") &&
20.980 + g_ascii_strcasecmp(command->str, "GetStatusHTML")) {
20.981 + mid = "Myth/";
20.982 + }
20.983 +
20.984 + g_snprintf(URL, size, "http://%s:%d/%s%s",
20.985 + backend_info->hostname, backend_info->status_port, mid,
20.986 + command->str);
20.987 +
20.988 + CURL *curl_handle;
20.989 +
20.990 + MemoryStruct chunk;
20.991 +
20.992 + chunk.memory = NULL; /* we expect realloc(NULL, size) to work */
20.993 + chunk.size = 0; /* no data at this point */
20.994 +
20.995 + curl_global_init(CURL_GLOBAL_ALL);
20.996 +
20.997 + /*
20.998 + * init the curl session
20.999 + */
20.1000 + curl_handle = curl_easy_init();
20.1001 +
20.1002 + /*
20.1003 + * specify URL to get
20.1004 + */
20.1005 + curl_easy_setopt(curl_handle, CURLOPT_URL, URL);
20.1006 +
20.1007 + /*
20.1008 + * send all data to this function
20.1009 + */
20.1010 + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION,
20.1011 + WriteMemoryCallback);
20.1012 +
20.1013 + /*
20.1014 + * we pass our 'chunk' struct to the callback function
20.1015 + */
20.1016 + curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &chunk);
20.1017 +
20.1018 + /*
20.1019 + * some servers don't like requests that are made without a user-agent
20.1020 + * field, so we provide one
20.1021 + */
20.1022 + curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
20.1023 +
20.1024 + /*
20.1025 + * set timeout
20.1026 + */
20.1027 + curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 20);
20.1028 +
20.1029 + /*
20.1030 + * get it!
20.1031 + */
20.1032 + curl_easy_perform(curl_handle);
20.1033 +
20.1034 + /*
20.1035 + * cleanup curl stuff
20.1036 + */
20.1037 + curl_easy_cleanup(curl_handle);
20.1038 +
20.1039 + return chunk;
20.1040 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/gmyth/gmyth/gmyth_http.h Mon Feb 25 17:51:43 2008 +0000
21.3 @@ -0,0 +1,204 @@
21.4 +/**
21.5 + * GMyth Library
21.6 + *
21.7 + * @file gmyth/gmyth_http.h
21.8 + *
21.9 + * @brief <p> GMythHttp library provides a wrapper to access
21.10 + * data from the database using http+xml
21.11 + *
21.12 + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
21.13 + * @author Artur Duque de Souza <artur.souza@indt.org.br>
21.14 + *
21.15 + *
21.16 + * This program is free software; you can redistribute it and/or modify
21.17 + * it under the terms of the GNU Lesser General Public License as published by
21.18 + * the Free Software Foundation; either version 2 of the License, or
21.19 + * (at your option) any later version.
21.20 + *
21.21 + * This program is distributed in the hope that it will be useful,
21.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
21.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21.24 + * GNU General Public License for more details.
21.25 + *
21.26 + * You should have received a copy of the GNU Lesser General Public License
21.27 + * along with this program; if not, write to the Free Software
21.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21.29 + */
21.30 +
21.31 +#ifndef __GMYTH_HTTP_H__
21.32 +#define __GMYTH_HTTP_H__
21.33 +
21.34 +#include <glib-object.h>
21.35 +
21.36 +#include <stdio.h>
21.37 +#include <stdlib.h>
21.38 +#include <string.h>
21.39 +#include <stdarg.h>
21.40 +#include <glib.h>
21.41 +#include <glib/gprintf.h>
21.42 +
21.43 +#include "gmyth_backendinfo.h"
21.44 +#include "gmyth_util.h"
21.45 +#include "gmyth_recprofile.h"
21.46 +
21.47 +#include <curl/curl.h>
21.48 +#include <curl/types.h>
21.49 +#include <curl/easy.h>
21.50 +
21.51 +G_BEGIN_DECLS
21.52 +#define MYTH_PORT_STATUS 6544
21.53 +#define JOB_UNKNOWN 0x0000
21.54 +#define JOB_QUEUED 0x0001
21.55 +#define JOB_PENDING 0x0002
21.56 +#define JOB_STARTING 0x0003
21.57 +#define JOB_RUNNING 0x0004
21.58 +#define JOB_STOPPING 0x0005
21.59 +#define JOB_PAUSED 0x0006
21.60 +#define JOB_RETRY 0x0007
21.61 +#define JOB_ERRORING 0x0008
21.62 +#define JOB_ABORTING 0x0009
21.63 + // JOB_DONE is a mask to indicate the job is done
21.64 + // whatever the status is
21.65 +#define JOB_DONE 0x0100
21.66 +#define JOB_FINISHED 0x0110
21.67 +#define JOB_ABORTED 0x0120
21.68 +#define JOB_ERRORED 0x0130
21.69 +#define JOB_CANCELLED 0x0140
21.70 +typedef struct _GMythRecorded_Recording GMythRecorded_Recording;
21.71 +typedef struct _GMythRecorded_Channel GMythRecorded_Channel;
21.72 +typedef struct _GMythRecorded_Program GMythRecorded_Program;
21.73 +typedef struct _GMythRecorded GMythRecorded;
21.74 +typedef struct _GMythProgram GMythProgram;
21.75 +typedef struct _GMythChannel GMythChannel;
21.76 +typedef struct _GMythEpg GMythEpg;
21.77 +typedef struct _MemoryStruct MemoryStruct;
21.78 +
21.79 +struct _MemoryStruct {
21.80 + char *memory;
21.81 + size_t size;
21.82 +};
21.83 +
21.84 +struct _GMythProgram {
21.85 + gchar *title;
21.86 + gchar *subtitle;
21.87 + gchar *catType;
21.88 + gchar *category;
21.89 + gint repeat;
21.90 + GTimeVal *startTime;
21.91 + GTimeVal *endTime;
21.92 +};
21.93 +
21.94 +struct _GMythChannel {
21.95 + gchar *channelName;
21.96 + gchar *chanNum;
21.97 + gint chanId;
21.98 + gint callSign;
21.99 + GSList *programList;
21.100 +};
21.101 +
21.102 +struct _GMythEpg {
21.103 + gint startChanId;
21.104 + gint endChanId;
21.105 + gchar *version;
21.106 + gint protoVer;
21.107 + gint totalCount;
21.108 + gint numOfChannels;
21.109 + GTimeVal *asOf;
21.110 + GTimeVal *startTime;
21.111 + GTimeVal *endTime;
21.112 + gint details;
21.113 + GSList *channelList;
21.114 +};
21.115 +
21.116 +
21.117 +struct _GMythRecorded_Recording {
21.118 + gint dupInType;
21.119 + gint dupMethod;
21.120 + gchar *playGroup;
21.121 + gchar *recGroup;
21.122 + gchar *recProfile;
21.123 + gint recPriority;
21.124 + gint recStatus;
21.125 + gint encoderId;
21.126 + gint recordId;
21.127 + gint recType;
21.128 + GTimeVal *recStartTs;
21.129 + GTimeVal *recEndTs;
21.130 +};
21.131 +
21.132 +
21.133 +struct _GMythRecorded_Channel {
21.134 + gchar *chanFilters;
21.135 + gchar *channelName;
21.136 + gint chanNum;
21.137 + gint sourceId;
21.138 + gint commFree;
21.139 + gint inputId;
21.140 + gint chanId;
21.141 + gint callSign;
21.142 +};
21.143 +
21.144 +
21.145 +struct _GMythRecorded_Program {
21.146 + gint programFlags;
21.147 + gchar *title;
21.148 + gint programId;
21.149 + gchar *catType;
21.150 + gchar *category;
21.151 + gint seriesId;
21.152 + GTimeVal *startTime;
21.153 + GTimeVal *endTime;
21.154 + GTimeVal *airdate; // ?
21.155 + GTimeVal *lastModified;
21.156 + gchar *subTitle;
21.157 + gint stars;
21.158 + gint repeat;
21.159 + gint fileSize;
21.160 + gchar *hostname;
21.161 + GMythRecorded_Channel channel;
21.162 + GMythRecorded_Recording recording;
21.163 +};
21.164 +
21.165 +struct _GMythRecorded {
21.166 + gchar *version;
21.167 + gint protoVer;
21.168 + gint totalCount;
21.169 + GTimeVal *asOf;
21.170 + GSList *programList;
21.171 +};
21.172 +
21.173 +
21.174 +gint gmyth_http_retrieve_job_status(GMythBackendInfo *
21.175 + backend_info, gint chanid,
21.176 + GTimeVal * start);
21.177 +
21.178 +gchar *gmyth_http_retrieve_setting(GMythBackendInfo *
21.179 + backend_info, gchar * key,
21.180 + gchar * hostname);
21.181 +
21.182 +GMythEpg gmyth_http_retrieve_epg(GMythBackendInfo * backend_info,
21.183 + GTimeVal * StartTime,
21.184 + GTimeVal * EndTime,
21.185 + gint StartChanId,
21.186 + gint NumOfChannels,
21.187 + gchar * Details);
21.188 +
21.189 +GMythRecorded gmyth_http_retrieve_recorded(GMythBackendInfo *
21.190 + backend_info);
21.191 +
21.192 +GSList *gmyth_http_retrieve_rec_profiles(GMythBackendInfo *
21.193 + backend_info,
21.194 + gchar * groupname);
21.195 +
21.196 +gint gmyth_http_create_rec_profile(GMythBackendInfo *
21.197 + backend_info,
21.198 + GMythRecProfile * profile);
21.199 +
21.200 +gint gmyth_http_del_rec_profile(GMythBackendInfo * backend_info,
21.201 + gint id);
21.202 +
21.203 +MemoryStruct gmyth_http_request(GMythBackendInfo * backend_info,
21.204 + GString * command);
21.205 +
21.206 +G_END_DECLS
21.207 +#endif /* __GMYTH_HTTP_H__ */
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/gmyth/gmyth/gmyth_jobqueue.c Mon Feb 25 17:51:43 2008 +0000
22.3 @@ -0,0 +1,200 @@
22.4 +/**
22.5 + * GMyth Library
22.6 + *
22.7 + * @file gmyth/gmyth_jobqueue.c
22.8 + *
22.9 + * @brief <p> Library to use JobQueue from mythbackend
22.10 + *
22.11 + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
22.12 + * @author Artur Duque de Souza <artur.souza@indt.org.br>
22.13 + *
22.14 + *
22.15 + * This program is free software; you can redistribute it and/or modify
22.16 + * it under the terms of the GNU Lesser General Public License as published by
22.17 + * the Free Software Foundation; either version 2 of the License, or
22.18 + * (at your option) any later version.
22.19 + *
22.20 + * This program is distributed in the hope that it will be useful,
22.21 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
22.22 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22.23 + * GNU General Public License for more details.
22.24 + *
22.25 + * You should have received a copy of the GNU Lesser General Public License
22.26 + * along with this program; if not, write to the Free Software
22.27 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22.28 + */
22.29 +
22.30 +#ifdef HAVE_CONFIG_H
22.31 +#include "config.h"
22.32 +#endif
22.33 +
22.34 +#include "gmyth_jobqueue.h"
22.35 +#include "gmyth_http.h"
22.36 +#include "gmyth_debug.h"
22.37 +#include "gmyth_socket.h"
22.38 +
22.39 +/** Function to connect
22.40 + *
22.41 + * @param backend_info the backendinfo
22.42 + * @return gboolean - result of connection
22.43 + *
22.44 + */
22.45 +static GMythSocket *
22.46 +backend_connect(GMythBackendInfo * backend_info)
22.47 +{
22.48 + GMythSocket *socket = gmyth_socket_new();
22.49 +
22.50 + if (gmyth_socket_connect_to_backend(socket,
22.51 + gmyth_backend_info_get_hostname
22.52 + (backend_info),
22.53 + gmyth_backend_info_get_port
22.54 + (backend_info), TRUE) == TRUE) {
22.55 + gmyth_debug("Backend socket connection success");
22.56 + return socket;
22.57 + } else {
22.58 + gmyth_debug("Connection failed");
22.59 + return NULL;
22.60 + }
22.61 +}
22.62 +
22.63 +
22.64 +/** Function to send a command to the backend
22.65 + *
22.66 + * @param socket pointer to a socket
22.67 + * @param action the action itself
22.68 + * @param job the action itself
22.69 + * @param chanid the action itself
22.70 + * @param starttime the action itself
22.71 + * @param options the action itself
22.72 + * @return the value returned by the backend
22.73 + *
22.74 + */
22.75 +static gchar *
22.76 +send_command(GMythSocket * socket, gchar * action,
22.77 + gchar * job, gint chanid, gchar * starttime, gchar * options)
22.78 +{
22.79 + GString *command = g_string_new("");
22.80 + GString *ret_str;
22.81 + gchar *ret;
22.82 +
22.83 + GMythStringList *retlist = gmyth_string_list_new();
22.84 +
22.85 + g_string_printf(command, "JOBQUEUE %s %s %d %s %s", action, job,
22.86 + chanid, starttime, options);
22.87 +
22.88 + gmyth_string_list_append_string(retlist, command);
22.89 + gmyth_socket_write_stringlist(socket, retlist);
22.90 +
22.91 + // receive answer
22.92 + gmyth_socket_read_stringlist(socket, retlist);
22.93 + ret_str = gmyth_string_list_get_string(retlist, 0);
22.94 +
22.95 + // ret = ret_str->str;
22.96 + ret = g_string_free(ret_str, FALSE);
22.97 + g_string_free(command, TRUE);
22.98 +
22.99 + gmyth_string_list_clear_all(retlist);
22.100 + g_object_unref(retlist);
22.101 +
22.102 + return ret;
22.103 +}
22.104 +
22.105 +
22.106 +/** Function to analyze the response from the backend
22.107 + *
22.108 + * @param ret the msg returned by the backend
22.109 + * @param value the expected value
22.110 + * @return 0 if success and -1 if error
22.111 + *
22.112 + */
22.113 +static gboolean
22.114 +test_result(gchar * ret, gchar * value)
22.115 +{
22.116 + if (g_ascii_strcasecmp(ret, value) == 0) {
22.117 + return TRUE;
22.118 + } else {
22.119 + gmyth_debug("JobQueue Error: %s", ret);
22.120 + return FALSE;
22.121 + }
22.122 +}
22.123 +
22.124 +/** Function to add a job inside JOBQUEUE
22.125 + *
22.126 + * @param transcode object holding all the info about the transcoding
22.127 + * @param job the job you want to add the action
22.128 + * @return TRUE if the job was added, FALSE if not
22.129 + *
22.130 + */
22.131 +gboolean
22.132 +gmyth_jobqueue_add_job(GMythTranscoder * transcode, gchar * job)
22.133 +{
22.134 + GMythSocket *socket = backend_connect(transcode->backend_info);
22.135 + gboolean res = FALSE;
22.136 +
22.137 + if (socket != NULL) {
22.138 + GString *options = g_string_new("");
22.139 + gchar *ret = NULL;
22.140 +
22.141 + if (g_ascii_strcasecmp(job, "JOB_TRANSCODE") == 0) {
22.142 + if (transcode->cutlist)
22.143 + g_string_append(options, " JOB_USE_CUTLIST");
22.144 +
22.145 + if (transcode->output)
22.146 + g_string_append_printf(options, " JOB_OUTPUT %s",
22.147 + transcode->output_filename);
22.148 +
22.149 + if (transcode->profile != NULL)
22.150 + g_string_append_printf(options, " %s", transcode->profile);
22.151 + }
22.152 + ret = send_command(socket, "ADD", job, transcode->chanid,
22.153 + transcode->starttime, options->str);
22.154 + res = test_result(ret, "JOBQUEUE_OK");
22.155 + gmyth_socket_close_connection(socket);
22.156 +
22.157 + g_object_unref(socket);
22.158 +
22.159 + g_string_free(options, TRUE);
22.160 +
22.161 + if (ret)
22.162 + g_free(ret);
22.163 +
22.164 + } else {
22.165 + gmyth_debug("JobQueue Connection Failed");
22.166 + }
22.167 +
22.168 + return res;
22.169 +}
22.170 +
22.171 +/** Function to change a job cmd inside JOBQUEUE
22.172 + *
22.173 + * @param transcode object holding all the info about the transcoding
22.174 + * @param action the action (ADD)
22.175 + * @param job the job you want to add the action
22.176 + * @return the value of the key
22.177 + *
22.178 + */
22.179 +gboolean
22.180 +gmyth_jobqueue_change_cmd(GMythTranscoder * transcode, gchar * action,
22.181 + gchar * job)
22.182 +{
22.183 + GMythSocket *socket = backend_connect(transcode->backend_info);
22.184 + gboolean res = FALSE;
22.185 +
22.186 + if (socket != NULL) {
22.187 + gchar *ret = send_command(socket, action, job,
22.188 + transcode->chanid,
22.189 + transcode->starttime, "");
22.190 +
22.191 + res = test_result(ret, "JOBQUEUE_CHANGED_CMD_OK");
22.192 +
22.193 + gmyth_socket_close_connection(socket);
22.194 + g_object_unref(socket);
22.195 +
22.196 + g_free(ret);
22.197 +
22.198 + } else {
22.199 + gmyth_debug("JobQueue Connection Failed");
22.200 + }
22.201 +
22.202 + return res;
22.203 +}
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/gmyth/gmyth/gmyth_jobqueue.h Mon Feb 25 17:51:43 2008 +0000
23.3 @@ -0,0 +1,52 @@
23.4 +/**
23.5 + * GMyth Library
23.6 + *
23.7 + * @file gmyth/gmyth_jobqueue.h
23.8 + *
23.9 + * @brief <p> Library to use JobQueue from mythbackend
23.10 + *
23.11 + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
23.12 + * @author Artur Duque de Souza <artur.souza@indt.org.br>
23.13 + *
23.14 + *
23.15 + * This program is free software; you can redistribute it and/or modify
23.16 + * it under the terms of the GNU Lesser General Public License as published by
23.17 + * the Free Software Foundation; either version 2 of the License, or
23.18 + * (at your option) any later version.
23.19 + *
23.20 + * This program is distributed in the hope that it will be useful,
23.21 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
23.22 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23.23 + * GNU General Public License for more details.
23.24 + *
23.25 + * You should have received a copy of the GNU Lesser General Public License
23.26 + * along with this program; if not, write to the Free Software
23.27 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23.28 + */
23.29 +
23.30 +#ifndef __GMYTH_JOBQUEUE_H__
23.31 +#define __GMYTH_JOBQUEUE_H__
23.32 +
23.33 +#include <glib-object.h>
23.34 +
23.35 +#include <stdio.h>
23.36 +#include <stdlib.h>
23.37 +#include <string.h>
23.38 +#include <stdarg.h>
23.39 +#include <glib.h>
23.40 +#include <glib/gprintf.h>
23.41 +
23.42 +#include "gmyth_stringlist.h"
23.43 +#include "gmyth_backendinfo.h"
23.44 +#include "gmyth_transcoder.h"
23.45 +#include "gmyth_socket.h"
23.46 +#include "gmyth_util.h"
23.47 +
23.48 +G_BEGIN_DECLS
23.49 + gboolean gmyth_jobqueue_add_job(GMythTranscoder * transcoder,
23.50 + gchar * job);
23.51 +gboolean gmyth_jobqueue_change_cmd(GMythTranscoder * transcoder,
23.52 + gchar * action, gchar * job);
23.53 +
23.54 +G_END_DECLS
23.55 +#endif /* __GMYTH_JOBQUEUE_H__ */
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/gmyth/gmyth/gmyth_livetv.c Mon Feb 25 17:51:43 2008 +0000
24.3 @@ -0,0 +1,980 @@
24.4 +/**
24.5 + * GMyth Library
24.6 + *
24.7 + * @file gmyth/gmyth_livetv.c
24.8 + *
24.9 + * @brief <p> GMythLiveTV starts a remote TV session with the MythTV backend.
24.10 + *
24.11 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
24.12 + * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
24.13 + *
24.14 + *
24.15 + * This program is free software; you can redistribute it and/or modify
24.16 + * it under the terms of the GNU Lesser General Public License as published by
24.17 + * the Free Software Foundation; either version 2 of the License, or
24.18 + * (at your option) any later version.
24.19 + *
24.20 + * This program is distributed in the hope that it will be useful,
24.21 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
24.22 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24.23 + * GNU General Public License for more details.
24.24 + *
24.25 + * You should have received a copy of the GNU Lesser General Public License
24.26 + * along with this program; if not, write to the Free Software
24.27 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24.28 + */
24.29 +
24.30 +#ifdef HAVE_CONFIG_H
24.31 +#include "config.h"
24.32 +#endif
24.33 +
24.34 +#include "gmyth_livetv.h"
24.35 +#include "gmyth_remote_util.h"
24.36 +#include "gmyth_tvchain.h"
24.37 +#include "gmyth_socket.h"
24.38 +#include "gmyth_backendinfo.h"
24.39 +#include "gmyth_debug.h"
24.40 +
24.41 +#include "gmyth_file.h"
24.42 +#include "gmyth_file_transfer.h"
24.43 +#include "gmyth_file_local.h"
24.44 +#include "gmyth_monitor_handler.h"
24.45 +
24.46 +#include "gmyth_common.h"
24.47 +#include "gmyth_util.h"
24.48 +
24.49 +static void gmyth_livetv_class_init(GMythLiveTVClass * klass);
24.50 +static void gmyth_livetv_init(GMythLiveTV * object);
24.51 +
24.52 +static void gmyth_livetv_dispose(GObject * object);
24.53 +static void gmyth_livetv_finalize(GObject * object);
24.54 +
24.55 +static gint tvchain_curr_index = -1;
24.56 +
24.57 +/*
24.58 + * static GStaticMutex lock = G_STATIC_MUTEX_INIT;
24.59 + */
24.60 +
24.61 +#define GMYTHTV_TRANSFER_MAX_WAITS 100
24.62 +
24.63 +G_DEFINE_TYPE(GMythLiveTV, gmyth_livetv, G_TYPE_OBJECT)
24.64 + static void gmyth_livetv_class_init(GMythLiveTVClass * klass)
24.65 +{
24.66 + GObjectClass *gobject_class;
24.67 +
24.68 + gobject_class = (GObjectClass *) klass;
24.69 +
24.70 + gobject_class->dispose = gmyth_livetv_dispose;
24.71 + gobject_class->finalize = gmyth_livetv_finalize;
24.72 +}
24.73 +
24.74 +static void
24.75 +gmyth_livetv_init(GMythLiveTV * livetv)
24.76 +{
24.77 + livetv->monitor = NULL;
24.78 + livetv->backend_info = NULL;
24.79 + livetv->local_hostname = NULL;
24.80 + livetv->file = NULL;
24.81 + livetv->setup_done = FALSE;
24.82 +
24.83 + livetv->socket = NULL;
24.84 + livetv->recorder = NULL;
24.85 + livetv->tvchain = NULL;
24.86 + livetv->proginfo = NULL;
24.87 + livetv->uri = NULL;
24.88 +
24.89 + livetv->mutex = g_mutex_new();
24.90 +}
24.91 +
24.92 +static void
24.93 +gmyth_livetv_dispose(GObject * object)
24.94 +{
24.95 + GMythLiveTV *livetv = GMYTH_LIVETV(object);
24.96 +
24.97 +
24.98 + if (livetv->disposed) {
24.99 + /*
24.100 + * If dispose did already run, return.
24.101 + */
24.102 + return;
24.103 + }
24.104 +
24.105 + /*
24.106 + * Make sure dispose does not run twice.
24.107 + */
24.108 + livetv->disposed = TRUE;
24.109 +
24.110 + if (livetv->monitor != NULL) {
24.111 + g_object_unref(livetv->monitor);
24.112 + livetv->monitor = NULL;
24.113 + }
24.114 +
24.115 +
24.116 + if (livetv->file != NULL) {
24.117 + g_object_unref(livetv->file);
24.118 + livetv->file = NULL;
24.119 + }
24.120 +
24.121 + if (livetv->recorder != NULL) {
24.122 + // gmyth_recorder_close(livetv->recorder);
24.123 + g_object_unref(livetv->recorder);
24.124 + livetv->recorder = NULL;
24.125 + }
24.126 +
24.127 + if (livetv->socket != NULL) {
24.128 + g_object_unref(livetv->socket);
24.129 + livetv->socket = NULL;
24.130 + }
24.131 +
24.132 + if (livetv->tvchain != NULL) {
24.133 + g_object_unref(livetv->tvchain);
24.134 + livetv->tvchain = NULL;
24.135 + }
24.136 +
24.137 + if (livetv->proginfo != NULL) {
24.138 + g_object_unref(livetv->proginfo);
24.139 + livetv->proginfo = NULL;
24.140 + }
24.141 +
24.142 + if (livetv->backend_info != NULL) {
24.143 + g_object_unref(livetv->backend_info);
24.144 + livetv->backend_info = NULL;
24.145 + }
24.146 +
24.147 + if (livetv->uri != NULL) {
24.148 + g_object_unref(livetv->uri);
24.149 + livetv->uri = NULL;
24.150 + }
24.151 +
24.152 + if (livetv->mutex != NULL) {
24.153 + g_mutex_free(livetv->mutex);
24.154 + livetv->mutex = NULL;
24.155 + }
24.156 +
24.157 + if (livetv->local_hostname != NULL) {
24.158 + g_string_free(livetv->local_hostname, TRUE);
24.159 + livetv->local_hostname = NULL;
24.160 + }
24.161 +
24.162 + G_OBJECT_CLASS(gmyth_livetv_parent_class)->dispose(object);
24.163 +}
24.164 +
24.165 +static void
24.166 +gmyth_livetv_finalize(GObject * object)
24.167 +{
24.168 + g_signal_handlers_destroy(object);
24.169 +
24.170 + G_OBJECT_CLASS(gmyth_livetv_parent_class)->finalize(object);
24.171 +}
24.172 +
24.173 +/**
24.174 + * Creates a new GMythLiveTV instance
24.175 + *
24.176 + * @return a newly allocated GMythLiveTV instance
24.177 + */
24.178 +GMythLiveTV *
24.179 +gmyth_livetv_new(GMythBackendInfo * backend_info)
24.180 +{
24.181 + GMythLiveTV *livetv =
24.182 + GMYTH_LIVETV(g_object_new(GMYTH_LIVETV_TYPE, NULL));
24.183 +
24.184 + livetv->backend_info = backend_info;
24.185 + g_object_ref(livetv->backend_info);
24.186 +
24.187 + return livetv;
24.188 +}
24.189 +
24.190 +/**
24.191 + * The GObject signal handler function, from which all status messages
24.192 + * from the Monitor Handler will be advertized, all time it receives
24.193 + * LiveTV status messages from the MythTV backend
24.194 + *
24.195 + * @param monitor a GMythMonitorHandler instance
24.196 + * @param msg_code the MythTV's server numeric status code
24.197 + * @param message the message's string description
24.198 + * @param user_data pointer to the GMythLiveTV instance
24.199 + */
24.200 +static void
24.201 +gmyth_livetv_monitor_signal_handler(GMythMonitorHandler * monitor,
24.202 + gint msg_code, gchar * message,
24.203 + gpointer user_data)
24.204 +{
24.205 + GMythLiveTV *live_tv = GMYTH_LIVETV(user_data);
24.206 +
24.207 + gmyth_debug
24.208 + ("LIVETV Signal handler ( msg = %s, code = %d, live_tv param = %s, user_data = %s )\n",
24.209 + message, msg_code, live_tv != NULL ? "" : "NULL",
24.210 + user_data != NULL ? "" : "NULL");
24.211 +
24.212 + if (NULL == live_tv || !IS_GMYTH_FILE_TRANSFER(live_tv->file)) {
24.213 + gmyth_debug("LiveTV_obj is equals to NULL!!!");
24.214 + return;
24.215 + }
24.216 +
24.217 + switch (msg_code) {
24.218 +
24.219 + case GMYTH_BACKEND_PROGRAM_INFO_CHANGED:
24.220 + {
24.221 + gmyth_debug
24.222 + ("LIVETV Program Changed request received [ msg = %s ]. Watching if the new "
24.223 + "TV Chain ID is the same as the old one...\n", message);
24.224 + if (g_ascii_strcasecmp
24.225 + (message,
24.226 + (gmyth_tvchain_get_id(live_tv->tvchain))->str) != 0) {
24.227 + gmyth_debug
24.228 + ("OK!!! MOVED to the next program chain [actual == %s]!",
24.229 + (gmyth_tvchain_get_id(live_tv->tvchain))->str);
24.230 + /*
24.231 + * advertises the FileTransfer about the program info
24.232 + * changed
24.233 + */
24.234 + if (live_tv->file != NULL) {
24.235 + gmyth_debug
24.236 + ("Emitting signal to the FileTransfer... [ \"program-info-changed \" ]");
24.237 +
24.238 + gmyth_file_transfer_emit_program_info_changed_signal
24.239 + (GMYTH_FILE_TRANSFER(live_tv->file), msg_code,
24.240 + (gpointer) (live_tv->recorder));
24.241 +
24.242 + /*
24.243 + * gmyth_livetv_monitor_handler_stop( live_tv );
24.244 + */
24.245 + } else
24.246 + gmyth_debug
24.247 + ("LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n");
24.248 + }
24.249 + break;
24.250 + }
24.251 + case GMYTH_BACKEND_DONE_RECORDING:
24.252 + {
24.253 + gmyth_debug
24.254 + ("LIVETV Program Changed request received [ msg = %s ]. Watching if the new "
24.255 + "TV Chain ID is the same as the old one...\n", message);
24.256 + if (g_ascii_strcasecmp
24.257 + (message,
24.258 + (gmyth_tvchain_get_id(live_tv->tvchain))->str) != 0) {
24.259 + gmyth_debug
24.260 + ("OK!!! MOVED to the next program chain [actual == %s]!",
24.261 + (gmyth_tvchain_get_id(live_tv->tvchain))->str);
24.262 + /*
24.263 + * advertises the FileTransfer about the program info
24.264 + * changed
24.265 + */
24.266 + if (live_tv->file != NULL) {
24.267 + gmyth_debug
24.268 + ("Emitting signal to the FileTransfer... [ \"backend-done-recording\" ]");
24.269 +
24.270 + gmyth_file_transfer_emit_program_info_changed_signal
24.271 + (GMYTH_FILE_TRANSFER(live_tv->file), msg_code,
24.272 + (gpointer) (live_tv->recorder));
24.273 +
24.274 + } else
24.275 + gmyth_debug
24.276 + ("LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n");
24.277 + }
24.278 + break;
24.279 + }
24.280 + case GMYTH_BACKEND_STOP_LIVETV:
24.281 + {
24.282 + gmyth_debug
24.283 + ("LIVETV Stop LiveTV request received [ msg = %s ]. Going out the "
24.284 + "LiveTV...\n", message);
24.285 + /*
24.286 + * stops the LiveTV
24.287 + */
24.288 + if (live_tv != NULL) {
24.289 + gmyth_debug("Going out the LiveTV... [ \"quit-livetv\" ]");
24.290 +
24.291 + g_object_unref(live_tv);
24.292 + } else
24.293 + gmyth_debug
24.294 + ("LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n");
24.295 +
24.296 + break;
24.297 + }
24.298 + default:
24.299 + break;
24.300 + } /* switch (Monitor Handler messages) */
24.301 +
24.302 +}
24.303 +
24.304 +/**
24.305 + * Starts the Monitor Handler to this GMythLiveTV session, in order
24.306 + * to receive the status messages from the MythTV's backend server
24.307 + *
24.308 + * @param live_tv the GMythLiveTV instance
24.309 + *
24.310 + * @return <code>true</code> if the Monitor Handler start-up process
24.311 + * had been concluded succcesfully
24.312 + */
24.313 +gboolean
24.314 +gmyth_livetv_monitor_handler_start(GMythLiveTV * livetv)
24.315 +{
24.316 + gboolean res = TRUE;
24.317 +
24.318 + if (livetv->monitor != NULL) {
24.319 + g_object_unref(livetv->monitor);
24.320 + livetv->monitor = NULL;
24.321 + }
24.322 +
24.323 + livetv->monitor = gmyth_monitor_handler_new();
24.324 + res =
24.325 + gmyth_monitor_handler_open(livetv->monitor,
24.326 + livetv->backend_info->hostname,
24.327 + livetv->backend_info->port);
24.328 +
24.329 + if (res == TRUE) {
24.330 + gmyth_debug
24.331 + ("Connect MythTV Monitor event socket! Trying to start the message handler...");
24.332 +
24.333 + res = gmyth_monitor_handler_start(livetv->monitor);
24.334 +
24.335 + if (res) {
24.336 + gmyth_debug
24.337 + ("MythTV Monitor event socket connected and listening!");
24.338 + g_signal_connect(G_OBJECT(livetv->monitor),
24.339 + "backend-events-handler", (GCallback)
24.340 + gmyth_livetv_monitor_signal_handler, livetv);
24.341 + } else {
24.342 + gmyth_debug
24.343 + ("Problems when trying to start MythTV Monitor event socket!");
24.344 + goto error;
24.345 + }
24.346 + }
24.347 +
24.348 + error:
24.349 + return res;
24.350 +
24.351 +}
24.352 +
24.353 +/**
24.354 + * Stops the Monitor Handler to this GMythLiveTV session, in order
24.355 + * to stop receiving the status messages from the MythTV's backend server
24.356 + *
24.357 + * @param live_tv the GMythLiveTV instance
24.358 + *
24.359 + * @return <code>true</code> if the Monitor Handler shutdown process
24.360 + * had been concluded succcesfully
24.361 + */
24.362 +void
24.363 +gmyth_livetv_monitor_handler_stop(GMythLiveTV * livetv)
24.364 +{
24.365 +
24.366 + if (livetv->monitor != NULL) {
24.367 + g_object_unref(livetv->monitor);
24.368 + livetv->monitor = NULL;
24.369 + }
24.370 +
24.371 +}
24.372 +
24.373 +#if 0
24.374 +static gchar *
24.375 +gmyth_livetv_create_remote_url(GMythLiveTV * livetv)
24.376 +{
24.377 + gchar *uri = g_strdup("");
24.378 +
24.379 + gmyth_backend_info_get_remote_h
24.380 + // gmyth_backend(livetv->backend_info)
24.381 + return uri;
24.382 +}
24.383 +#endif
24.384 +
24.385 +/**
24.386 + * Configures the GMythLiveTV session, sends SPAWN_LIVETV message,
24.387 + * sets the channel name, and gets the first program info about the
24.388 + * actual recording
24.389 + *
24.390 + * @param live_tv the GMythLiveTV instance
24.391 + * @param channel the channel name (the chan_name field, from the tvchain table)
24.392 + * @param backend_info the GMythBackendInfo describing the remote server
24.393 + *
24.394 + * @return <code>true</code> if the LiveTV's recorder instance configuration
24.395 + * had been concluded succcesfully
24.396 + */
24.397 +static gboolean
24.398 +gmyth_livetv_setup_recorder_channel_name(GMythLiveTV * livetv,
24.399 + gchar * channel)
24.400 +{
24.401 + gboolean res = TRUE;
24.402 +
24.403 + g_return_val_if_fail(livetv != NULL, FALSE);
24.404 +
24.405 + g_mutex_lock(livetv->mutex);
24.406 +
24.407 + if (livetv->socket == NULL) {
24.408 + livetv->socket = gmyth_socket_new();
24.409 + /*
24.410 + * FIME: Implement this at gmyth_socket
24.411 + */
24.412 + res =
24.413 + gmyth_socket_connect_to_backend(livetv->socket,
24.414 + livetv->backend_info->hostname,
24.415 + livetv->backend_info->port,
24.416 + TRUE);
24.417 + if (!res) {
24.418 + gmyth_debug("[%s] LiveTV can not connect to backend",
24.419 + __FUNCTION__);
24.420 + res = FALSE;
24.421 + goto error;
24.422 + }
24.423 + }
24.424 +
24.425 + livetv->is_livetv = TRUE;
24.426 +
24.427 + livetv->local_hostname = gmyth_socket_get_local_hostname();
24.428 +
24.429 + if (livetv->local_hostname == NULL) {
24.430 + g_warning("livetv could not retrieve the local hostname");
24.431 + res = FALSE;
24.432 + goto error;
24.433 + } else {
24.434 + gmyth_debug("Local hostname: %s", livetv->local_hostname->str);
24.435 + }
24.436 +
24.437 + if (livetv->recorder != NULL) {
24.438 + g_object_unref(livetv->recorder);
24.439 + livetv->recorder = NULL;
24.440 + }
24.441 +
24.442 + if (gmyth_remote_util_get_free_recorder_count(livetv->socket) <= 0) {
24.443 + gmyth_debug("No free remote encoder available.");
24.444 + res = FALSE;
24.445 + goto error;
24.446 + }
24.447 +
24.448 + /*
24.449 + * Gets the recorder num
24.450 + */
24.451 + livetv->recorder =
24.452 + remote_request_next_free_recorder(livetv->socket, -1);
24.453 + gmyth_socket_close_connection(livetv->socket);
24.454 +
24.455 + if (NULL == livetv->recorder) {
24.456 + gmyth_debug("[%s] None remote encoder available", __FUNCTION__);
24.457 + res = FALSE;
24.458 + goto error;
24.459 + }
24.460 +
24.461 + /*
24.462 + * Init remote encoder. Opens its control socket.
24.463 + */
24.464 + res = gmyth_recorder_setup(livetv->recorder);
24.465 + if (!res) {
24.466 + gmyth_debug("[%s] Fail while setting remote encoder\n",
24.467 + __FUNCTION__);
24.468 + res = FALSE;
24.469 + goto error;
24.470 + }
24.471 +
24.472 + /*
24.473 + * Creates livetv chain handler
24.474 + */
24.475 + livetv->tvchain = gmyth_tvchain_new();
24.476 + gmyth_tvchain_initialize(livetv->tvchain, livetv->backend_info);
24.477 +
24.478 + if (livetv->tvchain == NULL || livetv->tvchain->tvchain_id == NULL) {
24.479 + res = FALSE;
24.480 + goto error;
24.481 + }
24.482 + // Spawn live tv. Uses the socket to send mythprotocol data to start
24.483 + // livetv in the backend (remotelly)
24.484 + res = gmyth_recorder_spawntv(livetv->recorder,
24.485 + gmyth_tvchain_get_id(livetv->tvchain));
24.486 + if (!res) {
24.487 + gmyth_debug("[%s] Fail while spawn tv\n", __FUNCTION__);
24.488 + res = FALSE;
24.489 + goto error;
24.490 + }
24.491 +
24.492 + if (res == TRUE) {
24.493 + /*
24.494 + * loop finished, set the max tries variable to zero again...
24.495 + */
24.496 + gint wait_to_transfer = 0;
24.497 +
24.498 + while (wait_to_transfer++ < GMYTHTV_TRANSFER_MAX_WAITS &&
24.499 + (gmyth_recorder_is_recording(livetv->recorder) == FALSE))
24.500 + g_usleep(300);
24.501 +
24.502 + if (channel != NULL) {
24.503 + /*
24.504 + * Pauses remote encoder.
24.505 + */
24.506 + res = gmyth_recorder_pause_recording(livetv->recorder);
24.507 + if (!res) {
24.508 + gmyth_debug("[%s] Fail while pausing remote encoder\n",
24.509 + __FUNCTION__);
24.510 + res = FALSE;
24.511 + goto error;
24.512 + }
24.513 +
24.514 + if (gmyth_recorder_check_channel_name
24.515 + (livetv->recorder, channel)) {
24.516 + if (gmyth_recorder_set_channel_name
24.517 + (livetv->recorder, channel)) {
24.518 + gmyth_debug("Channel changed!!! [%s].\n", channel);
24.519 + }
24.520 + }
24.521 +
24.522 + }
24.523 + /*
24.524 + * if - changes the channel number
24.525 + */
24.526 + /*
24.527 + * sleep (5);
24.528 + */
24.529 + /*
24.530 + * FIXME: this is evil (tpm)
24.531 + */
24.532 + }
24.533 +
24.534 + /*
24.535 + * DEBUG message
24.536 + */
24.537 + GMythProgramInfo *prog_info =
24.538 + gmyth_recorder_get_current_program_info(livetv->recorder);
24.539 +
24.540 + if (NULL == prog_info) {
24.541 + gmyth_debug("ProgramInfo is equals to NULL!!!");
24.542 +
24.543 + gint i;
24.544 + gchar *channame = NULL;
24.545 +
24.546 + gmyth_debug("Problem getting current proginfo!\n");
24.547 +
24.548 + /*
24.549 + * mythbackend must not be tuned in to a channel, so keep
24.550 + * changing channels until we find a valid one, or until
24.551 + * we decide to give up.
24.552 + */
24.553 + for (i = 1; i < 1000; i++) {
24.554 + if (channame != NULL)
24.555 + g_free(channame);
24.556 + channame = g_strdup_printf("%d", i);
24.557 + if (gmyth_recorder_set_channel_name(livetv->recorder, channame)
24.558 + < 0) {
24.559 + continue;
24.560 + }
24.561 + prog_info =
24.562 + gmyth_recorder_get_next_program_info(livetv->recorder,
24.563 + BROWSE_DIRECTION_UP);
24.564 + gmyth_program_info_print(prog_info);
24.565 + if (prog_info != NULL)
24.566 + break;
24.567 + }
24.568 +
24.569 + }
24.570 +
24.571 + /*
24.572 + * if - Program Info
24.573 + */
24.574 + /*
24.575 + * prints program info data text
24.576 + */
24.577 + gmyth_debug("New ProgramInfo...\n");
24.578 + gmyth_program_info_print(prog_info);
24.579 +
24.580 + /*
24.581 + * check if the program chain could be obtained from the MythTV
24.582 + * protocol message
24.583 + */
24.584 + if (prog_info != NULL) {
24.585 + gmyth_backend_info_set_username(livetv->tvchain->backend_info,
24.586 + "mythtv");
24.587 + gmyth_backend_info_set_password(livetv->tvchain->backend_info,
24.588 + "mythtv");
24.589 + gmyth_backend_info_set_db_name(livetv->tvchain->backend_info,
24.590 + "mythconverg");
24.591 + GList *prog_list =
24.592 + gmyth_tvchain_get_program_info_from_channel(livetv->tvchain,
24.593 + channel);
24.594 + GMythProgramInfo *ch_prog = NULL;
24.595 +
24.596 + if (prog_list != NULL && g_list_length(prog_list) > 0) {
24.597 + ch_prog = (GMythProgramInfo *) g_list_nth_data(prog_list, 0);
24.598 + gmyth_debug
24.599 + ("Channel program info (from a list with size = %d)!",
24.600 + g_list_length(prog_list));
24.601 + gmyth_program_info_print(ch_prog);
24.602 + }
24.603 +
24.604 + gmyth_debug("Program Info: %s\n",
24.605 + gmyth_program_info_to_string(prog_info));
24.606 + livetv->proginfo = prog_info;
24.607 + /*
24.608 + * testing change channel
24.609 + */
24.610 + // gmyth_recorder_spawntv_no_tvchain( livetv->recorder );
24.611 + } else {
24.612 +
24.613 + /*
24.614 + * check for the program info in the TV program chain could be
24.615 + * obtained from the MythTV MySQL database
24.616 + */
24.617 +
24.618 + /*
24.619 + * Reload all TV chain from Mysql database.
24.620 + */
24.621 + gmyth_tvchain_reload_all(livetv->tvchain);
24.622 +
24.623 + if (livetv->tvchain == NULL) {
24.624 + res = FALSE;
24.625 + goto error;
24.626 + }
24.627 +
24.628 + /*
24.629 + * Get program info from database using chanid and starttime
24.630 + */
24.631 + livetv->proginfo =
24.632 + gmyth_tvchain_get_program_at(livetv->tvchain,
24.633 + tvchain_curr_index++);
24.634 + if (livetv->proginfo == NULL) {
24.635 + gmyth_debug("LiveTV not successfully started.\n");
24.636 + res = FALSE;
24.637 + goto error;
24.638 + } else {
24.639 + res = TRUE;
24.640 + gmyth_debug
24.641 + ("GMythLiveTV: All requests to backend to start TV were OK. [%s]\n",
24.642 + livetv->proginfo->pathname->str);
24.643 + }
24.644 +
24.645 + }
24.646 +
24.647 + livetv->uri =
24.648 + (GMythURI *) gmyth_backend_info_get_uri(livetv->backend_info);
24.649 +
24.650 + g_mutex_unlock(livetv->mutex);
24.651 +
24.652 + if (!gmyth_livetv_monitor_handler_start(livetv)) {
24.653 + res = FALSE;
24.654 + gmyth_debug("LiveTV MONITOR handler error on setup!");
24.655 + goto error;
24.656 + }
24.657 +
24.658 + livetv->setup_done = TRUE;
24.659 +
24.660 + return res;
24.661 +
24.662 + error:
24.663 + g_mutex_unlock(livetv->mutex);
24.664 +
24.665 + gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
24.666 +
24.667 + res = FALSE;
24.668 +
24.669 + if (livetv->local_hostname != NULL) {
24.670 + g_string_free(livetv->local_hostname, TRUE);
24.671 + livetv->local_hostname = NULL;
24.672 + }
24.673 +
24.674 + gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
24.675 +
24.676 + if (livetv->recorder != NULL) {
24.677 + g_object_unref(livetv->recorder);
24.678 + livetv->recorder = NULL;
24.679 + }
24.680 +
24.681 + gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
24.682 +
24.683 + if (livetv->tvchain != NULL) {
24.684 + g_object_unref(livetv->tvchain);
24.685 + livetv->tvchain = NULL;
24.686 + }
24.687 +
24.688 + gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
24.689 +
24.690 + if (livetv->proginfo != NULL) {
24.691 + g_object_unref(livetv->proginfo);
24.692 + livetv->proginfo = NULL;
24.693 + }
24.694 +
24.695 + gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
24.696 +
24.697 + if (livetv->monitor != NULL) {
24.698 + g_object_unref(livetv->monitor);
24.699 + livetv->monitor = NULL;
24.700 + }
24.701 +
24.702 +
24.703 + gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
24.704 +
24.705 + return res;
24.706 +
24.707 +}
24.708 +
24.709 +/**
24.710 + * Setup the GMythLiveTV session, sends SPAWN_LIVETV message,
24.711 + * sets the channel name, and gets the first program info about the
24.712 + * actual recording
24.713 + *
24.714 + * @param live_tv the GMythLiveTV instance
24.715 + * @param channel the channel name, in numerical format
24.716 + * @param backend_info the GMythBackendInfo describing the remote server
24.717 + *
24.718 + * @return <code>true</code> if the LiveTV's recorder instance configuration
24.719 + * had been concluded succcesfully
24.720 + */
24.721 +static gboolean
24.722 +gmyth_livetv_setup_recorder(GMythLiveTV * livetv, gint channel)
24.723 +{
24.724 + return gmyth_livetv_setup_recorder_channel_name(livetv,
24.725 + (channel !=
24.726 + -1) ?
24.727 + g_strdup_printf("%d",
24.728 + channel)
24.729 + : NULL);
24.730 +}
24.731 +
24.732 +/**
24.733 + * Setup the GMythLiveTV session, sends SPAWN_LIVETV message,
24.734 + * sets the channel name (numerical format), and gets the first program info about the
24.735 + * actual recording
24.736 + *
24.737 + * @param live_tv the GMythLiveTV instance
24.738 + * @param channel the channel name, in numerical format
24.739 + * @param backend_info the GMythBackendInfo describing the remote server
24.740 + *
24.741 + * @return <code>true</code> if the LiveTV's recorder instance configuration
24.742 + * had been concluded succcesfully
24.743 + */
24.744 +gboolean
24.745 +gmyth_livetv_channel_setup(GMythLiveTV * livetv, gint channel)
24.746 +{
24.747 + return gmyth_livetv_setup_recorder(livetv, channel);
24.748 +}
24.749 +
24.750 +/**
24.751 + * Setup the GMythLiveTV session, sends SPAWN_LIVETV message,
24.752 + * sets the channel name (string format), and gets the first program info about the
24.753 + * actual recording
24.754 + *
24.755 + * @param live_tv the GMythLiveTV instance
24.756 + * @param channel the channel name, in numerical format
24.757 + * @param backend_info the GMythBackendInfo describing the remote server
24.758 + *
24.759 + * @return <code>true</code> if the LiveTV's recorder instance configuration
24.760 + * had been concluded succcesfully
24.761 + */
24.762 +gboolean
24.763 +gmyth_livetv_channel_name_setup(GMythLiveTV * livetv, gchar * channel)
24.764 +{
24.765 + return gmyth_livetv_setup_recorder_channel_name(livetv, channel);
24.766 +}
24.767 +
24.768 +/**
24.769 + * Setup the GMythLiveTV session, sends SPAWN_LIVETV message,
24.770 + * and gets the first program info about the actual recording
24.771 + * (doesn't changes the channel).
24.772 + *
24.773 + * @param live_tv the GMythLiveTV instance
24.774 + * @param backend_info the GMythBackendInfo describing the remote server
24.775 + *
24.776 + * @return <code>true</code> if the LiveTV's recorder instance configuration
24.777 + * had been concluded succcesfully
24.778 + */
24.779 +gboolean
24.780 +gmyth_livetv_setup(GMythLiveTV * livetv)
24.781 +{
24.782 + return gmyth_livetv_setup_recorder(livetv, -1);
24.783 +}
24.784 +
24.785 +/**
24.786 + * Gets the next program info from this GMythLiveTV session.
24.787 + *
24.788 + * @param live_tv the GMythLiveTV instance
24.789 + *
24.790 + * @return <code>true</code> if the next program info could be got
24.791 + */
24.792 +gboolean
24.793 +gmyth_livetv_next_program_chain(GMythLiveTV * livetv)
24.794 +{
24.795 + gboolean res = TRUE;
24.796 + GMythProgramInfo *prog_info = NULL;
24.797 +
24.798 + if (!livetv->setup_done) {
24.799 + gmyth_debug("Call the setup function first!");
24.800 + goto error;
24.801 + }
24.802 +
24.803 + gmyth_debug("Current ProgramInfo...\n");
24.804 + prog_info = gmyth_recorder_get_current_program_info(livetv->recorder);
24.805 +
24.806 + if (prog_info != NULL) {
24.807 + livetv->proginfo = prog_info;
24.808 + } else {
24.809 + gmyth_debug
24.810 + ("ProgramInfo equals to NULL!!! Getting the next program info...");
24.811 + prog_info =
24.812 + gmyth_recorder_get_next_program_info(livetv->recorder,
24.813 + BROWSE_DIRECTION_RIGHT);
24.814 + livetv->proginfo = prog_info;
24.815 + }
24.816 + /*
24.817 + * prints program info data text
24.818 + */
24.819 + gmyth_program_info_print(prog_info);
24.820 +
24.821 + if (prog_info != NULL) {
24.822 + res = TRUE;
24.823 + livetv->proginfo = prog_info;
24.824 + gmyth_debug
24.825 + ("GMythLiveTV: All requests to backend to start TV were OK, program info changed.");
24.826 + } else {
24.827 + gmyth_debug
24.828 + ("[%s] LiveTV not successfully started on the next program chain.\n",
24.829 + __FUNCTION__);
24.830 + goto error;
24.831 + }
24.832 +
24.833 + livetv->setup_done = TRUE;
24.834 +
24.835 + return res;
24.836 +
24.837 + error:
24.838 + gmyth_debug("ERROR running LiveTV setup.\n");
24.839 +
24.840 + res = FALSE;
24.841 +
24.842 + g_string_free(livetv->local_hostname, TRUE);
24.843 +
24.844 + if (livetv->recorder != NULL) {
24.845 + g_object_unref(livetv->recorder);
24.846 + livetv->recorder = NULL;
24.847 + }
24.848 +
24.849 + if (livetv->tvchain != NULL) {
24.850 + g_object_unref(livetv->tvchain);
24.851 + livetv->tvchain = NULL;
24.852 + }
24.853 +
24.854 + if (livetv->proginfo != NULL) {
24.855 + g_object_unref(livetv->proginfo);
24.856 + livetv->proginfo = NULL;
24.857 + }
24.858 +
24.859 + return res;
24.860 +}
24.861 +
24.862 +/**
24.863 + * Creates a File Transfer session, using all configuration information
24.864 + * got from the actual program info.
24.865 + *
24.866 + * @param live_tv the GMythLiveTV instance
24.867 + *
24.868 + * @return the actual GMythFileTransfer instance, generated using the
24.869 + * data got from the actual program info.
24.870 + */
24.871 +GMythFile*
24.872 +gmyth_livetv_create_file_transfer(GMythLiveTV * livetv)
24.873 +{
24.874 + // GMythURI* uri = NULL;
24.875 +
24.876 + if (NULL == livetv)
24.877 + return NULL;
24.878 +
24.879 + if (!livetv->setup_done) {
24.880 + gmyth_debug
24.881 + ("Error: You must do the LiveTV setup, just before generating the FileTransfer from LiveTV source!");
24.882 + return NULL;
24.883 + }
24.884 +
24.885 + if (livetv->proginfo != NULL)
24.886 + gmyth_debug("URI path (from program info) = %s.\n",
24.887 + livetv->proginfo->pathname->str);
24.888 + else
24.889 + gmyth_debug("URI path (from URI) = %s.\n", livetv->uri->uri->str);
24.890 +
24.891 + g_mutex_lock(livetv->mutex);
24.892 +
24.893 + if (livetv->file != NULL) {
24.894 + /*
24.895 + * gmyth_file_transfer_close( livetv->file );
24.896 + */
24.897 + g_object_unref(livetv->file);
24.898 + livetv->file = NULL;
24.899 + }
24.900 +
24.901 + if (livetv->uri != NULL) {
24.902 + gmyth_debug
24.903 + ("URI is not NULL, creating from the ProgramInfo pathname... (%s)",
24.904 + livetv->proginfo->pathname->str);
24.905 + livetv->uri->path = g_string_erase(livetv->uri->path, 0, -1);
24.906 + livetv->uri->path =
24.907 + g_string_new(g_strrstr(livetv->proginfo->pathname->str, "/"));
24.908 + } else {
24.909 + gmyth_debug
24.910 + ("URI is NULL, creating from the ProgramInfo pathname... (%s)",
24.911 + livetv->proginfo->pathname->str);
24.912 + livetv->uri =
24.913 + gmyth_uri_new_with_value(livetv->proginfo->pathname->str);
24.914 + }
24.915 +
24.916 + if (NULL == livetv->uri) {
24.917 + gmyth_debug("Couldn't parse the URI to start LiveTV! [ uri = %s ]",
24.918 + livetv->proginfo->pathname->str);
24.919 + goto done;
24.920 + }
24.921 +
24.922 + if (gmyth_uri_is_local_file(livetv->uri))
24.923 + livetv->file =
24.924 + GMYTH_FILE(gmyth_file_local_new(livetv->backend_info));
24.925 + else {
24.926 + livetv->file =
24.927 + GMYTH_FILE(gmyth_file_transfer_new(livetv->backend_info));
24.928 + /*
24.929 + * gmyth_file_transfer_settimeout(
24.930 + * GMYTH_FILE_TRANSFER(livetv->file), TRUE );
24.931 + */
24.932 + }
24.933 +
24.934 + if (NULL == livetv->file) {
24.935 + gmyth_debug
24.936 + ("Error: couldn't create the FileTransfer from LiveTV source!");
24.937 + goto done;
24.938 + }
24.939 +
24.940 + g_object_ref(livetv->file);
24.941 +
24.942 +done:
24.943 + g_mutex_unlock(livetv->mutex);
24.944 + return livetv->file;
24.945 +}
24.946 +
24.947 +/**
24.948 + * Stops this LiveTV session.
24.949 + *
24.950 + * @param live_tv the GMythLiveTV instance
24.951 + */
24.952 +void
24.953 +gmyth_livetv_stop_playing(GMythLiveTV * livetv)
24.954 +{
24.955 + gmyth_debug("Stopping the LiveTV...\n");
24.956 +
24.957 + if (livetv->is_livetv) {
24.958 + if (!gmyth_recorder_stop_livetv(livetv->recorder)) {
24.959 + gmyth_debug("[%s] Error while stoping remote encoder",
24.960 + __FUNCTION__);
24.961 + }
24.962 +
24.963 + if (!gmyth_recorder_finish_recording(livetv->recorder)) {
24.964 + gmyth_debug
24.965 + ("[%s] Error while finishing recording on remote encoder",
24.966 + __FUNCTION__);
24.967 + }
24.968 + }
24.969 +}
24.970 +
24.971 +gboolean
24.972 +gmyth_livetv_is_playing(GMythLiveTV * livetv)
24.973 +{
24.974 + return TRUE;
24.975 +}
24.976 +
24.977 +void
24.978 +gmyth_livetv_start_playing(GMythLiveTV * livetv)
24.979 +{
24.980 +
24.981 + // TODO
24.982 +
24.983 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/gmyth/gmyth/gmyth_livetv.h Mon Feb 25 17:51:43 2008 +0000
25.3 @@ -0,0 +1,103 @@
25.4 +/**
25.5 + * GMyth Library
25.6 + *
25.7 + * @file gmyth/gmyth_livetv.h
25.8 + *
25.9 + * @brief <p> GMythLiveTV starts a remote TV session with the MythTV backend.
25.10 + *
25.11 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
25.12 + * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
25.13 + *
25.14 +*
25.15 +* This program is free software; you can redistribute it and/or modify
25.16 +* it under the terms of the GNU Lesser General Public License as published by
25.17 +* the Free Software Foundation; either version 2 of the License, or
25.18 +* (at your option) any later version.
25.19 +*
25.20 +* This program is distributed in the hope that it will be useful,
25.21 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
25.22 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25.23 + * GNU General Public License for more details.
25.24 + *
25.25 + * You should have received a copy of the GNU Lesser General Public License
25.26 + * along with this program; if not, write to the Free Software
25.27 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25.28 + */
25.29 +
25.30 +#ifndef GMYTH_LIVETV_H_
25.31 +#define GMYTH_LIVETV_H_
25.32 +
25.33 +#include <glib.h>
25.34 +#include <glib-object.h>
25.35 +
25.36 +#include "gmyth_recorder.h"
25.37 +#include "gmyth_tvchain.h"
25.38 +#include "gmyth_monitor_handler.h"
25.39 +#include "gmyth_file.h"
25.40 +#include "gmyth_programinfo.h"
25.41 +#include "gmyth_backendinfo.h"
25.42 +
25.43 +G_BEGIN_DECLS
25.44 +#define GMYTH_LIVETV_TYPE (gmyth_livetv_get_type ())
25.45 +#define GMYTH_LIVETV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_LIVETV_TYPE, GMythLiveTV))
25.46 +#define GMYTH_LIVETV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_LIVETV_TYPE, GMythLiveTVClass))
25.47 +#define IS_GMYTH_LIVETV(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_LIVETV_TYPE))
25.48 +#define IS_GMYTH_LIVETV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_LIVETV_TYPE))
25.49 +#define GMYTH_LIVETV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_LIVETV_TYPE, GMythLiveTVClass))
25.50 +typedef struct _GMythLiveTV GMythLiveTV;
25.51 +typedef struct _GMythLiveTVClass GMythLiveTVClass;
25.52 +
25.53 +struct _GMythLiveTVClass {
25.54 + GObjectClass parent_class;
25.55 +
25.56 + /*
25.57 + * callbacks
25.58 + */
25.59 +};
25.60 +
25.61 +struct _GMythLiveTV {
25.62 + GObject parent;
25.63 +
25.64 + GMythSocket *socket;
25.65 +
25.66 + GString *local_hostname;
25.67 +
25.68 + GMythBackendInfo *backend_info;
25.69 +
25.70 + GMythRecorder *recorder;
25.71 + GMythTVChain *tvchain;
25.72 + GMythProgramInfo *proginfo;
25.73 +
25.74 + GMythFile *file;
25.75 +
25.76 + GMythMonitorHandler *monitor;
25.77 + GMythURI *uri;
25.78 +
25.79 + gboolean is_livetv;
25.80 + gboolean setup_done;
25.81 +
25.82 + GMutex *mutex;
25.83 + gboolean disposed;
25.84 +};
25.85 +
25.86 +GType gmyth_livetv_get_type(void);
25.87 +
25.88 +GMythLiveTV *gmyth_livetv_new(GMythBackendInfo * backend_info);
25.89 +
25.90 +void gmyth_livetv_start_playing(GMythLiveTV * livetv);
25.91 +void gmyth_livetv_stop_playing(GMythLiveTV * livetv);
25.92 +
25.93 +gboolean gmyth_livetv_setup(GMythLiveTV * livetv);
25.94 +gboolean gmyth_livetv_channel_setup(GMythLiveTV * livetv,
25.95 + gint channel);
25.96 +gboolean gmyth_livetv_channel_name_setup(GMythLiveTV * livetv,
25.97 + gchar * channel);
25.98 +gboolean gmyth_livetv_next_program_chain(GMythLiveTV * livetv);
25.99 +
25.100 +GMythFile *gmyth_livetv_create_file_transfer(GMythLiveTV * livetv);
25.101 +
25.102 +gboolean gmyth_livetv_monitor_handler_start(GMythLiveTV * livetv);
25.103 +void gmyth_livetv_monitor_handler_stop(GMythLiveTV * livetv);
25.104 +
25.105 +G_END_DECLS
25.106 +#endif /* GMYTH_LIVETV_H_ */
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/gmyth/gmyth/gmyth_marshal.list Mon Feb 25 17:51:43 2008 +0000
26.3 @@ -0,0 +1,2 @@
26.4 +VOID:INT,STRING
26.5 +VOID:INT,POINTER
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
27.2 +++ b/gmyth/gmyth/gmyth_monitor_handler.c Mon Feb 25 17:51:43 2008 +0000
27.3 @@ -0,0 +1,593 @@
27.4 +/**
27.5 + * GMyth Library
27.6 + *
27.7 + * @file gmyth/gmyth_monitor_handler.c
27.8 + *
27.9 + * @brief <p> GMythMonitorHandler deals with the streaming media events remote/local
27.10 + * that are sent to the MythTV frontend.
27.11 + *
27.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
27.13 + * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
27.14 + *
27.15 + *
27.16 + * This program is free software; you can redistribute it and/or modify
27.17 + * it under the terms of the GNU Lesser General Public License as published by
27.18 + * the Free Software Foundation; either version 2 of the License, or
27.19 + * (at your option) any later version.
27.20 + *
27.21 + * This program is distributed in the hope that it will be useful,
27.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
27.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27.24 + * GNU General Public License for more details.
27.25 + *
27.26 + * You should have received a copy of the GNU Lesser General Public License
27.27 + * along with this program; if not, write to the Free Software
27.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27.29 + *
27.30 + * GStreamer MythTV plug-in properties:
27.31 + * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv]
27.32 + * - path (qurl - remote file to be opened)
27.33 + * - port number *
27.34 + */
27.35 +
27.36 +#ifdef HAVE_CONFIG_H
27.37 +#include "config.h"
27.38 +#endif
27.39 +
27.40 +#include <unistd.h>
27.41 +#include <glib.h>
27.42 +#include <arpa/inet.h>
27.43 +#include <sys/types.h>
27.44 +#include <sys/socket.h>
27.45 +#include <netdb.h>
27.46 +#include <errno.h>
27.47 +#include <stdlib.h>
27.48 +#include <assert.h>
27.49 +
27.50 +#include "gmyth_marshal.h"
27.51 +
27.52 +#include "gmyth_monitor_handler.h"
27.53 +#include "gmyth_debug.h"
27.54 +
27.55 +#define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER "
27.56 +
27.57 +#define GMYTHTV_VERSION 30
27.58 +
27.59 +#define GMYTHTV_TRANSFER_MAX_WAITS 700
27.60 +
27.61 +#define GMYTHTV_BUFFER_SIZE 8*1024
27.62 +
27.63 +#ifdef GMYTHTV_ENABLE_DEBUG
27.64 +#define GMYTHTV_ENABLE_DEBUG 1
27.65 +#else
27.66 +#undef GMYTHTV_ENABLE_DEBUG
27.67 +#endif
27.68 +
27.69 +/*
27.70 + * this NDEBUG is to maintain compatibility with GMyth library
27.71 + */
27.72 +#ifndef NDEBUG
27.73 +#define GMYTHTV_ENABLE_DEBUG 1
27.74 +#endif
27.75 +
27.76 +static gboolean gmyth_monitor_handler_listener (GIOChannel *io_channel,
27.77 + GIOCondition condition,
27.78 + gpointer data);
27.79 +
27.80 +static void gmyth_monitor_handler_default_listener(GMythMonitorHandler
27.81 + * monitor,
27.82 + gint msg_code,
27.83 + gchar * message);
27.84 +
27.85 +static void gmyth_monitor_handler_class_init(GMythMonitorHandlerClass *
27.86 + klass);
27.87 +static void gmyth_monitor_handler_init(GMythMonitorHandler * object);
27.88 +
27.89 +static void gmyth_monitor_handler_dispose(GObject * object);
27.90 +static void gmyth_monitor_handler_finalize(GObject * object);
27.91 +
27.92 +static gboolean gmyth_connect_to_backend_monitor(GMythMonitorHandler *
27.93 + monitor);
27.94 +
27.95 +static gboolean gmyth_monitor_handler_setup(GMythMonitorHandler * monitor,
27.96 + GIOChannel * channel);
27.97 +
27.98 +void gmyth_monitor_handler_close(GMythMonitorHandler * monitor);
27.99 +
27.100 +G_DEFINE_TYPE(GMythMonitorHandler, gmyth_monitor_handler, G_TYPE_OBJECT);
27.101 +
27.102 +static void
27.103 +gmyth_monitor_handler_class_init(GMythMonitorHandlerClass * klass)
27.104 +{
27.105 + GObjectClass *gobject_class;
27.106 + GMythMonitorHandlerClass *gmonitor_class;
27.107 +
27.108 + gobject_class = (GObjectClass *) klass;
27.109 + gmonitor_class = (GMythMonitorHandlerClass *) gobject_class;
27.110 +
27.111 + gobject_class->dispose = gmyth_monitor_handler_dispose;
27.112 + gobject_class->finalize = gmyth_monitor_handler_finalize;
27.113 +
27.114 + gmonitor_class->backend_events_handler_signal_id =
27.115 + g_signal_new("backend-events-handler",
27.116 + G_TYPE_FROM_CLASS(gmonitor_class),
27.117 + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE |
27.118 + G_SIGNAL_NO_HOOKS, 0, NULL, NULL,
27.119 + gmyth_marshal_VOID__INT_STRING, G_TYPE_NONE, 2,
27.120 + G_TYPE_INT, G_TYPE_STRING);
27.121 +
27.122 + gmonitor_class->backend_events_handler =
27.123 + gmyth_monitor_handler_default_listener;
27.124 +
27.125 +}
27.126 +
27.127 +static void
27.128 +gmyth_monitor_handler_init(GMythMonitorHandler * monitor)
27.129 +{
27.130 + g_return_if_fail(monitor != NULL);
27.131 +
27.132 + monitor->event_sock = NULL;
27.133 + monitor->hostname = NULL;
27.134 + monitor->port = 0;
27.135 + monitor->actual_index = 0;
27.136 + monitor->allow_msgs_listener = FALSE;
27.137 + /*
27.138 + * it is used for signalizing the event socket consumer thread
27.139 + */
27.140 + monitor->mutex = g_mutex_new();
27.141 +}
27.142 +
27.143 +static void
27.144 +gmyth_monitor_handler_dispose(GObject * object)
27.145 +{
27.146 + GMythMonitorHandler *monitor = GMYTH_MONITOR_HANDLER(object);
27.147 +
27.148 + gmyth_monitor_handler_close(monitor);
27.149 +
27.150 + monitor->allow_msgs_listener = FALSE;
27.151 +
27.152 + if (monitor->io_source != 0) {
27.153 + g_source_remove (monitor->io_source);
27.154 + monitor->io_source = 0;
27.155 + }
27.156 +
27.157 + /*
27.158 + * mutex to control access to the event socket consumer thread
27.159 + */
27.160 + if (monitor->mutex != NULL) {
27.161 + // g_mutex_unlock( monitor->mutex );
27.162 + g_mutex_free(monitor->mutex);
27.163 + monitor->mutex = NULL;
27.164 + }
27.165 +
27.166 + if (monitor->event_sock != NULL) {
27.167 + g_object_unref(monitor->event_sock);
27.168 + monitor->event_sock = NULL;
27.169 + }
27.170 +
27.171 + if (monitor->hostname != NULL) {
27.172 + g_free(monitor->hostname);
27.173 + monitor->hostname = NULL;
27.174 + }
27.175 +
27.176 +
27.177 + if (monitor->backend_msgs != NULL) {
27.178 + g_hash_table_destroy(monitor->backend_msgs);
27.179 + monitor->backend_msgs = NULL;
27.180 + }
27.181 +
27.182 + /*
27.183 + * if ( io_watcher_cond != NULL ) { g_cond_free( io_watcher_cond );
27.184 + * io_watcher_cond = NULL; }
27.185 + */
27.186 +
27.187 +
27.188 + G_OBJECT_CLASS(gmyth_monitor_handler_parent_class)->dispose(object);
27.189 +}
27.190 +
27.191 +static void
27.192 +gmyth_monitor_handler_finalize(GObject * object)
27.193 +{
27.194 + g_signal_handlers_destroy(object);
27.195 +
27.196 + G_OBJECT_CLASS(gmyth_monitor_handler_parent_class)->finalize(object);
27.197 +}
27.198 +
27.199 +/**
27.200 + * Creates a new instance of GMyth Monitor Handler.
27.201 + *
27.202 + * @return a new instance of the Monitor Handler.
27.203 + */
27.204 +GMythMonitorHandler *
27.205 +gmyth_monitor_handler_new(void)
27.206 +{
27.207 + GMythMonitorHandler *monitor =
27.208 + GMYTH_MONITOR_HANDLER(g_object_new
27.209 + (GMYTH_MONITOR_HANDLER_TYPE, FALSE));
27.210 +
27.211 + return monitor;
27.212 +}
27.213 +
27.214 +/**
27.215 + * Acquire the mutex to have access to the IO Watcher listener.
27.216 + *
27.217 + * @param monitor The GMythMonitorHandler instance.
27.218 + * @param do_wait Tells the IO Watcher to wait on the GCond. (obsolete)
27.219 + *
27.220 + * @return <code>true</code>, if the access to IO Watcher was acquired.
27.221 + */
27.222 +static gboolean
27.223 +myth_control_acquire_context(GMythMonitorHandler * monitor,
27.224 + gboolean do_wait)
27.225 +{
27.226 +
27.227 + gboolean ret = TRUE;
27.228 +
27.229 + g_mutex_lock(monitor->mutex);
27.230 +
27.231 + return ret;
27.232 +
27.233 +}
27.234 +
27.235 +/**
27.236 + * Release the mutex to have access to the IO Watcher listener.
27.237 + *
27.238 + * @param monitor The GMythMonitorHandler instance.
27.239 + *
27.240 + * @return <code>true</code>, if the access to IO Watcher was released.
27.241 + */
27.242 +static gboolean
27.243 +myth_control_release_context(GMythMonitorHandler * monitor)
27.244 +{
27.245 +
27.246 + gboolean ret = TRUE;
27.247 +
27.248 + g_mutex_unlock(monitor->mutex);
27.249 +
27.250 + return ret;
27.251 +}
27.252 +
27.253 +void
27.254 +gmyth_monitor_handler_close(GMythMonitorHandler * monitor)
27.255 +{
27.256 + monitor->allow_msgs_listener = FALSE;
27.257 +
27.258 +#if 0
27.259 + if (monitor->monitor_th != NULL) {
27.260 + g_thread_pool_free(monitor->monitor_th, TRUE, FALSE);
27.261 + // g_thread_exit( monitor->monitor_th );
27.262 + /*
27.263 + * if ( monitor->monitor_th != NULL ) g_object_unref(
27.264 + * monitor->monitor_th );
27.265 + */
27.266 + monitor->monitor_th = NULL;
27.267 + }
27.268 +
27.269 + if (monitor->event_sock != NULL) {
27.270 + gmyth_socket_close_connection(monitor->event_sock);
27.271 + }
27.272 +#endif
27.273 +
27.274 +}
27.275 +
27.276 +/**
27.277 + * Opens connection the the Monitor socket on MythTV backend server,
27.278 + * where all status messages are notified to the client.
27.279 + *
27.280 + * @param monitor The GMythMonitorHandler instance.
27.281 + * @param hostname The remote host name of the MythTV backend server.
27.282 + * @param port The remote port number of the MythTV backend server.
27.283 + *
27.284 + * @return <code>true</code>, if the connection was successfully opened.
27.285 + */
27.286 +gboolean
27.287 +gmyth_monitor_handler_open(GMythMonitorHandler * monitor,
27.288 + const gchar * hostname, gint port)
27.289 +{
27.290 + gboolean ret = TRUE;
27.291 +
27.292 + g_return_val_if_fail(hostname != NULL, FALSE);
27.293 +
27.294 + if (monitor->hostname != NULL) {
27.295 + g_free(monitor->hostname);
27.296 + monitor->hostname = NULL;
27.297 + }
27.298 +
27.299 + monitor->hostname = g_strdup(hostname);
27.300 + monitor->port = port;
27.301 +
27.302 + gmyth_debug("Monitor event socket --- hostname: %s, port %d\n",
27.303 + monitor->hostname, monitor->port);
27.304 +
27.305 + if (monitor->event_sock != NULL) {
27.306 + g_object_unref(monitor->event_sock);
27.307 + monitor->event_sock = NULL;
27.308 + }
27.309 +
27.310 + /*
27.311 + * configure the event socket
27.312 + */
27.313 + if (!gmyth_connect_to_backend_monitor(monitor)) {
27.314 + gmyth_debug("Connection to backend failed (Event Socket)!");
27.315 + ret = FALSE;
27.316 + } else {
27.317 + gmyth_debug ("Remote monitor event socket had been succesfully create");
27.318 + }
27.319 +
27.320 + return ret;
27.321 +}
27.322 +
27.323 +/**
27.324 + * Reads the data got from the connection to the Monitor socket,
27.325 + * and looks for some important status messages.
27.326 + *
27.327 + * @param monitor The GMythMonitorHandler instance.
27.328 + * @param strlist The GMythStringList instance got from the Monitor remote socket.
27.329 + * @param back_msg_action A string pointer to the status message detailed description.
27.330 + *
27.331 + * @return The backend status message code ID.
27.332 + */
27.333 +static gint
27.334 +gmyth_monitor_handler_is_backend_message(GMythMonitorHandler * monitor,
27.335 + GMythStringList * strlist,
27.336 + gchar ** back_msg_action)
27.337 +{
27.338 + gint msg_type = GMYTH_BACKEND_NO_MESSAGE;
27.339 + GString *back_msg = NULL;
27.340 +
27.341 + if (gmyth_string_list_length(strlist) > 0) {
27.342 +
27.343 + back_msg = gmyth_string_list_get_string(strlist, 0);
27.344 + if (back_msg != NULL && back_msg->str != NULL &&
27.345 + strstr(back_msg->str, "BACKEND") != NULL) {
27.346 + gmyth_debug("MONITOR HANDLER - Received backend message = %s",
27.347 + back_msg->str);
27.348 + *back_msg_action =
27.349 + gmyth_string_list_get_char_array(strlist, 1);
27.350 +
27.351 + if (back_msg_action != NULL) {
27.352 +
27.353 + if (g_strstr_len
27.354 + (*back_msg_action, strlen(*back_msg_action),
27.355 + "LIVETV_CHAIN")
27.356 + || g_strstr_len(*back_msg_action,
27.357 + strlen(*back_msg_action),
27.358 + "RECORDING_LIST_CHANGE")
27.359 + || g_strstr_len(*back_msg_action,
27.360 + strlen(*back_msg_action),
27.361 + "SCHEDULE_CHANGE")
27.362 + || g_strstr_len(*back_msg_action,
27.363 + strlen(*back_msg_action),
27.364 + "LIVETV_WATCH")) {
27.365 + gmyth_debug
27.366 + ("MONITOR: message type == GMYTH_BACKEND_PROGRAM_INFO_CHANGED, msg = %s",
27.367 + *back_msg_action);
27.368 + msg_type = GMYTH_BACKEND_PROGRAM_INFO_CHANGED;
27.369 + } else if (g_strstr_len
27.370 + (*back_msg_action, strlen(*back_msg_action),
27.371 + "DONE_RECORDING")) {
27.372 + gmyth_debug
27.373 + ("MONITOR: message type == GMYTH_BACKEND_DONE_RECORDING, msg = %s",
27.374 + *back_msg_action);
27.375 + msg_type = GMYTH_BACKEND_DONE_RECORDING;
27.376 + } else if (g_strstr_len
27.377 + (*back_msg_action, strlen(*back_msg_action),
27.378 + "QUIT")) {
27.379 + gmyth_debug
27.380 + ("MONITOR: message type == GMYTH_BACKEND_STOP_LIVETV, msg = %s",
27.381 + *back_msg_action);
27.382 + msg_type = GMYTH_BACKEND_STOP_LIVETV;
27.383 + }
27.384 +
27.385 + /*
27.386 + * g_hash_table_insert ( monitor->backend_msgs,
27.387 + * &(monitor->actual_index), *back_msg_action );
27.388 + */
27.389 +
27.390 + }
27.391 + /*
27.392 + * if
27.393 + */
27.394 + }
27.395 + /*
27.396 + * if
27.397 + */
27.398 + if (back_msg != NULL) {
27.399 + g_string_free(back_msg, TRUE);
27.400 + back_msg = NULL;
27.401 + }
27.402 +
27.403 + } /* if - Does Monitor got any message from
27.404 + * * * backend? */
27.405 + else {
27.406 + *back_msg_action = g_strdup("");
27.407 + }
27.408 +
27.409 + return msg_type;
27.410 +
27.411 +}
27.412 +
27.413 +static void
27.414 +gmyth_monitor_handler_default_listener(GMythMonitorHandler * monitor,
27.415 + gint msg_code, gchar * message)
27.416 +{
27.417 + // assert( message!= NULL );
27.418 + gmyth_debug("DEFAULT Signal handler ( msg = %s, code = %d )\n",
27.419 + message, msg_code);
27.420 +}
27.421 +
27.422 +static void
27.423 +gmyth_monitor_handler_print(GString * str, gpointer ptr)
27.424 +{
27.425 + gmyth_debug("Backend message event: %s --- ", str->str);
27.426 +}
27.427 +
27.428 +/**
27.429 + * Opens connection the the Monitor socket on MythTV backend server,
27.430 + * where all status messages are notified to the client.
27.431 + *
27.432 + * @param data Pointer to the GMythMonitorHandler.
27.433 + *
27.434 + * @return Pointer to a gboolean <code>true</code> value, if the data was
27.435 + * successfully read.
27.436 + */
27.437 +static gboolean
27.438 +gmyth_monitor_handler_listener (GIOChannel *io_channel,
27.439 + GIOCondition io_cond,
27.440 + gpointer data)
27.441 +{
27.442 + GMythMonitorHandler *monitor;
27.443 + guint recv = 0;
27.444 + gsize len = 0;
27.445 + GMythStringList *strlist = NULL;
27.446 + gint bytes_sent = 0;
27.447 +
27.448 + monitor = (GMythMonitorHandler *) data;
27.449 +
27.450 + gmyth_debug("Entering MONITOR handler listener...");
27.451 +
27.452 + myth_control_acquire_context(monitor, TRUE);
27.453 +
27.454 + if (((io_cond & G_IO_HUP) != 0) ||
27.455 + ((io_cond & G_IO_ERR) != 0)) {
27.456 + goto clean_up;
27.457 + }
27.458 +
27.459 +
27.460 + gmyth_debug("Listening on Monitor socket...!\n");
27.461 + strlist = gmyth_string_list_new();
27.462 +
27.463 + len = gmyth_socket_read_stringlist(monitor->event_sock, strlist);
27.464 + if ((len > 0) && strlist != NULL && gmyth_string_list_length(strlist) > 0) {
27.465 + gchar *back_msg_action;
27.466 + gint msg_type;
27.467 +
27.468 + bytes_sent = gmyth_string_list_get_int(strlist, 0);
27.469 + // on backend error
27.470 + gmyth_debug ("received data buffer from IO event channel... %d strings gone!\n", len);
27.471 + recv += len;
27.472 +
27.473 + /*
27.474 + * debug purpose: prints out all the string list
27.475 + * elements
27.476 + */
27.477 + g_list_foreach(strlist->glist,
27.478 + (GFunc) gmyth_monitor_handler_print,
27.479 + NULL);
27.480 +
27.481 + back_msg_action = g_new0(gchar, 1);
27.482 + msg_type = gmyth_monitor_handler_is_backend_message(monitor,
27.483 + strlist,
27.484 + &back_msg_action);
27.485 +
27.486 + if (msg_type != GMYTH_BACKEND_NO_MESSAGE) {
27.487 + g_signal_emit(monitor,
27.488 + GMYTH_MONITOR_HANDLER_GET_CLASS(monitor)->backend_events_handler_signal_id,
27.489 + 0, msg_type, back_msg_action);
27.490 + }
27.491 +
27.492 + if (back_msg_action != NULL)
27.493 + g_free(back_msg_action);
27.494 +
27.495 + g_object_unref(strlist);
27.496 + }
27.497 +
27.498 +clean_up:
27.499 + myth_control_release_context(monitor);
27.500 + return TRUE;
27.501 +}
27.502 +
27.503 +/**
27.504 + * Opens connection events' socket the the Monitor socket on
27.505 + * MythTV backend server.
27.506 + *
27.507 + * @param monitor The GMythMonitorHandler instance.
27.508 + *
27.509 + * @return <code>true</code>, if the socket was successfully opened.
27.510 + */
27.511 +static gboolean
27.512 +gmyth_connect_to_backend_monitor(GMythMonitorHandler * monitor)
27.513 +{
27.514 + gboolean ret = TRUE;
27.515 +
27.516 + monitor->event_sock = gmyth_socket_new();
27.517 +
27.518 + /*
27.519 + * Connects the socket, send Mythtv ANN Monitor and verify Mythtv
27.520 + * protocol version
27.521 + */
27.522 + if (!gmyth_socket_connect_to_backend_events(monitor->event_sock,
27.523 + monitor->hostname,
27.524 + monitor->port, FALSE)) {
27.525 + g_object_unref(monitor->event_sock);
27.526 + monitor->event_sock = NULL;
27.527 + ret = FALSE;
27.528 + }
27.529 +
27.530 + return ret;
27.531 +}
27.532 +
27.533 +/**
27.534 + * Opens connection the the Monitor socket on MythTV backend server,
27.535 + * where all status messages are notified to the client.
27.536 + *
27.537 + * @param monitor The GMythMonitorHandler instance.
27.538 + * @param channel The GIOChannel instance to the Monitor socket.
27.539 + *
27.540 + * @return Pointer to the boolean value, and it is <code>true</code> only if the
27.541 + * GMythMonitorHandler could be configured.
27.542 + */
27.543 +static gboolean
27.544 +gmyth_monitor_handler_setup(GMythMonitorHandler * monitor,
27.545 + GIOChannel * channel)
27.546 +{
27.547 + gboolean ret = TRUE;
27.548 +
27.549 + if (channel != NULL) {
27.550 + monitor->allow_msgs_listener = TRUE;
27.551 + monitor->io_source = g_io_add_watch (channel, G_IO_IN | G_IO_ERR | G_IO_HUP,
27.552 + gmyth_monitor_handler_listener,
27.553 + monitor);
27.554 + } else {
27.555 + ret = FALSE;
27.556 + }
27.557 + return ret;
27.558 +}
27.559 +
27.560 +/**
27.561 + * Starts the MonitorHandler thread to the GIOWatcher.
27.562 + *
27.563 + * @param monitor The GMythMonitorHandler instance.
27.564 + *
27.565 + * @return <code>true</code>, if the MonitorHandler was started.
27.566 + */
27.567 +gboolean
27.568 +gmyth_monitor_handler_start(GMythMonitorHandler * monitor)
27.569 +{
27.570 + gboolean ret = TRUE;
27.571 +
27.572 + if (!(ret = g_thread_supported())) {
27.573 + gmyth_debug("Thread system wasn't initialized, starting NOW!!!");
27.574 + g_thread_init(NULL);
27.575 + }
27.576 +
27.577 + ret =
27.578 + gmyth_monitor_handler_setup(monitor,
27.579 + monitor->event_sock->sd_io_ch);
27.580 + if (ret) {
27.581 + gmyth_debug
27.582 + ("\n[%s]\tOK! Starting listener on the MONITOR event socket...[thread location = %p]\n",
27.583 + __FUNCTION__, g_thread_self());
27.584 + } else {
27.585 + gmyth_debug
27.586 + ("\n[%s]\tERROR! Coudn't start listener on the MONITOR event socket...[thread location = %p]\n",
27.587 + __FUNCTION__, g_thread_self());
27.588 + ret = FALSE;
27.589 + }
27.590 +
27.591 + gmyth_debug
27.592 + ("[%s] Watch listener function over the IO control channel? %s!!!\n",
27.593 + __FUNCTION__, (ret == TRUE ? "YES" : "NO"));
27.594 +
27.595 + return ret;
27.596 +}
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
28.2 +++ b/gmyth/gmyth/gmyth_monitor_handler.h Mon Feb 25 17:51:43 2008 +0000
28.3 @@ -0,0 +1,122 @@
28.4 +/**
28.5 + * GMyth Library
28.6 + *
28.7 + * @file gmyth/gmyth_monitor_handler.h
28.8 + *
28.9 + * @brief <p> GMythMonitorHandler deals with the streaming media events remote/local
28.10 + * that are sent to the MythTV frontend.
28.11 + *
28.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
28.13 + * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
28.14 + *
28.15 + *
28.16 + * This program is free software; you can redistribute it and/or modify
28.17 + * it under the terms of the GNU Lesser General Public License as published by
28.18 + * the Free Software Foundation; either version 2 of the License, or
28.19 + * (at your option) any later version.
28.20 + *
28.21 + * This program is distributed in the hope that it will be useful,
28.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
28.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28.24 + * GNU General Public License for more details.
28.25 + *
28.26 + * You should have received a copy of the GNU Lesser General Public License
28.27 + * along with this program; if not, write to the Free Software
28.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28.29 + */
28.30 +
28.31 +#ifndef __GMYTH_MONITOR_HANDLER_H__
28.32 +#define __GMYTH_MONITOR_HANDLER_H__
28.33 +
28.34 +#include <glib-object.h>
28.35 +#include <glib.h>
28.36 +#include <stdio.h>
28.37 +#include <stdlib.h>
28.38 +#include <string.h>
28.39 +
28.40 +#include <netdb.h>
28.41 +#include <sys/socket.h>
28.42 +#include <unistd.h>
28.43 +
28.44 +#include "gmyth_socket.h"
28.45 +#include "gmyth_uri.h"
28.46 +
28.47 +G_BEGIN_DECLS
28.48 +#define GMYTH_MONITOR_HANDLER_TYPE (gmyth_monitor_handler_get_type ())
28.49 +#define GMYTH_MONITOR_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_MONITOR_HANDLER_TYPE, GMythMonitorHandler))
28.50 +#define GMYTH_MONITOR_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_MONITOR_HANDLER_TYPE, GMythMonitorHandlerClass))
28.51 +#define IS_GMYTH_MONITOR_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_MONITOR_HANDLER_TYPE))
28.52 +#define IS_GMYTH_MONITOR_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_MONITOR_HANDLER_TYPE))
28.53 +#define GMYTH_MONITOR_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_MONITOR_HANDLER_TYPE, GMythMonitorHandlerClass))
28.54 +#define GMYTHTV_MONITOR_HANDLER_READ_ERROR -314
28.55 + enum {
28.56 + GMYTH_BACKEND_NO_MESSAGE = 0,
28.57 + GMYTH_BACKEND_PROGRAM_INFO_CHANGED,
28.58 + GMYTH_BACKEND_DONE_RECORDING,
28.59 + GMYTH_BACKEND_STOP_LIVETV
28.60 +};
28.61 +
28.62 +typedef struct _GMythMonitorHandler GMythMonitorHandler;
28.63 +typedef struct _GMythMonitorHandlerClass GMythMonitorHandlerClass;
28.64 +
28.65 +struct _GMythMonitorHandlerClass {
28.66 + GObjectClass parent_class;
28.67 +
28.68 + /*
28.69 + * callbacks
28.70 + */
28.71 + guint backend_events_handler_signal_id;
28.72 +
28.73 + /*
28.74 + * signal default handlers
28.75 + */
28.76 + void (*backend_events_handler) (GMythMonitorHandler *
28.77 + monitor, gint msg_code,
28.78 + gchar * message);
28.79 +};
28.80 +
28.81 +struct _GMythMonitorHandler {
28.82 + GObject parent;
28.83 +
28.84 + /*
28.85 + * MythTV version number
28.86 + */
28.87 + gint mythtv_version;
28.88 +
28.89 + /*
28.90 + * socket descriptors
28.91 + */
28.92 + GMythSocket *event_sock;
28.93 +
28.94 + //gpointer(*gmyth_monitor_handler_listener) (gpointer data);
28.95 +
28.96 + gchar *hostname;
28.97 + gint port;
28.98 +
28.99 + gint64 actual_index;
28.100 +
28.101 + gboolean allow_msgs_listener;
28.102 +
28.103 + /*
28.104 + * stores the messages coming from the backend
28.105 + */
28.106 + GHashTable *backend_msgs;
28.107 +
28.108 + GMutex *mutex;
28.109 + guint io_source;
28.110 +};
28.111 +
28.112 +GType gmyth_monitor_handler_get_type(void);
28.113 +
28.114 +GMythMonitorHandler *gmyth_monitor_handler_new(void);
28.115 +
28.116 +gboolean gmyth_monitor_handler_open(GMythMonitorHandler * monitor,
28.117 + const gchar * hostname,
28.118 + gint port);
28.119 +
28.120 +gboolean gmyth_monitor_handler_start(GMythMonitorHandler * monitor);
28.121 +
28.122 +void gmyth_monitor_handler_close(GMythMonitorHandler * monitor);
28.123 +
28.124 +G_END_DECLS
28.125 +#endif /* __GMYTH_MONITOR_HANDLER_H__ */
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
29.2 +++ b/gmyth/gmyth/gmyth_programinfo.c Mon Feb 25 17:51:43 2008 +0000
29.3 @@ -0,0 +1,582 @@
29.4 +/**
29.5 + * GMyth Library
29.6 + *
29.7 + * @file gmyth/gmyth_programinfo.c
29.8 + *
29.9 + * @brief <p> GMythProgramInfo representing the program info, with the
29.10 + * configuration data to the actual remote file in the TV chain.
29.11 + *
29.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
29.13 + * @author Rosfran Borges <rosfran.borges@indt.org.br>
29.14 + * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
29.15 + *
29.16 + *
29.17 + * This program is free software; you can redistribute it and/or modify
29.18 + * it under the terms of the GNU Lesser General Public License as published by
29.19 + * the Free Software Foundation; either version 2 of the License, or
29.20 + * (at your option) any later version.
29.21 + *
29.22 + * This program is distributed in the hope that it will be useful,
29.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
29.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29.25 + * GNU General Public License for more details.
29.26 + *
29.27 + * You should have received a copy of the GNU Lesser General Public License
29.28 + * along with this program; if not, write to the Free Software
29.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29.30 + *
29.31 + */
29.32 +
29.33 +#ifdef HAVE_CONFIG_H
29.34 +#include "config.h"
29.35 +#endif
29.36 +
29.37 +#include <stdlib.h>
29.38 +#include <string.h>
29.39 +#include <assert.h>
29.40 +
29.41 +#include "gmyth_programinfo.h"
29.42 +#include "gmyth_util.h"
29.43 +#include "gmyth_debug.h"
29.44 +
29.45 +static void gmyth_program_info_class_init(GMythProgramInfoClass *
29.46 + klass);
29.47 +static void gmyth_program_info_init(GMythProgramInfo * object);
29.48 +
29.49 +static void gmyth_program_info_dispose(GObject * object);
29.50 +static void gmyth_program_info_finalize(GObject * object);
29.51 +
29.52 +G_DEFINE_TYPE(GMythProgramInfo, gmyth_program_info, G_TYPE_OBJECT)
29.53 + static const gchar *gmyth_program_info_non_null_value(const GString *
29.54 + str);
29.55 +
29.56 + static void gmyth_program_info_class_init(GMythProgramInfoClass *
29.57 + klass)
29.58 +{
29.59 + GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
29.60 +
29.61 + gobject_class->dispose = gmyth_program_info_dispose;
29.62 + gobject_class->finalize = gmyth_program_info_finalize;
29.63 +}
29.64 +
29.65 +static void
29.66 +gmyth_program_info_init(GMythProgramInfo * gmyth_program_info)
29.67 +{
29.68 + gmyth_program_info->chancommfree = 0;
29.69 +
29.70 + /** A flag informing if the program has video or not. */
29.71 + gmyth_program_info->isVideo = FALSE;
29.72 + gmyth_program_info->lenMins = 0;
29.73 +
29.74 + gmyth_program_info->stars = 0.0f;
29.75 + gmyth_program_info->repeat = 0;
29.76 +
29.77 + gmyth_program_info->hasAirDate = FALSE;
29.78 +
29.79 + gmyth_program_info->spread = 0;
29.80 + gmyth_program_info->startCol = 0;
29.81 +
29.82 + gmyth_program_info->recpriority2 = 0;
29.83 + gmyth_program_info->reactivate = 0;
29.84 +
29.85 + gmyth_program_info->recordid = 0;
29.86 + gmyth_program_info->parentid = 0;
29.87 +
29.88 + /** The backend video source id associated to this program.*/
29.89 + gmyth_program_info->sourceid = 0;
29.90 + /** the backend input id associated to this program.*/
29.91 + gmyth_program_info->inputid = 0;
29.92 + /** The backend card id associated to this program.*/
29.93 + gmyth_program_info->cardid = 0;
29.94 + gmyth_program_info->shareable = FALSE;
29.95 + gmyth_program_info->duplicate = FALSE;
29.96 +
29.97 + gmyth_program_info->findid = 0;
29.98 +
29.99 + gmyth_program_info->programflags = 0;
29.100 + gmyth_program_info->transcoder = 0;
29.101 +
29.102 + gmyth_program_info->recpriority = 0;
29.103 +
29.104 + /** The file size of the recorded program.*/
29.105 + gmyth_program_info->filesize = -1;
29.106 +}
29.107 +
29.108 +static void
29.109 +gmyth_program_info_dispose(GObject * object)
29.110 +{
29.111 + GMythProgramInfo *gmyth_program_info = GMYTH_PROGRAM_INFO(object);
29.112 +
29.113 + /** The program start time. */
29.114 + g_free(gmyth_program_info->startts);
29.115 +
29.116 + /** The program end time. */
29.117 + g_free(gmyth_program_info->endts);
29.118 +
29.119 + /** The recording schedule start time. */
29.120 + g_free(gmyth_program_info->recstartts);
29.121 +
29.122 + /** The recording schedule end time */
29.123 + g_free(gmyth_program_info->recendts);
29.124 +
29.125 + /** The program title. */
29.126 + if (gmyth_program_info->title != NULL) {
29.127 + g_string_free(gmyth_program_info->title, TRUE);
29.128 + gmyth_program_info->title = NULL;
29.129 + }
29.130 +
29.131 + /** The program subtitle. */
29.132 + if (gmyth_program_info->subtitle != NULL) {
29.133 + g_string_free(gmyth_program_info->subtitle, TRUE);
29.134 + gmyth_program_info->subtitle = NULL;
29.135 + }
29.136 +
29.137 + /** The program description. */
29.138 + if (gmyth_program_info->description != NULL) {
29.139 + g_string_free(gmyth_program_info->description, TRUE);
29.140 + gmyth_program_info->description = NULL;
29.141 + }
29.142 +
29.143 + /** The program category. */
29.144 + if (gmyth_program_info->category != NULL) {
29.145 + g_string_free(gmyth_program_info->category, TRUE);
29.146 + gmyth_program_info->category = NULL;
29.147 + }
29.148 +
29.149 + if (gmyth_program_info->chanstr != NULL) {
29.150 + g_string_free(gmyth_program_info->chanstr, TRUE);
29.151 + gmyth_program_info->chanstr = NULL;
29.152 + }
29.153 +
29.154 + if (gmyth_program_info->chansign != NULL) {
29.155 + g_string_free(gmyth_program_info->chansign, TRUE);
29.156 + gmyth_program_info->chansign = NULL;
29.157 + }
29.158 +
29.159 + /** The associated channel name. */
29.160 + if (gmyth_program_info->channame != NULL) {
29.161 + g_string_free(gmyth_program_info->channame, TRUE);
29.162 + gmyth_program_info->channame = NULL;
29.163 + }
29.164 +
29.165 + if (gmyth_program_info->chanOutputFilters != NULL) {
29.166 + g_string_free(gmyth_program_info->chanOutputFilters, TRUE);
29.167 + gmyth_program_info->chanOutputFilters = NULL;
29.168 + }
29.169 +
29.170 + if (gmyth_program_info->seriesid != NULL) {
29.171 + g_string_free(gmyth_program_info->seriesid, TRUE);
29.172 + gmyth_program_info->chanOutputFilters = NULL;
29.173 + }
29.174 +
29.175 + /** The program unique id. */
29.176 + if (gmyth_program_info->program_id != NULL) {
29.177 + g_string_free (gmyth_program_info->program_id, TRUE);
29.178 + gmyth_program_info->program_id = NULL;
29.179 + }
29.180 +
29.181 + if (gmyth_program_info->catType != NULL) {
29.182 + g_string_free(gmyth_program_info->catType, TRUE);
29.183 + gmyth_program_info->catType = NULL;
29.184 + }
29.185 +
29.186 + if (gmyth_program_info->sortTitle != NULL) {
29.187 + g_string_free(gmyth_program_info->sortTitle, TRUE);
29.188 + gmyth_program_info->sortTitle = NULL;
29.189 + }
29.190 +
29.191 + if (gmyth_program_info->year != NULL) {
29.192 + g_string_free(gmyth_program_info->year, TRUE);
29.193 + gmyth_program_info->year = NULL;
29.194 + }
29.195 +
29.196 + g_free(gmyth_program_info->originalAirDate);
29.197 +
29.198 + g_free(gmyth_program_info->lastmodified);
29.199 +
29.200 + g_free(gmyth_program_info->lastInUseTime);
29.201 +
29.202 + if (gmyth_program_info->schedulerid != NULL) {
29.203 + g_string_free(gmyth_program_info->schedulerid, TRUE);
29.204 + gmyth_program_info->schedulerid = NULL;
29.205 + }
29.206 +
29.207 + if (gmyth_program_info->recgroup != NULL) {
29.208 + g_string_free(gmyth_program_info->recgroup, TRUE);
29.209 + gmyth_program_info->recgroup = NULL;
29.210 + }
29.211 +
29.212 + if (gmyth_program_info->playgroup != NULL) {
29.213 + g_string_free(gmyth_program_info->playgroup, TRUE);
29.214 + gmyth_program_info->playgroup = NULL;
29.215 + }
29.216 +
29.217 + /** The file name of the recorded program.*/
29.218 + if (gmyth_program_info->pathname != NULL) {
29.219 + g_string_free(gmyth_program_info->pathname, TRUE);
29.220 + gmyth_program_info->pathname = NULL;
29.221 + }
29.222 +
29.223 + if (gmyth_program_info->hostname != NULL) {
29.224 + g_string_free(gmyth_program_info->hostname, TRUE);
29.225 + gmyth_program_info->hostname = NULL;
29.226 + }
29.227 +
29.228 + G_OBJECT_CLASS(gmyth_program_info_parent_class)->dispose(object);
29.229 +}
29.230 +
29.231 +static void
29.232 +gmyth_program_info_finalize(GObject * object)
29.233 +{
29.234 + g_signal_handlers_destroy(object);
29.235 +
29.236 + G_OBJECT_CLASS(gmyth_program_info_parent_class)->finalize(object);
29.237 +}
29.238 +
29.239 +/**
29.240 + * Creates a new instance of GMythProgramInfo.
29.241 + *
29.242 + * @return a new instance of GMythProgramInfo.
29.243 + */
29.244 +GMythProgramInfo *
29.245 +gmyth_program_info_new(void)
29.246 +{
29.247 + GMythProgramInfo *program_info =
29.248 + GMYTH_PROGRAM_INFO(g_object_new(GMYTH_PROGRAM_INFO_TYPE, NULL));
29.249 +
29.250 + return program_info;
29.251 +}
29.252 +
29.253 +/**
29.254 + * Converts an instance of a GMythProgramInfo, to a GMythStringList.
29.255 + *
29.256 + * @param prog A GMythProgramInfo instance.
29.257 + * @param slist The GMythStringList to be passed to this function, in order to
29.258 + * give the responsibility of the string list creation to the
29.259 + * API user.
29.260 + *
29.261 + * @return a GMythStringList with the program info fields.
29.262 + */
29.263 +GMythStringList *
29.264 +gmyth_program_info_to_string_list(GMythProgramInfo * prog,
29.265 + GMythStringList * slist)
29.266 +{
29.267 + g_return_val_if_fail(prog != NULL, NULL);
29.268 + g_return_val_if_fail(slist != NULL, NULL);
29.269 +
29.270 + gmyth_string_list_append_string(slist, prog->title); /* 0 */
29.271 + gmyth_string_list_append_string(slist, prog->subtitle); /* 1 */
29.272 + gmyth_string_list_append_string(slist, prog->description); /* 2 */
29.273 + gmyth_string_list_append_string(slist, prog->category); /* 3 */
29.274 + gmyth_string_list_append_int (slist, prog->channel_id); /* 4 */
29.275 + gmyth_string_list_append_string(slist, prog->chanstr); /* 5 */
29.276 + gmyth_string_list_append_string(slist, prog->chansign); /* 6 */
29.277 + gmyth_string_list_append_string(slist, prog->channame); /* 7 */
29.278 + gmyth_string_list_append_string(slist, prog->pathname); /* 8 */
29.279 + gmyth_string_list_append_int64(slist, 0); /* 9 */
29.280 +
29.281 + // fixme
29.282 + // gmyth_string_list_append_int64 (slist, 100/*prog->filesize*/); /* 9
29.283 + //
29.284 + //
29.285 + // */
29.286 + // gmyth_string_list_append_int (slist, 0); /* 10 */
29.287 +
29.288 + if (prog->startts)
29.289 + gmyth_string_list_append_int(slist, prog->startts->tv_sec); /* 11 */// DATETIME_TO_LIST(startts)
29.290 + else
29.291 + gmyth_string_list_append_int(slist, 0);
29.292 +
29.293 + if (prog->endts)
29.294 + gmyth_string_list_append_int(slist, prog->endts->tv_sec); /* 12 */// DATETIME_TO_LIST(endts)
29.295 + else
29.296 + gmyth_string_list_append_int(slist, 0);
29.297 +
29.298 + gmyth_string_list_append_int(slist, prog->duplicate); /* 13 */
29.299 + gmyth_string_list_append_int(slist, prog->shareable); /* 14 */
29.300 + gmyth_string_list_append_int(slist, prog->findid); /* 15 */
29.301 + gmyth_string_list_append_string(slist, prog->hostname); /* 16 */
29.302 + gmyth_string_list_append_int(slist, prog->sourceid); /* 17 */
29.303 + gmyth_string_list_append_int(slist, prog->cardid); /* 18 */
29.304 + gmyth_string_list_append_int(slist, prog->inputid); /* 19 */
29.305 + gmyth_string_list_append_int(slist, prog->recpriority); /* 20 */
29.306 + gmyth_string_list_append_int(slist, 0 /* prog->recstatus */ ); /* 21 */
29.307 + gmyth_string_list_append_int(slist, prog->recordid); /* 22 */
29.308 + gmyth_string_list_append_int(slist, 0 /* prog->rectype */ ); /* 23 */
29.309 + gmyth_string_list_append_int(slist, 0 /* prog->dupin */ ); /* 24 */
29.310 + gmyth_string_list_append_int(slist, 0 /* prog->dupmethod */ ); /* 25 */
29.311 + gmyth_string_list_append_int(slist, prog->recstartts != NULL ? prog->recstartts->tv_sec : 0); /* 26
29.312 + */// DATETIME_TO_LIST(recstartts)
29.313 + gmyth_string_list_append_int(slist, prog->recendts != NULL ? prog->recendts->tv_sec : 0); /* 27
29.314 + */// DATETIME_TO_LIST(recendts)
29.315 + gmyth_string_list_append_int(slist, prog->repeat); /* 28 */
29.316 + gmyth_string_list_append_int(slist, prog->programflags); /* 29 */
29.317 + gmyth_string_list_append_char_array(slist, "Default"); /* 30 */// prog->(recgroup
29.318 + //
29.319 + //
29.320 + // != "") ?
29.321 + // recgroup :
29.322 + // "Default")
29.323 + gmyth_string_list_append_int(slist, prog->chancommfree); /* 31 */
29.324 + gmyth_string_list_append_string(slist, prog->chanOutputFilters); /* 32
29.325 + */
29.326 + gmyth_string_list_append_string(slist, prog->seriesid); /* 33 */
29.327 + gmyth_string_list_append_string(slist, prog->program_id); /* 34 */
29.328 + gmyth_string_list_append_char_array(slist, ""); /* 35 */
29.329 + gmyth_string_list_append_int(slist, prog->lastmodified != NULL ? prog->lastmodified->tv_sec : 0); /* 36
29.330 + */// DATETIME_TO_LIST(lastmodified)
29.331 + gmyth_string_list_append_int(slist, 0); /* 37 */// FLOAT_TO_LIST(stars)
29.332 + gmyth_string_list_append_int(slist, prog->originalAirDate != NULL ? prog->originalAirDate->tv_sec : 0); /* 38
29.333 + */// DATETIME_TO_LIST(QDateTime(originalAirDate))
29.334 + gmyth_string_list_append_int(slist, prog->hasAirDate); /* 39 */
29.335 + gmyth_string_list_append_char_array(slist, "Default"); /* 40 */// prog->(playgroup
29.336 + //
29.337 + //
29.338 + // != "") ?
29.339 + // playgroup :
29.340 + // "Default")
29.341 + gmyth_string_list_append_int(slist, prog->recpriority2); /* 41 */
29.342 +
29.343 + return slist;
29.344 +}
29.345 +
29.346 +/**
29.347 + * Converts an instance of a GMythStringList, to a GMythProgramInfo.
29.348 + *
29.349 + * @param slist The GMythStringList got from the MythTV backend server.
29.350 + * @param pos The position in the GMythStringList to start getting the fields.
29.351 + *
29.352 + * @return a GMythProgramInfo representing the string list got from network.
29.353 + */
29.354 +GMythProgramInfo *
29.355 +gmyth_program_info_from_string_list_from_pos(GMythStringList * slist,
29.356 + guint pos)
29.357 +{
29.358 + GMythProgramInfo *prog = gmyth_program_info_new();
29.359 +
29.360 + g_return_val_if_fail(slist != NULL &&
29.361 + gmyth_string_list_get_string(slist, pos) != NULL,
29.362 + NULL);
29.363 +
29.364 + prog->title = gmyth_string_list_get_string(slist, pos);
29.365 + prog->subtitle = gmyth_string_list_get_string(slist, pos + 1);
29.366 + prog->description = gmyth_string_list_get_string(slist, pos + 2);
29.367 + prog->category = gmyth_string_list_get_string(slist, pos + 3);
29.368 + prog->channel_id = gmyth_string_list_get_int (slist, pos + 4);
29.369 + prog->channame = gmyth_string_list_get_string(slist, pos + 5);
29.370 + prog->chanstr = gmyth_string_list_get_string(slist, pos + 6);
29.371 + prog->chansign = gmyth_string_list_get_string(slist, pos + 7);
29.372 + prog->pathname = gmyth_string_list_get_string(slist, pos + 8);
29.373 +
29.374 + prog->filesize = gmyth_string_list_get_int64(slist, pos + 9);
29.375 +
29.376 + gmyth_debug("Prog info: [ %s, %s, %s, %s, %s, %s, %s, %s, %d ]\n",
29.377 + gmyth_program_info_non_null_value(prog->title),
29.378 + gmyth_program_info_non_null_value(prog->subtitle),
29.379 + gmyth_program_info_non_null_value(prog->description),
29.380 + gmyth_program_info_non_null_value(prog->category),
29.381 + gmyth_program_info_non_null_value(prog->channame),
29.382 + gmyth_program_info_non_null_value(prog->chanstr),
29.383 + gmyth_program_info_non_null_value(prog->chansign),
29.384 + gmyth_program_info_non_null_value(prog->pathname),
29.385 + gmyth_string_list_get_int(slist, pos + 11));
29.386 +
29.387 + prog->startts = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 11)))->str); // DATETIME_TO_LIST(startts)
29.388 + prog->endts = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 12)))->str); // DATETIME_TO_LIST(endts)
29.389 + prog->duplicate = gmyth_string_list_get_int(slist, pos + 13);
29.390 + prog->shareable = gmyth_string_list_get_int(slist, pos + 14);
29.391 + prog->findid = gmyth_string_list_get_int(slist, pos + 15);
29.392 + prog->hostname = gmyth_string_list_get_string(slist, pos + 16);
29.393 + prog->sourceid = gmyth_string_list_get_int(slist, pos + 17);
29.394 + prog->cardid = gmyth_string_list_get_int(slist, pos + 18);
29.395 + prog->inputid = gmyth_string_list_get_int(slist, pos + 19);
29.396 + prog->recpriority = gmyth_string_list_get_int(slist, pos + 20);
29.397 + prog->reactivate = gmyth_string_list_get_int(slist, pos + 21);
29.398 + prog->recordid = gmyth_string_list_get_int(slist, pos + 22);
29.399 + gmyth_string_list_get_int(slist, pos + 23);
29.400 + gmyth_string_list_get_int(slist, pos + 24);
29.401 + gmyth_string_list_get_int(slist, pos + 25);
29.402 + prog->recstartts = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 26)))->str); // DATETIME_TO_LIST(recstartts)
29.403 + prog->recendts = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 27)))->str); // DATETIME_TO_LIST(recendts)
29.404 + prog->repeat = gmyth_string_list_get_int(slist, pos + 28);
29.405 + prog->programflags = gmyth_string_list_get_int(slist, pos + 29);
29.406 + prog->recgroup = gmyth_string_list_get_string(slist, pos + 30); // prog->(recgroup
29.407 + //
29.408 + //
29.409 + // !=
29.410 + // "")
29.411 + // ?
29.412 + // recgroup
29.413 + // :
29.414 + // "Default")
29.415 + prog->chancommfree = gmyth_string_list_get_int(slist, pos + 31);
29.416 + prog->chanOutputFilters =
29.417 + gmyth_string_list_get_string(slist, pos + 32);
29.418 + prog->seriesid = gmyth_string_list_get_string(slist, pos + 33);
29.419 + prog->program_id = gmyth_string_list_get_string(slist, pos + 34);
29.420 + gmyth_string_list_get_string(slist, pos + 35);
29.421 + prog->lastmodified = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 36)))->str); // DATETIME_TO_LIST(lastmodified)
29.422 + gmyth_string_list_get_int(slist, pos + 37); // FLOAT_TO_LIST(stars)
29.423 + prog->originalAirDate = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 38)))->str); // DATETIME_TO_LIST(QDateTime(originalAirDate))
29.424 + prog->hasAirDate = gmyth_string_list_get_int(slist, pos + 39);
29.425 + prog->playgroup = gmyth_string_list_get_string(slist, pos + 40); // prog->(playgroup
29.426 + //
29.427 + //
29.428 + // !=
29.429 + // "")
29.430 + // ?
29.431 + // playgroup
29.432 + // :
29.433 + // "Default")
29.434 + prog->recpriority2 = gmyth_string_list_get_int(slist, pos + 41);
29.435 +
29.436 + return prog;
29.437 +}
29.438 +
29.439 +/**
29.440 + * Converts an instance of a GMythStringList, to a GMythProgramInfo.
29.441 + *
29.442 + * @param slist The GMythStringList got from the MythTV backend server.
29.443 + *
29.444 + * @return a GMythProgramInfo representing the string list got from network.
29.445 + */
29.446 +GMythProgramInfo *
29.447 +gmyth_program_info_from_string_list(GMythStringList * slist)
29.448 +{
29.449 + GMythProgramInfo *prog = NULL;
29.450 +
29.451 + g_return_val_if_fail(slist != NULL, NULL);
29.452 +
29.453 + prog = gmyth_program_info_from_string_list_from_pos(slist, 0);
29.454 +
29.455 + return prog;
29.456 +}
29.457 +
29.458 +/**
29.459 + * Converts an instance of a GMythStringList, to a GMythProgramInfo ( NEXT_PROGRAM_INFO ).
29.460 + *
29.461 + * @param slist The GMythStringList got from the MythTV backend server.
29.462 + *
29.463 + * @return a GMythProgramInfo representing the string list got from network.
29.464 + */
29.465 +GMythProgramInfo *
29.466 +gmyth_program_info_from_string_list_next_prog(GMythStringList * slist)
29.467 +{
29.468 + GMythProgramInfo *prog = gmyth_program_info_new();
29.469 +
29.470 + g_return_val_if_fail(slist != NULL, NULL);
29.471 +
29.472 + /*
29.473 + * {Home Improvement[]:[]No, No, Godot[]:[] US sitcom about a
29.474 + * DIY-obsessed father of three. When Tim tries to sell off his extra
29.475 + * ticket for an ice hockey game, he is arrested as a tout.[]:[]
29.476 + * Sitcom[]:[]2007-04-18T15:30:00[]:[]2007-04-18T16:00:00[]:[]ABC1[]:[]
29.477 + * /home/hmelo/.mythtv/channels/abc1.jpg[]:[]abc1[]:[]2000[]:[]25725844[]:[]
29.478 + * }
29.479 + */
29.480 +
29.481 + prog->title = gmyth_string_list_get_string(slist, 0);
29.482 + prog->subtitle = gmyth_string_list_get_string(slist, 1);
29.483 + prog->description = gmyth_string_list_get_string(slist, 2);
29.484 + prog->category = gmyth_string_list_get_string(slist, 3);
29.485 + prog->startts = gmyth_util_string_to_time_val(gmyth_string_list_get_char_array(slist, 4)); // DATETIME_TO_LIST(startts)
29.486 + prog->endts = gmyth_util_string_to_time_val(gmyth_string_list_get_char_array(slist, 5)); // DATETIME_TO_LIST(endts)
29.487 + prog->channame = gmyth_string_list_get_string(slist, 6);
29.488 + prog->chansign = gmyth_string_list_get_string(slist, 7);
29.489 + prog->chanstr = gmyth_string_list_get_string(slist, 8);
29.490 + prog->channel_id = gmyth_string_list_get_int (slist, 9);
29.491 + prog->filesize = gmyth_string_list_get_int64(slist, 10);
29.492 +
29.493 + gmyth_debug
29.494 + ("NEXT program info: [ %s, %s, %s, %s, %s, %s, %s, %s ]\n",
29.495 + gmyth_program_info_non_null_value(prog->title),
29.496 + gmyth_program_info_non_null_value(prog->subtitle),
29.497 + gmyth_program_info_non_null_value(prog->description),
29.498 + gmyth_program_info_non_null_value(prog->category),
29.499 + gmyth_program_info_non_null_value(prog->channame),
29.500 + gmyth_program_info_non_null_value(prog->chanstr),
29.501 + gmyth_program_info_non_null_value(prog->chansign),
29.502 + gmyth_program_info_non_null_value(prog->pathname));
29.503 +
29.504 + return prog;
29.505 +}
29.506 +
29.507 +static const gchar *
29.508 +gmyth_program_info_non_null_value(const GString * str)
29.509 +{
29.510 + return (str != NULL && str->str != NULL
29.511 + && strlen(str->str) > 0 ? str->str : " ");
29.512 +}
29.513 +
29.514 +/**
29.515 + * Prints out an instance of a GMythProgramInfo.
29.516 + *
29.517 + * @param prog A GMythProgramInfo instance.
29.518 + *
29.519 + * @return a string representing the program info.
29.520 + */
29.521 +const gchar *
29.522 +gmyth_program_info_to_string(const GMythProgramInfo * prog)
29.523 +{
29.524 + return
29.525 + g_strdup_printf
29.526 + ("Title: %s, Subtitle: %s, Description: %s, Category: %s, Channel ID: %d, "
29.527 + "Channel Name: %s, Chan str: %s, Channel Sign: %s, Path Name: %s, File Size: %lld, \n"
29.528 + "Start TS: %s, End TS: %s, Duplicate: %d, Shareable: %d, Find ID: %d, Hostname: %s, "
29.529 + "Source ID: %d, Vard ID: %d, Input ID: %d, Rec Priority: %d, Reactivate: %d, \n"
29.530 + "Record ID: %d, Rec Start TS: %s, Rec End TS: %s, Repeat: %d, Program Flags: %d, "
29.531 + "Rec Group: %s, Channel Comm Free: %d, Channel Output Filters: %s, Series ID: %s, \n"
29.532 + "Program ID: %s, Last Modified Date: %s, Original Air Date: %s, Has Air Date: %d, "
29.533 + "Play Group: %s.\n",
29.534 + gmyth_program_info_non_null_value(prog->title),
29.535 + gmyth_program_info_non_null_value(prog->subtitle),
29.536 + gmyth_program_info_non_null_value(prog->description),
29.537 + gmyth_program_info_non_null_value(prog->category),
29.538 + prog->channel_id,
29.539 + gmyth_program_info_non_null_value(prog->channame),
29.540 + gmyth_program_info_non_null_value(prog->chanstr),
29.541 + gmyth_program_info_non_null_value(prog->chansign),
29.542 + gmyth_program_info_non_null_value(prog->pathname), prog->filesize,
29.543 + gmyth_util_time_to_string_from_time_val(prog->startts),
29.544 + gmyth_util_time_to_string_from_time_val(prog->endts),
29.545 + prog->duplicate, prog->shareable, prog->findid,
29.546 + gmyth_program_info_non_null_value(prog->hostname), prog->sourceid,
29.547 + prog->cardid, prog->inputid, prog->recpriority, prog->reactivate,
29.548 + prog->recordid,
29.549 + gmyth_util_time_to_string_from_time_val(prog->recstartts),
29.550 + gmyth_util_time_to_string_from_time_val(prog->recendts),
29.551 + prog->repeat, prog->programflags,
29.552 + gmyth_program_info_non_null_value(prog->recgroup),
29.553 + prog->chancommfree,
29.554 + gmyth_program_info_non_null_value(prog->chanOutputFilters),
29.555 + gmyth_program_info_non_null_value(prog->seriesid),
29.556 + gmyth_program_info_non_null_value(prog->program_id),
29.557 + gmyth_util_time_to_string_from_time_val(prog->lastmodified),
29.558 + gmyth_util_time_to_string_from_time_val(prog->originalAirDate),
29.559 + prog->hasAirDate,
29.560 + gmyth_program_info_non_null_value(prog->playgroup));
29.561 +}
29.562 +
29.563 +/**
29.564 + * Say if an instance of a GMythProgramInfo is equals to another one.
29.565 + *
29.566 + * @param prog The first GMythProgramInfo instance.
29.567 + * @param prog The second GMythProgramInfo instance.
29.568 + *
29.569 + * @return <code>true</code>, if the program infos are equals.
29.570 + */
29.571 +gboolean
29.572 +gmyth_program_info_is_equals(const GMythProgramInfo * prog1,
29.573 + const GMythProgramInfo * prog2)
29.574 +{
29.575 + if ((strcmp(gmyth_program_info_non_null_value(prog1->title),
29.576 + gmyth_program_info_non_null_value(prog2->title)) == 0)
29.577 + ||
29.578 + (strcmp
29.579 + (gmyth_program_info_non_null_value(prog1->pathname),
29.580 + gmyth_program_info_non_null_value(prog2->pathname)) == 0))
29.581 + return TRUE;
29.582 + else
29.583 + return FALSE;
29.584 +
29.585 +}
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/gmyth/gmyth/gmyth_programinfo.h Mon Feb 25 17:51:43 2008 +0000
30.3 @@ -0,0 +1,180 @@
30.4 +/**
30.5 + * GMyth Library
30.6 + *
30.7 + * @file gmyth/gmyth_programinfo.h
30.8 + *
30.9 + * @brief <p> GMythProgramInfo representing the program info, with the
30.10 + * configuration data to the actual remote file in the TV chain.
30.11 + *
30.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
30.13 + * @author Rosfran Borges <rosfran.borges@indt.org.br>
30.14 + * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
30.15 + *
30.16 + *
30.17 + * This program is free software; you can redistribute it and/or modify
30.18 + * it under the terms of the GNU Lesser General Public License as published by
30.19 + * the Free Software Foundation; either version 2 of the License, or
30.20 + * (at your option) any later version.
30.21 + *
30.22 + * This program is distributed in the hope that it will be useful,
30.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
30.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30.25 + * GNU General Public License for more details.
30.26 + *
30.27 + * You should have received a copy of the GNU Lesser General Public License
30.28 + * along with this program; if not, write to the Free Software
30.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30.30 + *
30.31 + */
30.32 +
30.33 +#ifndef _GMYTH_PROGRAMINFO_H
30.34 +#define _GMYTH_PROGRAMINFO_H
30.35 +
30.36 +#include <glib.h>
30.37 +#include <glib-object.h>
30.38 +
30.39 +#include "gmyth_stringlist.h"
30.40 +
30.41 +G_BEGIN_DECLS
30.42 +#define GMYTH_PROGRAM_INFO_TYPE (gmyth_program_info_get_type ())
30.43 +#define GMYTH_PROGRAM_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_PROGRAM_INFO_TYPE, GMythProgramInfo))
30.44 +#define GMYTH_PROGRAM_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_PROGRAM_INFO_TYPE, GMythProgramInfoClass))
30.45 +#define IS_GMYTH_PROGRAM_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_PROGRAM_INFO_TYPE))
30.46 +#define IS_GMYTH_PROGRAM_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_PROGRAM_INFO_TYPE))
30.47 +#define GMYTH_PROGRAM_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_PROGRAM_INFO_TYPE, GMythProgramInfoClass))
30.48 +typedef struct _GMythProgramInfo GMythProgramInfo;
30.49 +typedef struct _GMythProgramInfoClass GMythProgramInfoClass;
30.50 +
30.51 +struct _GMythProgramInfoClass {
30.52 + GObjectClass parent_class;
30.53 +
30.54 + /*
30.55 + * callbacks
30.56 + */
30.57 +};
30.58 +
30.59 +/**
30.60 + * The GMythProgramInfo structure represents a program information
30.61 + * stored in the database. It could be a program from the EPG data,
30.62 + * a program scheduled to be recorded, or a program already recorded.
30.63 + */
30.64 +struct _GMythProgramInfo {
30.65 + GObject parent;
30.66 +
30.67 + /** The channel unique ID. */
30.68 + gint channel_id;
30.69 + /** The program start time. */
30.70 + GTimeVal *startts;
30.71 + /** The program end time. */
30.72 + GTimeVal *endts;
30.73 + /** The recording schedule start time. */
30.74 + GTimeVal *recstartts;
30.75 + /** The recording schedule end time */
30.76 + GTimeVal *recendts;
30.77 +
30.78 + /** The program title. */
30.79 + GString *title;
30.80 + /** The program subtitle. */
30.81 + GString *subtitle;
30.82 + /** The program description. */
30.83 + GString *description;
30.84 + /** The program category. */
30.85 + GString *category;
30.86 +
30.87 + GString *chanstr;
30.88 + GString *chansign;
30.89 + /** The associated channel name. */
30.90 + GString *channame;
30.91 + gint chancommfree;
30.92 + GString *chanOutputFilters;
30.93 +
30.94 + GString *seriesid;
30.95 + /** The program unique id. */
30.96 + GString *program_id;
30.97 + GString *catType;
30.98 +
30.99 + GString *sortTitle;
30.100 +
30.101 + /** A flag informing if the program has video or not. */
30.102 + gboolean isVideo;
30.103 + gint lenMins;
30.104 +
30.105 + GString *year;
30.106 + gdouble stars;
30.107 + gint repeat;
30.108 +
30.109 + GTimeVal *originalAirDate;
30.110 + GTimeVal *lastmodified;
30.111 + GTimeVal *lastInUseTime;
30.112 +
30.113 + gboolean hasAirDate;
30.114 +
30.115 + gint spread;
30.116 + gint startCol;
30.117 +
30.118 + gint recpriority2;
30.119 + gint reactivate;
30.120 +
30.121 + gint recordid;
30.122 + gint parentid;
30.123 +
30.124 + /** The backend video source id associated to this program.*/
30.125 + gint sourceid;
30.126 + /** the backend input id associated to this program.*/
30.127 + gint inputid;
30.128 + /** The backend card id associated to this program.*/
30.129 + gint cardid;
30.130 + gboolean shareable;
30.131 + gboolean duplicate;
30.132 +
30.133 + GString *schedulerid;
30.134 + gint findid;
30.135 +
30.136 + gint programflags;
30.137 + gint transcoder;
30.138 +
30.139 + GString *recgroup;
30.140 + GString *playgroup;
30.141 + gint rectype;
30.142 + gint recstatus;
30.143 + gint recpriority;
30.144 + gint dupin;
30.145 + gint dupmethod;
30.146 +
30.147 + /** The file size of the recorded program.*/
30.148 + gint64 filesize;
30.149 +
30.150 + /** The file name of the recorded program.*/
30.151 + GString *pathname;
30.152 + GString *hostname;
30.153 +};
30.154 +
30.155 +GType gmyth_program_info_get_type(void);
30.156 +
30.157 +GMythProgramInfo *gmyth_program_info_new(void);
30.158 +
30.159 +GMythStringList *gmyth_program_info_to_string_list(GMythProgramInfo * prog,
30.160 + GMythStringList *
30.161 + slist);
30.162 +
30.163 +GMythProgramInfo
30.164 + * gmyth_program_info_from_string_list_from_pos(GMythStringList * slist,
30.165 + guint pos);
30.166 +
30.167 +GMythProgramInfo *gmyth_program_info_from_string_list(GMythStringList *
30.168 + slist);
30.169 +
30.170 +GMythProgramInfo
30.171 + * gmyth_program_info_from_string_list_next_prog(GMythStringList *
30.172 + slist);
30.173 +
30.174 +const gchar *gmyth_program_info_to_string(const GMythProgramInfo *
30.175 + prog);
30.176 +
30.177 +gboolean gmyth_program_info_is_equals(const GMythProgramInfo *
30.178 + prog1,
30.179 + const GMythProgramInfo *
30.180 + prog2);
30.181 +
30.182 +G_END_DECLS
30.183 +#endif /*_GMYTH_PROGRAMINFO_H*/
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/gmyth/gmyth/gmyth_query.c Mon Feb 25 17:51:43 2008 +0000
31.3 @@ -0,0 +1,280 @@
31.4 +/**
31.5 + * GMyth Library
31.6 + *
31.7 + * @file gmyth/gmyth_query.c
31.8 + *
31.9 + * @brief <p> GMythQuery class provides a wrapper for accessing
31.10 + * the libmysqlclient funtions.
31.11 + *
31.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
31.13 + * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
31.14 + *
31.15 + *
31.16 + * This program is free software; you can redistribute it and/or modify
31.17 + * it under the terms of the GNU Lesser General Public License as published by
31.18 + * the Free Software Foundation; either version 2 of the License, or
31.19 + * (at your option) any later version.
31.20 + *
31.21 + * This program is distributed in the hope that it will be useful,
31.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
31.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31.24 + * GNU General Public License for more details.
31.25 + *
31.26 + * You should have received a copy of the GNU Lesser General Public License
31.27 + * along with this program; if not, write to the Free Software
31.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31.29 + */
31.30 +
31.31 +#ifdef HAVE_CONFIG_H
31.32 +#include "config.h"
31.33 +#endif
31.34 +
31.35 +#include <stdlib.h>
31.36 +#include <stdio.h>
31.37 +#include <assert.h>
31.38 +
31.39 +#include "gmyth_query.h"
31.40 +#include "gmyth_debug.h"
31.41 +
31.42 +static void gmyth_query_class_init(GMythQueryClass * klass);
31.43 +static void gmyth_query_init(GMythQuery * object);
31.44 +
31.45 +static void gmyth_query_dispose(GObject * object);
31.46 +static void gmyth_query_finalize(GObject * object);
31.47 +
31.48 +static void gmyth_query_print_error(MYSQL * conn, char *message);
31.49 +
31.50 +G_DEFINE_TYPE(GMythQuery, gmyth_query, G_TYPE_OBJECT)
31.51 + static void gmyth_query_class_init(GMythQueryClass * klass)
31.52 +{
31.53 + GObjectClass *gobject_class;
31.54 +
31.55 + gobject_class = (GObjectClass *) klass;
31.56 +
31.57 + gobject_class->dispose = gmyth_query_dispose;
31.58 + gobject_class->finalize = gmyth_query_finalize;
31.59 +}
31.60 +
31.61 +static void
31.62 +gmyth_query_init(GMythQuery * gmyth_query)
31.63 +{
31.64 + gmyth_query->backend_info = NULL;
31.65 +
31.66 + /*
31.67 + * initialize connection handler
31.68 + */
31.69 + gmyth_query->conn = mysql_init(NULL);
31.70 +
31.71 + if (!(gmyth_query->conn))
31.72 + g_warning("[%s] MSQL structure not initialized", __FUNCTION__);
31.73 +}
31.74 +
31.75 +static void
31.76 +gmyth_query_dispose(GObject * object)
31.77 +{
31.78 + GMythQuery *gmyth_query = GMYTH_QUERY(object);
31.79 +
31.80 + if (gmyth_query->conn != NULL) {
31.81 + gmyth_query_disconnect(gmyth_query);
31.82 + }
31.83 +
31.84 + if (gmyth_query->backend_info) {
31.85 + g_object_unref(gmyth_query->backend_info);
31.86 + gmyth_query->backend_info = NULL;
31.87 + }
31.88 +
31.89 + G_OBJECT_CLASS(gmyth_query_parent_class)->dispose(object);
31.90 +}
31.91 +
31.92 +static void
31.93 +gmyth_query_finalize(GObject * object)
31.94 +{
31.95 + g_signal_handlers_destroy(object);
31.96 +
31.97 + G_OBJECT_CLASS(gmyth_query_parent_class)->finalize(object);
31.98 +}
31.99 +
31.100 +/** Creates a new instance of GMythQuery.
31.101 + *
31.102 + * @return a new instance of GMythQuery.
31.103 + */
31.104 +GMythQuery *
31.105 +gmyth_query_new()
31.106 +{
31.107 + GMythQuery *sql_query =
31.108 + GMYTH_QUERY(g_object_new(GMYTH_QUERY_TYPE, NULL));
31.109 +
31.110 + return sql_query;
31.111 +}
31.112 +
31.113 +gboolean
31.114 +gmyth_query_connect_with_timeout(GMythQuery * gmyth_query,
31.115 + GMythBackendInfo * backend_info,
31.116 + guint timeout)
31.117 +{
31.118 + assert(gmyth_query);
31.119 +
31.120 + if (gmyth_query->conn == NULL)
31.121 + gmyth_query->conn = mysql_init(NULL);
31.122 +
31.123 + if (timeout != 0) {
31.124 + /*
31.125 + * sets connection timeout
31.126 + */
31.127 + mysql_options(gmyth_query->conn, MYSQL_OPT_CONNECT_TIMEOUT,
31.128 + (gchar *) & timeout);
31.129 + }
31.130 +
31.131 + return gmyth_query_connect(gmyth_query, backend_info);
31.132 +}
31.133 +
31.134 +/** Connects to the Mysql database in the backend. The backend address
31.135 + * is loaded from the GMythBackendInfo instance.
31.136 + *
31.137 + * @param gmyth_query the GMythEPG instance to be connected.
31.138 + * @return true if connection was success, false if failed.
31.139 + */
31.140 +gboolean
31.141 +gmyth_query_connect(GMythQuery * gmyth_query,
31.142 + GMythBackendInfo * backend_info)
31.143 +{
31.144 + assert(gmyth_query);
31.145 + g_return_val_if_fail(backend_info != NULL, FALSE);
31.146 + g_return_val_if_fail(backend_info->hostname != NULL, FALSE);
31.147 + g_return_val_if_fail(backend_info->username != NULL, FALSE);
31.148 + g_return_val_if_fail(backend_info->password != NULL, FALSE);
31.149 + g_return_val_if_fail(backend_info->db_name != NULL, FALSE);
31.150 +
31.151 + if (gmyth_query->backend_info != NULL) {
31.152 + g_object_unref(gmyth_query->backend_info);
31.153 + }
31.154 + gmyth_query->backend_info = g_object_ref(backend_info);
31.155 +
31.156 + if (gmyth_query->conn == NULL) {
31.157 + gmyth_query->conn = mysql_init(NULL);
31.158 + }
31.159 +
31.160 + /*
31.161 + * connect to server
31.162 + */
31.163 + if (mysql_real_connect(gmyth_query->conn,
31.164 + gmyth_query->backend_info->hostname,
31.165 + gmyth_query->backend_info->username,
31.166 + gmyth_query->backend_info->password,
31.167 + gmyth_query->backend_info->db_name,
31.168 + gmyth_query->backend_info->db_port,
31.169 + NULL,
31.170 + 0) == NULL) {
31.171 + gmyth_query_print_error(gmyth_query->conn,
31.172 + "mysql_real_connect() failed");
31.173 + return FALSE;
31.174 + }
31.175 +
31.176 + gmyth_debug
31.177 + ("[%s] Connection to Mysql server succeeded! (host = %s, user = %s, "
31.178 + "password = %s, db name = %s)", __FUNCTION__,
31.179 + gmyth_query->backend_info->hostname,
31.180 + gmyth_query->backend_info->username,
31.181 + gmyth_query->backend_info->password,
31.182 + gmyth_query->backend_info->db_name);
31.183 +
31.184 + return TRUE;
31.185 +}
31.186 +
31.187 +/** Disconnects from the Mysql database in the backend.
31.188 + *
31.189 + * @param gmyth_query the GMythQuery instance to be disconnected
31.190 + * @return true if disconnection was success, false if failed.
31.191 + */
31.192 +gboolean
31.193 +gmyth_query_disconnect(GMythQuery * gmyth_query)
31.194 +{
31.195 + g_return_val_if_fail(gmyth_query != NULL, FALSE);
31.196 + g_return_val_if_fail(gmyth_query->conn != NULL, FALSE);
31.197 +
31.198 + /*
31.199 + * TODO: Check how to return error
31.200 + */
31.201 + gmyth_debug("[%s] Closing gmyth_query->conn", __FUNCTION__);
31.202 +
31.203 + mysql_close(gmyth_query->conn);
31.204 + gmyth_query->conn = NULL;
31.205 +
31.206 + return TRUE;
31.207 +}
31.208 +
31.209 +static void
31.210 +gmyth_query_print_error(MYSQL * conn, char *message)
31.211 +{
31.212 + gmyth_debug("%s", message);
31.213 +
31.214 + if (conn != NULL) {
31.215 +#if MYSQL_VERSION_ID >= 40101
31.216 + gmyth_debug("Error %u (%s): %s\n",
31.217 + mysql_errno(conn), mysql_sqlstate(conn),
31.218 + mysql_error(conn));
31.219 +#else
31.220 + gmyth_debug("Error %u: %s\n", mysql_errno(conn),
31.221 + mysql_error(conn));
31.222 +#endif
31.223 + }
31.224 +}
31.225 +
31.226 +/** Sends the given query to the backend returning the query result as
31.227 + * MYSQL_RES pointer.
31.228 + *
31.229 + * FIXME: this function is returning NULL whether any error happens
31.230 + * or no rows are returned (e.g. UPDATE or REPLACE).
31.231 + *
31.232 + * @param gmyth_query the GMythQuery instance.
31.233 + * @param stmt_str the query text.
31.234 + * @return the MYSQL_RES result pointer or NULL if any error happens.
31.235 + */
31.236 +MYSQL_RES*
31.237 +gmyth_query_process_statement(GMythQuery * gmyth_query, char *stmt_str)
31.238 +{
31.239 + assert(gmyth_query);
31.240 +
31.241 + gmyth_debug("[%s] Running mysql query %s", __FUNCTION__, stmt_str);
31.242 +
31.243 + if (gmyth_query == NULL)
31.244 + return NULL;
31.245 +
31.246 + //the statement failed
31.247 + if (mysql_query(gmyth_query->conn, stmt_str) != 0) {
31.248 + gmyth_query_print_error(gmyth_query->conn,
31.249 + "Could not execute statement");
31.250 + return NULL;
31.251 + }
31.252 +
31.253 + //the statement succeeded; determine whether it returned data
31.254 + return mysql_store_result(gmyth_query->conn);
31.255 +}
31.256 +
31.257 +MYSQL_RES*
31.258 +gmyth_query_process_statement_with_increment(GMythQuery * gmyth_query,
31.259 + char *stmt_str, gulong * id)
31.260 +{
31.261 + assert(gmyth_query);
31.262 +
31.263 + gmyth_debug("[%s] Running mysql query %s", __FUNCTION__, stmt_str);
31.264 +
31.265 + if (gmyth_query == NULL)
31.266 + return NULL;
31.267 +
31.268 + /*
31.269 + * the statement failed
31.270 + */
31.271 + if (mysql_query(gmyth_query->conn, stmt_str) != 0) {
31.272 + gmyth_query_print_error(gmyth_query->conn,
31.273 + "Could not execute statement");
31.274 + return NULL;
31.275 + }
31.276 +
31.277 + *id = (my_ulonglong) mysql_insert_id(gmyth_query->conn);
31.278 +
31.279 + /*
31.280 + * the statement succeeded; determine whether it returned data
31.281 + */
31.282 + return mysql_store_result(gmyth_query->conn);
31.283 +}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/gmyth/gmyth/gmyth_query.h Mon Feb 25 17:51:43 2008 +0000
32.3 @@ -0,0 +1,93 @@
32.4 +/**
32.5 + * GMyth Library
32.6 + *
32.7 + * @file gmyth/gmyth_query.h
32.8 + *
32.9 + * @brief <p> GMythQuery class provides a wrapper for accessing
32.10 + * the libmysqlclient funtions.
32.11 + *
32.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
32.13 + * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
32.14 + *
32.15 + *
32.16 + * This program is free software; you can redistribute it and/or modify
32.17 + * it under the terms of the GNU Lesser General Public License as published by
32.18 + * the Free Software Foundation; either version 2 of the License, or
32.19 + * (at your option) any later version.
32.20 + *
32.21 + * This program is distributed in the hope that it will be useful,
32.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
32.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32.24 + * GNU General Public License for more details.
32.25 + *
32.26 + * You should have received a copy of the GNU Lesser General Public License
32.27 + * along with this program; if not, write to the Free Software
32.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
32.29 + */
32.30 +
32.31 +#ifndef __GMYTH_QUERY_H__
32.32 +#define __GMYTH_QUERY_H__
32.33 +
32.34 +#include <glib-object.h>
32.35 +
32.36 +/*
32.37 + * MYSQL includes
32.38 + */
32.39 +#include <mysql/mysql.h>
32.40 +
32.41 +#include "gmyth_backendinfo.h"
32.42 +
32.43 +G_BEGIN_DECLS
32.44 +#define GMYTH_QUERY_TYPE (gmyth_query_get_type ())
32.45 +#define GMYTH_QUERY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_QUERY_TYPE, GMythQuery))
32.46 +#define GMYTH_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_QUERY_TYPE, GMythQueryClass))
32.47 +#define IS_GMYTH_QUERY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_QUERY_TYPE))
32.48 +#define IS_GMYTH_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_QUERY_TYPE))
32.49 +#define GMYTH_QUERY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_QUERY_TYPE, GMythQueryClass))
32.50 +typedef struct _GMythQuery GMythQuery;
32.51 +typedef struct _GMythQueryClass GMythQueryClass;
32.52 +
32.53 +struct _GMythQueryClass {
32.54 + GObjectClass parent_class;
32.55 +
32.56 + /*
32.57 + * callbacks
32.58 + */
32.59 + /*
32.60 + * no one for now
32.61 + */
32.62 +};
32.63 +
32.64 +struct _GMythQuery {
32.65 + GObject parent;
32.66 +
32.67 + GMythBackendInfo *backend_info;
32.68 +
32.69 + /*
32.70 + * pointer to connection handler
32.71 + */
32.72 + MYSQL *conn;
32.73 +};
32.74 +
32.75 +
32.76 +GType gmyth_query_get_type(void);
32.77 +
32.78 +GMythQuery *gmyth_query_new(void);
32.79 +MYSQL_RES *gmyth_query_process_statement(GMythQuery * gmyth_query,
32.80 + gchar * stmt_str);
32.81 +MYSQL_RES *gmyth_query_process_statement_with_increment(GMythQuery *
32.82 + gmyth_query,
32.83 + char
32.84 + *stmt_str,
32.85 + gulong * id);
32.86 +
32.87 +gboolean gmyth_query_connect(GMythQuery * gmyth_query,
32.88 + GMythBackendInfo * backend_info);
32.89 +gboolean gmyth_query_connect_with_timeout(GMythQuery * gmyth_query,
32.90 + GMythBackendInfo *
32.91 + backend_info,
32.92 + guint timeout);
32.93 +gboolean gmyth_query_disconnect(GMythQuery * gmyth_query);
32.94 +
32.95 +G_END_DECLS
32.96 +#endif /* __GMYTH_QUERY_H__ */
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
33.2 +++ b/gmyth/gmyth/gmyth_recorder.c Mon Feb 25 17:51:43 2008 +0000
33.3 @@ -0,0 +1,1388 @@
33.4 +/**
33.5 + * GMyth Library
33.6 + *
33.7 + * @file gmyth/gmyth_recorder.c
33.8 + *
33.9 + * @brief <p> GMythRecorder defines functions for playing live tv.
33.10 + *
33.11 + * The remote encoder is used by gmyth_tvplayer to setup livetv.
33.12 + *
33.13 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
33.14 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
33.15 + * @author Rosfran Borges <rosfran.borges@indt.org.br>
33.16 + *
33.17 + *
33.18 + * This program is free software; you can redistribute it and/or modify
33.19 + * it under the terms of the GNU Lesser General Public License as published by
33.20 + * the Free Software Foundation; either version 2 of the License, or
33.21 + * (at your option) any later version.
33.22 + *
33.23 + * This program is distributed in the hope that it will be useful,
33.24 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
33.25 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33.26 + * GNU General Public License for more details.
33.27 + *
33.28 + * You should have received a copy of the GNU Lesser General Public License
33.29 + * along with this program; if not, write to the Free Software
33.30 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33.31 + */
33.32 +
33.33 +#ifdef HAVE_CONFIG_H
33.34 +#include "config.h"
33.35 +#endif
33.36 +
33.37 +#include "gmyth_recorder.h"
33.38 +
33.39 +#include <assert.h>
33.40 +
33.41 +#include "gmyth_stringlist.h"
33.42 +#include "gmyth_util.h"
33.43 +#include "gmyth_common.h"
33.44 +#include "gmyth_debug.h"
33.45 +
33.46 +#define GMYTHTV_RECORDER_HEADER "QUERY_RECORDER"
33.47 +
33.48 +static void gmyth_recorder_class_init(GMythRecorderClass * klass);
33.49 +static void gmyth_recorder_init(GMythRecorder * object);
33.50 +
33.51 +static void gmyth_recorder_dispose(GObject * object);
33.52 +static void gmyth_recorder_finalize(GObject * object);
33.53 +
33.54 +G_DEFINE_TYPE(GMythRecorder, gmyth_recorder, G_TYPE_OBJECT)
33.55 + static void gmyth_recorder_class_init(GMythRecorderClass * klass)
33.56 +{
33.57 + GObjectClass *gobject_class;
33.58 +
33.59 + gobject_class = (GObjectClass *) klass;
33.60 +
33.61 + gobject_class->dispose = gmyth_recorder_dispose;
33.62 + gobject_class->finalize = gmyth_recorder_finalize;
33.63 +}
33.64 +
33.65 +static void
33.66 +gmyth_recorder_init(GMythRecorder * gmyth_remote_encoder)
33.67 +{
33.68 +}
33.69 +
33.70 +static void
33.71 +gmyth_recorder_dispose(GObject * object)
33.72 +{
33.73 + GMythRecorder *recorder = GMYTH_RECORDER(object);
33.74 +
33.75 + gmyth_recorder_close(recorder);
33.76 +
33.77 + if (recorder->mutex != NULL) {
33.78 + g_mutex_free(recorder->mutex);
33.79 + recorder->mutex = NULL;
33.80 + }
33.81 +
33.82 + if (recorder->myth_socket != NULL) {
33.83 + g_object_unref(recorder->myth_socket);
33.84 + recorder->myth_socket = NULL;
33.85 + }
33.86 +
33.87 + if (recorder->progs_info_list != NULL)
33.88 + gmyth_free_program_list(recorder->progs_info_list);
33.89 +
33.90 + if (recorder->hostname != NULL)
33.91 + g_string_free(recorder->hostname, TRUE);
33.92 +
33.93 + G_OBJECT_CLASS(gmyth_recorder_parent_class)->dispose(object);
33.94 +}
33.95 +
33.96 +static void
33.97 +gmyth_recorder_finalize(GObject * object)
33.98 +{
33.99 + g_signal_handlers_destroy(object);
33.100 +
33.101 + G_OBJECT_CLASS(gmyth_recorder_parent_class)->finalize(object);
33.102 +}
33.103 +
33.104 +void
33.105 +gmyth_recorder_close(GMythRecorder * recorder)
33.106 +{
33.107 + if (recorder != NULL && recorder->recorder_num != -1) {
33.108 + g_mutex_lock(recorder->mutex);
33.109 +
33.110 + gmyth_recorder_stop_playing(recorder);
33.111 + gmyth_recorder_stop_livetv(recorder);
33.112 + gmyth_recorder_finish_recording(recorder);
33.113 + gmyth_recorder_free_tuner(recorder);
33.114 +
33.115 + g_mutex_unlock(recorder->mutex);
33.116 + }
33.117 +}
33.118 +
33.119 +/** Creates a new instance of GMythRecorder.
33.120 + *
33.121 + * @return a new instance of GMythRecorder.
33.122 + */
33.123 +GMythRecorder *
33.124 +gmyth_recorder_new(int num, GString * hostname, gshort port)
33.125 +{
33.126 + GMythRecorder *encoder =
33.127 + GMYTH_RECORDER(g_object_new(GMYTH_RECORDER_TYPE, FALSE));
33.128 +
33.129 + encoder->recorder_num = num;
33.130 + encoder->hostname = g_string_new(hostname->str);
33.131 + encoder->port = port;
33.132 +
33.133 + encoder->mutex = g_mutex_new();
33.134 +
33.135 + encoder->progs_info_list = NULL;
33.136 +
33.137 + return encoder;
33.138 +}
33.139 +
33.140 +/** Configures the remote encoder instance connecting it to Mythtv backend.
33.141 + *
33.142 + * @param recorder the GMythRecorder instance.
33.143 + *
33.144 + * @return TRUE if successfull, FALSE if any error happens.
33.145 + */
33.146 +gboolean
33.147 +gmyth_recorder_setup(GMythRecorder * recorder)
33.148 +{
33.149 + assert(recorder);
33.150 + gmyth_debug("[%s] Creating socket and connecting to backend",
33.151 + __FUNCTION__);
33.152 +
33.153 + if (recorder->myth_socket == NULL) {
33.154 + recorder->myth_socket = gmyth_socket_new();
33.155 +
33.156 + if (!gmyth_socket_connect_to_backend(recorder->myth_socket,
33.157 + recorder->hostname->str,
33.158 + recorder->port, TRUE)) {
33.159 + gmyth_debug
33.160 + ("GMythRemoteEncoder: Connection to backend failed");
33.161 + return FALSE;
33.162 + }
33.163 + } else {
33.164 + gmyth_debug("Remote encoder socket already created\n");
33.165 + }
33.166 +
33.167 + return TRUE;
33.168 +}
33.169 +
33.170 +/** Sends the SPAWN_LIVETV command through Mythtv protocol. This command
33.171 + * requests the backend to start capturing TV content.
33.172 + *
33.173 + * @param recorder The GMythRecorder instance.
33.174 + * @param tvchain_id The tvchain unique id.
33.175 + * @return true if success, false if any error happens.
33.176 + */
33.177 +gboolean
33.178 +gmyth_recorder_spawntv(GMythRecorder * recorder, GString * tvchain_id)
33.179 +{
33.180 + GMythStringList *str_list;
33.181 + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
33.182 + gboolean ret = TRUE;
33.183 +
33.184 + gmyth_debug("[%s] Spawntv with tvchain_id = %s", __FUNCTION__,
33.185 + tvchain_id->str);
33.186 +
33.187 + str_list = gmyth_string_list_new();
33.188 +
33.189 + g_mutex_lock(recorder->mutex);
33.190 +
33.191 + g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
33.192 +
33.193 + gmyth_string_list_append_string(str_list, tmp_str);
33.194 + g_string_free(tmp_str, TRUE);
33.195 +
33.196 + gmyth_string_list_append_char_array(str_list, "SPAWN_LIVETV");
33.197 +
33.198 + gmyth_string_list_append_string(str_list, tvchain_id);
33.199 + gmyth_string_list_append_int(str_list, 0); // PIP = FALSE (0)
33.200 +
33.201 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
33.202 +
33.203 + tmp_str = gmyth_string_list_get_string(str_list, 0);
33.204 +
33.205 + if (tmp_str == NULL) {
33.206 + gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__,
33.207 + tmp_str->str);
33.208 + ret = FALSE;
33.209 + goto cleanup;
33.210 + }
33.211 +
33.212 + if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
33.213 + gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__,
33.214 + tmp_str->str);
33.215 + ret = FALSE;
33.216 + goto cleanup;
33.217 + }
33.218 +
33.219 + cleanup:
33.220 + g_mutex_unlock(recorder->mutex);
33.221 +
33.222 + g_string_free(tmp_str, TRUE);
33.223 + g_object_unref(str_list);
33.224 +
33.225 + return ret;
33.226 +}
33.227 +
33.228 +/**
33.229 + * Sends the SPAWN_LIVETV command through Mythtv protocol. This command
33.230 + * requests the backend to start capturing TV content, but it doesn't need
33.231 + * the TV chain ID.
33.232 + *
33.233 + * @param recorder The GMythRecorder instance.
33.234 + * @return true if success, false if any error happens.
33.235 + */
33.236 +gboolean
33.237 +gmyth_recorder_spawntv_no_tvchain(GMythRecorder * recorder)
33.238 +{
33.239 + GMythStringList *str_list;
33.240 + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
33.241 + gboolean ret = TRUE;
33.242 +
33.243 + gmyth_debug("[%s] Spawntv, no TV chain!", __FUNCTION__);
33.244 +
33.245 + str_list = gmyth_string_list_new();
33.246 +
33.247 + g_mutex_lock(recorder->mutex);
33.248 +
33.249 + g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
33.250 +
33.251 + gmyth_string_list_append_string(str_list, tmp_str);
33.252 + g_string_free(tmp_str, TRUE);
33.253 +
33.254 + gmyth_string_list_append_char_array(str_list, "SPAWN_LIVETV");
33.255 +
33.256 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
33.257 +
33.258 + tmp_str = gmyth_string_list_get_string(str_list, 0);
33.259 +
33.260 + if (tmp_str == NULL) {
33.261 + gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__,
33.262 + tmp_str->str);
33.263 + ret = FALSE;
33.264 + goto cleanup;
33.265 + }
33.266 +
33.267 + if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
33.268 + gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__,
33.269 + tmp_str->str);
33.270 + ret = FALSE;
33.271 + goto cleanup;
33.272 + }
33.273 +
33.274 + cleanup:
33.275 + g_mutex_unlock(recorder->mutex);
33.276 +
33.277 + g_string_free(tmp_str, TRUE);
33.278 + g_object_unref(str_list);
33.279 +
33.280 + return ret;
33.281 +}
33.282 +
33.283 +/** Sends the command STOP_LIVETV to Mythtv backend.
33.284 + *
33.285 + * @param recorder the GMythRecorder instance.
33.286 + * @return true if success, false if any error happens.
33.287 + */
33.288 +gboolean
33.289 +gmyth_recorder_stop_livetv(GMythRecorder * recorder)
33.290 +{
33.291 + GMythStringList *str_list;
33.292 + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
33.293 + gboolean ret = TRUE;
33.294 +
33.295 + gmyth_debug("[%s]", __FUNCTION__);
33.296 +
33.297 + str_list = gmyth_string_list_new();
33.298 +
33.299 + g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
33.300 +
33.301 + gmyth_string_list_append_string(str_list, tmp_str);
33.302 + g_string_free(tmp_str, TRUE);
33.303 +
33.304 + gmyth_string_list_append_char_array(str_list, "STOP_LIVETV");
33.305 +
33.306 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
33.307 +
33.308 + tmp_str = gmyth_string_list_get_string(str_list, 0);
33.309 +
33.310 + if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
33.311 + gmyth_debug("[%s] Stop livetv request returned %s", __FUNCTION__,
33.312 + tmp_str->str);
33.313 + ret = FALSE;
33.314 + goto cleanup;
33.315 + }
33.316 +
33.317 + cleanup:
33.318 + g_string_free(tmp_str, TRUE);
33.319 + g_object_unref(str_list);
33.320 +
33.321 + return ret;
33.322 +}
33.323 +
33.324 +/** Sends the FRONTEND_READY command through Mythtv protocol. This command
33.325 + * advertises the backend to start capturing TV content.
33.326 + *
33.327 + * @param recorder The GMythRecorder instance.
33.328 + * @return TRUE if success, FALSE if any error happens.
33.329 + */
33.330 +gboolean
33.331 +gmyth_recorder_send_frontend_ready_command(GMythRecorder * recorder)
33.332 +{
33.333 + GMythStringList *str_list;
33.334 + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
33.335 + gboolean ret = TRUE;
33.336 +
33.337 + gmyth_debug("[%s] FRONTEND_READY with recorder id = %d", __FUNCTION__,
33.338 + recorder->recorder_num);
33.339 +
33.340 + str_list = gmyth_string_list_new();
33.341 +
33.342 + g_mutex_lock(recorder->mutex);
33.343 +
33.344 + g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
33.345 +
33.346 + gmyth_string_list_append_string(str_list, tmp_str);
33.347 + g_string_free(tmp_str, TRUE);
33.348 +
33.349 + gmyth_string_list_append_char_array(str_list, "FRONTEND_READY");
33.350 +
33.351 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
33.352 +
33.353 + tmp_str = gmyth_string_list_get_string(str_list, 0);
33.354 +
33.355 + if (tmp_str == NULL) {
33.356 + gmyth_debug
33.357 + ("[%s] FRONTEND_READY command request couldn't returns, reason: %s",
33.358 + __FUNCTION__, tmp_str->str);
33.359 + ret = FALSE;
33.360 + goto cleanup;
33.361 + }
33.362 +
33.363 + if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
33.364 + gmyth_debug("[%s] FRONTEND_READY request returned %s",
33.365 + __FUNCTION__, tmp_str->str);
33.366 + ret = FALSE;
33.367 + goto cleanup;
33.368 + }
33.369 +
33.370 + cleanup:
33.371 + g_mutex_unlock(recorder->mutex);
33.372 + g_string_free(tmp_str, TRUE);
33.373 + g_object_unref(str_list);
33.374 +
33.375 + return ret;
33.376 +}
33.377 +
33.378 +/** Send a CHECK_CHANNEL command request to the backend, in order to find if a
33.379 + * certain channel actually exists.
33.380 + *
33.381 + * @param recorder The GMythRecorder instance.
33.382 + * @param channel The new channel to be checked (string format).
33.383 + * @return true if success, false if any error happens.
33.384 + */
33.385 +gboolean
33.386 +gmyth_recorder_check_channel_name(GMythRecorder * recorder,
33.387 + gchar * channel)
33.388 +{
33.389 + GMythStringList *str_list;
33.390 + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
33.391 + gboolean ret = TRUE;
33.392 +
33.393 + gmyth_debug("[%s] CHECK_CHANNEL with channel = %s", __FUNCTION__,
33.394 + channel);
33.395 +
33.396 + str_list = gmyth_string_list_new();
33.397 +
33.398 + g_mutex_lock(recorder->mutex);
33.399 +
33.400 + g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
33.401 +
33.402 + gmyth_string_list_append_string(str_list, tmp_str);
33.403 + g_string_free(tmp_str, TRUE);
33.404 +
33.405 + gmyth_string_list_append_char_array(str_list, "CHECK_CHANNEL");
33.406 +
33.407 + gmyth_string_list_append_char_array(str_list, channel);
33.408 +
33.409 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
33.410 +
33.411 + tmp_str = gmyth_string_list_get_string(str_list, 0);
33.412 +
33.413 + if (tmp_str == NULL) {
33.414 + gmyth_debug("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__,
33.415 + tmp_str->str);
33.416 + ret = FALSE;
33.417 + goto cleanup;
33.418 + }
33.419 +
33.420 + if (g_ascii_strncasecmp(tmp_str->str, "ok", 2) == 0
33.421 + || g_ascii_strncasecmp(tmp_str->str, "0", 1) == 0) {
33.422 + gmyth_debug("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__,
33.423 + tmp_str->str);
33.424 + ret = FALSE;
33.425 + goto cleanup;
33.426 + }
33.427 +
33.428 + cleanup:
33.429 + g_mutex_unlock(recorder->mutex);
33.430 + g_string_free(tmp_str, TRUE);
33.431 + g_object_unref(str_list);
33.432 +
33.433 + return ret;
33.434 +}
33.435 +
33.436 +/** Send a CHECK_CHANNEL command request to the backend, in order to find if a
33.437 + * certain channel actually exists.
33.438 + *
33.439 + * @param recorder The GMythRecorder instance.
33.440 + * @param channel The new channel to be checked (decimal integer value).
33.441 + * @return true if success, false if any error happens.
33.442 + */
33.443 +gboolean
33.444 +gmyth_recorder_check_channel(GMythRecorder * recorder, gint channel)
33.445 +{
33.446 + return gmyth_recorder_check_channel_name(recorder,
33.447 + g_strdup_printf("%d",
33.448 + channel));
33.449 +}
33.450 +
33.451 +/** Send a SET_CHANNEL command request to the backend, to start streaming on another
33.452 + * TV content channel.
33.453 + *
33.454 + * @param recorder The GMythRecorder instance.
33.455 + * @param channel The new channel to be loaded.
33.456 + * @return true if success, false if any error happens.
33.457 + */
33.458 +gboolean
33.459 +gmyth_recorder_set_channel(GMythRecorder * recorder, gint channel)
33.460 +{
33.461 + GMythStringList *str_list;
33.462 + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
33.463 + gboolean ret = TRUE;
33.464 +
33.465 + gmyth_debug("[%s] SET_CHANNEL with channel = %d", __FUNCTION__,
33.466 + channel);
33.467 +
33.468 + str_list = gmyth_string_list_new();
33.469 +
33.470 + g_mutex_lock(recorder->mutex);
33.471 +
33.472 + g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
33.473 +
33.474 + gmyth_string_list_append_string(str_list, tmp_str);
33.475 + g_string_free(tmp_str, TRUE);
33.476 +
33.477 + gmyth_string_list_append_char_array(str_list, "SET_CHANNEL");
33.478 +
33.479 + gmyth_string_list_append_int(str_list, channel);
33.480 +
33.481 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
33.482 +
33.483 + tmp_str = gmyth_string_list_get_string(str_list, 0);
33.484 +
33.485 + if (tmp_str == NULL) {
33.486 + gmyth_debug("[%s] SET_CHANNEL request returned %s", __FUNCTION__,
33.487 + tmp_str->str);
33.488 + ret = FALSE;
33.489 + goto cleanup;
33.490 + }
33.491 +
33.492 + if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
33.493 + gmyth_debug("[%s] SET_CHANNEL request returned %s", __FUNCTION__,
33.494 + tmp_str->str);
33.495 + ret = FALSE;
33.496 + goto cleanup;
33.497 + }
33.498 +
33.499 + cleanup:
33.500 + g_mutex_unlock(recorder->mutex);
33.501 + g_string_free(tmp_str, TRUE);
33.502 + g_object_unref(str_list);
33.503 +
33.504 + return ret;
33.505 +}
33.506 +
33.507 +/** Send a SET_CHANNEL command request to the backend, to start streaming on another
33.508 + * TV content channel.
33.509 + *
33.510 + * @param recorder The GMythRecorder instance.
33.511 + * @param channel The new channel to be loaded.
33.512 + * @return true if success, false if any error happens.
33.513 + */
33.514 +gboolean
33.515 +gmyth_recorder_set_channel_name(GMythRecorder * recorder,
33.516 + const gchar * channel)
33.517 +{
33.518 + GMythStringList *str_list;
33.519 + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
33.520 + gboolean ret = TRUE;
33.521 +
33.522 + gmyth_debug("[%s] SET_CHANNEL with channel name = %s", __FUNCTION__,
33.523 + channel);
33.524 +
33.525 + str_list = gmyth_string_list_new();
33.526 +
33.527 + g_mutex_lock(recorder->mutex);
33.528 +
33.529 + g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
33.530 +
33.531 + gmyth_string_list_append_string(str_list, tmp_str);
33.532 + g_string_free(tmp_str, TRUE);
33.533 +
33.534 + gmyth_string_list_append_char_array(str_list, "SET_CHANNEL");
33.535 + gmyth_string_list_append_char_array(str_list, channel);
33.536 +
33.537 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
33.538 +
33.539 + tmp_str = gmyth_string_list_get_string(str_list, 0);
33.540 +
33.541 + if (tmp_str == NULL) {
33.542 + gmyth_debug("[%s] SET_CHANNEL name request returned NULL!",
33.543 + __FUNCTION__);
33.544 + ret = FALSE;
33.545 + goto cleanup;
33.546 + }
33.547 +
33.548 + if (tmp_str != NULL && g_ascii_strncasecmp(tmp_str->str, "ok", 2)
33.549 + /*
33.550 + * || g_ascii_strtoull( tmp_str->str, NULL, 10 ) == 0
33.551 + */
33.552 + ) {
33.553 + g_warning("[%s] SET_CHANNEL name request returned not ok",
33.554 + __FUNCTION__);
33.555 + ret = FALSE;
33.556 + goto cleanup;
33.557 + }
33.558 +
33.559 + cleanup:
33.560 + g_mutex_unlock(recorder->mutex);
33.561 + g_string_free(tmp_str, TRUE);
33.562 + g_object_unref(str_list);
33.563 +
33.564 + return ret;
33.565 +}
33.566 +
33.567 +/**
33.568 + * Changes the channel of the actual Recorder.
33.569 + *
33.570 + * CHANNEL_DIRECTION_UP - Go up one channel in the listing
33.571 + *
33.572 + * CHANNEL_DIRECTION_DOWN - Go down one channel in the listing
33.573 + *
33.574 + * CHANNEL_DIRECTION_FAVORITE - Go to the next favorite channel
33.575 + *
33.576 + * CHANNEL_DIRECTION_SAME - Stay
33.577 + *
33.578 + * @param recorder The GMythRecorder instance.
33.579 + * @param direction The new channel direction where to move to.
33.580 + * @return true if success, false if any error happens.
33.581 + */
33.582 +gboolean
33.583 +gmyth_recorder_change_channel(GMythRecorder * recorder,
33.584 + const GMythRecorderChannelChangeDirection
33.585 + direction)
33.586 +{
33.587 + GMythStringList *str_list;
33.588 + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
33.589 + gboolean ret = TRUE;
33.590 +
33.591 + gmyth_debug("[%s] CHANGE_CHANNEL to the channel direction = %u",
33.592 + __FUNCTION__, direction);
33.593 +
33.594 + str_list = gmyth_string_list_new();
33.595 +
33.596 + g_mutex_lock(recorder->mutex);
33.597 +
33.598 + g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
33.599 +
33.600 + gmyth_string_list_append_string(str_list, tmp_str);
33.601 + g_string_free(tmp_str, TRUE);
33.602 +
33.603 + gmyth_string_list_append_char_array(str_list, "CHANGE_CHANNEL");
33.604 + gmyth_string_list_append_int(str_list, direction);
33.605 +
33.606 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
33.607 +
33.608 + tmp_str = gmyth_string_list_get_string(str_list, 0);
33.609 +
33.610 + if (tmp_str == NULL) {
33.611 + gmyth_debug("[%s] CHANGE_CHANNEL name request returned %s",
33.612 + __FUNCTION__, tmp_str->str);
33.613 + ret = FALSE;
33.614 + goto cleanup;
33.615 + }
33.616 +
33.617 + if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)
33.618 + || g_ascii_strtoull(tmp_str->str, NULL, 10) == 0) {
33.619 + gmyth_debug("[%s] CHANGE_CHANNEL name request returned %s",
33.620 + __FUNCTION__, tmp_str->str);
33.621 + ret = FALSE;
33.622 + goto cleanup;
33.623 + }
33.624 +
33.625 + cleanup:
33.626 + g_mutex_unlock(recorder->mutex);
33.627 + g_string_free(tmp_str, TRUE);
33.628 + g_object_unref(str_list);
33.629 +
33.630 + return ret;
33.631 +}
33.632 +
33.633 +/**
33.634 + * Gets the channel's list from the MythTV backend server.
33.635 + *
33.636 + * @param recorder The GMythRecorder instance.
33.637 + *
33.638 + * @return a GList* instance with all the channel names.
33.639 + */
33.640 +GList *
33.641 +gmyth_recorder_get_channel_list(GMythRecorder * recorder)
33.642 +{
33.643 +
33.644 + GList *channel_list = NULL;
33.645 + gchar *channel = NULL;
33.646 + guint i;
33.647 +
33.648 + for (i = 0; i < 1000; i++) {
33.649 + channel = g_strdup_printf("%u", i);
33.650 +
33.651 + if (gmyth_recorder_check_channel_name(recorder, channel)) {
33.652 + channel_list = g_list_append(channel_list, g_strdup(channel));
33.653 + }
33.654 +
33.655 + } /* for - channel list */
33.656 +
33.657 + g_free(channel);
33.658 +
33.659 + return channel_list;
33.660 +
33.661 +}
33.662 +
33.663 +/** Send a PAUSE command request to the backend, to pause streaming on another
33.664 + * TV content channel.
33.665 + *
33.666 + * @param recorder The GMythRecorder instance.
33.667 + * @return true if success, false if any error happens.
33.668 + */
33.669 +gboolean
33.670 +gmyth_recorder_pause_recording(GMythRecorder * recorder)
33.671 +{
33.672 + GMythStringList *str_list;
33.673 + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
33.674 + gboolean ret = TRUE;
33.675 +
33.676 + gmyth_debug("[%s] PAUSE", __FUNCTION__);
33.677 +
33.678 + str_list = gmyth_string_list_new();
33.679 +
33.680 + g_mutex_lock(recorder->mutex);
33.681 +
33.682 + g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
33.683 +
33.684 + gmyth_string_list_append_string(str_list, tmp_str);
33.685 + g_string_free(tmp_str, TRUE);
33.686 +
33.687 + gmyth_string_list_append_char_array(str_list, "PAUSE");
33.688 +
33.689 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
33.690 +
33.691 + tmp_str = gmyth_string_list_get_string(str_list, 0);
33.692 +
33.693 + if (tmp_str == NULL) {
33.694 + gmyth_debug("[%s] PAUSE name request returned %s", __FUNCTION__,
33.695 + tmp_str->str);
33.696 + ret = FALSE;
33.697 + goto cleanup;
33.698 + }
33.699 +
33.700 + if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
33.701 + gmyth_debug("[%s] PAUSE name request returned %s", __FUNCTION__,
33.702 + tmp_str->str);
33.703 + ret = FALSE;
33.704 + goto cleanup;
33.705 + }
33.706 +
33.707 + cleanup:
33.708 + g_mutex_unlock(recorder->mutex);
33.709 + g_string_free(tmp_str, TRUE);
33.710 + g_object_unref(str_list);
33.711 +
33.712 + return ret;
33.713 +}
33.714 +
33.715 +static gboolean
33.716 +gmyth_recorder_find_if_program_exists(GMythRecorder * recorder,
33.717 + GMythProgramInfo * prog)
33.718 +{
33.719 + GList *lst = NULL;
33.720 +
33.721 + g_return_val_if_fail(recorder != NULL
33.722 + && recorder->progs_info_list != NULL, FALSE);
33.723 +
33.724 + for (lst = recorder->progs_info_list; lst != NULL;
33.725 + lst = g_list_next(lst)) {
33.726 + gmyth_debug("Got program info from list = [%s]",
33.727 + gmyth_program_info_to_string((GMythProgramInfo *)
33.728 + lst->data));
33.729 + if (gmyth_program_info_is_equals
33.730 + (prog, (GMythProgramInfo *) lst->data))
33.731 + return TRUE;
33.732 + }
33.733 +
33.734 + return FALSE;
33.735 +}
33.736 +
33.737 +/**
33.738 + * Requests the actual program info from the MythTV backend server.
33.739 + *
33.740 + * @param recorder The GMythRecorder instance.
33.741 + * @return The actual program info.
33.742 + */
33.743 +GMythProgramInfo *
33.744 +gmyth_recorder_get_current_program_info(GMythRecorder * recorder)
33.745 +{
33.746 + GMythStringList *str_list = NULL;
33.747 + GMythProgramInfo *program_info = NULL;
33.748 + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
33.749 +
33.750 + str_list = gmyth_string_list_new();
33.751 +
33.752 + g_mutex_lock(recorder->mutex);
33.753 +
33.754 + g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
33.755 +
33.756 + gmyth_string_list_append_string(str_list, tmp_str);
33.757 +
33.758 + if (recorder->myth_socket->mythtv_version >= 26)
33.759 + gmyth_string_list_append_char_array(str_list,
33.760 + "GET_CURRENT_RECORDING");
33.761 + else
33.762 + gmyth_string_list_append_char_array(str_list, "GET_PROGRAM_INFO");
33.763 +
33.764 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
33.765 +
33.766 + if (str_list == NULL) {
33.767 + gmyth_debug
33.768 + ("[%s] GET_PROGRAM_INFO request returned. Error getting program info, string list equals to NULL!",
33.769 + __FUNCTION__);
33.770 + goto cleanup;
33.771 + }
33.772 +
33.773 + program_info = gmyth_program_info_from_string_list(str_list);
33.774 +
33.775 + if (NULL == program_info || NULL == program_info->pathname
33.776 + || program_info->pathname->len <= 0) {
33.777 + gmyth_debug
33.778 + ("GET_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!");
33.779 +
33.780 + if (program_info)
33.781 + g_object_unref(program_info);
33.782 +
33.783 + program_info = NULL;
33.784 +
33.785 + goto cleanup;
33.786 + }
33.787 +
33.788 + if (!gmyth_recorder_find_if_program_exists(recorder, program_info))
33.789 + recorder->progs_info_list =
33.790 + g_list_append(recorder->progs_info_list,
33.791 + g_object_ref(program_info));
33.792 + cleanup:
33.793 + g_mutex_unlock(recorder->mutex);
33.794 + g_string_free(tmp_str, TRUE);
33.795 + g_object_unref(str_list);
33.796 +
33.797 + return program_info;
33.798 +}
33.799 +
33.800 +/**
33.801 + * Requests the actual program info from the MythTV backend server.
33.802 + *
33.803 + * @param rec_id The GMythRecorder record number.
33.804 + * @return The GMythRecorder instance.
33.805 + */
33.806 +GMythRecorder *
33.807 +gmyth_recorder_get_recorder_from_num(gint rec_id)
33.808 +{
33.809 + GMythRecorder *recorder = NULL;
33.810 + GMythStringList *str_list;
33.811 + GString *tmp_str = g_string_new("GET_RECORDER_FROM_NUM");
33.812 + gint command_size = 0;
33.813 +
33.814 + gchar *recorder_host = NULL;
33.815 + gint recorder_port;
33.816 +
33.817 + str_list = gmyth_string_list_new();
33.818 +
33.819 + /*
33.820 + * g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
33.821 + */
33.822 +
33.823 + g_mutex_lock(recorder->mutex);
33.824 +
33.825 + gmyth_string_list_append_string(str_list, tmp_str);
33.826 +
33.827 + gmyth_string_list_append_int(str_list, rec_id);
33.828 +
33.829 + command_size =
33.830 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket,
33.831 + str_list);
33.832 +
33.833 + if (str_list == NULL) {
33.834 + gmyth_debug
33.835 + ("[%s] GET_RECORDER_FROM_NUM request returned. Error getting recorder number %d, it is equals to NULL!!!",
33.836 + __FUNCTION__, rec_id);
33.837 + return NULL;
33.838 + }
33.839 +
33.840 + if (command_size > 0) {
33.841 + recorder_host = gmyth_string_list_get_char_array(str_list, 0);
33.842 + recorder_port = gmyth_string_list_get_int(str_list, 1);
33.843 +
33.844 + if (g_strstr_len(recorder_host, strlen(recorder_host), "nohost")
33.845 + != NULL) {
33.846 + gmyth_debug
33.847 + ("No available recorder with the recorder ID number %d!",
33.848 + rec_id);
33.849 + } else {
33.850 +
33.851 + recorder = gmyth_recorder_new(rec_id,
33.852 + g_string_new(recorder_host),
33.853 + (gshort) recorder_port);
33.854 +
33.855 + if (NULL == recorder) {
33.856 + gmyth_debug
33.857 + ("[%s] GET_RECORDER_FROM_NUM request returned. Error getting recorder number %d, it is equals to NULL!!!",
33.858 + __FUNCTION__, rec_id);
33.859 + g_object_unref(recorder);
33.860 + return NULL;
33.861 + }
33.862 +
33.863 + }
33.864 +
33.865 + } else {
33.866 + gmyth_debug
33.867 + ("Cannot find a valuable recorder with the recorder ID number %d, backend server error!",
33.868 + rec_id);
33.869 + }
33.870 +
33.871 + g_mutex_unlock(recorder->mutex);
33.872 +
33.873 + g_object_unref(str_list);
33.874 +
33.875 + g_string_free(tmp_str, TRUE);
33.876 +
33.877 + g_free(recorder_host);
33.878 +
33.879 + return recorder;
33.880 +
33.881 +}
33.882 +
33.883 +/**
33.884 + * Requests the actual program info from the MythTV backend server.
33.885 + *
33.886 + * @param recorder The GMythRecorder instance.
33.887 + * @param direction The direction to move based on the current channel (forward, backward,
33.888 + * up, down).
33.889 + *
33.890 + * @return The GMythProgramInfo next program info instance.
33.891 + */
33.892 +GMythProgramInfo *
33.893 +gmyth_recorder_get_next_program_info(GMythRecorder * recorder,
33.894 + const GMythRecorderBrowseDirection
33.895 + direction)
33.896 +{
33.897 + GMythProgramInfo *actual_proginfo = NULL;
33.898 + GMythProgramInfo *program_info = NULL;
33.899 + GMythStringList *str_list;
33.900 + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
33.901 +
33.902 + gchar *date = NULL;
33.903 + struct tm *tm = NULL;
33.904 + time_t t;
33.905 +
33.906 + actual_proginfo = gmyth_recorder_get_current_program_info(recorder);
33.907 +
33.908 + str_list = gmyth_string_list_new();
33.909 +
33.910 + g_mutex_lock(recorder->mutex);
33.911 +
33.912 + g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
33.913 +
33.914 + t = time(NULL);
33.915 + tm = localtime(&t);
33.916 + date = g_strdup_printf("%.4d%.2d%.2d%.2d%.2d%.2d", tm->tm_year + 1900,
33.917 + tm->tm_mon + 1, tm->tm_mday, tm->tm_hour,
33.918 + tm->tm_min, tm->tm_sec);
33.919 +
33.920 + gmyth_string_list_append_string(str_list, tmp_str);
33.921 + gmyth_string_list_append_char_array(str_list, "GET_NEXT_PROGRAM_INFO");
33.922 + gmyth_string_list_append_string(str_list, actual_proginfo->channame);
33.923 + gmyth_string_list_append_int(str_list, actual_proginfo->channel_id);
33.924 + gmyth_string_list_append_int(str_list, direction);
33.925 + gmyth_string_list_append_char_array(str_list, date);
33.926 +
33.927 + if (gmyth_socket_sendreceive_stringlist
33.928 + (recorder->myth_socket, str_list)
33.929 + > 0) {
33.930 +
33.931 + if (str_list == NULL) {
33.932 + gmyth_debug
33.933 + ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!",
33.934 + __FUNCTION__);
33.935 + goto done;
33.936 + }
33.937 + program_info =
33.938 + gmyth_program_info_from_string_list_next_prog(str_list);
33.939 +
33.940 + if (NULL == program_info) {
33.941 + gmyth_debug
33.942 + ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting next program info, it is equals to NULL!!!",
33.943 + __FUNCTION__);
33.944 + g_object_unref(program_info);
33.945 + goto done;
33.946 + }
33.947 +
33.948 + if ( /* ( program_info->chanid != NULL &&
33.949 + * strlen( program_info->chanid->str ) > 0
33.950 + * * * * * * ) && */
33.951 + (program_info->chansign != NULL
33.952 + && strlen(program_info->chansign->str) > 0)) {
33.953 + gmyth_debug("OK!!! Got the next program info... [%s].",
33.954 + program_info->chansign->str);
33.955 + } else {
33.956 + gmyth_debug
33.957 + ("GET_NEXT_PROGRAM_INFO request returned. Error getting next program info, it is equals to NULL!!!");
33.958 + g_object_unref(program_info);
33.959 + program_info = NULL;
33.960 + }
33.961 +
33.962 + }
33.963 + /*
33.964 + * if
33.965 + */
33.966 + done:
33.967 +
33.968 + g_mutex_unlock(recorder->mutex);
33.969 +
33.970 + if (actual_proginfo != NULL)
33.971 + g_object_unref(actual_proginfo);
33.972 +
33.973 + if (str_list != NULL)
33.974 + g_object_unref(str_list);
33.975 +
33.976 + if (tmp_str != NULL)
33.977 + g_string_free(tmp_str, TRUE);
33.978 +
33.979 + if (date != NULL)
33.980 + g_free(date);
33.981 + // if ( tm != NULL)
33.982 + // g_free (tm);
33.983 +
33.984 + return program_info;
33.985 +}
33.986 +
33.987 +/**
33.988 + * Requests the program info from the MythTV backend server, based on its
33.989 + * channel name.
33.990 + *
33.991 + * @param recorder The GMythRecorder instance.
33.992 + * @return The GMythProgramInfo next program info instance.
33.993 + */
33.994 +GMythProgramInfo *
33.995 +gmyth_recorder_get_program_info_from_channel_name(GMythRecorder * recorder,
33.996 + const gchar * channel)
33.997 +{
33.998 + // GMythProgramInfo* actual_proginfo= NULL;
33.999 + GMythProgramInfo *program_info = NULL;
33.1000 + GMythStringList *str_list;
33.1001 + GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
33.1002 +
33.1003 + /*
33.1004 + * gchar *date = NULL; struct tm *tm = NULL; time_t t;
33.1005 + *
33.1006 + * actual_proginfo =
33.1007 + * gmyth_recorder_get_current_program_info(recorder);
33.1008 + */
33.1009 +
33.1010 + str_list = gmyth_string_list_new();
33.1011 +
33.1012 + g_mutex_lock(recorder->mutex);
33.1013 +
33.1014 + g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
33.1015 +
33.1016 + /*
33.1017 + * t = time(NULL); tm = localtime(&t); date =
33.1018 + * g_strdup_printf("%.4d%.2d%.2d%.2d%.2d%.2d", tm->tm_year + 1900,
33.1019 + * tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
33.1020 + */
33.1021 +
33.1022 + gmyth_string_list_append_string(str_list, tmp_str);
33.1023 + gmyth_string_list_append_char_array(str_list, "GET_NEXT_PROGRAM_INFO");
33.1024 + gmyth_string_list_append_char_array(str_list, channel);
33.1025 + gmyth_string_list_append_char_array(str_list, "0");
33.1026 + gmyth_string_list_append_int(str_list, BROWSE_DIRECTION_UP);
33.1027 + gmyth_string_list_append_char_array(str_list, "0");
33.1028 +
33.1029 + do {
33.1030 +
33.1031 + if (str_list != NULL &&
33.1032 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket,
33.1033 + str_list) > 0) {
33.1034 +
33.1035 + if (str_list == NULL) {
33.1036 + gmyth_debug
33.1037 + ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!",
33.1038 + __FUNCTION__);
33.1039 + goto done;
33.1040 + }
33.1041 + program_info =
33.1042 + gmyth_program_info_from_string_list_next_prog(str_list);
33.1043 +
33.1044 + if (NULL == program_info) {
33.1045 + gmyth_debug
33.1046 + ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting next program info, it is equals to NULL!!!",
33.1047 + __FUNCTION__);
33.1048 + g_object_unref(program_info);
33.1049 + goto done;
33.1050 + }
33.1051 +
33.1052 + if ( /* ( program_info->chanid != NULL &&
33.1053 + * strlen( program_info->chanid->str ) > 0
33.1054 + * * * * * * ) && */
33.1055 + (program_info->chansign != NULL
33.1056 + && strlen(program_info->chansign->str) > 0)) {
33.1057 + gmyth_debug("OK!!! Got the next program info... [%s].",
33.1058 + program_info->chansign->str);
33.1059 + } else {
33.1060 + gmyth_debug
33.1061 + ("GET_NEXT_PROGRAM_INFO request returned. Error getting "
33.1062 + "next program info, it is equals to NULL!!!");
33.1063 + g_object_unref(program_info);
33.1064 + program_info = NULL;
33.1065 + }
33.1066 +
33.1067 + }
33.1068 + /*
33.1069 + * if
33.1070 + */
33.1071 + }
33.1072 + while (str_list != NULL);
33.1073 +
33.1074 + done:
33.1075 +
33.1076 + g_mutex_unlock(recorder->mutex);
33.1077 +
33.1078 + if (str_list != NULL)
33.1079 + g_object_unref(str_list);
33.1080 +
33.1081 + if (tmp_str != NULL)
33.1082 + g_string_free(tmp_str, TRUE);
33.1083 +
33.1084 + return program_info;
33.1085 +}
33.1086 +
33.1087 +/**
33.1088 + * Requests the actual remote file position on a LiveTV instance.
33.1089 + *
33.1090 + * @param recorder The GMythRecorder instance.
33.1091 + *
33.1092 + * @return The position, in bytes, of the offset to the read header.
33.1093 + */
33.1094 +gint64
33.1095 +gmyth_recorder_get_file_position(GMythRecorder * recorder)
33.1096 +{
33.1097 + gint64 pos = 0;
33.1098 + GString *query = g_string_new(GMYTHTV_RECORDER_HEADER);
33.1099 +
33.1100 + GMythStringList *str_list = gmyth_string_list_new();
33.1101 +
33.1102 + g_mutex_lock(recorder->mutex);
33.1103 +
33.1104 + g_string_append_printf(query, " %d", recorder->recorder_num);
33.1105 +
33.1106 + gmyth_string_list_append_string(str_list, query);
33.1107 + gmyth_string_list_append_char_array(str_list, "GET_FILE_POSITION");
33.1108 +
33.1109 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
33.1110 +
33.1111 + if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
33.1112 + GString *str = NULL;
33.1113 +
33.1114 + if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL
33.1115 + && strstr(str->str, "bad") == NULL)
33.1116 + pos = gmyth_string_list_get_int64(str_list, 0);
33.1117 + g_string_free(str, TRUE);
33.1118 + }
33.1119 +#ifndef GMYTHTV_ENABLE_DEBUG
33.1120 + gmyth_debug("[%s] Got file position = %lld\n", __FUNCTION__, pos);
33.1121 +#endif
33.1122 +
33.1123 + g_mutex_unlock(recorder->mutex);
33.1124 +
33.1125 + if (str_list != NULL)
33.1126 + g_object_unref(str_list);
33.1127 +
33.1128 + g_string_free(query, TRUE);
33.1129 +
33.1130 + return pos;
33.1131 +}
33.1132 +
33.1133 +/**
33.1134 + * Asks MythTV backend server about if it started to record the remote file.
33.1135 + *
33.1136 + * @param recorder The GMythRecorder instance.
33.1137 + *
33.1138 + * @return <code>true</code>, if the actual remote file is bein recorded.
33.1139 + */
33.1140 +gboolean
33.1141 +gmyth_recorder_is_recording(GMythRecorder * recorder)
33.1142 +{
33.1143 + gboolean ret = TRUE;
33.1144 +
33.1145 + g_return_val_if_fail(recorder != NULL, FALSE);
33.1146 +
33.1147 + GMythStringList *str_list = gmyth_string_list_new();
33.1148 + GString *message = g_string_new("");
33.1149 +
33.1150 + g_mutex_lock(recorder->mutex);
33.1151 +
33.1152 + g_string_printf(message, "%s %d", GMYTHTV_RECORDER_HEADER,
33.1153 + recorder->recorder_num);
33.1154 + gmyth_string_list_append_string(str_list, message);
33.1155 + gmyth_string_list_append_char_array(str_list, "IS_RECORDING");
33.1156 +
33.1157 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
33.1158 +
33.1159 + if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
33.1160 + GString *str = NULL;
33.1161 +
33.1162 + if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL
33.1163 + && strcmp(str->str, "bad") != 0) {
33.1164 + gint is_rec =
33.1165 + gmyth_string_list_get_int(str_list, 0);
33.1166 +
33.1167 + if (is_rec != 0)
33.1168 + ret = TRUE;
33.1169 + else
33.1170 + ret = FALSE;
33.1171 + }
33.1172 + g_string_free(str, TRUE);
33.1173 + }
33.1174 +
33.1175 + gmyth_debug("%s, stream is %s being recorded!\n", ret ? "YES" : "NO",
33.1176 + ret ? "" : "NOT");
33.1177 + // g_static_mutex_unlock (&mutex);
33.1178 +
33.1179 + g_mutex_unlock(recorder->mutex);
33.1180 +
33.1181 + if (str_list != NULL)
33.1182 + g_object_unref(str_list);
33.1183 +
33.1184 + g_string_free(message, TRUE);
33.1185 +
33.1186 + return ret;
33.1187 +
33.1188 +}
33.1189 +
33.1190 +/**
33.1191 + * Finish remote file recording process.
33.1192 + *
33.1193 + * @param recorder The GMythRecorder instance.
33.1194 + *
33.1195 + * @return <code>true</code>, if the recording had been actually closed.
33.1196 + */
33.1197 +gboolean
33.1198 +gmyth_recorder_finish_recording(GMythRecorder * recorder)
33.1199 +{
33.1200 + gboolean ret = TRUE;
33.1201 +
33.1202 + g_return_val_if_fail(recorder != NULL, FALSE);
33.1203 +
33.1204 + GMythStringList *str_list = gmyth_string_list_new();
33.1205 + GString *message = g_string_new("");
33.1206 +
33.1207 + g_string_printf(message, "%s %d", GMYTHTV_RECORDER_HEADER,
33.1208 + recorder->recorder_num);
33.1209 + gmyth_string_list_append_string(str_list, message);
33.1210 + gmyth_string_list_append_char_array(str_list, "FINISH_RECORDING");
33.1211 +
33.1212 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
33.1213 +
33.1214 + if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
33.1215 + GString *str = NULL;
33.1216 +
33.1217 + if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL &&
33.1218 + strcmp(str->str, "ok") != 0) {
33.1219 + gint is_rec =
33.1220 + gmyth_string_list_get_int(str_list, 0);
33.1221 +
33.1222 + if (is_rec != 0)
33.1223 + ret = TRUE;
33.1224 + else
33.1225 + ret = FALSE;
33.1226 + }
33.1227 + g_string_free(str, TRUE);
33.1228 + }
33.1229 +
33.1230 + gmyth_debug("%s, stream is %s finished!\n", ret ? "YES" : "NO",
33.1231 + ret ? "" : "NOT");
33.1232 + // g_static_mutex_unlock (&mutex);
33.1233 +
33.1234 + if (str_list != NULL)
33.1235 + g_object_unref(str_list);
33.1236 +
33.1237 + g_string_free(message, TRUE);
33.1238 +
33.1239 + return ret;
33.1240 +}
33.1241 +
33.1242 +
33.1243 +/**
33.1244 + * Stops playing the remote file.
33.1245 + *
33.1246 + * @param recorder The GMythRecorder instance.
33.1247 + *
33.1248 + * @return <code>true</code>, if the recording had been actually stopped.
33.1249 + */
33.1250 +gboolean
33.1251 +gmyth_recorder_stop_playing(GMythRecorder * recorder)
33.1252 +{
33.1253 + gboolean ret = TRUE;
33.1254 +
33.1255 + g_return_val_if_fail(recorder != NULL, FALSE);
33.1256 +
33.1257 + GMythStringList *str_list = gmyth_string_list_new();
33.1258 + GString *message = g_string_new("");
33.1259 +
33.1260 + g_string_printf(message, "%s %d", GMYTHTV_RECORDER_HEADER,
33.1261 + recorder->recorder_num);
33.1262 + gmyth_string_list_append_string(str_list, message);
33.1263 + gmyth_string_list_append_char_array(str_list, "STOP_PLAYING");
33.1264 +
33.1265 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
33.1266 +
33.1267 + if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
33.1268 + GString *str = NULL;
33.1269 +
33.1270 + if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL &&
33.1271 + strcmp(str->str, "ok") != 0) {
33.1272 + gint is_rec =
33.1273 + gmyth_string_list_get_int(str_list, 0);
33.1274 +
33.1275 + if (is_rec != 0)
33.1276 + ret = TRUE;
33.1277 + else
33.1278 + ret = FALSE;
33.1279 + }
33.1280 + g_string_free(str, TRUE);
33.1281 + }
33.1282 +
33.1283 + gmyth_debug("%s, stream is %s stopped!\n", ret ? "YES" : "NO",
33.1284 + ret ? "" : "NOT");
33.1285 +
33.1286 + if (str_list != NULL)
33.1287 + g_object_unref(str_list);
33.1288 +
33.1289 + g_string_free(message, TRUE);
33.1290 +
33.1291 + return ret;
33.1292 +}
33.1293 +
33.1294 +/**
33.1295 + * Free the tuner responsible for recording this channel.
33.1296 + *
33.1297 + * @param recorder The GMythRecorder instance.
33.1298 + *
33.1299 + * @return <code>true</code>, if the tuner had been freed.
33.1300 + */
33.1301 +gboolean
33.1302 +gmyth_recorder_free_tuner(GMythRecorder * recorder)
33.1303 +{
33.1304 + gboolean ret = TRUE;
33.1305 +
33.1306 + g_return_val_if_fail(recorder != NULL, FALSE);
33.1307 +
33.1308 + GMythStringList *str_list = gmyth_string_list_new();
33.1309 + GString *message = g_string_new("");
33.1310 +
33.1311 + g_string_printf(message, "%s %d", "FREE_TUNER",
33.1312 + recorder->recorder_num);
33.1313 + gmyth_string_list_append_string(str_list, message);
33.1314 +
33.1315 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
33.1316 +
33.1317 + if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
33.1318 + GString *str = NULL;
33.1319 +
33.1320 + if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL &&
33.1321 + g_ascii_strncasecmp(str->str, "ok", 2) != 0) {
33.1322 + gint is_rec =
33.1323 + gmyth_string_list_get_int(str_list, 0);
33.1324 +
33.1325 + if (is_rec != 0)
33.1326 + ret = TRUE;
33.1327 + else
33.1328 + ret = FALSE;
33.1329 + }
33.1330 + g_string_free(str, TRUE);
33.1331 + }
33.1332 +
33.1333 + gmyth_debug("%s, tuner is %s freed!\n", ret ? "YES" : "NO",
33.1334 + ret ? "" : "NOT");
33.1335 +
33.1336 + if (str_list != NULL)
33.1337 + g_object_unref(str_list);
33.1338 +
33.1339 + g_string_free(message, TRUE);
33.1340 +
33.1341 + return ret;
33.1342 +}
33.1343 +
33.1344 +/**
33.1345 + * Asks the MythTV backend server about the frame rate
33.1346 + * of this LiveTV instance.
33.1347 + *
33.1348 + * @param recorder The GMythRecorder instance.
33.1349 + *
33.1350 + * @return The framerate (double value) of the current video.
33.1351 + */
33.1352 +gdouble
33.1353 +gmyth_recorder_get_framerate(GMythRecorder * recorder)
33.1354 +{
33.1355 + gdouble fr = 0.0f;
33.1356 + GString *query = g_string_new(GMYTHTV_RECORDER_HEADER);
33.1357 +
33.1358 + GMythStringList *str_list = gmyth_string_list_new();
33.1359 +
33.1360 + g_mutex_lock(recorder->mutex);
33.1361 +
33.1362 + g_string_append_printf(query, " %d", recorder->recorder_num);
33.1363 +
33.1364 + gmyth_string_list_append_string(str_list, query);
33.1365 + gmyth_string_list_append_char_array(str_list, "GET_FRAMERATE");
33.1366 +
33.1367 + gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
33.1368 +
33.1369 + if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
33.1370 + GString *str = NULL;
33.1371 +
33.1372 + if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL
33.1373 + && strstr(str->str, "bad") == NULL)
33.1374 + fr = g_ascii_strtod(str->str, NULL);
33.1375 +
33.1376 + g_string_free(str, TRUE);
33.1377 + }
33.1378 +#ifndef GMYTHTV_ENABLE_DEBUG
33.1379 + gmyth_debug("[%s] Got file position = %f\n", __FUNCTION__, fr);
33.1380 +#endif
33.1381 +
33.1382 + g_mutex_unlock(recorder->mutex);
33.1383 +
33.1384 + if (str_list != NULL)
33.1385 + g_object_unref(str_list);
33.1386 +
33.1387 + g_string_free(query, TRUE);
33.1388 +
33.1389 + return fr;
33.1390 +
33.1391 +}
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/gmyth/gmyth/gmyth_recorder.h Mon Feb 25 17:51:43 2008 +0000
34.3 @@ -0,0 +1,162 @@
34.4 +/**
34.5 + * GMyth Library
34.6 + *
34.7 + * @file gmyth/gmyth_recorder.h
34.8 + *
34.9 + * @brief <p> GMythRecorder defines functions for playing live tv.
34.10 + *
34.11 + * The remote encoder is used by gmyth_tvplayer to setup livetv.
34.12 + *
34.13 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
34.14 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
34.15 + * @author Rosfran Borges <rosfran.borges@indt.org.br>
34.16 + *
34.17 + *
34.18 + * This program is free software; you can redistribute it and/or modify
34.19 + * it under the terms of the GNU Lesser General Public License as published by
34.20 + * the Free Software Foundation; either version 2 of the License, or
34.21 + * (at your option) any later version.
34.22 + *
34.23 + * This program is distributed in the hope that it will be useful,
34.24 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
34.25 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34.26 + * GNU General Public License for more details.
34.27 + *
34.28 + * You should have received a copy of the GNU Lesser General Public License
34.29 + * along with this program; if not, write to the Free Software
34.30 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34.31 + */
34.32 +
34.33 +#ifndef __GMYTH_RECORDER_H__
34.34 +#define __GMYTH_RECORDER_H__
34.35 +
34.36 +#include <glib-object.h>
34.37 +
34.38 +#include "gmyth_socket.h"
34.39 +#include "gmyth_programinfo.h"
34.40 +
34.41 +#include <stdio.h>
34.42 +#include <stdlib.h>
34.43 +#include <string.h>
34.44 +#include <netdb.h>
34.45 +#include <sys/socket.h>
34.46 +#include <unistd.h>
34.47 +
34.48 +G_BEGIN_DECLS
34.49 +#define GMYTH_RECORDER_TYPE (gmyth_recorder_get_type ())
34.50 +#define GMYTH_RECORDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_RECORDER_TYPE, GMythRecorder))
34.51 +#define GMYTH_RECORDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECORDER_TYPE, GMythRecorderClass))
34.52 +#define IS_GMYTH_RECORDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_RECORDER_TYPE))
34.53 +#define IS_GMYTH_RECORDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECORDER_TYPE))
34.54 +#define GMYTH_RECORDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_RECORDER_TYPE, GMythRecorderClass))
34.55 +typedef struct _GMythRecorder GMythRecorder;
34.56 +typedef struct _GMythRecorderClass GMythRecorderClass;
34.57 +
34.58 +struct _GMythRecorderClass {
34.59 + GObjectClass parent_class;
34.60 +
34.61 + /*
34.62 + * callbacks
34.63 + */
34.64 + /*
34.65 + * no one for now
34.66 + */
34.67 +};
34.68 +
34.69 +struct _GMythRecorder {
34.70 + GObject parent;
34.71 +
34.72 + /*
34.73 + * socket descriptor
34.74 + */
34.75 + GMythSocket *myth_socket;
34.76 +
34.77 + gint recorder_num;
34.78 + GString *hostname;
34.79 + gint port;
34.80 +
34.81 + GList *progs_info_list;
34.82 +
34.83 + GMutex *mutex;
34.84 +};
34.85 +
34.86 +typedef enum _GMythRecorderChannelChangeDirection {
34.87 + CHANNEL_DIRECTION_UP = 0,
34.88 + CHANNEL_DIRECTION_DOWN,
34.89 + CHANNEL_DIRECTION_FAVORITE,
34.90 + CHANNEL_DIRECTION_SAME
34.91 +} GMythRecorderChannelChangeDirection;
34.92 +
34.93 +typedef enum _GMythRecorderBrowseDirection {
34.94 + BROWSE_DIRECTION_SAME = 0, /* Stay in the same place */
34.95 + BROWSE_DIRECTION_UP, /* Move up one slot (down one channel) */
34.96 + BROWSE_DIRECTION_DOWN, /* Move down one slot (up one channel) */
34.97 + BROWSE_DIRECTION_LEFT, /* Move left one slot (down one time slot)
34.98 + */
34.99 + BROWSE_DIRECTION_RIGHT, /* Move right one slot (up one time slot) */
34.100 + BROWSE_DIRECTION_FAVORITE /* Move to the next favorite slot */
34.101 +} GMythRecorderBrowseDirection;
34.102 +
34.103 +GType gmyth_recorder_get_type(void);
34.104 +
34.105 +GMythRecorder *gmyth_recorder_new(int num, GString * hostname,
34.106 + gshort port);
34.107 +
34.108 +void gmyth_recorder_close(GMythRecorder * recorder);
34.109 +
34.110 +gboolean gmyth_recorder_setup(GMythRecorder * recorder);
34.111 +gboolean gmyth_recorder_spawntv(GMythRecorder * recorder,
34.112 + GString * tvchain_id);
34.113 +
34.114 +gboolean gmyth_recorder_spawntv_no_tvchain(GMythRecorder *
34.115 + recorder);
34.116 +
34.117 +gboolean gmyth_recorder_stop_livetv(GMythRecorder * recorder);
34.118 +
34.119 +gboolean gmyth_recorder_send_frontend_ready_command(GMythRecorder *
34.120 + recorder);
34.121 +
34.122 +gboolean gmyth_recorder_check_channel(GMythRecorder * recorder,
34.123 + gint channel);
34.124 +
34.125 +gboolean gmyth_recorder_check_channel_name(GMythRecorder * recorder,
34.126 + gchar * channel);
34.127 +
34.128 +gboolean gmyth_recorder_set_channel(GMythRecorder * recorder,
34.129 + gint channel);
34.130 +
34.131 +gboolean gmyth_recorder_set_channel_name(GMythRecorder * recorder,
34.132 + const gchar * channel);
34.133 +
34.134 +gboolean gmyth_recorder_change_channel(GMythRecorder * recorder, const
34.135 + GMythRecorderChannelChangeDirection
34.136 + direction);
34.137 +
34.138 +GList *gmyth_recorder_get_channel_list(GMythRecorder * recorder);
34.139 +
34.140 +gboolean gmyth_recorder_pause_recording(GMythRecorder * recorder);
34.141 +
34.142 +GMythProgramInfo *gmyth_recorder_get_current_program_info(GMythRecorder *
34.143 + recorder);
34.144 +
34.145 +GMythProgramInfo *gmyth_recorder_get_next_program_info(GMythRecorder *
34.146 + recorder, const
34.147 + GMythRecorderBrowseDirection
34.148 + direction);
34.149 +
34.150 +GMythRecorder *gmyth_recorder_get_recorder_from_num(gint rec_id);
34.151 +
34.152 +gint64 gmyth_recorder_get_file_position(GMythRecorder * recorder);
34.153 +
34.154 +gboolean gmyth_recorder_is_recording(GMythRecorder * recorder);
34.155 +
34.156 +gboolean gmyth_recorder_finish_recording(GMythRecorder * recorder);
34.157 +
34.158 +gboolean gmyth_recorder_stop_playing(GMythRecorder * recorder);
34.159 +
34.160 +gboolean gmyth_recorder_free_tuner(GMythRecorder * recorder);
34.161 +
34.162 +gdouble gmyth_recorder_get_framerate(GMythRecorder * recorder);
34.163 +
34.164 +G_END_DECLS
34.165 +#endif /* __GMYTH_REMOTE_ENCODER_H__ */
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/gmyth/gmyth/gmyth_recprofile.c Mon Feb 25 17:51:43 2008 +0000
35.3 @@ -0,0 +1,264 @@
35.4 +/**
35.5 + * GMyth Library
35.6 + *
35.7 + * @file gmyth/gmyth_recprofile.c
35.8 + *
35.9 + * @brief <p> This file contains the recprofile class.
35.10 + *
35.11 + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
35.12 + * @author Artur Duque de Souza <artur.souza@indt.org.br>
35.13 + *
35.14 + * This program is free software; you can redistribute it and/or modify
35.15 + * it under the terms of the GNU Lesser General Public License as published by
35.16 + * the Free Software Foundation; either version 2 of the License, or
35.17 + * (at your option) any later version.
35.18 + *
35.19 + * This program is distributed in the hope that it will be useful,
35.20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
35.21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35.22 + * GNU General Public License for more details.
35.23 + *
35.24 + * You should have received a copy of the GNU Lesser General Public License
35.25 + * along with this program; if not, write to the Free Software
35.26 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35.27 + */
35.28 +
35.29 +
35.30 +#ifdef HAVE_CONFIG_H
35.31 +#include "config.h"
35.32 +#endif
35.33 +
35.34 +#include <stdlib.h>
35.35 +#include <string.h>
35.36 +#include <assert.h>
35.37 +
35.38 +#include "gmyth_recprofile.h"
35.39 +#include "gmyth_util.h"
35.40 +#include "gmyth_debug.h"
35.41 +#include "gmyth_http.h"
35.42 +
35.43 +static void gmyth_recprofile_class_init(GMythRecProfileClass * klass);
35.44 +static void gmyth_recprofile_init(GMythRecProfile * object);
35.45 +
35.46 +static void gmyth_recprofile_dispose(GObject * object);
35.47 +static void gmyth_recprofile_finalize(GObject * object);
35.48 +
35.49 +G_DEFINE_TYPE(GMythRecProfile, gmyth_recprofile, G_TYPE_OBJECT)
35.50 + static void gmyth_recprofile_class_init(GMythRecProfileClass *
35.51 + klass)
35.52 +{
35.53 + GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
35.54 +
35.55 + gobject_class->dispose = gmyth_recprofile_dispose;
35.56 + gobject_class->finalize = gmyth_recprofile_finalize;
35.57 +}
35.58 +
35.59 +static void
35.60 +gmyth_recprofile_init(GMythRecProfile * recprofile)
35.61 +{
35.62 +}
35.63 +
35.64 +static void
35.65 +gmyth_recprofile_dispose(GObject * object)
35.66 +{
35.67 + GMythRecProfile *recprofile = GMYTH_RECPROFILE(object);
35.68 +
35.69 + if (recprofile->name)
35.70 + g_free(recprofile->name);
35.71 +
35.72 + if (recprofile->group)
35.73 + g_free(recprofile->group);
35.74 +
35.75 + if (recprofile->vcodec)
35.76 + g_free(recprofile->vcodec);
35.77 +
35.78 + if (recprofile->acodec)
35.79 + g_free(recprofile->acodec);
35.80 +
35.81 + if (recprofile->options)
35.82 + g_free(recprofile->options);
35.83 +
35.84 + G_OBJECT_CLASS(gmyth_recprofile_parent_class)->dispose(object);
35.85 +}
35.86 +
35.87 +static void
35.88 +gmyth_recprofile_finalize(GObject * object)
35.89 +{
35.90 + g_signal_handlers_destroy(object);
35.91 + G_OBJECT_CLASS(gmyth_recprofile_parent_class)->finalize(object);
35.92 +}
35.93 +
35.94 +/**
35.95 + * Creates a new instance of GMythRecProfile.
35.96 + *
35.97 + * @return a new instance of GMythRecProfile.
35.98 + **/
35.99 +GMythRecProfile *
35.100 +gmyth_recprofile_new(void)
35.101 +{
35.102 + GMythRecProfile *recprofile = GMYTH_RECPROFILE
35.103 + (g_object_new(GMYTH_RECPROFILE_TYPE, NULL));
35.104 +
35.105 + recprofile->id = 0;
35.106 + recprofile->name = NULL;
35.107 + recprofile->group = NULL;
35.108 + recprofile->vcodec = NULL;
35.109 + recprofile->acodec = NULL;
35.110 + recprofile->options = NULL;
35.111 +
35.112 + return recprofile;
35.113 +}
35.114 +
35.115 +
35.116 +/**
35.117 + *
35.118 + * gmyth_recprofile_get_profile_list
35.119 + * @brief get profile list from the backend
35.120 + * @param backend_info GMythBackendInfo*
35.121 + * @return GSList
35.122 + *
35.123 + **/
35.124 +GSList *
35.125 +gmyth_recprofile_get_profile_list(GMythBackendInfo * backend_info)
35.126 +{
35.127 + return gmyth_http_retrieve_rec_profiles(backend_info, "Transcoders");
35.128 +}
35.129 +
35.130 +/**
35.131 + *
35.132 + * gmyth_recprofile_create_profile
35.133 + * @brief get profile list from the backend
35.134 + * @param backend_info GMythBackendInfo*
35.135 + * @param profile GMythRecProfile*
35.136 + * @return gint representing the result
35.137 + *
35.138 + **/
35.139 +gint
35.140 +gmyth_recprofile_create_profile(GMythBackendInfo * backend_info,
35.141 + GMythRecProfile * profile)
35.142 +{
35.143 + return gmyth_http_create_rec_profile(backend_info, profile);
35.144 +}
35.145 +
35.146 +/**
35.147 + *
35.148 + * gmyth_recprofile_del_profile
35.149 + * @brief del profile from the backend
35.150 + * @param backend_info GMythBackendInfo*
35.151 + * @param id profile's id
35.152 + * @return gint representing the result
35.153 + *
35.154 + **/
35.155 +gint
35.156 +gmyth_recprofile_del_profile_list(GMythBackendInfo * backend_info, gint id)
35.157 +{
35.158 + return gmyth_http_del_rec_profile(backend_info, id);
35.159 +}
35.160 +
35.161 +/**
35.162 + *
35.163 + * gmyth_recprofile_set_id
35.164 + * @brief set recprofile's id
35.165 + * @param rec GMythRecProfile*
35.166 + * @param id profile's id
35.167 + * @return gint representing the result
35.168 + *
35.169 + **/
35.170 +gint
35.171 +gmyth_recprofile_set_id(GMythRecProfile * rec, gint id)
35.172 +{
35.173 + rec->id = id;
35.174 + return 0;
35.175 +}
35.176 +
35.177 +/**
35.178 + *
35.179 + * gmyth_recprofile_set
35.180 + * @brief set recprofile's property
35.181 + * @param rec GMythRecProfile*
35.182 + * @param member the member you want to modify
35.183 + * @param value the value
35.184 + * @return gint representing the result
35.185 + *
35.186 + **/
35.187 +gint
35.188 +gmyth_recprofile_set(GMythRecProfile * rec, gchar * member, gchar * value)
35.189 +{
35.190 + int ret = 0;
35.191 +
35.192 + if (value != NULL) {
35.193 + if (g_ascii_strcasecmp(member, "name") == 0)
35.194 + rec->name = g_strndup(value, strlen(value));
35.195 + else if (g_ascii_strcasecmp(member, "group") == 0)
35.196 + rec->group = g_strndup(value, strlen(value));
35.197 + else if (g_ascii_strcasecmp(member, "vcodec") == 0)
35.198 + rec->vcodec = g_strndup(value, strlen(value));
35.199 + else if (g_ascii_strcasecmp(member, "acodec") == 0)
35.200 + rec->acodec = g_strndup(value, strlen(value));
35.201 + else
35.202 + ret = -1;
35.203 + } else
35.204 + ret = -1;
35.205 +
35.206 + return ret;
35.207 +}
35.208 +
35.209 +/**
35.210 + *
35.211 + * gmyth_recprofile_set_name
35.212 + * @brief set recprofile's name
35.213 + * @param rec GMythRecProfile*
35.214 + * @param name profile's name
35.215 + * @return gint representing the result
35.216 + *
35.217 + **/
35.218 +gint
35.219 +gmyth_recprofile_set_name(GMythRecProfile * rec, gchar * name)
35.220 +{
35.221 + return gmyth_recprofile_set(rec, "name", name);
35.222 +}
35.223 +
35.224 +/**
35.225 + *
35.226 + * gmyth_recprofile_set_group
35.227 + * @brief set recprofile's group
35.228 + * @param rec GMythRecProfile*
35.229 + * @param group profile's group
35.230 + * @return gint representing the result
35.231 + *
35.232 + **/
35.233 +gint
35.234 +gmyth_recprofile_set_group(GMythRecProfile * rec, gchar * group)
35.235 +{
35.236 + return gmyth_recprofile_set(rec, "group", group);
35.237 +}
35.238 +
35.239 +/**
35.240 + *
35.241 + * gmyth_recprofile_set_vcodec
35.242 + * @brief set recprofile's vcodec
35.243 + * @param rec GMythRecProfile*
35.244 + * @param vcodec profile's vcodec
35.245 + * @return gint representing the result
35.246 + *
35.247 + **/
35.248 +gint
35.249 +gmyth_recprofile_set_vcodec(GMythRecProfile * rec, gchar * vcodec)
35.250 +{
35.251 + return gmyth_recprofile_set(rec, "vcodec", vcodec);
35.252 +}
35.253 +
35.254 +/**
35.255 + *
35.256 + * gmyth_recprofile_set_acodec
35.257 + * @brief set recprofile's acodec
35.258 + * @param rec GMythRecProfile*
35.259 + * @param acodec profile's acodec
35.260 + * @return gint representing the result
35.261 + *
35.262 + **/
35.263 +gint
35.264 +gmyth_recprofile_set_acodec(GMythRecProfile * rec, gchar * acodec)
35.265 +{
35.266 + return gmyth_recprofile_set(rec, "acodec", acodec);
35.267 +}
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/gmyth/gmyth/gmyth_recprofile.h Mon Feb 25 17:51:43 2008 +0000
36.3 @@ -0,0 +1,123 @@
36.4 +/**
36.5 + * GMyth Library
36.6 + *
36.7 + * @file gmyth/gmyth_recprofile.h
36.8 + *
36.9 + * @brief <p> This file contains the recprofile class.
36.10 + *
36.11 + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
36.12 + * @author Artur Duque de Souza <artur.souza@indt.org.br>
36.13 + *
36.14 + *
36.15 + * This program is free software; you can redistribute it and/or modify
36.16 + * it under the terms of the GNU Lesser General Public License as published by
36.17 + * the Free Software Foundation; either version 2 of the License, or
36.18 + * (at your option) any later version.
36.19 + *
36.20 + * This program is distributed in the hope that it will be useful,
36.21 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
36.22 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36.23 + * GNU General Public License for more details.
36.24 + *
36.25 + * You should have received a copy of the GNU Lesser General Public License
36.26 + * along with this program; if not, write to the Free Software
36.27 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36.28 + */
36.29 +
36.30 +#ifndef _GMYTH_RECPROFILE_H
36.31 +#define _GMYTH_RECPROFILE_H
36.32 +
36.33 +#include <glib.h>
36.34 +#include <glib-object.h>
36.35 +
36.36 +#include "gmyth_stringlist.h"
36.37 +#include "gmyth_backendinfo.h"
36.38 +#include "gmyth_socket.h"
36.39 +
36.40 +G_BEGIN_DECLS
36.41 +#define GMYTH_RECPROFILE_TYPE (gmyth_recprofile_get_type ())
36.42 +#define GMYTH_RECPROFILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_RECPROFILE_TYPE, GMythRecProfile))
36.43 +#define GMYTH_RECPROFILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECPROFILE_TYPE, GMythRecProfileClass))
36.44 +#define IS_GMYTH_RECPROFILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_RECPROFILE_TYPE))
36.45 +#define IS_GMYTH_RECPROFILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECPROFILE_TYPE))
36.46 +#define GMYTH_RECPROFILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_RECPROFILE_TYPE, GMythRecProfileClass))
36.47 +typedef struct _Options Options;
36.48 +typedef struct _GMythRecProfile GMythRecProfile;
36.49 +typedef struct _GMythRecProfileClass GMythRecProfileClass;
36.50 +
36.51 +struct _GMythRecProfileClass {
36.52 + GObjectClass parent_class;
36.53 + gint teste;
36.54 + /*
36.55 + * callbacks
36.56 + */
36.57 +};
36.58 +
36.59 +struct _GMythRecProfile {
36.60 + gint id;
36.61 + gchar *name;
36.62 + gchar *group;
36.63 + gchar *vcodec;
36.64 + gchar *acodec;
36.65 + Options *options;
36.66 +};
36.67 +
36.68 +struct _Options {
36.69 + gint transcodelossless;
36.70 + gint transcoderesize;
36.71 + gint width;
36.72 + gint height;
36.73 + gint rtjpegquality;
36.74 + gint rtjpeglumafilter;
36.75 + gint rtjpegchromafilter;
36.76 + gint mpeg4bitrate;
36.77 + gint mpeg4maxquality;
36.78 + gint mpeg4minquality;
36.79 + gint mpeg4qualdiff;
36.80 + gint mpeg4scalebitrate;
36.81 + gint mpeg4optionvhq;
36.82 + gint mpeg4option4mv;
36.83 + gint mpeg4optionidct;
36.84 + gint mpeg4optionime;
36.85 + gint hardwaremjpegquality;
36.86 + gint hardwaremjpeghdecimation;
36.87 + gint hardwaremjpegvdecimation;
36.88 + gchar *mpeg2streamtype;
36.89 + gchar *mpeg2aspectratio;
36.90 + gint mpeg2bitrate;
36.91 + gint mpeg2maxbitrate;
36.92 + gint samplerate;
36.93 + gint mp3quality;
36.94 + gint volume;
36.95 + gchar *mpeg2audtype;
36.96 + gint mpeg2audbitratel1;
36.97 + gint mpeg2audbitratel2;
36.98 + gint mpeg2audvolume;
36.99 +};
36.100 +
36.101 +GType gmyth_recprofile_type(void);
36.102 +
36.103 +GMythRecProfile *gmyth_recprofile_new(void);
36.104 +
36.105 +GSList *gmyth_recprofile_get_profile_list(GMythBackendInfo *
36.106 + backend_info);
36.107 +
36.108 +gint gmyth_recprofile_create_profile(GMythBackendInfo *
36.109 + backend_info,
36.110 + GMythRecProfile * profile);
36.111 +
36.112 +gint gmyth_recprofile_del_profile_list(GMythBackendInfo *
36.113 + backend_info, gint id);
36.114 +
36.115 +gint gmyth_recprofile_set_acodec(GMythRecProfile * rec,
36.116 + gchar * acodec);
36.117 +gint gmyth_recprofile_set_vcodec(GMythRecProfile * rec,
36.118 + gchar * vcodec);
36.119 +gint gmyth_recprofile_set_group(GMythRecProfile * rec,
36.120 + gchar * group);
36.121 +gint gmyth_recprofile_set_name(GMythRecProfile * rec,
36.122 + gchar * name);
36.123 +gint gmyth_recprofile_set_id(GMythRecProfile * rec, gint id);
36.124 +
36.125 +G_END_DECLS
36.126 +#endif /*_GMYTH_RECPROFILE_H*/
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/gmyth/gmyth/gmyth_remote_util.c Mon Feb 25 17:51:43 2008 +0000
37.3 @@ -0,0 +1,126 @@
37.4 +/**
37.5 + * GMyth Library
37.6 + *
37.7 + * @file gmyth/gmyth_remote_util.c
37.8 + *
37.9 + * @brief <p> This component provides utility functions for accessing remote data.
37.10 + *
37.11 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
37.12 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
37.13 + * @author Rosfran Borges <rosfran.borges@indt.org.br>
37.14 + *
37.15 + *
37.16 + * This program is free software; you can redistribute it and/or modify
37.17 + * it under the terms of the GNU Lesser General Public License as published by
37.18 + * the Free Software Foundation; either version 2 of the License, or
37.19 + * (at your option) any later version.
37.20 + *
37.21 + * This program is distributed in the hope that it will be useful,
37.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
37.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37.24 + * GNU General Public License for more details.
37.25 + *
37.26 + * You should have received a copy of the GNU Lesser General Public License
37.27 + * along with this program; if not, write to the Free Software
37.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37.29 + */
37.30 +
37.31 +#ifdef HAVE_CONFIG_H
37.32 +#include "config.h"
37.33 +#endif
37.34 +
37.35 +#include "gmyth_remote_util.h"
37.36 +
37.37 +#include "gmyth_recorder.h"
37.38 +#include "gmyth_stringlist.h"
37.39 +#include "gmyth_debug.h"
37.40 +
37.41 +/**
37.42 + * Requests the Mythtv backend for a free remote recorder.
37.43 + *
37.44 + * @param socket The socket instance where to send the command.
37.45 + * @param curr The recorder index, or -1 to consider the first one.
37.46 + *
37.47 + * @return the remote encoder instance available, or NULL if any error happens.
37.48 + */
37.49 +GMythRecorder *
37.50 +remote_request_next_free_recorder(GMythSocket * socket, gint curr)
37.51 +{
37.52 + GMythRecorder *recorder = NULL;
37.53 + GString *hostname;
37.54 + gint num,
37.55 + port;
37.56 +
37.57 + GMythStringList *strlist = gmyth_string_list_new();
37.58 +
37.59 + gmyth_debug("[%s] Request next free recorder in the backend",
37.60 + __FUNCTION__);
37.61 +
37.62 + gmyth_string_list_append_char_array(strlist, "GET_NEXT_FREE_RECORDER");
37.63 + gmyth_string_list_append_int(strlist, curr);
37.64 +
37.65 + if (!gmyth_socket_sendreceive_stringlist(socket, strlist)) {
37.66 + g_warning("GET_NEXT_FREE_RECORDER request error!\n");
37.67 + return NULL;
37.68 + }
37.69 +
37.70 + num = gmyth_string_list_get_int(strlist, 0);
37.71 + hostname = gmyth_string_list_get_string(strlist, 1);
37.72 + port = gmyth_string_list_get_int(strlist, 2);
37.73 +
37.74 + if (num < 0 || port < 0)
37.75 + goto clean_up;
37.76 +
37.77 + gmyth_debug
37.78 + ("[%s] Free recorder info received: num: %d, hostname: %s, port: %d",
37.79 + __FUNCTION__, num, hostname->str, port);
37.80 +
37.81 + recorder = gmyth_recorder_new(num, hostname, port);
37.82 +
37.83 + clean_up:
37.84 +
37.85 + g_string_free(hostname, TRUE);
37.86 + g_object_unref(strlist);
37.87 +
37.88 + return recorder;
37.89 +}
37.90 +
37.91 +/**
37.92 + * Requests the Mythtv backend for the number of free remote recorders.
37.93 + *
37.94 + * @param socket The socket instance where to send the command.
37.95 + *
37.96 + * @return the number of remote encoders instance available, or 0 if no one is actually free..
37.97 + */
37.98 +gint
37.99 +gmyth_remote_util_get_free_recorder_count(GMythSocket * socket)
37.100 +{
37.101 + gint num_recs = 0;
37.102 +
37.103 + GMythStringList *strlist = gmyth_string_list_new();
37.104 +
37.105 + gmyth_debug("[%s] Request next free recorder in the backend",
37.106 + __FUNCTION__);
37.107 +
37.108 + gmyth_string_list_append_char_array(strlist,
37.109 + "GET_FREE_RECORDER_COUNT");
37.110 +
37.111 + if (!gmyth_socket_sendreceive_stringlist(socket, strlist)) {
37.112 + gmyth_debug("GET_FREE_RECORDER_COUNT request error!");
37.113 + return 0;
37.114 + }
37.115 +
37.116 + num_recs = gmyth_string_list_get_int(strlist, 0);
37.117 +
37.118 + if (num_recs < 0)
37.119 + goto clean_up;
37.120 +
37.121 + gmyth_debug("[%s] Free recorder info received: num recorders: %d",
37.122 + __FUNCTION__, num_recs);
37.123 +
37.124 + clean_up:
37.125 +
37.126 + g_object_unref(strlist);
37.127 +
37.128 + return num_recs;
37.129 +}
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/gmyth/gmyth/gmyth_remote_util.h Mon Feb 25 17:51:43 2008 +0000
38.3 @@ -0,0 +1,41 @@
38.4 +/**
38.5 + * GMyth Library
38.6 + *
38.7 + * @file gmyth/gmyth_remote_util.h
38.8 + *
38.9 + * @brief <p> This component provides utility functions for accessing remote data.
38.10 + *
38.11 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
38.12 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
38.13 + *
38.14 + *
38.15 + * This program is free software; you can redistribute it and/or modify
38.16 + * it under the terms of the GNU Lesser General Public License as published by
38.17 + * the Free Software Foundation; either version 2 of the License, or
38.18 + * (at your option) any later version.
38.19 + *
38.20 + * This program is distributed in the hope that it will be useful,
38.21 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
38.22 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38.23 + * GNU General Public License for more details.
38.24 + *
38.25 + * You should have received a copy of the GNU Lesser General Public License
38.26 + * along with this program; if not, write to the Free Software
38.27 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38.28 + */
38.29 +
38.30 +#ifndef __REMOTE_UTIL_H__
38.31 +#define __REMOTE_UTIL_H__
38.32 +
38.33 +#include <glib.h>
38.34 +#include "gmyth_recorder.h"
38.35 +#include "gmyth_socket.h"
38.36 +
38.37 +G_BEGIN_DECLS
38.38 + GMythRecorder * remote_request_next_free_recorder(GMythSocket * socket,
38.39 + gint curr);
38.40 +gint gmyth_remote_util_get_free_recorder_count(GMythSocket *
38.41 + socket);
38.42 +
38.43 +G_END_DECLS
38.44 +#endif
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/gmyth/gmyth/gmyth_scheduler.c Mon Feb 25 17:51:43 2008 +0000
39.3 @@ -0,0 +1,1266 @@
39.4 +/**
39.5 + * GMyth Library
39.6 + *
39.7 + * @file gmyth/gmyth_scheduler.c
39.8 + *
39.9 + * @brief <p> The scheduler encapsulates all functions for browsing, scheduling
39.10 + * and modifying the recorded content.
39.11 + *
39.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
39.13 + * @author Alexsandro Jose Virginio dos Santos <alexsandro.santos@indt.org.br>
39.14 + *
39.15 + *
39.16 + * This program is free software; you can redistribute it and/or modify
39.17 + * it under the terms of the GNU Lesser General Public License as published by
39.18 + * the Free Software Foundation; either version 2 of the License, or
39.19 + * (at your option) any later version.
39.20 + *
39.21 + * This program is distributed in the hope that it will be useful,
39.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
39.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39.24 + * GNU General Public License for more details.
39.25 + *
39.26 + * You should have received a copy of the GNU Lesser General Public License
39.27 + * along with this program; if not, write to the Free Software
39.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39.29 + */
39.30 +
39.31 +#ifdef HAVE_CONFIG_H
39.32 +#include "config.h"
39.33 +#endif
39.34 +
39.35 +#include <assert.h>
39.36 +
39.37 +#include <glib.h>
39.38 +#include <glib/gprintf.h>
39.39 +
39.40 +#include "gmyth_scheduler.h"
39.41 +#include "gmyth_util.h"
39.42 +#include "gmyth_query.h"
39.43 +#include "gmyth_socket.h"
39.44 +#include "gmyth_debug.h"
39.45 +
39.46 +static void gmyth_scheduler_class_init(GMythSchedulerClass * klass);
39.47 +static void gmyth_scheduler_init(GMythScheduler * object);
39.48 +
39.49 +static void gmyth_scheduler_dispose(GObject * object);
39.50 +static void gmyth_scheduler_finalize(GObject * object);
39.51 +
39.52 +static gboolean update_backend(GMythScheduler * scheduler, gint record_id);
39.53 +
39.54 +G_DEFINE_TYPE(GMythScheduler, gmyth_scheduler, G_TYPE_OBJECT)
39.55 + static void gmyth_scheduler_class_init(GMythSchedulerClass * klass)
39.56 +{
39.57 + GObjectClass *gobject_class;
39.58 +
39.59 + gobject_class = (GObjectClass *) klass;
39.60 +
39.61 + gobject_class->dispose = gmyth_scheduler_dispose;
39.62 + gobject_class->finalize = gmyth_scheduler_finalize;
39.63 +}
39.64 +
39.65 +static void
39.66 +gmyth_scheduler_init(GMythScheduler * sched)
39.67 +{
39.68 + sched->recordid = 0;
39.69 + sched->type = 0;
39.70 + sched->search = 0;
39.71 + sched->profile = g_string_new("");
39.72 +
39.73 + sched->dupin = 0;
39.74 + sched->dupmethod = 0;
39.75 + sched->autoexpire = 0;
39.76 + sched->autotranscode = 0;
39.77 + sched->transcoder = 0;
39.78 +
39.79 + sched->autocommflag = 0;
39.80 + sched->autouserjob1 = 0;
39.81 + sched->autouserjob2 = 0;
39.82 + sched->autouserjob3 = 0;
39.83 + sched->autouserjob4 = 0;
39.84 +
39.85 + sched->startoffset = 0;
39.86 + sched->endoffset = 0;
39.87 + sched->maxepisodes = 0;
39.88 + sched->maxnewest = 0;
39.89 +
39.90 + sched->recpriority = 0;
39.91 + sched->recgroup = g_string_new("");
39.92 + sched->playgroup = g_string_new("");
39.93 +
39.94 + sched->prefinput = 0;
39.95 + sched->inactive = 0;
39.96 +
39.97 + sched->search_type = g_string_new("");
39.98 + sched->search_what = g_string_new("");
39.99 +
39.100 + sched->msqlquery = gmyth_query_new();
39.101 +}
39.102 +
39.103 +static void
39.104 +gmyth_scheduler_dispose(GObject * object)
39.105 +{
39.106 + GMythScheduler *scheduler = GMYTH_SCHEDULER(object);
39.107 +
39.108 + if (scheduler->backend_info) {
39.109 + g_object_unref(scheduler->backend_info);
39.110 + scheduler->backend_info = NULL;
39.111 + }
39.112 +
39.113 + if (scheduler->msqlquery) {
39.114 + g_object_unref(scheduler->msqlquery);
39.115 + scheduler->msqlquery = NULL;
39.116 + }
39.117 +
39.118 + g_string_free(scheduler->profile, TRUE);
39.119 + g_string_free(scheduler->recgroup, TRUE);
39.120 + g_string_free(scheduler->playgroup, TRUE);
39.121 + g_string_free(scheduler->search_type, TRUE);
39.122 + g_string_free(scheduler->search_what, TRUE);
39.123 +
39.124 + G_OBJECT_CLASS(gmyth_scheduler_parent_class)->dispose(object);
39.125 +}
39.126 +
39.127 +static void
39.128 +gmyth_scheduler_finalize(GObject * object)
39.129 +{
39.130 + g_signal_handlers_destroy(object);
39.131 +
39.132 + G_OBJECT_CLASS(gmyth_scheduler_parent_class)->finalize(object);
39.133 +}
39.134 +
39.135 +/** Creates a new instance of GMythScheduler.
39.136 + *
39.137 + * @return a new instance of GMythScheduler.
39.138 + */
39.139 +GMythScheduler *
39.140 +gmyth_scheduler_new()
39.141 +{
39.142 + GMythScheduler *scheduler =
39.143 + GMYTH_SCHEDULER(g_object_new(GMYTH_SCHEDULER_TYPE, NULL));
39.144 +
39.145 + return scheduler;
39.146 +}
39.147 +
39.148 +gboolean
39.149 +gmyth_scheduler_connect(GMythScheduler * scheduler,
39.150 + GMythBackendInfo * backend_info)
39.151 +{
39.152 + return gmyth_scheduler_connect_with_timeout(scheduler, backend_info,
39.153 + 0);
39.154 +}
39.155 +
39.156 +/** Connects to the Mysql database in the backend. The backend address
39.157 + * is loaded from the GMythSettings instance.
39.158 + *
39.159 + * @param scheduler the GMythScheduler instance to be connected.
39.160 + * @return true if connection was success, false if failed.
39.161 + */
39.162 +gboolean
39.163 +gmyth_scheduler_connect_with_timeout(GMythScheduler * scheduler,
39.164 + GMythBackendInfo * backend_info,
39.165 + guint timeout)
39.166 +{
39.167 + assert(scheduler);
39.168 + g_return_val_if_fail(backend_info != NULL, FALSE);
39.169 +
39.170 + if (scheduler->backend_info)
39.171 + g_object_unref(scheduler->backend_info);
39.172 +
39.173 + scheduler->backend_info = g_object_ref(backend_info);
39.174 +
39.175 + if (scheduler->msqlquery == NULL) {
39.176 + g_warning("[%s] GMythScheduler db initializing", __FUNCTION__);
39.177 + scheduler->msqlquery = gmyth_query_new();
39.178 + }
39.179 +
39.180 + if (!gmyth_query_connect_with_timeout(scheduler->msqlquery,
39.181 + scheduler->backend_info,
39.182 + timeout)) {
39.183 + g_warning("[%s] Error while connecting to db", __FUNCTION__);
39.184 + return FALSE;
39.185 + }
39.186 +
39.187 + return TRUE;
39.188 +}
39.189 +
39.190 +/** Disconnects from the Mysql database in the backend.
39.191 + *
39.192 + * @param scheduler the GMythScheduler instance to be disconnected
39.193 + * @return true if disconnection was success, false if failed.
39.194 + */
39.195 +gboolean
39.196 +gmyth_scheduler_disconnect(GMythScheduler * scheduler)
39.197 +{
39.198 + assert(scheduler);
39.199 +
39.200 + if (scheduler->msqlquery != NULL) {
39.201 + gmyth_query_disconnect(scheduler->msqlquery);
39.202 + }
39.203 +
39.204 + return TRUE;
39.205 +}
39.206 +
39.207 +/** Retrieves from the backend Mysql database the list of recording schedules.
39.208 + *
39.209 + * @param scheduler The GMythScheduler instance.
39.210 + * @param schedule_list the GList pointer to be filled with the loaded list of ScheduleInfo items.
39.211 + * @return The amount of schedules retrieved from database, or -1 if error.
39.212 + */
39.213 +gint
39.214 +gmyth_scheduler_get_schedule_list(GMythScheduler * scheduler,
39.215 + GList ** schedule_list)
39.216 +{
39.217 + ScheduleInfo *schedule;
39.218 + MYSQL_RES *msql_res;
39.219 + GString *query_str = g_string_new("");
39.220 + gchar *date_time = NULL;
39.221 +
39.222 + assert(scheduler);
39.223 +
39.224 + g_string_printf(query_str,
39.225 + "SELECT recordid,programid,chanid,starttime,startdate,"
39.226 + "endtime,enddate,title,subtitle,description,category,type,parentid,seriesid FROM record;");
39.227 +
39.228 + if (scheduler->msqlquery == NULL) {
39.229 + g_warning("[%s] Scheduler db connection not initialized",
39.230 + __FUNCTION__);
39.231 + return -1;
39.232 + }
39.233 + msql_res =
39.234 + gmyth_query_process_statement(scheduler->msqlquery,
39.235 + query_str->str);
39.236 +
39.237 + if (msql_res == NULL) {
39.238 + g_warning("DB retrieval of schedule list failed");
39.239 + return -1;
39.240 + } else {
39.241 + MYSQL_ROW row;
39.242 +
39.243 + *schedule_list = NULL;
39.244 +
39.245 + while ((row = mysql_fetch_row(msql_res)) != NULL) {
39.246 + schedule = g_new0(ScheduleInfo, 1);
39.247 + gint type = 0;
39.248 +
39.249 + schedule->schedule_id =
39.250 + (guint) g_ascii_strtoull(row[0], NULL, 10);
39.251 + schedule->program_id = g_string_new (row[1]);
39.252 + schedule->channel_id = (gint) g_ascii_strtoull (row[2], NULL, 10);
39.253 +
39.254 + /*
39.255 + * generate a time_t from a time and a date db field
39.256 + */
39.257 + date_time = g_strdup_printf("%sT%s", row[4], row[3]);
39.258 + schedule->start_time =
39.259 + gmyth_util_string_to_time_val(date_time);
39.260 + g_free(date_time);
39.261 +
39.262 + /*
39.263 + * generate a time_t from a time and a date db field
39.264 + */
39.265 + date_time = g_strdup_printf("%sT%s", row[6], row[5]);
39.266 + schedule->end_time = gmyth_util_string_to_time_val(date_time);
39.267 + g_free(date_time);
39.268 +
39.269 + schedule->title = g_string_new(row[7]);
39.270 + schedule->subtitle = g_string_new(row[8]);
39.271 + schedule->description = g_string_new(row[9]);
39.272 + schedule->category = g_string_new(row[10]);
39.273 + type = g_ascii_strtoull (row[11], NULL, 10);
39.274 + if (type == 4) {
39.275 + schedule->type = GMYTH_SCHEDULE_ALL_OCCURRENCES;
39.276 + } else if (type == 1) {
39.277 + schedule->type = GMYTH_SCHEDULE_ONE_OCCURRENCE;
39.278 + } else if (type == 8) {
39.279 + schedule->type = GMYTH_SCHEDULE_EXCEPTION;
39.280 + schedule->parentid = (gint) g_ascii_strtoull (row[12], NULL, 10);
39.281 + }
39.282 +
39.283 + schedule->seriesid = g_string_new (row[13]);
39.284 +
39.285 + (*schedule_list) = g_list_append(*(schedule_list), schedule);
39.286 + }
39.287 + }
39.288 +
39.289 + mysql_free_result(msql_res);
39.290 + g_string_free(query_str, TRUE);
39.291 +
39.292 + return (*schedule_list == NULL) ? 0 : g_list_length(*schedule_list);
39.293 +}
39.294 +
39.295 +/** Retrieves from the backend Mysql database the list of recorded programs.
39.296 + *
39.297 + * @param scheduler The GMythScheduler instance.
39.298 + * @param recorded_list the GList pointer to be filled with the loaded RecordInfo items.
39.299 + * @return The amount of recorded retrieved from database, or -1 if error.
39.300 + */
39.301 +gint
39.302 +gmyth_scheduler_get_recorded_list(GMythScheduler * scheduler,
39.303 + GList ** recorded_list)
39.304 +{
39.305 + RecordedInfo *record;
39.306 + MYSQL_RES *msql_res;
39.307 + GString *query_str = g_string_new("");
39.308 +
39.309 + assert(scheduler);
39.310 +
39.311 + g_string_printf(query_str,
39.312 + "SELECT recordid,programid,chanid,starttime,progstart,"
39.313 + "endtime,progend,title,subtitle,description,category,"
39.314 + "filesize,basename,seriesid FROM recorded WHERE recgroup != 'LiveTV'");
39.315 +
39.316 + if (scheduler->msqlquery == NULL) {
39.317 + g_warning("[%s] Scheduler db connection not initialized",
39.318 + __FUNCTION__);
39.319 + return -1;
39.320 + }
39.321 +
39.322 + msql_res =
39.323 + gmyth_query_process_statement(scheduler->msqlquery,
39.324 + query_str->str);
39.325 +
39.326 + if (msql_res == NULL) {
39.327 + g_warning("DB retrieval of recording list failed");
39.328 + return -1;
39.329 + } else {
39.330 + MYSQL_ROW row;
39.331 +
39.332 + (*recorded_list) = NULL;
39.333 +
39.334 + while ((row = mysql_fetch_row(msql_res)) != NULL) {
39.335 + record = g_new0(RecordedInfo, 1);
39.336 +
39.337 + record->record_id = (guint) g_ascii_strtoull(row[0], NULL, 10);
39.338 + record->program_id = g_string_new (row[1]);
39.339 + record->channel_id = (gint) g_ascii_strtoull(row[2], NULL, 10);
39.340 + record->start_time = gmyth_util_string_to_time_val(row[3]);
39.341 + record->end_time = gmyth_util_string_to_time_val(row[5]);
39.342 +
39.343 + record->title = g_string_new(row[7]);
39.344 + record->subtitle = g_string_new(row[8]);
39.345 + record->description = g_string_new(row[9]);
39.346 + record->category = g_string_new(row[10]);
39.347 + record->filesize = g_ascii_strtoull(row[11], NULL, 10);
39.348 + record->basename = g_string_new(row[12]);
39.349 + record->seriesid = g_string_new(row[13]);
39.350 +
39.351 + (*recorded_list) = g_list_append((*recorded_list), record);
39.352 + }
39.353 + }
39.354 +
39.355 + mysql_free_result(msql_res);
39.356 + g_string_free(query_str, TRUE);
39.357 +
39.358 + return (*recorded_list == NULL) ? 0 : g_list_length(*recorded_list);
39.359 +}
39.360 +
39.361 +RecordedInfo*
39.362 +gmyth_scheduler_get_recorded_info (GMythScheduler *scheduler,
39.363 + const gchar* basename)
39.364 +{
39.365 + RecordedInfo *record = NULL;
39.366 + MYSQL_RES *msql_res;
39.367 + GString *query_str = g_string_new("");
39.368 +
39.369 + assert(scheduler);
39.370 +
39.371 + g_string_printf(query_str,
39.372 + "SELECT recordid,programid,chanid,starttime,progstart,"
39.373 + "endtime,progend,title,subtitle,description,category,"
39.374 + "filesize,basename,seriesid FROM recorded "
39.375 + "WHERE recgroup != 'LiveTV' AND basename = '%s'", basename);
39.376 +
39.377 + if (scheduler->msqlquery == NULL) {
39.378 + g_warning("[%s] Scheduler db connection not initialized",
39.379 + __FUNCTION__);
39.380 + return NULL;
39.381 + }
39.382 +
39.383 + msql_res =
39.384 + gmyth_query_process_statement(scheduler->msqlquery,
39.385 + query_str->str);
39.386 +
39.387 + if (msql_res == NULL) {
39.388 + g_warning("DB retrieval of recording list failed");
39.389 + return NULL;
39.390 + } else {
39.391 + MYSQL_ROW row;
39.392 + row = mysql_fetch_row(msql_res);
39.393 + if (row != NULL) {
39.394 + record = g_new0(RecordedInfo, 1);
39.395 + record->record_id = (guint) g_ascii_strtoull(row[0], NULL, 10);
39.396 + record->program_id = g_string_new (row[1]);
39.397 + record->channel_id = (gint) g_ascii_strtoull(row[2], NULL, 10);
39.398 + record->start_time = gmyth_util_string_to_time_val(row[3]);
39.399 + record->end_time = gmyth_util_string_to_time_val(row[5]);
39.400 + record->title = g_string_new(row[7]);
39.401 + record->subtitle = g_string_new(row[8]);
39.402 + record->description = g_string_new(row[9]);
39.403 + record->category = g_string_new(row[10]);
39.404 + record->filesize = g_ascii_strtoull(row[11], NULL, 10);
39.405 + record->basename = g_string_new(row[12]);
39.406 + record->seriesid = g_string_new(row[13]);
39.407 + }
39.408 + }
39.409 +
39.410 + mysql_free_result(msql_res);
39.411 + g_string_free(query_str, TRUE);
39.412 +
39.413 + return record;
39.414 +}
39.415 +
39.416 +
39.417 +static void
39.418 +_set_value(GMythQuery * myth_query, char *field, gchar * value,
39.419 + gint rec_id)
39.420 +{
39.421 + gchar *query =
39.422 + g_strdup_printf
39.423 + ("UPDATE record SET recordid = %d, %s = \"%s\" WHERE recordid = %d;",
39.424 + rec_id, field, value, rec_id);
39.425 +
39.426 + gmyth_query_process_statement(myth_query, query);
39.427 + g_free(query);
39.428 +}
39.429 +
39.430 +static void
39.431 +_set_int_value(GMythQuery * myth_query, char *field, gint value,
39.432 + gint rec_id)
39.433 +{
39.434 + gchar *str_value = g_strdup_printf("%d", value);
39.435 +
39.436 + _set_value(myth_query, field, str_value, rec_id);
39.437 + g_free(str_value);
39.438 +}
39.439 +
39.440 +ScheduleInfo*
39.441 +gmyth_scheduler_add_schedule_program (GMythScheduler * scheduler,
39.442 + GMythProgramInfo *program,
39.443 + GMythScheduleType type)
39.444 +{
39.445 + ScheduleInfo *info;
39.446 +
39.447 + info = g_new0 (ScheduleInfo, 1);
39.448 + info->program_id = g_string_new (program->program_id->str);
39.449 + info->channel_id = program->channel_id;
39.450 + info->start_time = g_new0 (GTimeVal, 1);
39.451 + *info->start_time = *program->startts;
39.452 + info->end_time = g_new0 (GTimeVal, 1);
39.453 + *info->end_time = *program->endts;
39.454 + info->seriesid = g_string_new (program->seriesid->str);
39.455 + info->title = g_string_new (program->title->str);
39.456 + info->subtitle = g_string_new (program->subtitle->str);
39.457 + info->description = g_string_new (program->description->str);
39.458 + info->category = g_string_new (program->category->str);
39.459 + info->type = type;
39.460 +
39.461 + if (gmyth_scheduler_add_schedule_full (scheduler, info, type))
39.462 + {
39.463 + if (!program->recstartts)
39.464 + program->recstartts = g_new0 (GTimeVal, 1);
39.465 + *program->recstartts = *info->start_time;
39.466 +
39.467 + if (!program->recendts)
39.468 + program->recendts = g_new0 (GTimeVal, 1);
39.469 + *program->recendts = *info->end_time;
39.470 +
39.471 + program->recordid = info->schedule_id;
39.472 + return info;
39.473 + }
39.474 +
39.475 + gmyth_schedule_info_free (info);
39.476 + return NULL;
39.477 +}
39.478 +
39.479 +
39.480 +gboolean
39.481 +gmyth_scheduler_add_schedule_full (GMythScheduler * scheduler,
39.482 + ScheduleInfo * schedule_info, GMythScheduleType type)
39.483 +{
39.484 + MYSQL_RES *msql_res;
39.485 + gchar *query_str = "INSERT record (recordid) VALUE (0);";
39.486 + gchar *station = NULL;
39.487 + gulong rec_id;
39.488 +
39.489 + g_return_val_if_fail (IS_GMYTH_SCHEDULER (scheduler), FALSE);
39.490 +
39.491 + if (scheduler->msqlquery == NULL) {
39.492 + g_warning("[%s] Scheduler db connection not initialized",
39.493 + __FUNCTION__);
39.494 + return FALSE;
39.495 + }
39.496 +
39.497 + msql_res =
39.498 + gmyth_query_process_statement_with_increment(scheduler->msqlquery,
39.499 + query_str, &rec_id);
39.500 + mysql_free_result(msql_res);
39.501 +
39.502 + // Retrieves the station info
39.503 + query_str =
39.504 + g_strdup_printf
39.505 + ("SELECT callsign FROM channel WHERE chanid = %d;",
39.506 + schedule_info->channel_id);
39.507 + msql_res =
39.508 + gmyth_query_process_statement(scheduler->msqlquery, query_str);
39.509 + if (msql_res == NULL) {
39.510 + g_warning("[%s] msql query returned NULL MYSQL_RES", __FUNCTION__);
39.511 + return FALSE;
39.512 + } else {
39.513 + MYSQL_ROW row;
39.514 +
39.515 + if ((row = mysql_fetch_row(msql_res)) != NULL) {
39.516 + station = g_strdup(row[0]);
39.517 + }
39.518 + }
39.519 + mysql_free_result(msql_res);
39.520 + g_free(query_str);
39.521 +
39.522 + // _set_value (field, value, id);
39.523 + _set_int_value(scheduler->msqlquery, "chanid",
39.524 + schedule_info->channel_id, rec_id);
39.525 + _set_value(scheduler->msqlquery, "station", station, rec_id);
39.526 + _set_value(scheduler->msqlquery, "title", schedule_info->title->str,
39.527 + rec_id);
39.528 + // / subtitle, description
39.529 + _set_value(scheduler->msqlquery, "starttime",
39.530 + gmyth_util_time_to_string_only_time(schedule_info->
39.531 + start_time), rec_id);
39.532 + _set_value(scheduler->msqlquery, "startdate",
39.533 + gmyth_util_time_to_string_only_date(schedule_info->
39.534 + start_time), rec_id);
39.535 + _set_value(scheduler->msqlquery, "endtime",
39.536 + gmyth_util_time_to_string_only_time(schedule_info->
39.537 + end_time), rec_id);
39.538 + _set_value(scheduler->msqlquery, "enddate",
39.539 + gmyth_util_time_to_string_only_date(schedule_info->
39.540 + end_time), rec_id);
39.541 + // / category, series id, program id
39.542 + // _set_value (scheduler->msqlquery, "findday",
39.543 + // (gmyth_util_time_val_to_date( schedule_info->start_time
39.544 + // ))->tm_wday, rec_id);
39.545 + // _set_value (scheduler->msqlquery, "findtime",
39.546 + // gmyth_util_time_to_string_only_time( schedule_info->start_time),
39.547 + // rec_id);
39.548 + // _set_int_value (scheduler->msqlquery, "findid",
39.549 + // (gint)(schedule_info->start_time->tv_sec/60/60/24 + 719528),
39.550 + // rec_id);
39.551 +
39.552 + if (schedule_info->seriesid)
39.553 + _set_value(scheduler->msqlquery, "seriesid",
39.554 + schedule_info->seriesid->str, rec_id);
39.555 +
39.556 + _set_value(scheduler->msqlquery, "parentid", "0", rec_id);
39.557 + _set_value(scheduler->msqlquery, "search", "0", rec_id);
39.558 +
39.559 + if (type == GMYTH_SCHEDULE_ALL_OCCURRENCES) {
39.560 + _set_int_value(scheduler->msqlquery, "type", 3, rec_id);
39.561 + } else if (type == GMYTH_SCHEDULE_ONE_OCCURRENCE) {
39.562 + _set_int_value(scheduler->msqlquery, "type", 1, rec_id);
39.563 + } else if (type == GMYTH_SCHEDULE_EXCEPTION) {
39.564 + _set_int_value(scheduler->msqlquery, "type", 8, rec_id);
39.565 + _set_int_value(scheduler->msqlquery, "parentid", schedule_info->parentid,
39.566 + rec_id);
39.567 + }
39.568 +
39.569 + _set_value(scheduler->msqlquery, "recpriority", "0", rec_id);
39.570 + _set_value(scheduler->msqlquery, "startoffset", "0", rec_id);
39.571 + _set_value(scheduler->msqlquery, "endoffset", "0", rec_id);
39.572 + _set_value(scheduler->msqlquery, "dupmethod", "6", rec_id); // ?
39.573 + _set_value(scheduler->msqlquery, "dupin", "15", rec_id); // ?
39.574 +
39.575 + _set_value(scheduler->msqlquery, "prefinput", "0", rec_id);
39.576 + _set_value(scheduler->msqlquery, "inactive", "0", rec_id);
39.577 + _set_value(scheduler->msqlquery, "profile", "Default", rec_id);
39.578 + _set_value(scheduler->msqlquery, "recgroup", "Default", rec_id);
39.579 + _set_value(scheduler->msqlquery, "storagegroup", "Default", rec_id);
39.580 + _set_value(scheduler->msqlquery, "playgroup", "Default", rec_id);
39.581 + _set_value(scheduler->msqlquery, "autoexpire", "1", rec_id);
39.582 + _set_value(scheduler->msqlquery, "maxepisodes", "0", rec_id);
39.583 + _set_value(scheduler->msqlquery, "maxnewest", "0", rec_id);
39.584 + _set_value(scheduler->msqlquery, "autocommflag", "1", rec_id);
39.585 + _set_value(scheduler->msqlquery, "autotranscode", "0", rec_id);
39.586 + _set_value(scheduler->msqlquery, "transcoder", "0", rec_id);
39.587 +
39.588 + _set_value(scheduler->msqlquery, "autouserjob1", "0", rec_id);
39.589 + _set_value(scheduler->msqlquery, "autouserjob2", "0", rec_id);
39.590 + _set_value(scheduler->msqlquery, "autouserjob3", "0", rec_id);
39.591 + _set_value(scheduler->msqlquery, "autouserjob4", "0", rec_id);
39.592 +
39.593 + schedule_info->schedule_id = rec_id;
39.594 +
39.595 + /* Notify the backend of changes */
39.596 + return update_backend(scheduler, rec_id);
39.597 +}
39.598 +
39.599 +/** Requests the Mysql database in the backend to add a new schedule.
39.600 + *
39.601 + * @param scheduler the GMythScheduler instance.
39.602 + * @param schedule_info the ScheduleInfo with recording schedule information
39.603 + * to be added. record_id = -1 to add a new schedule, otherwise this
39.604 + * function will update the schedule in the db
39.605 + * @return gboolean returns FALSE if some error occurs, TRUE otherwise
39.606 + */
39.607 +gboolean
39.608 +gmyth_scheduler_add_schedule (GMythScheduler * scheduler,
39.609 + ScheduleInfo * schedule_info)
39.610 +{
39.611 + return gmyth_scheduler_add_schedule_full (scheduler, schedule_info,
39.612 + GMYTH_SCHEDULE_ONE_OCCURRENCE);
39.613 +}
39.614 +
39.615 +/** Requests the Mysql database in the backend to remove an existing schedule.
39.616 + *
39.617 + * @param scheduler the GMythScheduler instance.
39.618 + * @param schedule_id The schedule's record id to be removed
39.619 + * @return gboolean TRUE if success, FALSE if error
39.620 + */
39.621 +gboolean
39.622 +gmyth_scheduler_delete_schedule(GMythScheduler * scheduler, gint schedule_id)
39.623 +{
39.624 +
39.625 + MYSQL_RES *msql_res;
39.626 + GString *query_str = NULL;
39.627 +
39.628 + g_return_val_if_fail (scheduler != NULL, FALSE);
39.629 +
39.630 +
39.631 + if (scheduler->msqlquery == NULL) {
39.632 + g_warning("[%s] Scheduler db connection not initialized",
39.633 + __FUNCTION__);
39.634 + return FALSE;
39.635 + }
39.636 +
39.637 + query_str = g_string_new("");
39.638 + g_string_printf(query_str,
39.639 + "DELETE FROM record WHERE recordid=%d", schedule_id);
39.640 +
39.641 + msql_res =
39.642 + gmyth_query_process_statement(scheduler->msqlquery,
39.643 + query_str->str);
39.644 +
39.645 +
39.646 + mysql_free_result(msql_res);
39.647 + g_string_free(query_str, TRUE);
39.648 +
39.649 + // Notify the backend of the changes
39.650 + return update_backend(scheduler, schedule_id);
39.651 +}
39.652 +
39.653 +/*
39.654 + * Add an exception program to be removed from the schedule list, when programs
39.655 + * where scheduled with the GMYTH_SCHEDULE_ALL_OCCURRENCES option.
39.656 + * @param scheduler the GMythScheduler instance.
39.657 + * @param schedule_id the schedule id of the all occurrence schedule to be changed
39.658 + * @param exception_info the ScheduleInfo to be removed from all schedule occurrences
39.659 + * @return TRUE if success, FALSE if any error happens
39.660 + */
39.661 +gboolean
39.662 +gmyth_scheduler_add_exception (GMythScheduler *scheduler, gint schedule_id,
39.663 + ScheduleInfo *exception_info)
39.664 +{
39.665 + gboolean res;
39.666 +
39.667 + g_return_val_if_fail (scheduler != NULL, FALSE);
39.668 + g_return_val_if_fail (exception_info != NULL, FALSE);
39.669 +
39.670 + exception_info->parentid = schedule_id;
39.671 + res = gmyth_scheduler_add_schedule_full (scheduler, exception_info, GMYTH_SCHEDULE_EXCEPTION);
39.672 +
39.673 + return res;
39.674 +}
39.675 +
39.676 +/** Requests the Mysql database in the backend to remove an existing recorded item.
39.677 + *
39.678 + * @param scheduler the GMythScheduler instance.
39.679 + * @param record_id The recorded item id to be removed
39.680 + * @return gboolean TRUE if success, FALSE if error
39.681 + */
39.682 +gboolean
39.683 +gmyth_scheduler_delete_recorded(GMythScheduler * scheduler, gint record_id)
39.684 +{
39.685 +
39.686 + MYSQL_RES *msql_res;
39.687 +
39.688 + GString *query_str = g_string_new("");
39.689 +
39.690 + assert(scheduler);
39.691 +
39.692 + if (scheduler->msqlquery == NULL) {
39.693 + g_warning("[%s] Scheduler db connection not initialized",
39.694 + __FUNCTION__);
39.695 + return FALSE;
39.696 + }
39.697 + // ========================================
39.698 + g_string_printf(query_str,
39.699 + "DELETE FROM recorded WHERE recordid=%d", record_id);
39.700 +
39.701 + // FIXME: Mythtv implementation runs also: DELETE FROM oldfind WHERE
39.702 + // recordid = x
39.703 +
39.704 + msql_res =
39.705 + gmyth_query_process_statement(scheduler->msqlquery,
39.706 + query_str->str);
39.707 +
39.708 + mysql_free_result(msql_res);
39.709 + g_string_free(query_str, TRUE);
39.710 +
39.711 + // Notify the backend of the changes
39.712 + return update_backend(scheduler, record_id);
39.713 +}
39.714 +
39.715 +
39.716 +gboolean gmyth_scheduler_was_recorded_before(GMythScheduler* scheduler, gint channel_id,
39.717 + time_t start_time)
39.718 +{
39.719 + MYSQL_RES *msql_res;
39.720 + GString *query_str = g_string_new("");
39.721 +
39.722 + assert(scheduler);
39.723 + g_string_printf(query_str, "SELECT callsign FROM channel "
39.724 + "WHERE chanid = \"%d\"", channel_id);
39.725 +
39.726 + msql_res = gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
39.727 +
39.728 + if (msql_res) {
39.729 + MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
39.730 + if (msql_row) {
39.731 + GString* callsign = g_string_new(msql_row[0]);
39.732 + GString* startts = gmyth_util_time_to_string(start_time);
39.733 + g_string_printf(query_str, "SELECT * FROM oldrecorded "
39.734 + "WHERE station = \"%s\" AND starttime = \"%s\"",
39.735 + callsign->str, startts->str);
39.736 + msql_res = gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
39.737 + g_string_free(callsign, TRUE);
39.738 + g_string_free(startts, TRUE);
39.739 + g_string_free(query_str, TRUE);
39.740 + if (mysql_fetch_row(msql_res)) return TRUE;
39.741 + }
39.742 + }
39.743 + return FALSE;
39.744 +}
39.745 +
39.746 +
39.747 +gboolean gmyth_scheduler_reactivate_schedule(GMythScheduler* scheduler, gint channel_id,
39.748 + time_t start_time)
39.749 +
39.750 +{
39.751 + MYSQL_RES *msql_res;
39.752 + GString *query_str = g_string_new("");
39.753 +
39.754 + assert(scheduler);
39.755 + g_string_printf(query_str, "SELECT callsign FROM channel "
39.756 + "WHERE chanid = \"%d\"", channel_id);
39.757 +
39.758 + msql_res = gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
39.759 + if (msql_res) {
39.760 + MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
39.761 + if (msql_row) {
39.762 + GString* callsign = g_string_new(msql_row[0]);
39.763 + GString* startts = gmyth_util_time_to_string(start_time);
39.764 + g_string_printf(query_str, "UPDATE oldrecorded SET reactivate = 1 "
39.765 + "WHERE station = \"%s\" AND starttime = \"%s\"",
39.766 + callsign->str, startts->str);
39.767 + gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
39.768 + g_string_free(callsign, TRUE);
39.769 + g_string_free(startts, TRUE);
39.770 + g_string_free(query_str, TRUE);
39.771 + return TRUE;
39.772 + }
39.773 +
39.774 + }
39.775 +
39.776 + return FALSE;
39.777 +}
39.778 +
39.779 +
39.780 +/*
39.781 + * This should only be used in special situations. We do not know the time that
39.782 + * the recording was set. We just know that it is an "ongoing" record and then
39.783 + * we have to use this to get it's info. It's always the oldest one -> first on list
39.784 + *
39.785 + */
39.786 +GMythProgramInfo*
39.787 +gmyth_scheduler_get_recorded_on_time(GMythScheduler* scheduler,
39.788 + guint channel_id)
39.789 +{
39.790 + MYSQL_RES *msql_res;
39.791 + GMythProgramInfo *proginfo = NULL;
39.792 + GString *query_str = g_string_new("");
39.793 +
39.794 + assert(scheduler);
39.795 +
39.796 + g_string_printf(query_str,
39.797 + "SELECT recorded.chanid,starttime,endtime,title,"
39.798 + "subtitle,description,channel.channum,"
39.799 + "channel.callsign,channel.name,channel.commfree,"
39.800 + "channel.outputfilters,seriesid,programid,filesize,"
39.801 + "lastmodified,stars,previouslyshown,originalairdate,"
39.802 + "hostname,recordid,transcoder,playgroup,"
39.803 + "recorded.recpriority,progstart,progend,basename,recgroup,"
39.804 + "category,findid,duplicate "
39.805 + "FROM recorded " "LEFT JOIN channel "
39.806 + "ON recorded.chanid = channel.chanid "
39.807 + "WHERE recorded.chanid = %d "
39.808 + "ORDER BY starttime DESC", channel_id);
39.809 +
39.810 + msql_res =
39.811 + gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
39.812 +
39.813 + if (msql_res) {
39.814 + MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
39.815 +
39.816 + if (msql_row) {
39.817 + proginfo = gmyth_program_info_new();
39.818 +
39.819 + proginfo->channel_id = (gint) g_ascii_strtoull (msql_row[0], NULL, 10);
39.820 + proginfo->recstartts = gmyth_util_string_to_time_val(msql_row[1]);
39.821 + proginfo->recendts = gmyth_util_string_to_time_val(msql_row[2]);
39.822 +
39.823 + proginfo->title = g_string_new(msql_row[3]);
39.824 + proginfo->subtitle = g_string_new(msql_row[4]);
39.825 + proginfo->description = g_string_new(msql_row[5]);
39.826 +
39.827 + proginfo->chanstr = g_string_new(msql_row[6]);
39.828 + proginfo->chansign = g_string_new(msql_row[7]);
39.829 + proginfo->channame = g_string_new(msql_row[8]);
39.830 + proginfo->chancommfree = (gint) g_ascii_strtoull(msql_row[9], NULL, 10);
39.831 + proginfo->chanOutputFilters = g_string_new(msql_row[10]);
39.832 + proginfo->seriesid = g_string_new(msql_row[11]);
39.833 + proginfo->program_id = g_string_new(msql_row[12]);
39.834 + proginfo->filesize = g_ascii_strtoull(msql_row[13], NULL, 10);
39.835 +
39.836 + proginfo->lastmodified = gmyth_util_string_to_time_val(msql_row[14]);
39.837 + proginfo->stars = g_ascii_strtod(msql_row[15], NULL);
39.838 + proginfo->repeat = (gint)g_ascii_strtoull(msql_row[16], NULL, 10);
39.839 +
39.840 + if (msql_row[17] == NULL) {
39.841 + proginfo->originalAirDate = 0;
39.842 + proginfo->hasAirDate = FALSE;
39.843 + } else {
39.844 + proginfo->originalAirDate = gmyth_util_string_to_time_val(msql_row[17]);
39.845 + proginfo->hasAirDate = TRUE;
39.846 + }
39.847 +
39.848 + proginfo->hostname = g_string_new(msql_row[18]);
39.849 + proginfo->recordid = (gint) g_ascii_strtoull(msql_row[19], NULL, 10);
39.850 + proginfo->transcoder = (gint) g_ascii_strtoull(msql_row[20], NULL, 10);
39.851 +
39.852 + proginfo->playgroup = g_string_new(msql_row[21]);
39.853 + proginfo->recpriority = (gint) g_ascii_strtoull(msql_row[22], NULL, 10);
39.854 +
39.855 + proginfo->startts = gmyth_util_string_to_time_val(msql_row[23]);
39.856 + proginfo->endts = gmyth_util_string_to_time_val(msql_row[24]);
39.857 + proginfo->pathname = g_string_new(g_strdup(msql_row[25]));
39.858 + proginfo->recgroup = g_string_new(msql_row[26]);
39.859 + proginfo->category = g_string_new(msql_row[27]);
39.860 + proginfo->findid = (gint) g_ascii_strtoull(msql_row[28], NULL, 10);
39.861 +
39.862 + proginfo->recpriority2 = 0;
39.863 +
39.864 + g_string_printf(query_str,
39.865 + "SELECT dupmethod,dupin,parentid,type "
39.866 + "FROM record WHERE recordid = \"%d\"", proginfo->recordid);
39.867 +
39.868 + msql_res =
39.869 + gmyth_query_process_statement(scheduler->msqlquery,
39.870 + query_str->str);
39.871 +
39.872 + if (msql_res) {
39.873 + MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
39.874 +
39.875 + if (msql_row) {
39.876 + proginfo->dupmethod = (gint) g_ascii_strtoull(msql_row[0], NULL, 10);
39.877 + proginfo->dupin = (gint) g_ascii_strtoull(msql_row[1], NULL, 10);
39.878 + proginfo->parentid = (gint) g_ascii_strtoull(msql_row[2], NULL, 10);
39.879 + proginfo->rectype = 0;
39.880 + }
39.881 + }
39.882 +
39.883 +
39.884 + g_string_printf(query_str,
39.885 + "SELECT sourceid,cardid,cardinputid,shareable "
39.886 + "FROM cardinput");
39.887 +
39.888 + msql_res =
39.889 + gmyth_query_process_statement(scheduler->msqlquery,
39.890 + query_str->str);
39.891 +
39.892 + if (msql_res) {
39.893 + MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
39.894 +
39.895 + if (msql_row) {
39.896 + proginfo->sourceid = 0;
39.897 + proginfo->cardid = 0;
39.898 + proginfo->inputid = 0;
39.899 + if (msql_row[3] != NULL && g_ascii_strcasecmp("Y", msql_row[3]) == 0)
39.900 + proginfo->shareable = 1;
39.901 + else
39.902 + proginfo->shareable = 0;
39.903 + }
39.904 + }
39.905 +
39.906 +
39.907 +
39.908 + }
39.909 + }
39.910 +
39.911 + g_string_free(query_str, TRUE);
39.912 + return proginfo;
39.913 +}
39.914 +
39.915 +/** Retrieves an existing recorded item information from database. The information
39.916 + * is used to fill the returned GMythProgramInfo.
39.917 + *
39.918 + * @param scheduler The GMythScheduler instance.
39.919 + * @param channel The channel associated to the record
39.920 + * @param starttime The record start time
39.921 + * @return A GMythProgramInfo struct with the requested record item
39.922 + * information, or NULL if error.
39.923 + */
39.924 +GMythProgramInfo *
39.925 +gmyth_scheduler_get_recorded(GMythScheduler * scheduler,
39.926 + GString * channel, GTimeVal * starttime)
39.927 +{
39.928 + MYSQL_RES *msql_res;
39.929 + GMythProgramInfo *proginfo = NULL;
39.930 + GString *query_str = g_string_new("");
39.931 + gchar *time_str =
39.932 + gmyth_util_time_to_string_from_time_val(starttime);
39.933 +
39.934 + assert(scheduler);
39.935 +
39.936 + gmyth_debug("[%s] channel: %s", __FUNCTION__, channel->str);
39.937 +
39.938 + if (scheduler->msqlquery == NULL) {
39.939 + g_warning("[%s] Scheduler db connection not initialized",
39.940 + __FUNCTION__);
39.941 + return NULL;
39.942 + }
39.943 +
39.944 + g_string_printf(query_str,
39.945 + "SELECT recorded.chanid,starttime,endtime,title, "
39.946 + "subtitle,description,channel.channum, "
39.947 + "channel.callsign,channel.name,channel.commfree, "
39.948 + "channel.outputfilters,seriesid,programid,filesize, "
39.949 + "lastmodified,stars,previouslyshown,originalairdate, "
39.950 + "hostname,recordid,transcoder,playgroup, "
39.951 + "recorded.recpriority,progstart,progend,basename,recgroup "
39.952 + "FROM recorded " "LEFT JOIN channel "
39.953 + "ON recorded.chanid = channel.chanid "
39.954 + "WHERE recorded.chanid = \"%s\" "
39.955 + "AND starttime = \"%s\" ;", channel->str, time_str);
39.956 +
39.957 + msql_res =
39.958 + gmyth_query_process_statement(scheduler->msqlquery,
39.959 + query_str->str);
39.960 +
39.961 + if (msql_res /* && query.size() > 0 */ ) {
39.962 + MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
39.963 +
39.964 + if (msql_row) {
39.965 + proginfo = gmyth_program_info_new();
39.966 +
39.967 + proginfo->channel_id = (gint) g_ascii_strtoull (msql_row[0], NULL, 10);
39.968 + proginfo->startts =
39.969 + gmyth_util_string_to_time_val(msql_row[23]);
39.970 + proginfo->endts = gmyth_util_string_to_time_val(msql_row[24]);
39.971 + proginfo->recstartts =
39.972 + gmyth_util_string_to_time_val(msql_row[1]);
39.973 + proginfo->recendts =
39.974 + gmyth_util_string_to_time_val(msql_row[2]);
39.975 + proginfo->title = g_string_new(msql_row[3]);
39.976 + proginfo->subtitle = g_string_new(msql_row[4]);
39.977 + proginfo->description = g_string_new(msql_row[5]);
39.978 +
39.979 + proginfo->chanstr = g_string_new(msql_row[6]);
39.980 + proginfo->chansign = g_string_new(msql_row[7]);
39.981 + proginfo->channame = g_string_new(msql_row[0]);
39.982 + proginfo->chancommfree =
39.983 + (gint) g_ascii_strtoull(msql_row[9], NULL, 10);
39.984 + proginfo->chanOutputFilters = g_string_new(msql_row[10]);
39.985 + proginfo->seriesid = g_string_new(msql_row[11]);
39.986 + proginfo->program_id = g_string_new(msql_row[12]);
39.987 + proginfo->filesize = g_ascii_strtoull(msql_row[13], NULL, 10);
39.988 +
39.989 + proginfo->lastmodified =
39.990 + gmyth_util_string_to_time_val(msql_row[14]);
39.991 + proginfo->stars = g_ascii_strtod(msql_row[15], NULL);
39.992 + proginfo->repeat =
39.993 + (gint) g_ascii_strtoull(msql_row[16], NULL, 10);
39.994 +
39.995 + if (msql_row[17] == NULL) {
39.996 + proginfo->originalAirDate = 0;
39.997 + proginfo->hasAirDate = FALSE;
39.998 + } else {
39.999 + proginfo->originalAirDate =
39.1000 + gmyth_util_string_to_time_val(msql_row[17]);
39.1001 + proginfo->hasAirDate = TRUE;
39.1002 + }
39.1003 +
39.1004 + proginfo->hostname = g_string_new(msql_row[18]);
39.1005 + proginfo->recordid =
39.1006 + (gint) g_ascii_strtoull(msql_row[19], NULL, 10);
39.1007 + proginfo->transcoder =
39.1008 + (gint) g_ascii_strtoull(msql_row[20], NULL, 10);
39.1009 + // proginfo->spread = -1;
39.1010 + // proginfo->programflags = proginfo->getProgramFlags();
39.1011 +
39.1012 + proginfo->recgroup = g_string_new(msql_row[26]);
39.1013 + proginfo->playgroup = g_string_new(msql_row[21]);
39.1014 + proginfo->recpriority =
39.1015 + (gint) g_ascii_strtoull(msql_row[22], NULL, 10);
39.1016 +
39.1017 + proginfo->pathname = g_string_new(g_strdup(msql_row[25]));
39.1018 +
39.1019 + gmyth_debug("One program info loaded from mysql database\n");
39.1020 + }
39.1021 + }
39.1022 +
39.1023 + mysql_free_result(msql_res);
39.1024 + g_string_free(query_str, TRUE);
39.1025 + g_free(time_str);
39.1026 +
39.1027 + return proginfo;
39.1028 +}
39.1029 +
39.1030 +gboolean
39.1031 +gmyth_scheduler_stop_recording (GMythScheduler * scheduler,
39.1032 + gint channel_id)
39.1033 +{
39.1034 + GMythProgramInfo *program;
39.1035 + GMythSocket *socket;
39.1036 + gboolean res = FALSE;
39.1037 + GMythStringList *slist;
39.1038 +
39.1039 + socket = gmyth_backend_info_get_connected_socket (scheduler->backend_info);
39.1040 + program = gmyth_scheduler_get_recorded_on_time (scheduler, channel_id);
39.1041 +
39.1042 + if (program) {
39.1043 + slist = gmyth_string_list_new();
39.1044 + gmyth_string_list_append_char_array(slist, "STOP_RECORDING");
39.1045 +
39.1046 + gmyth_string_list_append_string(slist, program->title); /* 0 */
39.1047 + gmyth_string_list_append_string(slist, program->subtitle); /* 1 */
39.1048 + gmyth_string_list_append_string(slist, program->description); /* 2 */
39.1049 + gmyth_string_list_append_string(slist, program->category); /* 3 */
39.1050 + gmyth_string_list_append_int(slist, program->channel_id); /* 4 */
39.1051 + gmyth_string_list_append_string(slist, program->chanstr); /* 5 */
39.1052 + gmyth_string_list_append_string(slist, program->chansign); /* 6 */
39.1053 + gmyth_string_list_append_string(slist, program->channame); /* 7 */
39.1054 + gmyth_string_list_append_string(slist, program->pathname); /* 8 */
39.1055 + gmyth_string_list_append_int64(slist, program->filesize); /* 9 */
39.1056 +
39.1057 + if (program->startts)
39.1058 + gmyth_string_list_append_int(slist, program->startts->tv_sec); /* 10 */
39.1059 + else
39.1060 + gmyth_string_list_append_int(slist, 0);
39.1061 +
39.1062 + if (program->endts)
39.1063 + gmyth_string_list_append_int(slist, program->endts->tv_sec); /* 11 */
39.1064 + else
39.1065 + gmyth_string_list_append_int(slist, 0);
39.1066 +
39.1067 + gmyth_string_list_append_int(slist, program->duplicate); /* 12 */
39.1068 + gmyth_string_list_append_int(slist, program->shareable); /* 13 */
39.1069 + gmyth_string_list_append_int(slist, program->findid); /* 14 */
39.1070 + gmyth_string_list_append_string(slist, program->hostname); /* 15 */
39.1071 + gmyth_string_list_append_int(slist, program->sourceid); /* 16 */
39.1072 + gmyth_string_list_append_int(slist, program->cardid); /* 17 */
39.1073 + gmyth_string_list_append_int(slist, program->inputid); /* 18 */
39.1074 + gmyth_string_list_append_int(slist, program->recpriority); /* 19 */
39.1075 +
39.1076 + // recstatus == recording
39.1077 + gmyth_string_list_append_int(slist, -3); /* 20 */
39.1078 +
39.1079 + gmyth_string_list_append_int(slist, program->recordid); /* 21 */
39.1080 + gmyth_string_list_append_int(slist, program->rectype); /* 22 */
39.1081 + gmyth_string_list_append_int(slist, program->dupin); /* 23 */
39.1082 + gmyth_string_list_append_int(slist, program->dupmethod); /* 24 */
39.1083 +
39.1084 +
39.1085 + //fixme
39.1086 + program->recstartts->tv_sec -= (60*60);
39.1087 +
39.1088 + gmyth_string_list_append_int(slist,
39.1089 + program->recstartts != NULL ?
39.1090 + program->recstartts->tv_sec : 0); /* 26 */
39.1091 +
39.1092 + gmyth_string_list_append_int(slist,
39.1093 + program->recendts != NULL ?
39.1094 + program->recendts->tv_sec : 0); /* 27 */
39.1095 +
39.1096 + gmyth_string_list_append_int(slist, program->repeat); /* 28 */
39.1097 + gmyth_string_list_append_int(slist, program->programflags); /* 29 */
39.1098 +
39.1099 + gmyth_string_list_append_char_array(slist,
39.1100 + program->recgroup != NULL ?
39.1101 + program->recgroup->str : "Default"); /* 30 */
39.1102 +
39.1103 + gmyth_string_list_append_int(slist, program->chancommfree); /* 31 */
39.1104 + gmyth_string_list_append_string(slist, program->chanOutputFilters); /* 32 */
39.1105 + gmyth_string_list_append_string(slist, program->seriesid); /* 33 */
39.1106 + gmyth_string_list_append_string(slist, program->program_id); /* 34 */
39.1107 +
39.1108 + gmyth_string_list_append_int(slist,
39.1109 + program->lastmodified != NULL ?
39.1110 + program->lastmodified->tv_sec : 0); /* 35 */
39.1111 +
39.1112 + gmyth_string_list_append_float(slist, program->stars); /* 36 */
39.1113 +
39.1114 + gmyth_string_list_append_int(slist,
39.1115 + program->originalAirDate != NULL ?
39.1116 + program->originalAirDate->tv_sec : 0); /* 37 */
39.1117 +
39.1118 + gmyth_string_list_append_int(slist, program->hasAirDate); /* 38 */
39.1119 +
39.1120 + gmyth_string_list_append_char_array(slist,
39.1121 + program->playgroup != NULL ?
39.1122 + program->playgroup->str : "Default"); /* 39 */
39.1123 +
39.1124 + gmyth_string_list_append_int(slist, program->recpriority2); /* 40 */
39.1125 + gmyth_string_list_append_int(slist, program->recpriority2); /* 40 */
39.1126 +
39.1127 + gmyth_socket_sendreceive_stringlist(socket, slist);
39.1128 + res = (gmyth_string_list_get_int(slist, 0) == 1);
39.1129 +
39.1130 + g_object_unref (program);
39.1131 + g_object_unref (slist);
39.1132 + }
39.1133 +
39.1134 + g_object_unref (socket);
39.1135 + return res;
39.1136 +}
39.1137 +
39.1138 +
39.1139 +/** Notifies the backend of an update in the db.
39.1140 + *
39.1141 + * @param record_id the id of the modified recording.
39.1142 + */
39.1143 +// fixme: put void and discovery record_id inside
39.1144 +static gboolean
39.1145 +update_backend (GMythScheduler * scheduler,
39.1146 + gint record_id)
39.1147 +{
39.1148 + GMythSocket *socket;
39.1149 + GMythStringList *strlist = gmyth_string_list_new();
39.1150 + GString *datastr = g_string_new("RESCHEDULE_RECORDINGS ");
39.1151 + gboolean ret = FALSE;
39.1152 +
39.1153 + g_string_append_printf(datastr, "%d", record_id);
39.1154 + gmyth_string_list_append_string(strlist, datastr);
39.1155 +
39.1156 + socket = gmyth_backend_info_get_connected_socket (scheduler->backend_info);
39.1157 + if (socket != NULL) {
39.1158 + ret = (gmyth_socket_sendreceive_stringlist(socket, strlist) > 0);
39.1159 + g_object_unref (socket);
39.1160 + } else {
39.1161 + g_warning("[%s] Connection to backend failed!", __FUNCTION__);
39.1162 + }
39.1163 +
39.1164 + g_string_free(datastr, TRUE);
39.1165 + g_object_unref(strlist);
39.1166 + return ret;
39.1167 +}
39.1168 +
39.1169 +void
39.1170 +gmyth_scheduler_recorded_info_get_preview(RecordedInfo * info,
39.1171 + GByteArray * data)
39.1172 +{
39.1173 +}
39.1174 +
39.1175 +void
39.1176 +gmyth_recorded_info_free(RecordedInfo * info)
39.1177 +{
39.1178 + g_return_if_fail (info != NULL);
39.1179 +
39.1180 + if (info->program_id)
39.1181 + g_string_free (info->program_id, TRUE);
39.1182 +
39.1183 + if (info->title != NULL)
39.1184 + g_string_free(info->title, TRUE);
39.1185 +
39.1186 + if (info->subtitle != NULL)
39.1187 + g_string_free(info->subtitle, TRUE);
39.1188 +
39.1189 + if (info->description != NULL)
39.1190 + g_string_free(info->description, TRUE);
39.1191 +
39.1192 + if (info->category != NULL)
39.1193 + g_string_free(info->category, TRUE);
39.1194 +
39.1195 + if (info->basename != NULL)
39.1196 + g_string_free(info->basename, TRUE);
39.1197 +
39.1198 + if (info != NULL)
39.1199 + g_free(info->start_time);
39.1200 +
39.1201 + if (info != NULL)
39.1202 + g_free(info->end_time);
39.1203 +
39.1204 + g_free(info);
39.1205 +}
39.1206 +
39.1207 +static void
39.1208 +free_recorded_info_item(gpointer data, gpointer user_data)
39.1209 +{
39.1210 + RecordedInfo *info = (RecordedInfo *) data;
39.1211 +
39.1212 + gmyth_recorded_info_free(info);
39.1213 +}
39.1214 +
39.1215 +void
39.1216 +gmyth_recorded_info_list_free(GList * list)
39.1217 +{
39.1218 + g_return_if_fail(list != NULL);
39.1219 +
39.1220 + g_list_foreach(list, free_recorded_info_item, NULL);
39.1221 + g_list_free(list);
39.1222 +}
39.1223 +
39.1224 +void
39.1225 +gmyth_schedule_info_free(ScheduleInfo * info)
39.1226 +{
39.1227 +
39.1228 + g_return_if_fail(info != NULL);
39.1229 +
39.1230 + if (info->program_id)
39.1231 + g_string_free (info->program_id, TRUE);
39.1232 +
39.1233 + if (info->title != NULL)
39.1234 + g_string_free(info->title, TRUE);
39.1235 +
39.1236 + if (info->subtitle != NULL)
39.1237 + g_string_free(info->subtitle, TRUE);
39.1238 +
39.1239 + if (info->description != NULL)
39.1240 + g_string_free(info->description, TRUE);
39.1241 +
39.1242 + if (info->category != NULL)
39.1243 + g_string_free(info->category, TRUE);
39.1244 +
39.1245 + if (info != NULL)
39.1246 + g_free(info->start_time);
39.1247 +
39.1248 + if (info != NULL)
39.1249 + g_free(info->end_time);
39.1250 +
39.1251 + g_free(info);
39.1252 +}
39.1253 +
39.1254 +static void
39.1255 +free_schedule_info_item(gpointer data, gpointer user_data)
39.1256 +{
39.1257 + ScheduleInfo *info = (ScheduleInfo *) data;
39.1258 +
39.1259 + gmyth_schedule_info_free(info);
39.1260 +}
39.1261 +
39.1262 +void
39.1263 +gmyth_schedule_info_list_free(GList * list)
39.1264 +{
39.1265 + g_return_if_fail(list != NULL);
39.1266 +
39.1267 + g_list_foreach(list, free_schedule_info_item, NULL);
39.1268 + g_list_free(list);
39.1269 +}
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
40.2 +++ b/gmyth/gmyth/gmyth_scheduler.h Mon Feb 25 17:51:43 2008 +0000
40.3 @@ -0,0 +1,194 @@
40.4 +/**
40.5 + * GMyth Library
40.6 + *
40.7 + * @file gmyth/gmyth_scheduler.h
40.8 + *
40.9 + * @brief <p> The scheduler encapsulates all functions for browsing, scheduling
40.10 + * and modifying the recorded content.
40.11 + *
40.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
40.13 + * @author Alexsandro Jose Virginio dos Santos <alexsandro.santos@indt.org.br>
40.14 + *
40.15 + *
40.16 + * This program is free software; you can redistribute it and/or modify
40.17 + * it under the terms of the GNU Lesser General Public License as published by
40.18 + * the Free Software Foundation; either version 2 of the License, or
40.19 + * (at your option) any later version.
40.20 + *
40.21 + * This program is distributed in the hope that it will be useful,
40.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
40.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40.24 + * GNU General Public License for more details.
40.25 + *
40.26 + * You should have received a copy of the GNU Lesser General Public License
40.27 + * along with this program; if not, write to the Free Software
40.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
40.29 + */
40.30 +
40.31 +#ifndef __GMYTH_SCHEDULER_H__
40.32 +#define __GMYTH_SCHEDULER_H__
40.33 +
40.34 +#include <glib-object.h>
40.35 +#include <time.h>
40.36 +
40.37 +#include "gmyth_common.h"
40.38 +#include "gmyth_query.h"
40.39 +#include "gmyth_backendinfo.h"
40.40 +
40.41 +G_BEGIN_DECLS
40.42 +
40.43 +typedef enum {
40.44 + GMYTH_SCHEDULE_ONE_OCCURRENCE,
40.45 + GMYTH_SCHEDULE_ALL_OCCURRENCES,
40.46 + GMYTH_SCHEDULE_EXCEPTION
40.47 +} GMythScheduleType;
40.48 +
40.49 +
40.50 +#define GMYTH_SCHEDULER_TYPE (gmyth_scheduler_get_type ())
40.51 +#define GMYTH_SCHEDULER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SCHEDULER_TYPE, GMythScheduler))
40.52 +#define GMYTH_SCHEDULER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SCHEDULER_TYPE, GMythSchedulerClass))
40.53 +#define IS_GMYTH_SCHEDULER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_SCHEDULER_TYPE))
40.54 +#define IS_GMYTH_SCHEDULER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SCHEDULER_TYPE))
40.55 +#define GMYTH_SCHEDULER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_SCHEDULER_TYPE, GMythSchedulerClass))
40.56 +
40.57 +typedef struct _GMythScheduler GMythScheduler;
40.58 +typedef struct _GMythSchedulerClass GMythSchedulerClass;
40.59 +
40.60 +struct _GMythSchedulerClass {
40.61 + GObjectClass parent_class;
40.62 +};
40.63 +
40.64 +struct _GMythScheduler {
40.65 + GObject parent;
40.66 +
40.67 + unsigned long recordid;
40.68 + unsigned long type;
40.69 + unsigned long search;
40.70 + GString *profile;
40.71 +
40.72 + long dupin;
40.73 + long dupmethod;
40.74 + long autoexpire;
40.75 + short int autotranscode;
40.76 + long transcoder;
40.77 +
40.78 + short int autocommflag;
40.79 + short int autouserjob1;
40.80 + short int autouserjob2;
40.81 + short int autouserjob3;
40.82 + short int autouserjob4;
40.83 +
40.84 + long startoffset;
40.85 + long endoffset;
40.86 + long maxepisodes;
40.87 + long maxnewest;
40.88 +
40.89 + long recpriority;
40.90 + GString *recgroup;
40.91 + GString *playgroup;
40.92 +
40.93 + long prefinput;
40.94 + short int inactive;
40.95 +
40.96 + GString *search_type;
40.97 + GString *search_what;
40.98 +
40.99 + GMythQuery *msqlquery;
40.100 + GMythBackendInfo *backend_info;
40.101 +};
40.102 +
40.103 +typedef struct {
40.104 + guint schedule_id;
40.105 + gint channel_id;
40.106 + GString *program_id;
40.107 +
40.108 + GTimeVal *start_time;
40.109 + GTimeVal *end_time;
40.110 +
40.111 + GString *seriesid;
40.112 + GString *title;
40.113 + GString *subtitle;
40.114 + GString *description;
40.115 + GString *category;
40.116 +
40.117 + GMythScheduleType type;
40.118 +
40.119 + gint parentid;
40.120 +
40.121 +} ScheduleInfo;
40.122 +
40.123 +typedef struct {
40.124 + guint record_id;
40.125 + gint channel_id;
40.126 + GString *program_id;
40.127 +
40.128 + GTimeVal *start_time;
40.129 + GTimeVal *end_time;
40.130 +
40.131 + GString *seriesid;
40.132 + GString *title;
40.133 + GString *subtitle;
40.134 + GString *description;
40.135 + GString *category;
40.136 +
40.137 + GString *basename;
40.138 +
40.139 + guint64 filesize;
40.140 +
40.141 +} RecordedInfo;
40.142 +
40.143 +
40.144 +GType gmyth_scheduler_get_type (void);
40.145 +
40.146 +GMythScheduler* gmyth_scheduler_new (void);
40.147 +gboolean gmyth_scheduler_connect (GMythScheduler * scheduler,
40.148 + GMythBackendInfo * backend_info);
40.149 +gboolean gmyth_scheduler_connect_with_timeout (GMythScheduler * scheduler,
40.150 + GMythBackendInfo * backend_info,
40.151 + guint timeout);
40.152 +gboolean gmyth_scheduler_disconnect (GMythScheduler * scheduler);
40.153 +gint gmyth_scheduler_get_schedule_list (GMythScheduler * scheduler,
40.154 + GList ** sched_list);
40.155 +gint gmyth_scheduler_get_recorded_list (GMythScheduler * scheduler,
40.156 + GList ** rec_list);
40.157 +RecordedInfo* gmyth_scheduler_get_recorded_info (GMythScheduler *scheduler,
40.158 + const char *basename);
40.159 +gboolean gmyth_scheduler_was_recorded_before (GMythScheduler* scheduler,
40.160 + gint channel_id,
40.161 + time_t start_time);
40.162 +gboolean gmyth_scheduler_reactivate_schedule (GMythScheduler* scheduler,
40.163 + gint channel_id,
40.164 + time_t start_time);
40.165 +GMythProgramInfo* gmyth_scheduler_get_recorded_on_time (GMythScheduler* scheduler,
40.166 + guint channel_id);
40.167 +GMythProgramInfo* gmyth_scheduler_get_recorded (GMythScheduler * scheduler,
40.168 + GString * channel,
40.169 + GTimeVal * starttime);
40.170 +ScheduleInfo* gmyth_scheduler_add_schedule_program (GMythScheduler * scheduler,
40.171 + GMythProgramInfo *program,
40.172 + GMythScheduleType type);
40.173 +gint gmyth_scheduler_add_schedule (GMythScheduler * scheduler,
40.174 + ScheduleInfo * schedule_info);
40.175 +gboolean gmyth_scheduler_add_schedule_full (GMythScheduler * scheduler,
40.176 + ScheduleInfo * schedule_info,
40.177 + GMythScheduleType type);
40.178 +gboolean gmyth_scheduler_add_exception (GMythScheduler *scheduler,
40.179 + gint schedule_id,
40.180 + ScheduleInfo *exception_info);
40.181 +gboolean gmyth_scheduler_delete_schedule (GMythScheduler * scheduler,
40.182 + gint record_id);
40.183 +gint gmyth_scheduler_delete_recorded (GMythScheduler * scheduler,
40.184 + gint record_id);
40.185 +gboolean gmyth_scheduler_stop_recording (GMythScheduler * scheduler,
40.186 + gint channel_id);
40.187 +void gmyth_scheduler_recorded_info_get_preview(RecordedInfo * info,
40.188 + GByteArray * data);
40.189 +
40.190 +
40.191 +void gmyth_recorded_info_free (RecordedInfo * info);
40.192 +void gmyth_schedule_info_free (ScheduleInfo * info);
40.193 +void gmyth_recorded_info_list_free (GList * list);
40.194 +void gmyth_schedule_info_list_free (GList * list);
40.195 +
40.196 +G_END_DECLS
40.197 +#endif /* __GMYTH_SCHEDULER_H__ */
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
41.2 +++ b/gmyth/gmyth/gmyth_socket.c Mon Feb 25 17:51:43 2008 +0000
41.3 @@ -0,0 +1,1295 @@
41.4 +/**
41.5 + * GMyth Library
41.6 + *
41.7 + * @file gmyth/gmyth_socket.c
41.8 + *
41.9 + * @brief <p> MythTV socket implementation, according to the MythTV Project
41.10 + * (www.mythtv.org).
41.11 + *
41.12 + * This component provides basic socket functionalities to interact with
41.13 + * the Mythtv backend.
41.14 + * <p>
41.15 + *
41.16 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
41.17 + * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
41.18 + *
41.19 + *
41.20 + * This program is free software; you can redistribute it and/or modify
41.21 + * it under the terms of the GNU Lesser General Public License as published by
41.22 + * the Free Software Foundation; either version 2 of the License, or
41.23 + * (at your option) any later version.
41.24 + *
41.25 + * This program is distributed in the hope that it will be useful,
41.26 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
41.27 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41.28 + * GNU General Public License for more details.
41.29 + *
41.30 + * You should have received a copy of the GNU Lesser General Public License
41.31 + * along with this program; if not, write to the Free Software
41.32 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41.33 + */
41.34 +
41.35 +#ifdef HAVE_CONFIG_H
41.36 +#include "config.h"
41.37 +#endif
41.38 +
41.39 +#include "gmyth_socket.h"
41.40 +
41.41 +#include <glib.h>
41.42 +#include <glib/gprintf.h>
41.43 +
41.44 +#include <arpa/inet.h>
41.45 +#include <sys/types.h>
41.46 +#include <sys/socket.h>
41.47 +#include <sys/param.h>
41.48 +#include <netdb.h>
41.49 +#include <net/if.h>
41.50 +#include <errno.h>
41.51 +#include <assert.h>
41.52 +#include <stdlib.h>
41.53 +
41.54 +#include <unistd.h>
41.55 +#include <netinet/in.h>
41.56 +#include <fcntl.h>
41.57 +#include <signal.h>
41.58 +
41.59 +#include <sys/ioctl.h>
41.60 +
41.61 +#include "gmyth_stringlist.h"
41.62 +#include "gmyth_uri.h"
41.63 +#include "gmyth_debug.h"
41.64 +
41.65 +#define BUFLEN 512
41.66 +#define MYTH_SEPARATOR "[]:[]"
41.67 +#define MYTH_PROTOCOL_FIELD_SIZE 8
41.68 +
41.69 +/*
41.70 + * max number of iterations
41.71 + */
41.72 +#define MYTHTV_MAX_VERSION_CHECKS 40
41.73 +
41.74 +// FIXME: put this in the right place
41.75 +#define MYTHTV_VERSION_DEFAULT 31
41.76 +
41.77 +/*
41.78 + * static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
41.79 + */
41.80 +
41.81 +/*
41.82 + * static GStaticRWLock rwlock = G_STATIC_RW_LOCK_INIT;
41.83 + */
41.84 +
41.85 +static gchar *local_hostname = NULL;
41.86 +
41.87 +static void gmyth_socket_class_init(GMythSocketClass * klass);
41.88 +static void gmyth_socket_init(GMythSocket * object);
41.89 +
41.90 +static void gmyth_socket_dispose(GObject * object);
41.91 +static void gmyth_socket_finalize(GObject * object);
41.92 +
41.93 +G_DEFINE_TYPE(GMythSocket, gmyth_socket, G_TYPE_OBJECT)
41.94 + static void gmyth_socket_class_init(GMythSocketClass * klass)
41.95 +{
41.96 + GObjectClass *gobject_class;
41.97 +
41.98 + gobject_class = (GObjectClass *) klass;
41.99 +
41.100 + gobject_class->dispose = gmyth_socket_dispose;
41.101 + gobject_class->finalize = gmyth_socket_finalize;
41.102 +}
41.103 +
41.104 +static void
41.105 +gmyth_socket_init(GMythSocket * gmyth_socket)
41.106 +{
41.107 +
41.108 + /*
41.109 + * gmyth_socket->local_hostname = NULL;
41.110 + */
41.111 +
41.112 +}
41.113 +
41.114 +/** Gets the some important address translation info, from the client socket
41.115 + * that will open a connection.
41.116 + *
41.117 + * @return gint that represents the error number from getaddrinfo().
41.118 + */
41.119 +static gint
41.120 +gmyth_socket_toaddrinfo(const gchar * addr, gint port,
41.121 + struct addrinfo **addrInfo)
41.122 +{
41.123 + struct addrinfo hints;
41.124 + gchar *portStr = NULL;
41.125 + gint errorn = EADDRNOTAVAIL;
41.126 +
41.127 + g_return_val_if_fail(addr != NULL, -1);
41.128 +
41.129 + memset(&hints, 0, sizeof(struct addrinfo));
41.130 + hints.ai_family = AF_INET;
41.131 + hints.ai_socktype = SOCK_STREAM;
41.132 + /*
41.133 + * hints.ai_flags = AI_NUMERICHOST;
41.134 + */
41.135 +
41.136 + if (port != -1)
41.137 + portStr = g_strdup_printf("%d", port);
41.138 + else
41.139 + portStr = NULL;
41.140 +
41.141 + gmyth_debug("Getting name resolution for: %s, %d\n", addr, port);
41.142 +
41.143 + if ((errorn = getaddrinfo(addr, portStr, &hints, addrInfo)) != 0) {
41.144 + gmyth_debug("[%s] Socket ERROR: %s\n", __FUNCTION__,
41.145 + gai_strerror(errorn));
41.146 + }
41.147 +
41.148 + g_free(portStr);
41.149 +
41.150 + return errorn;
41.151 +}
41.152 +
41.153 +/*
41.154 + * static gint gmyth_socket_find_match_address_uri( GMythURI* uri, gchar
41.155 + * *address ) { if ( g_ascii_strcasecmp( gmyth_uri_get_host( uri ),
41.156 + * address ) == 0 ) { //gmyth_debug( "Found URI: %s !!!\n",
41.157 + * rui_uri_getvalue(uri) ); return 0; } else { return -1; } }
41.158 + */
41.159 +
41.160 +const gchar *PATH_PROC_NET_DEV = "/proc/net/dev";
41.161 +
41.162 +/** Gets the list of all local network interfaces (using the /proc/net/dev directory).
41.163 + *
41.164 + * @param current_connections A list with all the network interfaces are valid,
41.165 + * to be applied just like a filter.
41.166 + * @return List with all the local net interfaces.
41.167 + */
41.168 +GList *
41.169 +gmyth_socket_get_local_addrs(GList * current_connections)
41.170 +{
41.171 +
41.172 + GList *local_addrs = NULL;
41.173 + FILE *fd;
41.174 + gint s;
41.175 + gchar buffer[256 + 1];
41.176 + gchar ifaddr[20 + 1];
41.177 + gchar *ifname;
41.178 + gchar *sep;
41.179 +
41.180 + s = socket(AF_INET, SOCK_DGRAM, 0);
41.181 + if (s < 0)
41.182 + return 0;
41.183 + fd = fopen(PATH_PROC_NET_DEV, "r");
41.184 + fgets(buffer, sizeof(buffer) - 1, fd);
41.185 + fgets(buffer, sizeof(buffer) - 1, fd);
41.186 + while (!feof(fd)) {
41.187 + ifname = buffer;
41.188 +
41.189 + if (fgets(buffer, sizeof(buffer) - 1, fd) == NULL)
41.190 + break;
41.191 + sep = strrchr(buffer, ':');
41.192 + if (sep)
41.193 + *sep = 0;
41.194 + while (*ifname == ' ')
41.195 + ifname++;
41.196 + struct ifreq req;
41.197 +
41.198 + strcpy(req.ifr_name, ifname);
41.199 + if (ioctl(s, SIOCGIFFLAGS, &req) < 0)
41.200 + continue;
41.201 + if (!(req.ifr_flags & IFF_UP))
41.202 + continue;
41.203 + if (req.ifr_flags & IFF_LOOPBACK)
41.204 + continue;
41.205 + if (ioctl(s, SIOCGIFADDR, &req) < 0)
41.206 + continue;
41.207 + g_strlcpy(ifaddr,
41.208 + inet_ntoa(((struct sockaddr_in *) &req.ifr_addr)->
41.209 + sin_addr), sizeof(struct ifaddr) - 1);
41.210 + local_addrs = g_list_append(local_addrs, g_strdup(ifaddr));
41.211 +
41.212 + gmyth_debug
41.213 + ("( from the /proc/net/dev) Interface name: %s, address: %s\n",
41.214 + ifname, ifaddr);
41.215 + }
41.216 + fclose(fd);
41.217 + close(s);
41.218 + return local_addrs;
41.219 +}
41.220 +
41.221 +/**
41.222 + * Get only the local addresses from the primary interface
41.223 + */
41.224 +gchar *
41.225 +gmyth_socket_get_primary_addr(void)
41.226 +{
41.227 + gchar *if_eth0 = g_new0(gchar, sizeof(struct ifaddr) - 1);
41.228 + GList *if_tmp = NULL;
41.229 +
41.230 + GList *interfs = gmyth_socket_get_local_addrs(NULL);
41.231 +
41.232 + if (interfs != NULL && (g_list_length(interfs) > 0)) {
41.233 + // get the first occurrence (primary interface)
41.234 + if_tmp = g_list_first(interfs);
41.235 +
41.236 + if (if_tmp != NULL)
41.237 + g_strlcpy(if_eth0, (gchar *) if_tmp->data,
41.238 + sizeof(struct ifaddr) - 1);
41.239 +
41.240 + }
41.241 +
41.242 + if (interfs != NULL)
41.243 + g_list_free(interfs);
41.244 +
41.245 + return if_eth0;
41.246 +}
41.247 +
41.248 +/** This function retrieves the local hostname of the
41.249 + * client machine.
41.250 + *
41.251 + * @return GString* get local hostname.
41.252 + */
41.253 +GString *
41.254 +gmyth_socket_get_local_hostname(void)
41.255 +{
41.256 + char hname[50];
41.257 + gint res = gethostname(hname, 50);
41.258 +
41.259 + if (res == -1) {
41.260 + gmyth_debug("Error while getting hostname");
41.261 + return g_string_new("default");
41.262 + }
41.263 +
41.264 + return g_string_new(hname);
41.265 +
41.266 +#if 0
41.267 + GString *str = NULL;
41.268 +
41.269 + if (local_hostname != NULL && strlen(local_hostname) > 0)
41.270 + return g_string_new(local_hostname);
41.271 +
41.272 + gchar *localaddr = NULL;
41.273 + gboolean found_addr = FALSE;
41.274 + struct addrinfo *addr_info_data = NULL,
41.275 + *addr_info0 = NULL;
41.276 + struct sockaddr_in *sa = NULL;
41.277 + gchar localhostname[MAXHOSTNAMELEN];
41.278 +
41.279 +
41.280 + if (gethostname(localhostname, MAXHOSTNAMELEN) != 0) {
41.281 + gmyth_debug("Error on gethostname");
41.282 + }
41.283 + localhostname[MAXHOSTNAMELEN - 1] = 0;
41.284 +
41.285 + gint err =
41.286 + gmyth_socket_toaddrinfo(localhostname, -1, &addr_info_data);
41.287 +
41.288 + if (err == EADDRNOTAVAIL) {
41.289 + gmyth_debug("[%s] Address (%s) not available. (reason = %d)\n",
41.290 + __FUNCTION__, localhostname, err);
41.291 + return str;
41.292 + }
41.293 +
41.294 + g_mutex_lock(gmyth_socket->mutex);
41.295 +
41.296 + addr_info0 = addr_info_data;
41.297 +
41.298 + while (addr_info0 != NULL && addr_info0->ai_addr != NULL &&
41.299 + (sa = (struct sockaddr_in *) addr_info0->ai_addr) != NULL
41.300 + && !found_addr) {
41.301 + localaddr = inet_ntoa(sa->sin_addr);
41.302 +
41.303 + if (localaddr != NULL && (g_strrstr(localaddr, "127") == NULL)) {
41.304 + str = g_string_new(localaddr);
41.305 + found_addr = TRUE;
41.306 + g_free(localaddr);
41.307 + break;
41.308 + }
41.309 + /*
41.310 + * if (localaddr != NULL) { g_free (localaddr); localaddr = NULL;
41.311 + * }
41.312 + */
41.313 +
41.314 + addr_info0 = addr_info0->ai_next;
41.315 + };
41.316 +
41.317 + freeaddrinfo(addr_info_data);
41.318 + addr_info_data = NULL;
41.319 +
41.320 + if (found_addr == FALSE) {
41.321 + gchar *prim_addr = gmyth_socket_get_primary_addr();
41.322 +
41.323 + if (prim_addr != NULL) {
41.324 + gmyth_debug
41.325 + ("[%s] Could not determine the local alphanumerical hostname. Setting to %s\n",
41.326 + __FUNCTION__, prim_addr);
41.327 +
41.328 + str = g_string_new(prim_addr);
41.329 + g_free(prim_addr);
41.330 + } else {
41.331 + str = g_string_new(localhostname);
41.332 + }
41.333 + }
41.334 +
41.335 + g_mutex_unlock(gmyth_socket->mutex);
41.336 +
41.337 + if (str != NULL && str->str != NULL)
41.338 + local_hostname = g_strdup(str->str);
41.339 +
41.340 + return str;
41.341 +#endif
41.342 +}
41.343 +
41.344 +static void
41.345 +gmyth_socket_dispose(GObject * object)
41.346 +{
41.347 + GMythSocket *gmyth_socket = GMYTH_SOCKET(object);
41.348 +
41.349 + /*
41.350 + * disconnect socket
41.351 + */
41.352 + gmyth_socket_close_connection(gmyth_socket);
41.353 +
41.354 + g_free(gmyth_socket->hostname);
41.355 +
41.356 + g_free(local_hostname);
41.357 +
41.358 + local_hostname = NULL;
41.359 +
41.360 + if (gmyth_socket->mutex != NULL) {
41.361 + g_mutex_free(gmyth_socket->mutex);
41.362 + gmyth_socket->mutex = NULL;
41.363 + }
41.364 +
41.365 + G_OBJECT_CLASS(gmyth_socket_parent_class)->dispose(object);
41.366 +}
41.367 +
41.368 +static void
41.369 +gmyth_socket_finalize(GObject * object)
41.370 +{
41.371 + g_signal_handlers_destroy(object);
41.372 +
41.373 + G_OBJECT_CLASS(gmyth_socket_parent_class)->finalize(object);
41.374 +}
41.375 +
41.376 +/** Creates a new instance of GMythSocket.
41.377 + *
41.378 + * @return a new instance of GMythSocket.
41.379 + */
41.380 +GMythSocket *
41.381 +gmyth_socket_new()
41.382 +{
41.383 + GMythSocket *gmyth_socket =
41.384 + GMYTH_SOCKET(g_object_new(GMYTH_SOCKET_TYPE, NULL));
41.385 +
41.386 + gmyth_socket->mythtv_version = MYTHTV_VERSION_DEFAULT;
41.387 +
41.388 + gmyth_socket->mutex = g_mutex_new();
41.389 +
41.390 + return gmyth_socket;
41.391 +}
41.392 +
41.393 +/** Try to open an asynchronous connection to the MythTV backend.
41.394 + *
41.395 + * @param fd Socket descriptor.
41.396 + * @param remote Remote address.
41.397 + * @param len Newly created socket length field.
41.398 + * @param timeout Timeval argument with the time interval to timeout before closing.
41.399 + * @param err Error message number.
41.400 + * @return Any numerical value below 0, if an error had been found.
41.401 + */
41.402 +static gint
41.403 +gmyth_socket_try_connect(gint fd, struct sockaddr *remote, gint len,
41.404 + struct timeval *timeout, gint * err)
41.405 +{
41.406 + /*
41.407 + * g_return_val_if_fail( timeout != NULL, 0 );
41.408 + */
41.409 + gint saveflags,
41.410 + ret,
41.411 + back_err;
41.412 +
41.413 + fd_set fd_w;
41.414 +
41.415 + saveflags = fcntl(fd, F_GETFL, 0);
41.416 + if (saveflags < 0) {
41.417 + gmyth_debug("[%s] Problems when getting socket flags on fcntl.\n",
41.418 + __FUNCTION__);
41.419 + *err = errno;
41.420 + return -1;
41.421 + }
41.422 +
41.423 + /*
41.424 + * Set non blocking
41.425 + */
41.426 + if (fcntl(fd, F_SETFL, saveflags | O_NONBLOCK) < 0) {
41.427 + gmyth_debug
41.428 + ("[%s] Problems when setting non-blocking using fcntl.\n",
41.429 + __FUNCTION__);
41.430 + *err = errno;
41.431 + return -1;
41.432 + }
41.433 +
41.434 + /*
41.435 + * This will return immediately
41.436 + */
41.437 + *err = connect(fd, remote, len);
41.438 + back_err = errno;
41.439 +
41.440 + /*
41.441 + * restore flags
41.442 + */
41.443 + if (fcntl(fd, F_SETFL, saveflags) < 0) {
41.444 + gmyth_debug
41.445 + ("[%s] Problems when trying to restore flags with fcntl.\n",
41.446 + __FUNCTION__);
41.447 + *err = errno;
41.448 + return -1;
41.449 + }
41.450 +
41.451 + /*
41.452 + * return unless the connection was successful or the connect is still
41.453 + * in progress.
41.454 + */
41.455 + if (*err < 0 && back_err != EINPROGRESS) {
41.456 + gmyth_debug
41.457 + ("[%s] Connection unsucessfully (it is not in progress).\n",
41.458 + __FUNCTION__);
41.459 + *err = errno;
41.460 + return -1;
41.461 + }
41.462 +
41.463 + FD_ZERO(&fd_w);
41.464 + FD_SET(fd, &fd_w);
41.465 +
41.466 + *err = select(FD_SETSIZE, NULL, &fd_w, NULL, timeout);
41.467 + if (*err < 0) {
41.468 + gmyth_debug("[%s] Connection unsucessfull (timed out).\n",
41.469 + __FUNCTION__);
41.470 + *err = errno;
41.471 + return -1;
41.472 + }
41.473 +
41.474 + /*
41.475 + * 0 means it timeout out & no fds changed
41.476 + */
41.477 + if (*err == 0) {
41.478 + gmyth_debug
41.479 + ("[%s] Connection unsucessfull [%d] - 0 means it timeout out & no fds changed\n",
41.480 + __FUNCTION__, *err);
41.481 + close(fd);
41.482 + *err = ETIMEDOUT;
41.483 + return -1;
41.484 + }
41.485 +
41.486 + /*
41.487 + * Get the return code from the connect
41.488 + */
41.489 + len = sizeof(ret);
41.490 + *err = getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, (socklen_t *) & len);
41.491 +
41.492 + if (*err < 0) {
41.493 + gmyth_debug("[%s] Connection unsucessfull.\n", __FUNCTION__);
41.494 + *err = errno;
41.495 + return -1;
41.496 + }
41.497 +
41.498 + /*
41.499 + * ret=0 means success, otherwise it contains the errno
41.500 + */
41.501 + if (ret) {
41.502 + gmyth_debug
41.503 + ("[%s] Connection unsucessfull - Couldn't connect to remote host!!!\n",
41.504 + __FUNCTION__);
41.505 + *err = ret;
41.506 + return -1;
41.507 + }
41.508 +
41.509 + *err = 0;
41.510 + return 0;
41.511 +}
41.512 +
41.513 +/** Connects to the backend.
41.514 + *
41.515 + * @param gmyth_socket The GMythSocket instance.
41.516 + * @param hostname The backend hostname or IP address.
41.517 + * @param port The backend port.
41.518 + * @return TRUE if success, FALSE if error.
41.519 + */
41.520 +
41.521 +
41.522 +gboolean
41.523 +gmyth_socket_connect(GMythSocket * gmyth_socket,
41.524 + const gchar * hostname, gint port)
41.525 +{
41.526 + return gmyth_socket_connect_with_timeout(gmyth_socket, hostname, port,
41.527 + 30);
41.528 +}
41.529 +
41.530 +gboolean
41.531 +gmyth_socket_connect_with_timeout(GMythSocket * gmyth_socket,
41.532 + const gchar * hostname, gint port,
41.533 + guint timeout)
41.534 +{
41.535 + struct addrinfo *addr_info_data = NULL,
41.536 + *addr_info0 = NULL;
41.537 + struct linger ling;
41.538 + gchar *tmp_str;
41.539 + gint ret_code = 0; /* -1 */
41.540 +
41.541 + /*
41.542 + * FIXME: add as function parameter
41.543 + */
41.544 + gint err;
41.545 + gint errno;
41.546 + gboolean ret = TRUE;
41.547 +
41.548 + gmyth_debug("CONNECTING %s:%d", hostname, port);
41.549 +
41.550 + if (hostname == NULL)
41.551 + gmyth_debug("Invalid hostname parameter!\n");
41.552 +
41.553 + /*
41.554 + * store hostname and port number
41.555 + */
41.556 + gmyth_debug("CONNECTING %s:%d", hostname, port);
41.557 +
41.558 + errno = gmyth_socket_toaddrinfo(hostname, port, &addr_info_data);
41.559 +
41.560 + g_return_val_if_fail(addr_info_data != NULL
41.561 + && hostname != NULL, FALSE);
41.562 +
41.563 + /*
41.564 + * hack to avoid deleting the hostname when gmyth_socket->hostname ==
41.565 + * hostname
41.566 + */
41.567 + tmp_str = gmyth_socket->hostname;
41.568 +
41.569 + gmyth_socket->hostname = g_strdup(hostname);
41.570 + gmyth_socket->port = port;
41.571 +
41.572 + g_free(tmp_str);
41.573 +
41.574 + for (addr_info0 = addr_info_data; addr_info0;
41.575 + addr_info0 = addr_info_data->ai_next) {
41.576 + /*
41.577 + * init socket descriptor
41.578 + */
41.579 +
41.580 + g_debug ("FAMILY: %d, TYPE: %d, PROTOCOL: %d",
41.581 + addr_info0->ai_family,
41.582 + addr_info0->ai_socktype,
41.583 + addr_info0->ai_protocol);
41.584 + gmyth_socket->sd =
41.585 + socket(addr_info0->ai_family, addr_info0->ai_socktype,
41.586 + addr_info0->ai_protocol);
41.587 +
41.588 + if (gmyth_socket->sd < 0)
41.589 + continue;
41.590 +
41.591 + struct timeval *timeout_val = g_new0(struct timeval, 1);
41.592 +
41.593 + if (timeout != 0) {
41.594 + timeout_val->tv_sec = timeout;
41.595 + timeout_val->tv_usec = 0;
41.596 + } else {
41.597 + timeout_val->tv_sec = 5;
41.598 + timeout_val->tv_usec = 100;
41.599 + }
41.600 +
41.601 + if (gmyth_socket_try_connect
41.602 + (gmyth_socket->sd, (struct sockaddr *) addr_info0->ai_addr,
41.603 + addr_info0->ai_addrlen, timeout_val, &ret_code) < 0) {
41.604 + gmyth_debug("[%s] Error connecting to backend!\n",
41.605 + __FUNCTION__);
41.606 + if (ret_code == ETIMEDOUT)
41.607 + gmyth_debug("[%s]\tBackend host unreachable!\n",
41.608 + __FUNCTION__);
41.609 +
41.610 + close(gmyth_socket->sd);
41.611 + gmyth_socket->sd = -1;
41.612 + gmyth_debug("ERROR: %s\n", gai_strerror(ret_code));
41.613 + g_free(timeout_val);
41.614 + continue;
41.615 + }
41.616 +
41.617 + g_free(timeout_val);
41.618 +
41.619 + /*
41.620 + * only will be reached if none of the error above occurred
41.621 + */
41.622 + break;
41.623 + }
41.624 +
41.625 + freeaddrinfo(addr_info_data);
41.626 + addr_info_data = NULL;
41.627 +
41.628 + if (gmyth_socket->sd_io_ch != NULL) {
41.629 + g_io_channel_unref(gmyth_socket->sd_io_ch);
41.630 + gmyth_socket->sd_io_ch = NULL;
41.631 + }
41.632 +
41.633 +
41.634 + memset(&ling, 0, sizeof(struct linger));
41.635 + ling.l_onoff = TRUE;
41.636 + ling.l_linger = 1;
41.637 +
41.638 + err =
41.639 + setsockopt(gmyth_socket->sd, SOL_SOCKET, SO_LINGER, &ling,
41.640 + sizeof(struct linger));
41.641 +
41.642 + if (err < 0) {
41.643 + gmyth_debug("[%s] Setting connection unsucessfull.\n",
41.644 + __FUNCTION__);
41.645 + err = errno;
41.646 + ret = FALSE;
41.647 + goto cleanup;
41.648 + }
41.649 +
41.650 + gmyth_socket->sd_io_ch = g_io_channel_unix_new(gmyth_socket->sd);
41.651 +
41.652 + g_io_channel_set_close_on_unref(gmyth_socket->sd_io_ch, TRUE);
41.653 + // g_io_channel_set_encoding (gmyth_socket->sd_io_ch, NULL, NULL );
41.654 +
41.655 + GIOFlags flags = g_io_channel_get_flags(gmyth_socket->sd_io_ch);
41.656 +
41.657 + /*
41.658 + * unset the nonblock flag
41.659 + */
41.660 + flags &= ~G_IO_FLAG_NONBLOCK;
41.661 + /*
41.662 + * unset the nonblocking stuff for some time, because GNUTLS doesn't
41.663 + * like that
41.664 + */
41.665 + g_io_channel_set_flags(gmyth_socket->sd_io_ch, flags, NULL);
41.666 +
41.667 + ret = (ret_code == 0) ? TRUE : FALSE;
41.668 +
41.669 + cleanup:
41.670 + if (!ret)
41.671 + gmyth_debug("GMythSocket error - return code error!");
41.672 +
41.673 + return ret;
41.674 +}
41.675 +
41.676 +/** Gets the GIOChannel associated to the given GMythSocket.
41.677 + *
41.678 + * @param gmyth_socket The GMythSocket instance.
41.679 + */
41.680 +GIOChannel *
41.681 +gmyth_socket_get_io_channel(GMythSocket * gmyth_socket)
41.682 +{
41.683 + g_return_val_if_fail(gmyth_socket != NULL, NULL);
41.684 +
41.685 + return gmyth_socket->sd_io_ch;
41.686 +}
41.687 +
41.688 +/** Verifies if the socket is able to read.
41.689 + *
41.690 + * @param gmyth_socket The GMythSocket instance.
41.691 + * @return TRUE if the socket is able to read, FALSE if not.
41.692 + */
41.693 +gboolean
41.694 +gmyth_socket_is_able_to_read(GMythSocket * gmyth_socket)
41.695 +{
41.696 + gboolean ret = TRUE;
41.697 +
41.698 + /*
41.699 + * verify if the input (read) buffer is ready to receive data
41.700 + */
41.701 + GIOCondition io_cond =
41.702 + g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch);
41.703 +
41.704 + if ((io_cond & G_IO_IN) == 0) {
41.705 + gmyth_debug("[%s] IO channel is not able to send data!\n",
41.706 + __FUNCTION__);
41.707 + ret = FALSE;
41.708 + }
41.709 +
41.710 + return ret;
41.711 +
41.712 +}
41.713 +
41.714 +/** Verifies if the socket is able to write.
41.715 + *
41.716 + * @param gmyth_socket The GMythSocket instance.
41.717 + * @return TRUE if the socket is able to write, FALSE if not.
41.718 + */
41.719 +gboolean
41.720 +gmyth_socket_is_able_to_write(GMythSocket * gmyth_socket)
41.721 +{
41.722 + gboolean ret = TRUE;
41.723 +
41.724 + /*
41.725 + * verify if the input (read) buffer is ready to receive data
41.726 + */
41.727 + GIOCondition io_cond =
41.728 + g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch);
41.729 +
41.730 + if (((io_cond & G_IO_OUT) == 0) || ((io_cond & G_IO_HUP) == 0)) {
41.731 + gmyth_debug("[%s] IO channel is not able to send data!\n",
41.732 + __FUNCTION__);
41.733 + ret = FALSE;
41.734 + }
41.735 +
41.736 + return ret;
41.737 +
41.738 +}
41.739 +
41.740 +/** Sends a command to the backend.
41.741 + *
41.742 + * @param gmyth_socket the GMythSocket instance.
41.743 + * @param command The string command to be sent.
41.744 + */
41.745 +gboolean
41.746 +gmyth_socket_send_command(GMythSocket * gmyth_socket, GString * command)
41.747 +{
41.748 + gboolean ret = TRUE;
41.749 +
41.750 + GIOStatus io_status = G_IO_STATUS_NORMAL;
41.751 +
41.752 + // GIOCondition io_cond;
41.753 + GError *error = NULL;
41.754 +
41.755 + gchar *buffer = NULL;
41.756 +
41.757 + gsize bytes_written = 0;
41.758 +
41.759 + g_return_val_if_fail(gmyth_socket->sd_io_ch != NULL, FALSE);
41.760 +
41.761 + if (command == NULL || (command->len <= 0) || command->str == NULL) {
41.762 + gmyth_debug("[%s] Invalid NULL command parameter!\n",
41.763 + __FUNCTION__);
41.764 + ret = FALSE;
41.765 + goto done;
41.766 + }
41.767 +
41.768 + g_mutex_lock(gmyth_socket->mutex);
41.769 + gmyth_debug("Sending command to backend: %s\n", command->str);
41.770 +
41.771 + buffer = g_strnfill(BUFLEN, ' ');
41.772 + g_snprintf(buffer, MYTH_PROTOCOL_FIELD_SIZE + 1, "%-8d", command->len);
41.773 +
41.774 + command = g_string_prepend(command, buffer);
41.775 +
41.776 + /*
41.777 + * write bytes to socket
41.778 + */
41.779 + io_status =
41.780 + g_io_channel_write_chars(gmyth_socket->sd_io_ch, command->str,
41.781 + command->len, &bytes_written, &error);
41.782 +
41.783 +
41.784 + if ((io_status == G_IO_STATUS_ERROR) || (bytes_written <= 0)) {
41.785 + gmyth_debug("[%s] Error while writing to socket", __FUNCTION__);
41.786 + ret = FALSE;
41.787 + } else if (bytes_written < command->len) {
41.788 + gmyth_debug("[%s] Not all data was written socket", __FUNCTION__);
41.789 + ret = FALSE;
41.790 + }
41.791 +
41.792 + io_status = g_io_channel_flush(gmyth_socket->sd_io_ch, &error);
41.793 +
41.794 + if ((bytes_written != command->len)
41.795 + || (io_status == G_IO_STATUS_ERROR)) {
41.796 + gmyth_debug
41.797 + ("[%s] Some problem occurred when sending data to the socket\n",
41.798 + __FUNCTION__);
41.799 +
41.800 + ret = TRUE;
41.801 + }
41.802 +
41.803 + g_mutex_unlock(gmyth_socket->mutex);
41.804 + done:
41.805 + if (error != NULL) {
41.806 + gmyth_debug
41.807 + ("[%s] Error found reading data from IO channel: (%d, %s)\n",
41.808 + __FUNCTION__, error->code, error->message);
41.809 + ret = FALSE;
41.810 + g_error_free(error);
41.811 + }
41.812 +
41.813 + if (buffer != NULL)
41.814 + g_free(buffer);
41.815 +
41.816 + return ret;
41.817 +}
41.818 +
41.819 +/** Starts Mythtv protocol level connection. Checks Mythtv protocol version
41.820 + * supported by the backend and send the "ANN" command.
41.821 + *
41.822 + * @param gmyth_socket the GMythSocket instance.
41.823 + * @param hostname_backend The backend hostname or IP address.
41.824 + * @param port The backend port to connect.
41.825 + * @param blocking_client A flag to choose between blocking and non-blocking
41.826 + * @param with_events Sets the connection flag to receive events.
41.827 + * backend connection.
41.828 + */
41.829 +static gboolean
41.830 +gmyth_socket_connect_to_backend_and_events(GMythSocket * gmyth_socket,
41.831 + const gchar * hostname_backend,
41.832 + gint port,
41.833 + gboolean blocking_client,
41.834 + gboolean with_events)
41.835 +{
41.836 + if (!gmyth_socket_connect(gmyth_socket, hostname_backend, port)) {
41.837 + gmyth_debug("[%s] Could not open socket to backend machine [%s]\n",
41.838 + __FUNCTION__, hostname_backend);
41.839 + return FALSE;
41.840 + }
41.841 +
41.842 + if (gmyth_socket_check_protocol_version(gmyth_socket)) {
41.843 + GString *result;
41.844 + GString *base_str = g_string_new("");
41.845 + GString *hostname = NULL;
41.846 +
41.847 + hostname = gmyth_socket_get_local_hostname();
41.848 + if (hostname == NULL) {
41.849 + gmyth_debug
41.850 + ("Hostname not available, setting to n800frontend\n");
41.851 + hostname = g_string_new("n800frontend");
41.852 + }
41.853 +
41.854 + g_string_printf(base_str, "ANN %s %s %u",
41.855 + (blocking_client ? "Playback" : "Monitor"),
41.856 + hostname->str, with_events);
41.857 +
41.858 + gmyth_socket_send_command(gmyth_socket, base_str);
41.859 + result = gmyth_socket_receive_response(gmyth_socket);
41.860 +
41.861 + if (result != NULL) {
41.862 + gmyth_debug("Response received from backend: %s", result->str);
41.863 + g_string_free(result, TRUE);
41.864 + }
41.865 +
41.866 + g_string_free(hostname, TRUE);
41.867 + g_string_free(base_str, TRUE);
41.868 +
41.869 + return TRUE;
41.870 + } else {
41.871 + gmyth_debug("[%s] GMythSocket could not connect to the backend",
41.872 + __FUNCTION__);
41.873 + return FALSE;
41.874 + }
41.875 +}
41.876 +
41.877 +/** Starts Mythtv protocol level connection. Checks Mythtv protocol version
41.878 + * supported by the backend and send the "ANN" command.
41.879 + *
41.880 + * @param gmyth_socket the GMythSocket instance.
41.881 + * @param hostname_backend The backend hostname or IP address.
41.882 + * @param port The backend port to connect.
41.883 + * @param blocking_client A flag to choose between blocking and non-blocking
41.884 + */
41.885 +gboolean
41.886 +gmyth_socket_connect_to_backend(GMythSocket * gmyth_socket,
41.887 + const gchar * hostname_backend, gint port,
41.888 + gboolean blocking_client)
41.889 +{
41.890 + if (!gmyth_socket_connect_to_backend_and_events
41.891 + (gmyth_socket, hostname_backend, port, blocking_client, FALSE)) {
41.892 + gmyth_debug("Could not open socket to backend machine [%s]\n",
41.893 + hostname_backend);
41.894 + return FALSE;
41.895 + }
41.896 +
41.897 + return TRUE;
41.898 +
41.899 +}
41.900 +
41.901 +/** Starts Mythtv protocol level connection. Checks Mythtv protocol version
41.902 + * supported by the backend and send the "ANN" command.
41.903 + *
41.904 + * @param gmyth_socket the GMythSocket instance.
41.905 + * @param hostname_backend The backend hostname or IP address.
41.906 + * @param port The backend port to connect.
41.907 + * @param blocking_client A flag to choose between blocking and non-blocking
41.908 + */
41.909 +gboolean
41.910 +gmyth_socket_connect_to_backend_events(GMythSocket * gmyth_socket,
41.911 + const gchar * hostname_backend,
41.912 + gint port, gboolean blocking_client)
41.913 +{
41.914 + if (!gmyth_socket_connect_to_backend_and_events
41.915 + (gmyth_socket, hostname_backend, port, blocking_client, TRUE)) {
41.916 + gmyth_debug
41.917 + ("Could not open socket to backend machine in order to receive events [%s]\n",
41.918 + hostname_backend);
41.919 + return FALSE;
41.920 + }
41.921 +
41.922 + return TRUE;
41.923 +}
41.924 +
41.925 +/** Closes the socket connection to the backend.
41.926 + *
41.927 + * @param gmyth_socket The GMythSocket instance.
41.928 + */
41.929 +void
41.930 +gmyth_socket_close_connection(GMythSocket * gmyth_socket)
41.931 +{
41.932 + /*
41.933 + * if ( gmyth_socket->sd != -1 ) { close (gmyth_socket->sd);
41.934 + * gmyth_socket->sd = -1; }
41.935 + */
41.936 +
41.937 + if (gmyth_socket->sd_io_ch != NULL) {
41.938 + g_io_channel_shutdown(gmyth_socket->sd_io_ch, TRUE, NULL);
41.939 + g_io_channel_unref(gmyth_socket->sd_io_ch);
41.940 + gmyth_socket->sd_io_ch = NULL;
41.941 + gmyth_socket->sd = -1;
41.942 + }
41.943 +
41.944 +}
41.945 +
41.946 +
41.947 +/** Try the MythTV version numbers, and get the version returned by
41.948 + * the possible REJECT message, in order to contruct a new
41.949 + * MythTV version request.
41.950 + *
41.951 + * @param gmyth_socket The GMythSocket instance.
41.952 + * @param mythtv_version The Mythtv protocol version to be tested
41.953 + *
41.954 + * @return The actual MythTV the client is connected to.
41.955 + */
41.956 +gint
41.957 +gmyth_socket_check_protocol_version_number(GMythSocket * gmyth_socket,
41.958 + gint mythtv_version)
41.959 +{
41.960 + GString *response = NULL;
41.961 + GString *payload = NULL;
41.962 + gboolean res = TRUE;
41.963 + gint mythtv_new_version = MYTHTV_CANNOT_NEGOTIATE_VERSION;
41.964 + guint max_iterations = MYTHTV_MAX_VERSION_CHECKS;
41.965 +
41.966 + assert(gmyth_socket);
41.967 +
41.968 + try_new_version:
41.969 + payload = g_string_new("MYTH_PROTO_VERSION");
41.970 + g_string_append_printf(payload, " %d", mythtv_version);
41.971 +
41.972 + gmyth_socket_send_command(gmyth_socket, payload);
41.973 + response = gmyth_socket_receive_response(gmyth_socket);
41.974 +
41.975 + if (response == NULL) {
41.976 + gmyth_debug("[%s] Check protocol version error! Not answered!",
41.977 + __FUNCTION__);
41.978 + res = FALSE;
41.979 + goto done;
41.980 + }
41.981 +
41.982 + res = g_str_has_prefix(response->str, "ACCEPT");
41.983 + if (!res) {
41.984 + gmyth_debug("[%s] Protocol version request error: %s",
41.985 + __FUNCTION__, response->str);
41.986 + /*
41.987 + * get the version number returned by the REJECT message
41.988 + */
41.989 + if ((res = g_str_has_prefix(response->str, "REJECT")) == TRUE) {
41.990 + gchar *new_version = NULL;
41.991 +
41.992 + new_version = g_strrstr(response->str, "]");
41.993 + if (new_version != NULL) {
41.994 + ++new_version; /* skip ']' character */
41.995 + if (new_version != NULL) {
41.996 + gmyth_debug("[%s] got MythTV version = %s.\n",
41.997 + __FUNCTION__, new_version);
41.998 + mythtv_version =
41.999 + (gint) g_ascii_strtoull(new_version, NULL, 10);
41.1000 + /*
41.1001 + * do reconnection to the socket (socket is closed if
41.1002 + * the MythTV version was wrong)
41.1003 + */
41.1004 + gmyth_socket_connect(gmyth_socket,
41.1005 + gmyth_socket->hostname,
41.1006 + gmyth_socket->port);
41.1007 + new_version = NULL;
41.1008 + if (--max_iterations > 0) {
41.1009 + g_string_free(payload, TRUE);
41.1010 + g_string_free(response, TRUE);
41.1011 + goto try_new_version;
41.1012 + } else
41.1013 + goto done;
41.1014 + }
41.1015 + }
41.1016 + }
41.1017 + }
41.1018 +
41.1019 + /*
41.1020 + * change the return value to a valid one
41.1021 + */
41.1022 + if (res) {
41.1023 + mythtv_new_version = mythtv_version;
41.1024 + gmyth_socket->mythtv_version = mythtv_new_version;
41.1025 + }
41.1026 +
41.1027 + done:
41.1028 + g_string_free(payload, TRUE);
41.1029 + g_string_free(response, TRUE);
41.1030 +
41.1031 + return mythtv_new_version;
41.1032 +}
41.1033 +
41.1034 +/** Verifies if the Mythtv backend supported the GMyth supported version.
41.1035 + *
41.1036 + * @param gmyth_socket The GMythSocket instance.
41.1037 + * @return TRUE if supports, FALSE if not.
41.1038 + */
41.1039 +gboolean
41.1040 +gmyth_socket_check_protocol_version(GMythSocket * gmyth_socket)
41.1041 +{
41.1042 + return ((gmyth_socket->mythtv_version =
41.1043 + gmyth_socket_check_protocol_version_number(gmyth_socket,
41.1044 + MYTHTV_VERSION_DEFAULT))
41.1045 + != MYTHTV_CANNOT_NEGOTIATE_VERSION);
41.1046 +}
41.1047 +
41.1048 +/** Returns the Mythtv backend supported version.
41.1049 + *
41.1050 + * @param gmyth_socket The GMythSocket instance.
41.1051 + * @return The actual MythTV version number.
41.1052 + */
41.1053 +gint
41.1054 +gmyth_socket_get_protocol_version(GMythSocket * gmyth_socket)
41.1055 +{
41.1056 + return gmyth_socket->mythtv_version;
41.1057 +}
41.1058 +
41.1059 +/** Receives a backend answer after a gmyth_socket_send_command_call ().
41.1060 + *
41.1061 + * @param gmyth_socket The GMythSocket instance.
41.1062 + * @return The response received, or NULL if error or nothing was received.
41.1063 + */
41.1064 +GString *
41.1065 +gmyth_socket_receive_response(GMythSocket * gmyth_socket)
41.1066 +{
41.1067 + GIOStatus io_status = G_IO_STATUS_NORMAL;
41.1068 + GError *error = NULL;
41.1069 + gchar *buffer = NULL;
41.1070 +
41.1071 + GString *str = NULL;
41.1072 +
41.1073 + gsize bytes_read = 0;
41.1074 + gint len = 0;
41.1075 +
41.1076 + if (gmyth_socket == NULL)
41.1077 + return NULL;
41.1078 +
41.1079 + GIOCondition io_cond;
41.1080 +
41.1081 + /*
41.1082 + * verify if the input (read) buffer is ready to receive data
41.1083 + */
41.1084 + g_mutex_lock(gmyth_socket->mutex);
41.1085 +
41.1086 + buffer = g_strnfill(MYTH_PROTOCOL_FIELD_SIZE, ' ');
41.1087 + if (NULL == gmyth_socket->sd_io_ch) {
41.1088 + gmyth_socket_connect(gmyth_socket, gmyth_socket->hostname,
41.1089 + gmyth_socket->port);
41.1090 + }
41.1091 +
41.1092 + io_cond = g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch);
41.1093 + /*
41.1094 + * if ( NULL == gmyth_socket->sd_io_ch->read_buf || ( NULL ==
41.1095 + * gmyth_socket->sd_io_ch->read_buf->str ) ) gmyth_socket->sd_io_ch =
41.1096 + * g_io_channel_unix_new( gmyth_socket->sd );
41.1097 + */
41.1098 +
41.1099 + if (gmyth_socket->sd_io_ch->is_readable /* && !( ( io_cond & G_IO_IN )
41.1100 + * == 0 ) */ )
41.1101 + io_status =
41.1102 + g_io_channel_read_chars(gmyth_socket->sd_io_ch, buffer,
41.1103 + MYTH_PROTOCOL_FIELD_SIZE, &bytes_read,
41.1104 + &error);
41.1105 + else
41.1106 + return g_string_new("");
41.1107 +
41.1108 + /*
41.1109 + * verify if the input (read) buffer is ready to receive data
41.1110 + */
41.1111 + io_cond = g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch);
41.1112 +
41.1113 + // if ( ( io_cond & G_IO_IN ) == 0 )
41.1114 + // return NULL;
41.1115 +
41.1116 + gmyth_debug("[%s] Bytes read = %d\n", __FUNCTION__, bytes_read);
41.1117 +
41.1118 + if ((io_status == G_IO_STATUS_ERROR) || (bytes_read <= 0)) {
41.1119 + gmyth_debug("[%s] Error in mythprotocol response from backend\n",
41.1120 + __FUNCTION__);
41.1121 + str = NULL;
41.1122 + // return NULL;
41.1123 + } else if (buffer != NULL && strlen(buffer) > 0) {
41.1124 +
41.1125 + // io_status = g_io_channel_flush( gmyth_socket->sd_io_ch, &error
41.1126 + // );
41.1127 + /*
41.1128 + * verify if the input (read) buffer is ready to receive data
41.1129 + */
41.1130 + // io_cond = g_io_channel_get_buffer_condition(
41.1131 + // gmyth_socket->sd_io_ch );
41.1132 +
41.1133 + // if ( ( io_cond & G_IO_IN ) != 0 ) {
41.1134 + // gchar *buffer_aux = NULL;
41.1135 +
41.1136 + /*
41.1137 + * removes trailing whitespace
41.1138 + */
41.1139 + // buffer_aux = g_strstrip (buffer);
41.1140 + len = (gint) g_ascii_strtoull(g_strstrip(buffer), NULL, 10);
41.1141 +
41.1142 + g_free(buffer);
41.1143 +
41.1144 + /*
41.1145 + * if (buffer_aux != NULL) { g_free (buffer_aux); buffer_aux =
41.1146 + * NULL; }
41.1147 + */
41.1148 +
41.1149 + buffer = g_new0(gchar, len + 1);
41.1150 +
41.1151 + bytes_read = 0;
41.1152 + if (!(gmyth_socket != NULL && gmyth_socket->sd_io_ch != NULL))
41.1153 + return NULL;
41.1154 +
41.1155 + if (gmyth_socket->sd_io_ch->is_readable)
41.1156 + io_status =
41.1157 + g_io_channel_read_chars(gmyth_socket->sd_io_ch, buffer,
41.1158 + len, &bytes_read, &error);
41.1159 + else
41.1160 + return g_string_new("");
41.1161 +
41.1162 + buffer[bytes_read] = '\0';
41.1163 + // }
41.1164 + }
41.1165 +
41.1166 + g_mutex_unlock(gmyth_socket->mutex);
41.1167 + // g_static_rw_lock_reader_unlock (&rwlock);
41.1168 +
41.1169 + gmyth_debug("Response received from backend: ----- {%s}\n", buffer);
41.1170 + if ((bytes_read != len) || (io_status == G_IO_STATUS_ERROR))
41.1171 + str = NULL;
41.1172 + else
41.1173 + str = g_string_new(buffer);
41.1174 +
41.1175 + if (error != NULL) {
41.1176 + gmyth_debug
41.1177 + ("[%s] Error found receiving response from the IO channel: (%d, %s)\n",
41.1178 + __FUNCTION__, error->code, error->message);
41.1179 + str = NULL;
41.1180 + g_error_free(error);
41.1181 + }
41.1182 +
41.1183 + g_free(buffer);
41.1184 + return str;
41.1185 +}
41.1186 +
41.1187 +/** Format a Mythtv command from the str_list entries and send it to backend.
41.1188 + *
41.1189 + * @param gmyth_socket The GMythSocket instance.
41.1190 + * @param str_list The string list to form the command
41.1191 + * @return TRUE if command was sent, FALSE if any error happens.
41.1192 + */
41.1193 +gboolean
41.1194 +gmyth_socket_write_stringlist(GMythSocket * gmyth_socket,
41.1195 + GMythStringList * str_list)
41.1196 +{
41.1197 +
41.1198 + GList *tmp_list = NULL;
41.1199 + GPtrArray *ptr_array = NULL;
41.1200 + gchar *str_array = NULL;
41.1201 +
41.1202 + g_mutex_lock(gmyth_socket->mutex);
41.1203 + // g_static_rw_lock_writer_lock (&rwlock);
41.1204 +
41.1205 + ptr_array = g_ptr_array_sized_new(g_list_length(str_list->glist));
41.1206 +
41.1207 + // FIXME: change this implementation!
41.1208 + tmp_list = str_list->glist;
41.1209 + for (; tmp_list; tmp_list = tmp_list->next) {
41.1210 + if (tmp_list->data != NULL) {
41.1211 + g_ptr_array_add(ptr_array, ((GString *) tmp_list->data)->str);
41.1212 + } else {
41.1213 + g_ptr_array_add(ptr_array, "");
41.1214 + }
41.1215 + }
41.1216 + g_ptr_array_add(ptr_array, NULL); // g_str_joinv() needs a NULL
41.1217 + // terminated string
41.1218 +
41.1219 + str_array = g_strjoinv(MYTH_SEPARATOR, (gchar **) (ptr_array->pdata));
41.1220 +
41.1221 + g_mutex_unlock(gmyth_socket->mutex);
41.1222 + // g_static_rw_lock_writer_unlock (&rwlock);
41.1223 +
41.1224 + gmyth_debug("[%s] Sending socket request: %s\n", __FUNCTION__,
41.1225 + str_array);
41.1226 +
41.1227 + // Sends message to backend
41.1228 + // TODO: implement looping to send remaining data, and add timeout
41.1229 + // testing!
41.1230 + GString *command = g_string_new(str_array);
41.1231 +
41.1232 + gmyth_socket_send_command(gmyth_socket, command);
41.1233 +
41.1234 + g_string_free(command, TRUE);
41.1235 +
41.1236 + g_free(str_array);
41.1237 +
41.1238 + /*
41.1239 + * ptr_array is pointing to data inside str_list->glist
41.1240 + */
41.1241 + g_ptr_array_free(ptr_array, TRUE);
41.1242 +
41.1243 + return TRUE;
41.1244 +}
41.1245 +
41.1246 +/*
41.1247 + * Receives a backend command response and split it into the given string
41.1248 + * list. @param gmyth_socket The GMythSocket instance. @param str_list
41.1249 + * the string list to be filled. @return The number of received strings.
41.1250 + */
41.1251 +gint
41.1252 +gmyth_socket_read_stringlist(GMythSocket * gmyth_socket,
41.1253 + GMythStringList * str_list)
41.1254 +{
41.1255 + GString *response;
41.1256 + gint i;
41.1257 +
41.1258 + gmyth_string_list_clear_all(str_list);
41.1259 +
41.1260 + response = gmyth_socket_receive_response(gmyth_socket);
41.1261 + if (response != NULL && response->str != NULL && response->len > 0) {
41.1262 + gchar **str_array;
41.1263 +
41.1264 + g_mutex_lock(gmyth_socket->mutex);
41.1265 +
41.1266 + str_array = g_strsplit(response->str, MYTH_SEPARATOR, -1);
41.1267 +
41.1268 + for (i = 0; i < g_strv_length(str_array); i++) {
41.1269 + // if ( str_array[i] != NULL && strlen( str_array[i] ) > 0 )
41.1270 + gmyth_string_list_append_char_array(str_list, str_array[i]);
41.1271 + }
41.1272 +
41.1273 + g_mutex_unlock(gmyth_socket->mutex);
41.1274 + g_strfreev(str_array);
41.1275 + }
41.1276 +
41.1277 + g_string_free(response, TRUE);
41.1278 +
41.1279 + return gmyth_string_list_length(str_list);
41.1280 +}
41.1281 +
41.1282 +/** Formats a Mythtv protocol command based on str_list and sends it to
41.1283 + * the connected backend. The backend response is overwritten into str_list.
41.1284 + *
41.1285 + * @param gmyth_socket The GMythSocket instance.
41.1286 + * @param str_list The string list to be sent, and on which the answer
41.1287 + * will be written.
41.1288 + * @return TRUE if command was sent and an answer was received, FALSE if any
41.1289 + * error happens.
41.1290 + */
41.1291 +gint
41.1292 +gmyth_socket_sendreceive_stringlist(GMythSocket * gmyth_socket,
41.1293 + GMythStringList * str_list)
41.1294 +{
41.1295 + gmyth_socket_write_stringlist(gmyth_socket, str_list);
41.1296 +
41.1297 + return gmyth_socket_read_stringlist(gmyth_socket, str_list);
41.1298 +}
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42.2 +++ b/gmyth/gmyth/gmyth_socket.h Mon Feb 25 17:51:43 2008 +0000
42.3 @@ -0,0 +1,147 @@
42.4 +/**
42.5 + * GMyth Library
42.6 + *
42.7 + * @file gmyth/gmyth_socket.h
42.8 + *
42.9 + * @brief <p> MythTV socket implementation, according to the MythTV Project
42.10 + * (www.mythtv.org).
42.11 + *
42.12 + * This component provides basic socket functionalities to interact with
42.13 + * the Mythtv backend.
42.14 + * <p>
42.15 + *
42.16 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
42.17 + * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
42.18 + *
42.19 + *
42.20 + * This program is free software; you can redistribute it and/or modify
42.21 + * it under the terms of the GNU Lesser General Public License as published by
42.22 + * the Free Software Foundation; either version 2 of the License, or
42.23 + * (at your option) any later version.
42.24 + *
42.25 + * This program is distributed in the hope that it will be useful,
42.26 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
42.27 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42.28 + * GNU General Public License for more details.
42.29 + *
42.30 + * You should have received a copy of the GNU Lesser General Public License
42.31 + * along with this program; if not, write to the Free Software
42.32 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
42.33 + */
42.34 +
42.35 +#ifndef __GMYTH_SOCKET_H__
42.36 +#define __GMYTH_SOCKET_H__
42.37 +
42.38 +#include <glib-object.h>
42.39 +
42.40 +#include <string.h>
42.41 +#include <netdb.h>
42.42 +#include <sys/socket.h>
42.43 +#include <unistd.h>
42.44 +#include <glib.h>
42.45 +
42.46 +#include "gmyth_stringlist.h"
42.47 +
42.48 +G_BEGIN_DECLS
42.49 +#define GMYTH_SOCKET_TYPE (gmyth_socket_get_type ())
42.50 +#define GMYTH_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SOCKET_TYPE, GMythSocket))
42.51 +#define GMYTH_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SOCKET_TYPE, GMythSocketClass))
42.52 +#define IS_GMYTH_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_SOCKET_TYPE))
42.53 +#define IS_GMYTH_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SOCKET_TYPE))
42.54 +#define GMYTH_SOCKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_SOCKET_TYPE, GMythSocketClass))
42.55 +typedef struct _GMythSocket GMythSocket;
42.56 +typedef struct _GMythSocketClass GMythSocketClass;
42.57 +
42.58 +struct _GMythSocketClass {
42.59 + GObjectClass parent_class;
42.60 +
42.61 + /*
42.62 + * callbacks
42.63 + */
42.64 + /*
42.65 + * no one for now
42.66 + */
42.67 +};
42.68 +
42.69 +struct _GMythSocket {
42.70 + GObject parent;
42.71 +
42.72 + GMutex *mutex;
42.73 +
42.74 + /*
42.75 + * socket descriptor
42.76 + */
42.77 + gint sd;
42.78 + GIOChannel *sd_io_ch;
42.79 +
42.80 + gchar *hostname;
42.81 + gint port;
42.82 + gint mythtv_version;
42.83 +};
42.84 +
42.85 +/*
42.86 + * used when no protocol version number was negotiated
42.87 + */
42.88 +#define MYTHTV_CANNOT_NEGOTIATE_VERSION 0
42.89 +
42.90 +GType gmyth_socket_get_type(void);
42.91 +
42.92 +GMythSocket *gmyth_socket_new();
42.93 +
42.94 +GIOChannel *gmyth_socket_get_io_channel(GMythSocket * gmyth_socket);
42.95 +
42.96 +gboolean gmyth_socket_is_able_to_read(GMythSocket * gmyth_socket);
42.97 +gboolean gmyth_socket_is_able_to_write(GMythSocket * gmyth_socket);
42.98 +
42.99 +gboolean gmyth_socket_send_command(GMythSocket * gmyth_socket,
42.100 + GString * command);
42.101 +GString *gmyth_socket_receive_response(GMythSocket * gmyth_socket);
42.102 +gint gmyth_socket_sendreceive_stringlist(GMythSocket *
42.103 + gmyth_socket,
42.104 + GMythStringList *
42.105 + str_list);
42.106 +
42.107 +gboolean gmyth_socket_connect(GMythSocket * gmyth_socket,
42.108 + const gchar * hostname, gint port);
42.109 +gboolean gmyth_socket_connect_with_timeout(GMythSocket *
42.110 + gmyth_socket,
42.111 + const gchar * hostname,
42.112 + gint port,
42.113 + guint timeout);
42.114 +
42.115 +gboolean gmyth_socket_connect_to_backend(GMythSocket * gmyth_socket,
42.116 + const gchar *
42.117 + hostname_backend,
42.118 + gint port,
42.119 + gboolean blocking_client);
42.120 +
42.121 +gboolean gmyth_socket_connect_to_backend_events(GMythSocket *
42.122 + gmyth_socket,
42.123 + const gchar *
42.124 + hostname_backend,
42.125 + gint port,
42.126 + gboolean
42.127 + blocking_client);
42.128 +
42.129 +gchar *gmyth_socket_get_primary_addr(void);
42.130 +
42.131 +GString *gmyth_socket_get_local_hostname(void);
42.132 +
42.133 +void gmyth_socket_close_connection(GMythSocket * gmyth_socket);
42.134 +
42.135 +gboolean gmyth_socket_check_protocol_version(GMythSocket *
42.136 + gmyth_socket);
42.137 +gint gmyth_socket_check_protocol_version_number(GMythSocket *
42.138 + gmyth_socket,
42.139 + gint
42.140 + mythtv_version);
42.141 +
42.142 +gint gmyth_socket_get_protocol_version(GMythSocket *
42.143 + gmyth_socket);
42.144 +
42.145 +gboolean gmyth_socket_write_stringlist(GMythSocket * gmyth_socket,
42.146 + GMythStringList * str_list);
42.147 +gint gmyth_socket_read_stringlist(GMythSocket * gmyth_socket,
42.148 + GMythStringList * str_list);
42.149 +G_END_DECLS
42.150 +#endif /* __GMYTH_SOCKET_H__ */
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
43.2 +++ b/gmyth/gmyth/gmyth_stringlist.c Mon Feb 25 17:51:43 2008 +0000
43.3 @@ -0,0 +1,454 @@
43.4 +/**
43.5 + * GMyth Library
43.6 + *
43.7 + * @file gmyth/gmyth_stringlist.c
43.8 + *
43.9 + * @brief <p> This component contains functions for dealing with the stringlist
43.10 + * format of the mythprotocol.
43.11 + *
43.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
43.13 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
43.14 + *
43.15 + *
43.16 + * This program is free software; you can redistribute it and/or modify
43.17 + * it under the terms of the GNU Lesser General Public License as published by
43.18 + * the Free Software Foundation; either version 2 of the License, or
43.19 + * (at your option) any later version.
43.20 + *
43.21 + * This program is distributed in the hope that it will be useful,
43.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
43.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43.24 + * GNU General Public License for more details.
43.25 + *
43.26 + * You should have received a copy of the GNU Lesser General Public License
43.27 + * along with this program; if not, write to the Free Software
43.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43.29 + */
43.30 +
43.31 +#ifdef HAVE_CONFIG_H
43.32 +#include "config.h"
43.33 +#endif
43.34 +
43.35 +#include "gmyth_stringlist.h"
43.36 +
43.37 +#include "gmyth_debug.h"
43.38 +
43.39 +static void gmyth_string_list_class_init(GMythStringListClass * klass);
43.40 +static void gmyth_string_list_init(GMythStringList * object);
43.41 +
43.42 +static void gmyth_string_list_dispose(GObject * object);
43.43 +static void gmyth_string_list_finalize(GObject * object);
43.44 +
43.45 +G_DEFINE_TYPE(GMythStringList, gmyth_string_list, G_TYPE_OBJECT)
43.46 + static void gmyth_string_list_class_init(GMythStringListClass *
43.47 + klass)
43.48 +{
43.49 + GObjectClass *gobject_class;
43.50 +
43.51 + gobject_class = (GObjectClass *) klass;
43.52 +
43.53 + gobject_class->dispose = gmyth_string_list_dispose;
43.54 + gobject_class->finalize = gmyth_string_list_finalize;
43.55 +}
43.56 +
43.57 +static void
43.58 +gmyth_string_list_init(GMythStringList * gmyth_string_list)
43.59 +{
43.60 + gmyth_string_list->glist = NULL;
43.61 +}
43.62 +
43.63 +static void
43.64 +gmyth_string_list_dispose(GObject * object)
43.65 +{
43.66 + GMythStringList *gmyth_string_list = GMYTH_STRING_LIST(object);
43.67 +
43.68 + gmyth_string_list_clear_all(gmyth_string_list);
43.69 +
43.70 + G_OBJECT_CLASS(gmyth_string_list_parent_class)->dispose(object);
43.71 +}
43.72 +
43.73 +static void
43.74 +gmyth_string_list_finalize(GObject * object)
43.75 +{
43.76 + // GMythStringList *gmyth_string_list = GMYTH_STRING_LIST(object);
43.77 +
43.78 + g_signal_handlers_destroy(object);
43.79 +
43.80 + G_OBJECT_CLASS(gmyth_string_list_parent_class)->finalize(object);
43.81 +}
43.82 +
43.83 +/** Creates a new instance of GStringList.
43.84 + *
43.85 + * @return a new instance of GStringList.
43.86 + */
43.87 +GMythStringList *
43.88 +gmyth_string_list_new()
43.89 +{
43.90 + GMythStringList *gmyth_string_list =
43.91 + GMYTH_STRING_LIST(g_object_new(GMYTH_STRING_LIST_TYPE, NULL));
43.92 +
43.93 + return gmyth_string_list;
43.94 +}
43.95 +
43.96 +/** Appends a guint64 to the string list.
43.97 + *
43.98 + * @param strlist The GMythStringList instance.
43.99 + * @param value The guint64 to be appended.
43.100 + *
43.101 + * @return The appended guint64 converted to a GString object.
43.102 + */
43.103 +GString *
43.104 +gmyth_string_list_append_int(GMythStringList * strlist, const gint value)
43.105 +{
43.106 + GString *value_str = g_string_new("");
43.107 +
43.108 + g_string_printf(value_str, "%d", value);
43.109 +
43.110 + strlist->glist = g_list_append(strlist->glist, value_str);
43.111 +
43.112 + return value_str;
43.113 +}
43.114 +
43.115 +
43.116 +/** Appends a gdouble to the string list.
43.117 + *
43.118 + * @param strlist The GMythStringList instance.
43.119 + * @param value The gdouble to be appended.
43.120 + *
43.121 + * @return The appended gdouble converted to a GString object.
43.122 + */
43.123 +GString *
43.124 +gmyth_string_list_append_float(GMythStringList * strlist, const gdouble value)
43.125 +{
43.126 + GString *value_str = g_string_new("");
43.127 + g_string_printf(value_str, "%f", value);
43.128 + strlist->glist = g_list_append(strlist->glist, value_str);
43.129 + return value_str;
43.130 +}
43.131 +
43.132 +
43.133 +/** Appends a guint64 to the string list.
43.134 + *
43.135 + * @param strlist The GMythStringList instance.
43.136 + * @param value The guint64 to be appended.
43.137 + *
43.138 + * @return The appended guint64 converted to a GString object.
43.139 + */
43.140 +GString *
43.141 +gmyth_string_list_append_uint64(GMythStringList * strlist,
43.142 + const guint64 value)
43.143 +{
43.144 + GString *tmp_str1 = g_string_new("");
43.145 + GString *tmp_str2 = g_string_new("");
43.146 +
43.147 + gmyth_debug("value = %llu.\n", value);
43.148 +
43.149 + gulong l2 = ((guint64) value & 0xffffffff);
43.150 + gulong l1 = ((guint64) value >> 32);
43.151 +
43.152 + /*
43.153 + * high order part of guint64 value
43.154 + */
43.155 + g_string_printf(tmp_str1, "%lu", l1);
43.156 +
43.157 + gmyth_debug("[%s] uint64 (high) = %s\n", __FUNCTION__, tmp_str1->str);
43.158 +
43.159 + strlist->glist = g_list_append(strlist->glist, tmp_str1);
43.160 +
43.161 + /*
43.162 + * low order part of guint64 value
43.163 + */
43.164 + g_string_printf(tmp_str2, "%lu", l2);
43.165 +
43.166 + gmyth_debug("[%s] uint64 (low) = %s\n", __FUNCTION__, tmp_str2->str);
43.167 +
43.168 + strlist->glist = g_list_append(strlist->glist, tmp_str2);
43.169 +
43.170 + return tmp_str2;
43.171 +}
43.172 +
43.173 +/** Appends a gint64 to the string list.
43.174 + *
43.175 + * @param strlist The GMythStringList instance.
43.176 + * @param value The gint64 to be appended.
43.177 + *
43.178 + * @return The appended gint64 converted to a GString object.
43.179 + */
43.180 +GString *
43.181 +gmyth_string_list_append_int64(GMythStringList * strlist,
43.182 + const gint64 value)
43.183 +{
43.184 + GString *tmp_str1 = g_string_new("");
43.185 + GString *tmp_str2 = g_string_new("");
43.186 +
43.187 + gmyth_debug("value = %lld.\n", value);
43.188 +
43.189 + glong l2 = ((gint64) value & 0xffffffff);
43.190 + glong l1 = ((gint64) value >> 32);
43.191 +
43.192 + /*
43.193 + * high order part of gint64 value
43.194 + */
43.195 + g_string_printf(tmp_str1, "%ld", l1);
43.196 +
43.197 + gmyth_debug("[%s] int64 (high) = %s\n", __FUNCTION__, tmp_str1->str);
43.198 +
43.199 + strlist->glist = g_list_append(strlist->glist, tmp_str1);
43.200 +
43.201 + /*
43.202 + * low order part of gint64 value
43.203 + */
43.204 + g_string_printf(tmp_str2, "%ld", l2);
43.205 +
43.206 + gmyth_debug("[%s] int64 (low) = %s\n", __FUNCTION__, tmp_str2->str);
43.207 +
43.208 + strlist->glist = g_list_append(strlist->glist, tmp_str2);
43.209 +
43.210 + return tmp_str2;
43.211 +}
43.212 +
43.213 +/** Appends a char array to the string list.
43.214 + *
43.215 + * @param strlist The GMythStringList instance.
43.216 + * @param value The char array to be appended.
43.217 + *
43.218 + * @return The appended char array converted to a GString object.
43.219 + */
43.220 +GString *
43.221 +gmyth_string_list_append_char_array(GMythStringList * strlist,
43.222 + const gchar * value)
43.223 +{
43.224 + GString *tmp_str = NULL;
43.225 +
43.226 + g_return_val_if_fail(strlist != NULL, NULL);
43.227 +
43.228 + tmp_str = g_string_new(value);
43.229 +
43.230 + strlist->glist = g_list_append(strlist->glist, tmp_str);
43.231 +
43.232 + return tmp_str;
43.233 +}
43.234 +
43.235 +/** Appends a string to the string list.
43.236 + *
43.237 + * @param strlist The GMythStringList instance.
43.238 + * @param value The string to be appended.
43.239 + *
43.240 + * @return The appended string itself.
43.241 + */
43.242 +GString *
43.243 +gmyth_string_list_append_string(GMythStringList * strlist, GString * value)
43.244 +{
43.245 + g_return_val_if_fail(strlist != NULL, NULL);
43.246 +
43.247 + if (value != NULL) {
43.248 + strlist->glist =
43.249 + g_list_append(strlist->glist, g_string_new(value->str));
43.250 + } else {
43.251 + strlist->glist = g_list_append(strlist->glist, NULL);
43.252 + }
43.253 +
43.254 + return value;
43.255 +}
43.256 +
43.257 +/** Gets an integer value from the string list at the given position.
43.258 + *
43.259 + * @param strlist The GMythStringList instance.
43.260 + * @param index the integer position in the list, starting with zero.
43.261 + * @return The integer value.
43.262 + */
43.263 +gint
43.264 +gmyth_string_list_get_int(GMythStringList * strlist, const gint index)
43.265 +{
43.266 + // TODO: Create static method check_index()
43.267 + GString *tmp_str = NULL;
43.268 +
43.269 + g_return_val_if_fail(strlist != NULL, 0);
43.270 +
43.271 + tmp_str = (GString *) g_list_nth_data(strlist->glist, index);
43.272 +
43.273 + if (NULL == tmp_str || NULL == tmp_str->str
43.274 + || strlen(tmp_str->str) <= 0)
43.275 + return 0;
43.276 +
43.277 + return (gint) ( /* 0x00000000ffffffffL & (gint64) */
43.278 + g_ascii_strtoull(tmp_str->str, NULL, 10));
43.279 +}
43.280 +
43.281 +/** Gets a guint64 value from the string list at the given position.
43.282 + * According to the Mythtv protocol, the 64 bits value is formed by
43.283 + * two strings.
43.284 + *
43.285 + * @param strlist The GMythStringList instance.
43.286 + * @param index the index of the first string forming the 64 bits value.
43.287 + * Index starts with zero.
43.288 + * @return The guint64 value.
43.289 + */
43.290 +guint64
43.291 +gmyth_string_list_get_uint64(GMythStringList * strlist, const gint index)
43.292 +{
43.293 + // TODO: Create static method check_index()
43.294 + guint64 ret_value = 0;
43.295 + guint64 l2 = 0;
43.296 +
43.297 + g_return_val_if_fail(strlist != NULL, 0);
43.298 +
43.299 + const GString *tmp_str1 =
43.300 + (GString *) g_list_nth_data(strlist->glist, index);
43.301 + const GString *tmp_str2 =
43.302 + (GString *) g_list_nth_data(strlist->glist, index + 1);
43.303 +
43.304 + if (tmp_str1 != NULL)
43.305 + gmyth_debug("[%s] seek high bytes = %s\n", __FUNCTION__,
43.306 + tmp_str1->str);
43.307 + if (tmp_str2 == NULL || strlen(tmp_str2->str) > 0) {
43.308 + } else {
43.309 + gmyth_debug("[%s] seek low bytes = %s\n", __FUNCTION__,
43.310 + tmp_str2->str);
43.311 + }
43.312 +
43.313 + guint64 l1 = ((guint64) g_ascii_strtoull(tmp_str1->str, NULL, 10) /* &
43.314 + * 0xffffffff
43.315 + */
43.316 + );
43.317 +
43.318 + if (tmp_str2 != NULL && tmp_str2->str != NULL
43.319 + && strlen(tmp_str2->str) > 0) {
43.320 + l2 = ((guint64) g_ascii_strtoull(tmp_str2->str, NULL, 10)
43.321 + /*
43.322 + * & 0xffffffff
43.323 + */
43.324 + );
43.325 + } else {
43.326 + l2 = l1;
43.327 + l1 = 0;
43.328 + }
43.329 +
43.330 + gmyth_debug("[%s]\t[l1 == %llu, l2 == %llu]\n", __FUNCTION__, l1, l2);
43.331 +
43.332 + ret_value =
43.333 + ((guint64) (l2) /* & 0xffffffff */ ) | ((guint64) l1 << 32);
43.334 +
43.335 + gmyth_debug("[%s] returning uint64 value = %llu\n", __FUNCTION__,
43.336 + ret_value);
43.337 +
43.338 + return ret_value;
43.339 +}
43.340 +
43.341 +/** Gets a gint64 value from the string list at the given position.
43.342 + * According to the Mythtv protocol, the 64 bits value is formed by
43.343 + * two strings.
43.344 + *
43.345 + * @param strlist The GMythStringList instance.
43.346 + * @param index the index of the first string forming the 64 bits value.
43.347 + * Index starts with zero.
43.348 + * @return The gint64 value.
43.349 + */
43.350 +gint64
43.351 +gmyth_string_list_get_int64(GMythStringList * strlist, const gint index)
43.352 +{
43.353 + // TODO: Create static method check_index()
43.354 + gint64 ret_value = 0;
43.355 + gint64 l2 = 0;
43.356 +
43.357 + g_return_val_if_fail(strlist != NULL, 0);
43.358 +
43.359 + const GString *tmp_str1 =
43.360 + (GString *) g_list_nth_data(strlist->glist, index);
43.361 + const GString *tmp_str2 =
43.362 + (GString *) g_list_nth_data(strlist->glist, index + 1);
43.363 +
43.364 + if (tmp_str1 != NULL)
43.365 + gmyth_debug("[%s] seek high bytes = %s\n", __FUNCTION__,
43.366 + tmp_str1->str);
43.367 + if (tmp_str2 == NULL || strlen(tmp_str2->str) > 0) {
43.368 + } else {
43.369 + gmyth_debug("[%s] seek low bytes = %s\n", __FUNCTION__,
43.370 + tmp_str2->str);
43.371 + }
43.372 +
43.373 + gint64 l1 = ((guint64) g_ascii_strtoull(tmp_str1->str, NULL, 10) /* &
43.374 + * 0xffffffff
43.375 + */
43.376 + );
43.377 +
43.378 + if (tmp_str2 != NULL && tmp_str2->str != NULL
43.379 + && strlen(tmp_str2->str) > 0) {
43.380 + l2 = ((gint64) g_ascii_strtoull(tmp_str2->str, NULL, 10)
43.381 + /*
43.382 + * & 0xffffffff
43.383 + */
43.384 + );
43.385 + } else {
43.386 + l2 = l1;
43.387 + l1 = 0;
43.388 + }
43.389 +
43.390 + gmyth_debug("[%s]\t[l1 == %lld, l2 == %lld]\n", __FUNCTION__, l1, l2);
43.391 +
43.392 + ret_value = ((gint64) (l2) /* & 0xffffffff */ ) | ((gint64) l1 << 32);
43.393 +
43.394 + gmyth_debug("[%s] returning int64 value = %lld\n", __FUNCTION__,
43.395 + ret_value);
43.396 +
43.397 + return ret_value;
43.398 +}
43.399 +
43.400 +
43.401 +/** Gets a string from the string list at the given position. The GString must be deallocated.
43.402 + *
43.403 + * @param strlist The GMythStringList instance.
43.404 + * @param index the string position in the list, starting with zero.
43.405 + * @return A pointer to the string data.
43.406 + */
43.407 +GString *
43.408 +gmyth_string_list_get_string(GMythStringList * strlist, const gint index)
43.409 +{
43.410 + GString *ret;
43.411 +
43.412 + if (!strlist || !(strlist->glist)) {
43.413 + gmyth_debug("%s received Null arguments", __FUNCTION__);
43.414 + return NULL;
43.415 + }
43.416 +
43.417 + ret = (GString *) g_list_nth_data(strlist->glist, index);
43.418 +
43.419 + return g_string_new(ret->str);
43.420 +}
43.421 +
43.422 +
43.423 +static void
43.424 +gmyth_string_list_clear_element(GString * str_elem, void *data_aux)
43.425 +{
43.426 + if (str_elem != NULL)
43.427 + g_string_free(str_elem, TRUE);
43.428 +}
43.429 +
43.430 +/** Removes all strings from the string list.
43.431 + *
43.432 + * @param strlist The GMythStringList instance.
43.433 + */
43.434 +void
43.435 +gmyth_string_list_clear_all(GMythStringList * strlist)
43.436 +{
43.437 + if (strlist != NULL && strlist->glist) {
43.438 + g_list_foreach(strlist->glist,
43.439 + (GFunc) gmyth_string_list_clear_element, NULL);
43.440 + g_list_free(strlist->glist);
43.441 + strlist->glist = NULL;
43.442 + }
43.443 +}
43.444 +
43.445 +/** Retrieves the number of elements in the string list.
43.446 + *
43.447 + * @param strlist The GMythStringList instance.
43.448 + * @return the string list length.
43.449 + */
43.450 +gint
43.451 +gmyth_string_list_length(GMythStringList * strlist)
43.452 +{
43.453 + if (!(strlist != NULL && strlist->glist != NULL))
43.454 + return 0;
43.455 +
43.456 + return g_list_length(strlist->glist);
43.457 +}
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
44.2 +++ b/gmyth/gmyth/gmyth_stringlist.h Mon Feb 25 17:51:43 2008 +0000
44.3 @@ -0,0 +1,108 @@
44.4 +/**
44.5 + * GMyth Library
44.6 + *
44.7 + * @file gmyth/gmyth_stringlist.h
44.8 + *
44.9 + * @brief <p> This component contains functions for dealing with the stringlist
44.10 + * format of the mythprotocol.
44.11 + *
44.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
44.13 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
44.14 + *
44.15 + *
44.16 + * This program is free software; you can redistribute it and/or modify
44.17 + * it under the terms of the GNU Lesser General Public License as published by
44.18 + * the Free Software Foundation; either version 2 of the License, or
44.19 + * (at your option) any later version.
44.20 + *
44.21 + * This program is distributed in the hope that it will be useful,
44.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
44.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44.24 + * GNU General Public License for more details.
44.25 + *
44.26 + * You should have received a copy of the GNU Lesser General Public License
44.27 + * along with this program; if not, write to the Free Software
44.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44.29 + */
44.30 +
44.31 +#ifndef GMYTH_STRING_LIST_H_
44.32 +#define GMYTH_STRING_LIST_H_
44.33 +
44.34 +#include <glib-object.h>
44.35 +
44.36 +#include <stdio.h>
44.37 +#include <stdlib.h>
44.38 +#include <string.h>
44.39 +#include <netdb.h>
44.40 +#include <sys/socket.h>
44.41 +#include <unistd.h>
44.42 +
44.43 +G_BEGIN_DECLS
44.44 +#define GMYTH_STRING_LIST_TYPE (gmyth_string_list_get_type ())
44.45 +#define GMYTH_STRING_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_STRING_LIST_TYPE, GMythStringList))
44.46 +#define GMYTH_STRING_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_STRING_LIST_TYPE, GMythStringListClass))
44.47 +#define IS_GMYTH_STRING_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_STRING_LIST_TYPE))
44.48 +#define IS_GMYTH_STRING_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_STRING_LIST_TYPE))
44.49 +#define GMYTH_STRING_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_STRING_LIST_TYPE, GMythStringListClass))
44.50 +typedef struct _GMythStringList GMythStringList;
44.51 +typedef struct _GMythStringListClass GMythStringListClass;
44.52 +
44.53 +struct _GMythStringListClass {
44.54 + GObjectClass parent_class;
44.55 +
44.56 + /*
44.57 + * callbacks
44.58 + */
44.59 + /*
44.60 + * no one for now
44.61 + */
44.62 +};
44.63 +
44.64 +struct _GMythStringList {
44.65 + GObject parent;
44.66 +
44.67 + /*
44.68 + * string list
44.69 + */
44.70 + GList *glist;
44.71 +};
44.72 +
44.73 +
44.74 +GType gmyth_string_list_get_type(void);
44.75 +
44.76 +GMythStringList *gmyth_string_list_new(void);
44.77 +
44.78 +void gmyth_string_list_clear_all(GMythStringList * strlist);
44.79 +int gmyth_string_list_length(GMythStringList * strlist);
44.80 +
44.81 +GString *gmyth_string_list_append_float(GMythStringList * strlist,
44.82 + const gdouble value);
44.83 +
44.84 +GString *gmyth_string_list_append_int(GMythStringList * strlist,
44.85 + const gint value);
44.86 +GString *gmyth_string_list_append_uint64(GMythStringList * strlist,
44.87 + const guint64 value);
44.88 +
44.89 +GString *gmyth_string_list_append_int64(GMythStringList * strlist,
44.90 + const gint64 value);
44.91 +
44.92 +GString *gmyth_string_list_append_char_array(GMythStringList *
44.93 + strlist,
44.94 + const char *value);
44.95 +GString *gmyth_string_list_append_string(GMythStringList * strlist,
44.96 + GString * value);
44.97 +
44.98 +int gmyth_string_list_get_int(GMythStringList * strlist,
44.99 + const gint index);
44.100 +guint64 gmyth_string_list_get_uint64(GMythStringList * strlist,
44.101 + const gint index);
44.102 +gint64 gmyth_string_list_get_int64(GMythStringList * strlist,
44.103 + const gint index);
44.104 +GString *gmyth_string_list_get_string(GMythStringList * strlist,
44.105 + const gint index);
44.106 +
44.107 +#define gmyth_string_list_get_char_array(strlist, index) \
44.108 + (gmyth_string_list_get_string(strlist, index))->str
44.109 +
44.110 +G_END_DECLS
44.111 +#endif /* GMYTH_STRING_LIST_H_ */
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
45.2 +++ b/gmyth/gmyth/gmyth_transcoder.c Mon Feb 25 17:51:43 2008 +0000
45.3 @@ -0,0 +1,272 @@
45.4 +/**
45.5 + * GMyth Library
45.6 + *
45.7 + * @file gmyth/gmyth_transcoder.c
45.8 + *
45.9 + * @brief <p> This file contains the transcoder class.
45.10 + *
45.11 + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
45.12 + * @author Artur Duque de Souza <artur.souza@indt.org.br>
45.13 + *
45.14 + *
45.15 + * This program is free software; you can redistribute it and/or modify
45.16 + * it under the terms of the GNU Lesser General Public License as published by
45.17 + * the Free Software Foundation; either version 2 of the License, or
45.18 + * (at your option) any later version.
45.19 + *
45.20 + * This program is distributed in the hope that it will be useful,
45.21 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
45.22 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45.23 + * GNU General Public License for more details.
45.24 + *
45.25 + * You should have received a copy of the GNU Lesser General Public License
45.26 + * along with this program; if not, write to the Free Software
45.27 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
45.28 + */
45.29 +
45.30 +
45.31 +#ifdef HAVE_CONFIG_H
45.32 +#include "config.h"
45.33 +#endif
45.34 +
45.35 +#include <stdlib.h>
45.36 +#include <string.h>
45.37 +#include <assert.h>
45.38 +
45.39 +#include "gmyth_util.h"
45.40 +#include "gmyth_debug.h"
45.41 +
45.42 +#include "gmyth_jobqueue.h"
45.43 +#include "gmyth_transcoder.h"
45.44 +
45.45 +static void gmyth_transcoder_class_init(GMythTranscoderClass * klass);
45.46 +static void gmyth_transcoder_init(GMythTranscoder * object);
45.47 +
45.48 +static void gmyth_transcoder_dispose(GObject * object);
45.49 +static void gmyth_transcoder_finalize(GObject * object);
45.50 +
45.51 +G_DEFINE_TYPE(GMythTranscoder, gmyth_transcoder, G_TYPE_OBJECT)
45.52 + static void gmyth_transcoder_class_init(GMythTranscoderClass *
45.53 + klass)
45.54 +{
45.55 + GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
45.56 +
45.57 + gobject_class->dispose = gmyth_transcoder_dispose;
45.58 + gobject_class->finalize = gmyth_transcoder_finalize;
45.59 +}
45.60 +
45.61 +static void
45.62 +gmyth_transcoder_init(GMythTranscoder * transcoder)
45.63 +{
45.64 + transcoder->started = FALSE;
45.65 +}
45.66 +
45.67 +static void
45.68 +gmyth_transcoder_dispose(GObject * object)
45.69 +{
45.70 + GMythTranscoder *transcoder = GMYTH_TRANSCODER(object);
45.71 +
45.72 + g_free(transcoder->output_filename);
45.73 + g_free(transcoder->filename);
45.74 + g_free(transcoder->profile);
45.75 + g_free(transcoder->starttime);
45.76 +
45.77 + if (transcoder->backend_info)
45.78 + g_object_unref(transcoder->backend_info);
45.79 +
45.80 + G_OBJECT_CLASS(gmyth_transcoder_parent_class)->dispose(object);
45.81 +}
45.82 +
45.83 +static void
45.84 +gmyth_transcoder_finalize(GObject * object)
45.85 +{
45.86 + g_signal_handlers_destroy(object);
45.87 + G_OBJECT_CLASS(gmyth_transcoder_parent_class)->finalize(object);
45.88 +}
45.89 +
45.90 +/**
45.91 + * Creates a new instance of GMythTranscoder.
45.92 + *
45.93 + * @return a new instance of GMythTranscoder.
45.94 + **/
45.95 +GMythTranscoder *
45.96 +gmyth_transcoder_new(GMythBackendInfo * backend_info)
45.97 +{
45.98 + GMythTranscoder *transcoder = GMYTH_TRANSCODER
45.99 + (g_object_new(GMYTH_TRANSCODER_TYPE, NULL));
45.100 +
45.101 + if (backend_info != NULL) {
45.102 + g_object_ref(backend_info);
45.103 + transcoder->backend_info = backend_info;
45.104 + }
45.105 +
45.106 + return transcoder;
45.107 +}
45.108 +
45.109 +/**
45.110 + *
45.111 + * gmyth_transcoder_date_change_format
45.112 + * @brief converts a string like YYYY-MM-DDTHH:MM:SS into YYYYMMDDHHMMSS (vice versa)
45.113 + * @param date_s gchar*
45.114 + * @return gchar* with file or iso format
45.115 + *
45.116 + **/
45.117 +static gchar *
45.118 +gmyth_transcoder_date_change_format(gchar * date_s, int format)
45.119 +{
45.120 + if (date_s != NULL) {
45.121 + gint length = strlen(date_s);
45.122 +
45.123 + // create the right date format
45.124 + gchar *src = (gchar *) g_malloc0(sizeof(gchar) * length);
45.125 +
45.126 + strncpy(src, date_s, length);
45.127 +
45.128 + gchar *dst;
45.129 +
45.130 + if (format == DATE_FILE) {
45.131 + dst = (gchar *) g_malloc0(sizeof(gchar) * 16);
45.132 + snprintf(dst, 16, "%.4s%.2s%.2s%.2s%.2s%.2s", src, src + 5,
45.133 + src + 7, src + 9, src + 11, src + 13);
45.134 + dst[15] = '\0';
45.135 + } else if (format == DATE_ISO) {
45.136 + dst = (gchar *) g_malloc0(sizeof(gchar) * 20);
45.137 + snprintf(dst, 20, "%.4s-%.2s-%.2sT%.2s:%.2s:%.2s", src,
45.138 + src + 4, src + 6, src + 8, src + 10, src + 12);
45.139 + dst[19] = '\0';
45.140 + }
45.141 +
45.142 + gchar *ret = g_strdup(dst);
45.143 +
45.144 + g_free(src);
45.145 + g_free(dst);
45.146 +
45.147 + return ret;
45.148 + } else
45.149 + return NULL;
45.150 +}
45.151 +
45.152 +/**
45.153 + * gmyth_transcoder_set_output
45.154 + * @brief set transcoder to use output
45.155 + * @param value gboolean
45.156 + * @param outfile filename of output
45.157 + * @return void set's up the var to value
45.158 + *
45.159 + **/
45.160 +void
45.161 +gmyth_transcoder_set_output(GMythTranscoder * transcoder,
45.162 + gboolean value, const gchar * outputfile)
45.163 +{
45.164 + transcoder->output = value;
45.165 + transcoder->output_filename = g_strdup(outputfile);
45.166 +}
45.167 +
45.168 +/**
45.169 + * gmyth_transcoder_set_file
45.170 + * @brief set the file to transcoder
45.171 + * @param file filename
45.172 + * @return void set's up the var to value
45.173 + *
45.174 + **/
45.175 +void
45.176 +gmyth_transcoder_set_filename(GMythTranscoder * transcoder,
45.177 + const gchar * file)
45.178 +{
45.179 + // fixme: if this method is called twice, memory will not be
45.180 + // dealocated
45.181 + // one transcoder can be used only for one file request?
45.182 + if (file != NULL) {
45.183 + gchar **splited = g_strsplit(file, "_", 2);
45.184 +
45.185 + // Get chanid
45.186 + sscanf(splited[0], "%d", &(transcoder->chanid));
45.187 +
45.188 + // Get starttime
45.189 + gchar **date = g_strsplit(splited[1], ".", 2);
45.190 +
45.191 + transcoder->starttime =
45.192 + gmyth_transcoder_date_change_format(date[0], DATE_ISO);
45.193 +
45.194 + transcoder->filename = g_strdup(file);
45.195 + }
45.196 +}
45.197 +
45.198 +
45.199 +/**
45.200 + *
45.201 + * gmyth_transcoder_set_profile
45.202 + * @brief set transcoder's profile
45.203 + * @param rec GMythTranscoder*
45.204 + * @param value the value
45.205 + * @return gint representing the result
45.206 + *
45.207 + **/
45.208 +gint
45.209 +gmyth_transcoder_set_profile(GMythTranscoder * trans, const gchar * value)
45.210 +{
45.211 + g_return_val_if_fail(value != NULL, -1);
45.212 +
45.213 + trans->profile = g_strndup(value, strlen(value));
45.214 +
45.215 + return 0;
45.216 +}
45.217 +
45.218 +gboolean
45.219 +gmyth_transcoder_start(GMythTranscoder * trans)
45.220 +{
45.221 + g_return_val_if_fail(trans != NULL, FALSE);
45.222 + g_return_val_if_fail(trans->backend_info != NULL, FALSE);
45.223 + g_return_val_if_fail(trans->filename != NULL, FALSE);
45.224 +
45.225 + if (trans->started == FALSE) { // not started yet
45.226 + if (!gmyth_util_file_exists(trans->backend_info, trans->filename)) {
45.227 + gmyth_debug("File %s does not exist", trans->filename);
45.228 + }
45.229 + trans->started = gmyth_jobqueue_add_job(trans, "JOB_TRANSCODE");
45.230 + if (trans->started == FALSE)
45.231 + gmyth_debug("Error while starting GMythTranscoder to file: %s",
45.232 + trans->output_filename);
45.233 + } else {
45.234 + gmyth_debug("GMythTransfer already started!");
45.235 + }
45.236 +
45.237 + return trans->started;
45.238 +}
45.239 +
45.240 +gboolean
45.241 +gmyth_transcoder_pause(GMythTranscoder * trans)
45.242 +{
45.243 + g_return_val_if_fail(trans != NULL, FALSE);
45.244 + g_return_val_if_fail(trans->started == TRUE, FALSE);
45.245 +
45.246 + return gmyth_jobqueue_change_cmd(trans, "PAUSE", "JOB_TRANSCODE");
45.247 +}
45.248 +
45.249 +gboolean
45.250 +gmyth_transcoder_resume(GMythTranscoder * trans)
45.251 +{
45.252 + g_return_val_if_fail(trans != NULL, FALSE);
45.253 +
45.254 + return gmyth_jobqueue_change_cmd(trans, "RESUME", "JOB_TRANSCODE");
45.255 +}
45.256 +
45.257 +gboolean
45.258 +gmyth_transcoder_cancel(GMythTranscoder * trans)
45.259 +{
45.260 + g_return_val_if_fail(trans != NULL, FALSE);
45.261 + g_return_val_if_fail(trans->started == TRUE, FALSE);
45.262 +
45.263 + trans->started = FALSE;
45.264 +
45.265 + return gmyth_jobqueue_change_cmd(trans, "STOP", "JOB_TRANSCODE");
45.266 +}
45.267 +
45.268 +// fixme: implement this method
45.269 +gint
45.270 +gmyth_transcoder_get_progress(GMythTranscoder * trans)
45.271 +{
45.272 + static int fixme = 0;
45.273 +
45.274 + return (fixme++) % 101;
45.275 +}
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
46.2 +++ b/gmyth/gmyth/gmyth_transcoder.h Mon Feb 25 17:51:43 2008 +0000
46.3 @@ -0,0 +1,104 @@
46.4 +/**
46.5 + * GMyth Library
46.6 + *
46.7 + * @file gmyth/gmyth_transcoder.h
46.8 + *
46.9 + * @brief <p> This file contains the transcoder class.
46.10 + *
46.11 + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
46.12 + * @author Artur Duque de Souza <artur.souza@indt.org.br>
46.13 + *
46.14 + * This program is free software; you can redistribute it and/or modify
46.15 + * it under the terms of the GNU Lesser General Public License as published by
46.16 + * the Free Software Foundation; either version 2 of the License, or
46.17 + * (at your option) any later version.
46.18 + *
46.19 + * This program is distributed in the hope that it will be useful,
46.20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
46.21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46.22 + * GNU General Public License for more details.
46.23 + *
46.24 + * You should have received a copy of the GNU Lesser General Public License
46.25 + * along with this program; if not, write to the Free Software
46.26 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
46.27 + */
46.28 +
46.29 +#ifndef _GMYTH_TRANSCODER_H
46.30 +#define _GMYTH_TRANSCODER_H
46.31 +
46.32 +#include <glib.h>
46.33 +#include <glib-object.h>
46.34 +
46.35 +#include "gmyth_stringlist.h"
46.36 +#include "gmyth_backendinfo.h"
46.37 +#include "gmyth_socket.h"
46.38 +#include "gmyth_http.h"
46.39 +#include "gmyth_recprofile.h"
46.40 +
46.41 +G_BEGIN_DECLS
46.42 +#define GMYTH_TRANSCODER_TYPE (gmyth_transcoder_get_type ())
46.43 +#define GMYTH_TRANSCODER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TRANSCODER_TYPE, GMythTranscoder))
46.44 +#define GMYTH_TRANSCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TRANSCODER_TYPE, GMythTranscoderClass))
46.45 +#define IS_GMYTH_TRANSCODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_TRANSCODER_TYPE))
46.46 +#define IS_GMYTH_TRANSCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TRANSCODER_TYPE))
46.47 +#define GMYTH_TRANSCODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_TRANSCODER_TYPE, GMythTranscoderClass))
46.48 +#define DATE_ISO 0
46.49 +#define DATE_FILE 1
46.50 +typedef struct _GMythTranscoder GMythTranscoder;
46.51 +typedef struct _GMythTranscoderClass GMythTranscoderClass;
46.52 +
46.53 +struct _GMythTranscoderClass {
46.54 + GObjectClass parent_class;
46.55 +
46.56 + /*
46.57 + * callbacks
46.58 + */
46.59 +};
46.60 +
46.61 +/**
46.62 + * The GMythTranscoder structure is a class to implement functions
46.63 + * related to transcoding.
46.64 + */
46.65 +struct _GMythTranscoder {
46.66 + GObject parent;
46.67 +
46.68 + gboolean cutlist;
46.69 + gboolean output;
46.70 + gboolean started;
46.71 +
46.72 + /*
46.73 + * private begin
46.74 + */
46.75 + gchar *output_filename;
46.76 + gchar *filename;
46.77 + gchar *profile;
46.78 + /*
46.79 + * private end
46.80 + */
46.81 +
46.82 + gchar *starttime;
46.83 +
46.84 + gint chanid;
46.85 +
46.86 + GMythBackendInfo *backend_info;
46.87 +};
46.88 +
46.89 +GType gmyth_transcoder_type(void);
46.90 +
46.91 +GMythTranscoder *gmyth_transcoder_new(GMythBackendInfo * backend_info);
46.92 +void gmyth_transcoder_set_output(GMythTranscoder * transcode,
46.93 + gboolean value,
46.94 + const gchar * outputfile);
46.95 +void gmyth_transcoder_set_filename(GMythTranscoder * transcode,
46.96 + const gchar * file);
46.97 +gint gmyth_transcoder_set_profile(GMythTranscoder * trans,
46.98 + const gchar * value);
46.99 +gboolean gmyth_transcoder_start(GMythTranscoder * trans);
46.100 +gboolean gmyth_transcoder_pause(GMythTranscoder * trans);
46.101 +gboolean gmyth_transcoder_resume(GMythTranscoder * trans);
46.102 +gboolean gmyth_transcoder_cancel(GMythTranscoder * trans);
46.103 +gint gmyth_transcoder_get_progress(GMythTranscoder * trans);
46.104 +
46.105 +
46.106 +G_END_DECLS
46.107 +#endif /*_GMYTH_TRANSCODER_H*/
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
47.2 +++ b/gmyth/gmyth/gmyth_tvchain.c Mon Feb 25 17:51:43 2008 +0000
47.3 @@ -0,0 +1,620 @@
47.4 +/**
47.5 + * GMyth Library
47.6 + *
47.7 + * @file gmyth/gmyth_tvchain.c
47.8 + *
47.9 + * @brief <p> This component contains functions for creating and accessing
47.10 + * the tvchain functions for live tv playback.
47.11 + *
47.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
47.13 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
47.14 + *
47.15 + *
47.16 + * This program is free software; you can redistribute it and/or modify
47.17 + * it under the terms of the GNU Lesser General Public License as published by
47.18 + * the Free Software Foundation; either version 2 of the License, or
47.19 + * (at your option) any later version.
47.20 + *
47.21 + * This program is distributed in the hope that it will be useful,
47.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
47.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47.24 + * GNU General Public License for more details.
47.25 + *
47.26 + * You should have received a copy of the GNU Lesser General Public License
47.27 + * along with this program; if not, write to the Free Software
47.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
47.29 + */
47.30 +
47.31 +#ifdef HAVE_CONFIG_H
47.32 +#include "config.h"
47.33 +#endif
47.34 +
47.35 +#include "gmyth_tvchain.h"
47.36 +
47.37 +#include <glib.h>
47.38 +#include <time.h>
47.39 +#include <stdio.h>
47.40 +#include <stdlib.h>
47.41 +#include <assert.h>
47.42 +
47.43 +#include "gmyth_epg.h"
47.44 +#include "gmyth_util.h"
47.45 +#include "gmyth_query.h"
47.46 +#include "gmyth_scheduler.h"
47.47 +#include "gmyth_debug.h"
47.48 +
47.49 +static void gmyth_tvchain_class_init(GMythTVChainClass * klass);
47.50 +static void gmyth_tvchain_init(GMythTVChain * object);
47.51 +
47.52 +static void gmyth_tvchain_dispose(GObject * object);
47.53 +static void gmyth_tvchain_finalize(GObject * object);
47.54 +
47.55 +static void free_tvchain_entry(gpointer data, gpointer user_data);
47.56 +
47.57 +G_DEFINE_TYPE(GMythTVChain, gmyth_tvchain, G_TYPE_OBJECT)
47.58 + static void gmyth_tvchain_class_init(GMythTVChainClass * klass)
47.59 +{
47.60 + GObjectClass *gobject_class;
47.61 +
47.62 + gobject_class = (GObjectClass *) klass;
47.63 +
47.64 + gobject_class->dispose = gmyth_tvchain_dispose;
47.65 + gobject_class->finalize = gmyth_tvchain_finalize;
47.66 +}
47.67 +
47.68 +static void
47.69 +gmyth_tvchain_init(GMythTVChain * tvchain)
47.70 +{
47.71 + tvchain->tvchain_id = NULL;
47.72 +
47.73 + tvchain->cur_chanid = g_string_new("");
47.74 + tvchain->cur_startts = NULL;
47.75 +
47.76 + tvchain->mutex = g_mutex_new();
47.77 +}
47.78 +
47.79 +GMythTVChain *
47.80 +gmyth_tvchain_new()
47.81 +{
47.82 + GMythTVChain *tvchain =
47.83 + GMYTH_TVCHAIN(g_object_new(GMYTH_TVCHAIN_TYPE, NULL));
47.84 +
47.85 + return tvchain;
47.86 +}
47.87 +
47.88 +static void
47.89 +gmyth_tvchain_dispose(GObject * object)
47.90 +{
47.91 + GMythTVChain *tvchain = GMYTH_TVCHAIN(object);
47.92 +
47.93 + if (tvchain->tvchain_id != NULL) {
47.94 + g_string_free(tvchain->tvchain_id, TRUE);
47.95 + tvchain->tvchain_id = NULL;
47.96 + }
47.97 +
47.98 + if (tvchain->mutex != NULL) {
47.99 + g_mutex_free(tvchain->mutex);
47.100 + tvchain->mutex = NULL;
47.101 + }
47.102 +
47.103 + if (tvchain->tvchain_list != NULL) {
47.104 + g_list_foreach(tvchain->tvchain_list, free_tvchain_entry, NULL);
47.105 + g_list_free(tvchain->tvchain_list);
47.106 + }
47.107 +
47.108 + if (tvchain->cur_chanid != NULL) {
47.109 + g_string_free(tvchain->cur_chanid, TRUE);
47.110 + tvchain->cur_chanid = NULL;
47.111 + }
47.112 +
47.113 + if (tvchain->backend_info) {
47.114 + g_object_unref(tvchain->backend_info);
47.115 + tvchain->backend_info = NULL;
47.116 + }
47.117 +
47.118 +
47.119 + G_OBJECT_CLASS(gmyth_tvchain_parent_class)->dispose(object);
47.120 +}
47.121 +
47.122 +static void
47.123 +gmyth_tvchain_finalize(GObject * object)
47.124 +{
47.125 + g_signal_handlers_destroy(object);
47.126 +
47.127 + G_OBJECT_CLASS(gmyth_tvchain_parent_class)->finalize(object);
47.128 +}
47.129 +
47.130 +/** Initializes the tvchain and generates the tvchain id.
47.131 + *
47.132 + * @param tvchain The GMythTVChain instance.
47.133 + * @param hostname The local hostname used to generate the tvchain id.
47.134 + */
47.135 +gboolean
47.136 +gmyth_tvchain_initialize(GMythTVChain * tvchain,
47.137 + GMythBackendInfo * backend_info)
47.138 +{
47.139 + const char *hostname;
47.140 +
47.141 + assert(tvchain);
47.142 + g_return_val_if_fail(backend_info != NULL, FALSE);
47.143 +
47.144 + g_object_ref(backend_info);
47.145 + tvchain->backend_info = backend_info;
47.146 +
47.147 + hostname = gmyth_backend_info_get_hostname(backend_info);
47.148 +
47.149 + if (tvchain->tvchain_id == NULL) {
47.150 + gchar *isodate = NULL;
47.151 + GTimeVal *cur_time = g_new0(GTimeVal, 1);
47.152 +
47.153 + // struct tm* gmyth_util_time_val_to_date ( const GTimeVal* time )
47.154 +
47.155 + g_get_current_time(cur_time);
47.156 + isodate =
47.157 + gmyth_util_time_to_isoformat_from_time_val_fmt
47.158 + ("%Y-%m-%dT%H:%M:%S", cur_time);
47.159 +
47.160 + tvchain->tvchain_id =
47.161 + g_string_sized_new(7 + strlen(hostname) + strlen(isodate));
47.162 + g_string_printf(tvchain->tvchain_id, "live-%s-%s", hostname,
47.163 + isodate);
47.164 +
47.165 + gmyth_debug("[%s] tv_chain_id: %s", __FUNCTION__,
47.166 + tvchain->tvchain_id->str);
47.167 +
47.168 + g_free(isodate);
47.169 + g_free(cur_time);
47.170 + } else {
47.171 + gmyth_debug("[%s] TVchain already initialized", __FUNCTION__);
47.172 + }
47.173 +
47.174 + return TRUE;
47.175 +}
47.176 +
47.177 +/** Gets the tvchain id.
47.178 + *
47.179 + * @param tvchain The GMythTVChain instance.
47.180 + * @return The tvchain id.
47.181 + */
47.182 +GString *
47.183 +gmyth_tvchain_get_id(GMythTVChain * tvchain)
47.184 +{
47.185 + g_return_val_if_fail(tvchain != NULL
47.186 + && tvchain->tvchain_id != NULL, NULL);
47.187 +
47.188 + return tvchain->tvchain_id;
47.189 +}
47.190 +
47.191 +/** Reloads all tvchain entries in the database.
47.192 + *
47.193 + * @param tvchain The GMythTVChain instance.
47.194 + * @return TRUE if success, or FALSE if error.
47.195 + */
47.196 +gboolean
47.197 +gmyth_tvchain_reload_all(GMythTVChain * tvchain)
47.198 +{
47.199 + MYSQL_ROW msql_row;
47.200 + MYSQL_RES *msql_res = NULL;
47.201 + GMythQuery *gmyth_query = NULL;
47.202 + gboolean ret = TRUE;
47.203 + GString *stmt_str = NULL;
47.204 +
47.205 + g_mutex_lock(tvchain->mutex);
47.206 +
47.207 + /*
47.208 + * gets the initial size of the TVChain entries list
47.209 + */
47.210 + guint prev_size = g_list_length(tvchain->tvchain_list);
47.211 +
47.212 + gmyth_debug("[%s] chainid: %s", __FUNCTION__,
47.213 + tvchain->tvchain_id->str);
47.214 +
47.215 + if (tvchain != NULL && tvchain->tvchain_list != NULL) {
47.216 + g_list_free(tvchain->tvchain_list);
47.217 + tvchain->tvchain_list = NULL;
47.218 + }
47.219 +
47.220 + /*
47.221 + * TODO: Reuse gmyth_query already connected from context
47.222 + */
47.223 + gmyth_query = gmyth_query_new();
47.224 + if (!gmyth_query_connect(gmyth_query, tvchain->backend_info)) {
47.225 + gmyth_debug("[%s] Could not connect to db", __FUNCTION__);
47.226 + g_mutex_unlock(tvchain->mutex);
47.227 + ret = FALSE;
47.228 + goto done;
47.229 + }
47.230 +
47.231 + stmt_str = g_string_new("");
47.232 + g_string_printf(stmt_str,
47.233 + "SELECT chanid, starttime, endtime, discontinuity, "
47.234 + "chainpos, hostprefix, cardtype, channame, input "
47.235 + "FROM tvchain "
47.236 + "WHERE chainid = \"%s\" ORDER BY chainpos;",
47.237 + tvchain->tvchain_id->str);
47.238 +
47.239 + msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str);
47.240 + if (msql_res != NULL) {
47.241 +
47.242 + while ((msql_row = mysql_fetch_row(msql_res)) != NULL) {
47.243 + struct LiveTVChainEntry *entry =
47.244 + g_new0(struct LiveTVChainEntry, 1);
47.245 + entry->chanid = g_string_new(msql_row[0]);
47.246 + entry->starttime =
47.247 + gmyth_util_string_to_time_val((const gchar *) msql_row[1]);
47.248 + entry->endtime =
47.249 + gmyth_util_string_to_time_val((const gchar *) msql_row[2]);
47.250 + entry->discontinuity =
47.251 + g_ascii_strtoull(msql_row[3], NULL, 10) != 0;
47.252 + entry->hostprefix = g_string_new(msql_row[5]);
47.253 + entry->cardtype = g_string_new(msql_row[6]);
47.254 + entry->channum = g_string_new(msql_row[7]);
47.255 + entry->inputname = g_string_new(msql_row[8]);
47.256 +
47.257 + // m_maxpos = query.value(4).toInt() + 1;
47.258 + gmyth_debug
47.259 + ("[%s] Reading TV chain entry (channel %s): [%s, %s, %s]\n",
47.260 + __FUNCTION__, entry->channum->str, entry->chanid->str,
47.261 + (gchar *) msql_row[1], (gchar *) msql_row[2]);
47.262 +
47.263 + /*
47.264 + * add this to get the actual start timestamp of the last
47.265 + * recording
47.266 + */
47.267 + if (tvchain->cur_startts < entry->starttime)
47.268 + tvchain->cur_startts = entry->starttime;
47.269 +
47.270 + tvchain->tvchain_list =
47.271 + g_list_append(tvchain->tvchain_list, entry);
47.272 + }
47.273 + } else {
47.274 + gmyth_debug("gmyth_tvchain_reload_all query error!\n");
47.275 + g_mutex_unlock(tvchain->mutex);
47.276 +
47.277 + ret = FALSE;
47.278 + goto done;
47.279 + }
47.280 +
47.281 + g_mutex_unlock(tvchain->mutex);
47.282 +
47.283 + tvchain->cur_pos =
47.284 + gmyth_tvchain_program_is_at(tvchain, tvchain->cur_chanid,
47.285 + tvchain->cur_startts);
47.286 + gmyth_debug("[%s] TVChain current position = %d.\n", __FUNCTION__,
47.287 + tvchain->cur_pos);
47.288 +
47.289 + if (tvchain->cur_pos < 0)
47.290 + tvchain->cur_pos = 0;
47.291 +
47.292 + // if (m_switchid >= 0)
47.293 + // m_switchid =
47.294 + // ProgramIsAt(m_switchentry.chanid,m_switchentry.starttime);
47.295 +
47.296 + if (prev_size != g_list_length(tvchain->tvchain_list)) {
47.297 + gmyth_debug("[%s] Added new recording", __FUNCTION__);
47.298 + }
47.299 +
47.300 + done:
47.301 + if (stmt_str != NULL)
47.302 + g_string_free(stmt_str, TRUE);
47.303 +
47.304 + if (msql_res != NULL)
47.305 + mysql_free_result(msql_res);
47.306 +
47.307 + if (gmyth_query != NULL)
47.308 + g_object_unref(gmyth_query);
47.309 +
47.310 + return ret;
47.311 +}
47.312 +
47.313 +/**
47.314 + * Get all the program info entries in the database.
47.315 + *
47.316 + * @param tvchain The GMythTVChain instance.
47.317 + *
47.318 + * @return A program info listage.
47.319 + */
47.320 +GList *
47.321 +gmyth_tvchain_get_program_info_list(GMythTVChain * tvchain)
47.322 +{
47.323 + GList *prog_list = NULL;
47.324 + MYSQL_ROW msql_row;
47.325 + MYSQL_RES *msql_res = NULL;
47.326 + GMythQuery *gmyth_query = NULL;
47.327 + GString *stmt_str = NULL;
47.328 +
47.329 + g_mutex_lock(tvchain->mutex);
47.330 +
47.331 + gmyth_query = gmyth_query_new();
47.332 + if (!gmyth_query_connect(gmyth_query, tvchain->backend_info)) {
47.333 + gmyth_debug("Could not connect to db.");
47.334 + goto done;
47.335 + }
47.336 +
47.337 + stmt_str = g_string_new("");
47.338 + g_string_printf(stmt_str,
47.339 + "SELECT channum, icon " "FROM channel "
47.340 + "ORDER BY channum;");
47.341 +
47.342 + msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str);
47.343 + if (msql_res != NULL) {
47.344 +
47.345 + while ((msql_row = mysql_fetch_row(msql_res)) != NULL) {
47.346 + GMythProgramInfo *entry = gmyth_program_info_new();
47.347 +
47.348 + entry->channame = g_string_new(msql_row[0]);
47.349 + entry->chansign = g_string_new(msql_row[1]);
47.350 +
47.351 + gmyth_debug
47.352 + ("Reading TV program info entry (channel %s): [%s - {%s, %s}]\n",
47.353 + entry->channame->str, entry->chansign->str,
47.354 + (gchar *) msql_row[0], (gchar *) msql_row[1]);
47.355 +
47.356 + prog_list = g_list_append(prog_list, entry);
47.357 + }
47.358 + } else {
47.359 + gmyth_debug
47.360 + ("Query error when trying to get the channel list from database!\n");
47.361 + goto done;
47.362 + }
47.363 +
47.364 + done:
47.365 + g_mutex_unlock(tvchain->mutex);
47.366 +
47.367 + if (stmt_str != NULL)
47.368 + g_string_free(stmt_str, TRUE);
47.369 +
47.370 + if (msql_res != NULL)
47.371 + mysql_free_result(msql_res);
47.372 +
47.373 + if (gmyth_query != NULL)
47.374 + g_object_unref(gmyth_query);
47.375 +
47.376 + return prog_list;
47.377 +}
47.378 +
47.379 +/**
47.380 + * Get all the program info entries in the database, given a channel name.
47.381 + *
47.382 + * @param tvchain The GMythTVChain instance.
47.383 + * @param channel The channel name.
47.384 + *
47.385 + * @return A program info listage, based on a given channel name.
47.386 + */
47.387 +GList *
47.388 +gmyth_tvchain_get_program_info_from_channel(GMythTVChain * tvchain,
47.389 + const gchar * channel)
47.390 +{
47.391 + GList *prog_list = NULL;
47.392 + MYSQL_ROW msql_row;
47.393 + MYSQL_RES *msql_res = NULL;
47.394 + GMythQuery *gmyth_query = NULL;
47.395 + GString *stmt_str = NULL;
47.396 +
47.397 + g_mutex_lock(tvchain->mutex);
47.398 +
47.399 + gmyth_query = gmyth_query_new();
47.400 + if (!gmyth_query_connect(gmyth_query, tvchain->backend_info)) {
47.401 + gmyth_debug("Could not connect to db.");
47.402 + goto done;
47.403 + }
47.404 +
47.405 + stmt_str = g_string_new("");
47.406 + g_string_printf(stmt_str,
47.407 + "SELECT channum, icon "
47.408 + "FROM channel "
47.409 + "WHERE channum = \"%s\" ORDER BY channum;", channel);
47.410 +
47.411 + msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str);
47.412 + if (msql_res != NULL) {
47.413 +
47.414 + while ((msql_row = mysql_fetch_row(msql_res)) != NULL) {
47.415 + GMythProgramInfo *entry = gmyth_program_info_new();
47.416 +
47.417 + entry->channame = g_string_new(msql_row[0]);
47.418 + entry->chansign = g_string_new(msql_row[1]);
47.419 +
47.420 + gmyth_debug
47.421 + ("Reading TV program info entry (channel %s): [%s - {%s, %s}]\n",
47.422 + entry->channame->str, entry->chansign->str,
47.423 + (gchar *) msql_row[0], (gchar *) msql_row[1]);
47.424 +
47.425 + prog_list = g_list_append(prog_list, entry);
47.426 + }
47.427 + } else {
47.428 + gmyth_debug
47.429 + ("Query error when trying to get the channel list from database!\n");
47.430 + goto done;
47.431 + }
47.432 +
47.433 + done:
47.434 + g_mutex_unlock(tvchain->mutex);
47.435 +
47.436 + if (stmt_str != NULL)
47.437 + g_string_free(stmt_str, TRUE);
47.438 +
47.439 + if (msql_res != NULL)
47.440 + mysql_free_result(msql_res);
47.441 +
47.442 + if (gmyth_query != NULL)
47.443 + g_object_unref(gmyth_query);
47.444 +
47.445 + return prog_list;
47.446 +}
47.447 +
47.448 +/**
47.449 + * Returns the internal index for the TV chain related to the given
47.450 + * channel and start time.
47.451 + *
47.452 + * @param tvchain The GMythTVChain instance.
47.453 + * @param chanid The channel id.
47.454 + * @param startts The program start time.
47.455 + *
47.456 + * @return The position of the related program info in the TV chain.
47.457 + */
47.458 +gint
47.459 +gmyth_tvchain_program_is_at(GMythTVChain * tvchain, GString * chanid,
47.460 + GTimeVal * startts)
47.461 +{
47.462 + gint count = 0;
47.463 + struct LiveTVChainEntry *entry;
47.464 + GList *tmp_list = tvchain->tvchain_list;
47.465 + guint list_size = g_list_length(tvchain->tvchain_list);
47.466 +
47.467 + g_mutex_lock(tvchain->mutex);
47.468 +
47.469 + for (; tmp_list && (count < list_size);
47.470 + tmp_list = tvchain->tvchain_list->next, count++) {
47.471 + entry = (struct LiveTVChainEntry *) tmp_list->data;
47.472 + if (!g_strncasecmp(entry->chanid->str, chanid->str, chanid->len)
47.473 + && entry->starttime == startts) {
47.474 + g_mutex_unlock(tvchain->mutex);
47.475 + return count;
47.476 + }
47.477 + }
47.478 + g_mutex_unlock(tvchain->mutex);
47.479 +
47.480 + return -1;
47.481 +}
47.482 +
47.483 +/** Get the program info associated to the tvchain.
47.484 + *
47.485 + * @param tvchain The GMythTVChain instance.
47.486 + * @param index The tvchain index.
47.487 + *
47.488 + * @return The program info structure.
47.489 + */
47.490 +GMythProgramInfo *
47.491 +gmyth_tvchain_get_program_at(GMythTVChain * tvchain, gint index)
47.492 +{
47.493 + struct LiveTVChainEntry *entry;
47.494 +
47.495 + entry = gmyth_tvchain_get_entry_at(tvchain, index);
47.496 +
47.497 + if (entry)
47.498 + return gmyth_tvchain_entry_to_program(tvchain, entry);
47.499 +
47.500 + return NULL;
47.501 +}
47.502 +
47.503 +/** Gets a LiveTVChainEntry associated to the tvchain by its index.
47.504 + *
47.505 + * @param tvchain The GMythTVChain instance.
47.506 + * @param index The tvchain entry index
47.507 + * @return The LiveTVchainEntry structure.
47.508 + */
47.509 +struct LiveTVChainEntry *
47.510 +gmyth_tvchain_get_entry_at(GMythTVChain * tvchain, gint index)
47.511 +{
47.512 + struct LiveTVChainEntry *chain_entry = NULL;
47.513 +
47.514 + g_return_val_if_fail(tvchain != NULL
47.515 + && tvchain->tvchain_list != NULL, NULL);
47.516 +
47.517 + g_mutex_lock(tvchain->mutex);
47.518 +
47.519 + gint size = g_list_length(tvchain->tvchain_list);
47.520 + gint new_index = (index < 0
47.521 + || index >= size) ? size - 1 : index;
47.522 +
47.523 + if (new_index >= 0)
47.524 + chain_entry =
47.525 + (struct LiveTVChainEntry *) g_list_nth_data(tvchain->
47.526 + tvchain_list,
47.527 + new_index);
47.528 +
47.529 + g_mutex_unlock(tvchain->mutex);
47.530 +
47.531 + if (chain_entry != NULL) {
47.532 + gmyth_debug("[%s] Got TV Chain entry at %d.\n", __FUNCTION__,
47.533 + new_index);
47.534 +
47.535 + } else {
47.536 + gmyth_debug("[%s] failed to get entry at index %d", __FUNCTION__,
47.537 + index);
47.538 + }
47.539 +
47.540 + return chain_entry;
47.541 +}
47.542 +
47.543 +/**
47.544 + * Gets the program info from backend database associated to the tv chain entry.
47.545 + *
47.546 + * @param tvchain The GMythTVChain instance.
47.547 + * @param entry the LiveTVChainEntry to be converted.
47.548 + *
47.549 + * @return The program info.
47.550 + */
47.551 +GMythProgramInfo *
47.552 +gmyth_tvchain_entry_to_program(GMythTVChain * tvchain,
47.553 + struct LiveTVChainEntry * entry)
47.554 +{
47.555 + GMythProgramInfo *proginfo = NULL;
47.556 +
47.557 + g_return_val_if_fail(tvchain != NULL, NULL);
47.558 +
47.559 + if (!entry || !tvchain) {
47.560 + gmyth_debug
47.561 + ("gmyth_tvchain_entry_to_program() received NULL argument");
47.562 + return NULL;
47.563 + }
47.564 +
47.565 + GMythScheduler *scheduler = gmyth_scheduler_new();
47.566 +
47.567 + gmyth_scheduler_connect(scheduler, tvchain->backend_info);
47.568 + proginfo = gmyth_scheduler_get_recorded(scheduler,
47.569 + entry->chanid,
47.570 + entry->starttime);
47.571 + gmyth_scheduler_disconnect(scheduler);
47.572 +
47.573 + if (proginfo) {
47.574 + proginfo->pathname =
47.575 + g_string_prepend(proginfo->pathname, entry->hostprefix->str);
47.576 + } else {
47.577 + gmyth_debug
47.578 + ("tvchain_entry_to_program( chan id = %s, starttime = %ld) failed!",
47.579 + entry->chanid->str, entry->starttime->tv_sec);
47.580 + }
47.581 +
47.582 + return proginfo;
47.583 +}
47.584 +
47.585 +static void
47.586 +free_tvchain_entry(gpointer data, gpointer user_data)
47.587 +{
47.588 + struct LiveTVChainEntry *entry;
47.589 +
47.590 + g_return_if_fail(data != NULL);
47.591 +
47.592 + entry = (struct LiveTVChainEntry *) data;
47.593 +
47.594 + if (entry->chanid != NULL) {
47.595 + g_string_free(entry->chanid, TRUE);
47.596 + }
47.597 +
47.598 + if (entry->starttime != NULL) {
47.599 + g_free(entry->starttime);
47.600 + }
47.601 +
47.602 + if (entry->endtime != NULL) {
47.603 + g_free(entry->endtime);
47.604 + }
47.605 +
47.606 + if (entry->hostprefix) {
47.607 + g_string_free(entry->hostprefix, TRUE);
47.608 + }
47.609 +
47.610 + if (entry->cardtype) {
47.611 + g_string_free(entry->cardtype, TRUE);
47.612 + }
47.613 +
47.614 + if (entry->channum) {
47.615 + g_string_free(entry->channum, TRUE);
47.616 + }
47.617 +
47.618 + if (entry->inputname) {
47.619 + g_string_free(entry->inputname, TRUE);
47.620 + }
47.621 +
47.622 + g_free(entry);
47.623 +}
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
48.2 +++ b/gmyth/gmyth/gmyth_tvchain.h Mon Feb 25 17:51:43 2008 +0000
48.3 @@ -0,0 +1,118 @@
48.4 +/**
48.5 + * GMyth Library
48.6 + *
48.7 + * @file gmyth/gmyth_tvchain.h
48.8 + *
48.9 + * @brief <p> This component contains functions for creating and accessing
48.10 + * the tvchain functions for live tv playback.
48.11 + *
48.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
48.13 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
48.14 + *
48.15 + *
48.16 + * This program is free software; you can redistribute it and/or modify
48.17 + * it under the terms of the GNU Lesser General Public License as published by
48.18 + * the Free Software Foundation; either version 2 of the License, or
48.19 + * (at your option) any later version.
48.20 + *
48.21 + * This program is distributed in the hope that it will be useful,
48.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
48.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48.24 + * GNU General Public License for more details.
48.25 + *
48.26 + * You should have received a copy of the GNU Lesser General Public License
48.27 + * along with this program; if not, write to the Free Software
48.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
48.29 + */
48.30 +
48.31 +#ifndef LIVETVCHAIN_H_
48.32 +#define LIVETVCHAIN_H_
48.33 +
48.34 +#include <glib-object.h>
48.35 +#include <time.h>
48.36 +
48.37 +#include "gmyth_common.h"
48.38 +#include "gmyth_backendinfo.h"
48.39 +
48.40 +G_BEGIN_DECLS
48.41 +#define GMYTH_TVCHAIN_TYPE (gmyth_tvchain_get_type ())
48.42 +#define GMYTH_TVCHAIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TVCHAIN_TYPE, GMythTVChain))
48.43 +#define GMYTH_TVCHAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVCHAIN_TYPE, GMythTVChainClass))
48.44 +#define IS_GMYTH_TVCHAIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_TVCHAIN_TYPE))
48.45 +#define IS_GMYTH_TVCHAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVCHAIN_TYPE))
48.46 +#define GMYTH_TVCHAIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_TVCHAIN_TYPE, GMythTVChainClass))
48.47 +typedef struct _GMythTVChain GMythTVChain;
48.48 +typedef struct _GMythTVChainClass GMythTVChainClass;
48.49 +
48.50 +
48.51 +struct LiveTVChainEntry {
48.52 + GString *chanid;
48.53 +
48.54 + GTimeVal *starttime;
48.55 + GTimeVal *endtime;
48.56 +
48.57 + gboolean discontinuity; // if true, can't play smooth from
48.58 + // last entry
48.59 + GString *hostprefix;
48.60 + GString *cardtype;
48.61 + GString *channum;
48.62 + GString *inputname;
48.63 +};
48.64 +
48.65 +
48.66 +struct _GMythTVChainClass {
48.67 + GObjectClass parent_class;
48.68 +
48.69 + /*
48.70 + * callbacks
48.71 + */
48.72 + /*
48.73 + * no one for now
48.74 + */
48.75 +};
48.76 +
48.77 +struct _GMythTVChain {
48.78 + GObject parent;
48.79 +
48.80 + GString *tvchain_id;
48.81 + GList *tvchain_list;
48.82 +
48.83 + GTimeVal *cur_startts;
48.84 + GString *cur_chanid;
48.85 + gint cur_pos;
48.86 +
48.87 + GMythBackendInfo *backend_info;
48.88 +
48.89 + GMutex *mutex;
48.90 +};
48.91 +
48.92 +GType gmyth_tvchain_get_type(void);
48.93 +
48.94 +GMythTVChain *gmyth_tvchain_new();
48.95 +
48.96 +gboolean gmyth_tvchain_initialize(GMythTVChain * tvchain,
48.97 + GMythBackendInfo * backend_info);
48.98 +gboolean gmyth_tvchain_reload_all(GMythTVChain * tvchain);
48.99 +GString *gmyth_tvchain_get_id(GMythTVChain * tvchain);
48.100 +gint gmyth_tvchain_program_is_at(GMythTVChain * tvchain,
48.101 + GString * chanid,
48.102 + GTimeVal * startts);
48.103 +
48.104 +struct LiveTVChainEntry *gmyth_tvchain_get_entry_at(GMythTVChain * tvchain,
48.105 + gint index);
48.106 +
48.107 +GMythProgramInfo *gmyth_tvchain_entry_to_program(GMythTVChain * tvchain, struct LiveTVChainEntry
48.108 + *entry);
48.109 +GMythProgramInfo *gmyth_tvchain_get_program_at(GMythTVChain * tvchain,
48.110 + gint index);
48.111 +
48.112 +GList *gmyth_tvchain_get_program_info_from_channel(GMythTVChain *
48.113 + tvchain,
48.114 + const gchar *
48.115 + channel);
48.116 +
48.117 +GList *gmyth_tvchain_get_program_info_list(GMythTVChain *
48.118 + tvchain);
48.119 +
48.120 +G_END_DECLS
48.121 +#endif /* LIVETVCHAIN_H_ */
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/gmyth/gmyth/gmyth_uri.c Mon Feb 25 17:51:43 2008 +0000
49.3 @@ -0,0 +1,604 @@
49.4 +/**
49.5 + * GMyth Library
49.6 + *
49.7 + * @file gmyth/gmyth_uri.c
49.8 + *
49.9 + * @brief <p> GMythURI utils
49.10 + * - Extracts and parses a URI char string, in according with the RFC 2396
49.11 + * [http://www.ietf.org/rfc/rfc2396.txt]
49.12 + *
49.13 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
49.14 + * @author Rosfran Borges <rosfran.borges@indt.org.br>
49.15 + *
49.16 + *
49.17 + * This program is free software; you can redistribute it and/or modify
49.18 + * it under the terms of the GNU Lesser General Public License as published by
49.19 + * the Free Software Foundation; either version 2 of the License, or
49.20 + * (at your option) any later version.
49.21 + *
49.22 + * This program is distributed in the hope that it will be useful,
49.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
49.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49.25 + * GNU General Public License for more details.
49.26 + *
49.27 + * You should have received a copy of the GNU Lesser General Public License
49.28 + * along with this program; if not, write to the Free Software
49.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
49.30 + */
49.31 +
49.32 +#ifdef HAVE_CONFIG_H
49.33 +#include "config.h"
49.34 +#endif
49.35 +
49.36 +#include "gmyth_uri.h"
49.37 +#include "gmyth_socket.h"
49.38 +
49.39 +#include <glib.h>
49.40 +#include <string.h>
49.41 +#include <stdlib.h>
49.42 +
49.43 +#include "gmyth_debug.h"
49.44 +
49.45 +/****************************************
49.46 +* Define
49.47 +****************************************/
49.48 +
49.49 +#define GMYTH_URI_KNKOWN_PORT (-1)
49.50 +#define GMYTH_URI_DEFAULT_HTTP_PORT 80
49.51 +#define GMYTH_URI_DEFAULT_FTP_PORT 21
49.52 +#define GMYTH_URI_DEFAULT_MYTH_PORT 6543
49.53 +#define GMYTH_URI_DEFAULT_PATH "/"
49.54 +#define GMYTH_URI_MAXLEN 256
49.55 +
49.56 +#define GMYTH_URI_PROTOCOL_DELIM "://"
49.57 +#define GMYTH_URI_USER_DELIM "@"
49.58 +#define GMYTH_URI_COLON_DELIM ":"
49.59 +#define GMYTH_URI_SLASH_DELIM "/"
49.60 +#define GMYTH_URI_SBLACET_DELIM "["
49.61 +#define GMYTH_URI_EBLACET_DELIM "]"
49.62 +#define GMYTH_URI_SHARP_DELIM "#"
49.63 +#define GMYTH_URI_QUESTION_DELIM "?"
49.64 +#define GMYTH_URI_E_DELIM "&"
49.65 +#define GMYTH_URI_ESCAPING_CHAR "%"
49.66 +
49.67 +#define GMYTH_URI_PROTOCOL_MYTH "myth"
49.68 +#define GMYTH_URI_PROTOCOL_HTTP "http"
49.69 +#define GMYTH_URI_PROTOCOL_FTP "ftp"
49.70 +
49.71 +
49.72 +static void gmyth_uri_class_init(GMythURIClass * klass);
49.73 +static void gmyth_uri_init(GMythURI * object);
49.74 +
49.75 +static void gmyth_uri_dispose(GObject * object);
49.76 +static void gmyth_uri_finalize(GObject * object);
49.77 +
49.78 +static void gmyth_uri_parser_setup_and_new(GMythURI * uri,
49.79 + const gchar * value);
49.80 +static gchar *gmyth_uri_print_field(const GString * field);
49.81 +
49.82 +G_DEFINE_TYPE(GMythURI, gmyth_uri, G_TYPE_OBJECT)
49.83 + static void gmyth_uri_class_init(GMythURIClass * klass)
49.84 +{
49.85 + GObjectClass *gobject_class;
49.86 +
49.87 + gobject_class = (GObjectClass *) klass;
49.88 +
49.89 + gobject_class->dispose = gmyth_uri_dispose;
49.90 + gobject_class->finalize = gmyth_uri_finalize;
49.91 +}
49.92 +
49.93 +static void
49.94 +gmyth_uri_init(GMythURI * gmyth_uri)
49.95 +{
49.96 +}
49.97 +
49.98 +static void
49.99 +gmyth_uri_dispose(GObject * object)
49.100 +{
49.101 + GMythURI *gmyth_uri = GMYTH_URI(object);
49.102 +
49.103 + if (gmyth_uri->host != NULL) {
49.104 + g_string_free(gmyth_uri->host, TRUE);
49.105 + gmyth_uri->host = NULL;
49.106 + }
49.107 +
49.108 + if (gmyth_uri->protocol != NULL) {
49.109 + g_string_free(gmyth_uri->protocol, TRUE);
49.110 + gmyth_uri->protocol = NULL;
49.111 + }
49.112 +
49.113 + if (gmyth_uri->path != NULL) {
49.114 + g_string_free(gmyth_uri->path, TRUE);
49.115 + gmyth_uri->path = NULL;
49.116 + }
49.117 +
49.118 + if (gmyth_uri->fragment != NULL) {
49.119 + g_string_free(gmyth_uri->fragment, TRUE);
49.120 + gmyth_uri->fragment = NULL;
49.121 + }
49.122 +
49.123 + if (gmyth_uri->user != NULL) {
49.124 + g_string_free(gmyth_uri->user, TRUE);
49.125 + gmyth_uri->user = NULL;
49.126 + }
49.127 +
49.128 + if (gmyth_uri->password != NULL) {
49.129 + g_string_free(gmyth_uri->password, TRUE);
49.130 + gmyth_uri->password = NULL;
49.131 + }
49.132 +
49.133 + if (gmyth_uri->query != NULL) {
49.134 + g_string_free(gmyth_uri->query, TRUE);
49.135 + gmyth_uri->query = NULL;
49.136 + }
49.137 +
49.138 + if (gmyth_uri->uri != NULL) {
49.139 + g_string_free(gmyth_uri->uri, TRUE);
49.140 + gmyth_uri->uri = NULL;
49.141 + }
49.142 +
49.143 +
49.144 + G_OBJECT_CLASS(gmyth_uri_parent_class)->dispose(object);
49.145 +}
49.146 +
49.147 +static void
49.148 +gmyth_uri_finalize(GObject * object)
49.149 +{
49.150 + // GMythURI *gmyth_uri = GMYTH_URI(object);
49.151 +
49.152 + g_signal_handlers_destroy(object);
49.153 +
49.154 + G_OBJECT_CLASS(gmyth_uri_parent_class)->finalize(object);
49.155 +}
49.156 +
49.157 +/**
49.158 + * Creates a new instance of GMythURI.
49.159 + *
49.160 + * @return a new instance of GMythURI.
49.161 + */
49.162 +GMythURI *
49.163 +gmyth_uri_new(void)
49.164 +{
49.165 + GMythURI *gmyth_uri =
49.166 + GMYTH_URI(g_object_new(GMYTH_URI_TYPE, NULL));
49.167 +
49.168 + return gmyth_uri;
49.169 +}
49.170 +
49.171 +/**
49.172 + * Creates a new instance of GMythURI.
49.173 + *
49.174 + * @param uri_str The URI string representing this URI instance.
49.175 + *
49.176 + * @return a new instance of GMythURI.
49.177 + */
49.178 +GMythURI *
49.179 +gmyth_uri_new_with_value(const gchar * uri_str)
49.180 +{
49.181 + GMythURI *gmyth_uri =
49.182 + GMYTH_URI(g_object_new(GMYTH_URI_TYPE, NULL));
49.183 +
49.184 + gmyth_uri_parser_setup_and_new(gmyth_uri, uri_str);
49.185 +
49.186 + return gmyth_uri;
49.187 +}
49.188 +
49.189 +/**
49.190 + * Gets the starting offset of a substring inside a given string.
49.191 + *
49.192 + * @param haystack The given string to be searched for patterns.
49.193 + * @param needle The substring that should be matched over the haystack.
49.194 + *
49.195 + * @return The starting offset to the given substring, or <code>-1</code> if the
49.196 + * haystack function parameter doesn't contains the needle string argument.
49.197 + */
49.198 +static gint
49.199 +gmyth_strstr(const gchar * haystack, const gchar * needle)
49.200 +{
49.201 +
49.202 + gchar *strPos;
49.203 +
49.204 + if (haystack == NULL || needle == NULL)
49.205 + return -1;
49.206 + strPos = strstr(haystack, needle);
49.207 + if (strPos == NULL)
49.208 + return -1;
49.209 +
49.210 + return (strPos - haystack);
49.211 +
49.212 +}
49.213 +
49.214 +/**
49.215 + * Checks if a URI is absolute.
49.216 + *
49.217 + * @param uri The GMythURI instance.
49.218 + *
49.219 + * @return <code>true</code>, if the URI is absolute.
49.220 + */
49.221 +static gboolean
49.222 +gmyth_uri_isabsolute(const GMythURI * uri)
49.223 +{
49.224 + gboolean ret = FALSE;
49.225 +
49.226 + g_return_val_if_fail(uri != NULL && uri->uri != NULL
49.227 + && uri->protocol != NULL, FALSE);
49.228 +
49.229 + if (gmyth_strstr(uri->uri->str, GMYTH_URI_PROTOCOL_DELIM) == 0
49.230 + || strlen(uri->protocol->str) > 0)
49.231 + ret = TRUE;
49.232 +
49.233 + return ret;
49.234 +}
49.235 +
49.236 +/**
49.237 + * Searches for the first reverse character occurrence, from a given
49.238 + * list of characters, inside a given string.
49.239 + *
49.240 + * @param str The given string to be searched for characters occurrence.
49.241 + * @param chars The characters list. If this string returns 4 on strlen, there are
49.242 + * four possible characters to be matched.
49.243 + * @param nchars The number of characters to be matched, which has at most
49.244 + * strlen(chars).
49.245 + *
49.246 + * @return The starting offset to the first character occurrence,
49.247 + * or <code>-1</code> if the no character of the list could be found.
49.248 + */
49.249 +static gint
49.250 +gmyth_strrchr(const gchar * str, const gchar * chars, const gint nchars)
49.251 +{
49.252 +
49.253 + gint strLen;
49.254 + gint i,
49.255 + j;
49.256 +
49.257 + if (str == NULL || chars == NULL)
49.258 + return -1;
49.259 +
49.260 + strLen = strlen(str);
49.261 + for (i = (strLen - 1); 0 <= i; i--) {
49.262 + for (j = 0; j < nchars; j++) {
49.263 + if (str[i] == chars[j])
49.264 + return i;
49.265 + }
49.266 + }
49.267 +
49.268 + return -1;
49.269 +
49.270 +}
49.271 +
49.272 +static gchar *
49.273 +gmyth_uri_print_field(const GString * field)
49.274 +{
49.275 + if (field != NULL && field->str != NULL && strlen(field->str) > 0)
49.276 + return field->str;
49.277 + else
49.278 + return "";
49.279 +}
49.280 +
49.281 +static gint
49.282 +gmyth_uri_get_default_port (GMythURI * uri)
49.283 +{
49.284 + const gchar *protocol = gmyth_uri_get_protocol(uri);
49.285 +
49.286 + if (strcmp(protocol, GMYTH_URI_PROTOCOL_HTTP) == 0)
49.287 + return GMYTH_URI_DEFAULT_HTTP_PORT;
49.288 + if (strcmp(protocol, GMYTH_URI_PROTOCOL_FTP) == 0)
49.289 + return GMYTH_URI_DEFAULT_FTP_PORT;
49.290 + if (strcmp(protocol, GMYTH_URI_PROTOCOL_MYTH) == 0)
49.291 + return GMYTH_URI_DEFAULT_MYTH_PORT;
49.292 +
49.293 + return GMYTH_URI_KNKOWN_PORT;
49.294 +}
49.295 +
49.296 +/**
49.297 + * Parses a URI string into a GMythURI instance.
49.298 + *
49.299 + * @param uri The GMythURI instance.
49.300 + * @param value The URI string to be parsed.
49.301 + *
49.302 + */
49.303 +static void
49.304 +gmyth_uri_parser_setup_and_new(GMythURI * uri, const gchar * value)
49.305 +{
49.306 +
49.307 + gint uriLen;
49.308 + gint currIdx;
49.309 + gint protoIdx;
49.310 + gint atIdx;
49.311 + gint colonIdx;
49.312 + gint shashIdx;
49.313 + gint eIdx;
49.314 + gchar *host;
49.315 + gint eblacketIdx;
49.316 + gint hostLen;
49.317 + gint sharpIdx;
49.318 +
49.319 + /*
49.320 + * gint questionIdx; gint queryLen;
49.321 + */
49.322 +
49.323 + uriLen = strlen(value);
49.324 + uri->uri = g_string_new(value);
49.325 +
49.326 + currIdx = 0;
49.327 +
49.328 + /*** Protocol ****/
49.329 + protoIdx = gmyth_strstr(value, GMYTH_URI_PROTOCOL_DELIM);
49.330 + if (0 < protoIdx) {
49.331 + uri->protocol = g_string_new_len(value, protoIdx);
49.332 + currIdx += protoIdx + strlen(GMYTH_URI_PROTOCOL_DELIM);
49.333 + }
49.334 +
49.335 + /*** User (Password) ****/
49.336 + atIdx = gmyth_strstr(value + currIdx, GMYTH_URI_USER_DELIM);
49.337 + if (0 < atIdx) {
49.338 + colonIdx = gmyth_strstr(value + currIdx, GMYTH_URI_COLON_DELIM);
49.339 +
49.340 + if (0 < colonIdx && colonIdx < atIdx) {
49.341 + uri->user = g_string_new_len(value + currIdx, colonIdx);
49.342 + uri->password =
49.343 + g_string_new_len(value + currIdx + colonIdx + 1,
49.344 + atIdx - (colonIdx + 1));
49.345 + } else
49.346 + uri->user = g_string_new_len(value + currIdx, atIdx - currIdx);
49.347 + currIdx += atIdx + 1;
49.348 + }
49.349 +
49.350 + /*** Host (Port) ****/
49.351 + shashIdx = gmyth_strstr(value + currIdx, GMYTH_URI_SLASH_DELIM);
49.352 + if (0 < shashIdx)
49.353 + uri->host = g_string_new_len(value + currIdx, shashIdx);
49.354 + else if (gmyth_uri_isabsolute(uri) == TRUE)
49.355 + uri->host =
49.356 + g_string_new_len(value + currIdx, strlen(value) - currIdx);
49.357 +
49.358 + host = gmyth_uri_get_host(uri);
49.359 + colonIdx = gmyth_strrchr(host, GMYTH_URI_COLON_DELIM, 1);
49.360 + eblacketIdx = gmyth_strrchr(host, GMYTH_URI_EBLACET_DELIM, 1);
49.361 + if ((0 < colonIdx) && (eblacketIdx < colonIdx)) {
49.362 + GString *portStr = NULL;
49.363 + GString *hostStr = g_string_new(host != NULL ? host : "");
49.364 +
49.365 + hostLen = hostStr->len;
49.366 + /**** host ****/
49.367 + uri->host = g_string_erase(uri->host, 0, hostLen);
49.368 + uri->host =
49.369 + g_string_insert_len(uri->host, 0, hostStr->str, colonIdx);
49.370 + if (0 < hostLen) {
49.371 + if (host[0] == '[' && host[hostLen - 1] == ']')
49.372 + uri->host =
49.373 + g_string_new_len(hostStr->str + 1, colonIdx - 2);
49.374 + }
49.375 +
49.376 + /**** port ****/
49.377 + portStr = g_string_new_len(hostStr->str + colonIdx + 1,
49.378 + hostLen - colonIdx - 1);
49.379 + uri->port = (gint) g_ascii_strtoull(portStr->str, NULL, 10);
49.380 + g_string_free(portStr, TRUE);
49.381 + g_string_free(hostStr, TRUE);
49.382 + } else {
49.383 + uri->port = gmyth_uri_get_default_port (uri);
49.384 + }
49.385 +
49.386 + if (shashIdx > 0)
49.387 + currIdx += shashIdx;
49.388 +
49.389 + /*
49.390 + * Handle relative URL
49.391 + */
49.392 + if (gmyth_uri_isabsolute(uri) == FALSE) {
49.393 +
49.394 + if (shashIdx != 0) {
49.395 + /*
49.396 + * Add slash delimiter at the beginning of the URL, if it
49.397 + * doesn't exist
49.398 + */
49.399 + uri->path = g_string_new(GMYTH_URI_SLASH_DELIM);
49.400 + }
49.401 + uri->path = g_string_append(uri->path, value);
49.402 +
49.403 + } else {
49.404 + /*
49.405 + * First set path simply to the rest of URI
49.406 + */
49.407 + uri->path = g_string_new_len(value + currIdx, uriLen - currIdx);
49.408 + }
49.409 +
49.410 + // gmyth_debug( "uri value: %s", value );
49.411 + uri->query =
49.412 + g_string_new(g_strstr_len
49.413 + (value, strlen(value), GMYTH_URI_QUESTION_DELIM));
49.414 +
49.415 + eIdx = gmyth_strstr(value + currIdx, GMYTH_URI_QUESTION_DELIM);
49.416 +
49.417 + if (0 < eIdx) {
49.418 + uri->query =
49.419 + g_string_new(g_strstr_len
49.420 + (value, strlen(value), GMYTH_URI_QUESTION_DELIM));
49.421 + gmyth_debug("query = %s", uri->query->str);
49.422 + }
49.423 +
49.424 + /**** Path (Query/Fragment) ****/
49.425 + sharpIdx = gmyth_strstr(value + currIdx, GMYTH_URI_E_DELIM);
49.426 + if (0 < sharpIdx) {
49.427 + uri->path =
49.428 + g_string_append_len(uri->path, value + currIdx, sharpIdx);
49.429 + uri->fragment =
49.430 + g_string_new_len(value + currIdx + sharpIdx + 1,
49.431 + uriLen - (currIdx + sharpIdx + 1));
49.432 + }
49.433 +
49.434 + gmyth_debug
49.435 + ("[%s] GMythURI: host = %s, port = %d, path = %s, query = %s, fragment = %s, "
49.436 + "user = %s, password = %s.\n", __FUNCTION__,
49.437 + gmyth_uri_print_field(uri->host), uri->port,
49.438 + gmyth_uri_print_field(uri->path),
49.439 + gmyth_uri_print_field(uri->query),
49.440 + gmyth_uri_print_field(uri->fragment),
49.441 + gmyth_uri_print_field(uri->user),
49.442 + gmyth_uri_print_field(uri->password));
49.443 +
49.444 +}
49.445 +
49.446 +/**
49.447 + * Compares 2 URI instances, and checks them for equality.
49.448 + *
49.449 + * @param uri The first GMythURI instance for comparison.
49.450 + * @param uri The second GMythURI instance for comparison.
49.451 + *
49.452 + * @return <code>true</code>, if these two URI instances are equals.
49.453 + */
49.454 +gboolean
49.455 +gmyth_uri_is_equals(GMythURI * uri1, GMythURI * uri2)
49.456 +{
49.457 + return (g_ascii_strcasecmp
49.458 + (gmyth_uri_get_host(uri1), gmyth_uri_get_host(uri2)) == 0
49.459 + && gmyth_uri_get_port(uri1) == gmyth_uri_get_port(uri2));
49.460 +}
49.461 +
49.462 +/**
49.463 + * Checks if the URI instance represents a LiveTV recording.
49.464 + *
49.465 + * @param uri The GMythURI instance.
49.466 + *
49.467 + * @return <code>true</code>, if the URI points to LiveTV content.
49.468 + */
49.469 +gboolean
49.470 +gmyth_uri_is_livetv(GMythURI * uri)
49.471 +{
49.472 + gboolean ret = TRUE;
49.473 +
49.474 + g_return_val_if_fail(uri != NULL, FALSE);
49.475 + g_return_val_if_fail(uri->uri != NULL, FALSE);
49.476 + g_return_val_if_fail(uri->uri->str != NULL, FALSE);
49.477 +
49.478 + if ((strstr(uri->uri->str, "channel=") == NULL) &&
49.479 + (strstr(uri->uri->str, "livetv") == NULL))
49.480 + ret = FALSE;
49.481 +
49.482 + if (ret)
49.483 + gmyth_debug("This URI is a LiveTV recording...");
49.484 + else
49.485 + gmyth_debug("This URI is a stored remote recording.");
49.486 +
49.487 + return ret;
49.488 +
49.489 +}
49.490 +
49.491 +/**
49.492 + * Gets the channel name fro a URI instance.
49.493 + *
49.494 + * @param uri The GMythURI instance.
49.495 + *
49.496 + * @return The channel name, got from the substring "?channel=[channel_name]"
49.497 + * of the URI string.
49.498 + */
49.499 +gchar *
49.500 +gmyth_uri_get_channel_name(GMythURI * uri)
49.501 +{
49.502 + gchar *channel = NULL;
49.503 +
49.504 + g_return_val_if_fail(uri != NULL && uri->uri != NULL
49.505 + && uri->uri->str != NULL, FALSE);
49.506 +
49.507 + gchar *channel_query = g_strstr_len(gmyth_uri_get_query(uri),
49.508 + strlen(gmyth_uri_get_query
49.509 + (uri)),
49.510 + "channel");
49.511 +
49.512 + if (channel_query != NULL) {
49.513 + gchar **chan_key_value =
49.514 + g_strsplit(gmyth_uri_get_query(uri), "=", 2);
49.515 +
49.516 + /*
49.517 + * gmyth_debug( "Channel tuple is [ %s, %s ]", chan_key_value[0],
49.518 + * chan_key_value[1] );
49.519 + */
49.520 +
49.521 + if (chan_key_value[1] != NULL && strlen(chan_key_value[1]) > 0) {
49.522 + channel = g_strdup(chan_key_value[1]);
49.523 + }
49.524 +
49.525 + if (chan_key_value != NULL)
49.526 + g_strfreev(chan_key_value);
49.527 + }
49.528 +
49.529 + gmyth_debug("Got channel decimal value from the URI: %s", channel);
49.530 +
49.531 + return channel;
49.532 +
49.533 +}
49.534 +
49.535 +/**
49.536 + * Gets the channel number from a URI instance.
49.537 + *
49.538 + * @param uri The GMythURI instance.
49.539 + *
49.540 + * @return The channel number, got from the substring "?channel=[channel_number]"
49.541 + * of the URI string, or <code>-1</code> it if couldn't be converted.
49.542 + */
49.543 +gint
49.544 +gmyth_uri_get_channel_num(GMythURI * uri)
49.545 +{
49.546 + gchar *channel_name = gmyth_uri_get_channel_name(uri);
49.547 +
49.548 + if (channel_name != NULL) {
49.549 + return g_ascii_strtoull(channel_name, NULL, 10);
49.550 + }
49.551 +
49.552 + return -1;
49.553 +
49.554 +}
49.555 +
49.556 +/**
49.557 + * Checks if the URI instance represents a reference to a local file.
49.558 + *
49.559 + * @param uri The GMythURI instance.
49.560 + *
49.561 + * @return <code>true</code>, if the URI points to a local file.
49.562 + */
49.563 +gboolean
49.564 +gmyth_uri_is_local_file(const GMythURI * uri)
49.565 +{
49.566 + gboolean ret = FALSE;
49.567 + gint len = -1;
49.568 +
49.569 + GString *hostname = gmyth_socket_get_local_hostname();
49.570 +
49.571 + g_return_val_if_fail(uri != NULL, FALSE);
49.572 +
49.573 + len = strlen(gmyth_uri_get_host(uri));
49.574 +
49.575 + // gmyth_debug("URI: host = %s, hostname = %s.", uri->host->str,
49.576 + // hostname != NULL ? hostname->str : "[no hostname]");
49.577 +
49.578 + ret = (NULL != hostname && (g_ascii_strncasecmp(uri->host->str, (hostname)->str, len) == 0) /* ||
49.579 + * (
49.580 + * g_ascii_strncasecmp(
49.581 + * gmyth_uri_get_host(uri),
49.582 + * gmyth_socket_get_primary_addr(),
49.583 + * len
49.584 + * )
49.585 + * ==
49.586 + * 0
49.587 + * )
49.588 + */
49.589 + );
49.590 +
49.591 + if (ret)
49.592 + gmyth_debug("This URI is a local file...");
49.593 + else
49.594 + gmyth_debug("This URI is NOT a local file...");
49.595 +
49.596 + return ret;
49.597 +
49.598 +}
49.599 +
49.600 +char *
49.601 +gmyth_uri_to_string(const GMythURI * uri)
49.602 +{
49.603 + g_return_val_if_fail(uri != NULL, NULL);
49.604 + g_return_val_if_fail(uri->uri != NULL, NULL);
49.605 +
49.606 + return g_strdup(uri->uri->str);
49.607 +}
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
50.2 +++ b/gmyth/gmyth/gmyth_uri.h Mon Feb 25 17:51:43 2008 +0000
50.3 @@ -0,0 +1,101 @@
50.4 +/**
50.5 + * GMyth Library
50.6 + *
50.7 + * @file gmyth/gmyth_uri.h
50.8 + *
50.9 + * @brief <p> GMythURI utils
50.10 + * - Extracts and parses a URI char string, in according with the RFC 2396
50.11 + * [http://www.ietf.org/rfc/rfc2396.txt]
50.12 + *
50.13 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
50.14 + * @author Rosfran Borges <rosfran.borges@indt.org.br>
50.15 + *
50.16 + *
50.17 + * This program is free software; you can redistribute it and/or modify
50.18 + * it under the terms of the GNU Lesser General Public License as published by
50.19 + * the Free Software Foundation; either version 2 of the License, or
50.20 + * (at your option) any later version.
50.21 + *
50.22 + * This program is distributed in the hope that it will be useful,
50.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
50.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50.25 + * GNU General Public License for more details.
50.26 + *
50.27 + * You should have received a copy of the GNU Lesser General Public License
50.28 + * along with this program; if not, write to the Free Software
50.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
50.30 + */
50.31 +
50.32 +#ifndef _GMYTH_URI_H_
50.33 +#define _GMYTH_URI_H_
50.34 +
50.35 +#include <glib.h>
50.36 +#include <glib-object.h>
50.37 +
50.38 +#include <stdlib.h>
50.39 +#include <stdio.h>
50.40 +#include <string.h>
50.41 +
50.42 +G_BEGIN_DECLS
50.43 +#define GMYTH_URI_TYPE (gmyth_uri_get_type ())
50.44 +#define GMYTH_URI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_URI_TYPE, GMythURI))
50.45 +#define GMYTH_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_URI_TYPE, GMythURIClass))
50.46 +#define IS_GMYTH_URI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_URI_TYPE))
50.47 +#define IS_GMYTH_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_URI_TYPE))
50.48 +#define GMYTH_URI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_URI_TYPE, GMythURIClass))
50.49 +typedef struct _GMythURI GMythURI;
50.50 +typedef struct _GMythURIClass GMythURIClass;
50.51 +
50.52 +
50.53 + /****************************************
50.54 + * Data Type
50.55 + ****************************************/
50.56 +
50.57 +struct _GMythURIClass {
50.58 + GObjectClass parent_class;
50.59 +
50.60 + /*
50.61 + * callbacks
50.62 + */
50.63 + /*
50.64 + * no one for now
50.65 + */
50.66 +};
50.67 +
50.68 +struct _GMythURI {
50.69 +
50.70 + GObject parent;
50.71 +
50.72 + GString *uri;
50.73 + GString *host;
50.74 + gint port;
50.75 + GString *protocol;
50.76 + GString *path;
50.77 + GString *fragment;
50.78 + GString *user;
50.79 + GString *password;
50.80 + GString *query;
50.81 +
50.82 +};
50.83 +
50.84 +GType gmyth_uri_get_type(void);
50.85 +GMythURI *gmyth_uri_new(void);
50.86 +GMythURI *gmyth_uri_new_with_value(const gchar * value);
50.87 +gboolean gmyth_uri_is_equals(GMythURI * uri1, GMythURI * uri2);
50.88 +gboolean gmyth_uri_is_livetv(GMythURI * uri);
50.89 +gint gmyth_uri_get_channel_num(GMythURI * uri);
50.90 +gchar *gmyth_uri_get_channel_name(GMythURI * uri);
50.91 +char *gmyth_uri_to_string(const GMythURI * uri);
50.92 +gboolean gmyth_uri_is_local_file(const GMythURI * uri);
50.93 +
50.94 +#define gmyth_uri_get_host(urip) ( urip->host != NULL ? urip->host->str : "" )
50.95 +#define gmyth_uri_get_port(urip) ( urip->port )
50.96 +#define gmyth_uri_get_protocol(urip) ( urip->protocol != NULL ? urip->protocol->str : "" )
50.97 +#define gmyth_uri_get_path(urip) ( urip->path != NULL ? urip->path->str : "" )
50.98 +#define gmyth_uri_get_user(urip) ( urip->user != NULL ? urip->user->str : "" )
50.99 +#define gmyth_uri_get_password(urip) ( urip->password != NULL ? urip->password->str : "" )
50.100 +#define gmyth_uri_get_fragment(urip) ( urip->fragment != NULL ? urip->fragment->str : "" )
50.101 +#define gmyth_uri_get_query(urip) ( urip->query != NULL ? urip->query->str : "" )
50.102 +
50.103 +G_END_DECLS
50.104 +#endif /* _GMYTH_URI_H_ */
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
51.2 +++ b/gmyth/gmyth/gmyth_util.c Mon Feb 25 17:51:43 2008 +0000
51.3 @@ -0,0 +1,957 @@
51.4 +/**
51.5 + * GMyth Library
51.6 + *
51.7 + * @file gmyth/gmyth_util.c
51.8 + *
51.9 + * @brief <p> This component provides utility functions
51.10 + * (dealing with dates, time, string formatting, etc.).
51.11 + *
51.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
51.13 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
51.14 + * @author Rosfran Borges <rosfran.borges@indt.org.br>
51.15 + *
51.16 + *
51.17 + * This program is free software; you can redistribute it and/or modify
51.18 + * it under the terms of the GNU Lesser General Public License as published by
51.19 + * the Free Software Foundation; either version 2 of the License, or
51.20 + * (at your option) any later version.
51.21 + *
51.22 + * This program is distributed in the hope that it will be useful,
51.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
51.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51.25 + * GNU General Public License for more details.
51.26 + *
51.27 + * You should have received a copy of the GNU Lesser General Public License
51.28 + * along with this program; if not, write to the Free Software
51.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
51.30 + */
51.31 +
51.32 +#ifdef HAVE_CONFIG_H
51.33 +#include "config.h"
51.34 +#endif
51.35 +
51.36 +#define _XOPEN_SOURCE
51.37 +#define _XOPEN_SOURCE_EXTENDED
51.38 +#define __USE_MISC
51.39 +
51.40 +#include <glib.h>
51.41 +#include <glib/gprintf.h>
51.42 +#include <time.h>
51.43 +#include <sys/time.h>
51.44 +#include <sys/timex.h>
51.45 +
51.46 +#include "gmyth_socket.h"
51.47 +#include "gmyth_recorder.h"
51.48 +#include "gmyth_common.h"
51.49 +#include "gmyth_debug.h"
51.50 +
51.51 +#include "gmyth_util.h"
51.52 +
51.53 +#if !GLIB_CHECK_VERSION (2, 10, 0)
51.54 +gchar *g_time_val_to_iso8601(GTimeVal * time_);
51.55 +gboolean g_time_val_from_iso8601(const gchar * iso_date,
51.56 + GTimeVal * time_);
51.57 +void g_date_set_time_val(GDate * date, GTimeVal * timeval);
51.58 +
51.59 +#endif
51.60 +
51.61 +/** Converts a time_t struct in a GString at ISO standard format
51.62 + * (e.g. 2006-07-20T09:56:41).
51.63 + *
51.64 + * The returned GString memory should be deallocated from
51.65 + * the calling function.
51.66 + *
51.67 + * @param time_value the time value to be converted
51.68 + * @return GString* the converted isoformat string
51.69 + */
51.70 +GString *
51.71 +gmyth_util_time_to_isoformat(time_t time_value)
51.72 +{
51.73 + struct tm tm_time;
51.74 + GString *result;
51.75 +
51.76 + if (localtime_r(&time_value, &tm_time) == NULL) {
51.77 + gmyth_debug("gmyth_util_time_to_isoformat convertion error!\n");
51.78 + return NULL;
51.79 + }
51.80 +
51.81 + result = g_string_sized_new(20);
51.82 + g_string_printf(result, "%04d-%02d-%02dT%02d:%02d:%02d",
51.83 + tm_time.tm_year + 1900, tm_time.tm_mon + 1,
51.84 + tm_time.tm_mday, tm_time.tm_hour, tm_time.tm_min,
51.85 + tm_time.tm_sec);
51.86 +
51.87 + gmyth_debug("Result (ISO 8601) = %s", result->str);
51.88 +
51.89 + return result;
51.90 +}
51.91 +
51.92 +/** Converts a time_t struct in a GString at ISO standard format
51.93 + * (e.g. 2006-07-20T09:56:41).
51.94 + *
51.95 + * The returned GString memory should be deallocated from
51.96 + * the calling function.
51.97 + *
51.98 + * @param time_value the GTimeValue to be converted
51.99 + * @return GString* the converted isoformat string
51.100 + */
51.101 +gchar *
51.102 +gmyth_util_time_to_isoformat_from_time_val_fmt(const gchar * fmt_string,
51.103 + const GTimeVal * time_val)
51.104 +{
51.105 + gchar *result = NULL;
51.106 + struct tm *tm_time = NULL;
51.107 + time_t time;
51.108 +
51.109 + gint buffer_len = 0;
51.110 +
51.111 + g_return_val_if_fail(fmt_string != NULL, NULL);
51.112 +
51.113 + g_return_val_if_fail(time_val != NULL, NULL);
51.114 +
51.115 + time = time_val->tv_sec; // + (gint)( time_val->tv_usec /
51.116 + // G_USEC_PER_SEC );
51.117 +
51.118 + tm_time = g_malloc0(sizeof(struct tm));
51.119 +
51.120 + if (NULL == localtime_r(&time, tm_time)) {
51.121 + gmyth_debug("gmyth_util_time_to_isoformat convertion error!\n");
51.122 + } else {
51.123 + /*
51.124 + * we first check the return of strftime to allocate a buffer of
51.125 + * the correct size
51.126 + */
51.127 + buffer_len = strftime(NULL, SSIZE_MAX, fmt_string, tm_time);
51.128 + if (buffer_len > 0) {
51.129 + result = g_malloc0(buffer_len + 1);
51.130 + if (result == NULL) {
51.131 + gmyth_debug
51.132 + ("gmyth_util_time_to_isoformat convertion error!\n");
51.133 + return NULL;
51.134 + }
51.135 + strftime(result, buffer_len + 1, fmt_string, tm_time);
51.136 + gmyth_debug("Dateline (ISO result): %s", result);
51.137 + }
51.138 + } /* if */
51.139 +
51.140 + gmyth_debug("Result (strftime) = %s", result);
51.141 +
51.142 + // strptime( result, "%Y-%m-%dT%H:%M:%SZ", tm_time );
51.143 +
51.144 + // strftime( result, strlen(result), fmt_string, tm_time );
51.145 +
51.146 + g_free(tm_time);
51.147 +
51.148 + gmyth_debug("Result (ISO 8601) = %s", result);
51.149 +
51.150 + return result;
51.151 +}
51.152 +
51.153 +/** Converts a time_t struct in a GString at ISO standard format
51.154 + * (e.g. 2006-07-20 09:56:41).
51.155 + *
51.156 + * The returned GString memory should be deallocated from
51.157 + * the calling function.
51.158 + *
51.159 + * @param time_value the GTimeValue to be converted
51.160 + * @return GString* the converted isoformat string
51.161 + */
51.162 +gchar *
51.163 +gmyth_util_time_to_isoformat_from_time_val(const GTimeVal * time)
51.164 +{
51.165 + gchar *result =
51.166 + gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%d %H:%M:%S",
51.167 + time);
51.168 +
51.169 + // result[10] = ' ';
51.170 + // result[ strlen(result) - 1] = '\0';
51.171 +
51.172 + return result;
51.173 +}
51.174 +
51.175 +/** Converts a time_t struct in a GString at ISO standard format 2
51.176 + * (e.g. 2006-07-20T09:56:41).
51.177 + *
51.178 + * The returned GString memory should be deallocated from
51.179 + * the calling function.
51.180 + *
51.181 + * @param time_value the GTimeValue to be converted
51.182 + * @return GString* the converted isoformat string
51.183 + */
51.184 +gchar *
51.185 +gmyth_util_time_to_mythformat_from_time_val(const GTimeVal * time)
51.186 +{
51.187 + gchar *result =
51.188 + gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%dT%H:%M:%S",
51.189 + time);
51.190 +
51.191 + return result;
51.192 +}
51.193 +
51.194 +/** Converts a time_t struct in a GString at ISO standard format
51.195 + * (e.g. 2006-07-20T09:56:41).
51.196 + *
51.197 + * The returned GString memory should be deallocated from
51.198 + * the calling function.
51.199 + *
51.200 + * @param time_value the GTimeValue to be converted
51.201 + * @return GString* the converted isoformat string
51.202 + */
51.203 +gchar *
51.204 +gmyth_util_time_to_string_only_date(const GTimeVal * time)
51.205 +{
51.206 + gchar *result =
51.207 + gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%d", time);
51.208 + // result[10] = ' ';
51.209 + // result[ strlen(result) - 1] = '\0';
51.210 + return result;
51.211 +}
51.212 +
51.213 +/** Converts a time_t struct in a GString at ISO standard format
51.214 + * (e.g. 2006-07-20T09:56:41).
51.215 + *
51.216 + * The returned GString memory should be deallocated from
51.217 + * the calling function.
51.218 + *
51.219 + * @param time_value the GTimeValue to be converted
51.220 + * @return GString* the converted isoformat string
51.221 + */
51.222 +gchar *
51.223 +gmyth_util_time_to_string_only_time(const GTimeVal * time)
51.224 +{
51.225 + gchar *result =
51.226 + gmyth_util_time_to_isoformat_from_time_val_fmt("%H:%M:%S", time);
51.227 + // result[10] = ' ';
51.228 + // result[ strlen(result) - 1] = '\0';
51.229 + return result;
51.230 +}
51.231 +
51.232 +/** Converts a time_t struct in a GString to the following
51.233 + * format (e.g. 2006-07-20 09:56:41).
51.234 + *
51.235 + * The returned GString memory should be deallocated from
51.236 + * the calling function.
51.237 + *
51.238 + * @param time_value the time value to be converted
51.239 + * @return GString* the converted string
51.240 + */
51.241 +GString *
51.242 +gmyth_util_time_to_string(time_t time_value)
51.243 +{
51.244 + GString *result = gmyth_util_time_to_isoformat(time_value);
51.245 +
51.246 + result->str[10] = ' ';
51.247 + result->str[strlen(result->str) - 1] = '\0';
51.248 +
51.249 + return result;
51.250 +}
51.251 +
51.252 +/** Converts a time_t struct in a GString to the following
51.253 + * format (e.g. 2006-07-20 09:56:41).
51.254 + *
51.255 + * The returned GString memory should be deallocated from
51.256 + * the calling function.
51.257 + *
51.258 + * @param time_value the time value to be converted
51.259 + * @return GString* the converted string
51.260 + */
51.261 +gchar *
51.262 +gmyth_util_time_to_string_from_time_val(const GTimeVal * time_val)
51.263 +{
51.264 + gchar *result =
51.265 + gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%d %H:%M:%S",
51.266 + time_val);
51.267 +
51.268 + // result[10] = ' ';
51.269 +
51.270 + return result;
51.271 +}
51.272 +
51.273 +/** Converts a GString in the following format
51.274 + * (e.g. 2006-07-20 09:56:41) to a time_t struct.
51.275 + *
51.276 + * @param time_str the string to be converted
51.277 + * @return time_t the time converted value
51.278 + */
51.279 +time_t
51.280 +gmyth_util_string_to_time(GString * time_str)
51.281 +{
51.282 + gint year,
51.283 + month,
51.284 + day,
51.285 + hour,
51.286 + min,
51.287 + sec;
51.288 +
51.289 + gmyth_debug("[%s] time_str = %s. [%s]", __FUNCTION__,
51.290 + time_str !=
51.291 + NULL ? time_str->str : "[time string is NULL!]",
51.292 + time_str->str);
51.293 +
51.294 + if (sscanf(time_str->str, "%04d-%02d-%02d %02d:%02d:%02d",
51.295 + &year, &month, &day, &hour, &min, &sec) < 3) {
51.296 + gmyth_debug("GMythUtil: isoformat_to_time converter error!\n");
51.297 + return 0;
51.298 + }
51.299 +
51.300 + struct tm *tm_time = g_malloc0(sizeof(struct tm));
51.301 +
51.302 + tm_time->tm_year = year - 1900;
51.303 + tm_time->tm_mon = month - 1;
51.304 + tm_time->tm_mday = day;
51.305 + tm_time->tm_hour = hour;
51.306 + tm_time->tm_min = min;
51.307 + tm_time->tm_sec = sec;
51.308 +
51.309 + return mktime(tm_time);
51.310 +}
51.311 +
51.312 +/** Converts a GString in the following format
51.313 + * (e.g. 2006-07-20 09:56:41) to a time_t struct.
51.314 + *
51.315 + * @param time_str the string to be converted
51.316 + * @return time_t the time converted value
51.317 + */
51.318 +struct tm *
51.319 +gmyth_util_time_val_to_date(const GTimeVal * time)
51.320 +{
51.321 + struct tm *date = g_malloc0(sizeof(struct tm));
51.322 + time_t time_micros = time->tv_sec; // + (gint)( time->tv_usec
51.323 + //
51.324 + //
51.325 + // / G_USEC_PER_SEC );
51.326 +
51.327 + if (NULL == date) {
51.328 + gmyth_debug
51.329 + ("GMythUtil: GDate *gmyth_util_time_val_to_date (GTimeVal* time) - converter error!\n");
51.330 + return NULL;
51.331 + }
51.332 +
51.333 + if (NULL == localtime_r(&time_micros, date)) {
51.334 + gmyth_debug("gmyth_util_time_to_isoformat convertion error!\n");
51.335 + return NULL;
51.336 + }
51.337 +
51.338 + gmyth_debug("Converted from GTimeVal == %s to GDate", asctime(date));
51.339 +
51.340 + return date;
51.341 +}
51.342 +
51.343 +/** Converts a GString in the following format
51.344 + * (e.g. 2006-07-20 09:56:41) to a time_t struct.
51.345 + *
51.346 + * @param time_str the string to be converted
51.347 + * @return time_t the time converted value
51.348 + */
51.349 +GTimeVal *
51.350 +gmyth_util_string_to_time_val_fmt(const gchar * fmt_string,
51.351 + const gchar * time_str)
51.352 +{
51.353 + GTimeVal *time = g_new0(GTimeVal, 1);
51.354 + struct tm *tm_time = NULL;
51.355 + time_t time_micros;
51.356 + gchar *result;
51.357 +
51.358 + gmyth_debug("[%s] time_str = %s. [%s]", time_str, time_str != NULL ?
51.359 + time_str : "[time string is NULL!]", time_str);
51.360 +
51.361 + if (NULL == time_str) {
51.362 + gmyth_debug("GMythUtil: isoformat_to_time converter error!\n");
51.363 + return NULL;
51.364 + }
51.365 +
51.366 + tm_time = g_malloc0(sizeof(struct tm));
51.367 +
51.368 + /*
51.369 + * we first check the return of strftime to allocate a buffer of the
51.370 + * correct size
51.371 + */
51.372 + result = strptime(time_str, "%Y-%m-%dT%H:%M:%S", tm_time);
51.373 + if (NULL == result) {
51.374 + /*
51.375 + * we first check the return of strftime to allocate a buffer of
51.376 + * the correct size
51.377 + */
51.378 + result = strptime(time_str, "%Y-%m-%dT%H:%M:%SZ", tm_time);
51.379 + if (NULL == result) {
51.380 + /*
51.381 + * we first check the return of strftime to allocate a buffer
51.382 + * of the correct size
51.383 + */
51.384 + result = strptime(time_str, "%Y-%m-%d %H:%M:%S", tm_time);
51.385 + if (NULL == result) {
51.386 + result = strptime(time_str, "%Y-%m-%dT%H:%M", tm_time);
51.387 + if (NULL == result) {
51.388 + gmyth_debug("Dateline (ISO result): %s", result);
51.389 + g_free(tm_time);
51.390 + return NULL;
51.391 + // goto done;
51.392 + }
51.393 + }
51.394 + }
51.395 + }
51.396 +
51.397 + time_micros = mktime(tm_time);
51.398 +
51.399 + time->tv_sec = time_micros; // + (gint)( time_val->tv_usec /
51.400 + // G_USEC_PER_SEC );
51.401 +
51.402 + gmyth_debug("After mktime call... = %s", asctime(tm_time));
51.403 +
51.404 + g_free(tm_time);
51.405 +
51.406 + return time;
51.407 +}
51.408 +
51.409 +/** Converts a GString in the following format
51.410 + * (e.g. 2006-07-20 09:56:41) to a time_t struct.
51.411 + *
51.412 + * @param time_str the string to be converted
51.413 + * @return time_t the time converted value
51.414 + */
51.415 +GTimeVal *
51.416 +gmyth_util_string_to_time_val(const gchar * time_str)
51.417 +{
51.418 + GTimeVal *time =
51.419 + gmyth_util_string_to_time_val_fmt("%Y-%m-%d %H:%M:%S", time_str);
51.420 +
51.421 + return time;
51.422 +}
51.423 +
51.424 +/**
51.425 + * Checks if the given remote file exists.
51.426 + *
51.427 + * @param backend_info The GMythBackendInfo instance.
51.428 + * @param filename The file name of the remote file.
51.429 + *
51.430 + * @return <code>true</code>, if the remote file exists.
51.431 + */
51.432 +gboolean
51.433 +gmyth_util_file_exists(GMythBackendInfo * backend_info,
51.434 + const gchar * filename)
51.435 +{
51.436 + GMythSocket *socket;
51.437 + gboolean res = FALSE;
51.438 +
51.439 + gmyth_debug("Check if file %s exists", filename);
51.440 +
51.441 + g_return_val_if_fail(backend_info != NULL, FALSE);
51.442 + g_return_val_if_fail(filename != NULL, FALSE);
51.443 +
51.444 + socket = gmyth_backend_info_get_connected_socket (backend_info);
51.445 + if (socket != NULL) {
51.446 + res = gmyth_util_file_exists_from_socket (socket, filename);
51.447 + g_object_unref(socket);
51.448 + }
51.449 + return res;
51.450 +}
51.451 +
51.452 +gboolean
51.453 +gmyth_util_file_exists_from_socket (GMythSocket *sock,
51.454 + const gchar *filename)
51.455 +{
51.456 + gboolean res = FALSE;
51.457 + gint length = 0;
51.458 + GMythStringList *slist;
51.459 + GMythProgramInfo *program = NULL;
51.460 +
51.461 + program = gmyth_program_info_new();
51.462 + program->pathname = g_string_new(filename);
51.463 +
51.464 + slist = gmyth_string_list_new();
51.465 + gmyth_string_list_append_char_array(slist, "QUERY_CHECKFILE");
51.466 + gmyth_program_info_to_string_list(program, slist);
51.467 +
51.468 + length = gmyth_socket_sendreceive_stringlist (sock, slist);
51.469 + if (length > 0)
51.470 + res = (gmyth_string_list_get_int(slist, 0) == 1);
51.471 +
51.472 + g_object_unref(program);
51.473 + g_object_unref(slist);
51.474 +
51.475 + return res;
51.476 +}
51.477 +
51.478 +gboolean
51.479 +gmyth_util_get_backend_details (GMythSocket *sock, GMythBackendDetails **details)
51.480 +{
51.481 + gboolean res = FALSE;
51.482 + gint length = 0;
51.483 + GMythStringList *slist;
51.484 +
51.485 + slist = gmyth_string_list_new();
51.486 + gmyth_string_list_append_char_array(slist, "QUERY_FREE_SPACE");
51.487 +
51.488 + length = gmyth_socket_sendreceive_stringlist (sock, slist);
51.489 + if (length >= 8) {
51.490 + *details = g_new0 (GMythBackendDetails, 1);
51.491 + (*details)->total_space = gmyth_string_list_get_uint64 (slist, 4) * 1024;
51.492 + (*details)->used_space = gmyth_string_list_get_uint64 (slist, 6) * 1024;
51.493 + res = TRUE;
51.494 + }
51.495 +
51.496 + g_object_unref(slist);
51.497 +
51.498 + return res;
51.499 +}
51.500 +
51.501 +void
51.502 +gmyth_util_backend_details_free (GMythBackendDetails *details)
51.503 +{
51.504 + g_free (details);
51.505 +}
51.506 +
51.507 +
51.508 +/**
51.509 + * Checks if the given remote file exists, and gets its remote directory.
51.510 + *
51.511 + * @param backend_info The GMythBackendInfo instance.
51.512 + * @param filename The file name of the remote file.
51.513 + * @param current_dir String pointer to the directory where the remote file is stored.
51.514 + *
51.515 + * @return <code>true</code>, if the remote file exists.
51.516 + */
51.517 +gboolean
51.518 +gmyth_util_file_exists_and_get_remote_dir(GMythBackendInfo * backend_info,
51.519 + const gchar * filename,
51.520 + gchar ** current_dir)
51.521 +{
51.522 + GMythSocket *socket;
51.523 + gboolean res;
51.524 +
51.525 + *current_dir = NULL;
51.526 +
51.527 + socket = gmyth_socket_new();
51.528 + res = gmyth_socket_connect_to_backend(socket, backend_info->hostname,
51.529 + backend_info->port, TRUE);
51.530 +
51.531 + if (res == TRUE) {
51.532 + GMythStringList *slist;
51.533 + GMythProgramInfo *program = NULL;
51.534 +
51.535 + program = gmyth_program_info_new();
51.536 + program->pathname = g_string_new(filename);
51.537 +
51.538 + slist = gmyth_string_list_new();
51.539 + gmyth_string_list_append_char_array(slist, "QUERY_CHECKFILE");
51.540 +
51.541 + gmyth_program_info_to_string_list(program, slist);
51.542 +
51.543 + gmyth_socket_sendreceive_stringlist(socket, slist);
51.544 +
51.545 + res = (gmyth_string_list_get_int(slist, 0) == 1);
51.546 +
51.547 + if ((gmyth_string_list_length(slist) > 1) &&
51.548 + gmyth_string_list_get_char_array(slist, 1) != NULL)
51.549 + *current_dir =
51.550 + g_strdup(gmyth_string_list_get_char_array(slist, 1));
51.551 +
51.552 + if (*current_dir != NULL)
51.553 + gmyth_debug("Current directory = %s.", (*current_dir != NULL)
51.554 + ? *current_dir : "[directory not found]");
51.555 +
51.556 + g_object_unref(program);
51.557 +
51.558 + g_object_unref(slist);
51.559 +
51.560 + gmyth_socket_close_connection(socket);
51.561 + }
51.562 + g_object_unref(socket);
51.563 + return res;
51.564 +}
51.565 +
51.566 +/**
51.567 + * Creates a file name to a possible existing remote file,
51.568 + * based on some fields of the LiveTV/recorded program info.
51.569 + *
51.570 + * @param chan_id The channel ID number.
51.571 + * @param start_time The start time of the recording.
51.572 + *
51.573 + * @return The string representing the file name.
51.574 + */
51.575 +gchar *
51.576 +gmyth_util_create_filename(const gint chan_id, const GTimeVal * start_time)
51.577 +{
51.578 + gchar *basename = NULL;
51.579 +
51.580 + g_return_val_if_fail(start_time != NULL, NULL);
51.581 +
51.582 + gchar *isodate =
51.583 + gmyth_util_time_to_isoformat_from_time_val_fmt("%Y%m%d%H%M%S",
51.584 + start_time);
51.585 +
51.586 + basename = g_strdup_printf("%d_%s", chan_id, isodate);
51.587 +
51.588 + gmyth_debug("Basename (from chan_id and start_time): %s", basename);
51.589 +
51.590 + if (isodate)
51.591 + g_free(isodate);
51.592 +
51.593 + return basename;
51.594 +}
51.595 +
51.596 +/**
51.597 + * Gets the channel list.
51.598 + *
51.599 + * @param backend_info The GMythBackendInfo instance.
51.600 + *
51.601 + * @return a pointer to a GList with all the channels.
51.602 + */
51.603 +GList *
51.604 +gmyth_util_get_channel_list(GMythBackendInfo * backend_info)
51.605 +{
51.606 + GMythRecorder *recorder;
51.607 + GList *channel_list = NULL;
51.608 + gboolean res = FALSE;
51.609 +
51.610 + gmyth_debug("Gets channel list.");
51.611 +
51.612 + g_return_val_if_fail(backend_info != NULL, FALSE);
51.613 +
51.614 + recorder =
51.615 + gmyth_recorder_new(1,
51.616 + g_string_new(gmyth_backend_info_get_hostname
51.617 + (backend_info)),
51.618 + gmyth_backend_info_get_port(backend_info));
51.619 + res = gmyth_recorder_setup(recorder);
51.620 +
51.621 + if (res == TRUE) {
51.622 + // GList* channel_list = gmyth_recorder_get_channel_list( recorder
51.623 + //
51.624 + //
51.625 + // );
51.626 + gmyth_debug("Yeah, got channel list!!!");
51.627 + GList *ch = NULL;
51.628 + GMythChannelInfo *channel_info = NULL;
51.629 +
51.630 + for (ch = gmyth_recorder_get_channel_list(recorder); ch != NULL;) {
51.631 + channel_info = g_malloc0(sizeof(GMythChannelInfo));
51.632 + channel_info->channel_ID = 0;
51.633 + channel_info->channel_num =
51.634 + g_string_new(g_strdup((gchar *) ch->data));
51.635 + channel_info->channel_name = g_string_new("");
51.636 + gmyth_debug("Printing channel info... (%s)",
51.637 + channel_info->channel_num->str);
51.638 + channel_list =
51.639 + g_list_append(channel_list,
51.640 + g_memdup(channel_info,
51.641 + sizeof(GMythChannelInfo)));
51.642 +
51.643 + ch = g_list_next(ch);
51.644 +
51.645 + if (channel_info != NULL)
51.646 + g_free(channel_info);
51.647 + }
51.648 +
51.649 + } /* if */
51.650 + else {
51.651 + gmyth_debug("No, couldn't get the channel list!!!");
51.652 + }
51.653 +
51.654 + gmyth_debug("Got %d channels!!!", g_list_length(channel_list));
51.655 +
51.656 +
51.657 + g_object_unref(recorder);
51.658 +
51.659 + return channel_list;
51.660 +}
51.661 +
51.662 +/**
51.663 + * Gets all the recordings from remote encoder.
51.664 + *
51.665 + * @param backend_info The GMythBackendInfo instance.
51.666 + *
51.667 + * @return The program info's listage.
51.668 + */
51.669 +GSList *
51.670 +gmyth_util_get_all_recordings(GMythBackendInfo * backend_info)
51.671 +{
51.672 + GSList *program_list = NULL;
51.673 + GMythSocket *socket;
51.674 + gboolean res;
51.675 +
51.676 + socket = gmyth_socket_new();
51.677 + res = gmyth_socket_connect_to_backend(socket, backend_info->hostname,
51.678 + backend_info->port, TRUE);
51.679 +
51.680 + if (res == TRUE) {
51.681 + GMythStringList *slist = gmyth_string_list_new();
51.682 + guint pos = 0;
51.683 +
51.684 + gmyth_string_list_append_char_array(slist,
51.685 + "QUERY_RECORDINGS Play");
51.686 +
51.687 + gmyth_socket_sendreceive_stringlist(socket, slist);
51.688 +
51.689 + if (slist != NULL && (gmyth_string_list_length(slist) > 0)) {
51.690 + GMythProgramInfo *program = NULL;
51.691 +
51.692 + gmyth_debug("OK! Got the program list [size=%d].",
51.693 + gmyth_string_list_length(slist));
51.694 +
51.695 + do {
51.696 + program =
51.697 + gmyth_program_info_from_string_list_from_pos(slist,
51.698 + pos);
51.699 +
51.700 + if (program != NULL) {
51.701 + pos += 41;
51.702 +
51.703 + program_list = g_slist_append(program_list, program);
51.704 + } else
51.705 + break;
51.706 +
51.707 + }
51.708 + while (gmyth_string_list_length(slist) > pos);
51.709 +
51.710 + }
51.711 + /*
51.712 + * if
51.713 + */
51.714 + g_object_unref(slist);
51.715 +
51.716 + gmyth_socket_close_connection(socket);
51.717 + }
51.718 + g_object_unref(socket);
51.719 +
51.720 + return program_list;
51.721 +}
51.722 +
51.723 +/**
51.724 + * Checks if the given remote file exists, and gets its remote directory.
51.725 + *
51.726 + * @param backend_info The GMythBackendInfo instance.
51.727 + * @param channel The channel name of the program info.
51.728 + *
51.729 + * @return The requested program info.
51.730 + */
51.731 +GMythProgramInfo *
51.732 +gmyth_util_get_recording_from_channel(GMythBackendInfo * backend_info,
51.733 + const gchar * channel)
51.734 +{
51.735 + GSList *program_list = NULL;
51.736 + GMythProgramInfo *program = NULL;
51.737 +
51.738 + program_list = gmyth_util_get_all_recordings(backend_info);
51.739 +
51.740 + if (program_list != NULL && g_slist_length(program_list) > 0) {
51.741 + GMythProgramInfo *program = NULL;
51.742 + guint pos = 0;
51.743 +
51.744 + gmyth_debug("OK! Got the program list [size=%d].",
51.745 + g_slist_length(program_list));
51.746 +
51.747 + while (pos < g_slist_length(program_list)) {
51.748 + program =
51.749 + (GMythProgramInfo *) g_slist_nth_data(program_list, pos);
51.750 +
51.751 + if (program != NULL && program->channame != NULL &&
51.752 + g_ascii_strncasecmp(program->channame->str, channel,
51.753 + strlen(channel)) == 0) {
51.754 + break;
51.755 + }
51.756 +
51.757 + ++pos;
51.758 +
51.759 + } /* while */
51.760 +
51.761 + }
51.762 + /*
51.763 + * if
51.764 + */
51.765 + return program;
51.766 +}
51.767 +
51.768 +#if !GLIB_CHECK_VERSION (2, 10, 0)
51.769 +
51.770 +/*
51.771 + * Hacked from glib 2.10 <gtime.c>
51.772 + */
51.773 +
51.774 +static time_t
51.775 +mktime_utc(struct tm *tm)
51.776 +{
51.777 + time_t retval;
51.778 +
51.779 +#ifndef HAVE_TIMEGM
51.780 + static const gint days_before[] = {
51.781 + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
51.782 + };
51.783 +#endif
51.784 +
51.785 +#ifndef HAVE_TIMEGM
51.786 + if (tm->tm_mon < 0 || tm->tm_mon > 11)
51.787 + return (time_t) - 1;
51.788 +
51.789 + retval = (tm->tm_year - 70) * 365;
51.790 + retval += (tm->tm_year - 68) / 4;
51.791 + retval += days_before[tm->tm_mon] + tm->tm_mday - 1;
51.792 +
51.793 + if (tm->tm_year % 4 == 0 && tm->tm_mon < 2)
51.794 + retval -= 1;
51.795 +
51.796 + retval =
51.797 + ((((retval * 24) + tm->tm_hour) * 60) + tm->tm_min) * 60 +
51.798 + tm->tm_sec;
51.799 +#else
51.800 + retval = timegm(tm);
51.801 +#endif /* !HAVE_TIMEGM */
51.802 +
51.803 + return retval;
51.804 +}
51.805 +
51.806 +gboolean
51.807 +g_time_val_from_iso8601(const gchar * iso_date, GTimeVal * time_)
51.808 +{
51.809 + struct tm tm;
51.810 + long val;
51.811 +
51.812 + g_return_val_if_fail(iso_date != NULL, FALSE);
51.813 + g_return_val_if_fail(time_ != NULL, FALSE);
51.814 +
51.815 + val = strtoul(iso_date, (char **) &iso_date, 10);
51.816 + if (*iso_date == '-') {
51.817 + /*
51.818 + * YYYY-MM-DD
51.819 + */
51.820 + tm.tm_year = val - 1900;
51.821 + iso_date++;
51.822 + tm.tm_mon = strtoul(iso_date, (char **) &iso_date, 10) - 1;
51.823 +
51.824 + if (*iso_date++ != '-')
51.825 + return FALSE;
51.826 +
51.827 + tm.tm_mday = strtoul(iso_date, (char **) &iso_date, 10);
51.828 + } else {
51.829 + /*
51.830 + * YYYYMMDD
51.831 + */
51.832 + tm.tm_mday = val % 100;
51.833 + tm.tm_mon = (val % 10000) / 100 - 1;
51.834 + tm.tm_year = val / 10000 - 1900;
51.835 + }
51.836 +
51.837 + if (*iso_date++ != 'T')
51.838 + return FALSE;
51.839 +
51.840 + val = strtoul(iso_date, (char **) &iso_date, 10);
51.841 + if (*iso_date == ':') {
51.842 + /*
51.843 + * hh:mm:ss
51.844 + */
51.845 + tm.tm_hour = val;
51.846 + iso_date++;
51.847 + tm.tm_min = strtoul(iso_date, (char **) &iso_date, 10);
51.848 +
51.849 + if (*iso_date++ != ':')
51.850 + return FALSE;
51.851 +
51.852 + tm.tm_sec = strtoul(iso_date, (char **) &iso_date, 10);
51.853 + } else {
51.854 + /*
51.855 + * hhmmss
51.856 + */
51.857 + tm.tm_sec = val % 100;
51.858 + tm.tm_min = (val % 10000) / 100;
51.859 + tm.tm_hour = val / 10000;
51.860 + }
51.861 +
51.862 + time_->tv_sec = mktime_utc(&tm);
51.863 + time_->tv_usec = 1;
51.864 +
51.865 + if (*iso_date == '.')
51.866 + time_->tv_usec = strtoul(iso_date + 1, (char **) &iso_date, 10);
51.867 +
51.868 + if (*iso_date == '+' || *iso_date == '-') {
51.869 + gint sign = (*iso_date == '+') ? -1 : 1;
51.870 +
51.871 + val = 60 * strtoul(iso_date + 1, (char **) &iso_date, 10);
51.872 +
51.873 + if (*iso_date == ':')
51.874 + val = 60 * val + strtoul(iso_date + 1, NULL, 10);
51.875 + else
51.876 + val = 60 * (val / 100) + (val % 100);
51.877 +
51.878 + time_->tv_sec += (time_t) (val * sign);
51.879 + }
51.880 +
51.881 + return TRUE;
51.882 +}
51.883 +
51.884 +
51.885 +gchar *
51.886 +g_time_val_to_iso8601(GTimeVal * time_)
51.887 +{
51.888 + gchar *retval;
51.889 +
51.890 + g_return_val_if_fail(time_->tv_usec >= 0
51.891 + && time_->tv_usec < G_USEC_PER_SEC, NULL);
51.892 +
51.893 +#define ISO_8601_LEN 21
51.894 +#define ISO_8601_FORMAT "%Y-%m-%dT%H:%M:%SZ"
51.895 + retval = g_new0(gchar, ISO_8601_LEN + 1);
51.896 +
51.897 + strftime(retval, ISO_8601_LEN, ISO_8601_FORMAT,
51.898 + gmtime(&(time_->tv_sec)));
51.899 +
51.900 + return retval;
51.901 +}
51.902 +
51.903 +
51.904 +/*
51.905 + * Hacked from glib 2.10 <gdate.c>
51.906 + */
51.907 +
51.908 +void
51.909 +g_date_set_time_t(GDate * date, time_t timet)
51.910 +{
51.911 + struct tm tm;
51.912 +
51.913 + g_return_if_fail(date != NULL);
51.914 +
51.915 +#ifdef HAVE_LOCALTIME_R
51.916 + localtime_r(&timet, &tm);
51.917 +#else
51.918 + {
51.919 + struct tm *ptm = localtime(&timet);
51.920 +
51.921 + if (ptm == NULL) {
51.922 + /*
51.923 + * Happens at least in Microsoft's C library if you pass a
51.924 + * negative time_t. Use 2000-01-01 as default date.
51.925 + */
51.926 +#ifndef G_DISABLE_CHECKS
51.927 + g_return_if_fail_warning(G_LOG_DOMAIN, "g_date_set_time",
51.928 + "ptm != NULL");
51.929 +#endif
51.930 +
51.931 + tm.tm_mon = 0;
51.932 + tm.tm_mday = 1;
51.933 + tm.tm_year = 100;
51.934 + } else
51.935 + memcpy((void *) &tm, (void *) ptm, sizeof(struct tm));
51.936 + }
51.937 +#endif
51.938 +
51.939 + date->julian = FALSE;
51.940 +
51.941 + date->month = tm.tm_mon + 1;
51.942 + date->day = tm.tm_mday;
51.943 + date->year = tm.tm_year + 1900;
51.944 +
51.945 + g_return_if_fail(g_date_valid_dmy(date->day, date->month, date->year));
51.946 +
51.947 + date->dmy = TRUE;
51.948 +}
51.949 +
51.950 +
51.951 +void
51.952 +g_date_set_time_val(GDate * date, GTimeVal * timeval)
51.953 +{
51.954 + g_date_set_time_t(date, (time_t) timeval->tv_sec);
51.955 +}
51.956 +
51.957 +
51.958 +
51.959 +
51.960 +#endif
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
52.2 +++ b/gmyth/gmyth/gmyth_util.h Mon Feb 25 17:51:43 2008 +0000
52.3 @@ -0,0 +1,82 @@
52.4 +/**
52.5 + * GMyth Library
52.6 + *
52.7 + * @file gmyth/gmyth_util.h
52.8 + *
52.9 + * @brief <p> This component provides utility functions
52.10 + * (dealing with dates, time, string formatting, etc.).
52.11 + *
52.12 + * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
52.13 + * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
52.14 + * @author Rosfran Borges <rosfran.borges@indt.org.br>
52.15 + *
52.16 + *
52.17 + * This program is free software; you can redistribute it and/or modify
52.18 + * it under the terms of the GNU Lesser General Public License as published by
52.19 + * the Free Software Foundation; either version 2 of the License, or
52.20 + * (at your option) any later version.
52.21 + *
52.22 + * This program is distributed in the hope that it will be useful,
52.23 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
52.24 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
52.25 + * GNU General Public License for more details.
52.26 + *
52.27 + * You should have received a copy of the GNU Lesser General Public License
52.28 + * along with this program; if not, write to the Free Software
52.29 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
52.30 + */
52.31 +
52.32 +#ifndef GMYTH_UTIL_H_
52.33 +#define GMYTH_UTIL_H_
52.34 +
52.35 +#include <time.h>
52.36 +#include <glib.h>
52.37 +
52.38 +#include "gmyth_stringlist.h"
52.39 +#include "gmyth_backendinfo.h"
52.40 +#include "gmyth_programinfo.h"
52.41 +
52.42 +G_BEGIN_DECLS
52.43 +
52.44 +typedef struct {
52.45 + guint64 total_space;
52.46 + guint64 used_space;
52.47 +} GMythBackendDetails;
52.48 +
52.49 +
52.50 +GString* gmyth_util_time_to_isoformat (time_t time_value);
52.51 +GString* gmyth_util_time_to_string (time_t time_value);
52.52 +time_t gmyth_util_string_to_time (GString *time_str);
52.53 +gchar* gmyth_util_time_to_isoformat_from_time_val_fmt
52.54 + (const gchar *fmt_string,
52.55 + const GTimeVal *time_val);
52.56 +GTimeVal* gmyth_util_string_to_time_val_fmt (const gchar *fmt_string,
52.57 + const gchar *time_str);
52.58 +GTimeVal* gmyth_util_string_to_time_val (const gchar *time_str);
52.59 +gchar* gmyth_util_time_to_isoformat_from_time_val (const GTimeVal *time);
52.60 +gchar* gmyth_util_time_to_mythformat_from_time_val (const GTimeVal *time);
52.61 +gchar* gmyth_util_time_to_string_only_date (const GTimeVal *time);
52.62 +gchar* gmyth_util_time_to_string_only_time (const GTimeVal *time);
52.63 +gchar* gmyth_util_time_to_string_from_time_val (const GTimeVal *time_val);
52.64 +struct tm* gmyth_util_time_val_to_date (const GTimeVal * time);
52.65 +
52.66 +gboolean gmyth_util_get_backend_details (GMythSocket *sock, GMythBackendDetails **details);
52.67 +void gmyth_util_backend_details_free (GMythBackendDetails *details);
52.68 +
52.69 +gboolean gmyth_util_file_exists (GMythBackendInfo *backend_info,
52.70 + const gchar * filename);
52.71 +gboolean gmyth_util_file_exists_from_socket (GMythSocket *sock,
52.72 + const gchar *filename);
52.73 +gboolean gmyth_util_file_exists_and_get_remote_dir (GMythBackendInfo *backend_info,
52.74 + const gchar *filename,
52.75 + gchar **current_dir);
52.76 +gchar* gmyth_util_create_filename (const gint chan_id,
52.77 + const GTimeVal * start_time);
52.78 +GList* gmyth_util_get_channel_list (GMythBackendInfo *backend_info);
52.79 +GSList* gmyth_util_get_all_recordings (GMythBackendInfo *backend_info);
52.80 +GMythProgramInfo*
52.81 + gmyth_util_get_recording_from_channel (GMythBackendInfo *backend_info,
52.82 + const gchar *channel);
52.83 +
52.84 +G_END_DECLS
52.85 +#endif /* GMYTH_UTIL_H_ */
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
53.2 +++ b/gmyth/gmyth/gmyth_vlc.c Mon Feb 25 17:51:43 2008 +0000
53.3 @@ -0,0 +1,290 @@
53.4 +/**
53.5 + * GMyth Library
53.6 + *
53.7 + * @file gmyth/gmyth_vlc.c
53.8 + *
53.9 + * @brief <p> GMythVLC library provides functions that
53.10 + * interact with a VLC server running telnet interface.
53.11 + *
53.12 + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
53.13 + * @author Artur Duque de Souza <artur.souza@indt.org.br>
53.14 + *
53.15 + *
53.16 + * This program is free software; you can redistribute it and/or modify
53.17 + * it under the terms of the GNU Lesser General Public License as published by
53.18 + * the Free Software Foundation; either version 2 of the License, or
53.19 + * (at your option) any later version.
53.20 + *
53.21 + * This program is distributed in the hope that it will be useful,
53.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
53.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
53.24 + * GNU General Public License for more details.
53.25 + *
53.26 + * You should have received a copy of the GNU Lesser General Public License
53.27 + * along with this program; if not, write to the Free Software
53.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
53.29 + */
53.30 +
53.31 +#ifdef HAVE_CONFIG_H
53.32 +#include "config.h"
53.33 +#endif
53.34 +
53.35 +#include <assert.h>
53.36 +
53.37 +#include "gmyth_vlc.h"
53.38 +#include "gmyth_debug.h"
53.39 +#include "gmyth_socket.h"
53.40 +
53.41 +/*
53.42 + * static functions
53.43 + */
53.44 +static int _socket_send(int socket, gchar * msg);
53.45 +static int _socket_recv(int socket, gchar * buf);
53.46 +
53.47 +/** Primitive function to send a message through the socket
53.48 + *
53.49 + * @param socket
53.50 + * @param msg the message itself
53.51 + * @return 0 if success
53.52 + */
53.53 +static int
53.54 +_socket_send(int socket, gchar * msg)
53.55 +{
53.56 + size_t size = strlen(msg) + 2; // (\n + \0)
53.57 + gchar *final = (gchar *) g_malloc0(sizeof(gchar) * size);
53.58 +
53.59 + g_snprintf(final, size, "%s\n", msg);
53.60 +
53.61 + if (send(socket, final, strlen(final), 0) == -1)
53.62 + perror("GMyth_VLC: send error");
53.63 +
53.64 + g_free(final);
53.65 + return 0;
53.66 +}
53.67 +
53.68 +
53.69 +/** Primitive function to receive a message through the socket
53.70 + *
53.71 + * @param socket
53.72 + * @param buf Buffer to put the message
53.73 + * @return 0 if success
53.74 + */
53.75 +static int
53.76 +_socket_recv(int socket, gchar * buf)
53.77 +{
53.78 + int numbytes = 0;
53.79 +
53.80 + if ((numbytes = recv(socket, buf, BUFFER - 1, 0)) == -1) {
53.81 + perror("GMyth_VLC: recv error");
53.82 + return -1;
53.83 + }
53.84 +
53.85 + buf[numbytes - 1] = '\0';
53.86 + return numbytes;
53.87 +}
53.88 +
53.89 +
53.90 +/** Function that adds options to the output media
53.91 + *
53.92 + * @param vlc structure with options for vlc
53.93 + * @param output the number of the output media
53.94 + * @param kind the type of option we'll change
53.95 + * @param the params for the option
53.96 + * @return 0 if success
53.97 + */
53.98 +int
53.99 +gmyth_vlc_setup_output(GMythVlc * vlc, int output, gchar * kind,
53.100 + gchar * opts)
53.101 +{
53.102 + int ret;
53.103 +
53.104 + size_t size = strlen(opts) + 25;
53.105 + gchar *msg = g_malloc0(sizeof(gchar) * size);
53.106 +
53.107 + g_snprintf(msg, size, "setup output%d %s %s", output, kind, opts);
53.108 +
53.109 + ret = _socket_send(vlc->sockfd, msg);
53.110 +
53.111 + g_free(msg);
53.112 + return ret;
53.113 +}
53.114 +
53.115 +
53.116 +/** Function to clean the playlist
53.117 + *
53.118 + * @param vlc structure with options for vlc
53.119 + * @param output the number of the output media
53.120 + * @param file the file we want to insert in the playlist
53.121 + * @return 0 if success
53.122 + */
53.123 +int
53.124 +gmyth_vlc_clean_playlist(GMythVlc * vlc)
53.125 +{
53.126 + return _socket_send(vlc->sockfd, "del all");
53.127 +}
53.128 +
53.129 +
53.130 +/** Function to control the playlist
53.131 + *
53.132 + * @param vlc structure with options for vlc
53.133 + * @param output the number of the output media
53.134 + * @param command play, stop or pause(just for vod)
53.135 + * @return 0 if success
53.136 + */
53.137 +int
53.138 +gmyth_vlc_control_input(GMythVlc * vlc, int output, gchar * command)
53.139 +{
53.140 + size_t size = 25;
53.141 + gchar *msg = g_malloc0(sizeof(gchar) * size);
53.142 +
53.143 + g_snprintf(msg, size, "control output%d %s", output, command);
53.144 +
53.145 + int ret = _socket_send(vlc->sockfd, msg);
53.146 +
53.147 + g_free(msg);
53.148 + return ret;
53.149 +}
53.150 +
53.151 +
53.152 +
53.153 +/** Function to insert an item in the playlist
53.154 + *
53.155 + * @param vlc structure with options for vlc
53.156 + * @param output the number of the output media
53.157 + * @param file the file we want to insert in the playlist
53.158 + * @return 0 if success
53.159 + */
53.160 +int
53.161 +gmyth_vlc_create_input(GMythVlc * vlc, int output, gchar * file)
53.162 +{
53.163 + return gmyth_vlc_setup_output(vlc, output, "input", file);
53.164 +}
53.165 +
53.166 +
53.167 +/** Function to create a channel in vlc
53.168 + *
53.169 + * @param vlc structure with options for vlc
53.170 + * @param type the type of channel (broadcast, vod...)
53.171 + * @param port
53.172 + * @return 0 if success
53.173 + */
53.174 +int
53.175 +gmyth_vlc_create_channel(GMythVlc * vlc, gchar * type, int port,
53.176 + int vcodec)
53.177 +{
53.178 + int ret;
53.179 + size_t size = 40;
53.180 + gchar *msg = (gchar *) g_malloc0(sizeof(gchar) * size);
53.181 +
53.182 + g_snprintf(msg, size, "new output%d %s enabled loop", vlc->n_outputs,
53.183 + type);
53.184 +
53.185 + ret = _socket_send(vlc->sockfd, msg);
53.186 +
53.187 + if (ret > -1) {
53.188 + gmyth_vlc_setup_output(vlc, vlc->n_outputs, "option",
53.189 + "sout-keep=1");
53.190 +
53.191 + g_free(msg);
53.192 + size = 256;
53.193 + msg = (gchar *) g_malloc0(sizeof(gchar) * size);
53.194 +
53.195 + if (vcodec == MPEG1)
53.196 + // Best transcode option for N800 (MP1V)
53.197 + g_snprintf(msg, size, "#transcode{vcodec=mp1v,vb=384,"
53.198 + "fps=25.0,scale=1,acodec=mpga,"
53.199 + "ab=64,channels=1}:duplicate{dst="
53.200 + "std{access=http,mux=mpeg1,dst=" ":%d}}", port);
53.201 + else
53.202 + // Best transcode option for N800 (THEORA)
53.203 + g_snprintf(msg, size, "#transcode{vcodec=theo,vb=384,"
53.204 + "fps=25.0,scale=1,acodec=vorb,"
53.205 + "ab=64,channels=1}:duplicate{dst="
53.206 + "std{access=http,mux=ogg,dst=" ":%d}}", port);
53.207 +
53.208 + ret = gmyth_vlc_setup_output(vlc, vlc->n_outputs, "output", msg);
53.209 +
53.210 + vlc->n_outputs++;
53.211 + }
53.212 +
53.213 + g_free(msg);
53.214 +
53.215 + return ret;
53.216 +}
53.217 +
53.218 +
53.219 +/** Function to connect to vlc on the backend
53.220 + *
53.221 + * @param vlc structure with options for vlc
53.222 + * @param backend_info infos about the backend
53.223 + * @param passwd the password for telnet interface
53.224 + * @return 0 if success
53.225 + */
53.226 +int
53.227 +gmyth_vlc_connect(GMythVlc * vlc, GMythBackendInfo * backend_info,
53.228 + gchar * passwd, int port)
53.229 +{
53.230 + int numbytes;
53.231 +
53.232 + if ((vlc->he = gethostbyname(backend_info->hostname)) == NULL) {
53.233 + herror("GMyth_VLC: gethostbyname error");
53.234 + return -1;
53.235 + }
53.236 +
53.237 + if ((vlc->sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
53.238 + perror("GMyth_VLC: socket error");
53.239 + return -1;
53.240 + }
53.241 + // Socket properties
53.242 + vlc->their_addr.sin_family = AF_INET;
53.243 + vlc->their_addr.sin_port = htons(port);
53.244 + vlc->their_addr.sin_addr = *((struct in_addr *) vlc->he->h_addr);
53.245 + memset(&(vlc->their_addr.sin_zero), '\0', 8);
53.246 +
53.247 + if (connect(vlc->sockfd, (struct sockaddr *) &(vlc->their_addr),
53.248 + sizeof(struct sockaddr)) == -1) {
53.249 + perror("GMyth_VLC: connect error. Check VLC's telnet interface");
53.250 + return -1;
53.251 + }
53.252 + // Receive the Password's Prompt
53.253 + numbytes = _socket_recv(vlc->sockfd, vlc->buf);
53.254 +
53.255 + // Send the Password. We don't have to
53.256 + // care about passwords being sent in plain text
53.257 + // because telnet protocol does it.
53.258 + _socket_send(vlc->sockfd, passwd);
53.259 +
53.260 + // Receive the Welcome msg
53.261 + numbytes = _socket_recv(vlc->sockfd, vlc->buf);
53.262 + if (numbytes > -1)
53.263 + if (strncmp(vlc->buf, "\r\nWrong password.", 17) == 0) {
53.264 + perror("Gmyth_VLC: passwd error. Check your passwd");
53.265 + return -2;
53.266 + }
53.267 +
53.268 +
53.269 + return 0;
53.270 +}
53.271 +
53.272 +
53.273 +/** Function to disconnect from vlc
53.274 + *
53.275 + * @param vlc structure with options for vlc
53.276 + * @param backend_info infos about the backend
53.277 + * @return 0 if success
53.278 + */
53.279 +int
53.280 +gmyth_vlc_disconnect(GMythVlc * vlc)
53.281 +{
53.282 +
53.283 + int ret;
53.284 +
53.285 + ret = gmyth_vlc_clean_playlist(vlc);
53.286 +
53.287 + if (ret > -1) {
53.288 + vlc->n_outputs = 0;
53.289 + vlc->n_inputs = 0;
53.290 + }
53.291 +
53.292 + return close(vlc->sockfd);
53.293 +}
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
54.2 +++ b/gmyth/gmyth/gmyth_vlc.h Mon Feb 25 17:51:43 2008 +0000
54.3 @@ -0,0 +1,96 @@
54.4 +/**
54.5 + * GMyth Library
54.6 + *
54.7 + * @file gmyth/gmyth_vlc.h
54.8 + *
54.9 + * @brief <p> GMythVLC library provides functions that
54.10 + * interact with a VLC server running telnet interface.
54.11 + *
54.12 + * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
54.13 + * @author Artur Duque de Souza <artur.souza@indt.org.br>
54.14 + *
54.15 + *
54.16 + * This program is free software; you can redistribute it and/or modify
54.17 + * it under the terms of the GNU Lesser General Public License as published by
54.18 + * the Free Software Foundation; either version 2 of the License, or
54.19 + * (at your option) any later version.
54.20 + *
54.21 + * This program is distributed in the hope that it will be useful,
54.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
54.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
54.24 + * GNU General Public License for more details.
54.25 + *
54.26 + * You should have received a copy of the GNU Lesser General Public License
54.27 + * along with this program; if not, write to the Free Software
54.28 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
54.29 + */
54.30 +
54.31 +#ifndef __GMYTH_VLC_H__
54.32 +#define __GMYTH_VLC_H__
54.33 +
54.34 +#include <glib-object.h>
54.35 +
54.36 +#include <glib.h>
54.37 +#include <stdio.h>
54.38 +#include <stdlib.h>
54.39 +#include <unistd.h>
54.40 +#include <errno.h>
54.41 +#include <string.h>
54.42 +#include <netdb.h>
54.43 +#include <sys/types.h>
54.44 +#include <netinet/in.h>
54.45 +#include <sys/socket.h>
54.46 +
54.47 +
54.48 +#include "gmyth_backendinfo.h"
54.49 +#include "gmyth_util.h"
54.50 +
54.51 +G_BEGIN_DECLS
54.52 +#define VLC_TELNET_PORT 4212
54.53 +#define BUFFER 512
54.54 +#define MPEG1 0
54.55 +#define THEORA 1
54.56 +typedef struct _GMythVlc GMythVlc;
54.57 +
54.58 +struct _GMythVlc {
54.59 + int sockfd;
54.60 +
54.61 + // Number of outputs used
54.62 + int n_outputs;
54.63 +
54.64 + // Number of inputs
54.65 + int n_inputs;
54.66 +
54.67 + // Socket vars
54.68 + struct hostent *he;
54.69 + struct sockaddr_in their_addr;
54.70 +
54.71 + char buf[BUFFER];
54.72 +};
54.73 +
54.74 +
54.75 +
54.76 +int gmyth_vlc_setup_output(GMythVlc * vlc, int output,
54.77 + gchar * kind, gchar * opts);
54.78 +
54.79 +
54.80 +int gmyth_vlc_clean_playlist(GMythVlc * vlc);
54.81 +
54.82 +
54.83 +int gmyth_vlc_control_input(GMythVlc * vlc, int output,
54.84 + gchar * command);
54.85 +
54.86 +int gmyth_vlc_create_input(GMythVlc * vlc, int output,
54.87 + gchar * file);
54.88 +
54.89 +int gmyth_vlc_create_channel(GMythVlc * vlc, gchar * type,
54.90 + int port, int vcodec);
54.91 +
54.92 +int gmyth_vlc_connect(GMythVlc * vlc,
54.93 + GMythBackendInfo * backend_info,
54.94 + gchar * passwd, int port);
54.95 +
54.96 +int gmyth_vlc_disconnect(GMythVlc * vlc);
54.97 +
54.98 +G_END_DECLS
54.99 +#endif /* __GMYTH_VLC_H__ */
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
55.2 +++ b/gmyth/gmyth/gst-indent.sh Mon Feb 25 17:51:43 2008 +0000
55.3 @@ -0,0 +1,16 @@
55.4 +#!/bin/sh
55.5 +indent \
55.6 + --braces-on-if-line \
55.7 + --blank-lines-after-declarations \
55.8 + --case-brace-indentation0 \
55.9 + --case-indentation4 \
55.10 + --braces-after-struct-decl-line \
55.11 + --line-length80 \
55.12 + --no-tabs \
55.13 + --cuddle-else \
55.14 + --dont-line-up-parentheses \
55.15 + --continuation-indentation4 \
55.16 + --honour-newlines \
55.17 + --tab-size4 \
55.18 + --indent-level4 \
55.19 + $*
56.1 --- a/gmyth/samples/Makefile.am Mon Feb 25 17:45:36 2008 +0000
56.2 +++ b/gmyth/samples/Makefile.am Mon Feb 25 17:51:43 2008 +0000
56.3 @@ -7,7 +7,7 @@
56.4 gmyth_ls.c
56.5
56.6 LDADD = \
56.7 - $(top_builddir)/src/libgmyth.la
56.8 + $(top_builddir)/gmyth/libgmyth.la
56.9
56.10 AM_CFLAGS = -g
56.11
56.12 @@ -16,6 +16,6 @@
56.13
56.14 INCLUDES = \
56.15 -I$(top_srcdir) \
56.16 - -I$(top_srcdir)/src \
56.17 + -I$(top_srcdir)/gmyth \
56.18 $(GLIB_CFLAGS) \
56.19 $(GOBJECT_CFLAGS)
57.1 --- a/gmyth/src/Makefile.am Mon Feb 25 17:45:36 2008 +0000
57.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
57.3 @@ -1,98 +0,0 @@
57.4 -lib_LTLIBRARIES = libgmyth.la
57.5 -
57.6 -INCLUDES = -I$(top_srcdir)/src -I$(top_builddir)/src @GLIB_CFLAGS@ @GOBJECT_CFLAGS@
57.7 -
57.8 -BUILT_SOURCES = \
57.9 - gmyth_marshal.c \
57.10 - gmyth_marshal.h
57.11 -
57.12 -libgmyth_la_SOURCES = \
57.13 - gmyth_common.c \
57.14 - gmyth_debug.c \
57.15 - gmyth_epg.c \
57.16 - gmyth_recorder.c \
57.17 - gmyth_remote_util.c \
57.18 - gmyth_tvchain.c \
57.19 - gmyth_scheduler.c \
57.20 - gmyth_util.c \
57.21 - gmyth_query.c \
57.22 - gmyth_socket.c \
57.23 - gmyth_stringlist.c \
57.24 - gmyth_monitor_handler.c \
57.25 - gmyth_file_transfer.c \
57.26 - gmyth_livetv.c \
57.27 - gmyth_backendinfo.c \
57.28 - gmyth_programinfo.c \
57.29 - gmyth_uri.c \
57.30 - gmyth_http.c \
57.31 - gmyth_vlc.c \
57.32 - gmyth_jobqueue.c \
57.33 - gmyth_transcoder.c \
57.34 - gmyth_recprofile.c \
57.35 - gmyth_file.c \
57.36 - gmyth_file_local.c \
57.37 - $(BUILT_SOURCES)
57.38 -
57.39 -EXTRA_libgmyth_la_SOURCES = gmyth_marshal.list
57.40 -
57.41 -gmyth_marshal.h: gmyth_marshal.list
57.42 - glib-genmarshal --header --prefix=gmyth_marshal gmyth_marshal.list > gmyth_marshal.h.tmp
57.43 - mv gmyth_marshal.h.tmp gmyth_marshal.h
57.44 -
57.45 -gmyth_marshal.c: gmyth_marshal.list gmyth_marshal.h
57.46 - echo "#include \"glib-object.h\"" > gmyth_marshal.c.tmp
57.47 - echo "#include \"gmyth_marshal.h\"" >> gmyth_marshal.c.tmp
57.48 - glib-genmarshal --body --prefix=gmyth_marshal $(srcdir)/gmyth_marshal.list >> gmyth_marshal.c.tmp
57.49 - mv gmyth_marshal.c.tmp gmyth_marshal.c
57.50 -
57.51 -libgmyth_la_CFLAGS = \
57.52 - -DDATADIR=\"$(pkgdatadir)\" \
57.53 - $(GLIB_CFLAGS) \
57.54 - $(GOBJECT_CFLAGS) \
57.55 - $(GST_CFLAGS) \
57.56 - $(GSTBASE_CFLAGS) \
57.57 - $(GSTPLUGINSBASE_CFLAGS) \
57.58 - $(MYSQL_CFLAGS) \
57.59 - $(LIBXML_CFLAGS)
57.60 -
57.61 -libgmyth_la_LDFLAGS = \
57.62 - -export-dynamic \
57.63 - $(GLIB_CFLAGS) \
57.64 - $(GOBJECT_CFLAGS) \
57.65 - $(MYSQL_LIBS) \
57.66 - $(GST_LIBS) \
57.67 - $(GSTBASE_LIBS) \
57.68 - $(GSTPLUGINS_LIBS) \
57.69 - $(LIBXML_LIBS)
57.70 -
57.71 -libgmyth_includedir = \
57.72 - $(pkgincludedir)
57.73 -
57.74 -libgmyth_include_HEADERS = \
57.75 - gmyth.h \
57.76 - gmyth_common.h \
57.77 - gmyth_debug.h \
57.78 - gmyth_epg.h \
57.79 - gmyth_recorder.h \
57.80 - gmyth_scheduler.h \
57.81 - gmyth_tvchain.h \
57.82 - gmyth_util.h \
57.83 - gmyth_query.h \
57.84 - gmyth_socket.h \
57.85 - gmyth_remote_util.h \
57.86 - gmyth_stringlist.h \
57.87 - gmyth_monitor_handler.h \
57.88 - gmyth_file_transfer.h \
57.89 - gmyth_livetv.h \
57.90 - gmyth_backendinfo.h \
57.91 - gmyth_programinfo.h \
57.92 - gmyth_uri.h \
57.93 - gmyth_http.h \
57.94 - gmyth_vlc.h \
57.95 - gmyth_jobqueue.h \
57.96 - gmyth_transcoder.h \
57.97 - gmyth_recprofile.h \
57.98 - gmyth_file.h \
57.99 - gmyth_file_local.h
57.100 -
57.101 -CLEANFILES = $(BUILT_SOURCES)
58.1 --- a/gmyth/src/gmyth-indent.sh Mon Feb 25 17:45:36 2008 +0000
58.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
58.3 @@ -1,25 +0,0 @@
58.4 -#!/bin/sh
58.5 -indent \
58.6 - -gnu \
58.7 - -i4 \
58.8 - -l80 \
58.9 - -bfda \
58.10 - -nut \
58.11 - -pcs \
58.12 - -psl \
58.13 - -bli0 \
58.14 - -cs \
58.15 - -cli0 \
58.16 - -nbfda \
58.17 - -sai \
58.18 - -saw \
58.19 - -saf \
58.20 - -sbi4 \
58.21 - -npro \
58.22 - -nfca \
58.23 - -nsc \
58.24 - -ts4 \
58.25 - -prs \
58.26 - -bap \
58.27 - $*
58.28 -
59.1 --- a/gmyth/src/gmyth.h Mon Feb 25 17:45:36 2008 +0000
59.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
59.3 @@ -1,57 +0,0 @@
59.4 -/**
59.5 - * GMyth Library
59.6 - *
59.7 - * @file gmyth/gmyth.h
59.8 - *
59.9 - *
59.10 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
59.11 - * @author Renato Filho <renato.filho@indt.org.br>
59.12 - *
59.13 - *//*
59.14 - *
59.15 - * This program is free software; you can redistribute it and/or modify
59.16 - * it under the terms of the GNU Lesser General Public License as published by
59.17 - * the Free Software Foundation; either version 2 of the License, or
59.18 - * (at your option) any later version.
59.19 - *
59.20 - * This program is distributed in the hope that it will be useful,
59.21 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
59.22 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
59.23 - * GNU General Public License for more details.
59.24 - *
59.25 - * You should have received a copy of the GNU Lesser General Public License
59.26 - * along with this program; if not, write to the Free Software
59.27 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
59.28 - */
59.29 -
59.30 -
59.31 -
59.32 -#ifndef _GMYTH_H_
59.33 -#define _GMYTH_H_
59.34 -
59.35 -#include <gmyth/gmyth_backendinfo.h>
59.36 -#include <gmyth/gmyth_common.h>
59.37 -#include <gmyth/gmyth_debug.h>
59.38 -#include <gmyth/gmyth_epg.h>
59.39 -#include <gmyth/gmyth_file.h>
59.40 -#include <gmyth/gmyth_file_local.h>
59.41 -#include <gmyth/gmyth_file_transfer.h>
59.42 -#include <gmyth/gmyth_livetv.h>
59.43 -#include <gmyth/gmyth_monitor_handler.h>
59.44 -#include <gmyth/gmyth_programinfo.h>
59.45 -#include <gmyth/gmyth_query.h>
59.46 -#include <gmyth/gmyth_recorder.h>
59.47 -#include <gmyth/gmyth_remote_util.h>
59.48 -#include <gmyth/gmyth_scheduler.h>
59.49 -#include <gmyth/gmyth_socket.h>
59.50 -#include <gmyth/gmyth_stringlist.h>
59.51 -#include <gmyth/gmyth_tvchain.h>
59.52 -#include <gmyth/gmyth_uri.h>
59.53 -#include <gmyth/gmyth_util.h>
59.54 -#include <gmyth/gmyth_http.h>
59.55 -#include <gmyth/gmyth_vlc.h>
59.56 -#include <gmyth/gmyth_jobqueue.h>
59.57 -#include <gmyth/gmyth_transcoder.h>
59.58 -#include <gmyth/gmyth_recprofile.h>
59.59 -
59.60 -#endif /* _GMYTH_H_ */
60.1 --- a/gmyth/src/gmyth_backendinfo.c Mon Feb 25 17:45:36 2008 +0000
60.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
60.3 @@ -1,395 +0,0 @@
60.4 -/**
60.5 - * GMyth Library
60.6 - *
60.7 - * @file gmyth/gmyth_backend_info.c
60.8 - *
60.9 - * @brief <p> This component represents all the MythTV backend server
60.10 - * configuration information.
60.11 - *
60.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
60.13 - * @author Hallyson Melo <hallyson.melo@indt.org.br>
60.14 - * @author Rosfran Borges <rosfran.borges@indt.org.br>
60.15 - *
60.16 - *
60.17 - * This program is free software; you can redistribute it and/or modify
60.18 - * it under the terms of the GNU Lesser General Public License as published by
60.19 - * the Free Software Foundation; either version 2 of the License, or
60.20 - * (at your option) any later version.
60.21 - *
60.22 - * This program is distributed in the hope that it will be useful,
60.23 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
60.24 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60.25 - * GNU General Public License for more details.
60.26 - *
60.27 - * You should have received a copy of the GNU Lesser General Public License
60.28 - * along with this program; if not, write to the Free Software
60.29 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
60.30 - */
60.31 -
60.32 -#ifdef HAVE_CONFIG_H
60.33 -#include "config.h"
60.34 -#endif
60.35 -
60.36 -#include "gmyth_backendinfo.h"
60.37 -#include "gmyth_uri.h"
60.38 -#include "gmyth_debug.h"
60.39 -
60.40 -static void gmyth_backend_info_class_init(GMythBackendInfoClass *
60.41 - klass);
60.42 -static void gmyth_backend_info_init(GMythBackendInfo * object);
60.43 -
60.44 -static void gmyth_backend_info_dispose(GObject * object);
60.45 -static void gmyth_backend_info_finalize(GObject * object);
60.46 -
60.47 -G_DEFINE_TYPE(GMythBackendInfo, gmyth_backend_info, G_TYPE_OBJECT);
60.48 -static void gmyth_backend_info_class_init(GMythBackendInfoClass *
60.49 - klass)
60.50 -{
60.51 - GObjectClass *gobject_class;
60.52 -
60.53 - gobject_class = (GObjectClass *) klass;
60.54 -
60.55 - gobject_class->dispose = gmyth_backend_info_dispose;
60.56 - gobject_class->finalize = gmyth_backend_info_finalize;
60.57 -}
60.58 -
60.59 -static void
60.60 -gmyth_backend_info_init(GMythBackendInfo * backend_info)
60.61 -{
60.62 - backend_info->hostname = NULL;
60.63 - backend_info->port = -1;
60.64 - backend_info->username = NULL;
60.65 - backend_info->password = NULL;
60.66 - backend_info->db_name = NULL;
60.67 - backend_info->db_port = 0;
60.68 - backend_info->status_port = -1;
60.69 -}
60.70 -
60.71 -static void
60.72 -gmyth_backend_info_dispose(GObject * object)
60.73 -{
60.74 - GMythBackendInfo *backend_info = GMYTH_BACKEND_INFO(object);
60.75 -
60.76 - g_free(backend_info->hostname);
60.77 - g_free(backend_info->username);
60.78 - g_free(backend_info->password);
60.79 - g_free(backend_info->db_name);
60.80 -
60.81 - if (backend_info->sock)
60.82 - g_object_unref (backend_info->sock);
60.83 -
60.84 - backend_info->hostname = NULL;
60.85 - backend_info->port = -1;
60.86 - backend_info->username = NULL;
60.87 - backend_info->password = NULL;
60.88 - backend_info->db_name = NULL;
60.89 - backend_info->db_port = 0;
60.90 - backend_info->status_port = -1;
60.91 - backend_info->sock = NULL;
60.92 -
60.93 - G_OBJECT_CLASS(gmyth_backend_info_parent_class)->dispose(object);
60.94 -}
60.95 -
60.96 -static void
60.97 -gmyth_backend_info_finalize(GObject * object)
60.98 -{
60.99 - g_signal_handlers_destroy(object);
60.100 -
60.101 - G_OBJECT_CLASS(gmyth_backend_info_parent_class)->finalize(object);
60.102 -}
60.103 -
60.104 -/**
60.105 - * Creates a new instance of GMythBackendInfo.
60.106 - *
60.107 - * @return a new instance of GMythBackendInfo.
60.108 - */
60.109 -GMythBackendInfo *
60.110 -gmyth_backend_info_new()
60.111 -{
60.112 - GMythBackendInfo *backend_info =
60.113 - GMYTH_BACKEND_INFO(g_object_new(GMYTH_BACKEND_INFO_TYPE, NULL));
60.114 -
60.115 - return backend_info;
60.116 -}
60.117 -
60.118 -/**
60.119 - * Creates a new instance of GMythBackendInfo, based on a given set of
60.120 - * configuration parameters.
60.121 - *
60.122 - * @param hostname The hostname to the MythTV backend server.
60.123 - * @param username The user name to the MythTV backend MySQL server.
60.124 - * @param password The password to the user of the MythTV backend MySQL server.
60.125 - * @param db_name The database name of the MythTV backend, stored on the MySQL server.
60.126 - * @param port The port number of the MythTV backend server (commonly is 6543).
60.127 - *
60.128 - * @return a new instance of GMythBackendInfo.
60.129 - */
60.130 -GMythBackendInfo *
60.131 -gmyth_backend_info_new_full(const gchar * hostname, const gchar * username,
60.132 - const gchar * password, const gchar * db_name,
60.133 - gint port)
60.134 -{
60.135 - GMythBackendInfo *backend_info =
60.136 - GMYTH_BACKEND_INFO(g_object_new(GMYTH_BACKEND_INFO_TYPE, NULL));
60.137 -
60.138 - gmyth_backend_info_set_hostname(backend_info, hostname);
60.139 - gmyth_backend_info_set_username(backend_info, username);
60.140 - gmyth_backend_info_set_password(backend_info, password);
60.141 - gmyth_backend_info_set_db_name(backend_info, db_name);
60.142 - gmyth_backend_info_set_port(backend_info, port);
60.143 -
60.144 - return backend_info;
60.145 -}
60.146 -
60.147 -/**
60.148 - * Creates a new instance of GMythBackendInfo, based on the
60.149 - * MythTV's backend server URI string.
60.150 - *
60.151 - * @param uri_str The URI string pointing to the MythTV backend server.
60.152 - *
60.153 - * @return a new instance of GMythBackendInfo.
60.154 - */
60.155 -GMythBackendInfo *
60.156 -gmyth_backend_info_new_with_uri(const gchar * uri_str)
60.157 -{
60.158 - GMythBackendInfo *backend_info;
60.159 - GMythURI *uri;
60.160 - gchar **path_parts;
60.161 - gchar *db;
60.162 -
60.163 - backend_info = GMYTH_BACKEND_INFO(g_object_new(GMYTH_BACKEND_INFO_TYPE, NULL));
60.164 - uri = gmyth_uri_new_with_value (uri_str);
60.165 - path_parts = g_strsplit(gmyth_uri_get_path(uri), "&", -1);
60.166 - gmyth_backend_info_set_hostname(backend_info, gmyth_uri_get_host(uri));
60.167 - gmyth_backend_info_set_username(backend_info, gmyth_uri_get_user(uri));
60.168 - gmyth_backend_info_set_password(backend_info,
60.169 - gmyth_uri_get_password(uri));
60.170 -
60.171 - /*
60.172 - * gets the path info to database name, from the URI, and removes the
60.173 - * trash chars
60.174 - */
60.175 - if ((path_parts != NULL) && (strlen (path_parts[0]) > 0))
60.176 - {
60.177 - db = path_parts[0]+2;
60.178 - }
60.179 - else
60.180 - {
60.181 - db = gmyth_uri_get_path(uri);
60.182 - }
60.183 -
60.184 - gmyth_backend_info_set_db_name(backend_info, db);
60.185 -
60.186 - gmyth_backend_info_set_port(backend_info, gmyth_uri_get_port(uri));
60.187 -
60.188 - g_object_unref(uri);
60.189 - g_strfreev(path_parts);
60.190 -
60.191 - return backend_info;
60.192 -}
60.193 -
60.194 -void
60.195 -gmyth_backend_info_set_hostname(GMythBackendInfo * backend_info,
60.196 - const gchar * hostname)
60.197 -{
60.198 - g_return_if_fail(backend_info != NULL);
60.199 -
60.200 - if (NULL == hostname || strlen(hostname) <= 0) {
60.201 - gmyth_debug("Error trying to set a hostname equals to NULL.");
60.202 - } else {
60.203 - backend_info->hostname = g_strdup(hostname);
60.204 - }
60.205 -}
60.206 -
60.207 -void
60.208 -gmyth_backend_info_set_username(GMythBackendInfo * backend_info,
60.209 - const gchar * username)
60.210 -{
60.211 - g_return_if_fail(backend_info != NULL);
60.212 -
60.213 - backend_info->username = g_strdup(username);
60.214 -}
60.215 -
60.216 -void
60.217 -gmyth_backend_info_set_password(GMythBackendInfo * backend_info,
60.218 - const gchar * password)
60.219 -{
60.220 - g_return_if_fail(backend_info != NULL);
60.221 -
60.222 - backend_info->password = g_strdup(password);
60.223 -}
60.224 -
60.225 -void
60.226 -gmyth_backend_info_set_db_name(GMythBackendInfo * backend_info,
60.227 - const gchar * db_name)
60.228 -{
60.229 - g_return_if_fail(backend_info != NULL);
60.230 -
60.231 - backend_info->db_name = g_strdup(db_name);
60.232 -}
60.233 -
60.234 -void
60.235 -gmyth_backend_info_set_db_port(GMythBackendInfo * backend_info, gint db_port)
60.236 -{
60.237 - g_return_if_fail(backend_info != NULL);
60.238 -
60.239 - if (db_port <= 0) {
60.240 - gmyth_debug("Error trying to set a port less than 0.");
60.241 - } else {
60.242 - backend_info->db_port = db_port;
60.243 - }
60.244 -}
60.245 -
60.246 -void
60.247 -gmyth_backend_info_set_port(GMythBackendInfo * backend_info, gint port)
60.248 -{
60.249 - g_return_if_fail(backend_info != NULL);
60.250 -
60.251 - if (port <= 0) {
60.252 - gmyth_debug("Error trying to set a port less than 0.");
60.253 - } else {
60.254 - backend_info->port = port;
60.255 - }
60.256 -}
60.257 -
60.258 -void
60.259 -gmyth_backend_info_set_status_port(GMythBackendInfo * backend_info,
60.260 - gint port)
60.261 -{
60.262 - g_return_if_fail(backend_info != NULL);
60.263 -
60.264 - if (port <= 0) {
60.265 - gmyth_debug
60.266 - ("Error trying to set the status port to less than zero.");
60.267 - } else {
60.268 - backend_info->status_port = port;
60.269 - }
60.270 -}
60.271 -
60.272 -const gchar *
60.273 -gmyth_backend_info_get_hostname(GMythBackendInfo * backend_info)
60.274 -{
60.275 - g_return_val_if_fail(backend_info != NULL, NULL);
60.276 -
60.277 - return backend_info->hostname;
60.278 -}
60.279 -
60.280 -const gchar *
60.281 -gmyth_backend_info_get_username(GMythBackendInfo * backend_info)
60.282 -{
60.283 - g_return_val_if_fail(backend_info != NULL, NULL);
60.284 -
60.285 - return backend_info->username;
60.286 -}
60.287 -
60.288 -const gchar *
60.289 -gmyth_backend_info_get_password(GMythBackendInfo * backend_info)
60.290 -{
60.291 - g_return_val_if_fail(backend_info != NULL, NULL);
60.292 -
60.293 - return backend_info->password;
60.294 -}
60.295 -
60.296 -const gchar *
60.297 -gmyth_backend_info_get_db_name(GMythBackendInfo * backend_info)
60.298 -{
60.299 - g_return_val_if_fail(backend_info != NULL, NULL);
60.300 -
60.301 - return backend_info->db_name;
60.302 -}
60.303 -
60.304 -gint
60.305 -gmyth_backend_info_get_idb_port(GMythBackendInfo * backend_info)
60.306 -{
60.307 - g_return_val_if_fail(backend_info != NULL, -1);
60.308 -
60.309 - return backend_info->db_port;
60.310 -}
60.311 -
60.312 -
60.313 -gint
60.314 -gmyth_backend_info_get_port(GMythBackendInfo * backend_info)
60.315 -{
60.316 - g_return_val_if_fail(backend_info != NULL, -1);
60.317 -
60.318 - return backend_info->port;
60.319 -}
60.320 -
60.321 -/**
60.322 - * Creates a new instance of GMythURI, based on the GMythBackendInfo instance to the
60.323 - * MythTV's backend server.
60.324 - *
60.325 - * @param backend_info The GMythBackendInfo instance.
60.326 - *
60.327 - * @return an instance of GMythURI, created from a GMythBackendInfo.
60.328 - */
60.329 -GMythURI *
60.330 -gmyth_backend_info_get_uri(GMythBackendInfo * backend_info)
60.331 -{
60.332 - GMythURI *uri = NULL;
60.333 - gchar *uri_str = NULL;
60.334 - gchar *user_info = NULL;
60.335 - gchar *db_data = NULL;
60.336 -
60.337 - if ((backend_info->username != NULL
60.338 - && strlen(backend_info->username) > 0))
60.339 - user_info =
60.340 - g_strdup_printf("%s:%s@", backend_info->username,
60.341 - backend_info->password);
60.342 -
60.343 - if (backend_info->db_name != NULL && strlen(backend_info->db_name) > 0) {
60.344 - if ((g_strrstr(backend_info->db_name, "_") != NULL))
60.345 - db_data = g_strdup(backend_info->db_name);
60.346 - else
60.347 - db_data = g_strdup_printf("?%s&", backend_info->db_name);
60.348 - }
60.349 - // else if ( ( ( g_strrstr( backend_info->path, "livetv" ) != NULL )
60.350 - // ||
60.351 - // ( g_strrstr( backend_info->path, "/?" ) != NULL ) )
60.352 -
60.353 - uri_str = g_strdup_printf("myth://%s%s:%d/%s", user_info != NULL
60.354 - && strlen(user_info) > 0 ? user_info : "",
60.355 - backend_info->hostname, backend_info->port,
60.356 - db_data != NULL
60.357 - && strlen(db_data) > 0 ? db_data : "");
60.358 - uri = gmyth_uri_new_with_value(uri_str);
60.359 -
60.360 - if (user_info != NULL)
60.361 - g_free(user_info);
60.362 -
60.363 - if (db_data != NULL)
60.364 - g_free(db_data);
60.365 -
60.366 - g_free(uri_str);
60.367 -
60.368 - return uri;
60.369 -}
60.370 -
60.371 -gboolean
60.372 -gmyth_backend_info_is_local_file(GMythBackendInfo * backend_info)
60.373 -{
60.374 - g_return_val_if_fail(backend_info != NULL, FALSE);
60.375 -
60.376 - return
60.377 - gmyth_uri_is_local_file(gmyth_backend_info_get_uri(backend_info));
60.378 -}
60.379 -
60.380 -GMythSocket*
60.381 -gmyth_backend_info_get_connected_socket (GMythBackendInfo *backend_info)
60.382 -{
60.383 - if (backend_info->sock == NULL) {
60.384 - gboolean res;
60.385 - backend_info->sock = gmyth_socket_new ();
60.386 - res = gmyth_socket_connect_to_backend (backend_info->sock,
60.387 - backend_info->hostname,
60.388 - backend_info->port,
60.389 - TRUE);
60.390 - if (res == FALSE) {
60.391 - g_object_unref (backend_info->sock);
60.392 - backend_info->sock = NULL;
60.393 - return NULL;
60.394 - }
60.395 - }
60.396 -
60.397 - return g_object_ref (backend_info->sock);
60.398 -}
61.1 --- a/gmyth/src/gmyth_backendinfo.h Mon Feb 25 17:45:36 2008 +0000
61.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
61.3 @@ -1,121 +0,0 @@
61.4 -/**
61.5 - * GMyth Library
61.6 - *
61.7 - * @file gmyth/gmyth_backend_info.h
61.8 - *
61.9 - * @brief <p> This component represents all the MythTV backend server
61.10 - * configuration information.
61.11 - *
61.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
61.13 - * @author Hallyson Melo <hallyson.melo@indt.org.br>
61.14 - * @author Rosfran Borges <rosfran.borges@indt.org.br>
61.15 - *
61.16 -*
61.17 -* This program is free software; you can redistribute it and/or modify
61.18 -* it under the terms of the GNU Lesser General Public License as published by
61.19 -* the Free Software Foundation; either version 2 of the License, or
61.20 -* (at your option) any later version.
61.21 -*
61.22 -* This program is distributed in the hope that it will be useful,
61.23 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
61.24 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
61.25 - * GNU General Public License for more details.
61.26 - *
61.27 - * You should have received a copy of the GNU Lesser General Public License
61.28 - * along with this program; if not, write to the Free Software
61.29 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
61.30 - */
61.31 -
61.32 -#ifndef __GMYTH_BACKEND_INFO_H__
61.33 -#define __GMYTH_BACKEND_INFO_H__
61.34 -
61.35 -#include <glib-object.h>
61.36 -
61.37 -#include "gmyth_uri.h"
61.38 -#include "gmyth_socket.h"
61.39 -
61.40 -G_BEGIN_DECLS
61.41 -#define GMYTH_BACKEND_INFO_TYPE \
61.42 - (gmyth_backend_info_get_type ())
61.43 -#define GMYTH_BACKEND_INFO(obj) \
61.44 - (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_BACKEND_INFO_TYPE, GMythBackendInfo))
61.45 -#define GMYTH_BACKEND_INFO_CLASS(klass) \
61.46 - (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_BACKEND_INFO_TYPE, GMythBackendInfoClass))
61.47 -#define IS_GMYTH_BACKEND_INFO(obj) \
61.48 - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_BACKEND_INFO_TYPE))
61.49 -#define IS_GMYTH_BACKEND_INFO_CLASS(klass) \
61.50 - (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_BACKEND_INFO_TYPE))
61.51 -#define GMYTH_BACKEND_INFO_GET_CLASS(obj) \
61.52 - (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_BACKEND_INFO_TYPE, GMythBackendInfoClass))
61.53 -
61.54 -typedef struct _GMythBackendInfo GMythBackendInfo;
61.55 -typedef struct _GMythBackendInfoClass GMythBackendInfoClass;
61.56 -
61.57 -struct _GMythBackendInfoClass {
61.58 - GObjectClass parent_class;
61.59 -
61.60 - /*
61.61 - * callbacks
61.62 - */
61.63 - /*
61.64 - * no one for now
61.65 - */
61.66 -};
61.67 -
61.68 -struct _GMythBackendInfo {
61.69 - GObject parent;
61.70 - /** The backend hostname or ip address. */
61.71 - gchar *hostname;
61.72 - /** The backend port. */
61.73 - gint port;
61.74 - /** The username to connect to the mysql server. */
61.75 - gchar *username;
61.76 - /** The password to connect to the mysql server. */
61.77 - gchar *password;
61.78 - /** The mythtv's mysql database name. */
61.79 - gchar *db_name;
61.80 - /** The mysql database port */
61.81 - gint db_port;
61.82 - /** The backend status port for http connection */
61.83 - gint status_port;
61.84 -
61.85 - /* Private */
61.86 - GMythSocket *sock;
61.87 -};
61.88 -
61.89 -
61.90 -GType gmyth_backend_info_get_type (void) G_GNUC_CONST;
61.91 -GMythBackendInfo* gmyth_backend_info_new (void);
61.92 -GMythBackendInfo* gmyth_backend_info_new_full (const gchar *hostname,
61.93 - const gchar *username,
61.94 - const gchar *password,
61.95 - const gchar *db_name,
61.96 - gint port);
61.97 -GMythBackendInfo* gmyth_backend_info_new_with_uri (const gchar *uri_str);
61.98 -void gmyth_backend_info_set_hostname (GMythBackendInfo *backend_info,
61.99 - const gchar *hostname);
61.100 -void gmyth_backend_info_set_username (GMythBackendInfo *backend_info,
61.101 - const gchar *username);
61.102 -void gmyth_backend_info_set_password (GMythBackendInfo *backend_info,
61.103 - const gchar *password);
61.104 -void gmyth_backend_info_set_db_name (GMythBackendInfo *backend_info,
61.105 - const gchar *db_name);
61.106 -void gmyth_backend_info_set_db_port (GMythBackendInfo *backend_info,
61.107 - gint db_port);
61.108 -void gmyth_backend_info_set_port (GMythBackendInfo *backend_info,
61.109 - gint port);
61.110 -void gmyth_backend_info_set_status_port (GMythBackendInfo *backend_info,
61.111 - gint port);
61.112 -const gchar* gmyth_backend_info_get_hostname (GMythBackendInfo *backend_info);
61.113 -const gchar* gmyth_backend_info_get_username (GMythBackendInfo *backend_info);
61.114 -const gchar* gmyth_backend_info_get_password (GMythBackendInfo *backend_info);
61.115 -const gchar* gmyth_backend_info_get_db_name (GMythBackendInfo *backend_info);
61.116 -gint gmyth_backend_info_get_db_port (GMythBackendInfo *backend_info);
61.117 -gint gmyth_backend_info_get_port (GMythBackendInfo *backend_info);
61.118 -GMythURI* gmyth_backend_info_get_uri (GMythBackendInfo *backend_info);
61.119 -gboolean gmyth_backend_info_is_local_file (GMythBackendInfo *backend_info);
61.120 -GMythSocket* gmyth_backend_info_get_connected_socket
61.121 - (GMythBackendInfo *backend_info);
61.122 -
61.123 -G_END_DECLS
61.124 -#endif /* __GMYTH_BACKEND_INFO_H__ */
62.1 --- a/gmyth/src/gmyth_common.c Mon Feb 25 17:45:36 2008 +0000
62.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
62.3 @@ -1,154 +0,0 @@
62.4 -/**
62.5 - * GMyth Library
62.6 - *
62.7 - * @file gmyth/gmyth_common.c
62.8 - *
62.9 - * @brief <p> This file contains basic common functions for the gmyth library.
62.10 - *
62.11 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
62.12 - * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
62.13 - * @author Rosfran Borges <rosfran.borges@indt.org.br>
62.14 - *
62.15 - *
62.16 - * This program is free software; you can redistribute it and/or modify
62.17 - * it under the terms of the GNU Lesser General Public License as published by
62.18 - * the Free Software Foundation; either version 2 of the License, or
62.19 - * (at your option) any later version.
62.20 - *
62.21 - * This program is distributed in the hope that it will be useful,
62.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
62.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
62.24 - * GNU General Public License for more details.
62.25 - *
62.26 - * You should have received a copy of the GNU Lesser General Public License
62.27 - * along with this program; if not, write to the Free Software
62.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
62.29 - */
62.30 -
62.31 -#ifdef HAVE_CONFIG_H
62.32 -#include "config.h"
62.33 -#endif
62.34 -
62.35 -#include "gmyth_common.h"
62.36 -#include "gmyth_debug.h"
62.37 -#include "gmyth_util.h"
62.38 -
62.39 -static void free_channel_data(gpointer data, gpointer user_data);
62.40 -static void free_program_data(gpointer data, gpointer user_data);
62.41 -
62.42 -/**
62.43 -* Frees the memory allocated to the GMythChannelInfo objects inside list.
62.44 -* The list memory is also released by g_list_free(). If LIST is NULL it
62.45 -* simply returns.
62.46 -*
62.47 -* @param list the GList containing a list of GMythChannelInfo to free.
62.48 -*/
62.49 -void
62.50 -gmyth_free_channel_list(GList * list)
62.51 -{
62.52 - g_return_if_fail(list != NULL);
62.53 -
62.54 - g_list_foreach(list, free_channel_data, NULL);
62.55 - g_list_free(list);
62.56 -}
62.57 -
62.58 -/**
62.59 - * Frees the memory allocated to the GMythProgramInfo objects inside list.
62.60 - * The list memory is also released by g_list_free(). If list is NULL it
62.61 - * simply returns.
62.62 - *
62.63 - * @param list the GList containing a list of GMythProgramInfo to free.
62.64 - */
62.65 -void
62.66 -gmyth_free_program_list(GList * list)
62.67 -{
62.68 - g_return_if_fail(list != NULL);
62.69 -
62.70 - g_list_foreach(list, free_program_data, NULL);
62.71 - g_list_free(list);
62.72 -}
62.73 -
62.74 -void
62.75 -gmyth_channel_info_free(GMythChannelInfo * channel)
62.76 -{
62.77 - g_return_if_fail(channel != NULL);
62.78 -
62.79 - if (channel->channel_num)
62.80 - g_string_free(channel->channel_num, TRUE);
62.81 -
62.82 - if (channel->channel_name)
62.83 - g_string_free(channel->channel_name, TRUE);
62.84 -
62.85 - if (channel->channel_icon)
62.86 - g_string_free(channel->channel_icon, TRUE);
62.87 -
62.88 - g_free(channel);
62.89 -}
62.90 -
62.91 -/**
62.92 - * Prints the channel info to the standard output. The gmyth debug must be enabled.
62.93 - * @param channel_info the GMythChannelInfo instance
62.94 - */
62.95 -void
62.96 -gmyth_channel_info_print(GMythChannelInfo * channel_info)
62.97 -{
62.98 -#ifdef GMYTH_USE_DEBUG
62.99 - if (channel_info != NULL) {
62.100 - g_return_if_fail(channel_info->channel_name != NULL);
62.101 - g_return_if_fail(channel_info->channel_num != NULL);
62.102 -
62.103 - gmyth_debug("ChannelInfo (Name, Num, ID) = (%s, %s, %d)",
62.104 - channel_info->channel_name->str,
62.105 - channel_info->channel_num->str,
62.106 - channel_info->channel_ID);
62.107 -
62.108 - }
62.109 -#endif
62.110 -}
62.111 -
62.112 -/**
62.113 - * Prints the program info to the standard output. The gmyth debug must be enabled.
62.114 - * @param channel_info the GMythProgramInfo instance
62.115 - */
62.116 -void
62.117 -gmyth_program_info_print(GMythProgramInfo * program_info)
62.118 -{
62.119 -#ifdef GMYTH_USE_DEBUG
62.120 - g_return_if_fail(program_info);
62.121 -
62.122 - gmyth_debug("ProgramInfo\n\tTitle = %s\n\t"
62.123 - "Description = %s\n\t"
62.124 - "Start time= %s\t"
62.125 - "End time = %s\n"
62.126 - "Path name = %s\n"
62.127 - "File size = %lld\n",
62.128 - program_info->title ? program_info->title->str : "NULL",
62.129 - program_info->description ? program_info->description->
62.130 - str : "NULL",
62.131 - gmyth_util_time_to_string_from_time_val(program_info->
62.132 - startts),
62.133 - gmyth_util_time_to_string_from_time_val(program_info->
62.134 - endts),
62.135 - program_info->pathname ? program_info->pathname->
62.136 - str : "NULL", program_info->filesize);
62.137 -#endif
62.138 -}
62.139 -
62.140 -static void
62.141 -free_channel_data(gpointer data, gpointer user_data)
62.142 -{
62.143 - /*
62.144 - * Frees the GMythChannelInfo structure
62.145 - */
62.146 - GMythChannelInfo *channel = (GMythChannelInfo *) data;
62.147 -
62.148 - gmyth_channel_info_free(channel);
62.149 -}
62.150 -
62.151 -static void
62.152 -free_program_data(gpointer data, gpointer user_data)
62.153 -{
62.154 - g_return_if_fail(data != NULL);
62.155 -
62.156 - g_object_unref((GMythProgramInfo *) data);
62.157 -}
63.1 --- a/gmyth/src/gmyth_common.h Mon Feb 25 17:45:36 2008 +0000
63.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
63.3 @@ -1,62 +0,0 @@
63.4 -/**
63.5 - * GMyth Library
63.6 - *
63.7 - * @file gmyth/gmyth_common.h
63.8 - *
63.9 - * @brief <p> This file contains basic common functions for the gmyth library.
63.10 - *
63.11 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
63.12 - * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
63.13 - * @author Rosfran Borges <rosfran.borges@indt.org.br>
63.14 - *
63.15 - *
63.16 - * This program is free software; you can redistribute it and/or modify
63.17 - * it under the terms of the GNU Lesser General Public License as published by
63.18 - * the Free Software Foundation; either version 2 of the License, or
63.19 - * (at your option) any later version.
63.20 - *
63.21 - * This program is distributed in the hope that it will be useful,
63.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
63.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
63.24 - * GNU General Public License for more details.
63.25 - *
63.26 - * You should have received a copy of the GNU Lesser General Public License
63.27 - * along with this program; if not, write to the Free Software
63.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
63.29 - */
63.30 -
63.31 -#ifndef GMYTH_COMMON_H_
63.32 -#define GMYTH_COMMON_H_
63.33 -
63.34 -#include <glib.h>
63.35 -#include <time.h>
63.36 -
63.37 -#include "gmyth_programinfo.h"
63.38 -
63.39 -G_BEGIN_DECLS
63.40 - /**
63.41 - * The GMythChannelInfo structure represents the channel information
63.42 - * stored in the backend database.
63.43 - */
63.44 - typedef struct {
63.45 - /** The channel ID in backend database */
63.46 - gint channel_ID;
63.47 -
63.48 - /** The channel number */
63.49 - GString *channel_num;
63.50 -
63.51 - /** The channel name in backend database */
63.52 - GString *channel_name;
63.53 -
63.54 - /** The channel icon path in the backend database */
63.55 - GString *channel_icon;
63.56 -} GMythChannelInfo;
63.57 -
63.58 -void gmyth_free_channel_list (GList *list);
63.59 -void gmyth_free_program_list (GList *list);
63.60 -void gmyth_channel_info_free (GMythChannelInfo *channel_info);
63.61 -void gmyth_channel_info_print (GMythChannelInfo *channel_info);
63.62 -void gmyth_program_info_print (GMythProgramInfo *program_info);
63.63 -
63.64 -G_END_DECLS
63.65 -#endif /* GMYTH_COMMON_H_ */
64.1 --- a/gmyth/src/gmyth_debug.c Mon Feb 25 17:45:36 2008 +0000
64.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
64.3 @@ -1,54 +0,0 @@
64.4 -/**
64.5 - * GMyth Library
64.6 - *
64.7 - * @file gmyth/gmyth_debug.c
64.8 - *
64.9 - *
64.10 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
64.11 - * @author Renato Filho <renato.filho@indt.org.br>
64.12 - *
64.13 - *
64.14 - * This program is free software; you can redistribute it and/or modify
64.15 - * it under the terms of the GNU Lesser General Public License as published by
64.16 - * the Free Software Foundation; either version 2 of the License, or
64.17 - * (at your option) any later version.
64.18 - *
64.19 - * This program is distributed in the hope that it will be useful,
64.20 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
64.21 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
64.22 - * GNU General Public License for more details.
64.23 - *
64.24 - * You should have received a copy of the GNU Lesser General Public License
64.25 - * along with this program; if not, write to the Free Software
64.26 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
64.27 - */
64.28 -
64.29 -#ifdef HAVE_CONFIG_H
64.30 -#include "config.h"
64.31 -#endif
64.32 -
64.33 -#include "gmyth_debug.h"
64.34 -
64.35 -void
64.36 -gmyth_debug_real(const char *func,
64.37 - const char *file, const int line, gboolean newline,
64.38 - const char *format, ...)
64.39 -{
64.40 - va_list args;
64.41 - char buffer[1025];
64.42 - char str_time[255];
64.43 - time_t the_time;
64.44 -
64.45 - va_start(args, format);
64.46 -
64.47 - g_vsnprintf(buffer, 1024, format, args);
64.48 -
64.49 - va_end(args);
64.50 -
64.51 - time(&the_time);
64.52 - strftime(str_time, 254, "%H:%M:%S", localtime(&the_time));
64.53 -
64.54 - g_printerr(newline ? "(%s) [%p] [%s] %s:%d: %s\n" :
64.55 - "(%s) [%p] [%s] %s:%d: %s", str_time, g_thread_self(), func,
64.56 - file, line, buffer);
64.57 -}
65.1 --- a/gmyth/src/gmyth_debug.h Mon Feb 25 17:45:36 2008 +0000
65.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
65.3 @@ -1,46 +0,0 @@
65.4 -/**
65.5 - * GMyth Library
65.6 - *
65.7 - * @file gmyth/gmyth_debug.h
65.8 - *
65.9 - *
65.10 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
65.11 - * @author Renato Filho <renato.filho@indt.org.br>
65.12 - *
65.13 -*
65.14 -* This program is free software; you can redistribute it and/or modify
65.15 -* it under the terms of the GNU Lesser General Public License as published by
65.16 -* the Free Software Foundation; either version 2 of the License, or
65.17 -* (at your option) any later version.
65.18 -*
65.19 -* This program is distributed in the hope that it will be useful,
65.20 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
65.21 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
65.22 - * GNU General Public License for more details.
65.23 - *
65.24 - * You should have received a copy of the GNU Lesser General Public License
65.25 - * along with this program; if not, write to the Free Software
65.26 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
65.27 - */
65.28 -
65.29 -#ifndef __GMYTH_DEBUG_H__
65.30 -#define __GMYTH_DEBUG_H__
65.31 -
65.32 -#include <stdarg.h>
65.33 -#include <glib.h>
65.34 -#include <time.h>
65.35 -
65.36 -G_BEGIN_DECLS
65.37 -#ifdef GMYTH_USE_DEBUG
65.38 -#define gmyth_debug(...) gmyth_debug_real (__FUNCTION__, __FILE__, __LINE__, TRUE, __VA_ARGS__)
65.39 -#else
65.40 -#define gmyth_debug(...)
65.41 -#endif
65.42 - void
65.43 -gmyth_debug_real(const char *func,
65.44 - const char *file, int line, gboolean newline,
65.45 - const char *format, ...)
65.46 -G_GNUC_PRINTF(5, 6);
65.47 -
65.48 -G_END_DECLS
65.49 -#endif
66.1 --- a/gmyth/src/gmyth_epg.c Mon Feb 25 17:45:36 2008 +0000
66.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
66.3 @@ -1,446 +0,0 @@
66.4 -/**
66.5 - * GMyth Library
66.6 - *
66.7 - * @file gmyth/gmyth_epg.c
66.8 - *
66.9 - * @brief <p> GMythEPG class provides access to the program and channel data
66.10 - * from the Electronic Program Guide (EPG) of the Mythtv backend.
66.11 - *
66.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
66.13 - * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
66.14 - *
66.15 - * This program is free software; you can redistribute it and/or modify
66.16 - * it under the terms of the GNU Lesser General Public License as published by
66.17 - * the Free Software Foundation; either version 2 of the License, or
66.18 - * (at your option) any later version.
66.19 - *
66.20 - * This program is distributed in the hope that it will be useful,
66.21 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
66.22 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
66.23 - * GNU General Public License for more details.
66.24 - *
66.25 - * You should have received a copy of the GNU Lesser General Public License
66.26 - * along with this program; if not, write to the Free Software
66.27 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
66.28 - */
66.29 -
66.30 -#ifdef HAVE_CONFIG_H
66.31 -#include "config.h"
66.32 -#endif
66.33 -
66.34 -#include <mysql/mysql.h>
66.35 -#include <stdlib.h>
66.36 -#include <string.h>
66.37 -#include <assert.h>
66.38 -
66.39 -#include "gmyth_epg.h"
66.40 -#include "gmyth_programinfo.h"
66.41 -#include "gmyth_util.h"
66.42 -#include "gmyth_file_transfer.h"
66.43 -#include "gmyth_debug.h"
66.44 -
66.45 -#define CONNECT_TIMEOUT 6
66.46 -
66.47 -static void gmyth_epg_class_init(GMythEPGClass * klass);
66.48 -static void gmyth_epg_init(GMythEPG * object);
66.49 -
66.50 -static void gmyth_epg_dispose(GObject * object);
66.51 -static void gmyth_epg_finalize(GObject * object);
66.52 -
66.53 -G_DEFINE_TYPE(GMythEPG, gmyth_epg, G_TYPE_OBJECT)
66.54 - static void gmyth_epg_class_init(GMythEPGClass * klass)
66.55 -{
66.56 - GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
66.57 -
66.58 - gobject_class->dispose = gmyth_epg_dispose;
66.59 - gobject_class->finalize = gmyth_epg_finalize;
66.60 -}
66.61 -
66.62 -static void
66.63 -gmyth_epg_init(GMythEPG * gmyth_epg)
66.64 -{
66.65 -
66.66 -}
66.67 -
66.68 -static void
66.69 -gmyth_epg_dispose(GObject * object)
66.70 -{
66.71 - GMythEPG *gmyth_epg = GMYTH_EPG(object);
66.72 -
66.73 - if (gmyth_epg->sqlquery != NULL) {
66.74 - g_object_unref(gmyth_epg->sqlquery);
66.75 - gmyth_epg->sqlquery = NULL;
66.76 - }
66.77 -
66.78 - G_OBJECT_CLASS(gmyth_epg_parent_class)->dispose(object);
66.79 -}
66.80 -
66.81 -static void
66.82 -gmyth_epg_finalize(GObject * object)
66.83 -{
66.84 - g_signal_handlers_destroy(object);
66.85 -
66.86 - G_OBJECT_CLASS(gmyth_epg_parent_class)->finalize(object);
66.87 -}
66.88 -
66.89 -/**
66.90 - * Creates a new instance of GMythEPG.
66.91 - *
66.92 - * @return a new instance of GMythEPG.
66.93 - */
66.94 -GMythEPG *
66.95 -gmyth_epg_new(void)
66.96 -{
66.97 - GMythEPG *epg = GMYTH_EPG(g_object_new(GMYTH_EPG_TYPE, NULL));
66.98 -
66.99 - return epg;
66.100 -}
66.101 -
66.102 -/** Connects to the Mysql database in the backend. The backend address
66.103 - * is loaded from the GMythSettings instance.
66.104 - *
66.105 - * @param gmyth_epg the GMythEPG instance to be connected.
66.106 - * @return true if connection was success, false if failed.
66.107 - */
66.108 -gboolean
66.109 -gmyth_epg_connect(GMythEPG * gmyth_epg, GMythBackendInfo * backend_info)
66.110 -{
66.111 - g_return_val_if_fail(gmyth_epg != NULL, FALSE);
66.112 -
66.113 - if (gmyth_epg->sqlquery == NULL) {
66.114 - gmyth_debug("[%s] Creating gmyth_query", __FUNCTION__);
66.115 - gmyth_epg->sqlquery = gmyth_query_new();
66.116 - }
66.117 -
66.118 - if (!gmyth_query_connect_with_timeout(gmyth_epg->sqlquery,
66.119 - backend_info, CONNECT_TIMEOUT)) {
66.120 - gmyth_debug("[%s] Error while connecting to db", __FUNCTION__);
66.121 - return FALSE;
66.122 - }
66.123 -
66.124 - gmyth_epg->backend_info = backend_info;
66.125 - g_object_ref(backend_info);
66.126 -
66.127 - return TRUE;
66.128 -}
66.129 -
66.130 -/** Disconnects from the Mysql database in the backend.
66.131 - *
66.132 - * @param gmyth_epg the GMythEPG instance to be disconnected
66.133 - * @return true if disconnection was success, false if failed.
66.134 - */
66.135 -gboolean
66.136 -gmyth_epg_disconnect(GMythEPG * gmyth_epg)
66.137 -{
66.138 - g_return_val_if_fail(gmyth_epg != NULL, FALSE);
66.139 -
66.140 - if (gmyth_epg->sqlquery != NULL) {
66.141 - gmyth_query_disconnect(gmyth_epg->sqlquery);
66.142 - g_object_unref(gmyth_epg->sqlquery);
66.143 - gmyth_epg->sqlquery = NULL;
66.144 - }
66.145 -
66.146 - if (gmyth_epg->backend_info != NULL) {
66.147 - g_object_unref(gmyth_epg->backend_info);
66.148 - gmyth_epg->backend_info = NULL;
66.149 - }
66.150 -
66.151 - return TRUE;
66.152 -}
66.153 -
66.154 -/** Retrieves the available list of channels from the backend Mysql database.
66.155 - *
66.156 - * @param gmyth_epg the GMythEPG instance.
66.157 - * @param glist_ptr the GSList pointer to be filled with the loaded list address.
66.158 - * @return The amount of channels retrieved from database, or -1 if error.
66.159 - */
66.160 -gint
66.161 -gmyth_epg_get_channel_list(GMythEPG * gmyth_epg, GList ** glist_ptr)
66.162 -{
66.163 - MYSQL_RES *msql_res;
66.164 -
66.165 - g_return_val_if_fail(gmyth_epg != NULL, -1);
66.166 -
66.167 - msql_res = gmyth_query_process_statement(gmyth_epg->sqlquery,
66.168 - "SELECT chanid, channum, name, icon FROM channel;");
66.169 -
66.170 - (*glist_ptr) = NULL;
66.171 -
66.172 - if (msql_res == NULL) {
66.173 - gmyth_debug("[%s] msql query returned NULL MYSQL_RES",
66.174 - __FUNCTION__);
66.175 - return -1;
66.176 - } else {
66.177 - MYSQL_ROW row;
66.178 - GMythChannelInfo *channel_info;
66.179 -
66.180 - while ((row = mysql_fetch_row(msql_res)) != NULL) {
66.181 -
66.182 - channel_info = g_new0(GMythChannelInfo, 1);
66.183 - channel_info->channel_ID =
66.184 - (gint) g_ascii_strtoull(row[0], NULL, 10);
66.185 - channel_info->channel_num = g_string_new(row[1]);
66.186 - channel_info->channel_name = g_string_new(row[2]);
66.187 - channel_info->channel_icon = g_string_new(row[3]);
66.188 -#ifdef GMYTH_USE_DEBUG
66.189 - gmyth_channel_info_print(channel_info);
66.190 -#endif
66.191 - (*glist_ptr) = g_list_append((*glist_ptr), channel_info);
66.192 - }
66.193 - }
66.194 - mysql_free_result(msql_res);
66.195 -
66.196 - return (!(*glist_ptr)) ? 0 : g_list_length(*glist_ptr);
66.197 -}
66.198 -
66.199 -GMythChannelInfo *
66.200 -gmyth_epg_get_channel_info(GMythEPG * gmyth_epg, gint channel_id)
66.201 -{
66.202 - GMythChannelInfo *channel_info = NULL;
66.203 - MYSQL_RES *msql_res;
66.204 - gchar *query_str;
66.205 -
66.206 - g_return_val_if_fail(gmyth_epg != NULL, NULL);
66.207 -
66.208 - query_str =
66.209 - g_strdup_printf
66.210 - ("SELECT channum, name, icon FROM channel WHERE chanid=%d;",
66.211 - channel_id);
66.212 - msql_res =
66.213 - gmyth_query_process_statement(gmyth_epg->sqlquery, query_str);
66.214 -
66.215 - if (msql_res == NULL) {
66.216 - gmyth_debug("[%s] msql query returned NULL MYSQL_RES",
66.217 - __FUNCTION__);
66.218 - return NULL;
66.219 - } else {
66.220 - MYSQL_ROW row;
66.221 -
66.222 - if ((row = mysql_fetch_row(msql_res)) != NULL) {
66.223 -
66.224 - channel_info = g_new0(GMythChannelInfo, 1);
66.225 - channel_info->channel_ID = channel_id;
66.226 - channel_info->channel_num = g_string_new(row[0]);
66.227 - channel_info->channel_name = g_string_new(row[1]);
66.228 - channel_info->channel_icon = g_string_new(row[2]);
66.229 -#ifdef GMYTH_USE_DEBUG
66.230 - gmyth_channel_info_print(channel_info);
66.231 -#endif
66.232 - }
66.233 - }
66.234 - mysql_free_result(msql_res);
66.235 -
66.236 - return channel_info;
66.237 -}
66.238 -
66.239 -/**
66.240 - * Retrieves the available list of channels from the backend Mysql database.
66.241 - *
66.242 - * @param gmyth_epg the GMythEPG instance.
66.243 - * @param proglist the GSList pointer to be filled with the loaded list.
66.244 - * @param chan_num the channel num on which to search for program.
66.245 - * @param starttime the start time to search for programs.
66.246 - * @param endtime the end time to search for programs.
66.247 - * @return The amount of channels retrieved from database, or -1 if error.
66.248 - */
66.249 -gint
66.250 -gmyth_epg_get_program_list(GMythEPG * gmyth_epg, GList ** proglist,
66.251 - const gint chan_num, GTimeVal * starttime,
66.252 - GTimeVal * endtime)
66.253 -{
66.254 -
66.255 - gchar *startts =
66.256 - gmyth_util_time_to_string_from_time_val(starttime);
66.257 - gchar *endts =
66.258 - gmyth_util_time_to_string_from_time_val(endtime);
66.259 - MYSQL_ROW row;
66.260 - GString *querystr;
66.261 -
66.262 - assert(gmyth_epg);
66.263 -
66.264 - querystr =
66.265 - g_string_new
66.266 - ("SELECT DISTINCT program.chanid, program.starttime, program.endtime, "
66.267 - " program.title, program.subtitle, program.description, "
66.268 - " program.category, channel.channum, channel.callsign, "
66.269 - " channel.name, program.previouslyshown, channel.commfree, "
66.270 - " channel.outputfilters, program.seriesid, program.programid, "
66.271 - " program.airdate, program.stars, program.originalairdate, "
66.272 - " program.category_type, record.recordid, "
66.273 - " oldrecstatus.rectype, oldrecstatus.recstatus, "
66.274 - " oldrecstatus.findid "
66.275 - "FROM program "
66.276 - "LEFT JOIN channel ON program.chanid = channel.chanid "
66.277 - "LEFT JOIN record ON "
66.278 - " program.chanid = record.chanid AND "
66.279 - " DATE (program.starttime) = record.startdate AND "
66.280 - " TIME (program.starttime) = record.starttime AND "
66.281 - " DATE (program.endtime) = record.enddate AND "
66.282 - " TIME (program.endtime) = record.endtime "
66.283 - "LEFT JOIN oldrecorded AS oldrecstatus ON "
66.284 - " program.title = oldrecstatus.title AND "
66.285 - " channel.callsign = oldrecstatus.station AND "
66.286 - " program.starttime = oldrecstatus.starttime ");
66.287 -
66.288 - g_string_append_printf(querystr,
66.289 - "WHERE program.chanid = %d "
66.290 - " AND program.endtime >= '%s' "
66.291 - " AND program.starttime <= '%s' "
66.292 - " AND program.manualid = 0 ", chan_num,
66.293 - startts, endts);
66.294 -
66.295 - if (!g_strrstr(querystr->str, " GROUP BY "))
66.296 - querystr = g_string_append(querystr,
66.297 - " GROUP BY program.starttime, channel.channum, "
66.298 - " channel.callsign, program.title ");
66.299 -
66.300 - if (!g_strrstr(querystr->str, " LIMIT "))
66.301 - querystr = g_string_append(querystr, " LIMIT 1000 ");
66.302 -
66.303 - MYSQL_RES *res_set =
66.304 - gmyth_query_process_statement(gmyth_epg->sqlquery, querystr->str);
66.305 -
66.306 - if (res_set == NULL) {
66.307 - gmyth_debug("[%s] msql query returned NULL MYSQL_RES",
66.308 - __FUNCTION__);
66.309 - return -1;
66.310 - }
66.311 -
66.312 - *proglist = NULL;
66.313 - while ((row = mysql_fetch_row(res_set)) != NULL) {
66.314 -
66.315 - GMythProgramInfo *p = gmyth_program_info_new();
66.316 -
66.317 - p->channel_id = (int) g_ascii_strtoull (row[0], NULL, 10);
66.318 -
66.319 - p->startts = gmyth_util_string_to_time_val(row[1]);
66.320 - p->endts = gmyth_util_string_to_time_val(row[2]);
66.321 -
66.322 - p->recstartts = g_new0(GTimeVal, 1);
66.323 - p->recstartts->tv_sec = p->startts->tv_sec;
66.324 - p->recstartts->tv_usec = p->startts->tv_usec;
66.325 -
66.326 - p->recendts = g_new0(GTimeVal, 1);
66.327 - p->recendts->tv_sec = p->endts->tv_sec;
66.328 - p->recendts->tv_usec = p->endts->tv_usec;
66.329 -
66.330 - p->lastmodified = g_new0(GTimeVal, 1);
66.331 - p->lastmodified->tv_sec = p->startts->tv_sec;
66.332 - p->lastmodified->tv_usec = p->startts->tv_usec;
66.333 -
66.334 -
66.335 - p->title = g_string_new(row[3]);
66.336 - p->subtitle = g_string_new(row[4]);
66.337 - p->description = g_string_new(row[5]);
66.338 - p->category = g_string_new(row[6]);
66.339 - p->chanstr = g_string_new(row[7]);
66.340 - p->chansign = g_string_new(row[8]);
66.341 - p->channame = g_string_new(row[9]);
66.342 - p->repeat = g_ascii_strtoull(row[10], NULL, 10);
66.343 - p->chancommfree = g_ascii_strtoull(row[11], NULL, 10);
66.344 - p->chanOutputFilters = g_string_new(row[12]);
66.345 - p->seriesid = g_string_new(row[13]);
66.346 - p->program_id = g_string_new(row[14]);
66.347 - p->year = g_string_new(row[15]);
66.348 - p->stars = g_ascii_strtod(row[16], NULL);
66.349 -
66.350 - if (!row[17] || !strcmp(row[17], "")) {
66.351 - p->originalAirDate = 0;
66.352 - p->hasAirDate = FALSE;
66.353 - } else {
66.354 - p->originalAirDate = gmyth_util_string_to_time_val(row[17]);
66.355 - p->hasAirDate = TRUE;
66.356 - }
66.357 -
66.358 - p->catType = g_string_new(row[18]);
66.359 - if (row[19] != NULL)
66.360 - p->recordid = g_ascii_strtoull(row[19], NULL, 10);
66.361 -
66.362 - *proglist = g_list_append(*proglist, p);
66.363 -
66.364 -#ifdef GMYTH_USE_DEBUG
66.365 - gmyth_program_info_print(p);
66.366 -#endif
66.367 - }
66.368 -
66.369 - /*
66.370 - * deallocate
66.371 - */
66.372 - mysql_free_result(res_set);
66.373 - g_string_free(querystr, TRUE);
66.374 -
66.375 - return g_list_length (*proglist);
66.376 -}
66.377 -
66.378 -gboolean
66.379 -gmyth_epg_channel_has_icon(GMythEPG * gmyth_epg,
66.380 - GMythChannelInfo * channel_info)
66.381 -{
66.382 - gboolean res = FALSE;
66.383 -
66.384 - g_return_val_if_fail(gmyth_epg != NULL, FALSE);
66.385 - g_return_val_if_fail(channel_info != NULL, FALSE);
66.386 -
66.387 - if (channel_info->channel_icon != NULL) {
66.388 - res = gmyth_util_file_exists(gmyth_epg->backend_info,
66.389 - channel_info->channel_icon->str);
66.390 - }
66.391 -
66.392 - return res;
66.393 -
66.394 -}
66.395 -
66.396 -/**
66.397 - *
66.398 - * @param data the data pointer to be filled with icon binary data. It must be freed by the calling function.
66.399 - * @return TRUE if success, FALSE if any error happens.
66.400 - */
66.401 -gboolean
66.402 -gmyth_epg_channel_get_icon(GMythEPG * gmyth_epg,
66.403 - GMythChannelInfo * channel_info, guint8 ** data,
66.404 - guint * length)
66.405 -{
66.406 - gboolean res = FALSE;
66.407 -
66.408 - g_return_val_if_fail(gmyth_epg != NULL, FALSE);
66.409 - g_return_val_if_fail(channel_info != NULL, FALSE);
66.410 -
66.411 - if (gmyth_epg_channel_has_icon(gmyth_epg, channel_info)) {
66.412 - GMythFileTransfer *transfer =
66.413 - gmyth_file_transfer_new(gmyth_epg->backend_info);
66.414 -
66.415 - GMythFileReadResult gmyth_res;
66.416 - GByteArray *icon_data;
66.417 - guint64 icon_length = 0;
66.418 -
66.419 - res = gmyth_file_transfer_open(transfer,
66.420 - channel_info->channel_icon->str);
66.421 - if (!res) {
66.422 - gmyth_debug("Channel icon could not be opened");
66.423 - return FALSE;
66.424 - }
66.425 -
66.426 - icon_length = gmyth_file_transfer_get_filesize(transfer);
66.427 - if (icon_length <= 0) {
66.428 - gmyth_debug("Channel icon file size is zero or negative");
66.429 - return FALSE;
66.430 - }
66.431 -
66.432 - icon_data = g_byte_array_new();
66.433 - gmyth_res = gmyth_file_transfer_read(transfer,
66.434 - icon_data,
66.435 - icon_length, FALSE);
66.436 - if (gmyth_res == GMYTH_FILE_READ_EOF) {
66.437 - *length = icon_length;
66.438 - *data = icon_data->data;
66.439 - g_byte_array_free(icon_data, FALSE);
66.440 - res = TRUE;
66.441 - } else {
66.442 - *length = 0;
66.443 - *data = NULL;
66.444 - g_byte_array_free(icon_data, TRUE);
66.445 - }
66.446 - }
66.447 -
66.448 - return res;
66.449 -}
67.1 --- a/gmyth/src/gmyth_epg.h Mon Feb 25 17:45:36 2008 +0000
67.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
67.3 @@ -1,85 +0,0 @@
67.4 -/**
67.5 - * GMyth Library
67.6 - *
67.7 - * @file gmyth/gmyth_epg.h
67.8 - *
67.9 - * @brief <p> GMythEPG class provides access to the program and channel data
67.10 - * from the Electronic Program Guide (EPG) of the Mythtv backend.
67.11 - *
67.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
67.13 - * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
67.14 - *
67.15 - * This program is free software; you can redistribute it and/or modify
67.16 - * it under the terms of the GNU Lesser General Public License as published by
67.17 - * the Free Software Foundation; either version 2 of the License, or
67.18 - * (at your option) any later version.
67.19 - *
67.20 - * This program is distributed in the hope that it will be useful,
67.21 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
67.22 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
67.23 - * GNU General Public License for more details.
67.24 - *
67.25 - * You should have received a copy of the GNU Lesser General Public License
67.26 - * along with this program; if not, write to the Free Software
67.27 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
67.28 - */
67.29 -
67.30 -#ifndef GMYTH_EPG_H_
67.31 -#define GMYTH_EPG_H_
67.32 -
67.33 -#include <glib-object.h>
67.34 -
67.35 -#include "gmyth_query.h"
67.36 -#include "gmyth_common.h"
67.37 -
67.38 -G_BEGIN_DECLS
67.39 -#define GMYTH_EPG_TYPE (gmyth_epg_get_type ())
67.40 -#define GMYTH_EPG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_EPG_TYPE, GMythEPG))
67.41 -#define GMYTH_EPG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_EPG_TYPE, GMythEPGClass))
67.42 -#define IS_GMYTH_EPG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_EPG_TYPE))
67.43 -#define IS_GMYTH_EPG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_EPG_TYPE))
67.44 -#define GMYTH_EPG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_EPG_TYPE, GMythEPGClass))
67.45 -typedef struct _GMythEPG GMythEPG;
67.46 -typedef struct _GMythEPGClass GMythEPGClass;
67.47 -
67.48 -struct _GMythEPGClass {
67.49 - GObjectClass parent_class;
67.50 -
67.51 - /*
67.52 - * callbacks
67.53 - */
67.54 - /*
67.55 - * no one for now
67.56 - */
67.57 -};
67.58 -
67.59 -struct _GMythEPG {
67.60 - GObject parent;
67.61 -
67.62 - GMythQuery *sqlquery;
67.63 - GMythBackendInfo *backend_info;
67.64 -};
67.65 -
67.66 -GType gmyth_epg_get_type (void) G_GNUC_CONST;;
67.67 -GMythEPG* gmyth_epg_new (void);
67.68 -gboolean gmyth_epg_connect (GMythEPG *gmyth_epg,
67.69 - GMythBackendInfo *backend_info);
67.70 -gboolean gmyth_epg_disconnect (GMythEPG *gmyth_epg);
67.71 -gint gmyth_epg_get_channel_list (GMythEPG *gmyth_epg,
67.72 - GList **glist_ptr);
67.73 -gint gmyth_epg_get_program_list (GMythEPG *gmyth_epg,
67.74 - GList **proglist,
67.75 - gint chanNum,
67.76 - GTimeVal *starttime,
67.77 - GTimeVal *endtime);
67.78 -GMythChannelInfo*gmyth_epg_get_channel_info (GMythEPG *gmyth_epg,
67.79 - gint channel_id);
67.80 -gboolean gmyth_epg_channel_has_icon (GMythEPG *gmyth_epg,
67.81 - GMythChannelInfo *channel);
67.82 -gboolean gmyth_epg_channel_get_icon (GMythEPG *gmyth_epg,
67.83 - GMythChannelInfo *channel,
67.84 - guint8 **data,
67.85 - guint *length);
67.86 -
67.87 -G_END_DECLS
67.88 -#endif /* GMYTH_EPG_H_ */
68.1 --- a/gmyth/src/gmyth_file.c Mon Feb 25 17:45:36 2008 +0000
68.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
68.3 @@ -1,515 +0,0 @@
68.4 -/**
68.5 - * GMyth Library
68.6 - *
68.7 - * @file gmyth/gmyth_file.c
68.8 - *
68.9 - * @brief <p> GMythFile deals with the file streaming media remote/local
68.10 - * transfering to the MythTV frontend.
68.11 - *
68.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
68.13 - * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
68.14 - *
68.15 - *
68.16 - * This program is free software; you can redistribute it and/or modify
68.17 - * it under the terms of the GNU Lesser General Public License as published by
68.18 - * the Free Software Foundation; either version 2 of the License, or
68.19 - * (at your option) any later version.
68.20 - *
68.21 - * This program is distributed in the hope that it will be useful,
68.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
68.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
68.24 - * GNU General Public License for more details.
68.25 - *
68.26 - * You should have received a copy of the GNU Lesser General Public License
68.27 - * along with this program; if not, write to the Free Software
68.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
68.29 - */
68.30 -
68.31 -#ifdef HAVE_CONFIG_H
68.32 -#include "config.h"
68.33 -#endif
68.34 -
68.35 -#include "gmyth_file.h"
68.36 -#include "gmyth_recorder.h"
68.37 -#include "gmyth_util.h"
68.38 -#include "gmyth_socket.h"
68.39 -#include "gmyth_stringlist.h"
68.40 -#include "gmyth_debug.h"
68.41 -#include "gmyth_uri.h"
68.42 -#include "gmyth_marshal.h"
68.43 -
68.44 -#include <unistd.h>
68.45 -#include <glib.h>
68.46 -
68.47 -#include <arpa/inet.h>
68.48 -#include <sys/types.h>
68.49 -#include <sys/socket.h>
68.50 -#include <netdb.h>
68.51 -#include <errno.h>
68.52 -#include <stdlib.h>
68.53 -#include <assert.h>
68.54 -
68.55 -#define GMYTH_FILE_GET_PRIVATE(obj) \
68.56 - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_TYPE, GMythFilePrivate))
68.57 -
68.58 -struct _GMythFilePrivate {
68.59 - gboolean disposed;
68.60 - gint64 offset;
68.61 - guint64 filesize;
68.62 -
68.63 - GMythBackendInfo *backend_info;
68.64 -
68.65 - /*
68.66 - * Myth URI structure
68.67 - */
68.68 - gchar *filename;
68.69 -
68.70 - gint file_id;
68.71 -};
68.72 -
68.73 -enum {
68.74 - PROP_GMYTH_FILE_DUMMY,
68.75 - PROP_GMYTH_FILE_FILENAME,
68.76 - PROP_GMYTH_FILE_OFFSET,
68.77 - PROP_GMYTH_FILE_FILESIZE,
68.78 - PROP_GMYTH_FILE_BACKEND_INFO,
68.79 - PROP_GMYTH_FILE_FILEID
68.80 -};
68.81 -
68.82 -static void gmyth_file_set_property(GObject * object, guint prop_id,
68.83 - const GValue * value,
68.84 - GParamSpec * pspec);
68.85 -static void gmyth_file_get_property(GObject * object, guint prop_id,
68.86 - GValue * value,
68.87 - GParamSpec * pspec);
68.88 -
68.89 -static void gmyth_file_class_init(GMythFileClass * klass);
68.90 -static void gmyth_file_init(GMythFile * object);
68.91 -static void gmyth_file_dispose(GObject * object);
68.92 -static void gmyth_file_finalize(GObject * object);
68.93 -
68.94 -G_DEFINE_TYPE(GMythFile, gmyth_file, G_TYPE_OBJECT)
68.95 - static void gmyth_file_class_init(GMythFileClass * klass)
68.96 -{
68.97 - GObjectClass *gobject_class;
68.98 - GMythFileClass *gtransfer_class;
68.99 -
68.100 - gobject_class = (GObjectClass *) klass;
68.101 - gtransfer_class = (GMythFileClass *) gobject_class;
68.102 -
68.103 - gobject_class->dispose = gmyth_file_dispose;
68.104 - gobject_class->finalize = gmyth_file_finalize;
68.105 -
68.106 - gobject_class->set_property = gmyth_file_set_property;
68.107 - gobject_class->get_property = gmyth_file_get_property;
68.108 -
68.109 - g_object_class_install_property
68.110 - (gobject_class, PROP_GMYTH_FILE_FILENAME,
68.111 - g_param_spec_string("filename", "filename",
68.112 - "The file name.",
68.113 - "",
68.114 - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
68.115 - G_PARAM_STATIC_BLURB | G_PARAM_READABLE |
68.116 - G_PARAM_WRITABLE));
68.117 -
68.118 - g_object_class_install_property
68.119 - (gobject_class, PROP_GMYTH_FILE_OFFSET,
68.120 - g_param_spec_int64("file-offset", "file-offset",
68.121 - "The offset (position) of this file", 0,
68.122 - G_MAXINT64, 0,
68.123 - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
68.124 - G_PARAM_STATIC_BLURB | G_PARAM_READABLE |
68.125 - G_PARAM_WRITABLE));
68.126 -
68.127 - g_object_class_install_property
68.128 - (gobject_class, PROP_GMYTH_FILE_FILESIZE,
68.129 - g_param_spec_uint64("file-size", "file-size",
68.130 - "The file size in bytes",
68.131 - 0, G_MAXUINT64, 0,
68.132 - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
68.133 - G_PARAM_STATIC_BLURB | G_PARAM_READABLE |
68.134 - G_PARAM_WRITABLE));
68.135 -
68.136 - g_object_class_install_property
68.137 - (gobject_class, PROP_GMYTH_FILE_BACKEND_INFO,
68.138 - g_param_spec_object("backend-info", "backend-info",
68.139 - "The Backend Information about the remote server",
68.140 - G_TYPE_OBJECT,
68.141 - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
68.142 - G_PARAM_STATIC_BLURB | G_PARAM_READABLE |
68.143 - G_PARAM_WRITABLE));
68.144 -
68.145 - g_object_class_install_property
68.146 - (gobject_class, PROP_GMYTH_FILE_FILEID,
68.147 - g_param_spec_int("file-id", "file-id",
68.148 - "The file ID", 0, G_MAXINT, 0,
68.149 - G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
68.150 - G_PARAM_STATIC_BLURB | G_PARAM_READABLE |
68.151 - G_PARAM_WRITABLE));
68.152 -
68.153 - g_type_class_add_private(gobject_class, sizeof(GMythFilePrivate));
68.154 -
68.155 -}
68.156 -
68.157 -static void
68.158 -gmyth_file_init(GMythFile * file)
68.159 -{
68.160 - g_return_if_fail(file != NULL);
68.161 -
68.162 - file->priv = GMYTH_FILE_GET_PRIVATE(file);
68.163 -}
68.164 -
68.165 -static void
68.166 -gmyth_file_dispose(GObject * object)
68.167 -{
68.168 - GMythFilePrivate *priv;
68.169 - GMythFile *file = GMYTH_FILE(object);
68.170 -
68.171 - g_return_if_fail(file != NULL);
68.172 -
68.173 - priv = GMYTH_FILE_GET_PRIVATE(file);
68.174 -
68.175 - if (priv->disposed) {
68.176 - /*
68.177 - * If dispose did already run, return.
68.178 - */
68.179 - return;
68.180 - }
68.181 -
68.182 - /*
68.183 - * Make sure dispose does not run twice.
68.184 - */
68.185 - priv->disposed = TRUE;
68.186 -
68.187 - if (priv->backend_info != NULL) {
68.188 - g_object_unref(priv->backend_info);
68.189 - priv->backend_info = NULL;
68.190 - }
68.191 -
68.192 - if (priv->filename != NULL) {
68.193 - g_free(priv->filename);
68.194 - priv->filename = NULL;
68.195 - }
68.196 -
68.197 - G_OBJECT_CLASS(gmyth_file_parent_class)->dispose(object);
68.198 -}
68.199 -
68.200 -static void
68.201 -gmyth_file_finalize(GObject * object)
68.202 -{
68.203 - g_signal_handlers_destroy(object);
68.204 -
68.205 - G_OBJECT_CLASS(gmyth_file_parent_class)->finalize(object);
68.206 -}
68.207 -
68.208 -/**
68.209 - * Creates a new instance of GMythFile.
68.210 - *
68.211 - * @param backend_info The BackendInfo instance, with all the MythTV network
68.212 - * configuration data.
68.213 - *
68.214 - * @return a new instance of the File Transfer.
68.215 - */
68.216 -GMythFile *
68.217 -gmyth_file_new(GMythBackendInfo * backend_info)
68.218 -{
68.219 - GMythFile *file = NULL;
68.220 -
68.221 - g_return_val_if_fail(backend_info != NULL, NULL);
68.222 -
68.223 - GParameter *__params = g_new0(GParameter, 1);
68.224 - GParameter *__params_it = __params;
68.225 -
68.226 - (__params_it->name =
68.227 - "backend-info", g_value_init(&__params_it->value, G_TYPE_OBJECT),
68.228 - g_value_set_object(&__params_it->value, backend_info), __params_it++);
68.229 - file =
68.230 - g_object_newv(GMYTH_FILE_TYPE, __params_it - __params, __params);
68.231 -
68.232 - return file;
68.233 -}
68.234 -
68.235 -gchar *
68.236 -gmyth_file_get_file_name(GMythFile * file)
68.237 -{
68.238 - GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(file);
68.239 -
68.240 - g_return_val_if_fail(file != NULL, NULL);
68.241 -
68.242 - return priv->filename;
68.243 -}
68.244 -
68.245 -void
68.246 -gmyth_file_set_file_name(GMythFile * file, const gchar * filename)
68.247 -{
68.248 - g_return_if_fail(file != NULL);
68.249 - g_return_if_fail(filename != NULL);
68.250 -
68.251 - gchar *__temp2 = NULL;
68.252 - const gchar *__temp1 = NULL;
68.253 -
68.254 - file->priv->filename = (__temp2 =
68.255 - (__temp1 =
68.256 - filename,
68.257 - (__temp1 == NULL ? NULL : g_strdup(__temp1))),
68.258 - (file->priv->filename ==
68.259 - NULL ? NULL : (file->priv->filename =
68.260 - (g_free(file->priv->filename),
68.261 - NULL))), __temp2);
68.262 -}
68.263 -
68.264 -/**
68.265 - * Creates a new instance of GMythFile.
68.266 - *
68.267 - * @param uri_str The URI poiting to the MythTV backend server.
68.268 - *
68.269 - * @return a new instance of the File Transfer.
68.270 - */
68.271 -GMythFile *
68.272 -gmyth_file_new_with_uri(const gchar * uri_str)
68.273 -{
68.274 - GMythFile *file = GMYTH_FILE(g_object_new(GMYTH_FILE_TYPE, NULL));
68.275 - GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(file);
68.276 -
68.277 - priv->backend_info = gmyth_backend_info_new_with_uri(uri_str);
68.278 - return file;
68.279 -}
68.280 -
68.281 -/**
68.282 - * Open a File Transfer connection in order to get a remote file.
68.283 - *
68.284 - * @param file The actual File Transfer instance.
68.285 - * @param filename The file name of the remote file to be transfered to the client.
68.286 - *
68.287 - * @return <code>true</code>, if the connection opening had been done successfully.
68.288 - */
68.289 -gboolean
68.290 -gmyth_file_setup(GMythFile * file, const gchar * filename)
68.291 -{
68.292 - gboolean ret = TRUE;
68.293 - GMythFilePrivate *priv;
68.294 -
68.295 - g_return_val_if_fail(file != NULL, FALSE);
68.296 - g_return_val_if_fail(filename != NULL && strlen(filename) > 0, FALSE);
68.297 -
68.298 - priv = GMYTH_FILE_GET_PRIVATE(file);
68.299 -
68.300 - if (priv->filename != NULL) {
68.301 - gmyth_file_close(file);
68.302 - }
68.303 -
68.304 - priv->filename = g_strdup(filename);
68.305 -
68.306 - return ret;
68.307 -}
68.308 -
68.309 -/**
68.310 - * Closes a remote File Transfer connection.
68.311 - *
68.312 - * @param file The actual File Transfer instance.
68.313 - */
68.314 -void
68.315 -gmyth_file_close(GMythFile * file)
68.316 -{
68.317 - GMythFilePrivate *priv;
68.318 -
68.319 - priv = GMYTH_FILE_GET_PRIVATE(file);
68.320 -
68.321 - if (priv->filename) {
68.322 - g_free(priv->filename);
68.323 - priv->filename = NULL;
68.324 - }
68.325 -
68.326 -}
68.327 -
68.328 -/**
68.329 - * Gets the actual file size of the binary content.
68.330 - *
68.331 - * @param file The actual File Transfer instance.
68.332 - *
68.333 - * @return The actual file size in bytes.
68.334 - */
68.335 -guint64
68.336 -gmyth_file_get_filesize(GMythFile * file)
68.337 -{
68.338 - GMythFilePrivate *priv;
68.339 -
68.340 - g_return_val_if_fail(file != NULL, 0);
68.341 -
68.342 - priv = GMYTH_FILE_GET_PRIVATE(file);
68.343 - return priv->filesize;
68.344 -}
68.345 -
68.346 -/**
68.347 - * Sets the actual file size.
68.348 - *
68.349 - * @param file The actual File Transfer instance.
68.350 - * @param filesize The actual File Transfer size, in bytes.
68.351 - */
68.352 -void
68.353 -gmyth_file_set_filesize(GMythFile * file, guint64 filesize)
68.354 -{
68.355 - GMythFilePrivate *priv;
68.356 -
68.357 - priv = GMYTH_FILE_GET_PRIVATE(file);
68.358 -
68.359 - priv->filesize = filesize;
68.360 -}
68.361 -
68.362 -/**
68.363 - * Gets the actual offset of the binary content.
68.364 - *
68.365 - * @param file The actual File Transfer instance.
68.366 - *
68.367 - * @return The actual file offset in bytes.
68.368 - */
68.369 -gint64
68.370 -gmyth_file_get_offset(GMythFile * file)
68.371 -{
68.372 - g_return_val_if_fail(file != NULL, 0);
68.373 -
68.374 - return file->priv->offset;
68.375 -}
68.376 -
68.377 -/**
68.378 - * Sets the actual file offset.
68.379 - *
68.380 - * @param file The actual File instance.
68.381 - * @param filesize The actual File offset, in bytes.
68.382 - */
68.383 -void
68.384 -gmyth_file_set_offset(GMythFile * file, gint64 offset)
68.385 -{
68.386 - GMythFilePrivate *priv;
68.387 -
68.388 - priv = GMYTH_FILE_GET_PRIVATE(file);
68.389 -
68.390 - priv->offset = offset;
68.391 -}
68.392 -
68.393 -gchar *
68.394 -gmyth_file_get_uri(GMythFile * file)
68.395 -{
68.396 - GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(file);
68.397 - gchar *uri = NULL;
68.398 -
68.399 - g_return_val_if_fail(file != NULL, NULL);
68.400 -
68.401 - if (g_strstr_len(priv->filename, strlen(priv->filename), "://") !=
68.402 - NULL)
68.403 - uri = g_strdup(priv->filename);
68.404 - else
68.405 - uri =
68.406 - g_strdup_printf("myth://%s:%d/%s",
68.407 - gmyth_backend_info_get_hostname(priv->
68.408 - backend_info),
68.409 - gmyth_backend_info_get_port(priv->
68.410 - backend_info),
68.411 - priv->filename);
68.412 -
68.413 - return uri;
68.414 -}
68.415 -
68.416 -static void
68.417 -gmyth_file_set_property(GObject * object, guint prop_id,
68.418 - const GValue * value, GParamSpec * pspec)
68.419 -{
68.420 - GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(GMYTH_FILE(object));
68.421 -
68.422 - switch (prop_id) {
68.423 - case PROP_GMYTH_FILE_FILENAME:
68.424 - {
68.425 - if (!g_value_get_string(value)) {
68.426 - break;
68.427 - }
68.428 -
68.429 - if (priv->filename != NULL) {
68.430 - g_free(priv->filename);
68.431 - priv->filename = NULL;
68.432 - }
68.433 -
68.434 - priv->filename = g_value_dup_string(value);
68.435 - gmyth_debug("Changed the filename to [%s]!", priv->filename);
68.436 - break;
68.437 - }
68.438 - case PROP_GMYTH_FILE_OFFSET:
68.439 - {
68.440 - priv->offset = g_value_get_int64(value);
68.441 - break;
68.442 - }
68.443 - case PROP_GMYTH_FILE_FILESIZE:
68.444 - {
68.445 - priv->filesize = g_value_get_uint64(value);
68.446 - break;
68.447 - }
68.448 - case PROP_GMYTH_FILE_BACKEND_INFO:
68.449 - {
68.450 - if (!g_value_get_object(value)) {
68.451 - break;
68.452 - }
68.453 -
68.454 - if (priv->backend_info != NULL) {
68.455 - g_object_unref(priv->backend_info);
68.456 - priv->backend_info = NULL;
68.457 - }
68.458 -
68.459 - priv->backend_info = g_value_get_object(value);
68.460 - gmyth_debug("Changed the backend info to [%s]!",
68.461 - gmyth_backend_info_get_hostname(priv->
68.462 - backend_info));
68.463 - break;
68.464 - }
68.465 - case PROP_GMYTH_FILE_FILEID:
68.466 - {
68.467 - priv->file_id = g_value_get_int(value);
68.468 - break;
68.469 - }
68.470 -
68.471 - default:
68.472 - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
68.473 - break;
68.474 - }
68.475 -
68.476 -}
68.477 -
68.478 -static void
68.479 -gmyth_file_get_property(GObject * object, guint prop_id,
68.480 - GValue * value, GParamSpec * pspec)
68.481 -{
68.482 - GMythFilePrivate *priv = GMYTH_FILE_GET_PRIVATE(GMYTH_FILE(object));
68.483 -
68.484 - switch (prop_id) {
68.485 - case PROP_GMYTH_FILE_FILENAME:
68.486 - {
68.487 - gmyth_debug("Got the filename to [%s]!", priv->filename);
68.488 - g_value_set_string(value, priv->filename);
68.489 - break;
68.490 - }
68.491 - case PROP_GMYTH_FILE_OFFSET:
68.492 - {
68.493 - g_value_set_int64(value, priv->offset);
68.494 - break;
68.495 - }
68.496 - case PROP_GMYTH_FILE_FILESIZE:
68.497 - {
68.498 - g_value_set_uint64(value, priv->filesize);
68.499 - break;
68.500 - }
68.501 - case PROP_GMYTH_FILE_BACKEND_INFO:
68.502 - {
68.503 - g_value_set_object(value, priv->backend_info);
68.504 - break;
68.505 - }
68.506 - case PROP_GMYTH_FILE_FILEID:
68.507 - {
68.508 - g_value_set_int(value, priv->file_id);
68.509 - break;
68.510 - }
68.511 - default:
68.512 - {
68.513 - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
68.514 - break;
68.515 - }
68.516 - }
68.517 -
68.518 -}
69.1 --- a/gmyth/src/gmyth_file.h Mon Feb 25 17:45:36 2008 +0000
69.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
69.3 @@ -1,90 +0,0 @@
69.4 -/**
69.5 - * GMyth Library
69.6 - *
69.7 - * @file gmyth/gmyth_file.h
69.8 - *
69.9 - * @brief <p> GMythFile is the parent GMObject that deals with the file streaming
69.10 - * media remote/local transfering to the MythTV frontend.
69.11 - *
69.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
69.13 - * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
69.14 - *
69.15 - *
69.16 - * This program is free software; you can redistribute it and/or modify
69.17 - * it under the terms of the GNU Lesser General Public License as published by
69.18 - * the Free Software Foundation; either version 2 of the License, or
69.19 - * (at your option) any later version.
69.20 - *
69.21 - * This program is distributed in the hope that it will be useful,
69.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
69.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
69.24 - * GNU General Public License for more details.
69.25 - *
69.26 - * You should have received a copy of the GNU Lesser General Public License
69.27 - * along with this program; if not, write to the Free Software
69.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
69.29 - */
69.30 -
69.31 -#ifndef __GMYTH_FILE_H__
69.32 -#define __GMYTH_FILE_H__
69.33 -
69.34 -#include <glib-object.h>
69.35 -#include <glib.h>
69.36 -
69.37 -#include "gmyth_uri.h"
69.38 -#include "gmyth_backendinfo.h"
69.39 -
69.40 -#include <stdio.h>
69.41 -#include <stdlib.h>
69.42 -#include <string.h>
69.43 -#include <netdb.h>
69.44 -#include <sys/socket.h>
69.45 -#include <unistd.h>
69.46 -
69.47 -G_BEGIN_DECLS
69.48 -#define GMYTH_FILE_TYPE (gmyth_file_get_type ())
69.49 -#define GMYTH_FILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_FILE_TYPE, GMythFile))
69.50 -#define GMYTH_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TYPE, GMythFileClass))
69.51 -#define IS_GMYTH_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_FILE_TYPE))
69.52 -#define IS_GMYTH_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TYPE))
69.53 -#define GMYTH_FILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_FILE_TYPE, GMythFileClass))
69.54 -
69.55 -typedef enum {
69.56 - GMYTH_FILE_READ_OK = 0,
69.57 - GMYTH_FILE_READ_NEXT_PROG_CHAIN = 1,
69.58 - GMYTH_FILE_READ_ERROR = 2,
69.59 - GMYTH_FILE_READ_EOF = 3
69.60 -} GMythFileReadResult;
69.61 -
69.62 -typedef struct _GMythFile GMythFile;
69.63 -typedef struct _GMythFileClass GMythFileClass;
69.64 -typedef struct _GMythFilePrivate GMythFilePrivate;
69.65 -
69.66 -struct _GMythFile {
69.67 - GObject parent;
69.68 - GMythFilePrivate *priv;
69.69 -};
69.70 -
69.71 -struct _GMythFileClass {
69.72 - GObjectClass parent_class;
69.73 -};
69.74 -
69.75 -GType gmyth_file_get_type (void);
69.76 -GMythFile *gmyth_file_new (GMythBackendInfo *backend_info);
69.77 -gchar *gmyth_file_get_file_name (GMythFile *file);
69.78 -void gmyth_file_set_file_name (GMythFile *file,
69.79 - const gchar *filename);
69.80 -gboolean gmyth_file_setup (GMythFile *file,
69.81 - const gchar *filename);
69.82 -void gmyth_file_close (GMythFile *file);
69.83 -gboolean gmyth_file_is_open (GMythFile *file);
69.84 -guint64 gmyth_file_get_filesize (GMythFile *file);
69.85 -void gmyth_file_set_filesize (GMythFile *file,
69.86 - guint64 filesize);
69.87 -gint64 gmyth_file_get_offset (GMythFile *file);
69.88 -void gmyth_file_set_offset (GMythFile *file,
69.89 - gint64 offset);
69.90 -gchar *gmyth_file_get_uri (GMythFile *file);
69.91 -
69.92 -G_END_DECLS
69.93 -#endif /* __GMYTH_FILE_H__ */
70.1 --- a/gmyth/src/gmyth_file_local.c Mon Feb 25 17:45:36 2008 +0000
70.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
70.3 @@ -1,464 +0,0 @@
70.4 -/**
70.5 - * GMyth Library
70.6 - *
70.7 - * @file_local gmyth/gmyth_file_local.c
70.8 - *
70.9 - * @brief <p> GMythFileLocal deals with the file_local streaming media remote/local
70.10 - * transfering to the MythTV frontend.
70.11 - *
70.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
70.13 - * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
70.14 - *
70.15 - *
70.16 - * This program is free software; you can redistribute it and/or modify
70.17 - * it under the terms of the GNU Lesser General Public License as published by
70.18 - * the Free Software Foundation; either version 2 of the License, or
70.19 - * (at your option) any later version.
70.20 - *
70.21 - * This program is distributed in the hope that it will be useful,
70.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
70.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
70.24 - * GNU General Public License for more details.
70.25 - *
70.26 - * You should have received a copy of the GNU Lesser General Public License
70.27 - * along with this program; if not, write to the Free Software
70.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
70.29 - */
70.30 -
70.31 -#ifdef HAVE_CONFIG_H
70.32 -#include "config.h"
70.33 -#endif
70.34 -
70.35 -#include "gmyth_file_local.h"
70.36 -#include "gmyth_recorder.h"
70.37 -#include "gmyth_util.h"
70.38 -#include "gmyth_socket.h"
70.39 -#include "gmyth_stringlist.h"
70.40 -#include "gmyth_debug.h"
70.41 -#include "gmyth_uri.h"
70.42 -#include "gmyth_marshal.h"
70.43 -
70.44 -#include <unistd.h>
70.45 -#include <glib.h>
70.46 -
70.47 -#include <arpa/inet.h>
70.48 -#include <sys/types.h>
70.49 -#include <sys/socket.h>
70.50 -#include <netdb.h>
70.51 -#include <errno.h>
70.52 -#include <stdlib.h>
70.53 -#include <assert.h>
70.54 -
70.55 -#define GMYTH_FILE_LOCAL_GET_PRIVATE(obj) \
70.56 - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_LOCAL_TYPE, GMythFileLocalPrivate))
70.57 -
70.58 -struct _GMythFileLocalPrivate {
70.59 -
70.60 - gboolean disposed;
70.61 -
70.62 - GMutex *mutex;
70.63 -
70.64 - gint fd;
70.65 -
70.66 - GIOChannel *file_io;
70.67 -
70.68 -};
70.69 -
70.70 -static void gmyth_file_local_class_init(GMythFileLocalClass * klass);
70.71 -static void gmyth_file_local_init(GMythFileLocal * object);
70.72 -static void gmyth_file_local_dispose(GObject * object);
70.73 -static void gmyth_file_local_finalize(GObject * object);
70.74 -
70.75 -static gboolean _control_acquire_context(GMythFileLocal * file_local,
70.76 - gboolean do_wait);
70.77 -
70.78 -static gboolean _control_release_context(GMythFileLocal * file_local);
70.79 -
70.80 -G_DEFINE_TYPE(GMythFileLocal, gmyth_file_local, GMYTH_FILE_TYPE)
70.81 - static void gmyth_file_local_class_init(GMythFileLocalClass *
70.82 - klass)
70.83 -{
70.84 - GObjectClass *gobject_class;
70.85 - GMythFileLocalClass *gtransfer_class;
70.86 -
70.87 - gobject_class = (GObjectClass *) klass;
70.88 - gtransfer_class = (GMythFileLocalClass *) gobject_class;
70.89 -
70.90 - gobject_class->dispose = gmyth_file_local_dispose;
70.91 - gobject_class->finalize = gmyth_file_local_finalize;
70.92 -
70.93 - g_type_class_add_private(gobject_class, sizeof(GMythFileLocalPrivate));
70.94 -
70.95 -}
70.96 -
70.97 -static void
70.98 -gmyth_file_local_init(GMythFileLocal * file_local)
70.99 -{
70.100 - GMythFileLocalPrivate *priv;
70.101 -
70.102 - g_return_if_fail(file_local != NULL);
70.103 -
70.104 - priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
70.105 -
70.106 - priv->mutex = g_mutex_new();
70.107 -}
70.108 -
70.109 -static void
70.110 -gmyth_file_local_dispose(GObject * object)
70.111 -{
70.112 - GMythFileLocalPrivate *priv;
70.113 - GMythFileLocal *file_local = GMYTH_FILE_LOCAL(object);
70.114 -
70.115 - g_return_if_fail(file_local != NULL);
70.116 -
70.117 - priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
70.118 -
70.119 - if (priv->disposed) {
70.120 - /*
70.121 - * If dispose did already run, return.
70.122 - */
70.123 - return;
70.124 - }
70.125 -
70.126 - /*
70.127 - * Make sure dispose does not run twice.
70.128 - */
70.129 - priv->disposed = TRUE;
70.130 -
70.131 - if (priv->mutex != NULL) {
70.132 - g_mutex_free(priv->mutex);
70.133 - priv->mutex = NULL;
70.134 - }
70.135 -
70.136 - if (priv->file_io != NULL) {
70.137 - g_io_channel_unref(priv->file_io);
70.138 - priv->file_io = NULL;
70.139 - }
70.140 -
70.141 - G_OBJECT_CLASS(gmyth_file_local_parent_class)->dispose(object);
70.142 -}
70.143 -
70.144 -static void
70.145 -gmyth_file_local_finalize(GObject * object)
70.146 -{
70.147 - g_signal_handlers_destroy(object);
70.148 -
70.149 - G_OBJECT_CLASS(gmyth_file_local_parent_class)->finalize(object);
70.150 -}
70.151 -
70.152 -/**
70.153 - * Creates a new instance of GMythFileLocal.
70.154 - *
70.155 - * @param backend_info The BackendInfo instance, with all the MythTV network
70.156 - * configuration data.
70.157 - *
70.158 - * @return a new instance of the File Transfer.
70.159 - */
70.160 -GMythFileLocal *
70.161 -gmyth_file_local_new(GMythBackendInfo * backend_info)
70.162 -{
70.163 - GMythFileLocal *file_local =
70.164 - GMYTH_FILE_LOCAL(g_object_new(GMYTH_FILE_LOCAL_TYPE, NULL));
70.165 -
70.166 - g_object_set(GMYTH_FILE(file_local), "backend-info", &backend_info,
70.167 - NULL);
70.168 -
70.169 - return file_local;
70.170 -}
70.171 -
70.172 -/**
70.173 - * Creates a new instance of GMythFileLocal.
70.174 - *
70.175 - * @param uri_str The URI poiting to the MythTV backend server.
70.176 - *
70.177 - * @return a new instance of the File Transfer.
70.178 - */
70.179 -GMythFileLocal *
70.180 -gmyth_file_local_new_with_uri(const gchar * uri_str)
70.181 -{
70.182 - GMythFileLocal *file_local =
70.183 - GMYTH_FILE_LOCAL(g_object_new(GMYTH_FILE_LOCAL_TYPE, NULL));
70.184 - GMythURI *uri = gmyth_uri_new_with_value(uri_str);
70.185 -
70.186 - gmyth_debug("GMythURI path segment = %s", gmyth_uri_get_path(uri));
70.187 -
70.188 - g_object_set(GMYTH_FILE(file_local),
70.189 - "backend-info", gmyth_backend_info_new_with_uri(uri_str),
70.190 - "filename", g_strdup(gmyth_uri_get_path(uri)), NULL);
70.191 -
70.192 - g_object_unref(uri);
70.193 -
70.194 - return file_local;
70.195 -}
70.196 -
70.197 -gchar *
70.198 -gmyth_file_local_get_file_name(GMythFileLocal * file_local)
70.199 -{
70.200 - return gmyth_file_get_file_name(GMYTH_FILE(file_local));
70.201 -}
70.202 -
70.203 -void
70.204 -gmyth_file_local_set_file_name(GMythFileLocal * file_local,
70.205 - const gchar * filename)
70.206 -{
70.207 - gmyth_file_set_file_name(GMYTH_FILE(file_local), filename);
70.208 -}
70.209 -
70.210 -/**
70.211 - * Open a File in order to get a local file.
70.212 - *
70.213 - * @param file_local The actual File Transfer instance.
70.214 - *
70.215 - * @return <code>true</code>, if the connection opening had been done successfully.
70.216 - */
70.217 -gboolean
70.218 -gmyth_file_local_open(GMythFileLocal * file_local)
70.219 -{
70.220 - gboolean ret = TRUE;
70.221 - GMythFileLocalPrivate *priv;
70.222 - gchar *file_name_uri = NULL;
70.223 -
70.224 - g_return_val_if_fail(file_local != NULL, FALSE);
70.225 -
70.226 - priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
70.227 - file_name_uri = gmyth_file_local_get_file_name(file_local);
70.228 -
70.229 - if (file_name_uri != NULL) {
70.230 - priv->file_io =
70.231 - g_io_channel_new_file(g_strdup(file_name_uri), "r+", NULL);
70.232 - g_free(file_name_uri);
70.233 - }
70.234 -
70.235 - if (priv->file_io < 0)
70.236 - ret = FALSE;
70.237 -
70.238 - return ret;
70.239 -}
70.240 -
70.241 -/**
70.242 - * Closes a remote File Transfer connection.
70.243 - *
70.244 - * @param file_local The actual File Transfer instance.
70.245 - */
70.246 -void
70.247 -gmyth_file_local_close(GMythFileLocal * file_local)
70.248 -{
70.249 - g_return_if_fail(file_local != NULL);
70.250 -}
70.251 -
70.252 -/**
70.253 - * Acquire access to a local file read/write pointer.
70.254 - *
70.255 - * @param transfer The actual File Local instance.
70.256 - * @param do_wait Waits or not on a GCond, when trying to read from the remote socket.
70.257 - *
70.258 - * @return <code>true</code>, if the acquire had been got.
70.259 - */
70.260 -static gboolean
70.261 -_control_acquire_context(GMythFileLocal * file_local, gboolean do_wait)
70.262 -{
70.263 - gboolean ret = TRUE;
70.264 - GMythFileLocalPrivate *priv;
70.265 -
70.266 - g_return_val_if_fail(file_local != NULL, FALSE);
70.267 - priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
70.268 -
70.269 - g_mutex_lock(priv->mutex);
70.270 - return ret;
70.271 -}
70.272 -
70.273 -/**
70.274 - * Release access to a local file read/write pointer.
70.275 - *
70.276 - * @param transfer The actual File Transfer instance.
70.277 - *
70.278 - * @return <code>true</code>, if the local file read/write permissions had been releaseds.
70.279 - */
70.280 -static gboolean
70.281 -_control_release_context(GMythFileLocal * file_local)
70.282 -{
70.283 - gboolean ret = TRUE;
70.284 - GMythFileLocalPrivate *priv;
70.285 -
70.286 - g_return_val_if_fail(file_local != NULL, FALSE);
70.287 - priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
70.288 -
70.289 - g_mutex_unlock(priv->mutex);
70.290 -
70.291 - return ret;
70.292 -}
70.293 -
70.294 -/**
70.295 - * Reads a block from a remote file.
70.296 - *
70.297 - * @param transfer The actual File Transfer instance.
70.298 - * @param data A GByteArray instance, where all the binary data representing
70.299 - * the remote file will be stored.
70.300 - * @param size The block size, in bytes, to be requested from a remote file.
70.301 - * @param read_unlimited Tells the backend to read indefinitely (LiveTV), or only
70.302 - * gets the actual size
70.303 - *
70.304 - * @return The actual block size (in bytes) returned by REQUEST_BLOCK message,
70.305 - * or the error code.
70.306 - */
70.307 -GMythFileReadResult
70.308 -gmyth_file_local_read(GMythFileLocal * file_local, GByteArray * data,
70.309 - gint size, gboolean read_unlimited)
70.310 -{
70.311 - gsize bytes_read = 0;
70.312 - gint64 total_read = 0;
70.313 - GMythFileReadResult retval = GMYTH_FILE_READ_OK;
70.314 - GMythFileLocalPrivate *priv;
70.315 -
70.316 - GError *error = NULL;
70.317 -
70.318 - GIOCondition io_cond;
70.319 - GIOStatus io_status = G_IO_STATUS_NORMAL;
70.320 -
70.321 - g_return_val_if_fail(file_local != NULL, FALSE);
70.322 - g_return_val_if_fail(data != NULL, GMYTH_FILE_READ_ERROR);
70.323 -
70.324 - priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
70.325 -
70.326 - io_status = g_io_channel_set_encoding(priv->file_io, NULL, &error);
70.327 - if (io_status == G_IO_STATUS_NORMAL)
70.328 - gmyth_debug("Setting encoding to binary file data stream.\n");
70.329 -
70.330 - io_cond = g_io_channel_get_buffer_condition(priv->file_io);
70.331 -
70.332 - _control_acquire_context(file_local, TRUE);
70.333 -
70.334 - if (size > 0) {
70.335 - gchar *data_buffer = g_new0(gchar, size);
70.336 -
70.337 - io_status = g_io_channel_read_chars(priv->file_io,
70.338 - data_buffer, (gsize) size,
70.339 - &bytes_read, &error);
70.340 -
70.341 - if (io_status != G_IO_STATUS_NORMAL) {
70.342 - gmyth_debug("Error on io_channel");
70.343 - g_free(data_buffer);
70.344 - retval = GMYTH_FILE_READ_ERROR;
70.345 - goto error;
70.346 - }
70.347 -
70.348 - /*
70.349 - * append new data to the increasing byte array
70.350 - */
70.351 - data =
70.352 - g_byte_array_append(data, (const guint8 *) data_buffer,
70.353 - bytes_read);
70.354 - total_read += bytes_read;
70.355 -
70.356 - if (!read_unlimited
70.357 - && (gmyth_file_local_get_filesize(file_local) > 0)
70.358 - && (gmyth_file_local_get_offset(file_local) ==
70.359 - gmyth_file_local_get_filesize(file_local))) {
70.360 - retval = GMYTH_FILE_READ_EOF;
70.361 - goto error;
70.362 - }
70.363 -
70.364 - g_free(data_buffer);
70.365 - } else {
70.366 - retval = GMYTH_FILE_READ_ERROR;
70.367 - }
70.368 -
70.369 - error:
70.370 - _control_release_context(file_local);
70.371 -
70.372 - if (error != NULL) {
70.373 - gmyth_debug("Cleaning-up ERROR: [msg = %s, code = %d]\n",
70.374 - error->message, error->code);
70.375 - g_error_free(error);
70.376 - }
70.377 -
70.378 - if (total_read > 0)
70.379 - gmyth_file_local_set_offset(file_local,
70.380 - (gmyth_file_local_get_offset
70.381 - (file_local) + total_read));
70.382 -
70.383 - return retval;
70.384 -}
70.385 -
70.386 -gint64
70.387 -gmyth_file_local_seek(GMythFileLocal * file_local, gint64 pos,
70.388 - GSeekType whence)
70.389 -{
70.390 - GMythFileLocalPrivate *priv;
70.391 -
70.392 - GError *error;
70.393 -
70.394 - GIOStatus io_status = G_IO_STATUS_NORMAL;
70.395 -
70.396 - g_return_val_if_fail(file_local != NULL, -1);
70.397 -
70.398 - priv = GMYTH_FILE_LOCAL_GET_PRIVATE(file_local);
70.399 -
70.400 - io_status =
70.401 - g_io_channel_seek_position(priv->file_io, pos, whence, &error);
70.402 -
70.403 - if (io_status == G_IO_STATUS_ERROR)
70.404 - pos = -1;
70.405 -
70.406 - return pos;
70.407 -
70.408 -}
70.409 -
70.410 -/**
70.411 - * Gets the actual file_local size of the binary content.
70.412 - *
70.413 - * @param file_local The actual File Transfer instance.
70.414 - *
70.415 - * @return The actual file_local size in bytes.
70.416 - */
70.417 -guint64
70.418 -gmyth_file_local_get_filesize(GMythFileLocal * file_local)
70.419 -{
70.420 - g_return_val_if_fail(file_local != NULL, 0);
70.421 -
70.422 - return gmyth_file_get_filesize(GMYTH_FILE(file_local));
70.423 -}
70.424 -
70.425 -/**
70.426 - * Sets the actual file_local size.
70.427 - *
70.428 - * @param file_local The actual File Transfer instance.
70.429 - * @param filesize The actual File Transfer size, in bytes.
70.430 - */
70.431 -void
70.432 -gmyth_file_local_set_filesize(GMythFileLocal * file_local,
70.433 - guint64 filesize)
70.434 -{
70.435 - g_return_if_fail(file_local != NULL);
70.436 -
70.437 - gmyth_file_set_filesize(GMYTH_FILE(file_local), filesize);
70.438 -}
70.439 -
70.440 -/**
70.441 - * Gets the actual file offset of the binary content.
70.442 - *
70.443 - * @param file_local The actual File Transfer instance.
70.444 - *
70.445 - * @return The actual file offset in bytes.
70.446 - */
70.447 -gint64
70.448 -gmyth_file_local_get_offset(GMythFileLocal * file_local)
70.449 -{
70.450 - g_return_val_if_fail(file_local != NULL, 0);
70.451 -
70.452 - return gmyth_file_get_offset(GMYTH_FILE(file_local));
70.453 -}
70.454 -
70.455 -/**
70.456 - * Sets the actual file offset.
70.457 - *
70.458 - * @param file_local The actual File Local instance.
70.459 - * @param offset The actual File Local offset, in bytes.
70.460 - */
70.461 -void
70.462 -gmyth_file_local_set_offset(GMythFileLocal * file_local, gint64 offset)
70.463 -{
70.464 - g_return_if_fail(file_local != NULL);
70.465 -
70.466 - gmyth_file_set_offset(GMYTH_FILE(file_local), offset);
70.467 -}
71.1 --- a/gmyth/src/gmyth_file_local.h Mon Feb 25 17:45:36 2008 +0000
71.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
71.3 @@ -1,93 +0,0 @@
71.4 -/**
71.5 - * GMyth Library
71.6 - *
71.7 - * @file gmyth/gmyth_file_local_local.h
71.8 - *
71.9 - * @brief <p> GMythFileLocal is the parent GMythFile that deals with the file streaming
71.10 - * media local transfering from the MythTV backend.
71.11 - *
71.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
71.13 - * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
71.14 - *
71.15 - *
71.16 - * This program is free software; you can redistribute it and/or modify
71.17 - * it under the terms of the GNU Lesser General Public License as published by
71.18 - * the Free Software Foundation; either version 2 of the License, or
71.19 - * (at your option) any later version.
71.20 - *
71.21 - * This program is distributed in the hope that it will be useful,
71.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
71.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
71.24 - * GNU General Public License for more details.
71.25 - *
71.26 - * You should have received a copy of the GNU Lesser General Public License
71.27 - * along with this program; if not, write to the Free Software
71.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
71.29 - */
71.30 -
71.31 -#ifndef __GMYTH_FILE_LOCAL_H__
71.32 -#define __GMYTH_FILE_LOCAL_H__
71.33 -
71.34 -#include <glib-object.h>
71.35 -#include <glib.h>
71.36 -
71.37 -#include "gmyth_file.h"
71.38 -#include "gmyth_uri.h"
71.39 -#include "gmyth_backendinfo.h"
71.40 -
71.41 -#include <stdio.h>
71.42 -#include <stdlib.h>
71.43 -#include <string.h>
71.44 -#include <netdb.h>
71.45 -#include <sys/socket.h>
71.46 -#include <unistd.h>
71.47 -
71.48 -G_BEGIN_DECLS
71.49 -#define GMYTH_FILE_LOCAL_TYPE (gmyth_file_local_get_type ())
71.50 -#define GMYTH_FILE_LOCAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_FILE_LOCAL_TYPE, GMythFileLocal))
71.51 -#define GMYTH_FILE_LOCAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_LOCAL_TYPE, GMythFileLocalClass))
71.52 -#define IS_GMYTH_FILE_LOCAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_FILE_LOCAL_TYPE))
71.53 -#define IS_GMYTH_FILE_LOCAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_LOCAL_TYPE))
71.54 -#define GMYTH_FILE_LOCAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_FILE_LOCAL_TYPE, GMythFileLocalClass))
71.55 -typedef struct _GMythFileLocal GMythFileLocal;
71.56 -typedef struct _GMythFileLocalClass GMythFileLocalClass;
71.57 -typedef struct _GMythFileLocalPrivate GMythFileLocalPrivate;
71.58 -
71.59 -struct _GMythFileLocal {
71.60 - GMythFile parent;
71.61 -};
71.62 -
71.63 -struct _GMythFileLocalClass {
71.64 - GMythFileClass parent_class;
71.65 -};
71.66 -
71.67 -
71.68 -GType gmyth_file_local_get_type(void);
71.69 -GMythFileLocal *gmyth_file_local_new(GMythBackendInfo * backend_info);
71.70 -GMythFileLocal *gmyth_file_local_new_with_uri(const gchar * uri);
71.71 -gchar *gmyth_file_local_get_file_name(GMythFileLocal *
71.72 - file_local);
71.73 -void gmyth_file_local_set_file_name(GMythFileLocal * file_local,
71.74 - const gchar * filename);
71.75 -gboolean gmyth_file_local_open(GMythFileLocal * file_local);
71.76 -void gmyth_file_local_close(GMythFileLocal * file_local);
71.77 -gboolean gmyth_file_local_is_open(GMythFileLocal * file_local);
71.78 -
71.79 -GMythFileReadResult
71.80 -gmyth_file_local_read(GMythFileLocal * file_local,
71.81 - GByteArray * data, gint size,
71.82 - gboolean read_unlimited);
71.83 -
71.84 -gint64 gmyth_file_local_seek(GMythFileLocal * file_local,
71.85 - gint64 pos, GSeekType whence);
71.86 -
71.87 -guint64 gmyth_file_local_get_filesize(GMythFileLocal * file_local);
71.88 -void gmyth_file_local_set_filesize(GMythFileLocal * file,
71.89 - guint64 filesize);
71.90 -
71.91 -gint64 gmyth_file_local_get_offset(GMythFileLocal * file_local);
71.92 -void gmyth_file_local_set_offset(GMythFileLocal * file_local,
71.93 - gint64 offset);
71.94 -
71.95 -G_END_DECLS
71.96 -#endif /* __GMYTH_FILE_LOCAL_H__ */
72.1 --- a/gmyth/src/gmyth_file_transfer.c Mon Feb 25 17:45:36 2008 +0000
72.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
72.3 @@ -1,1014 +0,0 @@
72.4 -/**
72.5 - * GMyth Library
72.6 - *
72.7 - * @file gmyth/gmyth_file_transfer.c
72.8 - *
72.9 - * @brief <p> GMythFileTransfer deals with the file streaming media remote/local
72.10 - * transfering to the MythTV frontend.
72.11 - *
72.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
72.13 - * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
72.14 - *
72.15 - *
72.16 - * This program is free software; you can redistribute it and/or modify
72.17 - * it under the terms of the GNU Lesser General Public License as published by
72.18 - * the Free Software Foundation; either version 2 of the License, or
72.19 - * (at your option) any later version.
72.20 - *
72.21 - * This program is distributed in the hope that it will be useful,
72.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
72.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
72.24 - * GNU General Public License for more details.
72.25 - *
72.26 - * You should have received a copy of the GNU Lesser General Public License
72.27 - * along with this program; if not, write to the Free Software
72.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
72.29 - *
72.30 - * GStreamer MythTV plug-in properties:
72.31 - * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv]
72.32 - * - path (qurl - remote file to be opened)
72.33 - * - port number *
72.34 - */
72.35 -
72.36 -#ifdef HAVE_CONFIG_H
72.37 -#include "config.h"
72.38 -#endif
72.39 -
72.40 -#include "gmyth_file_transfer.h"
72.41 -#include "gmyth_recorder.h"
72.42 -#include "gmyth_util.h"
72.43 -#include "gmyth_socket.h"
72.44 -#include "gmyth_stringlist.h"
72.45 -#include "gmyth_debug.h"
72.46 -#include "gmyth_uri.h"
72.47 -#include "gmyth_marshal.h"
72.48 -
72.49 -#include <unistd.h>
72.50 -#include <glib.h>
72.51 -
72.52 -#include <arpa/inet.h>
72.53 -#include <sys/types.h>
72.54 -#include <sys/socket.h>
72.55 -#include <netdb.h>
72.56 -#include <errno.h>
72.57 -#include <stdlib.h>
72.58 -#include <assert.h>
72.59 -
72.60 -#define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER "
72.61 -
72.62 -
72.63 -#define GMYTH_FILE_TRANSFER_GET_PRIVATE(obj) \
72.64 - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferPrivate))
72.65 -
72.66 -enum myth_sock_types {
72.67 - GMYTH_PLAYBACK_TYPE = 0,
72.68 - GMYTH_MONITOR_TYPE,
72.69 - GMYTH_FILETRANSFER_TYPE,
72.70 - GMYTH_RINGBUFFER_TYPE
72.71 -};
72.72 -
72.73 -struct _GMythFileTransferPrivate {
72.74 - GMythRecorder *recorder;
72.75 -
72.76 - gboolean do_next_program_chain;
72.77 - gboolean disposed;
72.78 - gboolean livetv_wait;
72.79 -
72.80 - /*
72.81 - * MythTV version number
72.82 - */
72.83 - gint mythtv_version;
72.84 -
72.85 - /*
72.86 - * socket descriptors
72.87 - */
72.88 - GMythSocket *control_sock;
72.89 - GMythSocket *sock;
72.90 - GMutex *mutex;
72.91 - gint file_id;
72.92 -};
72.93 -
72.94 -static void gmyth_file_transfer_class_init(GMythFileTransferClass *
72.95 - klass);
72.96 -static void gmyth_file_transfer_init(GMythFileTransfer * object);
72.97 -static void gmyth_file_transfer_dispose(GObject * object);
72.98 -static void gmyth_file_transfer_finalize(GObject * object);
72.99 -static void _file_transfer_program_info_changed(GMythFileTransfer *
72.100 - transfer,
72.101 - gint msg_code,
72.102 - gpointer
72.103 - livetv_recorder);
72.104 -static gboolean _connect_to_backend(GMythFileTransfer * transfer);
72.105 -static gboolean _control_acquire_context(GMythFileTransfer * transfer,
72.106 - gboolean do_wait);
72.107 -static gboolean _control_release_context(GMythFileTransfer * transfer);
72.108 -
72.109 -G_DEFINE_TYPE(GMythFileTransfer, gmyth_file_transfer, GMYTH_FILE_TYPE)
72.110 - static void gmyth_file_transfer_class_init(GMythFileTransferClass *
72.111 - klass)
72.112 -{
72.113 - GObjectClass *gobject_class;
72.114 - GMythFileTransferClass *gtransfer_class;
72.115 -
72.116 - gobject_class = (GObjectClass *) klass;
72.117 - gtransfer_class = (GMythFileTransferClass *) gobject_class;
72.118 -
72.119 - gobject_class->dispose = gmyth_file_transfer_dispose;
72.120 - gobject_class->finalize = gmyth_file_transfer_finalize;
72.121 -
72.122 - g_type_class_add_private(gobject_class,
72.123 - sizeof(GMythFileTransferPrivate));
72.124 -
72.125 - gtransfer_class->program_info_changed_handler =
72.126 - _file_transfer_program_info_changed;
72.127 -
72.128 - gtransfer_class->program_info_changed_handler_signal_id =
72.129 - g_signal_new("program-info-changed",
72.130 - G_TYPE_FROM_CLASS(gtransfer_class),
72.131 - G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE |
72.132 - G_SIGNAL_NO_HOOKS, 0, NULL, NULL,
72.133 - gmyth_marshal_VOID__INT_POINTER, G_TYPE_NONE, 2,
72.134 - G_TYPE_INT, G_TYPE_POINTER);
72.135 -
72.136 -}
72.137 -
72.138 -static void
72.139 -gmyth_file_transfer_init(GMythFileTransfer * transfer)
72.140 -{
72.141 - g_return_if_fail(transfer != NULL);
72.142 -
72.143 - transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
72.144 - transfer->priv->mutex = g_mutex_new();
72.145 -
72.146 - g_signal_connect(G_OBJECT(transfer), "program-info-changed",
72.147 - (GCallback) (GMYTH_FILE_TRANSFER_GET_CLASS
72.148 - (transfer)->program_info_changed_handler),
72.149 - NULL);
72.150 -}
72.151 -
72.152 -static void
72.153 -gmyth_file_transfer_dispose(GObject * object)
72.154 -{
72.155 - GMythFileTransferPrivate *priv;
72.156 - GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER(object);
72.157 -
72.158 - g_return_if_fail(transfer != NULL);
72.159 -
72.160 - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
72.161 -
72.162 - if (priv->disposed) {
72.163 - /*
72.164 - * If dispose did already run, return.
72.165 - */
72.166 - return;
72.167 - }
72.168 -
72.169 - /*
72.170 - * Make sure dispose does not run twice.
72.171 - */
72.172 - priv->disposed = TRUE;
72.173 -
72.174 - if (priv->mutex != NULL) {
72.175 - g_mutex_free(priv->mutex);
72.176 - priv->mutex = NULL;
72.177 - }
72.178 -
72.179 - if (priv->control_sock != NULL) {
72.180 - g_object_unref(priv->control_sock);
72.181 - priv->control_sock = NULL;
72.182 - }
72.183 -
72.184 - if (priv->sock != NULL) {
72.185 - g_object_unref(priv->sock);
72.186 - priv->sock = NULL;
72.187 - }
72.188 -
72.189 - if (priv->recorder != NULL) {
72.190 - g_object_unref(priv->recorder);
72.191 - priv->recorder = NULL;
72.192 - }
72.193 -
72.194 - G_OBJECT_CLASS(gmyth_file_transfer_parent_class)->dispose(object);
72.195 -}
72.196 -
72.197 -static void
72.198 -gmyth_file_transfer_finalize(GObject * object)
72.199 -{
72.200 - g_signal_handlers_destroy(object);
72.201 -
72.202 - G_OBJECT_CLASS(gmyth_file_transfer_parent_class)->finalize(object);
72.203 -}
72.204 -
72.205 -/**
72.206 - * Creates a new instance of GMythFileTransfer.
72.207 - *
72.208 - * @param backend_info The BackendInfo instance, with all the MythTV network
72.209 - * configuration data.
72.210 - *
72.211 - * @return a new instance of the File Transfer.
72.212 - */
72.213 -GMythFileTransfer *
72.214 -gmyth_file_transfer_new(GMythBackendInfo * backend_info)
72.215 -{
72.216 - GMythFileTransfer *transfer = g_object_new(GMYTH_FILE_TRANSFER_TYPE,
72.217 - "backend-info",
72.218 - backend_info,
72.219 - NULL);
72.220 -
72.221 - // GValue val = {0,};
72.222 - // backend_info = g_object_ref( backend_info );
72.223 - gmyth_debug("Creating FileTransfer BackendInfo hostname = %s",
72.224 - gmyth_backend_info_get_hostname(backend_info));
72.225 - // GMythBackendInfo *backend_info = gmyth_backend_info_new_with_uri
72.226 - // (uri_str);
72.227 - // g_value_init (&val, G_TYPE_OBJECT);
72.228 - // g_value_set_object (&val, backend_info);
72.229 - // g_object_set (G_OBJECT (transfer), "backend-info", &val, NULL);
72.230 -
72.231 - return transfer;
72.232 -}
72.233 -
72.234 -gchar *
72.235 -gmyth_file_transfer_get_file_name(GMythFileTransfer * transfer)
72.236 -{
72.237 - gchar *filename;
72.238 -
72.239 - g_object_get(G_OBJECT(transfer), "filename", &filename, NULL);
72.240 -
72.241 - return filename;
72.242 -}
72.243 -
72.244 -/**
72.245 - * Creates a new instance of GMythFileTransfer.
72.246 - *
72.247 - * @param uri_str The URI poiting to the MythTV backend server.
72.248 - *
72.249 - * @return a new instance of the File Transfer.
72.250 - */
72.251 -GMythFileTransfer *
72.252 -gmyth_file_transfer_new_with_uri(const gchar * uri_str)
72.253 -{
72.254 - GMythFileTransfer *transfer =
72.255 - GMYTH_FILE_TRANSFER(g_object_new(GMYTH_FILE_TRANSFER_TYPE, NULL));
72.256 - gmyth_debug("URI str = %s", uri_str);
72.257 - // GMythBackendInfo *backend_info = gmyth_backend_info_new_with_uri
72.258 - // (uri_str);
72.259 - GValue val = { 0, };
72.260 - g_value_init(&val, G_TYPE_OBJECT);
72.261 - g_value_set_object(&val, gmyth_backend_info_new_with_uri(uri_str));
72.262 - g_object_set(G_OBJECT(transfer), "backend-info", &val, NULL);
72.263 -
72.264 - return transfer;
72.265 -}
72.266 -
72.267 -/**
72.268 - * Open a File Transfer connection in order to get a remote file.
72.269 - *
72.270 - * @param transfer The actual File Transfer instance.
72.271 - * @param filename The file name of the remote file to be transferred to the client.
72.272 - *
72.273 - * @return <code>true</code>, if the connection opening had been done successfully.
72.274 - */
72.275 -gboolean
72.276 -gmyth_file_transfer_open(GMythFileTransfer * transfer,
72.277 - const gchar * filename)
72.278 -{
72.279 - gboolean ret = TRUE;
72.280 - GMythFileTransferPrivate *priv;
72.281 -
72.282 - g_return_val_if_fail(transfer != NULL, FALSE);
72.283 - g_return_val_if_fail(filename != NULL && strlen(filename) > 0, FALSE);
72.284 -
72.285 - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
72.286 -
72.287 - gmyth_debug("Opening the FileTransfer... (%s)", filename);
72.288 -
72.289 - g_object_set(GMYTH_FILE(transfer), "filename", filename, NULL);
72.290 -
72.291 - /*
72.292 - * configure the control socket
72.293 - */
72.294 - if (TRUE /* priv->control_sock == NULL */ ) {
72.295 - if (!_connect_to_backend(transfer)) {
72.296 - gmyth_debug("Connection to backend failed (Control Socket).");
72.297 - ret = FALSE;
72.298 - }
72.299 -
72.300 - if (priv->do_next_program_chain) {
72.301 - priv->do_next_program_chain = FALSE; // fixme
72.302 - gmyth_debug
72.303 - ("New file available before the current file was opened");
72.304 - GMythProgramInfo *prog_info =
72.305 - gmyth_recorder_get_current_program_info(priv->recorder);
72.306 -
72.307 - if (prog_info != NULL && prog_info->pathname != NULL
72.308 - && strlen(prog_info->pathname->str) > 0
72.309 - && g_ascii_strcasecmp(prog_info->pathname->str,
72.310 - gmyth_file_get_file_name(GMYTH_FILE
72.311 - (transfer)))
72.312 - != 0)
72.313 - ret =
72.314 - gmyth_file_transfer_open(transfer,
72.315 - g_strrstr(prog_info->
72.316 - pathname->str,
72.317 - "/"));
72.318 -
72.319 - if (prog_info != NULL)
72.320 - g_object_unref(prog_info);
72.321 -
72.322 - if (!ret)
72.323 - gmyth_debug("Cannot change to the next program info!");
72.324 - else
72.325 - gmyth_debug("OK!!! MOVED to the next program info [%s]!",
72.326 - gmyth_file_get_file_name(GMYTH_FILE
72.327 - (transfer)));
72.328 -
72.329 - } else {
72.330 - gmyth_debug
72.331 - ("None new file found. We continue with the same file opened before");
72.332 - }
72.333 -
72.334 - } else {
72.335 - gmyth_debug("Remote transfer control socket already created.");
72.336 - }
72.337 -
72.338 - gmyth_debug("Got file with size = %lld.\n",
72.339 - gmyth_file_get_filesize(GMYTH_FILE(transfer)));
72.340 -
72.341 - return ret;
72.342 -}
72.343 -
72.344 -/**
72.345 - * Connect a File Transfer binary client socket to a remote file.
72.346 - *
72.347 - * @param transfer The actual File Transfer instance.
72.348 - *
72.349 - * @return <code>true</code>, if the connection had been configured successfully.
72.350 - */
72.351 -static gboolean
72.352 -_connect_to_backend(GMythFileTransfer * transfer)
72.353 -{
72.354 - GString *base_str = NULL;
72.355 - GString *hostname = NULL;
72.356 - GMythStringList *strlist = NULL;
72.357 - gboolean ret = TRUE;
72.358 - GMythFileTransferPrivate *priv;
72.359 - GMythBackendInfo *backend_info;
72.360 -
72.361 - g_return_val_if_fail(transfer != NULL, FALSE);
72.362 -
72.363 - g_object_get(GMYTH_FILE(transfer), "backend-info", &backend_info,
72.364 - NULL);
72.365 -
72.366 - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
72.367 - _control_acquire_context(transfer, TRUE);
72.368 -
72.369 - /*
72.370 - * Creates the control socket
72.371 - */
72.372 -
72.373 - if (priv->control_sock != NULL) {
72.374 - g_object_unref(priv->control_sock);
72.375 - priv->control_sock = NULL;
72.376 - }
72.377 -
72.378 - base_str = g_string_new("");
72.379 -
72.380 - priv->control_sock = gmyth_socket_new();
72.381 - // Connects the socket, send Mythtv ANN command and verify Mythtv
72.382 - // protocol version
72.383 - if (!gmyth_socket_connect_to_backend(priv->control_sock,
72.384 - backend_info->hostname,
72.385 - backend_info->port, TRUE)) {
72.386 -
72.387 - _control_release_context(transfer);
72.388 - g_object_unref(priv->control_sock);
72.389 - priv->control_sock = NULL;
72.390 - return FALSE;
72.391 - }
72.392 -
72.393 - /*
72.394 - * Creates the data socket
72.395 - */
72.396 - if (priv->sock != NULL) {
72.397 - g_object_unref(priv->sock);
72.398 - priv->sock = NULL;
72.399 - }
72.400 -
72.401 - priv->sock = gmyth_socket_new();
72.402 - gmyth_socket_connect(priv->sock, backend_info->hostname,
72.403 - backend_info->port);
72.404 - gmyth_debug("Connecting file transfer... (%s, %d)",
72.405 - backend_info->hostname, backend_info->port);
72.406 -
72.407 - strlist = gmyth_string_list_new();
72.408 - hostname = gmyth_socket_get_local_hostname();
72.409 - gmyth_debug("[%s] MythTV version (from backend) = %d.\n", __FUNCTION__,
72.410 - priv->control_sock->mythtv_version);
72.411 - if (priv->control_sock->mythtv_version > 26)
72.412 - g_string_printf(base_str, "ANN FileTransfer %s 1 -1",
72.413 - hostname->str);
72.414 - else
72.415 - g_string_printf(base_str, "ANN FileTransfer %s", hostname->str);
72.416 -
72.417 - gmyth_string_list_append_string(strlist, base_str);
72.418 - gmyth_string_list_append_char_array(strlist,
72.419 - gmyth_file_get_file_name(GMYTH_FILE
72.420 - (transfer)));
72.421 -
72.422 - gmyth_socket_write_stringlist(priv->sock, strlist);
72.423 -
72.424 - /*
72.425 - * MONITOR Handler - DVB TV Chain update messages!!!
72.426 - */
72.427 -
72.428 - gmyth_socket_read_stringlist(priv->sock, strlist);
72.429 -
72.430 - /*
72.431 - * file identification used in future file transfer requests to
72.432 - * backend
72.433 - */
72.434 - priv->file_id = gmyth_string_list_get_int(strlist, 1);
72.435 -
72.436 - /*
72.437 - * Myth URI stream file size - decoded using two 8-bytes sequences (64
72.438 - * bits/long long types)
72.439 - */
72.440 - gmyth_file_set_filesize(GMYTH_FILE(transfer),
72.441 - gmyth_string_list_get_int64(strlist, 2));
72.442 -
72.443 - gmyth_debug("***** Received: recordernum = %d, filesize = %"
72.444 - G_GUINT64_FORMAT "\n", priv->file_id,
72.445 - gmyth_file_get_filesize(GMYTH_FILE(transfer)));
72.446 -
72.447 - if (gmyth_file_get_filesize(GMYTH_FILE(transfer)) < 0) {
72.448 - gmyth_debug
72.449 - ("Got filesize equals to %llu is lesser than 0 [invalid stream file]\n",
72.450 - gmyth_file_get_filesize(GMYTH_FILE(transfer)));
72.451 - g_object_unref(priv->sock);
72.452 - priv->sock = NULL;
72.453 - ret = FALSE;
72.454 - }
72.455 -
72.456 - _control_release_context(transfer);
72.457 -
72.458 - if (strlist != NULL)
72.459 - g_object_unref(strlist);
72.460 -
72.461 - if (base_str != NULL)
72.462 - g_string_free(base_str, TRUE);
72.463 -
72.464 - if (hostname != NULL)
72.465 - g_string_free(hostname, TRUE);
72.466 -
72.467 - return ret;
72.468 -}
72.469 -
72.470 -/**
72.471 - * Receives a GObject signal coming from a LiveTV instance, all the time a
72.472 - * program info changes.
72.473 - *
72.474 - * @param transfer The actual File Transfer instance.
72.475 - * @param msg_code The MythTV backend message status code.
72.476 - * @param live_tv A pointer to the LiveTV instance. *
72.477 - */
72.478 -void
72.479 -gmyth_file_transfer_emit_program_info_changed_signal(GMythFileTransfer *
72.480 - transfer,
72.481 - gint msg_code,
72.482 - gpointer
72.483 - live_tv_recorder)
72.484 -{
72.485 - gmyth_debug("Calling signal handler... [FILE_TRANSFER]");
72.486 -
72.487 - g_signal_emit(transfer, GMYTH_FILE_TRANSFER_GET_CLASS(transfer)->program_info_changed_handler_signal_id, 0, /* details
72.488 - */
72.489 - msg_code, live_tv_recorder);
72.490 -
72.491 -}
72.492 -
72.493 -/**
72.494 - * Checks if the actual File Transfer connection is open.
72.495 - *
72.496 - * @param transfer The actual File Transfer instance.
72.497 - *
72.498 - * @return <code>true</code>, if the File Transfer connection is opened.
72.499 - */
72.500 -gboolean
72.501 -gmyth_file_transfer_is_open(GMythFileTransfer * transfer)
72.502 -{
72.503 - GMythStringList *strlist;
72.504 - GMythFileTransferPrivate *priv;
72.505 - GString *query;
72.506 -
72.507 - g_return_val_if_fail(transfer != NULL, FALSE);
72.508 -
72.509 - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
72.510 - g_return_val_if_fail(priv->control_sock != NULL, FALSE);
72.511 - g_return_val_if_fail(priv->sock != NULL, FALSE);
72.512 -
72.513 - _control_acquire_context(transfer, TRUE);
72.514 -
72.515 - strlist = gmyth_string_list_new();
72.516 - query = g_string_new(GMYTHTV_QUERY_HEADER);
72.517 - g_string_append_printf(query, "%d", priv->file_id);
72.518 -
72.519 - gmyth_string_list_append_string(strlist, query);
72.520 - gmyth_string_list_append_char_array(strlist, "IS_OPEN");
72.521 -
72.522 - gmyth_socket_write_stringlist(priv->control_sock, strlist);
72.523 - gmyth_socket_read_stringlist(priv->control_sock, strlist);
72.524 -
72.525 - _control_release_context(transfer);
72.526 -
72.527 - g_string_free(query, TRUE);
72.528 - g_object_unref(strlist);
72.529 -
72.530 - return (strlist != NULL && gmyth_string_list_get_int(strlist, 0) == 1);
72.531 -}
72.532 -
72.533 -/**
72.534 - * Closes a remote File Transfer connection.
72.535 - *
72.536 - * @param transfer The actual File Transfer instance.
72.537 - */
72.538 -void
72.539 -gmyth_file_transfer_close(GMythFileTransfer * transfer)
72.540 -{
72.541 - GMythStringList *strlist;
72.542 - GMythFileTransferPrivate *priv;
72.543 - GString *query;
72.544 -
72.545 - g_return_if_fail(transfer != NULL);
72.546 -
72.547 - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
72.548 -
72.549 - if (priv->control_sock == NULL)
72.550 - return;
72.551 -
72.552 - _control_acquire_context(transfer, TRUE);
72.553 -
72.554 - strlist = gmyth_string_list_new();
72.555 - query = g_string_new(GMYTHTV_QUERY_HEADER);
72.556 - g_string_append_printf(query, "%d", priv->file_id);
72.557 -
72.558 - gmyth_string_list_append_string(strlist, query);
72.559 - gmyth_string_list_append_char_array(strlist, "DONE");
72.560 -
72.561 - if (gmyth_socket_sendreceive_stringlist(priv->control_sock, strlist) <=
72.562 - 0) {
72.563 - // fixme: time out???
72.564 - gmyth_debug("Remote file timeout.\n");
72.565 - }
72.566 -
72.567 - g_string_free(query, TRUE);
72.568 - g_object_unref(strlist);
72.569 -
72.570 - if (priv->sock) {
72.571 - g_object_unref(priv->sock);
72.572 - priv->sock = NULL;
72.573 - }
72.574 -
72.575 - if (priv->control_sock) {
72.576 - g_object_unref(priv->control_sock);
72.577 - priv->control_sock = NULL;
72.578 - }
72.579 -
72.580 - _control_release_context(transfer);
72.581 -}
72.582 -
72.583 -/**
72.584 - * Do a seek operation (moves the read/write file pointer) on a remote file.
72.585 - *
72.586 - * @param transfer The actual File Transfer instance.
72.587 - * @param pos The position to be moved in the remote file.
72.588 - * @param whence Tells to what direction seek movement should be done.
72.589 - *
72.590 - * @return The actual position on the remote file (after seek has been done).
72.591 - */
72.592 -gint64
72.593 -gmyth_file_transfer_seek(GMythFileTransfer * transfer, guint64 pos,
72.594 - gint whence)
72.595 -{
72.596 - GMythStringList *strlist = gmyth_string_list_new();
72.597 - GMythFileTransferPrivate *priv;
72.598 - GString *query;
72.599 -
72.600 - g_return_val_if_fail(transfer != NULL, FALSE);
72.601 - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
72.602 -
72.603 - g_return_val_if_fail(priv->sock != NULL, -1);
72.604 - g_return_val_if_fail(priv->control_sock != NULL, -1);
72.605 -
72.606 - strlist = gmyth_string_list_new();
72.607 - query = g_string_new(GMYTHTV_QUERY_HEADER);
72.608 - g_string_append_printf(query, "%d", priv->file_id);
72.609 -
72.610 - /*
72.611 - * myth_control_acquire_context( transfer, TRUE );
72.612 - */
72.613 -
72.614 - gmyth_string_list_append_string(strlist, query);
72.615 - gmyth_string_list_append_char_array(strlist, "SEEK");
72.616 - gmyth_string_list_append_uint64(strlist, pos);
72.617 -
72.618 - gmyth_string_list_append_int(strlist, whence);
72.619 -
72.620 - if (pos > 0)
72.621 - gmyth_string_list_append_uint64(strlist, pos);
72.622 - else
72.623 - gmyth_string_list_append_uint64(strlist,
72.624 - gmyth_file_get_offset(GMYTH_FILE
72.625 - (transfer)));
72.626 -
72.627 - gmyth_socket_sendreceive_stringlist(priv->control_sock, strlist);
72.628 -
72.629 - gint64 retval = gmyth_string_list_get_int64(strlist, 0);
72.630 -
72.631 - gmyth_file_set_offset(GMYTH_FILE(transfer), retval);
72.632 - gmyth_debug("Got reading position pointer from the streaming = %lld\n",
72.633 - retval);
72.634 -
72.635 - g_object_unref(strlist);
72.636 - g_string_free(query, TRUE);
72.637 -
72.638 - /*
72.639 - * myth_control_release_context( transfer );
72.640 - */
72.641 -
72.642 - return retval;
72.643 -}
72.644 -
72.645 -/**
72.646 - * Acquire access to a remote file socket read/write pointer.
72.647 - *
72.648 - * @param transfer The actual File Transfer instance.
72.649 - * @param do_wait Waits or not on a GCond, when trying to read from the remote socket.
72.650 - *
72.651 - * @return <code>true</code>, if the acquire had been got.
72.652 - */
72.653 -static gboolean
72.654 -_control_acquire_context(GMythFileTransfer * transfer, gboolean do_wait)
72.655 -{
72.656 - gboolean ret = TRUE;
72.657 - GMythFileTransferPrivate *priv;
72.658 -
72.659 - g_return_val_if_fail(transfer != NULL, FALSE);
72.660 - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
72.661 -
72.662 - g_mutex_lock(priv->mutex);
72.663 - return ret;
72.664 -}
72.665 -
72.666 -/**
72.667 - * Release access to a remote file socket read/write pointer.
72.668 - *
72.669 - * @param transfer The actual File Transfer instance.
72.670 - *
72.671 - * @return <code>true</code>, if the socket read/write permissions had been releaseds.
72.672 - */
72.673 -static gboolean
72.674 -_control_release_context(GMythFileTransfer * transfer)
72.675 -{
72.676 - gboolean ret = TRUE;
72.677 - GMythFileTransferPrivate *priv;
72.678 -
72.679 - g_return_val_if_fail(transfer != NULL, FALSE);
72.680 - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
72.681 -
72.682 - g_mutex_unlock(priv->mutex);
72.683 -
72.684 - return ret;
72.685 -}
72.686 -
72.687 -/**
72.688 - * Reads a block from a remote file.
72.689 - *
72.690 - * @param transfer The actual File Transfer instance.
72.691 - * @param data A GByteArray instance, where all the binary data representing
72.692 - * the remote file will be stored.
72.693 - * @param size The block size, in bytes, to be requested from a remote file.
72.694 - * @param read_unlimited Tells the backend to read indefinitely (LiveTV), or only
72.695 - * gets the actual size
72.696 - *
72.697 - * @return The actual block size (in bytes) returned by REQUEST_BLOCK message,
72.698 - * or the error code.
72.699 - */
72.700 -GMythFileReadResult
72.701 -gmyth_file_transfer_read(GMythFileTransfer * transfer, GByteArray * data,
72.702 - gint size, gboolean read_unlimited)
72.703 -{
72.704 - gint bytes_sent = 0;
72.705 - gsize bytes_read = 0;
72.706 - gint64 total_read = 0;
72.707 - GMythFileReadResult retval = GMYTH_FILE_READ_OK;
72.708 - GMythFileTransferPrivate *priv;
72.709 -
72.710 - GError *error = NULL;
72.711 -
72.712 - GIOChannel *io_channel;
72.713 - GIOChannel *io_channel_control;
72.714 -
72.715 - GIOCondition io_cond;
72.716 - GIOCondition io_cond_control;
72.717 - GIOStatus io_status = G_IO_STATUS_NORMAL;
72.718 - GIOStatus io_status_control = G_IO_STATUS_NORMAL;
72.719 -
72.720 - GMythStringList *strlist;
72.721 - GMythStringList *ret_strlist = NULL;
72.722 - gboolean ret = TRUE;
72.723 - GString *query;
72.724 -
72.725 - g_return_val_if_fail(transfer != NULL, FALSE);
72.726 - g_return_val_if_fail(data != NULL, GMYTH_FILE_READ_ERROR);
72.727 -
72.728 - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
72.729 -
72.730 - strlist = gmyth_string_list_new();
72.731 -
72.732 - io_channel = priv->sock->sd_io_ch;
72.733 - io_channel_control = priv->control_sock->sd_io_ch;
72.734 -
72.735 - io_status = g_io_channel_set_encoding(io_channel, NULL, &error);
72.736 - if (io_status == G_IO_STATUS_NORMAL)
72.737 - gmyth_debug("[%s] Setting encoding to binary data socket).\n",
72.738 - __FUNCTION__);
72.739 -
72.740 - io_cond = g_io_channel_get_buffer_condition(io_channel);
72.741 -
72.742 - io_cond_control = g_io_channel_get_buffer_condition(io_channel);
72.743 - if (priv->sock == NULL || (io_status == G_IO_STATUS_ERROR)) {
72.744 - g_printerr
72.745 - ("gmyth_file_transfer_read(): Called with no raw socket.\n");
72.746 - return GMYTH_FILE_READ_ERROR;
72.747 - }
72.748 -
72.749 - if (priv->control_sock == NULL
72.750 - || (io_status_control == G_IO_STATUS_ERROR)) {
72.751 - g_printerr
72.752 - ("gmyth_file_transfer_read(): Called with no control socket.\n");
72.753 - return GMYTH_FILE_READ_ERROR;
72.754 - }
72.755 -
72.756 - query = g_string_new(GMYTHTV_QUERY_HEADER);
72.757 - g_string_append_printf(query, "%d", priv->file_id);
72.758 - gmyth_debug("[%s] Transfer_query = %s\n", __FUNCTION__, query->str);
72.759 -
72.760 - _control_acquire_context(transfer, TRUE);
72.761 - // Do Read
72.762 - gmyth_string_list_append_char_array(strlist, query->str);
72.763 - gmyth_string_list_append_char_array(strlist, "REQUEST_BLOCK");
72.764 - gmyth_string_list_append_int(strlist, size - total_read);
72.765 -
72.766 - guint iter_count = 3;
72.767 -
72.768 - do {
72.769 - bytes_sent = 0;
72.770 -
72.771 - // Request the block to the backend
72.772 - gmyth_socket_write_stringlist(priv->control_sock, strlist);
72.773 -
72.774 - if (ret_strlist != NULL)
72.775 - g_object_unref(ret_strlist);
72.776 -
72.777 - ret_strlist = gmyth_string_list_new();
72.778 - // Receives the backand answer
72.779 - gmyth_socket_read_stringlist(priv->control_sock, ret_strlist);
72.780 -
72.781 - if (ret_strlist != NULL
72.782 - && gmyth_string_list_length(ret_strlist) > 0) {
72.783 - bytes_sent = gmyth_string_list_get_int(ret_strlist, 0); // -1
72.784 - // on
72.785 - // backend
72.786 - // error
72.787 - gmyth_debug("[%s] got SENT buffer message = %d\n",
72.788 - __FUNCTION__, bytes_sent);
72.789 - }
72.790 -
72.791 - if (read_unlimited && (bytes_sent == 0)) {
72.792 - g_usleep(300);
72.793 - }
72.794 -
72.795 - --iter_count;
72.796 -
72.797 - }
72.798 - while (read_unlimited && (bytes_sent == 0) && iter_count > 0);
72.799 -
72.800 - if (bytes_sent > 0) {
72.801 - gchar *data_buffer = g_new0(gchar, bytes_sent);
72.802 -
72.803 - io_status = g_io_channel_read_chars(io_channel,
72.804 - data_buffer,
72.805 - (gsize) bytes_sent,
72.806 - &bytes_read, &error);
72.807 -
72.808 - if (io_status != G_IO_STATUS_NORMAL) {
72.809 - gmyth_debug("Error on io_channel");
72.810 - g_free(data_buffer);
72.811 - g_object_unref(strlist);
72.812 - retval = GMYTH_FILE_READ_ERROR;
72.813 - goto error;
72.814 - }
72.815 -
72.816 - /*
72.817 - * append new data to the increasing byte array
72.818 - */
72.819 - data =
72.820 - g_byte_array_append(data, (const guint8 *) data_buffer,
72.821 - bytes_read);
72.822 - gmyth_file_set_offset(GMYTH_FILE(transfer),
72.823 - gmyth_file_get_offset(GMYTH_FILE(transfer)) +
72.824 - bytes_read);
72.825 -
72.826 - if (!read_unlimited
72.827 - && (gmyth_file_get_filesize(GMYTH_FILE(transfer)) > 0)
72.828 - && (gmyth_file_get_offset(GMYTH_FILE(transfer)) ==
72.829 - gmyth_file_get_filesize(GMYTH_FILE(transfer)))) {
72.830 - retval = GMYTH_FILE_READ_EOF;
72.831 - goto error;
72.832 - }
72.833 -
72.834 - g_free(data_buffer);
72.835 - } else {
72.836 - retval = GMYTH_FILE_READ_ERROR;
72.837 - }
72.838 -
72.839 - if (strlist != NULL) {
72.840 - g_object_unref(strlist);
72.841 - strlist = NULL;
72.842 - }
72.843 -
72.844 - if (ret_strlist != NULL) {
72.845 - g_object_unref(ret_strlist);
72.846 - ret_strlist = NULL;
72.847 - }
72.848 -
72.849 - if (read_unlimited && (bytes_sent == 0)) {
72.850 - gmyth_debug("Trying to move to the next program chain...");
72.851 - if (priv->recorder != NULL && priv->do_next_program_chain) {
72.852 - priv->do_next_program_chain = FALSE;
72.853 - retval = GMYTH_FILE_READ_NEXT_PROG_CHAIN;
72.854 - GMythProgramInfo *prog_info =
72.855 - gmyth_recorder_get_current_program_info(priv->recorder);
72.856 -
72.857 - gmyth_debug
72.858 - ("Comparing if the current prog. info = %s [strlen == %d] is equals to "
72.859 - " %s [strlen == %d]...", prog_info->pathname->str,
72.860 - strlen(prog_info->pathname->str),
72.861 - gmyth_file_get_file_name(GMYTH_FILE(transfer)),
72.862 - strlen(gmyth_file_get_file_name(GMYTH_FILE(transfer))));
72.863 -
72.864 - if (prog_info != NULL && prog_info->pathname != NULL
72.865 - && strlen(prog_info->pathname->str) > 0
72.866 - && (NULL ==
72.867 - g_strstr_len(prog_info->pathname->str,
72.868 - strlen(prog_info->pathname->str),
72.869 - gmyth_file_get_file_name(GMYTH_FILE
72.870 - (transfer))))) {
72.871 - /*
72.872 - * releasing context got at this function starting...
72.873 - */
72.874 - _control_release_context(transfer);
72.875 - ret =
72.876 - gmyth_file_transfer_open(transfer,
72.877 - g_strrstr(prog_info->
72.878 - pathname->str,
72.879 - "/"));
72.880 - _control_acquire_context(transfer, TRUE);
72.881 - /*
72.882 - * acquiring context released at this function stopping...
72.883 - */
72.884 -
72.885 - if (prog_info != NULL)
72.886 - g_object_unref(prog_info);
72.887 -
72.888 - if (!ret)
72.889 - gmyth_debug("Cannot change to the next program info!");
72.890 - else
72.891 - gmyth_debug
72.892 - ("OK!!! MOVED to the next program info [%s]!",
72.893 - gmyth_file_get_file_name(GMYTH_FILE(transfer)));
72.894 - }
72.895 -
72.896 - }
72.897 -
72.898 - }
72.899 - /*
72.900 - * if
72.901 - */
72.902 - error:
72.903 -
72.904 - _control_release_context(transfer);
72.905 - g_string_free(query, TRUE);
72.906 -
72.907 - if (error != NULL) {
72.908 - gmyth_debug("Cleaning-up ERROR: %s [msg = %s, code = %d]\n",
72.909 - __FUNCTION__, error->message, error->code);
72.910 - g_error_free(error);
72.911 - }
72.912 -
72.913 - if (total_read > 0)
72.914 - gmyth_file_set_offset(GMYTH_FILE(transfer),
72.915 - gmyth_file_get_offset(GMYTH_FILE
72.916 - (transfer)) +
72.917 - total_read);
72.918 -
72.919 - return retval;
72.920 -}
72.921 -
72.922 -static void
72.923 -_file_transfer_program_info_changed(GMythFileTransfer * transfer,
72.924 - gint msg_code,
72.925 - gpointer livetv_recorder)
72.926 -{
72.927 - GMythRecorder *recorder;
72.928 - GMythFileTransferPrivate *priv;
72.929 -
72.930 - g_return_if_fail(transfer != NULL);
72.931 -
72.932 - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
72.933 -
72.934 - recorder = GMYTH_RECORDER(livetv_recorder);
72.935 - gmyth_debug
72.936 - ("Program info changed! ( file transfer orig. = %p, ptr. = [%s] )",
72.937 - transfer, livetv_recorder != NULL ? "[NOT NULL]" : "[NULL]");
72.938 -
72.939 - if (NULL != recorder) {
72.940 - gmyth_debug
72.941 - ("YES, the requested program info movement on the LiveTV transfer is authentical!");
72.942 - }
72.943 -
72.944 - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
72.945 - g_object_ref(recorder);
72.946 - priv->recorder = recorder;
72.947 - priv->do_next_program_chain = TRUE;
72.948 -}
72.949 -
72.950 -/**
72.951 - * Sets the timeout flag of a file being transfered.
72.952 - *
72.953 - * @param transfer The actual File Transfer instance.
72.954 - * @param fast If this is <code>true</code>, sets the remote timeout to be as fast
72.955 - * as possible.
72.956 - *
72.957 - * @return <code>true</code>, if the acquire had been got.
72.958 - */
72.959 -gboolean
72.960 -gmyth_file_transfer_settimeout(GMythFileTransfer * transfer, gboolean fast)
72.961 -{
72.962 - GMythFileTransferPrivate *priv;
72.963 - GMythStringList *strlist = NULL;
72.964 -
72.965 - g_return_val_if_fail(transfer != NULL, FALSE);
72.966 -
72.967 - priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
72.968 -
72.969 - g_return_val_if_fail(priv->sock != NULL, FALSE);
72.970 - g_return_val_if_fail(priv->control_sock != NULL, FALSE);
72.971 -
72.972 - _control_acquire_context(transfer, TRUE);
72.973 -
72.974 - strlist = gmyth_string_list_new();
72.975 - gmyth_string_list_append_char_array(strlist, GMYTHTV_QUERY_HEADER);
72.976 - gmyth_string_list_append_char_array(strlist, "SET_TIMEOUT");
72.977 - gmyth_string_list_append_int(strlist, fast);
72.978 -
72.979 - gint strlist_len =
72.980 - gmyth_socket_sendreceive_stringlist(priv->control_sock,
72.981 - strlist);
72.982 -
72.983 - if (strlist_len > 0)
72.984 - gmyth_debug("Yes, timeout was changed: %s.",
72.985 - gmyth_string_list_get_char_array(strlist, 0));
72.986 - else
72.987 - gmyth_debug("Timeout cannot be changed!");
72.988 -
72.989 - _control_release_context(transfer);
72.990 -
72.991 - gmyth_debug("%s setting timeout flag of this file transfer = %s\n",
72.992 - strlist_len > 0 ? "Yes," : "NOT",
72.993 - fast ? "FAST" : "NOT FAST");
72.994 -
72.995 - g_object_unref(strlist);
72.996 -
72.997 - return TRUE;
72.998 -}
72.999 -
72.1000 -/**
72.1001 - * Gets the actual file size of the binary content.
72.1002 - *
72.1003 - * @param transfer The actual File Transfer instance.
72.1004 - *
72.1005 - * @return The actual file size in bytes.
72.1006 - */
72.1007 -guint64
72.1008 -gmyth_file_transfer_get_filesize(GMythFileTransfer * transfer)
72.1009 -{
72.1010 - guint64 filesize;
72.1011 -
72.1012 - g_return_val_if_fail(transfer != NULL, 0);
72.1013 -
72.1014 - g_object_get(GMYTH_FILE(transfer), "file-size", &filesize, NULL);
72.1015 -
72.1016 - return filesize;
72.1017 -}
73.1 --- a/gmyth/src/gmyth_file_transfer.h Mon Feb 25 17:45:36 2008 +0000
73.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
73.3 @@ -1,111 +0,0 @@
73.4 -/**
73.5 - * GMyth Library
73.6 - *
73.7 - * @file gmyth/gmyth_file_transfer.h
73.8 - *
73.9 - * @brief <p> GMythFileTransfer deals with the file streaming media remote/local
73.10 - * transfering to the MythTV frontend.
73.11 - *
73.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
73.13 - * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
73.14 - *
73.15 - *
73.16 - * This program is free software; you can redistribute it and/or modify
73.17 - * it under the terms of the GNU Lesser General Public License as published by
73.18 - * the Free Software Foundation; either version 2 of the License, or
73.19 - * (at your option) any later version.
73.20 - *
73.21 - * This program is distributed in the hope that it will be useful,
73.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
73.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
73.24 - * GNU General Public License for more details.
73.25 - *
73.26 - * You should have received a copy of the GNU Lesser General Public License
73.27 - * along with this program; if not, write to the Free Software
73.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
73.29 - */
73.30 -
73.31 -#ifndef __GMYTH_FILE_TRANSFER_H__
73.32 -#define __GMYTH_FILE_TRANSFER_H__
73.33 -
73.34 -#include <glib-object.h>
73.35 -#include <glib.h>
73.36 -
73.37 -#include "gmyth_file.h"
73.38 -#include "gmyth_socket.h"
73.39 -#include "gmyth_uri.h"
73.40 -#include "gmyth_backendinfo.h"
73.41 -
73.42 -#include <stdio.h>
73.43 -#include <stdlib.h>
73.44 -#include <string.h>
73.45 -#include <netdb.h>
73.46 -#include <sys/socket.h>
73.47 -#include <unistd.h>
73.48 -
73.49 -G_BEGIN_DECLS
73.50 -#define GMYTH_FILE_TRANSFER_TYPE (gmyth_file_transfer_get_type ())
73.51 -#define GMYTH_FILE_TRANSFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransfer))
73.52 -#define GMYTH_FILE_TRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferClass))
73.53 -#define IS_GMYTH_FILE_TRANSFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_FILE_TRANSFER_TYPE))
73.54 -#define IS_GMYTH_FILE_TRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TRANSFER_TYPE))
73.55 -#define GMYTH_FILE_TRANSFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferClass))
73.56 -typedef struct _GMythFileTransfer GMythFileTransfer;
73.57 -typedef struct _GMythFileTransferClass GMythFileTransferClass;
73.58 -typedef struct _GMythFileTransferPrivate GMythFileTransferPrivate;
73.59 -
73.60 -struct _GMythFileTransfer {
73.61 - GMythFile parent;
73.62 - GMythFileTransferPrivate *priv;
73.63 -};
73.64 -
73.65 -struct _GMythFileTransferClass {
73.66 - GMythFileClass parent_class;
73.67 -
73.68 - /*
73.69 - * callbacks
73.70 - */
73.71 - guint program_info_changed_handler_signal_id;
73.72 -
73.73 - /*
73.74 - * signal default handlers
73.75 - */
73.76 - void (*program_info_changed_handler) (GMythFileTransfer *
73.77 - transfer,
73.78 - gint msg_code,
73.79 - gpointer
73.80 - livetv_recorder);
73.81 -};
73.82 -
73.83 -
73.84 -GType gmyth_file_transfer_get_type(void);
73.85 -GMythFileTransfer *gmyth_file_transfer_new(GMythBackendInfo *
73.86 - backend_info);
73.87 -gchar *gmyth_file_transfer_get_file_name(GMythFileTransfer *
73.88 - transfer);
73.89 -gboolean gmyth_file_transfer_open(GMythFileTransfer * transfer,
73.90 - const gchar * filename);
73.91 -void gmyth_file_transfer_close(GMythFileTransfer * transfer);
73.92 -gboolean gmyth_file_transfer_is_open(GMythFileTransfer * transfer);
73.93 -
73.94 -GMythFileReadResult
73.95 -gmyth_file_transfer_read(GMythFileTransfer * transfer,
73.96 - GByteArray * data, gint size,
73.97 - gboolean read_unlimited);
73.98 -gint64 gmyth_file_transfer_seek(GMythFileTransfer * transfer,
73.99 - guint64 pos, gint whence);
73.100 -gboolean gmyth_file_transfer_settimeout(GMythFileTransfer *
73.101 - transfer, gboolean fast);
73.102 -guint64 gmyth_file_transfer_get_filesize(GMythFileTransfer *
73.103 - transfer);
73.104 -
73.105 -void
73.106 - gmyth_file_transfer_emit_program_info_changed_signal(GMythFileTransfer *
73.107 - transfer,
73.108 - gint
73.109 - msg_code,
73.110 - gpointer
73.111 - live_tv_recorder);
73.112 -
73.113 -G_END_DECLS
73.114 -#endif /* __GMYTH_FILE_TRANSFER_H__ */
74.1 --- a/gmyth/src/gmyth_http.c Mon Feb 25 17:45:36 2008 +0000
74.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
74.3 @@ -1,1037 +0,0 @@
74.4 -/**
74.5 - * GMyth Library
74.6 - *
74.7 - * @file gmyth/gmyth_http.c
74.8 - *
74.9 - * @brief <p> GMythHttp library provides a wrapper to access
74.10 - * data from the database using http+xml
74.11 - *
74.12 - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
74.13 - * @author Artur Duque de Souza <artur.souza@indt.org.br>
74.14 - *
74.15 - *
74.16 - * This program is free software; you can redistribute it and/or modify
74.17 - * it under the terms of the GNU Lesser General Public License as published by
74.18 - * the Free Software Foundation; either version 2 of the License, or
74.19 - * (at your option) any later version.
74.20 - *
74.21 - * This program is distributed in the hope that it will be useful,
74.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
74.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
74.24 - * GNU General Public License for more details.
74.25 - *
74.26 - * You should have received a copy of the GNU Lesser General Public License
74.27 - * along with this program; if not, write to the Free Software
74.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
74.29 - */
74.30 -
74.31 -#ifdef HAVE_CONFIG_H
74.32 -#include "config.h"
74.33 -#endif
74.34 -
74.35 -#include <assert.h>
74.36 -#include <libxml/parser.h>
74.37 -#include <libxml/tree.h>
74.38 -#include <libxml/xpath.h>
74.39 -#include <libxml/uri.h>
74.40 -
74.41 -#include "gmyth_http.h"
74.42 -#include "gmyth_debug.h"
74.43 -#include "gmyth_socket.h"
74.44 -
74.45 -xmlXPathObjectPtr
74.46 -getnodeset(xmlDocPtr doc, xmlChar * xpath)
74.47 -{
74.48 -
74.49 - xmlXPathContextPtr context;
74.50 - xmlXPathObjectPtr result;
74.51 -
74.52 - context = xmlXPathNewContext(doc);
74.53 - result = xmlXPathEvalExpression(xpath, context);
74.54 -
74.55 - if (xmlXPathNodeSetIsEmpty(result->nodesetval)) {
74.56 - g_fprintf(stderr, "Error: No result at XPath\n");
74.57 - return NULL;
74.58 - }
74.59 -
74.60 - xmlXPathFreeContext(context);
74.61 - return result;
74.62 -}
74.63 -
74.64 -
74.65 -xmlDocPtr
74.66 -XMLParse(const char *content, int length)
74.67 -{
74.68 - xmlDocPtr doc; /* the resulting document tree */
74.69 -
74.70 - doc = xmlReadMemory(content, length, NULL, NULL, 0);
74.71 - if (doc == NULL) {
74.72 - g_fprintf(stderr, "Error: Failed to parse XML document\n");
74.73 - return NULL;
74.74 - }
74.75 -
74.76 - return doc;
74.77 -}
74.78 -
74.79 -xmlXPathObjectPtr
74.80 -getXPath(xmlChar * xpath, xmlDocPtr doc)
74.81 -{
74.82 - xmlXPathObjectPtr result;
74.83 -
74.84 - result = getnodeset(doc, xpath);
74.85 - return result;
74.86 -}
74.87 -
74.88 -
74.89 -/** Retrieves the Progam List from the Channel
74.90 - *
74.91 - * @param nodeTab A pointer to a node inside the XML
74.92 - * @return A GSList containing a list of all the programs
74.93 - */
74.94 -GSList *
74.95 -get_Program_List(xmlNodePtr node)
74.96 -{
74.97 - GSList *program_list = NULL;
74.98 -
74.99 - while (node != NULL) {
74.100 - if (g_ascii_strcasecmp((char *) node->name, "text") != 0) {
74.101 - GMythProgram *program = (GMythProgram *)
74.102 - g_malloc(sizeof(struct _GMythProgram));
74.103 -
74.104 - program->title = g_strdup((char *)
74.105 - xmlGetProp(node,
74.106 - (xmlChar *) "title"));
74.107 -
74.108 - program->subtitle = g_strdup((char *)
74.109 - xmlGetProp(node, (xmlChar *)
74.110 - "subtitle"));
74.111 -
74.112 - program->catType = g_strdup((char *)
74.113 - xmlGetProp(node, (xmlChar *)
74.114 - "catType"));
74.115 -
74.116 - program->category = g_strdup((char *)
74.117 - xmlGetProp(node, (xmlChar *)
74.118 - "category"));
74.119 -
74.120 - sscanf((char *) xmlGetProp(node, (xmlChar *) "repeat"),
74.121 - "%d", &(program->repeat));
74.122 -
74.123 - program->startTime = gmyth_util_string_to_time_val
74.124 - ((char *) xmlGetProp(node, (xmlChar *) "startTime"));
74.125 -
74.126 - program->endTime = gmyth_util_string_to_time_val
74.127 - ((char *) xmlGetProp(node, (xmlChar *) "endTime"));
74.128 -
74.129 - program_list = g_slist_append(program_list, program);
74.130 - }
74.131 -
74.132 - node = node->next;
74.133 - }
74.134 -
74.135 - return program_list;
74.136 -}
74.137 -
74.138 -/** Retrieves the Channel List from the ProgramGuide
74.139 - *
74.140 - * @param node A pointer to a node inside the XML
74.141 - * @param epg The struct where is the current epg
74.142 - * @return The epg from "param" updated
74.143 - */
74.144 -void
74.145 -get_Channel_List(xmlNodePtr node, GMythEpg * epg)
74.146 -{
74.147 - epg->channelList = NULL;
74.148 -
74.149 - while (node != NULL) {
74.150 -
74.151 - if (g_ascii_strcasecmp((char *) node->name, "text") != 0) {
74.152 - GMythChannel *channel = (GMythChannel *) g_malloc
74.153 - (sizeof(struct _GMythChannel));
74.154 -
74.155 - channel->channelName = g_strdup((char *)
74.156 - xmlGetProp(node, (xmlChar *)
74.157 - "channelName"));
74.158 -
74.159 - channel->chanNum = g_strdup((char *)
74.160 - xmlGetProp(node, (xmlChar *)
74.161 - "chanNum"));
74.162 -
74.163 - sscanf((char *) xmlGetProp(node, (xmlChar *) "chanId"),
74.164 - "%d", &(channel->chanId));
74.165 -
74.166 - sscanf((char *) xmlGetProp(node, (xmlChar *) "callSign"),
74.167 - "%d", &(channel->callSign));
74.168 -
74.169 - channel->programList = get_Program_List(node->children);
74.170 -
74.171 - epg->channelList = g_slist_append(epg->channelList, channel);
74.172 -
74.173 - }
74.174 -
74.175 - node = node->next;
74.176 - }
74.177 -}
74.178 -
74.179 -/** Retrieves the properties from the ProgramGuide
74.180 - *
74.181 - * @param nodeTab A pointer to a node inside the XML
74.182 - * @param epg The struct where is the current epg
74.183 - * @return The epg from "param" updated
74.184 - */
74.185 -void
74.186 -get_ProgramGuide_Properties(xmlNodePtr nodeTab, GMythEpg * epg)
74.187 -{
74.188 -
74.189 - xmlNode *ptr = nodeTab->children->next->children;
74.190 -
74.191 - epg->startTime = gmyth_util_string_to_time_val((char *) ptr->content);
74.192 -
74.193 - ptr = ptr->parent->next->next->children;
74.194 - epg->endTime = gmyth_util_string_to_time_val((char *) ptr->content);
74.195 -
74.196 - ptr = ptr->parent->next->next->children;
74.197 - sscanf((char *) ptr->content, "%d", &(epg->startChanId));
74.198 -
74.199 - ptr = ptr->parent->next->next->children;
74.200 - sscanf((char *) ptr->content, "%d", &(epg->endChanId));
74.201 -
74.202 - ptr = ptr->parent->next->next->children;
74.203 - sscanf((char *) ptr->content, "%d", &(epg->numOfChannels));
74.204 -
74.205 - ptr = ptr->parent->next->next->children;
74.206 - sscanf((char *) ptr->content, "%d", &(epg->details));
74.207 -
74.208 - ptr = ptr->parent->next->next->children;
74.209 - sscanf((char *) ptr->content, "%d", &(epg->totalCount));
74.210 -
74.211 - ptr = ptr->parent->next->next->children;
74.212 - epg->asOf = gmyth_util_string_to_time_val((char *) ptr->content);
74.213 -
74.214 - ptr = ptr->parent->next->next->children;
74.215 - epg->version = g_strdup((char *) ptr->content);
74.216 -
74.217 - ptr = ptr->parent->next->next->children;
74.218 - sscanf((char *) ptr->content, "%d", &(epg->protoVer));
74.219 -
74.220 - ptr = ptr->parent->next->next->children;
74.221 - // go to Channel section and retrieve Channels and Programs
74.222 - if (epg->numOfChannels > 0)
74.223 - get_Channel_List(ptr, epg);
74.224 - else
74.225 - epg->channelList = NULL;
74.226 -}
74.227 -
74.228 -/** Aux function to retrieve the Eletronic Program Guide
74.229 - *
74.230 - * @param doc An XML document (xmlDocPtr)
74.231 - * @return The epg
74.232 - */
74.233 -void
74.234 -getEpg(xmlDocPtr doc, GMythEpg * epg)
74.235 -{
74.236 - xmlXPathObjectPtr result;
74.237 - xmlNodeSetPtr nodeset;
74.238 - xmlChar *keyword;
74.239 -
74.240 - int i;
74.241 -
74.242 - result = getXPath((xmlChar *) "/*", doc);
74.243 -
74.244 - if (result) {
74.245 - nodeset = result->nodesetval;
74.246 - for (i = 0; i < nodeset->nodeNr; i++) {
74.247 - keyword = (xmlChar *) nodeset->nodeTab[i]->name;
74.248 - if (g_ascii_strcasecmp
74.249 - ((char *) keyword, "GetProgramGuideResponse") == 0) {
74.250 - get_ProgramGuide_Properties(nodeset->nodeTab[i], epg);
74.251 - break;
74.252 - }
74.253 - }
74.254 - xmlXPathFreeObject(result);
74.255 - }
74.256 -
74.257 -}
74.258 -
74.259 -
74.260 -
74.261 -/** Retrieves the Eletronic Program Guide from the backend
74.262 - *
74.263 - * @param doc An XML document (xmlDocPtr)
74.264 - * @return The epg
74.265 - */
74.266 -GMythEpg
74.267 -gmyth_http_retrieve_epg(GMythBackendInfo * backend_info,
74.268 - GTimeVal * StartTime, GTimeVal * EndTime,
74.269 - gint StartChanId, gint NumOfChannels,
74.270 - gchar * Details)
74.271 -{
74.272 - GMythEpg epg;
74.273 - MemoryStruct chunk;
74.274 -
74.275 - chunk.memory = NULL; /* we expect realloc(NULL, size) to work */
74.276 - chunk.size = 0; /* no data at this point */
74.277 -
74.278 - gchar *starttime;
74.279 -
74.280 - starttime = (gchar *) xmlURIEscapeStr((const xmlChar *)
74.281 - gmyth_util_time_to_mythformat_from_time_val
74.282 - (StartTime), NULL);
74.283 -
74.284 - gchar *endtime;
74.285 -
74.286 - endtime = (gchar *) xmlURIEscapeStr((const xmlChar *)
74.287 - gmyth_util_time_to_mythformat_from_time_val
74.288 - (EndTime), NULL);
74.289 -
74.290 - GString *command = g_string_new("");
74.291 -
74.292 - g_string_printf(command,
74.293 - "GetProgramGuide?StartTime=%s&EndTime=%s&StartChanId=%d"
74.294 - "&NumOfChannels=%d&Details=%s", starttime, endtime,
74.295 - StartChanId, NumOfChannels, Details);
74.296 - gmyth_debug("HTTP Request command = %s\n", command->str);
74.297 -
74.298 - chunk = gmyth_http_request(backend_info, command);
74.299 - if (chunk.memory != NULL) {
74.300 - xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory));
74.301 -
74.302 - getEpg(doc, &epg);
74.303 - free(chunk.memory);
74.304 - }
74.305 -
74.306 - return epg;
74.307 -}
74.308 -
74.309 -
74.310 -GMythRecorded_Recording
74.311 -retrieve_recorded_recording(xmlNodePtr node)
74.312 -{
74.313 - GMythRecorded_Recording recording;
74.314 -
74.315 - if (g_ascii_strcasecmp((char *) node->name, "text") != 0) {
74.316 -
74.317 - sscanf((char *) xmlGetProp(node, (xmlChar *) "dupInType"),
74.318 - "%d", &(recording.dupInType));
74.319 -
74.320 - sscanf((char *) xmlGetProp(node, (xmlChar *) "dupMethod"),
74.321 - "%d", &(recording.dupMethod));
74.322 -
74.323 - sscanf((char *) xmlGetProp(node, (xmlChar *) "recStatus"),
74.324 - "%d", &(recording.recStatus));
74.325 -
74.326 - sscanf((char *) xmlGetProp(node, (xmlChar *) "encoderId"),
74.327 - "%d", &(recording.encoderId));
74.328 -
74.329 - sscanf((char *) xmlGetProp(node, (xmlChar *) "recordId"),
74.330 - "%d", &(recording.recordId));
74.331 -
74.332 - sscanf((char *) xmlGetProp(node, (xmlChar *) "recType"),
74.333 - "%d", &(recording.recType));
74.334 -
74.335 - recording.playGroup = g_strdup((char *)
74.336 - xmlGetProp(node, (xmlChar *)
74.337 - "playGroup"));
74.338 -
74.339 - recording.recGroup = g_strdup((char *)
74.340 - xmlGetProp(node,
74.341 - (xmlChar *) "recGroup"));
74.342 -
74.343 - recording.recProfile = g_strdup((char *)
74.344 - xmlGetProp(node, (xmlChar *)
74.345 - "recProfile"));
74.346 -
74.347 - sscanf((char *) xmlGetProp(node, (xmlChar *) "recPriority"),
74.348 - "%d", &(recording.recPriority));
74.349 -
74.350 - recording.recStartTs = gmyth_util_string_to_time_val
74.351 - ((char *) xmlGetProp(node, (xmlChar *) "recStartTs"));
74.352 -
74.353 - recording.recEndTs = gmyth_util_string_to_time_val
74.354 - ((char *) xmlGetProp(node, (xmlChar *) "recEndTs"));
74.355 - }
74.356 -
74.357 - return recording;
74.358 -}
74.359 -
74.360 -
74.361 -GMythRecorded_Channel
74.362 -retrieve_recorded_channel(xmlNodePtr node)
74.363 -{
74.364 - GMythRecorded_Channel channel;
74.365 -
74.366 - if (g_ascii_strcasecmp((char *) node->name, "text") != 0) {
74.367 -
74.368 - channel.chanFilters = g_strdup((char *)
74.369 - xmlGetProp(node, (xmlChar *)
74.370 - "chanFilters"));
74.371 -
74.372 - channel.channelName = g_strdup((char *)
74.373 - xmlGetProp(node, (xmlChar *)
74.374 - "channelName"));
74.375 -
74.376 - sscanf((char *) xmlGetProp(node, (xmlChar *) "chanNum"),
74.377 - "%d", &(channel.chanNum));
74.378 -
74.379 - sscanf((char *) xmlGetProp(node, (xmlChar *) "sourceId"),
74.380 - "%d", &(channel.sourceId));
74.381 -
74.382 - sscanf((char *) xmlGetProp(node, (xmlChar *) "commFree"),
74.383 - "%d", &(channel.commFree));
74.384 -
74.385 - sscanf((char *) xmlGetProp(node, (xmlChar *) "inputId"),
74.386 - "%d", &(channel.inputId));
74.387 -
74.388 - sscanf((char *) xmlGetProp(node, (xmlChar *) "chanId"),
74.389 - "%d", &(channel.chanId));
74.390 -
74.391 - sscanf((char *) xmlGetProp(node, (xmlChar *) "callSign"),
74.392 - "%d", &(channel.callSign));
74.393 - }
74.394 -
74.395 - return channel;
74.396 -}
74.397 -
74.398 -
74.399 -
74.400 -/** Retrieves all the programs from Recorded XML
74.401 - *
74.402 - * @param nodeTab A pointer to a node inside the XML
74.403 - * @param recorded The struct where is the current epg
74.404 - * @return list with all the recorded programs
74.405 - */
74.406 -GSList *
74.407 -get_Recorded_Programs(xmlNodePtr node)
74.408 -{
74.409 - GSList *programList = NULL;
74.410 -
74.411 - while (node != NULL) {
74.412 -
74.413 - if (g_ascii_strcasecmp((char *) node->name, "text") != 0) {
74.414 -
74.415 - GMythRecorded_Program *program = (GMythRecorded_Program *)
74.416 - g_malloc(sizeof(struct _GMythRecorded_Program));
74.417 -
74.418 - sscanf((char *)
74.419 - xmlGetProp(node, (xmlChar *) "programFlags"), "%d",
74.420 - &(program->programFlags));
74.421 -
74.422 - program->title = g_strdup((char *)
74.423 - xmlGetProp(node,
74.424 - (xmlChar *) "title"));
74.425 -
74.426 - sscanf((char *) xmlGetProp(node, (xmlChar *) "programId"),
74.427 - "%d", &(program->programId));
74.428 -
74.429 - program->catType = g_strdup((char *)
74.430 - xmlGetProp(node, (xmlChar *)
74.431 - "catType"));
74.432 -
74.433 - program->category = g_strdup((char *)
74.434 - xmlGetProp(node, (xmlChar *)
74.435 - "category"));
74.436 -
74.437 - sscanf((char *) xmlGetProp(node, (xmlChar *) "seriesId"),
74.438 - "%d", &(program->seriesId));
74.439 -
74.440 -
74.441 - program->startTime = gmyth_util_string_to_time_val
74.442 - ((char *) xmlGetProp(node, (xmlChar *) "startTime"));
74.443 -
74.444 - program->endTime = gmyth_util_string_to_time_val
74.445 - ((char *) xmlGetProp(node, (xmlChar *) "endTime"));
74.446 -
74.447 - program->lastModified = gmyth_util_string_to_time_val((char *)
74.448 - xmlGetProp
74.449 - (node,
74.450 - (xmlChar
74.451 - *)
74.452 - "lastModified"));
74.453 -
74.454 - /*
74.455 - * TODO: FIX ME at gmyth_util program->asOf =
74.456 - * gmyth_util_string_to_time_val\ ((char *)xmlGetProp(node,
74.457 - * (xmlChar *)"airdate"));
74.458 - */
74.459 -
74.460 - program->subTitle = g_strdup((char *)
74.461 - xmlGetProp(node, (xmlChar *)
74.462 - "subTitle"));
74.463 -
74.464 - sscanf((char *) xmlGetProp(node, (xmlChar *) "stars"),
74.465 - "%d", &(program->stars));
74.466 -
74.467 - sscanf((char *) xmlGetProp(node, (xmlChar *) "repeat"),
74.468 - "%d", &(program->repeat));
74.469 -
74.470 - sscanf((char *) xmlGetProp(node, (xmlChar *) "fileSize"),
74.471 - "%d", &(program->repeat));
74.472 -
74.473 - program->hostname = g_strdup((char *)
74.474 - xmlGetProp(node, (xmlChar *)
74.475 - "hostname"));
74.476 -
74.477 - program->channel = retrieve_recorded_channel(node->children);
74.478 -
74.479 - // Skip the \n
74.480 - program->recording =
74.481 - retrieve_recorded_recording(node->children->next->next);
74.482 -
74.483 - // add to the list
74.484 - programList = g_slist_append(programList, program);
74.485 - }
74.486 -
74.487 - node = node->next;
74.488 - }
74.489 -
74.490 - return programList;
74.491 -}
74.492 -
74.493 -/** Retrieves the properties from Recorded XML
74.494 - *
74.495 - * @param nodeTab A pointer to a node inside the XML
74.496 - * @param recorded The struct where is the current epg
74.497 - * @return "recorded" from "param" updated
74.498 - */
74.499 -void
74.500 -get_Recorded_Properties(xmlNodePtr nodeTab, GMythRecorded * recorded)
74.501 -{
74.502 - xmlNode *ptr = nodeTab->children->next->children;
74.503 -
74.504 - sscanf((char *) ptr->content, "%d", &(recorded->totalCount));
74.505 -
74.506 -
74.507 - ptr = ptr->parent->next->next->children;
74.508 - recorded->asOf = gmyth_util_string_to_time_val((char *) ptr->content);
74.509 -
74.510 - ptr = ptr->parent->next->next->children;
74.511 - recorded->version = g_strdup((char *) ptr->content);
74.512 -
74.513 - ptr = ptr->parent->next->next->children;
74.514 - sscanf((char *) ptr->content, "%d", &(recorded->protoVer));
74.515 -
74.516 - ptr = ptr->parent->next->next->children;
74.517 - if (recorded->totalCount > 0)
74.518 - recorded->programList = get_Recorded_Programs(ptr->children);
74.519 -
74.520 -}
74.521 -
74.522 -
74.523 -/** Aux function to retrieve Recorded programs
74.524 - *
74.525 - * @param doc An XML document (xmlDocPtr)
74.526 - * @return The recorded var updated
74.527 - */
74.528 -void
74.529 -getRecorded(xmlDocPtr doc, GMythRecorded * recorded)
74.530 -{
74.531 - xmlXPathObjectPtr result;
74.532 - xmlNodeSetPtr nodeset;
74.533 - xmlChar *keyword;
74.534 -
74.535 - int i;
74.536 -
74.537 - result = getXPath((xmlChar *) "/*", doc);
74.538 -
74.539 - if (result) {
74.540 - nodeset = result->nodesetval;
74.541 - for (i = 0; i < nodeset->nodeNr; i++) {
74.542 - keyword = (xmlChar *) nodeset->nodeTab[i]->name;
74.543 - if (g_ascii_strcasecmp
74.544 - ((char *) keyword, "GetRecordedResponse") == 0) {
74.545 - get_Recorded_Properties(nodeset->nodeTab[i], recorded);
74.546 - break;
74.547 - }
74.548 - }
74.549 - xmlXPathFreeObject(result);
74.550 - }
74.551 -
74.552 -}
74.553 -
74.554 -
74.555 -/** Function to retrieve the files that are recorded
74.556 - *
74.557 - */
74.558 -GMythRecorded
74.559 -gmyth_http_retrieve_recorded(GMythBackendInfo * backend_info)
74.560 -{
74.561 - GMythRecorded recorded;
74.562 - MemoryStruct chunk;
74.563 -
74.564 - chunk.memory = NULL;
74.565 - chunk.size = 0;
74.566 -
74.567 - GString *command = g_string_new("");
74.568 -
74.569 - g_string_printf(command, "GetRecorded");
74.570 -
74.571 - chunk = gmyth_http_request(backend_info, command);
74.572 - if (chunk.memory != NULL) {
74.573 - xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory));
74.574 -
74.575 - getRecorded(doc, &recorded);
74.576 - free(chunk.memory);
74.577 - }
74.578 -
74.579 - return recorded;
74.580 -}
74.581 -
74.582 -
74.583 -
74.584 -/** Function to retrieve jobqueue status
74.585 - *
74.586 - */
74.587 -gint
74.588 -gmyth_http_retrieve_job_status(GMythBackendInfo * backend_info,
74.589 - gint chanid, GTimeVal * start)
74.590 -{
74.591 - gint status = 0;
74.592 - gint count = 0;
74.593 - gint temp_chanid = 0;
74.594 - GTimeVal *temp_start = NULL;
74.595 - int i;
74.596 -
74.597 - xmlXPathObjectPtr result;
74.598 - xmlNodeSetPtr nodeset;
74.599 - xmlNodePtr node;
74.600 - MemoryStruct chunk;
74.601 -
74.602 - chunk.memory = NULL;
74.603 - chunk.size = 0;
74.604 -
74.605 - GString *command = g_string_new("");
74.606 -
74.607 - g_string_printf(command, "GetStatus");
74.608 -
74.609 - chunk = gmyth_http_request(backend_info, command);
74.610 -
74.611 - if (chunk.memory != NULL) {
74.612 - xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory));
74.613 -
74.614 - result = getXPath((xmlChar *) "/Status/JobQueue", doc);
74.615 - if (result) {
74.616 - nodeset = result->nodesetval;
74.617 - node = nodeset->nodeTab[0];
74.618 - sscanf((char *) xmlGetProp(node, (xmlChar *) "count"),
74.619 - "%d", &count);
74.620 -
74.621 - if (count > 0) {
74.622 -
74.623 - // Get the first child
74.624 - node = node->children->next;
74.625 -
74.626 - for (i = 0; i < count; i++) {
74.627 -
74.628 - sscanf((char *)
74.629 - xmlGetProp(node, (xmlChar *) "chanId"), "%d",
74.630 - &temp_chanid);
74.631 -
74.632 - if (chanid == temp_chanid) {
74.633 - temp_start = gmyth_util_string_to_time_val((char *)
74.634 - xmlGetProp
74.635 - (node,
74.636 - (xmlChar
74.637 - *)
74.638 - "startTime"));
74.639 -
74.640 - if ((temp_start->tv_sec == start->tv_sec) &&
74.641 - (temp_start->tv_usec == start->tv_usec))
74.642 - sscanf((char *)
74.643 - xmlGetProp(node,
74.644 - (xmlChar *) "status"),
74.645 - "%d", &status);
74.646 - }
74.647 - // Escape "text" node
74.648 - node = node->next->next;
74.649 - }
74.650 - }
74.651 -
74.652 - }
74.653 -
74.654 - xmlXPathFreeObject(result);
74.655 - free(chunk.memory);
74.656 -
74.657 - }
74.658 -
74.659 - return status;
74.660 -}
74.661 -
74.662 -
74.663 -
74.664 -/** Function to retrieve settings on the backend
74.665 - *
74.666 - * @param backend_info infos about the backend
74.667 - * @param key the key you want to retrieve
74.668 - * @param hostname the hostname that the key is set up
74.669 - * @return the value of the key
74.670 - */
74.671 -gchar *
74.672 -gmyth_http_retrieve_setting(GMythBackendInfo * backend_info,
74.673 - gchar * key, gchar * hostname)
74.674 -{
74.675 - xmlXPathObjectPtr result;
74.676 - xmlNodeSetPtr nodeset;
74.677 - xmlChar *keyword;
74.678 - MemoryStruct chunk;
74.679 - gchar *value = NULL;
74.680 -
74.681 - chunk.memory = NULL;
74.682 - chunk.size = 0;
74.683 -
74.684 - GString *command = g_string_new("");
74.685 -
74.686 - g_string_printf(command, "GetSetting?Key=%s&HostName=%s&Default=NULL",
74.687 - key, hostname);
74.688 -
74.689 - chunk = gmyth_http_request(backend_info, command);
74.690 -
74.691 - if (chunk.memory != NULL) {
74.692 - xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory));
74.693 -
74.694 - result = getXPath((xmlChar *) "/GetSettingResponse/Values/*", doc);
74.695 -
74.696 - if (result) {
74.697 - nodeset = result->nodesetval;
74.698 - keyword = (xmlChar *) nodeset->nodeTab[0]->name;
74.699 - if (g_ascii_strcasecmp((char *) keyword, "Value") == 0) {
74.700 - // Here we have the value
74.701 - value = (gchar *) nodeset->nodeTab[0]->children->content;
74.702 - }
74.703 - xmlXPathFreeObject(result);
74.704 - }
74.705 -
74.706 - free(chunk.memory);
74.707 - }
74.708 -
74.709 - return value;
74.710 -}
74.711 -
74.712 -/** Common steps for rec_profile's functions
74.713 - *
74.714 - * @param backend_info infos about the backend
74.715 - * @param id the profile's id that you want to delete
74.716 - * @return 0 if OK
74.717 - */
74.718 -gint
74.719 -rec_profile_common(GMythBackendInfo * backend_info, GString * command)
74.720 -{
74.721 - xmlXPathObjectPtr result;
74.722 - xmlNodeSetPtr nodeset;
74.723 - xmlChar *keyword;
74.724 - MemoryStruct chunk;
74.725 -
74.726 - chunk.memory = NULL;
74.727 - chunk.size = 0;
74.728 -
74.729 - int ret = -1;
74.730 -
74.731 - chunk = gmyth_http_request(backend_info, command);
74.732 -
74.733 - if (chunk.memory != NULL) {
74.734 - xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory));
74.735 -
74.736 - result = getXPath((xmlChar *) "/*", doc);
74.737 -
74.738 - if (result) {
74.739 - nodeset = result->nodesetval;
74.740 - keyword = (xmlChar *) nodeset->nodeTab[0]->name;
74.741 -
74.742 - if (g_ascii_strcasecmp((char *) keyword, "Success") == 0)
74.743 - ret = 0;
74.744 -
74.745 - xmlXPathFreeObject(result);
74.746 - }
74.747 -
74.748 - free(chunk.memory);
74.749 - }
74.750 -
74.751 - return ret;
74.752 -}
74.753 -
74.754 -
74.755 -/** Function to delete recording profiles
74.756 - *
74.757 - * @param backend_info infos about the backend
74.758 - * @param id the profile's id that you want to delete
74.759 - * @return 0 if OK
74.760 - */
74.761 -gint
74.762 -gmyth_http_del_rec_profile(GMythBackendInfo * backend_info, gint id)
74.763 -{
74.764 -
74.765 - GString *command = g_string_new("");
74.766 -
74.767 - g_string_printf(command, "delRecProfiles?id=%d", id);
74.768 -
74.769 -
74.770 - return rec_profile_common(backend_info, command);
74.771 -}
74.772 -
74.773 -/** Function to create recording profiles
74.774 - *
74.775 - * @param backend_info infos about the backend
74.776 - * @param profilename the name of profile you want to use
74.777 - * @param groupname the name of groupname you want to use
74.778 - * @param vcodec the name of the video codec you want to use
74.779 - * @param acodec the name of the audo codec you want to use
74.780 - * @return 0 if OK
74.781 - */
74.782 -gint
74.783 -gmyth_http_create_rec_profile(GMythBackendInfo * backend_info,
74.784 - GMythRecProfile * profile)
74.785 -{
74.786 -
74.787 - if (profile->name != NULL && profile->group != NULL &&
74.788 - profile->vcodec && profile->acodec && profile->options != NULL) {
74.789 - GString *command = g_string_new("");
74.790 -
74.791 - g_string_printf(command, "createRecProfiles?profilename=%s&"
74.792 - "groupname=%s&vcodec=%s&acodec=%s&"
74.793 - "transcodelossless=%d&transcoderesize=%d&"
74.794 - "width=%d&height=%d&rtjpegquality=%d&"
74.795 - "rtjpeglumafilter=%d&rtjpegchromafilter=%d&"
74.796 - "mpeg4bitrate=%d&mpeg4maxquality=%d&"
74.797 - "mpeg4minquality=%d&mpeg4qualdiff=%d&"
74.798 - "mpeg4scalebitrate=%d&mpeg4optionvhq=%d&"
74.799 - "mpeg4option4mv=%d&mpeg4optionidct=%d&"
74.800 - "mpeg4optionime=%d&hardwaremjpegquality=%d&"
74.801 - "hardwaremjpeghdecimation=%d&hardwaremjpegvdecimation=%d&"
74.802 - "mpeg2streamtype=%s&mpeg2aspectratio=%s&"
74.803 - "mpeg2bitrate=%d&mpeg2maxbitrate=%d&"
74.804 - "samplerate=%d&mp3quality=%d&"
74.805 - "volume=%d&mpeg2audtype=%s&"
74.806 - "mpeg2audbitratel1=%d&mpeg2audbitratel2=%d&"
74.807 - "mpeg2audvolume=%d",
74.808 - profile->name, profile->group,
74.809 - profile->vcodec, profile->acodec,
74.810 - profile->options->transcodelossless,
74.811 - profile->options->transcoderesize,
74.812 - profile->options->width,
74.813 - profile->options->height,
74.814 - profile->options->rtjpegquality,
74.815 - profile->options->rtjpeglumafilter,
74.816 - profile->options->rtjpegchromafilter,
74.817 - profile->options->mpeg4bitrate,
74.818 - profile->options->mpeg4maxquality,
74.819 - profile->options->mpeg4minquality,
74.820 - profile->options->mpeg4qualdiff,
74.821 - profile->options->mpeg4scalebitrate,
74.822 - profile->options->mpeg4optionvhq,
74.823 - profile->options->mpeg4option4mv,
74.824 - profile->options->mpeg4optionidct,
74.825 - profile->options->mpeg4optionime,
74.826 - profile->options->hardwaremjpegquality,
74.827 - profile->options->hardwaremjpeghdecimation,
74.828 - profile->options->hardwaremjpegvdecimation,
74.829 - profile->options->mpeg2streamtype,
74.830 - profile->options->mpeg2aspectratio,
74.831 - profile->options->mpeg2bitrate,
74.832 - profile->options->mpeg2maxbitrate,
74.833 - profile->options->samplerate,
74.834 - profile->options->mp3quality,
74.835 - profile->options->volume,
74.836 - profile->options->mpeg2audtype,
74.837 - profile->options->mpeg2audbitratel1,
74.838 - profile->options->mpeg2audbitratel2,
74.839 - profile->options->mpeg2audvolume);
74.840 -
74.841 -
74.842 - return rec_profile_common(backend_info, command);
74.843 - } else
74.844 - return -1;
74.845 -}
74.846 -
74.847 -/** Function to retrieve recording profiles
74.848 - *
74.849 - * @param backend_info infos about the backend
74.850 - * @param groupname the name of group you want to retrieve
74.851 - * @return the list of profiles
74.852 - */
74.853 -GSList *
74.854 -gmyth_http_retrieve_rec_profiles(GMythBackendInfo * backend_info,
74.855 - gchar * groupname)
74.856 -{
74.857 - xmlXPathObjectPtr result;
74.858 - xmlNodeSetPtr nodeset;
74.859 - xmlChar *keyword;
74.860 - MemoryStruct chunk;
74.861 - GSList *profiles = NULL;
74.862 -
74.863 - chunk.memory = NULL;
74.864 - chunk.size = 0;
74.865 -
74.866 - GString *command = g_string_new("");
74.867 -
74.868 - g_string_printf(command, "GetRecProfiles?groupname=%s", groupname);
74.869 -
74.870 - chunk = gmyth_http_request(backend_info, command);
74.871 -
74.872 - if (chunk.memory != NULL) {
74.873 - xmlDocPtr doc = XMLParse(chunk.memory, strlen(chunk.memory));
74.874 -
74.875 - result = getXPath((xmlChar *) "/*", doc);
74.876 -
74.877 - if (result) {
74.878 - nodeset = result->nodesetval;
74.879 - keyword = (xmlChar *) nodeset->nodeTab[0]->name;
74.880 -
74.881 - if (g_ascii_strcasecmp((char *) keyword, "Profiles") == 0) {
74.882 - xmlNodePtr node = nodeset->nodeTab[0]->children->next;
74.883 - GMythRecProfile *profile;
74.884 -
74.885 - while (node != NULL) {
74.886 - if (g_ascii_strcasecmp((char *) node->name, "text") !=
74.887 - 0) {
74.888 - profile = gmyth_recprofile_new();
74.889 -
74.890 - sscanf((char *) xmlGetProp(node, (xmlChar *)
74.891 - "id"), "%d",
74.892 - &(profile->id));
74.893 -
74.894 - profile->name = g_strdup((char *)
74.895 - xmlGetProp(node,
74.896 - (xmlChar *)
74.897 - "name"));
74.898 -
74.899 - profile->vcodec = g_strdup((char *)
74.900 - xmlGetProp(node,
74.901 - (xmlChar *)
74.902 - "vcodec"));
74.903 -
74.904 - profile->acodec = g_strdup((char *)
74.905 - xmlGetProp(node,
74.906 - (xmlChar *)
74.907 - "acodec"));
74.908 -
74.909 - profile->group = g_strdup(groupname);
74.910 -
74.911 - profiles = g_slist_append(profiles, profile);
74.912 - }
74.913 - node = node->next;
74.914 - }
74.915 -
74.916 - }
74.917 - xmlXPathFreeObject(result);
74.918 - }
74.919 -
74.920 - free(chunk.memory);
74.921 - }
74.922 -
74.923 - return profiles;
74.924 -}
74.925 -
74.926 -
74.927 -
74.928 -/*
74.929 - * Aux functions got from libcurl
74.930 - */
74.931 -void *
74.932 -myrealloc(void *ptr, size_t size)
74.933 -{
74.934 - /*
74.935 - * There might be a realloc() out there that doesn't like reallocing
74.936 - * NULL pointers, so we take care of it here
74.937 - */
74.938 - if (ptr)
74.939 - return realloc(ptr, size);
74.940 - else
74.941 - return malloc(size);
74.942 -}
74.943 -
74.944 -size_t
74.945 -WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
74.946 -{
74.947 - size_t realsize = size * nmemb;
74.948 - MemoryStruct *mem = (struct _MemoryStruct *) data;
74.949 -
74.950 - mem->memory =
74.951 - (char *) myrealloc(mem->memory, mem->size + realsize + 1);
74.952 - if (mem->memory) {
74.953 - memcpy(&(mem->memory[mem->size]), ptr, realsize);
74.954 - mem->size += realsize;
74.955 - mem->memory[mem->size] = 0;
74.956 - }
74.957 -
74.958 - return realsize;
74.959 -}
74.960 -
74.961 -
74.962 -/** Send HTTP Command and receives the result of it
74.963 - *
74.964 - * @return A string with the response from the server
74.965 - * NULL if there is no response.
74.966 - */
74.967 -MemoryStruct
74.968 -gmyth_http_request(GMythBackendInfo * backend_info, GString * command)
74.969 -{
74.970 - LIBXML_TEST_VERSION
74.971 - size_t size =
74.972 - strlen(backend_info->hostname) + strlen(command->str) + 20;
74.973 -
74.974 - gchar *URL = (gchar *) g_malloc(sizeof(gchar) * size);
74.975 - gchar *mid = (gchar *) g_malloc(sizeof(gchar) * 6);
74.976 -
74.977 - mid = "";
74.978 -
74.979 - if (g_ascii_strcasecmp(command->str, "GetStatus") &&
74.980 - g_ascii_strcasecmp(command->str, "GetStatusHTML")) {
74.981 - mid = "Myth/";
74.982 - }
74.983 -
74.984 - g_snprintf(URL, size, "http://%s:%d/%s%s",
74.985 - backend_info->hostname, backend_info->status_port, mid,
74.986 - command->str);
74.987 -
74.988 - CURL *curl_handle;
74.989 -
74.990 - MemoryStruct chunk;
74.991 -
74.992 - chunk.memory = NULL; /* we expect realloc(NULL, size) to work */
74.993 - chunk.size = 0; /* no data at this point */
74.994 -
74.995 - curl_global_init(CURL_GLOBAL_ALL);
74.996 -
74.997 - /*
74.998 - * init the curl session
74.999 - */
74.1000 - curl_handle = curl_easy_init();
74.1001 -
74.1002 - /*
74.1003 - * specify URL to get
74.1004 - */
74.1005 - curl_easy_setopt(curl_handle, CURLOPT_URL, URL);
74.1006 -
74.1007 - /*
74.1008 - * send all data to this function
74.1009 - */
74.1010 - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION,
74.1011 - WriteMemoryCallback);
74.1012 -
74.1013 - /*
74.1014 - * we pass our 'chunk' struct to the callback function
74.1015 - */
74.1016 - curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *) &chunk);
74.1017 -
74.1018 - /*
74.1019 - * some servers don't like requests that are made without a user-agent
74.1020 - * field, so we provide one
74.1021 - */
74.1022 - curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
74.1023 -
74.1024 - /*
74.1025 - * set timeout
74.1026 - */
74.1027 - curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, 20);
74.1028 -
74.1029 - /*
74.1030 - * get it!
74.1031 - */
74.1032 - curl_easy_perform(curl_handle);
74.1033 -
74.1034 - /*
74.1035 - * cleanup curl stuff
74.1036 - */
74.1037 - curl_easy_cleanup(curl_handle);
74.1038 -
74.1039 - return chunk;
74.1040 -}
75.1 --- a/gmyth/src/gmyth_http.h Mon Feb 25 17:45:36 2008 +0000
75.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
75.3 @@ -1,204 +0,0 @@
75.4 -/**
75.5 - * GMyth Library
75.6 - *
75.7 - * @file gmyth/gmyth_http.h
75.8 - *
75.9 - * @brief <p> GMythHttp library provides a wrapper to access
75.10 - * data from the database using http+xml
75.11 - *
75.12 - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
75.13 - * @author Artur Duque de Souza <artur.souza@indt.org.br>
75.14 - *
75.15 - *
75.16 - * This program is free software; you can redistribute it and/or modify
75.17 - * it under the terms of the GNU Lesser General Public License as published by
75.18 - * the Free Software Foundation; either version 2 of the License, or
75.19 - * (at your option) any later version.
75.20 - *
75.21 - * This program is distributed in the hope that it will be useful,
75.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
75.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
75.24 - * GNU General Public License for more details.
75.25 - *
75.26 - * You should have received a copy of the GNU Lesser General Public License
75.27 - * along with this program; if not, write to the Free Software
75.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
75.29 - */
75.30 -
75.31 -#ifndef __GMYTH_HTTP_H__
75.32 -#define __GMYTH_HTTP_H__
75.33 -
75.34 -#include <glib-object.h>
75.35 -
75.36 -#include <stdio.h>
75.37 -#include <stdlib.h>
75.38 -#include <string.h>
75.39 -#include <stdarg.h>
75.40 -#include <glib.h>
75.41 -#include <glib/gprintf.h>
75.42 -
75.43 -#include "gmyth_backendinfo.h"
75.44 -#include "gmyth_util.h"
75.45 -#include "gmyth_recprofile.h"
75.46 -
75.47 -#include <curl/curl.h>
75.48 -#include <curl/types.h>
75.49 -#include <curl/easy.h>
75.50 -
75.51 -G_BEGIN_DECLS
75.52 -#define MYTH_PORT_STATUS 6544
75.53 -#define JOB_UNKNOWN 0x0000
75.54 -#define JOB_QUEUED 0x0001
75.55 -#define JOB_PENDING 0x0002
75.56 -#define JOB_STARTING 0x0003
75.57 -#define JOB_RUNNING 0x0004
75.58 -#define JOB_STOPPING 0x0005
75.59 -#define JOB_PAUSED 0x0006
75.60 -#define JOB_RETRY 0x0007
75.61 -#define JOB_ERRORING 0x0008
75.62 -#define JOB_ABORTING 0x0009
75.63 - // JOB_DONE is a mask to indicate the job is done
75.64 - // whatever the status is
75.65 -#define JOB_DONE 0x0100
75.66 -#define JOB_FINISHED 0x0110
75.67 -#define JOB_ABORTED 0x0120
75.68 -#define JOB_ERRORED 0x0130
75.69 -#define JOB_CANCELLED 0x0140
75.70 -typedef struct _GMythRecorded_Recording GMythRecorded_Recording;
75.71 -typedef struct _GMythRecorded_Channel GMythRecorded_Channel;
75.72 -typedef struct _GMythRecorded_Program GMythRecorded_Program;
75.73 -typedef struct _GMythRecorded GMythRecorded;
75.74 -typedef struct _GMythProgram GMythProgram;
75.75 -typedef struct _GMythChannel GMythChannel;
75.76 -typedef struct _GMythEpg GMythEpg;
75.77 -typedef struct _MemoryStruct MemoryStruct;
75.78 -
75.79 -struct _MemoryStruct {
75.80 - char *memory;
75.81 - size_t size;
75.82 -};
75.83 -
75.84 -struct _GMythProgram {
75.85 - gchar *title;
75.86 - gchar *subtitle;
75.87 - gchar *catType;
75.88 - gchar *category;
75.89 - gint repeat;
75.90 - GTimeVal *startTime;
75.91 - GTimeVal *endTime;
75.92 -};
75.93 -
75.94 -struct _GMythChannel {
75.95 - gchar *channelName;
75.96 - gchar *chanNum;
75.97 - gint chanId;
75.98 - gint callSign;
75.99 - GSList *programList;
75.100 -};
75.101 -
75.102 -struct _GMythEpg {
75.103 - gint startChanId;
75.104 - gint endChanId;
75.105 - gchar *version;
75.106 - gint protoVer;
75.107 - gint totalCount;
75.108 - gint numOfChannels;
75.109 - GTimeVal *asOf;
75.110 - GTimeVal *startTime;
75.111 - GTimeVal *endTime;
75.112 - gint details;
75.113 - GSList *channelList;
75.114 -};
75.115 -
75.116 -
75.117 -struct _GMythRecorded_Recording {
75.118 - gint dupInType;
75.119 - gint dupMethod;
75.120 - gchar *playGroup;
75.121 - gchar *recGroup;
75.122 - gchar *recProfile;
75.123 - gint recPriority;
75.124 - gint recStatus;
75.125 - gint encoderId;
75.126 - gint recordId;
75.127 - gint recType;
75.128 - GTimeVal *recStartTs;
75.129 - GTimeVal *recEndTs;
75.130 -};
75.131 -
75.132 -
75.133 -struct _GMythRecorded_Channel {
75.134 - gchar *chanFilters;
75.135 - gchar *channelName;
75.136 - gint chanNum;
75.137 - gint sourceId;
75.138 - gint commFree;
75.139 - gint inputId;
75.140 - gint chanId;
75.141 - gint callSign;
75.142 -};
75.143 -
75.144 -
75.145 -struct _GMythRecorded_Program {
75.146 - gint programFlags;
75.147 - gchar *title;
75.148 - gint programId;
75.149 - gchar *catType;
75.150 - gchar *category;
75.151 - gint seriesId;
75.152 - GTimeVal *startTime;
75.153 - GTimeVal *endTime;
75.154 - GTimeVal *airdate; // ?
75.155 - GTimeVal *lastModified;
75.156 - gchar *subTitle;
75.157 - gint stars;
75.158 - gint repeat;
75.159 - gint fileSize;
75.160 - gchar *hostname;
75.161 - GMythRecorded_Channel channel;
75.162 - GMythRecorded_Recording recording;
75.163 -};
75.164 -
75.165 -struct _GMythRecorded {
75.166 - gchar *version;
75.167 - gint protoVer;
75.168 - gint totalCount;
75.169 - GTimeVal *asOf;
75.170 - GSList *programList;
75.171 -};
75.172 -
75.173 -
75.174 -gint gmyth_http_retrieve_job_status(GMythBackendInfo *
75.175 - backend_info, gint chanid,
75.176 - GTimeVal * start);
75.177 -
75.178 -gchar *gmyth_http_retrieve_setting(GMythBackendInfo *
75.179 - backend_info, gchar * key,
75.180 - gchar * hostname);
75.181 -
75.182 -GMythEpg gmyth_http_retrieve_epg(GMythBackendInfo * backend_info,
75.183 - GTimeVal * StartTime,
75.184 - GTimeVal * EndTime,
75.185 - gint StartChanId,
75.186 - gint NumOfChannels,
75.187 - gchar * Details);
75.188 -
75.189 -GMythRecorded gmyth_http_retrieve_recorded(GMythBackendInfo *
75.190 - backend_info);
75.191 -
75.192 -GSList *gmyth_http_retrieve_rec_profiles(GMythBackendInfo *
75.193 - backend_info,
75.194 - gchar * groupname);
75.195 -
75.196 -gint gmyth_http_create_rec_profile(GMythBackendInfo *
75.197 - backend_info,
75.198 - GMythRecProfile * profile);
75.199 -
75.200 -gint gmyth_http_del_rec_profile(GMythBackendInfo * backend_info,
75.201 - gint id);
75.202 -
75.203 -MemoryStruct gmyth_http_request(GMythBackendInfo * backend_info,
75.204 - GString * command);
75.205 -
75.206 -G_END_DECLS
75.207 -#endif /* __GMYTH_HTTP_H__ */
76.1 --- a/gmyth/src/gmyth_jobqueue.c Mon Feb 25 17:45:36 2008 +0000
76.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
76.3 @@ -1,200 +0,0 @@
76.4 -/**
76.5 - * GMyth Library
76.6 - *
76.7 - * @file gmyth/gmyth_jobqueue.c
76.8 - *
76.9 - * @brief <p> Library to use JobQueue from mythbackend
76.10 - *
76.11 - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
76.12 - * @author Artur Duque de Souza <artur.souza@indt.org.br>
76.13 - *
76.14 - *
76.15 - * This program is free software; you can redistribute it and/or modify
76.16 - * it under the terms of the GNU Lesser General Public License as published by
76.17 - * the Free Software Foundation; either version 2 of the License, or
76.18 - * (at your option) any later version.
76.19 - *
76.20 - * This program is distributed in the hope that it will be useful,
76.21 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
76.22 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
76.23 - * GNU General Public License for more details.
76.24 - *
76.25 - * You should have received a copy of the GNU Lesser General Public License
76.26 - * along with this program; if not, write to the Free Software
76.27 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
76.28 - */
76.29 -
76.30 -#ifdef HAVE_CONFIG_H
76.31 -#include "config.h"
76.32 -#endif
76.33 -
76.34 -#include "gmyth_jobqueue.h"
76.35 -#include "gmyth_http.h"
76.36 -#include "gmyth_debug.h"
76.37 -#include "gmyth_socket.h"
76.38 -
76.39 -/** Function to connect
76.40 - *
76.41 - * @param backend_info the backendinfo
76.42 - * @return gboolean - result of connection
76.43 - *
76.44 - */
76.45 -static GMythSocket *
76.46 -backend_connect(GMythBackendInfo * backend_info)
76.47 -{
76.48 - GMythSocket *socket = gmyth_socket_new();
76.49 -
76.50 - if (gmyth_socket_connect_to_backend(socket,
76.51 - gmyth_backend_info_get_hostname
76.52 - (backend_info),
76.53 - gmyth_backend_info_get_port
76.54 - (backend_info), TRUE) == TRUE) {
76.55 - gmyth_debug("Backend socket connection success");
76.56 - return socket;
76.57 - } else {
76.58 - gmyth_debug("Connection failed");
76.59 - return NULL;
76.60 - }
76.61 -}
76.62 -
76.63 -
76.64 -/** Function to send a command to the backend
76.65 - *
76.66 - * @param socket pointer to a socket
76.67 - * @param action the action itself
76.68 - * @param job the action itself
76.69 - * @param chanid the action itself
76.70 - * @param starttime the action itself
76.71 - * @param options the action itself
76.72 - * @return the value returned by the backend
76.73 - *
76.74 - */
76.75 -static gchar *
76.76 -send_command(GMythSocket * socket, gchar * action,
76.77 - gchar * job, gint chanid, gchar * starttime, gchar * options)
76.78 -{
76.79 - GString *command = g_string_new("");
76.80 - GString *ret_str;
76.81 - gchar *ret;
76.82 -
76.83 - GMythStringList *retlist = gmyth_string_list_new();
76.84 -
76.85 - g_string_printf(command, "JOBQUEUE %s %s %d %s %s", action, job,
76.86 - chanid, starttime, options);
76.87 -
76.88 - gmyth_string_list_append_string(retlist, command);
76.89 - gmyth_socket_write_stringlist(socket, retlist);
76.90 -
76.91 - // receive answer
76.92 - gmyth_socket_read_stringlist(socket, retlist);
76.93 - ret_str = gmyth_string_list_get_string(retlist, 0);
76.94 -
76.95 - // ret = ret_str->str;
76.96 - ret = g_string_free(ret_str, FALSE);
76.97 - g_string_free(command, TRUE);
76.98 -
76.99 - gmyth_string_list_clear_all(retlist);
76.100 - g_object_unref(retlist);
76.101 -
76.102 - return ret;
76.103 -}
76.104 -
76.105 -
76.106 -/** Function to analyze the response from the backend
76.107 - *
76.108 - * @param ret the msg returned by the backend
76.109 - * @param value the expected value
76.110 - * @return 0 if success and -1 if error
76.111 - *
76.112 - */
76.113 -static gboolean
76.114 -test_result(gchar * ret, gchar * value)
76.115 -{
76.116 - if (g_ascii_strcasecmp(ret, value) == 0) {
76.117 - return TRUE;
76.118 - } else {
76.119 - gmyth_debug("JobQueue Error: %s", ret);
76.120 - return FALSE;
76.121 - }
76.122 -}
76.123 -
76.124 -/** Function to add a job inside JOBQUEUE
76.125 - *
76.126 - * @param transcode object holding all the info about the transcoding
76.127 - * @param job the job you want to add the action
76.128 - * @return TRUE if the job was added, FALSE if not
76.129 - *
76.130 - */
76.131 -gboolean
76.132 -gmyth_jobqueue_add_job(GMythTranscoder * transcode, gchar * job)
76.133 -{
76.134 - GMythSocket *socket = backend_connect(transcode->backend_info);
76.135 - gboolean res = FALSE;
76.136 -
76.137 - if (socket != NULL) {
76.138 - GString *options = g_string_new("");
76.139 - gchar *ret = NULL;
76.140 -
76.141 - if (g_ascii_strcasecmp(job, "JOB_TRANSCODE") == 0) {
76.142 - if (transcode->cutlist)
76.143 - g_string_append(options, " JOB_USE_CUTLIST");
76.144 -
76.145 - if (transcode->output)
76.146 - g_string_append_printf(options, " JOB_OUTPUT %s",
76.147 - transcode->output_filename);
76.148 -
76.149 - if (transcode->profile != NULL)
76.150 - g_string_append_printf(options, " %s", transcode->profile);
76.151 - }
76.152 - ret = send_command(socket, "ADD", job, transcode->chanid,
76.153 - transcode->starttime, options->str);
76.154 - res = test_result(ret, "JOBQUEUE_OK");
76.155 - gmyth_socket_close_connection(socket);
76.156 -
76.157 - g_object_unref(socket);
76.158 -
76.159 - g_string_free(options, TRUE);
76.160 -
76.161 - if (ret)
76.162 - g_free(ret);
76.163 -
76.164 - } else {
76.165 - gmyth_debug("JobQueue Connection Failed");
76.166 - }
76.167 -
76.168 - return res;
76.169 -}
76.170 -
76.171 -/** Function to change a job cmd inside JOBQUEUE
76.172 - *
76.173 - * @param transcode object holding all the info about the transcoding
76.174 - * @param action the action (ADD)
76.175 - * @param job the job you want to add the action
76.176 - * @return the value of the key
76.177 - *
76.178 - */
76.179 -gboolean
76.180 -gmyth_jobqueue_change_cmd(GMythTranscoder * transcode, gchar * action,
76.181 - gchar * job)
76.182 -{
76.183 - GMythSocket *socket = backend_connect(transcode->backend_info);
76.184 - gboolean res = FALSE;
76.185 -
76.186 - if (socket != NULL) {
76.187 - gchar *ret = send_command(socket, action, job,
76.188 - transcode->chanid,
76.189 - transcode->starttime, "");
76.190 -
76.191 - res = test_result(ret, "JOBQUEUE_CHANGED_CMD_OK");
76.192 -
76.193 - gmyth_socket_close_connection(socket);
76.194 - g_object_unref(socket);
76.195 -
76.196 - g_free(ret);
76.197 -
76.198 - } else {
76.199 - gmyth_debug("JobQueue Connection Failed");
76.200 - }
76.201 -
76.202 - return res;
76.203 -}
77.1 --- a/gmyth/src/gmyth_jobqueue.h Mon Feb 25 17:45:36 2008 +0000
77.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
77.3 @@ -1,52 +0,0 @@
77.4 -/**
77.5 - * GMyth Library
77.6 - *
77.7 - * @file gmyth/gmyth_jobqueue.h
77.8 - *
77.9 - * @brief <p> Library to use JobQueue from mythbackend
77.10 - *
77.11 - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
77.12 - * @author Artur Duque de Souza <artur.souza@indt.org.br>
77.13 - *
77.14 - *
77.15 - * This program is free software; you can redistribute it and/or modify
77.16 - * it under the terms of the GNU Lesser General Public License as published by
77.17 - * the Free Software Foundation; either version 2 of the License, or
77.18 - * (at your option) any later version.
77.19 - *
77.20 - * This program is distributed in the hope that it will be useful,
77.21 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
77.22 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
77.23 - * GNU General Public License for more details.
77.24 - *
77.25 - * You should have received a copy of the GNU Lesser General Public License
77.26 - * along with this program; if not, write to the Free Software
77.27 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
77.28 - */
77.29 -
77.30 -#ifndef __GMYTH_JOBQUEUE_H__
77.31 -#define __GMYTH_JOBQUEUE_H__
77.32 -
77.33 -#include <glib-object.h>
77.34 -
77.35 -#include <stdio.h>
77.36 -#include <stdlib.h>
77.37 -#include <string.h>
77.38 -#include <stdarg.h>
77.39 -#include <glib.h>
77.40 -#include <glib/gprintf.h>
77.41 -
77.42 -#include "gmyth_stringlist.h"
77.43 -#include "gmyth_backendinfo.h"
77.44 -#include "gmyth_transcoder.h"
77.45 -#include "gmyth_socket.h"
77.46 -#include "gmyth_util.h"
77.47 -
77.48 -G_BEGIN_DECLS
77.49 - gboolean gmyth_jobqueue_add_job(GMythTranscoder * transcoder,
77.50 - gchar * job);
77.51 -gboolean gmyth_jobqueue_change_cmd(GMythTranscoder * transcoder,
77.52 - gchar * action, gchar * job);
77.53 -
77.54 -G_END_DECLS
77.55 -#endif /* __GMYTH_JOBQUEUE_H__ */
78.1 --- a/gmyth/src/gmyth_livetv.c Mon Feb 25 17:45:36 2008 +0000
78.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
78.3 @@ -1,980 +0,0 @@
78.4 -/**
78.5 - * GMyth Library
78.6 - *
78.7 - * @file gmyth/gmyth_livetv.c
78.8 - *
78.9 - * @brief <p> GMythLiveTV starts a remote TV session with the MythTV backend.
78.10 - *
78.11 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
78.12 - * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
78.13 - *
78.14 - *
78.15 - * This program is free software; you can redistribute it and/or modify
78.16 - * it under the terms of the GNU Lesser General Public License as published by
78.17 - * the Free Software Foundation; either version 2 of the License, or
78.18 - * (at your option) any later version.
78.19 - *
78.20 - * This program is distributed in the hope that it will be useful,
78.21 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
78.22 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
78.23 - * GNU General Public License for more details.
78.24 - *
78.25 - * You should have received a copy of the GNU Lesser General Public License
78.26 - * along with this program; if not, write to the Free Software
78.27 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
78.28 - */
78.29 -
78.30 -#ifdef HAVE_CONFIG_H
78.31 -#include "config.h"
78.32 -#endif
78.33 -
78.34 -#include "gmyth_livetv.h"
78.35 -#include "gmyth_remote_util.h"
78.36 -#include "gmyth_tvchain.h"
78.37 -#include "gmyth_socket.h"
78.38 -#include "gmyth_backendinfo.h"
78.39 -#include "gmyth_debug.h"
78.40 -
78.41 -#include "gmyth_file.h"
78.42 -#include "gmyth_file_transfer.h"
78.43 -#include "gmyth_file_local.h"
78.44 -#include "gmyth_monitor_handler.h"
78.45 -
78.46 -#include "gmyth_common.h"
78.47 -#include "gmyth_util.h"
78.48 -
78.49 -static void gmyth_livetv_class_init(GMythLiveTVClass * klass);
78.50 -static void gmyth_livetv_init(GMythLiveTV * object);
78.51 -
78.52 -static void gmyth_livetv_dispose(GObject * object);
78.53 -static void gmyth_livetv_finalize(GObject * object);
78.54 -
78.55 -static gint tvchain_curr_index = -1;
78.56 -
78.57 -/*
78.58 - * static GStaticMutex lock = G_STATIC_MUTEX_INIT;
78.59 - */
78.60 -
78.61 -#define GMYTHTV_TRANSFER_MAX_WAITS 100
78.62 -
78.63 -G_DEFINE_TYPE(GMythLiveTV, gmyth_livetv, G_TYPE_OBJECT)
78.64 - static void gmyth_livetv_class_init(GMythLiveTVClass * klass)
78.65 -{
78.66 - GObjectClass *gobject_class;
78.67 -
78.68 - gobject_class = (GObjectClass *) klass;
78.69 -
78.70 - gobject_class->dispose = gmyth_livetv_dispose;
78.71 - gobject_class->finalize = gmyth_livetv_finalize;
78.72 -}
78.73 -
78.74 -static void
78.75 -gmyth_livetv_init(GMythLiveTV * livetv)
78.76 -{
78.77 - livetv->monitor = NULL;
78.78 - livetv->backend_info = NULL;
78.79 - livetv->local_hostname = NULL;
78.80 - livetv->file = NULL;
78.81 - livetv->setup_done = FALSE;
78.82 -
78.83 - livetv->socket = NULL;
78.84 - livetv->recorder = NULL;
78.85 - livetv->tvchain = NULL;
78.86 - livetv->proginfo = NULL;
78.87 - livetv->uri = NULL;
78.88 -
78.89 - livetv->mutex = g_mutex_new();
78.90 -}
78.91 -
78.92 -static void
78.93 -gmyth_livetv_dispose(GObject * object)
78.94 -{
78.95 - GMythLiveTV *livetv = GMYTH_LIVETV(object);
78.96 -
78.97 -
78.98 - if (livetv->disposed) {
78.99 - /*
78.100 - * If dispose did already run, return.
78.101 - */
78.102 - return;
78.103 - }
78.104 -
78.105 - /*
78.106 - * Make sure dispose does not run twice.
78.107 - */
78.108 - livetv->disposed = TRUE;
78.109 -
78.110 - if (livetv->monitor != NULL) {
78.111 - g_object_unref(livetv->monitor);
78.112 - livetv->monitor = NULL;
78.113 - }
78.114 -
78.115 -
78.116 - if (livetv->file != NULL) {
78.117 - g_object_unref(livetv->file);
78.118 - livetv->file = NULL;
78.119 - }
78.120 -
78.121 - if (livetv->recorder != NULL) {
78.122 - // gmyth_recorder_close(livetv->recorder);
78.123 - g_object_unref(livetv->recorder);
78.124 - livetv->recorder = NULL;
78.125 - }
78.126 -
78.127 - if (livetv->socket != NULL) {
78.128 - g_object_unref(livetv->socket);
78.129 - livetv->socket = NULL;
78.130 - }
78.131 -
78.132 - if (livetv->tvchain != NULL) {
78.133 - g_object_unref(livetv->tvchain);
78.134 - livetv->tvchain = NULL;
78.135 - }
78.136 -
78.137 - if (livetv->proginfo != NULL) {
78.138 - g_object_unref(livetv->proginfo);
78.139 - livetv->proginfo = NULL;
78.140 - }
78.141 -
78.142 - if (livetv->backend_info != NULL) {
78.143 - g_object_unref(livetv->backend_info);
78.144 - livetv->backend_info = NULL;
78.145 - }
78.146 -
78.147 - if (livetv->uri != NULL) {
78.148 - g_object_unref(livetv->uri);
78.149 - livetv->uri = NULL;
78.150 - }
78.151 -
78.152 - if (livetv->mutex != NULL) {
78.153 - g_mutex_free(livetv->mutex);
78.154 - livetv->mutex = NULL;
78.155 - }
78.156 -
78.157 - if (livetv->local_hostname != NULL) {
78.158 - g_string_free(livetv->local_hostname, TRUE);
78.159 - livetv->local_hostname = NULL;
78.160 - }
78.161 -
78.162 - G_OBJECT_CLASS(gmyth_livetv_parent_class)->dispose(object);
78.163 -}
78.164 -
78.165 -static void
78.166 -gmyth_livetv_finalize(GObject * object)
78.167 -{
78.168 - g_signal_handlers_destroy(object);
78.169 -
78.170 - G_OBJECT_CLASS(gmyth_livetv_parent_class)->finalize(object);
78.171 -}
78.172 -
78.173 -/**
78.174 - * Creates a new GMythLiveTV instance
78.175 - *
78.176 - * @return a newly allocated GMythLiveTV instance
78.177 - */
78.178 -GMythLiveTV *
78.179 -gmyth_livetv_new(GMythBackendInfo * backend_info)
78.180 -{
78.181 - GMythLiveTV *livetv =
78.182 - GMYTH_LIVETV(g_object_new(GMYTH_LIVETV_TYPE, NULL));
78.183 -
78.184 - livetv->backend_info = backend_info;
78.185 - g_object_ref(livetv->backend_info);
78.186 -
78.187 - return livetv;
78.188 -}
78.189 -
78.190 -/**
78.191 - * The GObject signal handler function, from which all status messages
78.192 - * from the Monitor Handler will be advertized, all time it receives
78.193 - * LiveTV status messages from the MythTV backend
78.194 - *
78.195 - * @param monitor a GMythMonitorHandler instance
78.196 - * @param msg_code the MythTV's server numeric status code
78.197 - * @param message the message's string description
78.198 - * @param user_data pointer to the GMythLiveTV instance
78.199 - */
78.200 -static void
78.201 -gmyth_livetv_monitor_signal_handler(GMythMonitorHandler * monitor,
78.202 - gint msg_code, gchar * message,
78.203 - gpointer user_data)
78.204 -{
78.205 - GMythLiveTV *live_tv = GMYTH_LIVETV(user_data);
78.206 -
78.207 - gmyth_debug
78.208 - ("LIVETV Signal handler ( msg = %s, code = %d, live_tv param = %s, user_data = %s )\n",
78.209 - message, msg_code, live_tv != NULL ? "" : "NULL",
78.210 - user_data != NULL ? "" : "NULL");
78.211 -
78.212 - if (NULL == live_tv || !IS_GMYTH_FILE_TRANSFER(live_tv->file)) {
78.213 - gmyth_debug("LiveTV_obj is equals to NULL!!!");
78.214 - return;
78.215 - }
78.216 -
78.217 - switch (msg_code) {
78.218 -
78.219 - case GMYTH_BACKEND_PROGRAM_INFO_CHANGED:
78.220 - {
78.221 - gmyth_debug
78.222 - ("LIVETV Program Changed request received [ msg = %s ]. Watching if the new "
78.223 - "TV Chain ID is the same as the old one...\n", message);
78.224 - if (g_ascii_strcasecmp
78.225 - (message,
78.226 - (gmyth_tvchain_get_id(live_tv->tvchain))->str) != 0) {
78.227 - gmyth_debug
78.228 - ("OK!!! MOVED to the next program chain [actual == %s]!",
78.229 - (gmyth_tvchain_get_id(live_tv->tvchain))->str);
78.230 - /*
78.231 - * advertises the FileTransfer about the program info
78.232 - * changed
78.233 - */
78.234 - if (live_tv->file != NULL) {
78.235 - gmyth_debug
78.236 - ("Emitting signal to the FileTransfer... [ \"program-info-changed \" ]");
78.237 -
78.238 - gmyth_file_transfer_emit_program_info_changed_signal
78.239 - (GMYTH_FILE_TRANSFER(live_tv->file), msg_code,
78.240 - (gpointer) (live_tv->recorder));
78.241 -
78.242 - /*
78.243 - * gmyth_livetv_monitor_handler_stop( live_tv );
78.244 - */
78.245 - } else
78.246 - gmyth_debug
78.247 - ("LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n");
78.248 - }
78.249 - break;
78.250 - }
78.251 - case GMYTH_BACKEND_DONE_RECORDING:
78.252 - {
78.253 - gmyth_debug
78.254 - ("LIVETV Program Changed request received [ msg = %s ]. Watching if the new "
78.255 - "TV Chain ID is the same as the old one...\n", message);
78.256 - if (g_ascii_strcasecmp
78.257 - (message,
78.258 - (gmyth_tvchain_get_id(live_tv->tvchain))->str) != 0) {
78.259 - gmyth_debug
78.260 - ("OK!!! MOVED to the next program chain [actual == %s]!",
78.261 - (gmyth_tvchain_get_id(live_tv->tvchain))->str);
78.262 - /*
78.263 - * advertises the FileTransfer about the program info
78.264 - * changed
78.265 - */
78.266 - if (live_tv->file != NULL) {
78.267 - gmyth_debug
78.268 - ("Emitting signal to the FileTransfer... [ \"backend-done-recording\" ]");
78.269 -
78.270 - gmyth_file_transfer_emit_program_info_changed_signal
78.271 - (GMYTH_FILE_TRANSFER(live_tv->file), msg_code,
78.272 - (gpointer) (live_tv->recorder));
78.273 -
78.274 - } else
78.275 - gmyth_debug
78.276 - ("LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n");
78.277 - }
78.278 - break;
78.279 - }
78.280 - case GMYTH_BACKEND_STOP_LIVETV:
78.281 - {
78.282 - gmyth_debug
78.283 - ("LIVETV Stop LiveTV request received [ msg = %s ]. Going out the "
78.284 - "LiveTV...\n", message);
78.285 - /*
78.286 - * stops the LiveTV
78.287 - */
78.288 - if (live_tv != NULL) {
78.289 - gmyth_debug("Going out the LiveTV... [ \"quit-livetv\" ]");
78.290 -
78.291 - g_object_unref(live_tv);
78.292 - } else
78.293 - gmyth_debug
78.294 - ("LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n");
78.295 -
78.296 - break;
78.297 - }
78.298 - default:
78.299 - break;
78.300 - } /* switch (Monitor Handler messages) */
78.301 -
78.302 -}
78.303 -
78.304 -/**
78.305 - * Starts the Monitor Handler to this GMythLiveTV session, in order
78.306 - * to receive the status messages from the MythTV's backend server
78.307 - *
78.308 - * @param live_tv the GMythLiveTV instance
78.309 - *
78.310 - * @return <code>true</code> if the Monitor Handler start-up process
78.311 - * had been concluded succcesfully
78.312 - */
78.313 -gboolean
78.314 -gmyth_livetv_monitor_handler_start(GMythLiveTV * livetv)
78.315 -{
78.316 - gboolean res = TRUE;
78.317 -
78.318 - if (livetv->monitor != NULL) {
78.319 - g_object_unref(livetv->monitor);
78.320 - livetv->monitor = NULL;
78.321 - }
78.322 -
78.323 - livetv->monitor = gmyth_monitor_handler_new();
78.324 - res =
78.325 - gmyth_monitor_handler_open(livetv->monitor,
78.326 - livetv->backend_info->hostname,
78.327 - livetv->backend_info->port);
78.328 -
78.329 - if (res == TRUE) {
78.330 - gmyth_debug
78.331 - ("Connect MythTV Monitor event socket! Trying to start the message handler...");
78.332 -
78.333 - res = gmyth_monitor_handler_start(livetv->monitor);
78.334 -
78.335 - if (res) {
78.336 - gmyth_debug
78.337 - ("MythTV Monitor event socket connected and listening!");
78.338 - g_signal_connect(G_OBJECT(livetv->monitor),
78.339 - "backend-events-handler", (GCallback)
78.340 - gmyth_livetv_monitor_signal_handler, livetv);
78.341 - } else {
78.342 - gmyth_debug
78.343 - ("Problems when trying to start MythTV Monitor event socket!");
78.344 - goto error;
78.345 - }
78.346 - }
78.347 -
78.348 - error:
78.349 - return res;
78.350 -
78.351 -}
78.352 -
78.353 -/**
78.354 - * Stops the Monitor Handler to this GMythLiveTV session, in order
78.355 - * to stop receiving the status messages from the MythTV's backend server
78.356 - *
78.357 - * @param live_tv the GMythLiveTV instance
78.358 - *
78.359 - * @return <code>true</code> if the Monitor Handler shutdown process
78.360 - * had been concluded succcesfully
78.361 - */
78.362 -void
78.363 -gmyth_livetv_monitor_handler_stop(GMythLiveTV * livetv)
78.364 -{
78.365 -
78.366 - if (livetv->monitor != NULL) {
78.367 - g_object_unref(livetv->monitor);
78.368 - livetv->monitor = NULL;
78.369 - }
78.370 -
78.371 -}
78.372 -
78.373 -#if 0
78.374 -static gchar *
78.375 -gmyth_livetv_create_remote_url(GMythLiveTV * livetv)
78.376 -{
78.377 - gchar *uri = g_strdup("");
78.378 -
78.379 - gmyth_backend_info_get_remote_h
78.380 - // gmyth_backend(livetv->backend_info)
78.381 - return uri;
78.382 -}
78.383 -#endif
78.384 -
78.385 -/**
78.386 - * Configures the GMythLiveTV session, sends SPAWN_LIVETV message,
78.387 - * sets the channel name, and gets the first program info about the
78.388 - * actual recording
78.389 - *
78.390 - * @param live_tv the GMythLiveTV instance
78.391 - * @param channel the channel name (the chan_name field, from the tvchain table)
78.392 - * @param backend_info the GMythBackendInfo describing the remote server
78.393 - *
78.394 - * @return <code>true</code> if the LiveTV's recorder instance configuration
78.395 - * had been concluded succcesfully
78.396 - */
78.397 -static gboolean
78.398 -gmyth_livetv_setup_recorder_channel_name(GMythLiveTV * livetv,
78.399 - gchar * channel)
78.400 -{
78.401 - gboolean res = TRUE;
78.402 -
78.403 - g_return_val_if_fail(livetv != NULL, FALSE);
78.404 -
78.405 - g_mutex_lock(livetv->mutex);
78.406 -
78.407 - if (livetv->socket == NULL) {
78.408 - livetv->socket = gmyth_socket_new();
78.409 - /*
78.410 - * FIME: Implement this at gmyth_socket
78.411 - */
78.412 - res =
78.413 - gmyth_socket_connect_to_backend(livetv->socket,
78.414 - livetv->backend_info->hostname,
78.415 - livetv->backend_info->port,
78.416 - TRUE);
78.417 - if (!res) {
78.418 - gmyth_debug("[%s] LiveTV can not connect to backend",
78.419 - __FUNCTION__);
78.420 - res = FALSE;
78.421 - goto error;
78.422 - }
78.423 - }
78.424 -
78.425 - livetv->is_livetv = TRUE;
78.426 -
78.427 - livetv->local_hostname = gmyth_socket_get_local_hostname();
78.428 -
78.429 - if (livetv->local_hostname == NULL) {
78.430 - g_warning("livetv could not retrieve the local hostname");
78.431 - res = FALSE;
78.432 - goto error;
78.433 - } else {
78.434 - gmyth_debug("Local hostname: %s", livetv->local_hostname->str);
78.435 - }
78.436 -
78.437 - if (livetv->recorder != NULL) {
78.438 - g_object_unref(livetv->recorder);
78.439 - livetv->recorder = NULL;
78.440 - }
78.441 -
78.442 - if (gmyth_remote_util_get_free_recorder_count(livetv->socket) <= 0) {
78.443 - gmyth_debug("No free remote encoder available.");
78.444 - res = FALSE;
78.445 - goto error;
78.446 - }
78.447 -
78.448 - /*
78.449 - * Gets the recorder num
78.450 - */
78.451 - livetv->recorder =
78.452 - remote_request_next_free_recorder(livetv->socket, -1);
78.453 - gmyth_socket_close_connection(livetv->socket);
78.454 -
78.455 - if (NULL == livetv->recorder) {
78.456 - gmyth_debug("[%s] None remote encoder available", __FUNCTION__);
78.457 - res = FALSE;
78.458 - goto error;
78.459 - }
78.460 -
78.461 - /*
78.462 - * Init remote encoder. Opens its control socket.
78.463 - */
78.464 - res = gmyth_recorder_setup(livetv->recorder);
78.465 - if (!res) {
78.466 - gmyth_debug("[%s] Fail while setting remote encoder\n",
78.467 - __FUNCTION__);
78.468 - res = FALSE;
78.469 - goto error;
78.470 - }
78.471 -
78.472 - /*
78.473 - * Creates livetv chain handler
78.474 - */
78.475 - livetv->tvchain = gmyth_tvchain_new();
78.476 - gmyth_tvchain_initialize(livetv->tvchain, livetv->backend_info);
78.477 -
78.478 - if (livetv->tvchain == NULL || livetv->tvchain->tvchain_id == NULL) {
78.479 - res = FALSE;
78.480 - goto error;
78.481 - }
78.482 - // Spawn live tv. Uses the socket to send mythprotocol data to start
78.483 - // livetv in the backend (remotelly)
78.484 - res = gmyth_recorder_spawntv(livetv->recorder,
78.485 - gmyth_tvchain_get_id(livetv->tvchain));
78.486 - if (!res) {
78.487 - gmyth_debug("[%s] Fail while spawn tv\n", __FUNCTION__);
78.488 - res = FALSE;
78.489 - goto error;
78.490 - }
78.491 -
78.492 - if (res == TRUE) {
78.493 - /*
78.494 - * loop finished, set the max tries variable to zero again...
78.495 - */
78.496 - gint wait_to_transfer = 0;
78.497 -
78.498 - while (wait_to_transfer++ < GMYTHTV_TRANSFER_MAX_WAITS &&
78.499 - (gmyth_recorder_is_recording(livetv->recorder) == FALSE))
78.500 - g_usleep(300);
78.501 -
78.502 - if (channel != NULL) {
78.503 - /*
78.504 - * Pauses remote encoder.
78.505 - */
78.506 - res = gmyth_recorder_pause_recording(livetv->recorder);
78.507 - if (!res) {
78.508 - gmyth_debug("[%s] Fail while pausing remote encoder\n",
78.509 - __FUNCTION__);
78.510 - res = FALSE;
78.511 - goto error;
78.512 - }
78.513 -
78.514 - if (gmyth_recorder_check_channel_name
78.515 - (livetv->recorder, channel)) {
78.516 - if (gmyth_recorder_set_channel_name
78.517 - (livetv->recorder, channel)) {
78.518 - gmyth_debug("Channel changed!!! [%s].\n", channel);
78.519 - }
78.520 - }
78.521 -
78.522 - }
78.523 - /*
78.524 - * if - changes the channel number
78.525 - */
78.526 - /*
78.527 - * sleep (5);
78.528 - */
78.529 - /*
78.530 - * FIXME: this is evil (tpm)
78.531 - */
78.532 - }
78.533 -
78.534 - /*
78.535 - * DEBUG message
78.536 - */
78.537 - GMythProgramInfo *prog_info =
78.538 - gmyth_recorder_get_current_program_info(livetv->recorder);
78.539 -
78.540 - if (NULL == prog_info) {
78.541 - gmyth_debug("ProgramInfo is equals to NULL!!!");
78.542 -
78.543 - gint i;
78.544 - gchar *channame = NULL;
78.545 -
78.546 - gmyth_debug("Problem getting current proginfo!\n");
78.547 -
78.548 - /*
78.549 - * mythbackend must not be tuned in to a channel, so keep
78.550 - * changing channels until we find a valid one, or until
78.551 - * we decide to give up.
78.552 - */
78.553 - for (i = 1; i < 1000; i++) {
78.554 - if (channame != NULL)
78.555 - g_free(channame);
78.556 - channame = g_strdup_printf("%d", i);
78.557 - if (gmyth_recorder_set_channel_name(livetv->recorder, channame)
78.558 - < 0) {
78.559 - continue;
78.560 - }
78.561 - prog_info =
78.562 - gmyth_recorder_get_next_program_info(livetv->recorder,
78.563 - BROWSE_DIRECTION_UP);
78.564 - gmyth_program_info_print(prog_info);
78.565 - if (prog_info != NULL)
78.566 - break;
78.567 - }
78.568 -
78.569 - }
78.570 -
78.571 - /*
78.572 - * if - Program Info
78.573 - */
78.574 - /*
78.575 - * prints program info data text
78.576 - */
78.577 - gmyth_debug("New ProgramInfo...\n");
78.578 - gmyth_program_info_print(prog_info);
78.579 -
78.580 - /*
78.581 - * check if the program chain could be obtained from the MythTV
78.582 - * protocol message
78.583 - */
78.584 - if (prog_info != NULL) {
78.585 - gmyth_backend_info_set_username(livetv->tvchain->backend_info,
78.586 - "mythtv");
78.587 - gmyth_backend_info_set_password(livetv->tvchain->backend_info,
78.588 - "mythtv");
78.589 - gmyth_backend_info_set_db_name(livetv->tvchain->backend_info,
78.590 - "mythconverg");
78.591 - GList *prog_list =
78.592 - gmyth_tvchain_get_program_info_from_channel(livetv->tvchain,
78.593 - channel);
78.594 - GMythProgramInfo *ch_prog = NULL;
78.595 -
78.596 - if (prog_list != NULL && g_list_length(prog_list) > 0) {
78.597 - ch_prog = (GMythProgramInfo *) g_list_nth_data(prog_list, 0);
78.598 - gmyth_debug
78.599 - ("Channel program info (from a list with size = %d)!",
78.600 - g_list_length(prog_list));
78.601 - gmyth_program_info_print(ch_prog);
78.602 - }
78.603 -
78.604 - gmyth_debug("Program Info: %s\n",
78.605 - gmyth_program_info_to_string(prog_info));
78.606 - livetv->proginfo = prog_info;
78.607 - /*
78.608 - * testing change channel
78.609 - */
78.610 - // gmyth_recorder_spawntv_no_tvchain( livetv->recorder );
78.611 - } else {
78.612 -
78.613 - /*
78.614 - * check for the program info in the TV program chain could be
78.615 - * obtained from the MythTV MySQL database
78.616 - */
78.617 -
78.618 - /*
78.619 - * Reload all TV chain from Mysql database.
78.620 - */
78.621 - gmyth_tvchain_reload_all(livetv->tvchain);
78.622 -
78.623 - if (livetv->tvchain == NULL) {
78.624 - res = FALSE;
78.625 - goto error;
78.626 - }
78.627 -
78.628 - /*
78.629 - * Get program info from database using chanid and starttime
78.630 - */
78.631 - livetv->proginfo =
78.632 - gmyth_tvchain_get_program_at(livetv->tvchain,
78.633 - tvchain_curr_index++);
78.634 - if (livetv->proginfo == NULL) {
78.635 - gmyth_debug("LiveTV not successfully started.\n");
78.636 - res = FALSE;
78.637 - goto error;
78.638 - } else {
78.639 - res = TRUE;
78.640 - gmyth_debug
78.641 - ("GMythLiveTV: All requests to backend to start TV were OK. [%s]\n",
78.642 - livetv->proginfo->pathname->str);
78.643 - }
78.644 -
78.645 - }
78.646 -
78.647 - livetv->uri =
78.648 - (GMythURI *) gmyth_backend_info_get_uri(livetv->backend_info);
78.649 -
78.650 - g_mutex_unlock(livetv->mutex);
78.651 -
78.652 - if (!gmyth_livetv_monitor_handler_start(livetv)) {
78.653 - res = FALSE;
78.654 - gmyth_debug("LiveTV MONITOR handler error on setup!");
78.655 - goto error;
78.656 - }
78.657 -
78.658 - livetv->setup_done = TRUE;
78.659 -
78.660 - return res;
78.661 -
78.662 - error:
78.663 - g_mutex_unlock(livetv->mutex);
78.664 -
78.665 - gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
78.666 -
78.667 - res = FALSE;
78.668 -
78.669 - if (livetv->local_hostname != NULL) {
78.670 - g_string_free(livetv->local_hostname, TRUE);
78.671 - livetv->local_hostname = NULL;
78.672 - }
78.673 -
78.674 - gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
78.675 -
78.676 - if (livetv->recorder != NULL) {
78.677 - g_object_unref(livetv->recorder);
78.678 - livetv->recorder = NULL;
78.679 - }
78.680 -
78.681 - gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
78.682 -
78.683 - if (livetv->tvchain != NULL) {
78.684 - g_object_unref(livetv->tvchain);
78.685 - livetv->tvchain = NULL;
78.686 - }
78.687 -
78.688 - gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
78.689 -
78.690 - if (livetv->proginfo != NULL) {
78.691 - g_object_unref(livetv->proginfo);
78.692 - livetv->proginfo = NULL;
78.693 - }
78.694 -
78.695 - gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
78.696 -
78.697 - if (livetv->monitor != NULL) {
78.698 - g_object_unref(livetv->monitor);
78.699 - livetv->monitor = NULL;
78.700 - }
78.701 -
78.702 -
78.703 - gmyth_debug("[%s] ERROR running LiveTV setup.\n", __FUNCTION__);
78.704 -
78.705 - return res;
78.706 -
78.707 -}
78.708 -
78.709 -/**
78.710 - * Setup the GMythLiveTV session, sends SPAWN_LIVETV message,
78.711 - * sets the channel name, and gets the first program info about the
78.712 - * actual recording
78.713 - *
78.714 - * @param live_tv the GMythLiveTV instance
78.715 - * @param channel the channel name, in numerical format
78.716 - * @param backend_info the GMythBackendInfo describing the remote server
78.717 - *
78.718 - * @return <code>true</code> if the LiveTV's recorder instance configuration
78.719 - * had been concluded succcesfully
78.720 - */
78.721 -static gboolean
78.722 -gmyth_livetv_setup_recorder(GMythLiveTV * livetv, gint channel)
78.723 -{
78.724 - return gmyth_livetv_setup_recorder_channel_name(livetv,
78.725 - (channel !=
78.726 - -1) ?
78.727 - g_strdup_printf("%d",
78.728 - channel)
78.729 - : NULL);
78.730 -}
78.731 -
78.732 -/**
78.733 - * Setup the GMythLiveTV session, sends SPAWN_LIVETV message,
78.734 - * sets the channel name (numerical format), and gets the first program info about the
78.735 - * actual recording
78.736 - *
78.737 - * @param live_tv the GMythLiveTV instance
78.738 - * @param channel the channel name, in numerical format
78.739 - * @param backend_info the GMythBackendInfo describing the remote server
78.740 - *
78.741 - * @return <code>true</code> if the LiveTV's recorder instance configuration
78.742 - * had been concluded succcesfully
78.743 - */
78.744 -gboolean
78.745 -gmyth_livetv_channel_setup(GMythLiveTV * livetv, gint channel)
78.746 -{
78.747 - return gmyth_livetv_setup_recorder(livetv, channel);
78.748 -}
78.749 -
78.750 -/**
78.751 - * Setup the GMythLiveTV session, sends SPAWN_LIVETV message,
78.752 - * sets the channel name (string format), and gets the first program info about the
78.753 - * actual recording
78.754 - *
78.755 - * @param live_tv the GMythLiveTV instance
78.756 - * @param channel the channel name, in numerical format
78.757 - * @param backend_info the GMythBackendInfo describing the remote server
78.758 - *
78.759 - * @return <code>true</code> if the LiveTV's recorder instance configuration
78.760 - * had been concluded succcesfully
78.761 - */
78.762 -gboolean
78.763 -gmyth_livetv_channel_name_setup(GMythLiveTV * livetv, gchar * channel)
78.764 -{
78.765 - return gmyth_livetv_setup_recorder_channel_name(livetv, channel);
78.766 -}
78.767 -
78.768 -/**
78.769 - * Setup the GMythLiveTV session, sends SPAWN_LIVETV message,
78.770 - * and gets the first program info about the actual recording
78.771 - * (doesn't changes the channel).
78.772 - *
78.773 - * @param live_tv the GMythLiveTV instance
78.774 - * @param backend_info the GMythBackendInfo describing the remote server
78.775 - *
78.776 - * @return <code>true</code> if the LiveTV's recorder instance configuration
78.777 - * had been concluded succcesfully
78.778 - */
78.779 -gboolean
78.780 -gmyth_livetv_setup(GMythLiveTV * livetv)
78.781 -{
78.782 - return gmyth_livetv_setup_recorder(livetv, -1);
78.783 -}
78.784 -
78.785 -/**
78.786 - * Gets the next program info from this GMythLiveTV session.
78.787 - *
78.788 - * @param live_tv the GMythLiveTV instance
78.789 - *
78.790 - * @return <code>true</code> if the next program info could be got
78.791 - */
78.792 -gboolean
78.793 -gmyth_livetv_next_program_chain(GMythLiveTV * livetv)
78.794 -{
78.795 - gboolean res = TRUE;
78.796 - GMythProgramInfo *prog_info = NULL;
78.797 -
78.798 - if (!livetv->setup_done) {
78.799 - gmyth_debug("Call the setup function first!");
78.800 - goto error;
78.801 - }
78.802 -
78.803 - gmyth_debug("Current ProgramInfo...\n");
78.804 - prog_info = gmyth_recorder_get_current_program_info(livetv->recorder);
78.805 -
78.806 - if (prog_info != NULL) {
78.807 - livetv->proginfo = prog_info;
78.808 - } else {
78.809 - gmyth_debug
78.810 - ("ProgramInfo equals to NULL!!! Getting the next program info...");
78.811 - prog_info =
78.812 - gmyth_recorder_get_next_program_info(livetv->recorder,
78.813 - BROWSE_DIRECTION_RIGHT);
78.814 - livetv->proginfo = prog_info;
78.815 - }
78.816 - /*
78.817 - * prints program info data text
78.818 - */
78.819 - gmyth_program_info_print(prog_info);
78.820 -
78.821 - if (prog_info != NULL) {
78.822 - res = TRUE;
78.823 - livetv->proginfo = prog_info;
78.824 - gmyth_debug
78.825 - ("GMythLiveTV: All requests to backend to start TV were OK, program info changed.");
78.826 - } else {
78.827 - gmyth_debug
78.828 - ("[%s] LiveTV not successfully started on the next program chain.\n",
78.829 - __FUNCTION__);
78.830 - goto error;
78.831 - }
78.832 -
78.833 - livetv->setup_done = TRUE;
78.834 -
78.835 - return res;
78.836 -
78.837 - error:
78.838 - gmyth_debug("ERROR running LiveTV setup.\n");
78.839 -
78.840 - res = FALSE;
78.841 -
78.842 - g_string_free(livetv->local_hostname, TRUE);
78.843 -
78.844 - if (livetv->recorder != NULL) {
78.845 - g_object_unref(livetv->recorder);
78.846 - livetv->recorder = NULL;
78.847 - }
78.848 -
78.849 - if (livetv->tvchain != NULL) {
78.850 - g_object_unref(livetv->tvchain);
78.851 - livetv->tvchain = NULL;
78.852 - }
78.853 -
78.854 - if (livetv->proginfo != NULL) {
78.855 - g_object_unref(livetv->proginfo);
78.856 - livetv->proginfo = NULL;
78.857 - }
78.858 -
78.859 - return res;
78.860 -}
78.861 -
78.862 -/**
78.863 - * Creates a File Transfer session, using all configuration information
78.864 - * got from the actual program info.
78.865 - *
78.866 - * @param live_tv the GMythLiveTV instance
78.867 - *
78.868 - * @return the actual GMythFileTransfer instance, generated using the
78.869 - * data got from the actual program info.
78.870 - */
78.871 -GMythFile*
78.872 -gmyth_livetv_create_file_transfer(GMythLiveTV * livetv)
78.873 -{
78.874 - // GMythURI* uri = NULL;
78.875 -
78.876 - if (NULL == livetv)
78.877 - return NULL;
78.878 -
78.879 - if (!livetv->setup_done) {
78.880 - gmyth_debug
78.881 - ("Error: You must do the LiveTV setup, just before generating the FileTransfer from LiveTV source!");
78.882 - return NULL;
78.883 - }
78.884 -
78.885 - if (livetv->proginfo != NULL)
78.886 - gmyth_debug("URI path (from program info) = %s.\n",
78.887 - livetv->proginfo->pathname->str);
78.888 - else
78.889 - gmyth_debug("URI path (from URI) = %s.\n", livetv->uri->uri->str);
78.890 -
78.891 - g_mutex_lock(livetv->mutex);
78.892 -
78.893 - if (livetv->file != NULL) {
78.894 - /*
78.895 - * gmyth_file_transfer_close( livetv->file );
78.896 - */
78.897 - g_object_unref(livetv->file);
78.898 - livetv->file = NULL;
78.899 - }
78.900 -
78.901 - if (livetv->uri != NULL) {
78.902 - gmyth_debug
78.903 - ("URI is not NULL, creating from the ProgramInfo pathname... (%s)",
78.904 - livetv->proginfo->pathname->str);
78.905 - livetv->uri->path = g_string_erase(livetv->uri->path, 0, -1);
78.906 - livetv->uri->path =
78.907 - g_string_new(g_strrstr(livetv->proginfo->pathname->str, "/"));
78.908 - } else {
78.909 - gmyth_debug
78.910 - ("URI is NULL, creating from the ProgramInfo pathname... (%s)",
78.911 - livetv->proginfo->pathname->str);
78.912 - livetv->uri =
78.913 - gmyth_uri_new_with_value(livetv->proginfo->pathname->str);
78.914 - }
78.915 -
78.916 - if (NULL == livetv->uri) {
78.917 - gmyth_debug("Couldn't parse the URI to start LiveTV! [ uri = %s ]",
78.918 - livetv->proginfo->pathname->str);
78.919 - goto done;
78.920 - }
78.921 -
78.922 - if (gmyth_uri_is_local_file(livetv->uri))
78.923 - livetv->file =
78.924 - GMYTH_FILE(gmyth_file_local_new(livetv->backend_info));
78.925 - else {
78.926 - livetv->file =
78.927 - GMYTH_FILE(gmyth_file_transfer_new(livetv->backend_info));
78.928 - /*
78.929 - * gmyth_file_transfer_settimeout(
78.930 - * GMYTH_FILE_TRANSFER(livetv->file), TRUE );
78.931 - */
78.932 - }
78.933 -
78.934 - if (NULL == livetv->file) {
78.935 - gmyth_debug
78.936 - ("Error: couldn't create the FileTransfer from LiveTV source!");
78.937 - goto done;
78.938 - }
78.939 -
78.940 - g_object_ref(livetv->file);
78.941 -
78.942 -done:
78.943 - g_mutex_unlock(livetv->mutex);
78.944 - return livetv->file;
78.945 -}
78.946 -
78.947 -/**
78.948 - * Stops this LiveTV session.
78.949 - *
78.950 - * @param live_tv the GMythLiveTV instance
78.951 - */
78.952 -void
78.953 -gmyth_livetv_stop_playing(GMythLiveTV * livetv)
78.954 -{
78.955 - gmyth_debug("Stopping the LiveTV...\n");
78.956 -
78.957 - if (livetv->is_livetv) {
78.958 - if (!gmyth_recorder_stop_livetv(livetv->recorder)) {
78.959 - gmyth_debug("[%s] Error while stoping remote encoder",
78.960 - __FUNCTION__);
78.961 - }
78.962 -
78.963 - if (!gmyth_recorder_finish_recording(livetv->recorder)) {
78.964 - gmyth_debug
78.965 - ("[%s] Error while finishing recording on remote encoder",
78.966 - __FUNCTION__);
78.967 - }
78.968 - }
78.969 -}
78.970 -
78.971 -gboolean
78.972 -gmyth_livetv_is_playing(GMythLiveTV * livetv)
78.973 -{
78.974 - return TRUE;
78.975 -}
78.976 -
78.977 -void
78.978 -gmyth_livetv_start_playing(GMythLiveTV * livetv)
78.979 -{
78.980 -
78.981 - // TODO
78.982 -
78.983 -}
79.1 --- a/gmyth/src/gmyth_livetv.h Mon Feb 25 17:45:36 2008 +0000
79.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
79.3 @@ -1,103 +0,0 @@
79.4 -/**
79.5 - * GMyth Library
79.6 - *
79.7 - * @file gmyth/gmyth_livetv.h
79.8 - *
79.9 - * @brief <p> GMythLiveTV starts a remote TV session with the MythTV backend.
79.10 - *
79.11 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
79.12 - * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
79.13 - *
79.14 -*
79.15 -* This program is free software; you can redistribute it and/or modify
79.16 -* it under the terms of the GNU Lesser General Public License as published by
79.17 -* the Free Software Foundation; either version 2 of the License, or
79.18 -* (at your option) any later version.
79.19 -*
79.20 -* This program is distributed in the hope that it will be useful,
79.21 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
79.22 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
79.23 - * GNU General Public License for more details.
79.24 - *
79.25 - * You should have received a copy of the GNU Lesser General Public License
79.26 - * along with this program; if not, write to the Free Software
79.27 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
79.28 - */
79.29 -
79.30 -#ifndef GMYTH_LIVETV_H_
79.31 -#define GMYTH_LIVETV_H_
79.32 -
79.33 -#include <glib.h>
79.34 -#include <glib-object.h>
79.35 -
79.36 -#include "gmyth_recorder.h"
79.37 -#include "gmyth_tvchain.h"
79.38 -#include "gmyth_monitor_handler.h"
79.39 -#include "gmyth_file.h"
79.40 -#include "gmyth_programinfo.h"
79.41 -#include "gmyth_backendinfo.h"
79.42 -
79.43 -G_BEGIN_DECLS
79.44 -#define GMYTH_LIVETV_TYPE (gmyth_livetv_get_type ())
79.45 -#define GMYTH_LIVETV(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_LIVETV_TYPE, GMythLiveTV))
79.46 -#define GMYTH_LIVETV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_LIVETV_TYPE, GMythLiveTVClass))
79.47 -#define IS_GMYTH_LIVETV(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_LIVETV_TYPE))
79.48 -#define IS_GMYTH_LIVETV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_LIVETV_TYPE))
79.49 -#define GMYTH_LIVETV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_LIVETV_TYPE, GMythLiveTVClass))
79.50 -typedef struct _GMythLiveTV GMythLiveTV;
79.51 -typedef struct _GMythLiveTVClass GMythLiveTVClass;
79.52 -
79.53 -struct _GMythLiveTVClass {
79.54 - GObjectClass parent_class;
79.55 -
79.56 - /*
79.57 - * callbacks
79.58 - */
79.59 -};
79.60 -
79.61 -struct _GMythLiveTV {
79.62 - GObject parent;
79.63 -
79.64 - GMythSocket *socket;
79.65 -
79.66 - GString *local_hostname;
79.67 -
79.68 - GMythBackendInfo *backend_info;
79.69 -
79.70 - GMythRecorder *recorder;
79.71 - GMythTVChain *tvchain;
79.72 - GMythProgramInfo *proginfo;
79.73 -
79.74 - GMythFile *file;
79.75 -
79.76 - GMythMonitorHandler *monitor;
79.77 - GMythURI *uri;
79.78 -
79.79 - gboolean is_livetv;
79.80 - gboolean setup_done;
79.81 -
79.82 - GMutex *mutex;
79.83 - gboolean disposed;
79.84 -};
79.85 -
79.86 -GType gmyth_livetv_get_type(void);
79.87 -
79.88 -GMythLiveTV *gmyth_livetv_new(GMythBackendInfo * backend_info);
79.89 -
79.90 -void gmyth_livetv_start_playing(GMythLiveTV * livetv);
79.91 -void gmyth_livetv_stop_playing(GMythLiveTV * livetv);
79.92 -
79.93 -gboolean gmyth_livetv_setup(GMythLiveTV * livetv);
79.94 -gboolean gmyth_livetv_channel_setup(GMythLiveTV * livetv,
79.95 - gint channel);
79.96 -gboolean gmyth_livetv_channel_name_setup(GMythLiveTV * livetv,
79.97 - gchar * channel);
79.98 -gboolean gmyth_livetv_next_program_chain(GMythLiveTV * livetv);
79.99 -
79.100 -GMythFile *gmyth_livetv_create_file_transfer(GMythLiveTV * livetv);
79.101 -
79.102 -gboolean gmyth_livetv_monitor_handler_start(GMythLiveTV * livetv);
79.103 -void gmyth_livetv_monitor_handler_stop(GMythLiveTV * livetv);
79.104 -
79.105 -G_END_DECLS
79.106 -#endif /* GMYTH_LIVETV_H_ */
80.1 --- a/gmyth/src/gmyth_marshal.list Mon Feb 25 17:45:36 2008 +0000
80.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
80.3 @@ -1,2 +0,0 @@
80.4 -VOID:INT,STRING
80.5 -VOID:INT,POINTER
81.1 --- a/gmyth/src/gmyth_monitor_handler.c Mon Feb 25 17:45:36 2008 +0000
81.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
81.3 @@ -1,593 +0,0 @@
81.4 -/**
81.5 - * GMyth Library
81.6 - *
81.7 - * @file gmyth/gmyth_monitor_handler.c
81.8 - *
81.9 - * @brief <p> GMythMonitorHandler deals with the streaming media events remote/local
81.10 - * that are sent to the MythTV frontend.
81.11 - *
81.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
81.13 - * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
81.14 - *
81.15 - *
81.16 - * This program is free software; you can redistribute it and/or modify
81.17 - * it under the terms of the GNU Lesser General Public License as published by
81.18 - * the Free Software Foundation; either version 2 of the License, or
81.19 - * (at your option) any later version.
81.20 - *
81.21 - * This program is distributed in the hope that it will be useful,
81.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
81.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81.24 - * GNU General Public License for more details.
81.25 - *
81.26 - * You should have received a copy of the GNU Lesser General Public License
81.27 - * along with this program; if not, write to the Free Software
81.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
81.29 - *
81.30 - * GStreamer MythTV plug-in properties:
81.31 - * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv]
81.32 - * - path (qurl - remote file to be opened)
81.33 - * - port number *
81.34 - */
81.35 -
81.36 -#ifdef HAVE_CONFIG_H
81.37 -#include "config.h"
81.38 -#endif
81.39 -
81.40 -#include <unistd.h>
81.41 -#include <glib.h>
81.42 -#include <arpa/inet.h>
81.43 -#include <sys/types.h>
81.44 -#include <sys/socket.h>
81.45 -#include <netdb.h>
81.46 -#include <errno.h>
81.47 -#include <stdlib.h>
81.48 -#include <assert.h>
81.49 -
81.50 -#include "gmyth_marshal.h"
81.51 -
81.52 -#include "gmyth_monitor_handler.h"
81.53 -#include "gmyth_debug.h"
81.54 -
81.55 -#define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER "
81.56 -
81.57 -#define GMYTHTV_VERSION 30
81.58 -
81.59 -#define GMYTHTV_TRANSFER_MAX_WAITS 700
81.60 -
81.61 -#define GMYTHTV_BUFFER_SIZE 8*1024
81.62 -
81.63 -#ifdef GMYTHTV_ENABLE_DEBUG
81.64 -#define GMYTHTV_ENABLE_DEBUG 1
81.65 -#else
81.66 -#undef GMYTHTV_ENABLE_DEBUG
81.67 -#endif
81.68 -
81.69 -/*
81.70 - * this NDEBUG is to maintain compatibility with GMyth library
81.71 - */
81.72 -#ifndef NDEBUG
81.73 -#define GMYTHTV_ENABLE_DEBUG 1
81.74 -#endif
81.75 -
81.76 -static gboolean gmyth_monitor_handler_listener (GIOChannel *io_channel,
81.77 - GIOCondition condition,
81.78 - gpointer data);
81.79 -
81.80 -static void gmyth_monitor_handler_default_listener(GMythMonitorHandler
81.81 - * monitor,
81.82 - gint msg_code,
81.83 - gchar * message);
81.84 -
81.85 -static void gmyth_monitor_handler_class_init(GMythMonitorHandlerClass *
81.86 - klass);
81.87 -static void gmyth_monitor_handler_init(GMythMonitorHandler * object);
81.88 -
81.89 -static void gmyth_monitor_handler_dispose(GObject * object);
81.90 -static void gmyth_monitor_handler_finalize(GObject * object);
81.91 -
81.92 -static gboolean gmyth_connect_to_backend_monitor(GMythMonitorHandler *
81.93 - monitor);
81.94 -
81.95 -static gboolean gmyth_monitor_handler_setup(GMythMonitorHandler * monitor,
81.96 - GIOChannel * channel);
81.97 -
81.98 -void gmyth_monitor_handler_close(GMythMonitorHandler * monitor);
81.99 -
81.100 -G_DEFINE_TYPE(GMythMonitorHandler, gmyth_monitor_handler, G_TYPE_OBJECT);
81.101 -
81.102 -static void
81.103 -gmyth_monitor_handler_class_init(GMythMonitorHandlerClass * klass)
81.104 -{
81.105 - GObjectClass *gobject_class;
81.106 - GMythMonitorHandlerClass *gmonitor_class;
81.107 -
81.108 - gobject_class = (GObjectClass *) klass;
81.109 - gmonitor_class = (GMythMonitorHandlerClass *) gobject_class;
81.110 -
81.111 - gobject_class->dispose = gmyth_monitor_handler_dispose;
81.112 - gobject_class->finalize = gmyth_monitor_handler_finalize;
81.113 -
81.114 - gmonitor_class->backend_events_handler_signal_id =
81.115 - g_signal_new("backend-events-handler",
81.116 - G_TYPE_FROM_CLASS(gmonitor_class),
81.117 - G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE |
81.118 - G_SIGNAL_NO_HOOKS, 0, NULL, NULL,
81.119 - gmyth_marshal_VOID__INT_STRING, G_TYPE_NONE, 2,
81.120 - G_TYPE_INT, G_TYPE_STRING);
81.121 -
81.122 - gmonitor_class->backend_events_handler =
81.123 - gmyth_monitor_handler_default_listener;
81.124 -
81.125 -}
81.126 -
81.127 -static void
81.128 -gmyth_monitor_handler_init(GMythMonitorHandler * monitor)
81.129 -{
81.130 - g_return_if_fail(monitor != NULL);
81.131 -
81.132 - monitor->event_sock = NULL;
81.133 - monitor->hostname = NULL;
81.134 - monitor->port = 0;
81.135 - monitor->actual_index = 0;
81.136 - monitor->allow_msgs_listener = FALSE;
81.137 - /*
81.138 - * it is used for signalizing the event socket consumer thread
81.139 - */
81.140 - monitor->mutex = g_mutex_new();
81.141 -}
81.142 -
81.143 -static void
81.144 -gmyth_monitor_handler_dispose(GObject * object)
81.145 -{
81.146 - GMythMonitorHandler *monitor = GMYTH_MONITOR_HANDLER(object);
81.147 -
81.148 - gmyth_monitor_handler_close(monitor);
81.149 -
81.150 - monitor->allow_msgs_listener = FALSE;
81.151 -
81.152 - if (monitor->io_source != 0) {
81.153 - g_source_remove (monitor->io_source);
81.154 - monitor->io_source = 0;
81.155 - }
81.156 -
81.157 - /*
81.158 - * mutex to control access to the event socket consumer thread
81.159 - */
81.160 - if (monitor->mutex != NULL) {
81.161 - // g_mutex_unlock( monitor->mutex );
81.162 - g_mutex_free(monitor->mutex);
81.163 - monitor->mutex = NULL;
81.164 - }
81.165 -
81.166 - if (monitor->event_sock != NULL) {
81.167 - g_object_unref(monitor->event_sock);
81.168 - monitor->event_sock = NULL;
81.169 - }
81.170 -
81.171 - if (monitor->hostname != NULL) {
81.172 - g_free(monitor->hostname);
81.173 - monitor->hostname = NULL;
81.174 - }
81.175 -
81.176 -
81.177 - if (monitor->backend_msgs != NULL) {
81.178 - g_hash_table_destroy(monitor->backend_msgs);
81.179 - monitor->backend_msgs = NULL;
81.180 - }
81.181 -
81.182 - /*
81.183 - * if ( io_watcher_cond != NULL ) { g_cond_free( io_watcher_cond );
81.184 - * io_watcher_cond = NULL; }
81.185 - */
81.186 -
81.187 -
81.188 - G_OBJECT_CLASS(gmyth_monitor_handler_parent_class)->dispose(object);
81.189 -}
81.190 -
81.191 -static void
81.192 -gmyth_monitor_handler_finalize(GObject * object)
81.193 -{
81.194 - g_signal_handlers_destroy(object);
81.195 -
81.196 - G_OBJECT_CLASS(gmyth_monitor_handler_parent_class)->finalize(object);
81.197 -}
81.198 -
81.199 -/**
81.200 - * Creates a new instance of GMyth Monitor Handler.
81.201 - *
81.202 - * @return a new instance of the Monitor Handler.
81.203 - */
81.204 -GMythMonitorHandler *
81.205 -gmyth_monitor_handler_new(void)
81.206 -{
81.207 - GMythMonitorHandler *monitor =
81.208 - GMYTH_MONITOR_HANDLER(g_object_new
81.209 - (GMYTH_MONITOR_HANDLER_TYPE, FALSE));
81.210 -
81.211 - return monitor;
81.212 -}
81.213 -
81.214 -/**
81.215 - * Acquire the mutex to have access to the IO Watcher listener.
81.216 - *
81.217 - * @param monitor The GMythMonitorHandler instance.
81.218 - * @param do_wait Tells the IO Watcher to wait on the GCond. (obsolete)
81.219 - *
81.220 - * @return <code>true</code>, if the access to IO Watcher was acquired.
81.221 - */
81.222 -static gboolean
81.223 -myth_control_acquire_context(GMythMonitorHandler * monitor,
81.224 - gboolean do_wait)
81.225 -{
81.226 -
81.227 - gboolean ret = TRUE;
81.228 -
81.229 - g_mutex_lock(monitor->mutex);
81.230 -
81.231 - return ret;
81.232 -
81.233 -}
81.234 -
81.235 -/**
81.236 - * Release the mutex to have access to the IO Watcher listener.
81.237 - *
81.238 - * @param monitor The GMythMonitorHandler instance.
81.239 - *
81.240 - * @return <code>true</code>, if the access to IO Watcher was released.
81.241 - */
81.242 -static gboolean
81.243 -myth_control_release_context(GMythMonitorHandler * monitor)
81.244 -{
81.245 -
81.246 - gboolean ret = TRUE;
81.247 -
81.248 - g_mutex_unlock(monitor->mutex);
81.249 -
81.250 - return ret;
81.251 -}
81.252 -
81.253 -void
81.254 -gmyth_monitor_handler_close(GMythMonitorHandler * monitor)
81.255 -{
81.256 - monitor->allow_msgs_listener = FALSE;
81.257 -
81.258 -#if 0
81.259 - if (monitor->monitor_th != NULL) {
81.260 - g_thread_pool_free(monitor->monitor_th, TRUE, FALSE);
81.261 - // g_thread_exit( monitor->monitor_th );
81.262 - /*
81.263 - * if ( monitor->monitor_th != NULL ) g_object_unref(
81.264 - * monitor->monitor_th );
81.265 - */
81.266 - monitor->monitor_th = NULL;
81.267 - }
81.268 -
81.269 - if (monitor->event_sock != NULL) {
81.270 - gmyth_socket_close_connection(monitor->event_sock);
81.271 - }
81.272 -#endif
81.273 -
81.274 -}
81.275 -
81.276 -/**
81.277 - * Opens connection the the Monitor socket on MythTV backend server,
81.278 - * where all status messages are notified to the client.
81.279 - *
81.280 - * @param monitor The GMythMonitorHandler instance.
81.281 - * @param hostname The remote host name of the MythTV backend server.
81.282 - * @param port The remote port number of the MythTV backend server.
81.283 - *
81.284 - * @return <code>true</code>, if the connection was successfully opened.
81.285 - */
81.286 -gboolean
81.287 -gmyth_monitor_handler_open(GMythMonitorHandler * monitor,
81.288 - const gchar * hostname, gint port)
81.289 -{
81.290 - gboolean ret = TRUE;
81.291 -
81.292 - g_return_val_if_fail(hostname != NULL, FALSE);
81.293 -
81.294 - if (monitor->hostname != NULL) {
81.295 - g_free(monitor->hostname);
81.296 - monitor->hostname = NULL;
81.297 - }
81.298 -
81.299 - monitor->hostname = g_strdup(hostname);
81.300 - monitor->port = port;
81.301 -
81.302 - gmyth_debug("Monitor event socket --- hostname: %s, port %d\n",
81.303 - monitor->hostname, monitor->port);
81.304 -
81.305 - if (monitor->event_sock != NULL) {
81.306 - g_object_unref(monitor->event_sock);
81.307 - monitor->event_sock = NULL;
81.308 - }
81.309 -
81.310 - /*
81.311 - * configure the event socket
81.312 - */
81.313 - if (!gmyth_connect_to_backend_monitor(monitor)) {
81.314 - gmyth_debug("Connection to backend failed (Event Socket)!");
81.315 - ret = FALSE;
81.316 - } else {
81.317 - gmyth_debug ("Remote monitor event socket had been succesfully create");
81.318 - }
81.319 -
81.320 - return ret;
81.321 -}
81.322 -
81.323 -/**
81.324 - * Reads the data got from the connection to the Monitor socket,
81.325 - * and looks for some important status messages.
81.326 - *
81.327 - * @param monitor The GMythMonitorHandler instance.
81.328 - * @param strlist The GMythStringList instance got from the Monitor remote socket.
81.329 - * @param back_msg_action A string pointer to the status message detailed description.
81.330 - *
81.331 - * @return The backend status message code ID.
81.332 - */
81.333 -static gint
81.334 -gmyth_monitor_handler_is_backend_message(GMythMonitorHandler * monitor,
81.335 - GMythStringList * strlist,
81.336 - gchar ** back_msg_action)
81.337 -{
81.338 - gint msg_type = GMYTH_BACKEND_NO_MESSAGE;
81.339 - GString *back_msg = NULL;
81.340 -
81.341 - if (gmyth_string_list_length(strlist) > 0) {
81.342 -
81.343 - back_msg = gmyth_string_list_get_string(strlist, 0);
81.344 - if (back_msg != NULL && back_msg->str != NULL &&
81.345 - strstr(back_msg->str, "BACKEND") != NULL) {
81.346 - gmyth_debug("MONITOR HANDLER - Received backend message = %s",
81.347 - back_msg->str);
81.348 - *back_msg_action =
81.349 - gmyth_string_list_get_char_array(strlist, 1);
81.350 -
81.351 - if (back_msg_action != NULL) {
81.352 -
81.353 - if (g_strstr_len
81.354 - (*back_msg_action, strlen(*back_msg_action),
81.355 - "LIVETV_CHAIN")
81.356 - || g_strstr_len(*back_msg_action,
81.357 - strlen(*back_msg_action),
81.358 - "RECORDING_LIST_CHANGE")
81.359 - || g_strstr_len(*back_msg_action,
81.360 - strlen(*back_msg_action),
81.361 - "SCHEDULE_CHANGE")
81.362 - || g_strstr_len(*back_msg_action,
81.363 - strlen(*back_msg_action),
81.364 - "LIVETV_WATCH")) {
81.365 - gmyth_debug
81.366 - ("MONITOR: message type == GMYTH_BACKEND_PROGRAM_INFO_CHANGED, msg = %s",
81.367 - *back_msg_action);
81.368 - msg_type = GMYTH_BACKEND_PROGRAM_INFO_CHANGED;
81.369 - } else if (g_strstr_len
81.370 - (*back_msg_action, strlen(*back_msg_action),
81.371 - "DONE_RECORDING")) {
81.372 - gmyth_debug
81.373 - ("MONITOR: message type == GMYTH_BACKEND_DONE_RECORDING, msg = %s",
81.374 - *back_msg_action);
81.375 - msg_type = GMYTH_BACKEND_DONE_RECORDING;
81.376 - } else if (g_strstr_len
81.377 - (*back_msg_action, strlen(*back_msg_action),
81.378 - "QUIT")) {
81.379 - gmyth_debug
81.380 - ("MONITOR: message type == GMYTH_BACKEND_STOP_LIVETV, msg = %s",
81.381 - *back_msg_action);
81.382 - msg_type = GMYTH_BACKEND_STOP_LIVETV;
81.383 - }
81.384 -
81.385 - /*
81.386 - * g_hash_table_insert ( monitor->backend_msgs,
81.387 - * &(monitor->actual_index), *back_msg_action );
81.388 - */
81.389 -
81.390 - }
81.391 - /*
81.392 - * if
81.393 - */
81.394 - }
81.395 - /*
81.396 - * if
81.397 - */
81.398 - if (back_msg != NULL) {
81.399 - g_string_free(back_msg, TRUE);
81.400 - back_msg = NULL;
81.401 - }
81.402 -
81.403 - } /* if - Does Monitor got any message from
81.404 - * * * backend? */
81.405 - else {
81.406 - *back_msg_action = g_strdup("");
81.407 - }
81.408 -
81.409 - return msg_type;
81.410 -
81.411 -}
81.412 -
81.413 -static void
81.414 -gmyth_monitor_handler_default_listener(GMythMonitorHandler * monitor,
81.415 - gint msg_code, gchar * message)
81.416 -{
81.417 - // assert( message!= NULL );
81.418 - gmyth_debug("DEFAULT Signal handler ( msg = %s, code = %d )\n",
81.419 - message, msg_code);
81.420 -}
81.421 -
81.422 -static void
81.423 -gmyth_monitor_handler_print(GString * str, gpointer ptr)
81.424 -{
81.425 - gmyth_debug("Backend message event: %s --- ", str->str);
81.426 -}
81.427 -
81.428 -/**
81.429 - * Opens connection the the Monitor socket on MythTV backend server,
81.430 - * where all status messages are notified to the client.
81.431 - *
81.432 - * @param data Pointer to the GMythMonitorHandler.
81.433 - *
81.434 - * @return Pointer to a gboolean <code>true</code> value, if the data was
81.435 - * successfully read.
81.436 - */
81.437 -static gboolean
81.438 -gmyth_monitor_handler_listener (GIOChannel *io_channel,
81.439 - GIOCondition io_cond,
81.440 - gpointer data)
81.441 -{
81.442 - GMythMonitorHandler *monitor;
81.443 - guint recv = 0;
81.444 - gsize len = 0;
81.445 - GMythStringList *strlist = NULL;
81.446 - gint bytes_sent = 0;
81.447 -
81.448 - monitor = (GMythMonitorHandler *) data;
81.449 -
81.450 - gmyth_debug("Entering MONITOR handler listener...");
81.451 -
81.452 - myth_control_acquire_context(monitor, TRUE);
81.453 -
81.454 - if (((io_cond & G_IO_HUP) != 0) ||
81.455 - ((io_cond & G_IO_ERR) != 0)) {
81.456 - goto clean_up;
81.457 - }
81.458 -
81.459 -
81.460 - gmyth_debug("Listening on Monitor socket...!\n");
81.461 - strlist = gmyth_string_list_new();
81.462 -
81.463 - len = gmyth_socket_read_stringlist(monitor->event_sock, strlist);
81.464 - if ((len > 0) && strlist != NULL && gmyth_string_list_length(strlist) > 0) {
81.465 - gchar *back_msg_action;
81.466 - gint msg_type;
81.467 -
81.468 - bytes_sent = gmyth_string_list_get_int(strlist, 0);
81.469 - // on backend error
81.470 - gmyth_debug ("received data buffer from IO event channel... %d strings gone!\n", len);
81.471 - recv += len;
81.472 -
81.473 - /*
81.474 - * debug purpose: prints out all the string list
81.475 - * elements
81.476 - */
81.477 - g_list_foreach(strlist->glist,
81.478 - (GFunc) gmyth_monitor_handler_print,
81.479 - NULL);
81.480 -
81.481 - back_msg_action = g_new0(gchar, 1);
81.482 - msg_type = gmyth_monitor_handler_is_backend_message(monitor,
81.483 - strlist,
81.484 - &back_msg_action);
81.485 -
81.486 - if (msg_type != GMYTH_BACKEND_NO_MESSAGE) {
81.487 - g_signal_emit(monitor,
81.488 - GMYTH_MONITOR_HANDLER_GET_CLASS(monitor)->backend_events_handler_signal_id,
81.489 - 0, msg_type, back_msg_action);
81.490 - }
81.491 -
81.492 - if (back_msg_action != NULL)
81.493 - g_free(back_msg_action);
81.494 -
81.495 - g_object_unref(strlist);
81.496 - }
81.497 -
81.498 -clean_up:
81.499 - myth_control_release_context(monitor);
81.500 - return TRUE;
81.501 -}
81.502 -
81.503 -/**
81.504 - * Opens connection events' socket the the Monitor socket on
81.505 - * MythTV backend server.
81.506 - *
81.507 - * @param monitor The GMythMonitorHandler instance.
81.508 - *
81.509 - * @return <code>true</code>, if the socket was successfully opened.
81.510 - */
81.511 -static gboolean
81.512 -gmyth_connect_to_backend_monitor(GMythMonitorHandler * monitor)
81.513 -{
81.514 - gboolean ret = TRUE;
81.515 -
81.516 - monitor->event_sock = gmyth_socket_new();
81.517 -
81.518 - /*
81.519 - * Connects the socket, send Mythtv ANN Monitor and verify Mythtv
81.520 - * protocol version
81.521 - */
81.522 - if (!gmyth_socket_connect_to_backend_events(monitor->event_sock,
81.523 - monitor->hostname,
81.524 - monitor->port, FALSE)) {
81.525 - g_object_unref(monitor->event_sock);
81.526 - monitor->event_sock = NULL;
81.527 - ret = FALSE;
81.528 - }
81.529 -
81.530 - return ret;
81.531 -}
81.532 -
81.533 -/**
81.534 - * Opens connection the the Monitor socket on MythTV backend server,
81.535 - * where all status messages are notified to the client.
81.536 - *
81.537 - * @param monitor The GMythMonitorHandler instance.
81.538 - * @param channel The GIOChannel instance to the Monitor socket.
81.539 - *
81.540 - * @return Pointer to the boolean value, and it is <code>true</code> only if the
81.541 - * GMythMonitorHandler could be configured.
81.542 - */
81.543 -static gboolean
81.544 -gmyth_monitor_handler_setup(GMythMonitorHandler * monitor,
81.545 - GIOChannel * channel)
81.546 -{
81.547 - gboolean ret = TRUE;
81.548 -
81.549 - if (channel != NULL) {
81.550 - monitor->allow_msgs_listener = TRUE;
81.551 - monitor->io_source = g_io_add_watch (channel, G_IO_IN | G_IO_ERR | G_IO_HUP,
81.552 - gmyth_monitor_handler_listener,
81.553 - monitor);
81.554 - } else {
81.555 - ret = FALSE;
81.556 - }
81.557 - return ret;
81.558 -}
81.559 -
81.560 -/**
81.561 - * Starts the MonitorHandler thread to the GIOWatcher.
81.562 - *
81.563 - * @param monitor The GMythMonitorHandler instance.
81.564 - *
81.565 - * @return <code>true</code>, if the MonitorHandler was started.
81.566 - */
81.567 -gboolean
81.568 -gmyth_monitor_handler_start(GMythMonitorHandler * monitor)
81.569 -{
81.570 - gboolean ret = TRUE;
81.571 -
81.572 - if (!(ret = g_thread_supported())) {
81.573 - gmyth_debug("Thread system wasn't initialized, starting NOW!!!");
81.574 - g_thread_init(NULL);
81.575 - }
81.576 -
81.577 - ret =
81.578 - gmyth_monitor_handler_setup(monitor,
81.579 - monitor->event_sock->sd_io_ch);
81.580 - if (ret) {
81.581 - gmyth_debug
81.582 - ("\n[%s]\tOK! Starting listener on the MONITOR event socket...[thread location = %p]\n",
81.583 - __FUNCTION__, g_thread_self());
81.584 - } else {
81.585 - gmyth_debug
81.586 - ("\n[%s]\tERROR! Coudn't start listener on the MONITOR event socket...[thread location = %p]\n",
81.587 - __FUNCTION__, g_thread_self());
81.588 - ret = FALSE;
81.589 - }
81.590 -
81.591 - gmyth_debug
81.592 - ("[%s] Watch listener function over the IO control channel? %s!!!\n",
81.593 - __FUNCTION__, (ret == TRUE ? "YES" : "NO"));
81.594 -
81.595 - return ret;
81.596 -}
82.1 --- a/gmyth/src/gmyth_monitor_handler.h Mon Feb 25 17:45:36 2008 +0000
82.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
82.3 @@ -1,122 +0,0 @@
82.4 -/**
82.5 - * GMyth Library
82.6 - *
82.7 - * @file gmyth/gmyth_monitor_handler.h
82.8 - *
82.9 - * @brief <p> GMythMonitorHandler deals with the streaming media events remote/local
82.10 - * that are sent to the MythTV frontend.
82.11 - *
82.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
82.13 - * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
82.14 - *
82.15 - *
82.16 - * This program is free software; you can redistribute it and/or modify
82.17 - * it under the terms of the GNU Lesser General Public License as published by
82.18 - * the Free Software Foundation; either version 2 of the License, or
82.19 - * (at your option) any later version.
82.20 - *
82.21 - * This program is distributed in the hope that it will be useful,
82.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
82.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
82.24 - * GNU General Public License for more details.
82.25 - *
82.26 - * You should have received a copy of the GNU Lesser General Public License
82.27 - * along with this program; if not, write to the Free Software
82.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
82.29 - */
82.30 -
82.31 -#ifndef __GMYTH_MONITOR_HANDLER_H__
82.32 -#define __GMYTH_MONITOR_HANDLER_H__
82.33 -
82.34 -#include <glib-object.h>
82.35 -#include <glib.h>
82.36 -#include <stdio.h>
82.37 -#include <stdlib.h>
82.38 -#include <string.h>
82.39 -
82.40 -#include <netdb.h>
82.41 -#include <sys/socket.h>
82.42 -#include <unistd.h>
82.43 -
82.44 -#include "gmyth_socket.h"
82.45 -#include "gmyth_uri.h"
82.46 -
82.47 -G_BEGIN_DECLS
82.48 -#define GMYTH_MONITOR_HANDLER_TYPE (gmyth_monitor_handler_get_type ())
82.49 -#define GMYTH_MONITOR_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_MONITOR_HANDLER_TYPE, GMythMonitorHandler))
82.50 -#define GMYTH_MONITOR_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_MONITOR_HANDLER_TYPE, GMythMonitorHandlerClass))
82.51 -#define IS_GMYTH_MONITOR_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_MONITOR_HANDLER_TYPE))
82.52 -#define IS_GMYTH_MONITOR_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_MONITOR_HANDLER_TYPE))
82.53 -#define GMYTH_MONITOR_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_MONITOR_HANDLER_TYPE, GMythMonitorHandlerClass))
82.54 -#define GMYTHTV_MONITOR_HANDLER_READ_ERROR -314
82.55 - enum {
82.56 - GMYTH_BACKEND_NO_MESSAGE = 0,
82.57 - GMYTH_BACKEND_PROGRAM_INFO_CHANGED,
82.58 - GMYTH_BACKEND_DONE_RECORDING,
82.59 - GMYTH_BACKEND_STOP_LIVETV
82.60 -};
82.61 -
82.62 -typedef struct _GMythMonitorHandler GMythMonitorHandler;
82.63 -typedef struct _GMythMonitorHandlerClass GMythMonitorHandlerClass;
82.64 -
82.65 -struct _GMythMonitorHandlerClass {
82.66 - GObjectClass parent_class;
82.67 -
82.68 - /*
82.69 - * callbacks
82.70 - */
82.71 - guint backend_events_handler_signal_id;
82.72 -
82.73 - /*
82.74 - * signal default handlers
82.75 - */
82.76 - void (*backend_events_handler) (GMythMonitorHandler *
82.77 - monitor, gint msg_code,
82.78 - gchar * message);
82.79 -};
82.80 -
82.81 -struct _GMythMonitorHandler {
82.82 - GObject parent;
82.83 -
82.84 - /*
82.85 - * MythTV version number
82.86 - */
82.87 - gint mythtv_version;
82.88 -
82.89 - /*
82.90 - * socket descriptors
82.91 - */
82.92 - GMythSocket *event_sock;
82.93 -
82.94 - //gpointer(*gmyth_monitor_handler_listener) (gpointer data);
82.95 -
82.96 - gchar *hostname;
82.97 - gint port;
82.98 -
82.99 - gint64 actual_index;
82.100 -
82.101 - gboolean allow_msgs_listener;
82.102 -
82.103 - /*
82.104 - * stores the messages coming from the backend
82.105 - */
82.106 - GHashTable *backend_msgs;
82.107 -
82.108 - GMutex *mutex;
82.109 - guint io_source;
82.110 -};
82.111 -
82.112 -GType gmyth_monitor_handler_get_type(void);
82.113 -
82.114 -GMythMonitorHandler *gmyth_monitor_handler_new(void);
82.115 -
82.116 -gboolean gmyth_monitor_handler_open(GMythMonitorHandler * monitor,
82.117 - const gchar * hostname,
82.118 - gint port);
82.119 -
82.120 -gboolean gmyth_monitor_handler_start(GMythMonitorHandler * monitor);
82.121 -
82.122 -void gmyth_monitor_handler_close(GMythMonitorHandler * monitor);
82.123 -
82.124 -G_END_DECLS
82.125 -#endif /* __GMYTH_MONITOR_HANDLER_H__ */
83.1 --- a/gmyth/src/gmyth_programinfo.c Mon Feb 25 17:45:36 2008 +0000
83.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
83.3 @@ -1,582 +0,0 @@
83.4 -/**
83.5 - * GMyth Library
83.6 - *
83.7 - * @file gmyth/gmyth_programinfo.c
83.8 - *
83.9 - * @brief <p> GMythProgramInfo representing the program info, with the
83.10 - * configuration data to the actual remote file in the TV chain.
83.11 - *
83.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
83.13 - * @author Rosfran Borges <rosfran.borges@indt.org.br>
83.14 - * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
83.15 - *
83.16 - *
83.17 - * This program is free software; you can redistribute it and/or modify
83.18 - * it under the terms of the GNU Lesser General Public License as published by
83.19 - * the Free Software Foundation; either version 2 of the License, or
83.20 - * (at your option) any later version.
83.21 - *
83.22 - * This program is distributed in the hope that it will be useful,
83.23 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
83.24 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83.25 - * GNU General Public License for more details.
83.26 - *
83.27 - * You should have received a copy of the GNU Lesser General Public License
83.28 - * along with this program; if not, write to the Free Software
83.29 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
83.30 - *
83.31 - */
83.32 -
83.33 -#ifdef HAVE_CONFIG_H
83.34 -#include "config.h"
83.35 -#endif
83.36 -
83.37 -#include <stdlib.h>
83.38 -#include <string.h>
83.39 -#include <assert.h>
83.40 -
83.41 -#include "gmyth_programinfo.h"
83.42 -#include "gmyth_util.h"
83.43 -#include "gmyth_debug.h"
83.44 -
83.45 -static void gmyth_program_info_class_init(GMythProgramInfoClass *
83.46 - klass);
83.47 -static void gmyth_program_info_init(GMythProgramInfo * object);
83.48 -
83.49 -static void gmyth_program_info_dispose(GObject * object);
83.50 -static void gmyth_program_info_finalize(GObject * object);
83.51 -
83.52 -G_DEFINE_TYPE(GMythProgramInfo, gmyth_program_info, G_TYPE_OBJECT)
83.53 - static const gchar *gmyth_program_info_non_null_value(const GString *
83.54 - str);
83.55 -
83.56 - static void gmyth_program_info_class_init(GMythProgramInfoClass *
83.57 - klass)
83.58 -{
83.59 - GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
83.60 -
83.61 - gobject_class->dispose = gmyth_program_info_dispose;
83.62 - gobject_class->finalize = gmyth_program_info_finalize;
83.63 -}
83.64 -
83.65 -static void
83.66 -gmyth_program_info_init(GMythProgramInfo * gmyth_program_info)
83.67 -{
83.68 - gmyth_program_info->chancommfree = 0;
83.69 -
83.70 - /** A flag informing if the program has video or not. */
83.71 - gmyth_program_info->isVideo = FALSE;
83.72 - gmyth_program_info->lenMins = 0;
83.73 -
83.74 - gmyth_program_info->stars = 0.0f;
83.75 - gmyth_program_info->repeat = 0;
83.76 -
83.77 - gmyth_program_info->hasAirDate = FALSE;
83.78 -
83.79 - gmyth_program_info->spread = 0;
83.80 - gmyth_program_info->startCol = 0;
83.81 -
83.82 - gmyth_program_info->recpriority2 = 0;
83.83 - gmyth_program_info->reactivate = 0;
83.84 -
83.85 - gmyth_program_info->recordid = 0;
83.86 - gmyth_program_info->parentid = 0;
83.87 -
83.88 - /** The backend video source id associated to this program.*/
83.89 - gmyth_program_info->sourceid = 0;
83.90 - /** the backend input id associated to this program.*/
83.91 - gmyth_program_info->inputid = 0;
83.92 - /** The backend card id associated to this program.*/
83.93 - gmyth_program_info->cardid = 0;
83.94 - gmyth_program_info->shareable = FALSE;
83.95 - gmyth_program_info->duplicate = FALSE;
83.96 -
83.97 - gmyth_program_info->findid = 0;
83.98 -
83.99 - gmyth_program_info->programflags = 0;
83.100 - gmyth_program_info->transcoder = 0;
83.101 -
83.102 - gmyth_program_info->recpriority = 0;
83.103 -
83.104 - /** The file size of the recorded program.*/
83.105 - gmyth_program_info->filesize = -1;
83.106 -}
83.107 -
83.108 -static void
83.109 -gmyth_program_info_dispose(GObject * object)
83.110 -{
83.111 - GMythProgramInfo *gmyth_program_info = GMYTH_PROGRAM_INFO(object);
83.112 -
83.113 - /** The program start time. */
83.114 - g_free(gmyth_program_info->startts);
83.115 -
83.116 - /** The program end time. */
83.117 - g_free(gmyth_program_info->endts);
83.118 -
83.119 - /** The recording schedule start time. */
83.120 - g_free(gmyth_program_info->recstartts);
83.121 -
83.122 - /** The recording schedule end time */
83.123 - g_free(gmyth_program_info->recendts);
83.124 -
83.125 - /** The program title. */
83.126 - if (gmyth_program_info->title != NULL) {
83.127 - g_string_free(gmyth_program_info->title, TRUE);
83.128 - gmyth_program_info->title = NULL;
83.129 - }
83.130 -
83.131 - /** The program subtitle. */
83.132 - if (gmyth_program_info->subtitle != NULL) {
83.133 - g_string_free(gmyth_program_info->subtitle, TRUE);
83.134 - gmyth_program_info->subtitle = NULL;
83.135 - }
83.136 -
83.137 - /** The program description. */
83.138 - if (gmyth_program_info->description != NULL) {
83.139 - g_string_free(gmyth_program_info->description, TRUE);
83.140 - gmyth_program_info->description = NULL;
83.141 - }
83.142 -
83.143 - /** The program category. */
83.144 - if (gmyth_program_info->category != NULL) {
83.145 - g_string_free(gmyth_program_info->category, TRUE);
83.146 - gmyth_program_info->category = NULL;
83.147 - }
83.148 -
83.149 - if (gmyth_program_info->chanstr != NULL) {
83.150 - g_string_free(gmyth_program_info->chanstr, TRUE);
83.151 - gmyth_program_info->chanstr = NULL;
83.152 - }
83.153 -
83.154 - if (gmyth_program_info->chansign != NULL) {
83.155 - g_string_free(gmyth_program_info->chansign, TRUE);
83.156 - gmyth_program_info->chansign = NULL;
83.157 - }
83.158 -
83.159 - /** The associated channel name. */
83.160 - if (gmyth_program_info->channame != NULL) {
83.161 - g_string_free(gmyth_program_info->channame, TRUE);
83.162 - gmyth_program_info->channame = NULL;
83.163 - }
83.164 -
83.165 - if (gmyth_program_info->chanOutputFilters != NULL) {
83.166 - g_string_free(gmyth_program_info->chanOutputFilters, TRUE);
83.167 - gmyth_program_info->chanOutputFilters = NULL;
83.168 - }
83.169 -
83.170 - if (gmyth_program_info->seriesid != NULL) {
83.171 - g_string_free(gmyth_program_info->seriesid, TRUE);
83.172 - gmyth_program_info->chanOutputFilters = NULL;
83.173 - }
83.174 -
83.175 - /** The program unique id. */
83.176 - if (gmyth_program_info->program_id != NULL) {
83.177 - g_string_free (gmyth_program_info->program_id, TRUE);
83.178 - gmyth_program_info->program_id = NULL;
83.179 - }
83.180 -
83.181 - if (gmyth_program_info->catType != NULL) {
83.182 - g_string_free(gmyth_program_info->catType, TRUE);
83.183 - gmyth_program_info->catType = NULL;
83.184 - }
83.185 -
83.186 - if (gmyth_program_info->sortTitle != NULL) {
83.187 - g_string_free(gmyth_program_info->sortTitle, TRUE);
83.188 - gmyth_program_info->sortTitle = NULL;
83.189 - }
83.190 -
83.191 - if (gmyth_program_info->year != NULL) {
83.192 - g_string_free(gmyth_program_info->year, TRUE);
83.193 - gmyth_program_info->year = NULL;
83.194 - }
83.195 -
83.196 - g_free(gmyth_program_info->originalAirDate);
83.197 -
83.198 - g_free(gmyth_program_info->lastmodified);
83.199 -
83.200 - g_free(gmyth_program_info->lastInUseTime);
83.201 -
83.202 - if (gmyth_program_info->schedulerid != NULL) {
83.203 - g_string_free(gmyth_program_info->schedulerid, TRUE);
83.204 - gmyth_program_info->schedulerid = NULL;
83.205 - }
83.206 -
83.207 - if (gmyth_program_info->recgroup != NULL) {
83.208 - g_string_free(gmyth_program_info->recgroup, TRUE);
83.209 - gmyth_program_info->recgroup = NULL;
83.210 - }
83.211 -
83.212 - if (gmyth_program_info->playgroup != NULL) {
83.213 - g_string_free(gmyth_program_info->playgroup, TRUE);
83.214 - gmyth_program_info->playgroup = NULL;
83.215 - }
83.216 -
83.217 - /** The file name of the recorded program.*/
83.218 - if (gmyth_program_info->pathname != NULL) {
83.219 - g_string_free(gmyth_program_info->pathname, TRUE);
83.220 - gmyth_program_info->pathname = NULL;
83.221 - }
83.222 -
83.223 - if (gmyth_program_info->hostname != NULL) {
83.224 - g_string_free(gmyth_program_info->hostname, TRUE);
83.225 - gmyth_program_info->hostname = NULL;
83.226 - }
83.227 -
83.228 - G_OBJECT_CLASS(gmyth_program_info_parent_class)->dispose(object);
83.229 -}
83.230 -
83.231 -static void
83.232 -gmyth_program_info_finalize(GObject * object)
83.233 -{
83.234 - g_signal_handlers_destroy(object);
83.235 -
83.236 - G_OBJECT_CLASS(gmyth_program_info_parent_class)->finalize(object);
83.237 -}
83.238 -
83.239 -/**
83.240 - * Creates a new instance of GMythProgramInfo.
83.241 - *
83.242 - * @return a new instance of GMythProgramInfo.
83.243 - */
83.244 -GMythProgramInfo *
83.245 -gmyth_program_info_new(void)
83.246 -{
83.247 - GMythProgramInfo *program_info =
83.248 - GMYTH_PROGRAM_INFO(g_object_new(GMYTH_PROGRAM_INFO_TYPE, NULL));
83.249 -
83.250 - return program_info;
83.251 -}
83.252 -
83.253 -/**
83.254 - * Converts an instance of a GMythProgramInfo, to a GMythStringList.
83.255 - *
83.256 - * @param prog A GMythProgramInfo instance.
83.257 - * @param slist The GMythStringList to be passed to this function, in order to
83.258 - * give the responsibility of the string list creation to the
83.259 - * API user.
83.260 - *
83.261 - * @return a GMythStringList with the program info fields.
83.262 - */
83.263 -GMythStringList *
83.264 -gmyth_program_info_to_string_list(GMythProgramInfo * prog,
83.265 - GMythStringList * slist)
83.266 -{
83.267 - g_return_val_if_fail(prog != NULL, NULL);
83.268 - g_return_val_if_fail(slist != NULL, NULL);
83.269 -
83.270 - gmyth_string_list_append_string(slist, prog->title); /* 0 */
83.271 - gmyth_string_list_append_string(slist, prog->subtitle); /* 1 */
83.272 - gmyth_string_list_append_string(slist, prog->description); /* 2 */
83.273 - gmyth_string_list_append_string(slist, prog->category); /* 3 */
83.274 - gmyth_string_list_append_int (slist, prog->channel_id); /* 4 */
83.275 - gmyth_string_list_append_string(slist, prog->chanstr); /* 5 */
83.276 - gmyth_string_list_append_string(slist, prog->chansign); /* 6 */
83.277 - gmyth_string_list_append_string(slist, prog->channame); /* 7 */
83.278 - gmyth_string_list_append_string(slist, prog->pathname); /* 8 */
83.279 - gmyth_string_list_append_int64(slist, 0); /* 9 */
83.280 -
83.281 - // fixme
83.282 - // gmyth_string_list_append_int64 (slist, 100/*prog->filesize*/); /* 9
83.283 - //
83.284 - //
83.285 - // */
83.286 - // gmyth_string_list_append_int (slist, 0); /* 10 */
83.287 -
83.288 - if (prog->startts)
83.289 - gmyth_string_list_append_int(slist, prog->startts->tv_sec); /* 11 */// DATETIME_TO_LIST(startts)
83.290 - else
83.291 - gmyth_string_list_append_int(slist, 0);
83.292 -
83.293 - if (prog->endts)
83.294 - gmyth_string_list_append_int(slist, prog->endts->tv_sec); /* 12 */// DATETIME_TO_LIST(endts)
83.295 - else
83.296 - gmyth_string_list_append_int(slist, 0);
83.297 -
83.298 - gmyth_string_list_append_int(slist, prog->duplicate); /* 13 */
83.299 - gmyth_string_list_append_int(slist, prog->shareable); /* 14 */
83.300 - gmyth_string_list_append_int(slist, prog->findid); /* 15 */
83.301 - gmyth_string_list_append_string(slist, prog->hostname); /* 16 */
83.302 - gmyth_string_list_append_int(slist, prog->sourceid); /* 17 */
83.303 - gmyth_string_list_append_int(slist, prog->cardid); /* 18 */
83.304 - gmyth_string_list_append_int(slist, prog->inputid); /* 19 */
83.305 - gmyth_string_list_append_int(slist, prog->recpriority); /* 20 */
83.306 - gmyth_string_list_append_int(slist, 0 /* prog->recstatus */ ); /* 21 */
83.307 - gmyth_string_list_append_int(slist, prog->recordid); /* 22 */
83.308 - gmyth_string_list_append_int(slist, 0 /* prog->rectype */ ); /* 23 */
83.309 - gmyth_string_list_append_int(slist, 0 /* prog->dupin */ ); /* 24 */
83.310 - gmyth_string_list_append_int(slist, 0 /* prog->dupmethod */ ); /* 25 */
83.311 - gmyth_string_list_append_int(slist, prog->recstartts != NULL ? prog->recstartts->tv_sec : 0); /* 26
83.312 - */// DATETIME_TO_LIST(recstartts)
83.313 - gmyth_string_list_append_int(slist, prog->recendts != NULL ? prog->recendts->tv_sec : 0); /* 27
83.314 - */// DATETIME_TO_LIST(recendts)
83.315 - gmyth_string_list_append_int(slist, prog->repeat); /* 28 */
83.316 - gmyth_string_list_append_int(slist, prog->programflags); /* 29 */
83.317 - gmyth_string_list_append_char_array(slist, "Default"); /* 30 */// prog->(recgroup
83.318 - //
83.319 - //
83.320 - // != "") ?
83.321 - // recgroup :
83.322 - // "Default")
83.323 - gmyth_string_list_append_int(slist, prog->chancommfree); /* 31 */
83.324 - gmyth_string_list_append_string(slist, prog->chanOutputFilters); /* 32
83.325 - */
83.326 - gmyth_string_list_append_string(slist, prog->seriesid); /* 33 */
83.327 - gmyth_string_list_append_string(slist, prog->program_id); /* 34 */
83.328 - gmyth_string_list_append_char_array(slist, ""); /* 35 */
83.329 - gmyth_string_list_append_int(slist, prog->lastmodified != NULL ? prog->lastmodified->tv_sec : 0); /* 36
83.330 - */// DATETIME_TO_LIST(lastmodified)
83.331 - gmyth_string_list_append_int(slist, 0); /* 37 */// FLOAT_TO_LIST(stars)
83.332 - gmyth_string_list_append_int(slist, prog->originalAirDate != NULL ? prog->originalAirDate->tv_sec : 0); /* 38
83.333 - */// DATETIME_TO_LIST(QDateTime(originalAirDate))
83.334 - gmyth_string_list_append_int(slist, prog->hasAirDate); /* 39 */
83.335 - gmyth_string_list_append_char_array(slist, "Default"); /* 40 */// prog->(playgroup
83.336 - //
83.337 - //
83.338 - // != "") ?
83.339 - // playgroup :
83.340 - // "Default")
83.341 - gmyth_string_list_append_int(slist, prog->recpriority2); /* 41 */
83.342 -
83.343 - return slist;
83.344 -}
83.345 -
83.346 -/**
83.347 - * Converts an instance of a GMythStringList, to a GMythProgramInfo.
83.348 - *
83.349 - * @param slist The GMythStringList got from the MythTV backend server.
83.350 - * @param pos The position in the GMythStringList to start getting the fields.
83.351 - *
83.352 - * @return a GMythProgramInfo representing the string list got from network.
83.353 - */
83.354 -GMythProgramInfo *
83.355 -gmyth_program_info_from_string_list_from_pos(GMythStringList * slist,
83.356 - guint pos)
83.357 -{
83.358 - GMythProgramInfo *prog = gmyth_program_info_new();
83.359 -
83.360 - g_return_val_if_fail(slist != NULL &&
83.361 - gmyth_string_list_get_string(slist, pos) != NULL,
83.362 - NULL);
83.363 -
83.364 - prog->title = gmyth_string_list_get_string(slist, pos);
83.365 - prog->subtitle = gmyth_string_list_get_string(slist, pos + 1);
83.366 - prog->description = gmyth_string_list_get_string(slist, pos + 2);
83.367 - prog->category = gmyth_string_list_get_string(slist, pos + 3);
83.368 - prog->channel_id = gmyth_string_list_get_int (slist, pos + 4);
83.369 - prog->channame = gmyth_string_list_get_string(slist, pos + 5);
83.370 - prog->chanstr = gmyth_string_list_get_string(slist, pos + 6);
83.371 - prog->chansign = gmyth_string_list_get_string(slist, pos + 7);
83.372 - prog->pathname = gmyth_string_list_get_string(slist, pos + 8);
83.373 -
83.374 - prog->filesize = gmyth_string_list_get_int64(slist, pos + 9);
83.375 -
83.376 - gmyth_debug("Prog info: [ %s, %s, %s, %s, %s, %s, %s, %s, %d ]\n",
83.377 - gmyth_program_info_non_null_value(prog->title),
83.378 - gmyth_program_info_non_null_value(prog->subtitle),
83.379 - gmyth_program_info_non_null_value(prog->description),
83.380 - gmyth_program_info_non_null_value(prog->category),
83.381 - gmyth_program_info_non_null_value(prog->channame),
83.382 - gmyth_program_info_non_null_value(prog->chanstr),
83.383 - gmyth_program_info_non_null_value(prog->chansign),
83.384 - gmyth_program_info_non_null_value(prog->pathname),
83.385 - gmyth_string_list_get_int(slist, pos + 11));
83.386 -
83.387 - prog->startts = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 11)))->str); // DATETIME_TO_LIST(startts)
83.388 - prog->endts = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 12)))->str); // DATETIME_TO_LIST(endts)
83.389 - prog->duplicate = gmyth_string_list_get_int(slist, pos + 13);
83.390 - prog->shareable = gmyth_string_list_get_int(slist, pos + 14);
83.391 - prog->findid = gmyth_string_list_get_int(slist, pos + 15);
83.392 - prog->hostname = gmyth_string_list_get_string(slist, pos + 16);
83.393 - prog->sourceid = gmyth_string_list_get_int(slist, pos + 17);
83.394 - prog->cardid = gmyth_string_list_get_int(slist, pos + 18);
83.395 - prog->inputid = gmyth_string_list_get_int(slist, pos + 19);
83.396 - prog->recpriority = gmyth_string_list_get_int(slist, pos + 20);
83.397 - prog->reactivate = gmyth_string_list_get_int(slist, pos + 21);
83.398 - prog->recordid = gmyth_string_list_get_int(slist, pos + 22);
83.399 - gmyth_string_list_get_int(slist, pos + 23);
83.400 - gmyth_string_list_get_int(slist, pos + 24);
83.401 - gmyth_string_list_get_int(slist, pos + 25);
83.402 - prog->recstartts = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 26)))->str); // DATETIME_TO_LIST(recstartts)
83.403 - prog->recendts = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 27)))->str); // DATETIME_TO_LIST(recendts)
83.404 - prog->repeat = gmyth_string_list_get_int(slist, pos + 28);
83.405 - prog->programflags = gmyth_string_list_get_int(slist, pos + 29);
83.406 - prog->recgroup = gmyth_string_list_get_string(slist, pos + 30); // prog->(recgroup
83.407 - //
83.408 - //
83.409 - // !=
83.410 - // "")
83.411 - // ?
83.412 - // recgroup
83.413 - // :
83.414 - // "Default")
83.415 - prog->chancommfree = gmyth_string_list_get_int(slist, pos + 31);
83.416 - prog->chanOutputFilters =
83.417 - gmyth_string_list_get_string(slist, pos + 32);
83.418 - prog->seriesid = gmyth_string_list_get_string(slist, pos + 33);
83.419 - prog->program_id = gmyth_string_list_get_string(slist, pos + 34);
83.420 - gmyth_string_list_get_string(slist, pos + 35);
83.421 - prog->lastmodified = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 36)))->str); // DATETIME_TO_LIST(lastmodified)
83.422 - gmyth_string_list_get_int(slist, pos + 37); // FLOAT_TO_LIST(stars)
83.423 - prog->originalAirDate = gmyth_util_string_to_time_val((gmyth_util_time_to_isoformat((time_t) gmyth_string_list_get_int(slist, pos + 38)))->str); // DATETIME_TO_LIST(QDateTime(originalAirDate))
83.424 - prog->hasAirDate = gmyth_string_list_get_int(slist, pos + 39);
83.425 - prog->playgroup = gmyth_string_list_get_string(slist, pos + 40); // prog->(playgroup
83.426 - //
83.427 - //
83.428 - // !=
83.429 - // "")
83.430 - // ?
83.431 - // playgroup
83.432 - // :
83.433 - // "Default")
83.434 - prog->recpriority2 = gmyth_string_list_get_int(slist, pos + 41);
83.435 -
83.436 - return prog;
83.437 -}
83.438 -
83.439 -/**
83.440 - * Converts an instance of a GMythStringList, to a GMythProgramInfo.
83.441 - *
83.442 - * @param slist The GMythStringList got from the MythTV backend server.
83.443 - *
83.444 - * @return a GMythProgramInfo representing the string list got from network.
83.445 - */
83.446 -GMythProgramInfo *
83.447 -gmyth_program_info_from_string_list(GMythStringList * slist)
83.448 -{
83.449 - GMythProgramInfo *prog = NULL;
83.450 -
83.451 - g_return_val_if_fail(slist != NULL, NULL);
83.452 -
83.453 - prog = gmyth_program_info_from_string_list_from_pos(slist, 0);
83.454 -
83.455 - return prog;
83.456 -}
83.457 -
83.458 -/**
83.459 - * Converts an instance of a GMythStringList, to a GMythProgramInfo ( NEXT_PROGRAM_INFO ).
83.460 - *
83.461 - * @param slist The GMythStringList got from the MythTV backend server.
83.462 - *
83.463 - * @return a GMythProgramInfo representing the string list got from network.
83.464 - */
83.465 -GMythProgramInfo *
83.466 -gmyth_program_info_from_string_list_next_prog(GMythStringList * slist)
83.467 -{
83.468 - GMythProgramInfo *prog = gmyth_program_info_new();
83.469 -
83.470 - g_return_val_if_fail(slist != NULL, NULL);
83.471 -
83.472 - /*
83.473 - * {Home Improvement[]:[]No, No, Godot[]:[] US sitcom about a
83.474 - * DIY-obsessed father of three. When Tim tries to sell off his extra
83.475 - * ticket for an ice hockey game, he is arrested as a tout.[]:[]
83.476 - * Sitcom[]:[]2007-04-18T15:30:00[]:[]2007-04-18T16:00:00[]:[]ABC1[]:[]
83.477 - * /home/hmelo/.mythtv/channels/abc1.jpg[]:[]abc1[]:[]2000[]:[]25725844[]:[]
83.478 - * }
83.479 - */
83.480 -
83.481 - prog->title = gmyth_string_list_get_string(slist, 0);
83.482 - prog->subtitle = gmyth_string_list_get_string(slist, 1);
83.483 - prog->description = gmyth_string_list_get_string(slist, 2);
83.484 - prog->category = gmyth_string_list_get_string(slist, 3);
83.485 - prog->startts = gmyth_util_string_to_time_val(gmyth_string_list_get_char_array(slist, 4)); // DATETIME_TO_LIST(startts)
83.486 - prog->endts = gmyth_util_string_to_time_val(gmyth_string_list_get_char_array(slist, 5)); // DATETIME_TO_LIST(endts)
83.487 - prog->channame = gmyth_string_list_get_string(slist, 6);
83.488 - prog->chansign = gmyth_string_list_get_string(slist, 7);
83.489 - prog->chanstr = gmyth_string_list_get_string(slist, 8);
83.490 - prog->channel_id = gmyth_string_list_get_int (slist, 9);
83.491 - prog->filesize = gmyth_string_list_get_int64(slist, 10);
83.492 -
83.493 - gmyth_debug
83.494 - ("NEXT program info: [ %s, %s, %s, %s, %s, %s, %s, %s ]\n",
83.495 - gmyth_program_info_non_null_value(prog->title),
83.496 - gmyth_program_info_non_null_value(prog->subtitle),
83.497 - gmyth_program_info_non_null_value(prog->description),
83.498 - gmyth_program_info_non_null_value(prog->category),
83.499 - gmyth_program_info_non_null_value(prog->channame),
83.500 - gmyth_program_info_non_null_value(prog->chanstr),
83.501 - gmyth_program_info_non_null_value(prog->chansign),
83.502 - gmyth_program_info_non_null_value(prog->pathname));
83.503 -
83.504 - return prog;
83.505 -}
83.506 -
83.507 -static const gchar *
83.508 -gmyth_program_info_non_null_value(const GString * str)
83.509 -{
83.510 - return (str != NULL && str->str != NULL
83.511 - && strlen(str->str) > 0 ? str->str : " ");
83.512 -}
83.513 -
83.514 -/**
83.515 - * Prints out an instance of a GMythProgramInfo.
83.516 - *
83.517 - * @param prog A GMythProgramInfo instance.
83.518 - *
83.519 - * @return a string representing the program info.
83.520 - */
83.521 -const gchar *
83.522 -gmyth_program_info_to_string(const GMythProgramInfo * prog)
83.523 -{
83.524 - return
83.525 - g_strdup_printf
83.526 - ("Title: %s, Subtitle: %s, Description: %s, Category: %s, Channel ID: %d, "
83.527 - "Channel Name: %s, Chan str: %s, Channel Sign: %s, Path Name: %s, File Size: %lld, \n"
83.528 - "Start TS: %s, End TS: %s, Duplicate: %d, Shareable: %d, Find ID: %d, Hostname: %s, "
83.529 - "Source ID: %d, Vard ID: %d, Input ID: %d, Rec Priority: %d, Reactivate: %d, \n"
83.530 - "Record ID: %d, Rec Start TS: %s, Rec End TS: %s, Repeat: %d, Program Flags: %d, "
83.531 - "Rec Group: %s, Channel Comm Free: %d, Channel Output Filters: %s, Series ID: %s, \n"
83.532 - "Program ID: %s, Last Modified Date: %s, Original Air Date: %s, Has Air Date: %d, "
83.533 - "Play Group: %s.\n",
83.534 - gmyth_program_info_non_null_value(prog->title),
83.535 - gmyth_program_info_non_null_value(prog->subtitle),
83.536 - gmyth_program_info_non_null_value(prog->description),
83.537 - gmyth_program_info_non_null_value(prog->category),
83.538 - prog->channel_id,
83.539 - gmyth_program_info_non_null_value(prog->channame),
83.540 - gmyth_program_info_non_null_value(prog->chanstr),
83.541 - gmyth_program_info_non_null_value(prog->chansign),
83.542 - gmyth_program_info_non_null_value(prog->pathname), prog->filesize,
83.543 - gmyth_util_time_to_string_from_time_val(prog->startts),
83.544 - gmyth_util_time_to_string_from_time_val(prog->endts),
83.545 - prog->duplicate, prog->shareable, prog->findid,
83.546 - gmyth_program_info_non_null_value(prog->hostname), prog->sourceid,
83.547 - prog->cardid, prog->inputid, prog->recpriority, prog->reactivate,
83.548 - prog->recordid,
83.549 - gmyth_util_time_to_string_from_time_val(prog->recstartts),
83.550 - gmyth_util_time_to_string_from_time_val(prog->recendts),
83.551 - prog->repeat, prog->programflags,
83.552 - gmyth_program_info_non_null_value(prog->recgroup),
83.553 - prog->chancommfree,
83.554 - gmyth_program_info_non_null_value(prog->chanOutputFilters),
83.555 - gmyth_program_info_non_null_value(prog->seriesid),
83.556 - gmyth_program_info_non_null_value(prog->program_id),
83.557 - gmyth_util_time_to_string_from_time_val(prog->lastmodified),
83.558 - gmyth_util_time_to_string_from_time_val(prog->originalAirDate),
83.559 - prog->hasAirDate,
83.560 - gmyth_program_info_non_null_value(prog->playgroup));
83.561 -}
83.562 -
83.563 -/**
83.564 - * Say if an instance of a GMythProgramInfo is equals to another one.
83.565 - *
83.566 - * @param prog The first GMythProgramInfo instance.
83.567 - * @param prog The second GMythProgramInfo instance.
83.568 - *
83.569 - * @return <code>true</code>, if the program infos are equals.
83.570 - */
83.571 -gboolean
83.572 -gmyth_program_info_is_equals(const GMythProgramInfo * prog1,
83.573 - const GMythProgramInfo * prog2)
83.574 -{
83.575 - if ((strcmp(gmyth_program_info_non_null_value(prog1->title),
83.576 - gmyth_program_info_non_null_value(prog2->title)) == 0)
83.577 - ||
83.578 - (strcmp
83.579 - (gmyth_program_info_non_null_value(prog1->pathname),
83.580 - gmyth_program_info_non_null_value(prog2->pathname)) == 0))
83.581 - return TRUE;
83.582 - else
83.583 - return FALSE;
83.584 -
83.585 -}
84.1 --- a/gmyth/src/gmyth_programinfo.h Mon Feb 25 17:45:36 2008 +0000
84.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
84.3 @@ -1,180 +0,0 @@
84.4 -/**
84.5 - * GMyth Library
84.6 - *
84.7 - * @file gmyth/gmyth_programinfo.h
84.8 - *
84.9 - * @brief <p> GMythProgramInfo representing the program info, with the
84.10 - * configuration data to the actual remote file in the TV chain.
84.11 - *
84.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
84.13 - * @author Rosfran Borges <rosfran.borges@indt.org.br>
84.14 - * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
84.15 - *
84.16 - *
84.17 - * This program is free software; you can redistribute it and/or modify
84.18 - * it under the terms of the GNU Lesser General Public License as published by
84.19 - * the Free Software Foundation; either version 2 of the License, or
84.20 - * (at your option) any later version.
84.21 - *
84.22 - * This program is distributed in the hope that it will be useful,
84.23 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
84.24 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
84.25 - * GNU General Public License for more details.
84.26 - *
84.27 - * You should have received a copy of the GNU Lesser General Public License
84.28 - * along with this program; if not, write to the Free Software
84.29 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
84.30 - *
84.31 - */
84.32 -
84.33 -#ifndef _GMYTH_PROGRAMINFO_H
84.34 -#define _GMYTH_PROGRAMINFO_H
84.35 -
84.36 -#include <glib.h>
84.37 -#include <glib-object.h>
84.38 -
84.39 -#include "gmyth_stringlist.h"
84.40 -
84.41 -G_BEGIN_DECLS
84.42 -#define GMYTH_PROGRAM_INFO_TYPE (gmyth_program_info_get_type ())
84.43 -#define GMYTH_PROGRAM_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_PROGRAM_INFO_TYPE, GMythProgramInfo))
84.44 -#define GMYTH_PROGRAM_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_PROGRAM_INFO_TYPE, GMythProgramInfoClass))
84.45 -#define IS_GMYTH_PROGRAM_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_PROGRAM_INFO_TYPE))
84.46 -#define IS_GMYTH_PROGRAM_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_PROGRAM_INFO_TYPE))
84.47 -#define GMYTH_PROGRAM_INFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_PROGRAM_INFO_TYPE, GMythProgramInfoClass))
84.48 -typedef struct _GMythProgramInfo GMythProgramInfo;
84.49 -typedef struct _GMythProgramInfoClass GMythProgramInfoClass;
84.50 -
84.51 -struct _GMythProgramInfoClass {
84.52 - GObjectClass parent_class;
84.53 -
84.54 - /*
84.55 - * callbacks
84.56 - */
84.57 -};
84.58 -
84.59 -/**
84.60 - * The GMythProgramInfo structure represents a program information
84.61 - * stored in the database. It could be a program from the EPG data,
84.62 - * a program scheduled to be recorded, or a program already recorded.
84.63 - */
84.64 -struct _GMythProgramInfo {
84.65 - GObject parent;
84.66 -
84.67 - /** The channel unique ID. */
84.68 - gint channel_id;
84.69 - /** The program start time. */
84.70 - GTimeVal *startts;
84.71 - /** The program end time. */
84.72 - GTimeVal *endts;
84.73 - /** The recording schedule start time. */
84.74 - GTimeVal *recstartts;
84.75 - /** The recording schedule end time */
84.76 - GTimeVal *recendts;
84.77 -
84.78 - /** The program title. */
84.79 - GString *title;
84.80 - /** The program subtitle. */
84.81 - GString *subtitle;
84.82 - /** The program description. */
84.83 - GString *description;
84.84 - /** The program category. */
84.85 - GString *category;
84.86 -
84.87 - GString *chanstr;
84.88 - GString *chansign;
84.89 - /** The associated channel name. */
84.90 - GString *channame;
84.91 - gint chancommfree;
84.92 - GString *chanOutputFilters;
84.93 -
84.94 - GString *seriesid;
84.95 - /** The program unique id. */
84.96 - GString *program_id;
84.97 - GString *catType;
84.98 -
84.99 - GString *sortTitle;
84.100 -
84.101 - /** A flag informing if the program has video or not. */
84.102 - gboolean isVideo;
84.103 - gint lenMins;
84.104 -
84.105 - GString *year;
84.106 - gdouble stars;
84.107 - gint repeat;
84.108 -
84.109 - GTimeVal *originalAirDate;
84.110 - GTimeVal *lastmodified;
84.111 - GTimeVal *lastInUseTime;
84.112 -
84.113 - gboolean hasAirDate;
84.114 -
84.115 - gint spread;
84.116 - gint startCol;
84.117 -
84.118 - gint recpriority2;
84.119 - gint reactivate;
84.120 -
84.121 - gint recordid;
84.122 - gint parentid;
84.123 -
84.124 - /** The backend video source id associated to this program.*/
84.125 - gint sourceid;
84.126 - /** the backend input id associated to this program.*/
84.127 - gint inputid;
84.128 - /** The backend card id associated to this program.*/
84.129 - gint cardid;
84.130 - gboolean shareable;
84.131 - gboolean duplicate;
84.132 -
84.133 - GString *schedulerid;
84.134 - gint findid;
84.135 -
84.136 - gint programflags;
84.137 - gint transcoder;
84.138 -
84.139 - GString *recgroup;
84.140 - GString *playgroup;
84.141 - gint rectype;
84.142 - gint recstatus;
84.143 - gint recpriority;
84.144 - gint dupin;
84.145 - gint dupmethod;
84.146 -
84.147 - /** The file size of the recorded program.*/
84.148 - gint64 filesize;
84.149 -
84.150 - /** The file name of the recorded program.*/
84.151 - GString *pathname;
84.152 - GString *hostname;
84.153 -};
84.154 -
84.155 -GType gmyth_program_info_get_type(void);
84.156 -
84.157 -GMythProgramInfo *gmyth_program_info_new(void);
84.158 -
84.159 -GMythStringList *gmyth_program_info_to_string_list(GMythProgramInfo * prog,
84.160 - GMythStringList *
84.161 - slist);
84.162 -
84.163 -GMythProgramInfo
84.164 - * gmyth_program_info_from_string_list_from_pos(GMythStringList * slist,
84.165 - guint pos);
84.166 -
84.167 -GMythProgramInfo *gmyth_program_info_from_string_list(GMythStringList *
84.168 - slist);
84.169 -
84.170 -GMythProgramInfo
84.171 - * gmyth_program_info_from_string_list_next_prog(GMythStringList *
84.172 - slist);
84.173 -
84.174 -const gchar *gmyth_program_info_to_string(const GMythProgramInfo *
84.175 - prog);
84.176 -
84.177 -gboolean gmyth_program_info_is_equals(const GMythProgramInfo *
84.178 - prog1,
84.179 - const GMythProgramInfo *
84.180 - prog2);
84.181 -
84.182 -G_END_DECLS
84.183 -#endif /*_GMYTH_PROGRAMINFO_H*/
85.1 --- a/gmyth/src/gmyth_query.c Mon Feb 25 17:45:36 2008 +0000
85.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
85.3 @@ -1,280 +0,0 @@
85.4 -/**
85.5 - * GMyth Library
85.6 - *
85.7 - * @file gmyth/gmyth_query.c
85.8 - *
85.9 - * @brief <p> GMythQuery class provides a wrapper for accessing
85.10 - * the libmysqlclient funtions.
85.11 - *
85.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
85.13 - * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
85.14 - *
85.15 - *
85.16 - * This program is free software; you can redistribute it and/or modify
85.17 - * it under the terms of the GNU Lesser General Public License as published by
85.18 - * the Free Software Foundation; either version 2 of the License, or
85.19 - * (at your option) any later version.
85.20 - *
85.21 - * This program is distributed in the hope that it will be useful,
85.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
85.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
85.24 - * GNU General Public License for more details.
85.25 - *
85.26 - * You should have received a copy of the GNU Lesser General Public License
85.27 - * along with this program; if not, write to the Free Software
85.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
85.29 - */
85.30 -
85.31 -#ifdef HAVE_CONFIG_H
85.32 -#include "config.h"
85.33 -#endif
85.34 -
85.35 -#include <stdlib.h>
85.36 -#include <stdio.h>
85.37 -#include <assert.h>
85.38 -
85.39 -#include "gmyth_query.h"
85.40 -#include "gmyth_debug.h"
85.41 -
85.42 -static void gmyth_query_class_init(GMythQueryClass * klass);
85.43 -static void gmyth_query_init(GMythQuery * object);
85.44 -
85.45 -static void gmyth_query_dispose(GObject * object);
85.46 -static void gmyth_query_finalize(GObject * object);
85.47 -
85.48 -static void gmyth_query_print_error(MYSQL * conn, char *message);
85.49 -
85.50 -G_DEFINE_TYPE(GMythQuery, gmyth_query, G_TYPE_OBJECT)
85.51 - static void gmyth_query_class_init(GMythQueryClass * klass)
85.52 -{
85.53 - GObjectClass *gobject_class;
85.54 -
85.55 - gobject_class = (GObjectClass *) klass;
85.56 -
85.57 - gobject_class->dispose = gmyth_query_dispose;
85.58 - gobject_class->finalize = gmyth_query_finalize;
85.59 -}
85.60 -
85.61 -static void
85.62 -gmyth_query_init(GMythQuery * gmyth_query)
85.63 -{
85.64 - gmyth_query->backend_info = NULL;
85.65 -
85.66 - /*
85.67 - * initialize connection handler
85.68 - */
85.69 - gmyth_query->conn = mysql_init(NULL);
85.70 -
85.71 - if (!(gmyth_query->conn))
85.72 - g_warning("[%s] MSQL structure not initialized", __FUNCTION__);
85.73 -}
85.74 -
85.75 -static void
85.76 -gmyth_query_dispose(GObject * object)
85.77 -{
85.78 - GMythQuery *gmyth_query = GMYTH_QUERY(object);
85.79 -
85.80 - if (gmyth_query->conn != NULL) {
85.81 - gmyth_query_disconnect(gmyth_query);
85.82 - }
85.83 -
85.84 - if (gmyth_query->backend_info) {
85.85 - g_object_unref(gmyth_query->backend_info);
85.86 - gmyth_query->backend_info = NULL;
85.87 - }
85.88 -
85.89 - G_OBJECT_CLASS(gmyth_query_parent_class)->dispose(object);
85.90 -}
85.91 -
85.92 -static void
85.93 -gmyth_query_finalize(GObject * object)
85.94 -{
85.95 - g_signal_handlers_destroy(object);
85.96 -
85.97 - G_OBJECT_CLASS(gmyth_query_parent_class)->finalize(object);
85.98 -}
85.99 -
85.100 -/** Creates a new instance of GMythQuery.
85.101 - *
85.102 - * @return a new instance of GMythQuery.
85.103 - */
85.104 -GMythQuery *
85.105 -gmyth_query_new()
85.106 -{
85.107 - GMythQuery *sql_query =
85.108 - GMYTH_QUERY(g_object_new(GMYTH_QUERY_TYPE, NULL));
85.109 -
85.110 - return sql_query;
85.111 -}
85.112 -
85.113 -gboolean
85.114 -gmyth_query_connect_with_timeout(GMythQuery * gmyth_query,
85.115 - GMythBackendInfo * backend_info,
85.116 - guint timeout)
85.117 -{
85.118 - assert(gmyth_query);
85.119 -
85.120 - if (gmyth_query->conn == NULL)
85.121 - gmyth_query->conn = mysql_init(NULL);
85.122 -
85.123 - if (timeout != 0) {
85.124 - /*
85.125 - * sets connection timeout
85.126 - */
85.127 - mysql_options(gmyth_query->conn, MYSQL_OPT_CONNECT_TIMEOUT,
85.128 - (gchar *) & timeout);
85.129 - }
85.130 -
85.131 - return gmyth_query_connect(gmyth_query, backend_info);
85.132 -}
85.133 -
85.134 -/** Connects to the Mysql database in the backend. The backend address
85.135 - * is loaded from the GMythBackendInfo instance.
85.136 - *
85.137 - * @param gmyth_query the GMythEPG instance to be connected.
85.138 - * @return true if connection was success, false if failed.
85.139 - */
85.140 -gboolean
85.141 -gmyth_query_connect(GMythQuery * gmyth_query,
85.142 - GMythBackendInfo * backend_info)
85.143 -{
85.144 - assert(gmyth_query);
85.145 - g_return_val_if_fail(backend_info != NULL, FALSE);
85.146 - g_return_val_if_fail(backend_info->hostname != NULL, FALSE);
85.147 - g_return_val_if_fail(backend_info->username != NULL, FALSE);
85.148 - g_return_val_if_fail(backend_info->password != NULL, FALSE);
85.149 - g_return_val_if_fail(backend_info->db_name != NULL, FALSE);
85.150 -
85.151 - if (gmyth_query->backend_info != NULL) {
85.152 - g_object_unref(gmyth_query->backend_info);
85.153 - }
85.154 - gmyth_query->backend_info = g_object_ref(backend_info);
85.155 -
85.156 - if (gmyth_query->conn == NULL) {
85.157 - gmyth_query->conn = mysql_init(NULL);
85.158 - }
85.159 -
85.160 - /*
85.161 - * connect to server
85.162 - */
85.163 - if (mysql_real_connect(gmyth_query->conn,
85.164 - gmyth_query->backend_info->hostname,
85.165 - gmyth_query->backend_info->username,
85.166 - gmyth_query->backend_info->password,
85.167 - gmyth_query->backend_info->db_name,
85.168 - gmyth_query->backend_info->db_port,
85.169 - NULL,
85.170 - 0) == NULL) {
85.171 - gmyth_query_print_error(gmyth_query->conn,
85.172 - "mysql_real_connect() failed");
85.173 - return FALSE;
85.174 - }
85.175 -
85.176 - gmyth_debug
85.177 - ("[%s] Connection to Mysql server succeeded! (host = %s, user = %s, "
85.178 - "password = %s, db name = %s)", __FUNCTION__,
85.179 - gmyth_query->backend_info->hostname,
85.180 - gmyth_query->backend_info->username,
85.181 - gmyth_query->backend_info->password,
85.182 - gmyth_query->backend_info->db_name);
85.183 -
85.184 - return TRUE;
85.185 -}
85.186 -
85.187 -/** Disconnects from the Mysql database in the backend.
85.188 - *
85.189 - * @param gmyth_query the GMythQuery instance to be disconnected
85.190 - * @return true if disconnection was success, false if failed.
85.191 - */
85.192 -gboolean
85.193 -gmyth_query_disconnect(GMythQuery * gmyth_query)
85.194 -{
85.195 - g_return_val_if_fail(gmyth_query != NULL, FALSE);
85.196 - g_return_val_if_fail(gmyth_query->conn != NULL, FALSE);
85.197 -
85.198 - /*
85.199 - * TODO: Check how to return error
85.200 - */
85.201 - gmyth_debug("[%s] Closing gmyth_query->conn", __FUNCTION__);
85.202 -
85.203 - mysql_close(gmyth_query->conn);
85.204 - gmyth_query->conn = NULL;
85.205 -
85.206 - return TRUE;
85.207 -}
85.208 -
85.209 -static void
85.210 -gmyth_query_print_error(MYSQL * conn, char *message)
85.211 -{
85.212 - gmyth_debug("%s", message);
85.213 -
85.214 - if (conn != NULL) {
85.215 -#if MYSQL_VERSION_ID >= 40101
85.216 - gmyth_debug("Error %u (%s): %s\n",
85.217 - mysql_errno(conn), mysql_sqlstate(conn),
85.218 - mysql_error(conn));
85.219 -#else
85.220 - gmyth_debug("Error %u: %s\n", mysql_errno(conn),
85.221 - mysql_error(conn));
85.222 -#endif
85.223 - }
85.224 -}
85.225 -
85.226 -/** Sends the given query to the backend returning the query result as
85.227 - * MYSQL_RES pointer.
85.228 - *
85.229 - * FIXME: this function is returning NULL whether any error happens
85.230 - * or no rows are returned (e.g. UPDATE or REPLACE).
85.231 - *
85.232 - * @param gmyth_query the GMythQuery instance.
85.233 - * @param stmt_str the query text.
85.234 - * @return the MYSQL_RES result pointer or NULL if any error happens.
85.235 - */
85.236 -MYSQL_RES*
85.237 -gmyth_query_process_statement(GMythQuery * gmyth_query, char *stmt_str)
85.238 -{
85.239 - assert(gmyth_query);
85.240 -
85.241 - gmyth_debug("[%s] Running mysql query %s", __FUNCTION__, stmt_str);
85.242 -
85.243 - if (gmyth_query == NULL)
85.244 - return NULL;
85.245 -
85.246 - //the statement failed
85.247 - if (mysql_query(gmyth_query->conn, stmt_str) != 0) {
85.248 - gmyth_query_print_error(gmyth_query->conn,
85.249 - "Could not execute statement");
85.250 - return NULL;
85.251 - }
85.252 -
85.253 - //the statement succeeded; determine whether it returned data
85.254 - return mysql_store_result(gmyth_query->conn);
85.255 -}
85.256 -
85.257 -MYSQL_RES*
85.258 -gmyth_query_process_statement_with_increment(GMythQuery * gmyth_query,
85.259 - char *stmt_str, gulong * id)
85.260 -{
85.261 - assert(gmyth_query);
85.262 -
85.263 - gmyth_debug("[%s] Running mysql query %s", __FUNCTION__, stmt_str);
85.264 -
85.265 - if (gmyth_query == NULL)
85.266 - return NULL;
85.267 -
85.268 - /*
85.269 - * the statement failed
85.270 - */
85.271 - if (mysql_query(gmyth_query->conn, stmt_str) != 0) {
85.272 - gmyth_query_print_error(gmyth_query->conn,
85.273 - "Could not execute statement");
85.274 - return NULL;
85.275 - }
85.276 -
85.277 - *id = (my_ulonglong) mysql_insert_id(gmyth_query->conn);
85.278 -
85.279 - /*
85.280 - * the statement succeeded; determine whether it returned data
85.281 - */
85.282 - return mysql_store_result(gmyth_query->conn);
85.283 -}
86.1 --- a/gmyth/src/gmyth_query.h Mon Feb 25 17:45:36 2008 +0000
86.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
86.3 @@ -1,93 +0,0 @@
86.4 -/**
86.5 - * GMyth Library
86.6 - *
86.7 - * @file gmyth/gmyth_query.h
86.8 - *
86.9 - * @brief <p> GMythQuery class provides a wrapper for accessing
86.10 - * the libmysqlclient funtions.
86.11 - *
86.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
86.13 - * @author Leonardo Sobral Cunha <leonardo.cunha@indt.org.br>
86.14 - *
86.15 - *
86.16 - * This program is free software; you can redistribute it and/or modify
86.17 - * it under the terms of the GNU Lesser General Public License as published by
86.18 - * the Free Software Foundation; either version 2 of the License, or
86.19 - * (at your option) any later version.
86.20 - *
86.21 - * This program is distributed in the hope that it will be useful,
86.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
86.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
86.24 - * GNU General Public License for more details.
86.25 - *
86.26 - * You should have received a copy of the GNU Lesser General Public License
86.27 - * along with this program; if not, write to the Free Software
86.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
86.29 - */
86.30 -
86.31 -#ifndef __GMYTH_QUERY_H__
86.32 -#define __GMYTH_QUERY_H__
86.33 -
86.34 -#include <glib-object.h>
86.35 -
86.36 -/*
86.37 - * MYSQL includes
86.38 - */
86.39 -#include <mysql/mysql.h>
86.40 -
86.41 -#include "gmyth_backendinfo.h"
86.42 -
86.43 -G_BEGIN_DECLS
86.44 -#define GMYTH_QUERY_TYPE (gmyth_query_get_type ())
86.45 -#define GMYTH_QUERY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_QUERY_TYPE, GMythQuery))
86.46 -#define GMYTH_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_QUERY_TYPE, GMythQueryClass))
86.47 -#define IS_GMYTH_QUERY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_QUERY_TYPE))
86.48 -#define IS_GMYTH_QUERY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_QUERY_TYPE))
86.49 -#define GMYTH_QUERY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_QUERY_TYPE, GMythQueryClass))
86.50 -typedef struct _GMythQuery GMythQuery;
86.51 -typedef struct _GMythQueryClass GMythQueryClass;
86.52 -
86.53 -struct _GMythQueryClass {
86.54 - GObjectClass parent_class;
86.55 -
86.56 - /*
86.57 - * callbacks
86.58 - */
86.59 - /*
86.60 - * no one for now
86.61 - */
86.62 -};
86.63 -
86.64 -struct _GMythQuery {
86.65 - GObject parent;
86.66 -
86.67 - GMythBackendInfo *backend_info;
86.68 -
86.69 - /*
86.70 - * pointer to connection handler
86.71 - */
86.72 - MYSQL *conn;
86.73 -};
86.74 -
86.75 -
86.76 -GType gmyth_query_get_type(void);
86.77 -
86.78 -GMythQuery *gmyth_query_new(void);
86.79 -MYSQL_RES *gmyth_query_process_statement(GMythQuery * gmyth_query,
86.80 - gchar * stmt_str);
86.81 -MYSQL_RES *gmyth_query_process_statement_with_increment(GMythQuery *
86.82 - gmyth_query,
86.83 - char
86.84 - *stmt_str,
86.85 - gulong * id);
86.86 -
86.87 -gboolean gmyth_query_connect(GMythQuery * gmyth_query,
86.88 - GMythBackendInfo * backend_info);
86.89 -gboolean gmyth_query_connect_with_timeout(GMythQuery * gmyth_query,
86.90 - GMythBackendInfo *
86.91 - backend_info,
86.92 - guint timeout);
86.93 -gboolean gmyth_query_disconnect(GMythQuery * gmyth_query);
86.94 -
86.95 -G_END_DECLS
86.96 -#endif /* __GMYTH_QUERY_H__ */
87.1 --- a/gmyth/src/gmyth_recorder.c Mon Feb 25 17:45:36 2008 +0000
87.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
87.3 @@ -1,1388 +0,0 @@
87.4 -/**
87.5 - * GMyth Library
87.6 - *
87.7 - * @file gmyth/gmyth_recorder.c
87.8 - *
87.9 - * @brief <p> GMythRecorder defines functions for playing live tv.
87.10 - *
87.11 - * The remote encoder is used by gmyth_tvplayer to setup livetv.
87.12 - *
87.13 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
87.14 - * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
87.15 - * @author Rosfran Borges <rosfran.borges@indt.org.br>
87.16 - *
87.17 - *
87.18 - * This program is free software; you can redistribute it and/or modify
87.19 - * it under the terms of the GNU Lesser General Public License as published by
87.20 - * the Free Software Foundation; either version 2 of the License, or
87.21 - * (at your option) any later version.
87.22 - *
87.23 - * This program is distributed in the hope that it will be useful,
87.24 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
87.25 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
87.26 - * GNU General Public License for more details.
87.27 - *
87.28 - * You should have received a copy of the GNU Lesser General Public License
87.29 - * along with this program; if not, write to the Free Software
87.30 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
87.31 - */
87.32 -
87.33 -#ifdef HAVE_CONFIG_H
87.34 -#include "config.h"
87.35 -#endif
87.36 -
87.37 -#include "gmyth_recorder.h"
87.38 -
87.39 -#include <assert.h>
87.40 -
87.41 -#include "gmyth_stringlist.h"
87.42 -#include "gmyth_util.h"
87.43 -#include "gmyth_common.h"
87.44 -#include "gmyth_debug.h"
87.45 -
87.46 -#define GMYTHTV_RECORDER_HEADER "QUERY_RECORDER"
87.47 -
87.48 -static void gmyth_recorder_class_init(GMythRecorderClass * klass);
87.49 -static void gmyth_recorder_init(GMythRecorder * object);
87.50 -
87.51 -static void gmyth_recorder_dispose(GObject * object);
87.52 -static void gmyth_recorder_finalize(GObject * object);
87.53 -
87.54 -G_DEFINE_TYPE(GMythRecorder, gmyth_recorder, G_TYPE_OBJECT)
87.55 - static void gmyth_recorder_class_init(GMythRecorderClass * klass)
87.56 -{
87.57 - GObjectClass *gobject_class;
87.58 -
87.59 - gobject_class = (GObjectClass *) klass;
87.60 -
87.61 - gobject_class->dispose = gmyth_recorder_dispose;
87.62 - gobject_class->finalize = gmyth_recorder_finalize;
87.63 -}
87.64 -
87.65 -static void
87.66 -gmyth_recorder_init(GMythRecorder * gmyth_remote_encoder)
87.67 -{
87.68 -}
87.69 -
87.70 -static void
87.71 -gmyth_recorder_dispose(GObject * object)
87.72 -{
87.73 - GMythRecorder *recorder = GMYTH_RECORDER(object);
87.74 -
87.75 - gmyth_recorder_close(recorder);
87.76 -
87.77 - if (recorder->mutex != NULL) {
87.78 - g_mutex_free(recorder->mutex);
87.79 - recorder->mutex = NULL;
87.80 - }
87.81 -
87.82 - if (recorder->myth_socket != NULL) {
87.83 - g_object_unref(recorder->myth_socket);
87.84 - recorder->myth_socket = NULL;
87.85 - }
87.86 -
87.87 - if (recorder->progs_info_list != NULL)
87.88 - gmyth_free_program_list(recorder->progs_info_list);
87.89 -
87.90 - if (recorder->hostname != NULL)
87.91 - g_string_free(recorder->hostname, TRUE);
87.92 -
87.93 - G_OBJECT_CLASS(gmyth_recorder_parent_class)->dispose(object);
87.94 -}
87.95 -
87.96 -static void
87.97 -gmyth_recorder_finalize(GObject * object)
87.98 -{
87.99 - g_signal_handlers_destroy(object);
87.100 -
87.101 - G_OBJECT_CLASS(gmyth_recorder_parent_class)->finalize(object);
87.102 -}
87.103 -
87.104 -void
87.105 -gmyth_recorder_close(GMythRecorder * recorder)
87.106 -{
87.107 - if (recorder != NULL && recorder->recorder_num != -1) {
87.108 - g_mutex_lock(recorder->mutex);
87.109 -
87.110 - gmyth_recorder_stop_playing(recorder);
87.111 - gmyth_recorder_stop_livetv(recorder);
87.112 - gmyth_recorder_finish_recording(recorder);
87.113 - gmyth_recorder_free_tuner(recorder);
87.114 -
87.115 - g_mutex_unlock(recorder->mutex);
87.116 - }
87.117 -}
87.118 -
87.119 -/** Creates a new instance of GMythRecorder.
87.120 - *
87.121 - * @return a new instance of GMythRecorder.
87.122 - */
87.123 -GMythRecorder *
87.124 -gmyth_recorder_new(int num, GString * hostname, gshort port)
87.125 -{
87.126 - GMythRecorder *encoder =
87.127 - GMYTH_RECORDER(g_object_new(GMYTH_RECORDER_TYPE, FALSE));
87.128 -
87.129 - encoder->recorder_num = num;
87.130 - encoder->hostname = g_string_new(hostname->str);
87.131 - encoder->port = port;
87.132 -
87.133 - encoder->mutex = g_mutex_new();
87.134 -
87.135 - encoder->progs_info_list = NULL;
87.136 -
87.137 - return encoder;
87.138 -}
87.139 -
87.140 -/** Configures the remote encoder instance connecting it to Mythtv backend.
87.141 - *
87.142 - * @param recorder the GMythRecorder instance.
87.143 - *
87.144 - * @return TRUE if successfull, FALSE if any error happens.
87.145 - */
87.146 -gboolean
87.147 -gmyth_recorder_setup(GMythRecorder * recorder)
87.148 -{
87.149 - assert(recorder);
87.150 - gmyth_debug("[%s] Creating socket and connecting to backend",
87.151 - __FUNCTION__);
87.152 -
87.153 - if (recorder->myth_socket == NULL) {
87.154 - recorder->myth_socket = gmyth_socket_new();
87.155 -
87.156 - if (!gmyth_socket_connect_to_backend(recorder->myth_socket,
87.157 - recorder->hostname->str,
87.158 - recorder->port, TRUE)) {
87.159 - gmyth_debug
87.160 - ("GMythRemoteEncoder: Connection to backend failed");
87.161 - return FALSE;
87.162 - }
87.163 - } else {
87.164 - gmyth_debug("Remote encoder socket already created\n");
87.165 - }
87.166 -
87.167 - return TRUE;
87.168 -}
87.169 -
87.170 -/** Sends the SPAWN_LIVETV command through Mythtv protocol. This command
87.171 - * requests the backend to start capturing TV content.
87.172 - *
87.173 - * @param recorder The GMythRecorder instance.
87.174 - * @param tvchain_id The tvchain unique id.
87.175 - * @return true if success, false if any error happens.
87.176 - */
87.177 -gboolean
87.178 -gmyth_recorder_spawntv(GMythRecorder * recorder, GString * tvchain_id)
87.179 -{
87.180 - GMythStringList *str_list;
87.181 - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
87.182 - gboolean ret = TRUE;
87.183 -
87.184 - gmyth_debug("[%s] Spawntv with tvchain_id = %s", __FUNCTION__,
87.185 - tvchain_id->str);
87.186 -
87.187 - str_list = gmyth_string_list_new();
87.188 -
87.189 - g_mutex_lock(recorder->mutex);
87.190 -
87.191 - g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
87.192 -
87.193 - gmyth_string_list_append_string(str_list, tmp_str);
87.194 - g_string_free(tmp_str, TRUE);
87.195 -
87.196 - gmyth_string_list_append_char_array(str_list, "SPAWN_LIVETV");
87.197 -
87.198 - gmyth_string_list_append_string(str_list, tvchain_id);
87.199 - gmyth_string_list_append_int(str_list, 0); // PIP = FALSE (0)
87.200 -
87.201 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
87.202 -
87.203 - tmp_str = gmyth_string_list_get_string(str_list, 0);
87.204 -
87.205 - if (tmp_str == NULL) {
87.206 - gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__,
87.207 - tmp_str->str);
87.208 - ret = FALSE;
87.209 - goto cleanup;
87.210 - }
87.211 -
87.212 - if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
87.213 - gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__,
87.214 - tmp_str->str);
87.215 - ret = FALSE;
87.216 - goto cleanup;
87.217 - }
87.218 -
87.219 - cleanup:
87.220 - g_mutex_unlock(recorder->mutex);
87.221 -
87.222 - g_string_free(tmp_str, TRUE);
87.223 - g_object_unref(str_list);
87.224 -
87.225 - return ret;
87.226 -}
87.227 -
87.228 -/**
87.229 - * Sends the SPAWN_LIVETV command through Mythtv protocol. This command
87.230 - * requests the backend to start capturing TV content, but it doesn't need
87.231 - * the TV chain ID.
87.232 - *
87.233 - * @param recorder The GMythRecorder instance.
87.234 - * @return true if success, false if any error happens.
87.235 - */
87.236 -gboolean
87.237 -gmyth_recorder_spawntv_no_tvchain(GMythRecorder * recorder)
87.238 -{
87.239 - GMythStringList *str_list;
87.240 - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
87.241 - gboolean ret = TRUE;
87.242 -
87.243 - gmyth_debug("[%s] Spawntv, no TV chain!", __FUNCTION__);
87.244 -
87.245 - str_list = gmyth_string_list_new();
87.246 -
87.247 - g_mutex_lock(recorder->mutex);
87.248 -
87.249 - g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
87.250 -
87.251 - gmyth_string_list_append_string(str_list, tmp_str);
87.252 - g_string_free(tmp_str, TRUE);
87.253 -
87.254 - gmyth_string_list_append_char_array(str_list, "SPAWN_LIVETV");
87.255 -
87.256 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
87.257 -
87.258 - tmp_str = gmyth_string_list_get_string(str_list, 0);
87.259 -
87.260 - if (tmp_str == NULL) {
87.261 - gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__,
87.262 - tmp_str->str);
87.263 - ret = FALSE;
87.264 - goto cleanup;
87.265 - }
87.266 -
87.267 - if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
87.268 - gmyth_debug("[%s] Spawntv request returned %s", __FUNCTION__,
87.269 - tmp_str->str);
87.270 - ret = FALSE;
87.271 - goto cleanup;
87.272 - }
87.273 -
87.274 - cleanup:
87.275 - g_mutex_unlock(recorder->mutex);
87.276 -
87.277 - g_string_free(tmp_str, TRUE);
87.278 - g_object_unref(str_list);
87.279 -
87.280 - return ret;
87.281 -}
87.282 -
87.283 -/** Sends the command STOP_LIVETV to Mythtv backend.
87.284 - *
87.285 - * @param recorder the GMythRecorder instance.
87.286 - * @return true if success, false if any error happens.
87.287 - */
87.288 -gboolean
87.289 -gmyth_recorder_stop_livetv(GMythRecorder * recorder)
87.290 -{
87.291 - GMythStringList *str_list;
87.292 - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
87.293 - gboolean ret = TRUE;
87.294 -
87.295 - gmyth_debug("[%s]", __FUNCTION__);
87.296 -
87.297 - str_list = gmyth_string_list_new();
87.298 -
87.299 - g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
87.300 -
87.301 - gmyth_string_list_append_string(str_list, tmp_str);
87.302 - g_string_free(tmp_str, TRUE);
87.303 -
87.304 - gmyth_string_list_append_char_array(str_list, "STOP_LIVETV");
87.305 -
87.306 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
87.307 -
87.308 - tmp_str = gmyth_string_list_get_string(str_list, 0);
87.309 -
87.310 - if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
87.311 - gmyth_debug("[%s] Stop livetv request returned %s", __FUNCTION__,
87.312 - tmp_str->str);
87.313 - ret = FALSE;
87.314 - goto cleanup;
87.315 - }
87.316 -
87.317 - cleanup:
87.318 - g_string_free(tmp_str, TRUE);
87.319 - g_object_unref(str_list);
87.320 -
87.321 - return ret;
87.322 -}
87.323 -
87.324 -/** Sends the FRONTEND_READY command through Mythtv protocol. This command
87.325 - * advertises the backend to start capturing TV content.
87.326 - *
87.327 - * @param recorder The GMythRecorder instance.
87.328 - * @return TRUE if success, FALSE if any error happens.
87.329 - */
87.330 -gboolean
87.331 -gmyth_recorder_send_frontend_ready_command(GMythRecorder * recorder)
87.332 -{
87.333 - GMythStringList *str_list;
87.334 - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
87.335 - gboolean ret = TRUE;
87.336 -
87.337 - gmyth_debug("[%s] FRONTEND_READY with recorder id = %d", __FUNCTION__,
87.338 - recorder->recorder_num);
87.339 -
87.340 - str_list = gmyth_string_list_new();
87.341 -
87.342 - g_mutex_lock(recorder->mutex);
87.343 -
87.344 - g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
87.345 -
87.346 - gmyth_string_list_append_string(str_list, tmp_str);
87.347 - g_string_free(tmp_str, TRUE);
87.348 -
87.349 - gmyth_string_list_append_char_array(str_list, "FRONTEND_READY");
87.350 -
87.351 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
87.352 -
87.353 - tmp_str = gmyth_string_list_get_string(str_list, 0);
87.354 -
87.355 - if (tmp_str == NULL) {
87.356 - gmyth_debug
87.357 - ("[%s] FRONTEND_READY command request couldn't returns, reason: %s",
87.358 - __FUNCTION__, tmp_str->str);
87.359 - ret = FALSE;
87.360 - goto cleanup;
87.361 - }
87.362 -
87.363 - if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
87.364 - gmyth_debug("[%s] FRONTEND_READY request returned %s",
87.365 - __FUNCTION__, tmp_str->str);
87.366 - ret = FALSE;
87.367 - goto cleanup;
87.368 - }
87.369 -
87.370 - cleanup:
87.371 - g_mutex_unlock(recorder->mutex);
87.372 - g_string_free(tmp_str, TRUE);
87.373 - g_object_unref(str_list);
87.374 -
87.375 - return ret;
87.376 -}
87.377 -
87.378 -/** Send a CHECK_CHANNEL command request to the backend, in order to find if a
87.379 - * certain channel actually exists.
87.380 - *
87.381 - * @param recorder The GMythRecorder instance.
87.382 - * @param channel The new channel to be checked (string format).
87.383 - * @return true if success, false if any error happens.
87.384 - */
87.385 -gboolean
87.386 -gmyth_recorder_check_channel_name(GMythRecorder * recorder,
87.387 - gchar * channel)
87.388 -{
87.389 - GMythStringList *str_list;
87.390 - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
87.391 - gboolean ret = TRUE;
87.392 -
87.393 - gmyth_debug("[%s] CHECK_CHANNEL with channel = %s", __FUNCTION__,
87.394 - channel);
87.395 -
87.396 - str_list = gmyth_string_list_new();
87.397 -
87.398 - g_mutex_lock(recorder->mutex);
87.399 -
87.400 - g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
87.401 -
87.402 - gmyth_string_list_append_string(str_list, tmp_str);
87.403 - g_string_free(tmp_str, TRUE);
87.404 -
87.405 - gmyth_string_list_append_char_array(str_list, "CHECK_CHANNEL");
87.406 -
87.407 - gmyth_string_list_append_char_array(str_list, channel);
87.408 -
87.409 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
87.410 -
87.411 - tmp_str = gmyth_string_list_get_string(str_list, 0);
87.412 -
87.413 - if (tmp_str == NULL) {
87.414 - gmyth_debug("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__,
87.415 - tmp_str->str);
87.416 - ret = FALSE;
87.417 - goto cleanup;
87.418 - }
87.419 -
87.420 - if (g_ascii_strncasecmp(tmp_str->str, "ok", 2) == 0
87.421 - || g_ascii_strncasecmp(tmp_str->str, "0", 1) == 0) {
87.422 - gmyth_debug("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__,
87.423 - tmp_str->str);
87.424 - ret = FALSE;
87.425 - goto cleanup;
87.426 - }
87.427 -
87.428 - cleanup:
87.429 - g_mutex_unlock(recorder->mutex);
87.430 - g_string_free(tmp_str, TRUE);
87.431 - g_object_unref(str_list);
87.432 -
87.433 - return ret;
87.434 -}
87.435 -
87.436 -/** Send a CHECK_CHANNEL command request to the backend, in order to find if a
87.437 - * certain channel actually exists.
87.438 - *
87.439 - * @param recorder The GMythRecorder instance.
87.440 - * @param channel The new channel to be checked (decimal integer value).
87.441 - * @return true if success, false if any error happens.
87.442 - */
87.443 -gboolean
87.444 -gmyth_recorder_check_channel(GMythRecorder * recorder, gint channel)
87.445 -{
87.446 - return gmyth_recorder_check_channel_name(recorder,
87.447 - g_strdup_printf("%d",
87.448 - channel));
87.449 -}
87.450 -
87.451 -/** Send a SET_CHANNEL command request to the backend, to start streaming on another
87.452 - * TV content channel.
87.453 - *
87.454 - * @param recorder The GMythRecorder instance.
87.455 - * @param channel The new channel to be loaded.
87.456 - * @return true if success, false if any error happens.
87.457 - */
87.458 -gboolean
87.459 -gmyth_recorder_set_channel(GMythRecorder * recorder, gint channel)
87.460 -{
87.461 - GMythStringList *str_list;
87.462 - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
87.463 - gboolean ret = TRUE;
87.464 -
87.465 - gmyth_debug("[%s] SET_CHANNEL with channel = %d", __FUNCTION__,
87.466 - channel);
87.467 -
87.468 - str_list = gmyth_string_list_new();
87.469 -
87.470 - g_mutex_lock(recorder->mutex);
87.471 -
87.472 - g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
87.473 -
87.474 - gmyth_string_list_append_string(str_list, tmp_str);
87.475 - g_string_free(tmp_str, TRUE);
87.476 -
87.477 - gmyth_string_list_append_char_array(str_list, "SET_CHANNEL");
87.478 -
87.479 - gmyth_string_list_append_int(str_list, channel);
87.480 -
87.481 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
87.482 -
87.483 - tmp_str = gmyth_string_list_get_string(str_list, 0);
87.484 -
87.485 - if (tmp_str == NULL) {
87.486 - gmyth_debug("[%s] SET_CHANNEL request returned %s", __FUNCTION__,
87.487 - tmp_str->str);
87.488 - ret = FALSE;
87.489 - goto cleanup;
87.490 - }
87.491 -
87.492 - if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
87.493 - gmyth_debug("[%s] SET_CHANNEL request returned %s", __FUNCTION__,
87.494 - tmp_str->str);
87.495 - ret = FALSE;
87.496 - goto cleanup;
87.497 - }
87.498 -
87.499 - cleanup:
87.500 - g_mutex_unlock(recorder->mutex);
87.501 - g_string_free(tmp_str, TRUE);
87.502 - g_object_unref(str_list);
87.503 -
87.504 - return ret;
87.505 -}
87.506 -
87.507 -/** Send a SET_CHANNEL command request to the backend, to start streaming on another
87.508 - * TV content channel.
87.509 - *
87.510 - * @param recorder The GMythRecorder instance.
87.511 - * @param channel The new channel to be loaded.
87.512 - * @return true if success, false if any error happens.
87.513 - */
87.514 -gboolean
87.515 -gmyth_recorder_set_channel_name(GMythRecorder * recorder,
87.516 - const gchar * channel)
87.517 -{
87.518 - GMythStringList *str_list;
87.519 - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
87.520 - gboolean ret = TRUE;
87.521 -
87.522 - gmyth_debug("[%s] SET_CHANNEL with channel name = %s", __FUNCTION__,
87.523 - channel);
87.524 -
87.525 - str_list = gmyth_string_list_new();
87.526 -
87.527 - g_mutex_lock(recorder->mutex);
87.528 -
87.529 - g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
87.530 -
87.531 - gmyth_string_list_append_string(str_list, tmp_str);
87.532 - g_string_free(tmp_str, TRUE);
87.533 -
87.534 - gmyth_string_list_append_char_array(str_list, "SET_CHANNEL");
87.535 - gmyth_string_list_append_char_array(str_list, channel);
87.536 -
87.537 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
87.538 -
87.539 - tmp_str = gmyth_string_list_get_string(str_list, 0);
87.540 -
87.541 - if (tmp_str == NULL) {
87.542 - gmyth_debug("[%s] SET_CHANNEL name request returned NULL!",
87.543 - __FUNCTION__);
87.544 - ret = FALSE;
87.545 - goto cleanup;
87.546 - }
87.547 -
87.548 - if (tmp_str != NULL && g_ascii_strncasecmp(tmp_str->str, "ok", 2)
87.549 - /*
87.550 - * || g_ascii_strtoull( tmp_str->str, NULL, 10 ) == 0
87.551 - */
87.552 - ) {
87.553 - g_warning("[%s] SET_CHANNEL name request returned not ok",
87.554 - __FUNCTION__);
87.555 - ret = FALSE;
87.556 - goto cleanup;
87.557 - }
87.558 -
87.559 - cleanup:
87.560 - g_mutex_unlock(recorder->mutex);
87.561 - g_string_free(tmp_str, TRUE);
87.562 - g_object_unref(str_list);
87.563 -
87.564 - return ret;
87.565 -}
87.566 -
87.567 -/**
87.568 - * Changes the channel of the actual Recorder.
87.569 - *
87.570 - * CHANNEL_DIRECTION_UP - Go up one channel in the listing
87.571 - *
87.572 - * CHANNEL_DIRECTION_DOWN - Go down one channel in the listing
87.573 - *
87.574 - * CHANNEL_DIRECTION_FAVORITE - Go to the next favorite channel
87.575 - *
87.576 - * CHANNEL_DIRECTION_SAME - Stay
87.577 - *
87.578 - * @param recorder The GMythRecorder instance.
87.579 - * @param direction The new channel direction where to move to.
87.580 - * @return true if success, false if any error happens.
87.581 - */
87.582 -gboolean
87.583 -gmyth_recorder_change_channel(GMythRecorder * recorder,
87.584 - const GMythRecorderChannelChangeDirection
87.585 - direction)
87.586 -{
87.587 - GMythStringList *str_list;
87.588 - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
87.589 - gboolean ret = TRUE;
87.590 -
87.591 - gmyth_debug("[%s] CHANGE_CHANNEL to the channel direction = %u",
87.592 - __FUNCTION__, direction);
87.593 -
87.594 - str_list = gmyth_string_list_new();
87.595 -
87.596 - g_mutex_lock(recorder->mutex);
87.597 -
87.598 - g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
87.599 -
87.600 - gmyth_string_list_append_string(str_list, tmp_str);
87.601 - g_string_free(tmp_str, TRUE);
87.602 -
87.603 - gmyth_string_list_append_char_array(str_list, "CHANGE_CHANNEL");
87.604 - gmyth_string_list_append_int(str_list, direction);
87.605 -
87.606 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
87.607 -
87.608 - tmp_str = gmyth_string_list_get_string(str_list, 0);
87.609 -
87.610 - if (tmp_str == NULL) {
87.611 - gmyth_debug("[%s] CHANGE_CHANNEL name request returned %s",
87.612 - __FUNCTION__, tmp_str->str);
87.613 - ret = FALSE;
87.614 - goto cleanup;
87.615 - }
87.616 -
87.617 - if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)
87.618 - || g_ascii_strtoull(tmp_str->str, NULL, 10) == 0) {
87.619 - gmyth_debug("[%s] CHANGE_CHANNEL name request returned %s",
87.620 - __FUNCTION__, tmp_str->str);
87.621 - ret = FALSE;
87.622 - goto cleanup;
87.623 - }
87.624 -
87.625 - cleanup:
87.626 - g_mutex_unlock(recorder->mutex);
87.627 - g_string_free(tmp_str, TRUE);
87.628 - g_object_unref(str_list);
87.629 -
87.630 - return ret;
87.631 -}
87.632 -
87.633 -/**
87.634 - * Gets the channel's list from the MythTV backend server.
87.635 - *
87.636 - * @param recorder The GMythRecorder instance.
87.637 - *
87.638 - * @return a GList* instance with all the channel names.
87.639 - */
87.640 -GList *
87.641 -gmyth_recorder_get_channel_list(GMythRecorder * recorder)
87.642 -{
87.643 -
87.644 - GList *channel_list = NULL;
87.645 - gchar *channel = NULL;
87.646 - guint i;
87.647 -
87.648 - for (i = 0; i < 1000; i++) {
87.649 - channel = g_strdup_printf("%u", i);
87.650 -
87.651 - if (gmyth_recorder_check_channel_name(recorder, channel)) {
87.652 - channel_list = g_list_append(channel_list, g_strdup(channel));
87.653 - }
87.654 -
87.655 - } /* for - channel list */
87.656 -
87.657 - g_free(channel);
87.658 -
87.659 - return channel_list;
87.660 -
87.661 -}
87.662 -
87.663 -/** Send a PAUSE command request to the backend, to pause streaming on another
87.664 - * TV content channel.
87.665 - *
87.666 - * @param recorder The GMythRecorder instance.
87.667 - * @return true if success, false if any error happens.
87.668 - */
87.669 -gboolean
87.670 -gmyth_recorder_pause_recording(GMythRecorder * recorder)
87.671 -{
87.672 - GMythStringList *str_list;
87.673 - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
87.674 - gboolean ret = TRUE;
87.675 -
87.676 - gmyth_debug("[%s] PAUSE", __FUNCTION__);
87.677 -
87.678 - str_list = gmyth_string_list_new();
87.679 -
87.680 - g_mutex_lock(recorder->mutex);
87.681 -
87.682 - g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
87.683 -
87.684 - gmyth_string_list_append_string(str_list, tmp_str);
87.685 - g_string_free(tmp_str, TRUE);
87.686 -
87.687 - gmyth_string_list_append_char_array(str_list, "PAUSE");
87.688 -
87.689 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
87.690 -
87.691 - tmp_str = gmyth_string_list_get_string(str_list, 0);
87.692 -
87.693 - if (tmp_str == NULL) {
87.694 - gmyth_debug("[%s] PAUSE name request returned %s", __FUNCTION__,
87.695 - tmp_str->str);
87.696 - ret = FALSE;
87.697 - goto cleanup;
87.698 - }
87.699 -
87.700 - if (g_ascii_strncasecmp(tmp_str->str, "ok", 2)) {
87.701 - gmyth_debug("[%s] PAUSE name request returned %s", __FUNCTION__,
87.702 - tmp_str->str);
87.703 - ret = FALSE;
87.704 - goto cleanup;
87.705 - }
87.706 -
87.707 - cleanup:
87.708 - g_mutex_unlock(recorder->mutex);
87.709 - g_string_free(tmp_str, TRUE);
87.710 - g_object_unref(str_list);
87.711 -
87.712 - return ret;
87.713 -}
87.714 -
87.715 -static gboolean
87.716 -gmyth_recorder_find_if_program_exists(GMythRecorder * recorder,
87.717 - GMythProgramInfo * prog)
87.718 -{
87.719 - GList *lst = NULL;
87.720 -
87.721 - g_return_val_if_fail(recorder != NULL
87.722 - && recorder->progs_info_list != NULL, FALSE);
87.723 -
87.724 - for (lst = recorder->progs_info_list; lst != NULL;
87.725 - lst = g_list_next(lst)) {
87.726 - gmyth_debug("Got program info from list = [%s]",
87.727 - gmyth_program_info_to_string((GMythProgramInfo *)
87.728 - lst->data));
87.729 - if (gmyth_program_info_is_equals
87.730 - (prog, (GMythProgramInfo *) lst->data))
87.731 - return TRUE;
87.732 - }
87.733 -
87.734 - return FALSE;
87.735 -}
87.736 -
87.737 -/**
87.738 - * Requests the actual program info from the MythTV backend server.
87.739 - *
87.740 - * @param recorder The GMythRecorder instance.
87.741 - * @return The actual program info.
87.742 - */
87.743 -GMythProgramInfo *
87.744 -gmyth_recorder_get_current_program_info(GMythRecorder * recorder)
87.745 -{
87.746 - GMythStringList *str_list = NULL;
87.747 - GMythProgramInfo *program_info = NULL;
87.748 - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
87.749 -
87.750 - str_list = gmyth_string_list_new();
87.751 -
87.752 - g_mutex_lock(recorder->mutex);
87.753 -
87.754 - g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
87.755 -
87.756 - gmyth_string_list_append_string(str_list, tmp_str);
87.757 -
87.758 - if (recorder->myth_socket->mythtv_version >= 26)
87.759 - gmyth_string_list_append_char_array(str_list,
87.760 - "GET_CURRENT_RECORDING");
87.761 - else
87.762 - gmyth_string_list_append_char_array(str_list, "GET_PROGRAM_INFO");
87.763 -
87.764 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
87.765 -
87.766 - if (str_list == NULL) {
87.767 - gmyth_debug
87.768 - ("[%s] GET_PROGRAM_INFO request returned. Error getting program info, string list equals to NULL!",
87.769 - __FUNCTION__);
87.770 - goto cleanup;
87.771 - }
87.772 -
87.773 - program_info = gmyth_program_info_from_string_list(str_list);
87.774 -
87.775 - if (NULL == program_info || NULL == program_info->pathname
87.776 - || program_info->pathname->len <= 0) {
87.777 - gmyth_debug
87.778 - ("GET_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!");
87.779 -
87.780 - if (program_info)
87.781 - g_object_unref(program_info);
87.782 -
87.783 - program_info = NULL;
87.784 -
87.785 - goto cleanup;
87.786 - }
87.787 -
87.788 - if (!gmyth_recorder_find_if_program_exists(recorder, program_info))
87.789 - recorder->progs_info_list =
87.790 - g_list_append(recorder->progs_info_list,
87.791 - g_object_ref(program_info));
87.792 - cleanup:
87.793 - g_mutex_unlock(recorder->mutex);
87.794 - g_string_free(tmp_str, TRUE);
87.795 - g_object_unref(str_list);
87.796 -
87.797 - return program_info;
87.798 -}
87.799 -
87.800 -/**
87.801 - * Requests the actual program info from the MythTV backend server.
87.802 - *
87.803 - * @param rec_id The GMythRecorder record number.
87.804 - * @return The GMythRecorder instance.
87.805 - */
87.806 -GMythRecorder *
87.807 -gmyth_recorder_get_recorder_from_num(gint rec_id)
87.808 -{
87.809 - GMythRecorder *recorder = NULL;
87.810 - GMythStringList *str_list;
87.811 - GString *tmp_str = g_string_new("GET_RECORDER_FROM_NUM");
87.812 - gint command_size = 0;
87.813 -
87.814 - gchar *recorder_host = NULL;
87.815 - gint recorder_port;
87.816 -
87.817 - str_list = gmyth_string_list_new();
87.818 -
87.819 - /*
87.820 - * g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
87.821 - */
87.822 -
87.823 - g_mutex_lock(recorder->mutex);
87.824 -
87.825 - gmyth_string_list_append_string(str_list, tmp_str);
87.826 -
87.827 - gmyth_string_list_append_int(str_list, rec_id);
87.828 -
87.829 - command_size =
87.830 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket,
87.831 - str_list);
87.832 -
87.833 - if (str_list == NULL) {
87.834 - gmyth_debug
87.835 - ("[%s] GET_RECORDER_FROM_NUM request returned. Error getting recorder number %d, it is equals to NULL!!!",
87.836 - __FUNCTION__, rec_id);
87.837 - return NULL;
87.838 - }
87.839 -
87.840 - if (command_size > 0) {
87.841 - recorder_host = gmyth_string_list_get_char_array(str_list, 0);
87.842 - recorder_port = gmyth_string_list_get_int(str_list, 1);
87.843 -
87.844 - if (g_strstr_len(recorder_host, strlen(recorder_host), "nohost")
87.845 - != NULL) {
87.846 - gmyth_debug
87.847 - ("No available recorder with the recorder ID number %d!",
87.848 - rec_id);
87.849 - } else {
87.850 -
87.851 - recorder = gmyth_recorder_new(rec_id,
87.852 - g_string_new(recorder_host),
87.853 - (gshort) recorder_port);
87.854 -
87.855 - if (NULL == recorder) {
87.856 - gmyth_debug
87.857 - ("[%s] GET_RECORDER_FROM_NUM request returned. Error getting recorder number %d, it is equals to NULL!!!",
87.858 - __FUNCTION__, rec_id);
87.859 - g_object_unref(recorder);
87.860 - return NULL;
87.861 - }
87.862 -
87.863 - }
87.864 -
87.865 - } else {
87.866 - gmyth_debug
87.867 - ("Cannot find a valuable recorder with the recorder ID number %d, backend server error!",
87.868 - rec_id);
87.869 - }
87.870 -
87.871 - g_mutex_unlock(recorder->mutex);
87.872 -
87.873 - g_object_unref(str_list);
87.874 -
87.875 - g_string_free(tmp_str, TRUE);
87.876 -
87.877 - g_free(recorder_host);
87.878 -
87.879 - return recorder;
87.880 -
87.881 -}
87.882 -
87.883 -/**
87.884 - * Requests the actual program info from the MythTV backend server.
87.885 - *
87.886 - * @param recorder The GMythRecorder instance.
87.887 - * @param direction The direction to move based on the current channel (forward, backward,
87.888 - * up, down).
87.889 - *
87.890 - * @return The GMythProgramInfo next program info instance.
87.891 - */
87.892 -GMythProgramInfo *
87.893 -gmyth_recorder_get_next_program_info(GMythRecorder * recorder,
87.894 - const GMythRecorderBrowseDirection
87.895 - direction)
87.896 -{
87.897 - GMythProgramInfo *actual_proginfo = NULL;
87.898 - GMythProgramInfo *program_info = NULL;
87.899 - GMythStringList *str_list;
87.900 - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
87.901 -
87.902 - gchar *date = NULL;
87.903 - struct tm *tm = NULL;
87.904 - time_t t;
87.905 -
87.906 - actual_proginfo = gmyth_recorder_get_current_program_info(recorder);
87.907 -
87.908 - str_list = gmyth_string_list_new();
87.909 -
87.910 - g_mutex_lock(recorder->mutex);
87.911 -
87.912 - g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
87.913 -
87.914 - t = time(NULL);
87.915 - tm = localtime(&t);
87.916 - date = g_strdup_printf("%.4d%.2d%.2d%.2d%.2d%.2d", tm->tm_year + 1900,
87.917 - tm->tm_mon + 1, tm->tm_mday, tm->tm_hour,
87.918 - tm->tm_min, tm->tm_sec);
87.919 -
87.920 - gmyth_string_list_append_string(str_list, tmp_str);
87.921 - gmyth_string_list_append_char_array(str_list, "GET_NEXT_PROGRAM_INFO");
87.922 - gmyth_string_list_append_string(str_list, actual_proginfo->channame);
87.923 - gmyth_string_list_append_int(str_list, actual_proginfo->channel_id);
87.924 - gmyth_string_list_append_int(str_list, direction);
87.925 - gmyth_string_list_append_char_array(str_list, date);
87.926 -
87.927 - if (gmyth_socket_sendreceive_stringlist
87.928 - (recorder->myth_socket, str_list)
87.929 - > 0) {
87.930 -
87.931 - if (str_list == NULL) {
87.932 - gmyth_debug
87.933 - ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!",
87.934 - __FUNCTION__);
87.935 - goto done;
87.936 - }
87.937 - program_info =
87.938 - gmyth_program_info_from_string_list_next_prog(str_list);
87.939 -
87.940 - if (NULL == program_info) {
87.941 - gmyth_debug
87.942 - ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting next program info, it is equals to NULL!!!",
87.943 - __FUNCTION__);
87.944 - g_object_unref(program_info);
87.945 - goto done;
87.946 - }
87.947 -
87.948 - if ( /* ( program_info->chanid != NULL &&
87.949 - * strlen( program_info->chanid->str ) > 0
87.950 - * * * * * * ) && */
87.951 - (program_info->chansign != NULL
87.952 - && strlen(program_info->chansign->str) > 0)) {
87.953 - gmyth_debug("OK!!! Got the next program info... [%s].",
87.954 - program_info->chansign->str);
87.955 - } else {
87.956 - gmyth_debug
87.957 - ("GET_NEXT_PROGRAM_INFO request returned. Error getting next program info, it is equals to NULL!!!");
87.958 - g_object_unref(program_info);
87.959 - program_info = NULL;
87.960 - }
87.961 -
87.962 - }
87.963 - /*
87.964 - * if
87.965 - */
87.966 - done:
87.967 -
87.968 - g_mutex_unlock(recorder->mutex);
87.969 -
87.970 - if (actual_proginfo != NULL)
87.971 - g_object_unref(actual_proginfo);
87.972 -
87.973 - if (str_list != NULL)
87.974 - g_object_unref(str_list);
87.975 -
87.976 - if (tmp_str != NULL)
87.977 - g_string_free(tmp_str, TRUE);
87.978 -
87.979 - if (date != NULL)
87.980 - g_free(date);
87.981 - // if ( tm != NULL)
87.982 - // g_free (tm);
87.983 -
87.984 - return program_info;
87.985 -}
87.986 -
87.987 -/**
87.988 - * Requests the program info from the MythTV backend server, based on its
87.989 - * channel name.
87.990 - *
87.991 - * @param recorder The GMythRecorder instance.
87.992 - * @return The GMythProgramInfo next program info instance.
87.993 - */
87.994 -GMythProgramInfo *
87.995 -gmyth_recorder_get_program_info_from_channel_name(GMythRecorder * recorder,
87.996 - const gchar * channel)
87.997 -{
87.998 - // GMythProgramInfo* actual_proginfo= NULL;
87.999 - GMythProgramInfo *program_info = NULL;
87.1000 - GMythStringList *str_list;
87.1001 - GString *tmp_str = g_string_new(GMYTHTV_RECORDER_HEADER);
87.1002 -
87.1003 - /*
87.1004 - * gchar *date = NULL; struct tm *tm = NULL; time_t t;
87.1005 - *
87.1006 - * actual_proginfo =
87.1007 - * gmyth_recorder_get_current_program_info(recorder);
87.1008 - */
87.1009 -
87.1010 - str_list = gmyth_string_list_new();
87.1011 -
87.1012 - g_mutex_lock(recorder->mutex);
87.1013 -
87.1014 - g_string_append_printf(tmp_str, " %d", recorder->recorder_num);
87.1015 -
87.1016 - /*
87.1017 - * t = time(NULL); tm = localtime(&t); date =
87.1018 - * g_strdup_printf("%.4d%.2d%.2d%.2d%.2d%.2d", tm->tm_year + 1900,
87.1019 - * tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
87.1020 - */
87.1021 -
87.1022 - gmyth_string_list_append_string(str_list, tmp_str);
87.1023 - gmyth_string_list_append_char_array(str_list, "GET_NEXT_PROGRAM_INFO");
87.1024 - gmyth_string_list_append_char_array(str_list, channel);
87.1025 - gmyth_string_list_append_char_array(str_list, "0");
87.1026 - gmyth_string_list_append_int(str_list, BROWSE_DIRECTION_UP);
87.1027 - gmyth_string_list_append_char_array(str_list, "0");
87.1028 -
87.1029 - do {
87.1030 -
87.1031 - if (str_list != NULL &&
87.1032 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket,
87.1033 - str_list) > 0) {
87.1034 -
87.1035 - if (str_list == NULL) {
87.1036 - gmyth_debug
87.1037 - ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!",
87.1038 - __FUNCTION__);
87.1039 - goto done;
87.1040 - }
87.1041 - program_info =
87.1042 - gmyth_program_info_from_string_list_next_prog(str_list);
87.1043 -
87.1044 - if (NULL == program_info) {
87.1045 - gmyth_debug
87.1046 - ("[%s] GET_NEXT_PROGRAM_INFO request returned. Error getting next program info, it is equals to NULL!!!",
87.1047 - __FUNCTION__);
87.1048 - g_object_unref(program_info);
87.1049 - goto done;
87.1050 - }
87.1051 -
87.1052 - if ( /* ( program_info->chanid != NULL &&
87.1053 - * strlen( program_info->chanid->str ) > 0
87.1054 - * * * * * * ) && */
87.1055 - (program_info->chansign != NULL
87.1056 - && strlen(program_info->chansign->str) > 0)) {
87.1057 - gmyth_debug("OK!!! Got the next program info... [%s].",
87.1058 - program_info->chansign->str);
87.1059 - } else {
87.1060 - gmyth_debug
87.1061 - ("GET_NEXT_PROGRAM_INFO request returned. Error getting "
87.1062 - "next program info, it is equals to NULL!!!");
87.1063 - g_object_unref(program_info);
87.1064 - program_info = NULL;
87.1065 - }
87.1066 -
87.1067 - }
87.1068 - /*
87.1069 - * if
87.1070 - */
87.1071 - }
87.1072 - while (str_list != NULL);
87.1073 -
87.1074 - done:
87.1075 -
87.1076 - g_mutex_unlock(recorder->mutex);
87.1077 -
87.1078 - if (str_list != NULL)
87.1079 - g_object_unref(str_list);
87.1080 -
87.1081 - if (tmp_str != NULL)
87.1082 - g_string_free(tmp_str, TRUE);
87.1083 -
87.1084 - return program_info;
87.1085 -}
87.1086 -
87.1087 -/**
87.1088 - * Requests the actual remote file position on a LiveTV instance.
87.1089 - *
87.1090 - * @param recorder The GMythRecorder instance.
87.1091 - *
87.1092 - * @return The position, in bytes, of the offset to the read header.
87.1093 - */
87.1094 -gint64
87.1095 -gmyth_recorder_get_file_position(GMythRecorder * recorder)
87.1096 -{
87.1097 - gint64 pos = 0;
87.1098 - GString *query = g_string_new(GMYTHTV_RECORDER_HEADER);
87.1099 -
87.1100 - GMythStringList *str_list = gmyth_string_list_new();
87.1101 -
87.1102 - g_mutex_lock(recorder->mutex);
87.1103 -
87.1104 - g_string_append_printf(query, " %d", recorder->recorder_num);
87.1105 -
87.1106 - gmyth_string_list_append_string(str_list, query);
87.1107 - gmyth_string_list_append_char_array(str_list, "GET_FILE_POSITION");
87.1108 -
87.1109 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
87.1110 -
87.1111 - if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
87.1112 - GString *str = NULL;
87.1113 -
87.1114 - if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL
87.1115 - && strstr(str->str, "bad") == NULL)
87.1116 - pos = gmyth_string_list_get_int64(str_list, 0);
87.1117 - g_string_free(str, TRUE);
87.1118 - }
87.1119 -#ifndef GMYTHTV_ENABLE_DEBUG
87.1120 - gmyth_debug("[%s] Got file position = %lld\n", __FUNCTION__, pos);
87.1121 -#endif
87.1122 -
87.1123 - g_mutex_unlock(recorder->mutex);
87.1124 -
87.1125 - if (str_list != NULL)
87.1126 - g_object_unref(str_list);
87.1127 -
87.1128 - g_string_free(query, TRUE);
87.1129 -
87.1130 - return pos;
87.1131 -}
87.1132 -
87.1133 -/**
87.1134 - * Asks MythTV backend server about if it started to record the remote file.
87.1135 - *
87.1136 - * @param recorder The GMythRecorder instance.
87.1137 - *
87.1138 - * @return <code>true</code>, if the actual remote file is bein recorded.
87.1139 - */
87.1140 -gboolean
87.1141 -gmyth_recorder_is_recording(GMythRecorder * recorder)
87.1142 -{
87.1143 - gboolean ret = TRUE;
87.1144 -
87.1145 - g_return_val_if_fail(recorder != NULL, FALSE);
87.1146 -
87.1147 - GMythStringList *str_list = gmyth_string_list_new();
87.1148 - GString *message = g_string_new("");
87.1149 -
87.1150 - g_mutex_lock(recorder->mutex);
87.1151 -
87.1152 - g_string_printf(message, "%s %d", GMYTHTV_RECORDER_HEADER,
87.1153 - recorder->recorder_num);
87.1154 - gmyth_string_list_append_string(str_list, message);
87.1155 - gmyth_string_list_append_char_array(str_list, "IS_RECORDING");
87.1156 -
87.1157 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
87.1158 -
87.1159 - if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
87.1160 - GString *str = NULL;
87.1161 -
87.1162 - if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL
87.1163 - && strcmp(str->str, "bad") != 0) {
87.1164 - gint is_rec =
87.1165 - gmyth_string_list_get_int(str_list, 0);
87.1166 -
87.1167 - if (is_rec != 0)
87.1168 - ret = TRUE;
87.1169 - else
87.1170 - ret = FALSE;
87.1171 - }
87.1172 - g_string_free(str, TRUE);
87.1173 - }
87.1174 -
87.1175 - gmyth_debug("%s, stream is %s being recorded!\n", ret ? "YES" : "NO",
87.1176 - ret ? "" : "NOT");
87.1177 - // g_static_mutex_unlock (&mutex);
87.1178 -
87.1179 - g_mutex_unlock(recorder->mutex);
87.1180 -
87.1181 - if (str_list != NULL)
87.1182 - g_object_unref(str_list);
87.1183 -
87.1184 - g_string_free(message, TRUE);
87.1185 -
87.1186 - return ret;
87.1187 -
87.1188 -}
87.1189 -
87.1190 -/**
87.1191 - * Finish remote file recording process.
87.1192 - *
87.1193 - * @param recorder The GMythRecorder instance.
87.1194 - *
87.1195 - * @return <code>true</code>, if the recording had been actually closed.
87.1196 - */
87.1197 -gboolean
87.1198 -gmyth_recorder_finish_recording(GMythRecorder * recorder)
87.1199 -{
87.1200 - gboolean ret = TRUE;
87.1201 -
87.1202 - g_return_val_if_fail(recorder != NULL, FALSE);
87.1203 -
87.1204 - GMythStringList *str_list = gmyth_string_list_new();
87.1205 - GString *message = g_string_new("");
87.1206 -
87.1207 - g_string_printf(message, "%s %d", GMYTHTV_RECORDER_HEADER,
87.1208 - recorder->recorder_num);
87.1209 - gmyth_string_list_append_string(str_list, message);
87.1210 - gmyth_string_list_append_char_array(str_list, "FINISH_RECORDING");
87.1211 -
87.1212 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
87.1213 -
87.1214 - if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
87.1215 - GString *str = NULL;
87.1216 -
87.1217 - if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL &&
87.1218 - strcmp(str->str, "ok") != 0) {
87.1219 - gint is_rec =
87.1220 - gmyth_string_list_get_int(str_list, 0);
87.1221 -
87.1222 - if (is_rec != 0)
87.1223 - ret = TRUE;
87.1224 - else
87.1225 - ret = FALSE;
87.1226 - }
87.1227 - g_string_free(str, TRUE);
87.1228 - }
87.1229 -
87.1230 - gmyth_debug("%s, stream is %s finished!\n", ret ? "YES" : "NO",
87.1231 - ret ? "" : "NOT");
87.1232 - // g_static_mutex_unlock (&mutex);
87.1233 -
87.1234 - if (str_list != NULL)
87.1235 - g_object_unref(str_list);
87.1236 -
87.1237 - g_string_free(message, TRUE);
87.1238 -
87.1239 - return ret;
87.1240 -}
87.1241 -
87.1242 -
87.1243 -/**
87.1244 - * Stops playing the remote file.
87.1245 - *
87.1246 - * @param recorder The GMythRecorder instance.
87.1247 - *
87.1248 - * @return <code>true</code>, if the recording had been actually stopped.
87.1249 - */
87.1250 -gboolean
87.1251 -gmyth_recorder_stop_playing(GMythRecorder * recorder)
87.1252 -{
87.1253 - gboolean ret = TRUE;
87.1254 -
87.1255 - g_return_val_if_fail(recorder != NULL, FALSE);
87.1256 -
87.1257 - GMythStringList *str_list = gmyth_string_list_new();
87.1258 - GString *message = g_string_new("");
87.1259 -
87.1260 - g_string_printf(message, "%s %d", GMYTHTV_RECORDER_HEADER,
87.1261 - recorder->recorder_num);
87.1262 - gmyth_string_list_append_string(str_list, message);
87.1263 - gmyth_string_list_append_char_array(str_list, "STOP_PLAYING");
87.1264 -
87.1265 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
87.1266 -
87.1267 - if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
87.1268 - GString *str = NULL;
87.1269 -
87.1270 - if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL &&
87.1271 - strcmp(str->str, "ok") != 0) {
87.1272 - gint is_rec =
87.1273 - gmyth_string_list_get_int(str_list, 0);
87.1274 -
87.1275 - if (is_rec != 0)
87.1276 - ret = TRUE;
87.1277 - else
87.1278 - ret = FALSE;
87.1279 - }
87.1280 - g_string_free(str, TRUE);
87.1281 - }
87.1282 -
87.1283 - gmyth_debug("%s, stream is %s stopped!\n", ret ? "YES" : "NO",
87.1284 - ret ? "" : "NOT");
87.1285 -
87.1286 - if (str_list != NULL)
87.1287 - g_object_unref(str_list);
87.1288 -
87.1289 - g_string_free(message, TRUE);
87.1290 -
87.1291 - return ret;
87.1292 -}
87.1293 -
87.1294 -/**
87.1295 - * Free the tuner responsible for recording this channel.
87.1296 - *
87.1297 - * @param recorder The GMythRecorder instance.
87.1298 - *
87.1299 - * @return <code>true</code>, if the tuner had been freed.
87.1300 - */
87.1301 -gboolean
87.1302 -gmyth_recorder_free_tuner(GMythRecorder * recorder)
87.1303 -{
87.1304 - gboolean ret = TRUE;
87.1305 -
87.1306 - g_return_val_if_fail(recorder != NULL, FALSE);
87.1307 -
87.1308 - GMythStringList *str_list = gmyth_string_list_new();
87.1309 - GString *message = g_string_new("");
87.1310 -
87.1311 - g_string_printf(message, "%s %d", "FREE_TUNER",
87.1312 - recorder->recorder_num);
87.1313 - gmyth_string_list_append_string(str_list, message);
87.1314 -
87.1315 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
87.1316 -
87.1317 - if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
87.1318 - GString *str = NULL;
87.1319 -
87.1320 - if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL &&
87.1321 - g_ascii_strncasecmp(str->str, "ok", 2) != 0) {
87.1322 - gint is_rec =
87.1323 - gmyth_string_list_get_int(str_list, 0);
87.1324 -
87.1325 - if (is_rec != 0)
87.1326 - ret = TRUE;
87.1327 - else
87.1328 - ret = FALSE;
87.1329 - }
87.1330 - g_string_free(str, TRUE);
87.1331 - }
87.1332 -
87.1333 - gmyth_debug("%s, tuner is %s freed!\n", ret ? "YES" : "NO",
87.1334 - ret ? "" : "NOT");
87.1335 -
87.1336 - if (str_list != NULL)
87.1337 - g_object_unref(str_list);
87.1338 -
87.1339 - g_string_free(message, TRUE);
87.1340 -
87.1341 - return ret;
87.1342 -}
87.1343 -
87.1344 -/**
87.1345 - * Asks the MythTV backend server about the frame rate
87.1346 - * of this LiveTV instance.
87.1347 - *
87.1348 - * @param recorder The GMythRecorder instance.
87.1349 - *
87.1350 - * @return The framerate (double value) of the current video.
87.1351 - */
87.1352 -gdouble
87.1353 -gmyth_recorder_get_framerate(GMythRecorder * recorder)
87.1354 -{
87.1355 - gdouble fr = 0.0f;
87.1356 - GString *query = g_string_new(GMYTHTV_RECORDER_HEADER);
87.1357 -
87.1358 - GMythStringList *str_list = gmyth_string_list_new();
87.1359 -
87.1360 - g_mutex_lock(recorder->mutex);
87.1361 -
87.1362 - g_string_append_printf(query, " %d", recorder->recorder_num);
87.1363 -
87.1364 - gmyth_string_list_append_string(str_list, query);
87.1365 - gmyth_string_list_append_char_array(str_list, "GET_FRAMERATE");
87.1366 -
87.1367 - gmyth_socket_sendreceive_stringlist(recorder->myth_socket, str_list);
87.1368 -
87.1369 - if (str_list != NULL && gmyth_string_list_length(str_list) > 0) {
87.1370 - GString *str = NULL;
87.1371 -
87.1372 - if ((str = gmyth_string_list_get_string(str_list, 0)) != NULL
87.1373 - && strstr(str->str, "bad") == NULL)
87.1374 - fr = g_ascii_strtod(str->str, NULL);
87.1375 -
87.1376 - g_string_free(str, TRUE);
87.1377 - }
87.1378 -#ifndef GMYTHTV_ENABLE_DEBUG
87.1379 - gmyth_debug("[%s] Got file position = %f\n", __FUNCTION__, fr);
87.1380 -#endif
87.1381 -
87.1382 - g_mutex_unlock(recorder->mutex);
87.1383 -
87.1384 - if (str_list != NULL)
87.1385 - g_object_unref(str_list);
87.1386 -
87.1387 - g_string_free(query, TRUE);
87.1388 -
87.1389 - return fr;
87.1390 -
87.1391 -}
88.1 --- a/gmyth/src/gmyth_recorder.h Mon Feb 25 17:45:36 2008 +0000
88.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
88.3 @@ -1,162 +0,0 @@
88.4 -/**
88.5 - * GMyth Library
88.6 - *
88.7 - * @file gmyth/gmyth_recorder.h
88.8 - *
88.9 - * @brief <p> GMythRecorder defines functions for playing live tv.
88.10 - *
88.11 - * The remote encoder is used by gmyth_tvplayer to setup livetv.
88.12 - *
88.13 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
88.14 - * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
88.15 - * @author Rosfran Borges <rosfran.borges@indt.org.br>
88.16 - *
88.17 - *
88.18 - * This program is free software; you can redistribute it and/or modify
88.19 - * it under the terms of the GNU Lesser General Public License as published by
88.20 - * the Free Software Foundation; either version 2 of the License, or
88.21 - * (at your option) any later version.
88.22 - *
88.23 - * This program is distributed in the hope that it will be useful,
88.24 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
88.25 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
88.26 - * GNU General Public License for more details.
88.27 - *
88.28 - * You should have received a copy of the GNU Lesser General Public License
88.29 - * along with this program; if not, write to the Free Software
88.30 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
88.31 - */
88.32 -
88.33 -#ifndef __GMYTH_RECORDER_H__
88.34 -#define __GMYTH_RECORDER_H__
88.35 -
88.36 -#include <glib-object.h>
88.37 -
88.38 -#include "gmyth_socket.h"
88.39 -#include "gmyth_programinfo.h"
88.40 -
88.41 -#include <stdio.h>
88.42 -#include <stdlib.h>
88.43 -#include <string.h>
88.44 -#include <netdb.h>
88.45 -#include <sys/socket.h>
88.46 -#include <unistd.h>
88.47 -
88.48 -G_BEGIN_DECLS
88.49 -#define GMYTH_RECORDER_TYPE (gmyth_recorder_get_type ())
88.50 -#define GMYTH_RECORDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_RECORDER_TYPE, GMythRecorder))
88.51 -#define GMYTH_RECORDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECORDER_TYPE, GMythRecorderClass))
88.52 -#define IS_GMYTH_RECORDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_RECORDER_TYPE))
88.53 -#define IS_GMYTH_RECORDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECORDER_TYPE))
88.54 -#define GMYTH_RECORDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_RECORDER_TYPE, GMythRecorderClass))
88.55 -typedef struct _GMythRecorder GMythRecorder;
88.56 -typedef struct _GMythRecorderClass GMythRecorderClass;
88.57 -
88.58 -struct _GMythRecorderClass {
88.59 - GObjectClass parent_class;
88.60 -
88.61 - /*
88.62 - * callbacks
88.63 - */
88.64 - /*
88.65 - * no one for now
88.66 - */
88.67 -};
88.68 -
88.69 -struct _GMythRecorder {
88.70 - GObject parent;
88.71 -
88.72 - /*
88.73 - * socket descriptor
88.74 - */
88.75 - GMythSocket *myth_socket;
88.76 -
88.77 - gint recorder_num;
88.78 - GString *hostname;
88.79 - gint port;
88.80 -
88.81 - GList *progs_info_list;
88.82 -
88.83 - GMutex *mutex;
88.84 -};
88.85 -
88.86 -typedef enum _GMythRecorderChannelChangeDirection {
88.87 - CHANNEL_DIRECTION_UP = 0,
88.88 - CHANNEL_DIRECTION_DOWN,
88.89 - CHANNEL_DIRECTION_FAVORITE,
88.90 - CHANNEL_DIRECTION_SAME
88.91 -} GMythRecorderChannelChangeDirection;
88.92 -
88.93 -typedef enum _GMythRecorderBrowseDirection {
88.94 - BROWSE_DIRECTION_SAME = 0, /* Stay in the same place */
88.95 - BROWSE_DIRECTION_UP, /* Move up one slot (down one channel) */
88.96 - BROWSE_DIRECTION_DOWN, /* Move down one slot (up one channel) */
88.97 - BROWSE_DIRECTION_LEFT, /* Move left one slot (down one time slot)
88.98 - */
88.99 - BROWSE_DIRECTION_RIGHT, /* Move right one slot (up one time slot) */
88.100 - BROWSE_DIRECTION_FAVORITE /* Move to the next favorite slot */
88.101 -} GMythRecorderBrowseDirection;
88.102 -
88.103 -GType gmyth_recorder_get_type(void);
88.104 -
88.105 -GMythRecorder *gmyth_recorder_new(int num, GString * hostname,
88.106 - gshort port);
88.107 -
88.108 -void gmyth_recorder_close(GMythRecorder * recorder);
88.109 -
88.110 -gboolean gmyth_recorder_setup(GMythRecorder * recorder);
88.111 -gboolean gmyth_recorder_spawntv(GMythRecorder * recorder,
88.112 - GString * tvchain_id);
88.113 -
88.114 -gboolean gmyth_recorder_spawntv_no_tvchain(GMythRecorder *
88.115 - recorder);
88.116 -
88.117 -gboolean gmyth_recorder_stop_livetv(GMythRecorder * recorder);
88.118 -
88.119 -gboolean gmyth_recorder_send_frontend_ready_command(GMythRecorder *
88.120 - recorder);
88.121 -
88.122 -gboolean gmyth_recorder_check_channel(GMythRecorder * recorder,
88.123 - gint channel);
88.124 -
88.125 -gboolean gmyth_recorder_check_channel_name(GMythRecorder * recorder,
88.126 - gchar * channel);
88.127 -
88.128 -gboolean gmyth_recorder_set_channel(GMythRecorder * recorder,
88.129 - gint channel);
88.130 -
88.131 -gboolean gmyth_recorder_set_channel_name(GMythRecorder * recorder,
88.132 - const gchar * channel);
88.133 -
88.134 -gboolean gmyth_recorder_change_channel(GMythRecorder * recorder, const
88.135 - GMythRecorderChannelChangeDirection
88.136 - direction);
88.137 -
88.138 -GList *gmyth_recorder_get_channel_list(GMythRecorder * recorder);
88.139 -
88.140 -gboolean gmyth_recorder_pause_recording(GMythRecorder * recorder);
88.141 -
88.142 -GMythProgramInfo *gmyth_recorder_get_current_program_info(GMythRecorder *
88.143 - recorder);
88.144 -
88.145 -GMythProgramInfo *gmyth_recorder_get_next_program_info(GMythRecorder *
88.146 - recorder, const
88.147 - GMythRecorderBrowseDirection
88.148 - direction);
88.149 -
88.150 -GMythRecorder *gmyth_recorder_get_recorder_from_num(gint rec_id);
88.151 -
88.152 -gint64 gmyth_recorder_get_file_position(GMythRecorder * recorder);
88.153 -
88.154 -gboolean gmyth_recorder_is_recording(GMythRecorder * recorder);
88.155 -
88.156 -gboolean gmyth_recorder_finish_recording(GMythRecorder * recorder);
88.157 -
88.158 -gboolean gmyth_recorder_stop_playing(GMythRecorder * recorder);
88.159 -
88.160 -gboolean gmyth_recorder_free_tuner(GMythRecorder * recorder);
88.161 -
88.162 -gdouble gmyth_recorder_get_framerate(GMythRecorder * recorder);
88.163 -
88.164 -G_END_DECLS
88.165 -#endif /* __GMYTH_REMOTE_ENCODER_H__ */
89.1 --- a/gmyth/src/gmyth_recprofile.c Mon Feb 25 17:45:36 2008 +0000
89.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
89.3 @@ -1,264 +0,0 @@
89.4 -/**
89.5 - * GMyth Library
89.6 - *
89.7 - * @file gmyth/gmyth_recprofile.c
89.8 - *
89.9 - * @brief <p> This file contains the recprofile class.
89.10 - *
89.11 - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
89.12 - * @author Artur Duque de Souza <artur.souza@indt.org.br>
89.13 - *
89.14 - * This program is free software; you can redistribute it and/or modify
89.15 - * it under the terms of the GNU Lesser General Public License as published by
89.16 - * the Free Software Foundation; either version 2 of the License, or
89.17 - * (at your option) any later version.
89.18 - *
89.19 - * This program is distributed in the hope that it will be useful,
89.20 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
89.21 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
89.22 - * GNU General Public License for more details.
89.23 - *
89.24 - * You should have received a copy of the GNU Lesser General Public License
89.25 - * along with this program; if not, write to the Free Software
89.26 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
89.27 - */
89.28 -
89.29 -
89.30 -#ifdef HAVE_CONFIG_H
89.31 -#include "config.h"
89.32 -#endif
89.33 -
89.34 -#include <stdlib.h>
89.35 -#include <string.h>
89.36 -#include <assert.h>
89.37 -
89.38 -#include "gmyth_recprofile.h"
89.39 -#include "gmyth_util.h"
89.40 -#include "gmyth_debug.h"
89.41 -#include "gmyth_http.h"
89.42 -
89.43 -static void gmyth_recprofile_class_init(GMythRecProfileClass * klass);
89.44 -static void gmyth_recprofile_init(GMythRecProfile * object);
89.45 -
89.46 -static void gmyth_recprofile_dispose(GObject * object);
89.47 -static void gmyth_recprofile_finalize(GObject * object);
89.48 -
89.49 -G_DEFINE_TYPE(GMythRecProfile, gmyth_recprofile, G_TYPE_OBJECT)
89.50 - static void gmyth_recprofile_class_init(GMythRecProfileClass *
89.51 - klass)
89.52 -{
89.53 - GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
89.54 -
89.55 - gobject_class->dispose = gmyth_recprofile_dispose;
89.56 - gobject_class->finalize = gmyth_recprofile_finalize;
89.57 -}
89.58 -
89.59 -static void
89.60 -gmyth_recprofile_init(GMythRecProfile * recprofile)
89.61 -{
89.62 -}
89.63 -
89.64 -static void
89.65 -gmyth_recprofile_dispose(GObject * object)
89.66 -{
89.67 - GMythRecProfile *recprofile = GMYTH_RECPROFILE(object);
89.68 -
89.69 - if (recprofile->name)
89.70 - g_free(recprofile->name);
89.71 -
89.72 - if (recprofile->group)
89.73 - g_free(recprofile->group);
89.74 -
89.75 - if (recprofile->vcodec)
89.76 - g_free(recprofile->vcodec);
89.77 -
89.78 - if (recprofile->acodec)
89.79 - g_free(recprofile->acodec);
89.80 -
89.81 - if (recprofile->options)
89.82 - g_free(recprofile->options);
89.83 -
89.84 - G_OBJECT_CLASS(gmyth_recprofile_parent_class)->dispose(object);
89.85 -}
89.86 -
89.87 -static void
89.88 -gmyth_recprofile_finalize(GObject * object)
89.89 -{
89.90 - g_signal_handlers_destroy(object);
89.91 - G_OBJECT_CLASS(gmyth_recprofile_parent_class)->finalize(object);
89.92 -}
89.93 -
89.94 -/**
89.95 - * Creates a new instance of GMythRecProfile.
89.96 - *
89.97 - * @return a new instance of GMythRecProfile.
89.98 - **/
89.99 -GMythRecProfile *
89.100 -gmyth_recprofile_new(void)
89.101 -{
89.102 - GMythRecProfile *recprofile = GMYTH_RECPROFILE
89.103 - (g_object_new(GMYTH_RECPROFILE_TYPE, NULL));
89.104 -
89.105 - recprofile->id = 0;
89.106 - recprofile->name = NULL;
89.107 - recprofile->group = NULL;
89.108 - recprofile->vcodec = NULL;
89.109 - recprofile->acodec = NULL;
89.110 - recprofile->options = NULL;
89.111 -
89.112 - return recprofile;
89.113 -}
89.114 -
89.115 -
89.116 -/**
89.117 - *
89.118 - * gmyth_recprofile_get_profile_list
89.119 - * @brief get profile list from the backend
89.120 - * @param backend_info GMythBackendInfo*
89.121 - * @return GSList
89.122 - *
89.123 - **/
89.124 -GSList *
89.125 -gmyth_recprofile_get_profile_list(GMythBackendInfo * backend_info)
89.126 -{
89.127 - return gmyth_http_retrieve_rec_profiles(backend_info, "Transcoders");
89.128 -}
89.129 -
89.130 -/**
89.131 - *
89.132 - * gmyth_recprofile_create_profile
89.133 - * @brief get profile list from the backend
89.134 - * @param backend_info GMythBackendInfo*
89.135 - * @param profile GMythRecProfile*
89.136 - * @return gint representing the result
89.137 - *
89.138 - **/
89.139 -gint
89.140 -gmyth_recprofile_create_profile(GMythBackendInfo * backend_info,
89.141 - GMythRecProfile * profile)
89.142 -{
89.143 - return gmyth_http_create_rec_profile(backend_info, profile);
89.144 -}
89.145 -
89.146 -/**
89.147 - *
89.148 - * gmyth_recprofile_del_profile
89.149 - * @brief del profile from the backend
89.150 - * @param backend_info GMythBackendInfo*
89.151 - * @param id profile's id
89.152 - * @return gint representing the result
89.153 - *
89.154 - **/
89.155 -gint
89.156 -gmyth_recprofile_del_profile_list(GMythBackendInfo * backend_info, gint id)
89.157 -{
89.158 - return gmyth_http_del_rec_profile(backend_info, id);
89.159 -}
89.160 -
89.161 -/**
89.162 - *
89.163 - * gmyth_recprofile_set_id
89.164 - * @brief set recprofile's id
89.165 - * @param rec GMythRecProfile*
89.166 - * @param id profile's id
89.167 - * @return gint representing the result
89.168 - *
89.169 - **/
89.170 -gint
89.171 -gmyth_recprofile_set_id(GMythRecProfile * rec, gint id)
89.172 -{
89.173 - rec->id = id;
89.174 - return 0;
89.175 -}
89.176 -
89.177 -/**
89.178 - *
89.179 - * gmyth_recprofile_set
89.180 - * @brief set recprofile's property
89.181 - * @param rec GMythRecProfile*
89.182 - * @param member the member you want to modify
89.183 - * @param value the value
89.184 - * @return gint representing the result
89.185 - *
89.186 - **/
89.187 -gint
89.188 -gmyth_recprofile_set(GMythRecProfile * rec, gchar * member, gchar * value)
89.189 -{
89.190 - int ret = 0;
89.191 -
89.192 - if (value != NULL) {
89.193 - if (g_ascii_strcasecmp(member, "name") == 0)
89.194 - rec->name = g_strndup(value, strlen(value));
89.195 - else if (g_ascii_strcasecmp(member, "group") == 0)
89.196 - rec->group = g_strndup(value, strlen(value));
89.197 - else if (g_ascii_strcasecmp(member, "vcodec") == 0)
89.198 - rec->vcodec = g_strndup(value, strlen(value));
89.199 - else if (g_ascii_strcasecmp(member, "acodec") == 0)
89.200 - rec->acodec = g_strndup(value, strlen(value));
89.201 - else
89.202 - ret = -1;
89.203 - } else
89.204 - ret = -1;
89.205 -
89.206 - return ret;
89.207 -}
89.208 -
89.209 -/**
89.210 - *
89.211 - * gmyth_recprofile_set_name
89.212 - * @brief set recprofile's name
89.213 - * @param rec GMythRecProfile*
89.214 - * @param name profile's name
89.215 - * @return gint representing the result
89.216 - *
89.217 - **/
89.218 -gint
89.219 -gmyth_recprofile_set_name(GMythRecProfile * rec, gchar * name)
89.220 -{
89.221 - return gmyth_recprofile_set(rec, "name", name);
89.222 -}
89.223 -
89.224 -/**
89.225 - *
89.226 - * gmyth_recprofile_set_group
89.227 - * @brief set recprofile's group
89.228 - * @param rec GMythRecProfile*
89.229 - * @param group profile's group
89.230 - * @return gint representing the result
89.231 - *
89.232 - **/
89.233 -gint
89.234 -gmyth_recprofile_set_group(GMythRecProfile * rec, gchar * group)
89.235 -{
89.236 - return gmyth_recprofile_set(rec, "group", group);
89.237 -}
89.238 -
89.239 -/**
89.240 - *
89.241 - * gmyth_recprofile_set_vcodec
89.242 - * @brief set recprofile's vcodec
89.243 - * @param rec GMythRecProfile*
89.244 - * @param vcodec profile's vcodec
89.245 - * @return gint representing the result
89.246 - *
89.247 - **/
89.248 -gint
89.249 -gmyth_recprofile_set_vcodec(GMythRecProfile * rec, gchar * vcodec)
89.250 -{
89.251 - return gmyth_recprofile_set(rec, "vcodec", vcodec);
89.252 -}
89.253 -
89.254 -/**
89.255 - *
89.256 - * gmyth_recprofile_set_acodec
89.257 - * @brief set recprofile's acodec
89.258 - * @param rec GMythRecProfile*
89.259 - * @param acodec profile's acodec
89.260 - * @return gint representing the result
89.261 - *
89.262 - **/
89.263 -gint
89.264 -gmyth_recprofile_set_acodec(GMythRecProfile * rec, gchar * acodec)
89.265 -{
89.266 - return gmyth_recprofile_set(rec, "acodec", acodec);
89.267 -}
90.1 --- a/gmyth/src/gmyth_recprofile.h Mon Feb 25 17:45:36 2008 +0000
90.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
90.3 @@ -1,123 +0,0 @@
90.4 -/**
90.5 - * GMyth Library
90.6 - *
90.7 - * @file gmyth/gmyth_recprofile.h
90.8 - *
90.9 - * @brief <p> This file contains the recprofile class.
90.10 - *
90.11 - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
90.12 - * @author Artur Duque de Souza <artur.souza@indt.org.br>
90.13 - *
90.14 - *
90.15 - * This program is free software; you can redistribute it and/or modify
90.16 - * it under the terms of the GNU Lesser General Public License as published by
90.17 - * the Free Software Foundation; either version 2 of the License, or
90.18 - * (at your option) any later version.
90.19 - *
90.20 - * This program is distributed in the hope that it will be useful,
90.21 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
90.22 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
90.23 - * GNU General Public License for more details.
90.24 - *
90.25 - * You should have received a copy of the GNU Lesser General Public License
90.26 - * along with this program; if not, write to the Free Software
90.27 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
90.28 - */
90.29 -
90.30 -#ifndef _GMYTH_RECPROFILE_H
90.31 -#define _GMYTH_RECPROFILE_H
90.32 -
90.33 -#include <glib.h>
90.34 -#include <glib-object.h>
90.35 -
90.36 -#include "gmyth_stringlist.h"
90.37 -#include "gmyth_backendinfo.h"
90.38 -#include "gmyth_socket.h"
90.39 -
90.40 -G_BEGIN_DECLS
90.41 -#define GMYTH_RECPROFILE_TYPE (gmyth_recprofile_get_type ())
90.42 -#define GMYTH_RECPROFILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_RECPROFILE_TYPE, GMythRecProfile))
90.43 -#define GMYTH_RECPROFILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECPROFILE_TYPE, GMythRecProfileClass))
90.44 -#define IS_GMYTH_RECPROFILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_RECPROFILE_TYPE))
90.45 -#define IS_GMYTH_RECPROFILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_RECPROFILE_TYPE))
90.46 -#define GMYTH_RECPROFILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_RECPROFILE_TYPE, GMythRecProfileClass))
90.47 -typedef struct _Options Options;
90.48 -typedef struct _GMythRecProfile GMythRecProfile;
90.49 -typedef struct _GMythRecProfileClass GMythRecProfileClass;
90.50 -
90.51 -struct _GMythRecProfileClass {
90.52 - GObjectClass parent_class;
90.53 - gint teste;
90.54 - /*
90.55 - * callbacks
90.56 - */
90.57 -};
90.58 -
90.59 -struct _GMythRecProfile {
90.60 - gint id;
90.61 - gchar *name;
90.62 - gchar *group;
90.63 - gchar *vcodec;
90.64 - gchar *acodec;
90.65 - Options *options;
90.66 -};
90.67 -
90.68 -struct _Options {
90.69 - gint transcodelossless;
90.70 - gint transcoderesize;
90.71 - gint width;
90.72 - gint height;
90.73 - gint rtjpegquality;
90.74 - gint rtjpeglumafilter;
90.75 - gint rtjpegchromafilter;
90.76 - gint mpeg4bitrate;
90.77 - gint mpeg4maxquality;
90.78 - gint mpeg4minquality;
90.79 - gint mpeg4qualdiff;
90.80 - gint mpeg4scalebitrate;
90.81 - gint mpeg4optionvhq;
90.82 - gint mpeg4option4mv;
90.83 - gint mpeg4optionidct;
90.84 - gint mpeg4optionime;
90.85 - gint hardwaremjpegquality;
90.86 - gint hardwaremjpeghdecimation;
90.87 - gint hardwaremjpegvdecimation;
90.88 - gchar *mpeg2streamtype;
90.89 - gchar *mpeg2aspectratio;
90.90 - gint mpeg2bitrate;
90.91 - gint mpeg2maxbitrate;
90.92 - gint samplerate;
90.93 - gint mp3quality;
90.94 - gint volume;
90.95 - gchar *mpeg2audtype;
90.96 - gint mpeg2audbitratel1;
90.97 - gint mpeg2audbitratel2;
90.98 - gint mpeg2audvolume;
90.99 -};
90.100 -
90.101 -GType gmyth_recprofile_type(void);
90.102 -
90.103 -GMythRecProfile *gmyth_recprofile_new(void);
90.104 -
90.105 -GSList *gmyth_recprofile_get_profile_list(GMythBackendInfo *
90.106 - backend_info);
90.107 -
90.108 -gint gmyth_recprofile_create_profile(GMythBackendInfo *
90.109 - backend_info,
90.110 - GMythRecProfile * profile);
90.111 -
90.112 -gint gmyth_recprofile_del_profile_list(GMythBackendInfo *
90.113 - backend_info, gint id);
90.114 -
90.115 -gint gmyth_recprofile_set_acodec(GMythRecProfile * rec,
90.116 - gchar * acodec);
90.117 -gint gmyth_recprofile_set_vcodec(GMythRecProfile * rec,
90.118 - gchar * vcodec);
90.119 -gint gmyth_recprofile_set_group(GMythRecProfile * rec,
90.120 - gchar * group);
90.121 -gint gmyth_recprofile_set_name(GMythRecProfile * rec,
90.122 - gchar * name);
90.123 -gint gmyth_recprofile_set_id(GMythRecProfile * rec, gint id);
90.124 -
90.125 -G_END_DECLS
90.126 -#endif /*_GMYTH_RECPROFILE_H*/
91.1 --- a/gmyth/src/gmyth_remote_util.c Mon Feb 25 17:45:36 2008 +0000
91.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
91.3 @@ -1,126 +0,0 @@
91.4 -/**
91.5 - * GMyth Library
91.6 - *
91.7 - * @file gmyth/gmyth_remote_util.c
91.8 - *
91.9 - * @brief <p> This component provides utility functions for accessing remote data.
91.10 - *
91.11 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
91.12 - * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
91.13 - * @author Rosfran Borges <rosfran.borges@indt.org.br>
91.14 - *
91.15 - *
91.16 - * This program is free software; you can redistribute it and/or modify
91.17 - * it under the terms of the GNU Lesser General Public License as published by
91.18 - * the Free Software Foundation; either version 2 of the License, or
91.19 - * (at your option) any later version.
91.20 - *
91.21 - * This program is distributed in the hope that it will be useful,
91.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
91.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
91.24 - * GNU General Public License for more details.
91.25 - *
91.26 - * You should have received a copy of the GNU Lesser General Public License
91.27 - * along with this program; if not, write to the Free Software
91.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
91.29 - */
91.30 -
91.31 -#ifdef HAVE_CONFIG_H
91.32 -#include "config.h"
91.33 -#endif
91.34 -
91.35 -#include "gmyth_remote_util.h"
91.36 -
91.37 -#include "gmyth_recorder.h"
91.38 -#include "gmyth_stringlist.h"
91.39 -#include "gmyth_debug.h"
91.40 -
91.41 -/**
91.42 - * Requests the Mythtv backend for a free remote recorder.
91.43 - *
91.44 - * @param socket The socket instance where to send the command.
91.45 - * @param curr The recorder index, or -1 to consider the first one.
91.46 - *
91.47 - * @return the remote encoder instance available, or NULL if any error happens.
91.48 - */
91.49 -GMythRecorder *
91.50 -remote_request_next_free_recorder(GMythSocket * socket, gint curr)
91.51 -{
91.52 - GMythRecorder *recorder = NULL;
91.53 - GString *hostname;
91.54 - gint num,
91.55 - port;
91.56 -
91.57 - GMythStringList *strlist = gmyth_string_list_new();
91.58 -
91.59 - gmyth_debug("[%s] Request next free recorder in the backend",
91.60 - __FUNCTION__);
91.61 -
91.62 - gmyth_string_list_append_char_array(strlist, "GET_NEXT_FREE_RECORDER");
91.63 - gmyth_string_list_append_int(strlist, curr);
91.64 -
91.65 - if (!gmyth_socket_sendreceive_stringlist(socket, strlist)) {
91.66 - g_warning("GET_NEXT_FREE_RECORDER request error!\n");
91.67 - return NULL;
91.68 - }
91.69 -
91.70 - num = gmyth_string_list_get_int(strlist, 0);
91.71 - hostname = gmyth_string_list_get_string(strlist, 1);
91.72 - port = gmyth_string_list_get_int(strlist, 2);
91.73 -
91.74 - if (num < 0 || port < 0)
91.75 - goto clean_up;
91.76 -
91.77 - gmyth_debug
91.78 - ("[%s] Free recorder info received: num: %d, hostname: %s, port: %d",
91.79 - __FUNCTION__, num, hostname->str, port);
91.80 -
91.81 - recorder = gmyth_recorder_new(num, hostname, port);
91.82 -
91.83 - clean_up:
91.84 -
91.85 - g_string_free(hostname, TRUE);
91.86 - g_object_unref(strlist);
91.87 -
91.88 - return recorder;
91.89 -}
91.90 -
91.91 -/**
91.92 - * Requests the Mythtv backend for the number of free remote recorders.
91.93 - *
91.94 - * @param socket The socket instance where to send the command.
91.95 - *
91.96 - * @return the number of remote encoders instance available, or 0 if no one is actually free..
91.97 - */
91.98 -gint
91.99 -gmyth_remote_util_get_free_recorder_count(GMythSocket * socket)
91.100 -{
91.101 - gint num_recs = 0;
91.102 -
91.103 - GMythStringList *strlist = gmyth_string_list_new();
91.104 -
91.105 - gmyth_debug("[%s] Request next free recorder in the backend",
91.106 - __FUNCTION__);
91.107 -
91.108 - gmyth_string_list_append_char_array(strlist,
91.109 - "GET_FREE_RECORDER_COUNT");
91.110 -
91.111 - if (!gmyth_socket_sendreceive_stringlist(socket, strlist)) {
91.112 - gmyth_debug("GET_FREE_RECORDER_COUNT request error!");
91.113 - return 0;
91.114 - }
91.115 -
91.116 - num_recs = gmyth_string_list_get_int(strlist, 0);
91.117 -
91.118 - if (num_recs < 0)
91.119 - goto clean_up;
91.120 -
91.121 - gmyth_debug("[%s] Free recorder info received: num recorders: %d",
91.122 - __FUNCTION__, num_recs);
91.123 -
91.124 - clean_up:
91.125 -
91.126 - g_object_unref(strlist);
91.127 -
91.128 - return num_recs;
91.129 -}
92.1 --- a/gmyth/src/gmyth_remote_util.h Mon Feb 25 17:45:36 2008 +0000
92.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
92.3 @@ -1,41 +0,0 @@
92.4 -/**
92.5 - * GMyth Library
92.6 - *
92.7 - * @file gmyth/gmyth_remote_util.h
92.8 - *
92.9 - * @brief <p> This component provides utility functions for accessing remote data.
92.10 - *
92.11 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
92.12 - * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
92.13 - *
92.14 - *
92.15 - * This program is free software; you can redistribute it and/or modify
92.16 - * it under the terms of the GNU Lesser General Public License as published by
92.17 - * the Free Software Foundation; either version 2 of the License, or
92.18 - * (at your option) any later version.
92.19 - *
92.20 - * This program is distributed in the hope that it will be useful,
92.21 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
92.22 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
92.23 - * GNU General Public License for more details.
92.24 - *
92.25 - * You should have received a copy of the GNU Lesser General Public License
92.26 - * along with this program; if not, write to the Free Software
92.27 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
92.28 - */
92.29 -
92.30 -#ifndef __REMOTE_UTIL_H__
92.31 -#define __REMOTE_UTIL_H__
92.32 -
92.33 -#include <glib.h>
92.34 -#include "gmyth_recorder.h"
92.35 -#include "gmyth_socket.h"
92.36 -
92.37 -G_BEGIN_DECLS
92.38 - GMythRecorder * remote_request_next_free_recorder(GMythSocket * socket,
92.39 - gint curr);
92.40 -gint gmyth_remote_util_get_free_recorder_count(GMythSocket *
92.41 - socket);
92.42 -
92.43 -G_END_DECLS
92.44 -#endif
93.1 --- a/gmyth/src/gmyth_scheduler.c Mon Feb 25 17:45:36 2008 +0000
93.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
93.3 @@ -1,1266 +0,0 @@
93.4 -/**
93.5 - * GMyth Library
93.6 - *
93.7 - * @file gmyth/gmyth_scheduler.c
93.8 - *
93.9 - * @brief <p> The scheduler encapsulates all functions for browsing, scheduling
93.10 - * and modifying the recorded content.
93.11 - *
93.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
93.13 - * @author Alexsandro Jose Virginio dos Santos <alexsandro.santos@indt.org.br>
93.14 - *
93.15 - *
93.16 - * This program is free software; you can redistribute it and/or modify
93.17 - * it under the terms of the GNU Lesser General Public License as published by
93.18 - * the Free Software Foundation; either version 2 of the License, or
93.19 - * (at your option) any later version.
93.20 - *
93.21 - * This program is distributed in the hope that it will be useful,
93.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
93.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
93.24 - * GNU General Public License for more details.
93.25 - *
93.26 - * You should have received a copy of the GNU Lesser General Public License
93.27 - * along with this program; if not, write to the Free Software
93.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
93.29 - */
93.30 -
93.31 -#ifdef HAVE_CONFIG_H
93.32 -#include "config.h"
93.33 -#endif
93.34 -
93.35 -#include <assert.h>
93.36 -
93.37 -#include <glib.h>
93.38 -#include <glib/gprintf.h>
93.39 -
93.40 -#include "gmyth_scheduler.h"
93.41 -#include "gmyth_util.h"
93.42 -#include "gmyth_query.h"
93.43 -#include "gmyth_socket.h"
93.44 -#include "gmyth_debug.h"
93.45 -
93.46 -static void gmyth_scheduler_class_init(GMythSchedulerClass * klass);
93.47 -static void gmyth_scheduler_init(GMythScheduler * object);
93.48 -
93.49 -static void gmyth_scheduler_dispose(GObject * object);
93.50 -static void gmyth_scheduler_finalize(GObject * object);
93.51 -
93.52 -static gboolean update_backend(GMythScheduler * scheduler, gint record_id);
93.53 -
93.54 -G_DEFINE_TYPE(GMythScheduler, gmyth_scheduler, G_TYPE_OBJECT)
93.55 - static void gmyth_scheduler_class_init(GMythSchedulerClass * klass)
93.56 -{
93.57 - GObjectClass *gobject_class;
93.58 -
93.59 - gobject_class = (GObjectClass *) klass;
93.60 -
93.61 - gobject_class->dispose = gmyth_scheduler_dispose;
93.62 - gobject_class->finalize = gmyth_scheduler_finalize;
93.63 -}
93.64 -
93.65 -static void
93.66 -gmyth_scheduler_init(GMythScheduler * sched)
93.67 -{
93.68 - sched->recordid = 0;
93.69 - sched->type = 0;
93.70 - sched->search = 0;
93.71 - sched->profile = g_string_new("");
93.72 -
93.73 - sched->dupin = 0;
93.74 - sched->dupmethod = 0;
93.75 - sched->autoexpire = 0;
93.76 - sched->autotranscode = 0;
93.77 - sched->transcoder = 0;
93.78 -
93.79 - sched->autocommflag = 0;
93.80 - sched->autouserjob1 = 0;
93.81 - sched->autouserjob2 = 0;
93.82 - sched->autouserjob3 = 0;
93.83 - sched->autouserjob4 = 0;
93.84 -
93.85 - sched->startoffset = 0;
93.86 - sched->endoffset = 0;
93.87 - sched->maxepisodes = 0;
93.88 - sched->maxnewest = 0;
93.89 -
93.90 - sched->recpriority = 0;
93.91 - sched->recgroup = g_string_new("");
93.92 - sched->playgroup = g_string_new("");
93.93 -
93.94 - sched->prefinput = 0;
93.95 - sched->inactive = 0;
93.96 -
93.97 - sched->search_type = g_string_new("");
93.98 - sched->search_what = g_string_new("");
93.99 -
93.100 - sched->msqlquery = gmyth_query_new();
93.101 -}
93.102 -
93.103 -static void
93.104 -gmyth_scheduler_dispose(GObject * object)
93.105 -{
93.106 - GMythScheduler *scheduler = GMYTH_SCHEDULER(object);
93.107 -
93.108 - if (scheduler->backend_info) {
93.109 - g_object_unref(scheduler->backend_info);
93.110 - scheduler->backend_info = NULL;
93.111 - }
93.112 -
93.113 - if (scheduler->msqlquery) {
93.114 - g_object_unref(scheduler->msqlquery);
93.115 - scheduler->msqlquery = NULL;
93.116 - }
93.117 -
93.118 - g_string_free(scheduler->profile, TRUE);
93.119 - g_string_free(scheduler->recgroup, TRUE);
93.120 - g_string_free(scheduler->playgroup, TRUE);
93.121 - g_string_free(scheduler->search_type, TRUE);
93.122 - g_string_free(scheduler->search_what, TRUE);
93.123 -
93.124 - G_OBJECT_CLASS(gmyth_scheduler_parent_class)->dispose(object);
93.125 -}
93.126 -
93.127 -static void
93.128 -gmyth_scheduler_finalize(GObject * object)
93.129 -{
93.130 - g_signal_handlers_destroy(object);
93.131 -
93.132 - G_OBJECT_CLASS(gmyth_scheduler_parent_class)->finalize(object);
93.133 -}
93.134 -
93.135 -/** Creates a new instance of GMythScheduler.
93.136 - *
93.137 - * @return a new instance of GMythScheduler.
93.138 - */
93.139 -GMythScheduler *
93.140 -gmyth_scheduler_new()
93.141 -{
93.142 - GMythScheduler *scheduler =
93.143 - GMYTH_SCHEDULER(g_object_new(GMYTH_SCHEDULER_TYPE, NULL));
93.144 -
93.145 - return scheduler;
93.146 -}
93.147 -
93.148 -gboolean
93.149 -gmyth_scheduler_connect(GMythScheduler * scheduler,
93.150 - GMythBackendInfo * backend_info)
93.151 -{
93.152 - return gmyth_scheduler_connect_with_timeout(scheduler, backend_info,
93.153 - 0);
93.154 -}
93.155 -
93.156 -/** Connects to the Mysql database in the backend. The backend address
93.157 - * is loaded from the GMythSettings instance.
93.158 - *
93.159 - * @param scheduler the GMythScheduler instance to be connected.
93.160 - * @return true if connection was success, false if failed.
93.161 - */
93.162 -gboolean
93.163 -gmyth_scheduler_connect_with_timeout(GMythScheduler * scheduler,
93.164 - GMythBackendInfo * backend_info,
93.165 - guint timeout)
93.166 -{
93.167 - assert(scheduler);
93.168 - g_return_val_if_fail(backend_info != NULL, FALSE);
93.169 -
93.170 - if (scheduler->backend_info)
93.171 - g_object_unref(scheduler->backend_info);
93.172 -
93.173 - scheduler->backend_info = g_object_ref(backend_info);
93.174 -
93.175 - if (scheduler->msqlquery == NULL) {
93.176 - g_warning("[%s] GMythScheduler db initializing", __FUNCTION__);
93.177 - scheduler->msqlquery = gmyth_query_new();
93.178 - }
93.179 -
93.180 - if (!gmyth_query_connect_with_timeout(scheduler->msqlquery,
93.181 - scheduler->backend_info,
93.182 - timeout)) {
93.183 - g_warning("[%s] Error while connecting to db", __FUNCTION__);
93.184 - return FALSE;
93.185 - }
93.186 -
93.187 - return TRUE;
93.188 -}
93.189 -
93.190 -/** Disconnects from the Mysql database in the backend.
93.191 - *
93.192 - * @param scheduler the GMythScheduler instance to be disconnected
93.193 - * @return true if disconnection was success, false if failed.
93.194 - */
93.195 -gboolean
93.196 -gmyth_scheduler_disconnect(GMythScheduler * scheduler)
93.197 -{
93.198 - assert(scheduler);
93.199 -
93.200 - if (scheduler->msqlquery != NULL) {
93.201 - gmyth_query_disconnect(scheduler->msqlquery);
93.202 - }
93.203 -
93.204 - return TRUE;
93.205 -}
93.206 -
93.207 -/** Retrieves from the backend Mysql database the list of recording schedules.
93.208 - *
93.209 - * @param scheduler The GMythScheduler instance.
93.210 - * @param schedule_list the GList pointer to be filled with the loaded list of ScheduleInfo items.
93.211 - * @return The amount of schedules retrieved from database, or -1 if error.
93.212 - */
93.213 -gint
93.214 -gmyth_scheduler_get_schedule_list(GMythScheduler * scheduler,
93.215 - GList ** schedule_list)
93.216 -{
93.217 - ScheduleInfo *schedule;
93.218 - MYSQL_RES *msql_res;
93.219 - GString *query_str = g_string_new("");
93.220 - gchar *date_time = NULL;
93.221 -
93.222 - assert(scheduler);
93.223 -
93.224 - g_string_printf(query_str,
93.225 - "SELECT recordid,programid,chanid,starttime,startdate,"
93.226 - "endtime,enddate,title,subtitle,description,category,type,parentid,seriesid FROM record;");
93.227 -
93.228 - if (scheduler->msqlquery == NULL) {
93.229 - g_warning("[%s] Scheduler db connection not initialized",
93.230 - __FUNCTION__);
93.231 - return -1;
93.232 - }
93.233 - msql_res =
93.234 - gmyth_query_process_statement(scheduler->msqlquery,
93.235 - query_str->str);
93.236 -
93.237 - if (msql_res == NULL) {
93.238 - g_warning("DB retrieval of schedule list failed");
93.239 - return -1;
93.240 - } else {
93.241 - MYSQL_ROW row;
93.242 -
93.243 - *schedule_list = NULL;
93.244 -
93.245 - while ((row = mysql_fetch_row(msql_res)) != NULL) {
93.246 - schedule = g_new0(ScheduleInfo, 1);
93.247 - gint type = 0;
93.248 -
93.249 - schedule->schedule_id =
93.250 - (guint) g_ascii_strtoull(row[0], NULL, 10);
93.251 - schedule->program_id = g_string_new (row[1]);
93.252 - schedule->channel_id = (gint) g_ascii_strtoull (row[2], NULL, 10);
93.253 -
93.254 - /*
93.255 - * generate a time_t from a time and a date db field
93.256 - */
93.257 - date_time = g_strdup_printf("%sT%s", row[4], row[3]);
93.258 - schedule->start_time =
93.259 - gmyth_util_string_to_time_val(date_time);
93.260 - g_free(date_time);
93.261 -
93.262 - /*
93.263 - * generate a time_t from a time and a date db field
93.264 - */
93.265 - date_time = g_strdup_printf("%sT%s", row[6], row[5]);
93.266 - schedule->end_time = gmyth_util_string_to_time_val(date_time);
93.267 - g_free(date_time);
93.268 -
93.269 - schedule->title = g_string_new(row[7]);
93.270 - schedule->subtitle = g_string_new(row[8]);
93.271 - schedule->description = g_string_new(row[9]);
93.272 - schedule->category = g_string_new(row[10]);
93.273 - type = g_ascii_strtoull (row[11], NULL, 10);
93.274 - if (type == 4) {
93.275 - schedule->type = GMYTH_SCHEDULE_ALL_OCCURRENCES;
93.276 - } else if (type == 1) {
93.277 - schedule->type = GMYTH_SCHEDULE_ONE_OCCURRENCE;
93.278 - } else if (type == 8) {
93.279 - schedule->type = GMYTH_SCHEDULE_EXCEPTION;
93.280 - schedule->parentid = (gint) g_ascii_strtoull (row[12], NULL, 10);
93.281 - }
93.282 -
93.283 - schedule->seriesid = g_string_new (row[13]);
93.284 -
93.285 - (*schedule_list) = g_list_append(*(schedule_list), schedule);
93.286 - }
93.287 - }
93.288 -
93.289 - mysql_free_result(msql_res);
93.290 - g_string_free(query_str, TRUE);
93.291 -
93.292 - return (*schedule_list == NULL) ? 0 : g_list_length(*schedule_list);
93.293 -}
93.294 -
93.295 -/** Retrieves from the backend Mysql database the list of recorded programs.
93.296 - *
93.297 - * @param scheduler The GMythScheduler instance.
93.298 - * @param recorded_list the GList pointer to be filled with the loaded RecordInfo items.
93.299 - * @return The amount of recorded retrieved from database, or -1 if error.
93.300 - */
93.301 -gint
93.302 -gmyth_scheduler_get_recorded_list(GMythScheduler * scheduler,
93.303 - GList ** recorded_list)
93.304 -{
93.305 - RecordedInfo *record;
93.306 - MYSQL_RES *msql_res;
93.307 - GString *query_str = g_string_new("");
93.308 -
93.309 - assert(scheduler);
93.310 -
93.311 - g_string_printf(query_str,
93.312 - "SELECT recordid,programid,chanid,starttime,progstart,"
93.313 - "endtime,progend,title,subtitle,description,category,"
93.314 - "filesize,basename,seriesid FROM recorded WHERE recgroup != 'LiveTV'");
93.315 -
93.316 - if (scheduler->msqlquery == NULL) {
93.317 - g_warning("[%s] Scheduler db connection not initialized",
93.318 - __FUNCTION__);
93.319 - return -1;
93.320 - }
93.321 -
93.322 - msql_res =
93.323 - gmyth_query_process_statement(scheduler->msqlquery,
93.324 - query_str->str);
93.325 -
93.326 - if (msql_res == NULL) {
93.327 - g_warning("DB retrieval of recording list failed");
93.328 - return -1;
93.329 - } else {
93.330 - MYSQL_ROW row;
93.331 -
93.332 - (*recorded_list) = NULL;
93.333 -
93.334 - while ((row = mysql_fetch_row(msql_res)) != NULL) {
93.335 - record = g_new0(RecordedInfo, 1);
93.336 -
93.337 - record->record_id = (guint) g_ascii_strtoull(row[0], NULL, 10);
93.338 - record->program_id = g_string_new (row[1]);
93.339 - record->channel_id = (gint) g_ascii_strtoull(row[2], NULL, 10);
93.340 - record->start_time = gmyth_util_string_to_time_val(row[3]);
93.341 - record->end_time = gmyth_util_string_to_time_val(row[5]);
93.342 -
93.343 - record->title = g_string_new(row[7]);
93.344 - record->subtitle = g_string_new(row[8]);
93.345 - record->description = g_string_new(row[9]);
93.346 - record->category = g_string_new(row[10]);
93.347 - record->filesize = g_ascii_strtoull(row[11], NULL, 10);
93.348 - record->basename = g_string_new(row[12]);
93.349 - record->seriesid = g_string_new(row[13]);
93.350 -
93.351 - (*recorded_list) = g_list_append((*recorded_list), record);
93.352 - }
93.353 - }
93.354 -
93.355 - mysql_free_result(msql_res);
93.356 - g_string_free(query_str, TRUE);
93.357 -
93.358 - return (*recorded_list == NULL) ? 0 : g_list_length(*recorded_list);
93.359 -}
93.360 -
93.361 -RecordedInfo*
93.362 -gmyth_scheduler_get_recorded_info (GMythScheduler *scheduler,
93.363 - const gchar* basename)
93.364 -{
93.365 - RecordedInfo *record = NULL;
93.366 - MYSQL_RES *msql_res;
93.367 - GString *query_str = g_string_new("");
93.368 -
93.369 - assert(scheduler);
93.370 -
93.371 - g_string_printf(query_str,
93.372 - "SELECT recordid,programid,chanid,starttime,progstart,"
93.373 - "endtime,progend,title,subtitle,description,category,"
93.374 - "filesize,basename,seriesid FROM recorded "
93.375 - "WHERE recgroup != 'LiveTV' AND basename = '%s'", basename);
93.376 -
93.377 - if (scheduler->msqlquery == NULL) {
93.378 - g_warning("[%s] Scheduler db connection not initialized",
93.379 - __FUNCTION__);
93.380 - return NULL;
93.381 - }
93.382 -
93.383 - msql_res =
93.384 - gmyth_query_process_statement(scheduler->msqlquery,
93.385 - query_str->str);
93.386 -
93.387 - if (msql_res == NULL) {
93.388 - g_warning("DB retrieval of recording list failed");
93.389 - return NULL;
93.390 - } else {
93.391 - MYSQL_ROW row;
93.392 - row = mysql_fetch_row(msql_res);
93.393 - if (row != NULL) {
93.394 - record = g_new0(RecordedInfo, 1);
93.395 - record->record_id = (guint) g_ascii_strtoull(row[0], NULL, 10);
93.396 - record->program_id = g_string_new (row[1]);
93.397 - record->channel_id = (gint) g_ascii_strtoull(row[2], NULL, 10);
93.398 - record->start_time = gmyth_util_string_to_time_val(row[3]);
93.399 - record->end_time = gmyth_util_string_to_time_val(row[5]);
93.400 - record->title = g_string_new(row[7]);
93.401 - record->subtitle = g_string_new(row[8]);
93.402 - record->description = g_string_new(row[9]);
93.403 - record->category = g_string_new(row[10]);
93.404 - record->filesize = g_ascii_strtoull(row[11], NULL, 10);
93.405 - record->basename = g_string_new(row[12]);
93.406 - record->seriesid = g_string_new(row[13]);
93.407 - }
93.408 - }
93.409 -
93.410 - mysql_free_result(msql_res);
93.411 - g_string_free(query_str, TRUE);
93.412 -
93.413 - return record;
93.414 -}
93.415 -
93.416 -
93.417 -static void
93.418 -_set_value(GMythQuery * myth_query, char *field, gchar * value,
93.419 - gint rec_id)
93.420 -{
93.421 - gchar *query =
93.422 - g_strdup_printf
93.423 - ("UPDATE record SET recordid = %d, %s = \"%s\" WHERE recordid = %d;",
93.424 - rec_id, field, value, rec_id);
93.425 -
93.426 - gmyth_query_process_statement(myth_query, query);
93.427 - g_free(query);
93.428 -}
93.429 -
93.430 -static void
93.431 -_set_int_value(GMythQuery * myth_query, char *field, gint value,
93.432 - gint rec_id)
93.433 -{
93.434 - gchar *str_value = g_strdup_printf("%d", value);
93.435 -
93.436 - _set_value(myth_query, field, str_value, rec_id);
93.437 - g_free(str_value);
93.438 -}
93.439 -
93.440 -ScheduleInfo*
93.441 -gmyth_scheduler_add_schedule_program (GMythScheduler * scheduler,
93.442 - GMythProgramInfo *program,
93.443 - GMythScheduleType type)
93.444 -{
93.445 - ScheduleInfo *info;
93.446 -
93.447 - info = g_new0 (ScheduleInfo, 1);
93.448 - info->program_id = g_string_new (program->program_id->str);
93.449 - info->channel_id = program->channel_id;
93.450 - info->start_time = g_new0 (GTimeVal, 1);
93.451 - *info->start_time = *program->startts;
93.452 - info->end_time = g_new0 (GTimeVal, 1);
93.453 - *info->end_time = *program->endts;
93.454 - info->seriesid = g_string_new (program->seriesid->str);
93.455 - info->title = g_string_new (program->title->str);
93.456 - info->subtitle = g_string_new (program->subtitle->str);
93.457 - info->description = g_string_new (program->description->str);
93.458 - info->category = g_string_new (program->category->str);
93.459 - info->type = type;
93.460 -
93.461 - if (gmyth_scheduler_add_schedule_full (scheduler, info, type))
93.462 - {
93.463 - if (!program->recstartts)
93.464 - program->recstartts = g_new0 (GTimeVal, 1);
93.465 - *program->recstartts = *info->start_time;
93.466 -
93.467 - if (!program->recendts)
93.468 - program->recendts = g_new0 (GTimeVal, 1);
93.469 - *program->recendts = *info->end_time;
93.470 -
93.471 - program->recordid = info->schedule_id;
93.472 - return info;
93.473 - }
93.474 -
93.475 - gmyth_schedule_info_free (info);
93.476 - return NULL;
93.477 -}
93.478 -
93.479 -
93.480 -gboolean
93.481 -gmyth_scheduler_add_schedule_full (GMythScheduler * scheduler,
93.482 - ScheduleInfo * schedule_info, GMythScheduleType type)
93.483 -{
93.484 - MYSQL_RES *msql_res;
93.485 - gchar *query_str = "INSERT record (recordid) VALUE (0);";
93.486 - gchar *station = NULL;
93.487 - gulong rec_id;
93.488 -
93.489 - g_return_val_if_fail (IS_GMYTH_SCHEDULER (scheduler), FALSE);
93.490 -
93.491 - if (scheduler->msqlquery == NULL) {
93.492 - g_warning("[%s] Scheduler db connection not initialized",
93.493 - __FUNCTION__);
93.494 - return FALSE;
93.495 - }
93.496 -
93.497 - msql_res =
93.498 - gmyth_query_process_statement_with_increment(scheduler->msqlquery,
93.499 - query_str, &rec_id);
93.500 - mysql_free_result(msql_res);
93.501 -
93.502 - // Retrieves the station info
93.503 - query_str =
93.504 - g_strdup_printf
93.505 - ("SELECT callsign FROM channel WHERE chanid = %d;",
93.506 - schedule_info->channel_id);
93.507 - msql_res =
93.508 - gmyth_query_process_statement(scheduler->msqlquery, query_str);
93.509 - if (msql_res == NULL) {
93.510 - g_warning("[%s] msql query returned NULL MYSQL_RES", __FUNCTION__);
93.511 - return FALSE;
93.512 - } else {
93.513 - MYSQL_ROW row;
93.514 -
93.515 - if ((row = mysql_fetch_row(msql_res)) != NULL) {
93.516 - station = g_strdup(row[0]);
93.517 - }
93.518 - }
93.519 - mysql_free_result(msql_res);
93.520 - g_free(query_str);
93.521 -
93.522 - // _set_value (field, value, id);
93.523 - _set_int_value(scheduler->msqlquery, "chanid",
93.524 - schedule_info->channel_id, rec_id);
93.525 - _set_value(scheduler->msqlquery, "station", station, rec_id);
93.526 - _set_value(scheduler->msqlquery, "title", schedule_info->title->str,
93.527 - rec_id);
93.528 - // / subtitle, description
93.529 - _set_value(scheduler->msqlquery, "starttime",
93.530 - gmyth_util_time_to_string_only_time(schedule_info->
93.531 - start_time), rec_id);
93.532 - _set_value(scheduler->msqlquery, "startdate",
93.533 - gmyth_util_time_to_string_only_date(schedule_info->
93.534 - start_time), rec_id);
93.535 - _set_value(scheduler->msqlquery, "endtime",
93.536 - gmyth_util_time_to_string_only_time(schedule_info->
93.537 - end_time), rec_id);
93.538 - _set_value(scheduler->msqlquery, "enddate",
93.539 - gmyth_util_time_to_string_only_date(schedule_info->
93.540 - end_time), rec_id);
93.541 - // / category, series id, program id
93.542 - // _set_value (scheduler->msqlquery, "findday",
93.543 - // (gmyth_util_time_val_to_date( schedule_info->start_time
93.544 - // ))->tm_wday, rec_id);
93.545 - // _set_value (scheduler->msqlquery, "findtime",
93.546 - // gmyth_util_time_to_string_only_time( schedule_info->start_time),
93.547 - // rec_id);
93.548 - // _set_int_value (scheduler->msqlquery, "findid",
93.549 - // (gint)(schedule_info->start_time->tv_sec/60/60/24 + 719528),
93.550 - // rec_id);
93.551 -
93.552 - if (schedule_info->seriesid)
93.553 - _set_value(scheduler->msqlquery, "seriesid",
93.554 - schedule_info->seriesid->str, rec_id);
93.555 -
93.556 - _set_value(scheduler->msqlquery, "parentid", "0", rec_id);
93.557 - _set_value(scheduler->msqlquery, "search", "0", rec_id);
93.558 -
93.559 - if (type == GMYTH_SCHEDULE_ALL_OCCURRENCES) {
93.560 - _set_int_value(scheduler->msqlquery, "type", 3, rec_id);
93.561 - } else if (type == GMYTH_SCHEDULE_ONE_OCCURRENCE) {
93.562 - _set_int_value(scheduler->msqlquery, "type", 1, rec_id);
93.563 - } else if (type == GMYTH_SCHEDULE_EXCEPTION) {
93.564 - _set_int_value(scheduler->msqlquery, "type", 8, rec_id);
93.565 - _set_int_value(scheduler->msqlquery, "parentid", schedule_info->parentid,
93.566 - rec_id);
93.567 - }
93.568 -
93.569 - _set_value(scheduler->msqlquery, "recpriority", "0", rec_id);
93.570 - _set_value(scheduler->msqlquery, "startoffset", "0", rec_id);
93.571 - _set_value(scheduler->msqlquery, "endoffset", "0", rec_id);
93.572 - _set_value(scheduler->msqlquery, "dupmethod", "6", rec_id); // ?
93.573 - _set_value(scheduler->msqlquery, "dupin", "15", rec_id); // ?
93.574 -
93.575 - _set_value(scheduler->msqlquery, "prefinput", "0", rec_id);
93.576 - _set_value(scheduler->msqlquery, "inactive", "0", rec_id);
93.577 - _set_value(scheduler->msqlquery, "profile", "Default", rec_id);
93.578 - _set_value(scheduler->msqlquery, "recgroup", "Default", rec_id);
93.579 - _set_value(scheduler->msqlquery, "storagegroup", "Default", rec_id);
93.580 - _set_value(scheduler->msqlquery, "playgroup", "Default", rec_id);
93.581 - _set_value(scheduler->msqlquery, "autoexpire", "1", rec_id);
93.582 - _set_value(scheduler->msqlquery, "maxepisodes", "0", rec_id);
93.583 - _set_value(scheduler->msqlquery, "maxnewest", "0", rec_id);
93.584 - _set_value(scheduler->msqlquery, "autocommflag", "1", rec_id);
93.585 - _set_value(scheduler->msqlquery, "autotranscode", "0", rec_id);
93.586 - _set_value(scheduler->msqlquery, "transcoder", "0", rec_id);
93.587 -
93.588 - _set_value(scheduler->msqlquery, "autouserjob1", "0", rec_id);
93.589 - _set_value(scheduler->msqlquery, "autouserjob2", "0", rec_id);
93.590 - _set_value(scheduler->msqlquery, "autouserjob3", "0", rec_id);
93.591 - _set_value(scheduler->msqlquery, "autouserjob4", "0", rec_id);
93.592 -
93.593 - schedule_info->schedule_id = rec_id;
93.594 -
93.595 - /* Notify the backend of changes */
93.596 - return update_backend(scheduler, rec_id);
93.597 -}
93.598 -
93.599 -/** Requests the Mysql database in the backend to add a new schedule.
93.600 - *
93.601 - * @param scheduler the GMythScheduler instance.
93.602 - * @param schedule_info the ScheduleInfo with recording schedule information
93.603 - * to be added. record_id = -1 to add a new schedule, otherwise this
93.604 - * function will update the schedule in the db
93.605 - * @return gboolean returns FALSE if some error occurs, TRUE otherwise
93.606 - */
93.607 -gboolean
93.608 -gmyth_scheduler_add_schedule (GMythScheduler * scheduler,
93.609 - ScheduleInfo * schedule_info)
93.610 -{
93.611 - return gmyth_scheduler_add_schedule_full (scheduler, schedule_info,
93.612 - GMYTH_SCHEDULE_ONE_OCCURRENCE);
93.613 -}
93.614 -
93.615 -/** Requests the Mysql database in the backend to remove an existing schedule.
93.616 - *
93.617 - * @param scheduler the GMythScheduler instance.
93.618 - * @param schedule_id The schedule's record id to be removed
93.619 - * @return gboolean TRUE if success, FALSE if error
93.620 - */
93.621 -gboolean
93.622 -gmyth_scheduler_delete_schedule(GMythScheduler * scheduler, gint schedule_id)
93.623 -{
93.624 -
93.625 - MYSQL_RES *msql_res;
93.626 - GString *query_str = NULL;
93.627 -
93.628 - g_return_val_if_fail (scheduler != NULL, FALSE);
93.629 -
93.630 -
93.631 - if (scheduler->msqlquery == NULL) {
93.632 - g_warning("[%s] Scheduler db connection not initialized",
93.633 - __FUNCTION__);
93.634 - return FALSE;
93.635 - }
93.636 -
93.637 - query_str = g_string_new("");
93.638 - g_string_printf(query_str,
93.639 - "DELETE FROM record WHERE recordid=%d", schedule_id);
93.640 -
93.641 - msql_res =
93.642 - gmyth_query_process_statement(scheduler->msqlquery,
93.643 - query_str->str);
93.644 -
93.645 -
93.646 - mysql_free_result(msql_res);
93.647 - g_string_free(query_str, TRUE);
93.648 -
93.649 - // Notify the backend of the changes
93.650 - return update_backend(scheduler, schedule_id);
93.651 -}
93.652 -
93.653 -/*
93.654 - * Add an exception program to be removed from the schedule list, when programs
93.655 - * where scheduled with the GMYTH_SCHEDULE_ALL_OCCURRENCES option.
93.656 - * @param scheduler the GMythScheduler instance.
93.657 - * @param schedule_id the schedule id of the all occurrence schedule to be changed
93.658 - * @param exception_info the ScheduleInfo to be removed from all schedule occurrences
93.659 - * @return TRUE if success, FALSE if any error happens
93.660 - */
93.661 -gboolean
93.662 -gmyth_scheduler_add_exception (GMythScheduler *scheduler, gint schedule_id,
93.663 - ScheduleInfo *exception_info)
93.664 -{
93.665 - gboolean res;
93.666 -
93.667 - g_return_val_if_fail (scheduler != NULL, FALSE);
93.668 - g_return_val_if_fail (exception_info != NULL, FALSE);
93.669 -
93.670 - exception_info->parentid = schedule_id;
93.671 - res = gmyth_scheduler_add_schedule_full (scheduler, exception_info, GMYTH_SCHEDULE_EXCEPTION);
93.672 -
93.673 - return res;
93.674 -}
93.675 -
93.676 -/** Requests the Mysql database in the backend to remove an existing recorded item.
93.677 - *
93.678 - * @param scheduler the GMythScheduler instance.
93.679 - * @param record_id The recorded item id to be removed
93.680 - * @return gboolean TRUE if success, FALSE if error
93.681 - */
93.682 -gboolean
93.683 -gmyth_scheduler_delete_recorded(GMythScheduler * scheduler, gint record_id)
93.684 -{
93.685 -
93.686 - MYSQL_RES *msql_res;
93.687 -
93.688 - GString *query_str = g_string_new("");
93.689 -
93.690 - assert(scheduler);
93.691 -
93.692 - if (scheduler->msqlquery == NULL) {
93.693 - g_warning("[%s] Scheduler db connection not initialized",
93.694 - __FUNCTION__);
93.695 - return FALSE;
93.696 - }
93.697 - // ========================================
93.698 - g_string_printf(query_str,
93.699 - "DELETE FROM recorded WHERE recordid=%d", record_id);
93.700 -
93.701 - // FIXME: Mythtv implementation runs also: DELETE FROM oldfind WHERE
93.702 - // recordid = x
93.703 -
93.704 - msql_res =
93.705 - gmyth_query_process_statement(scheduler->msqlquery,
93.706 - query_str->str);
93.707 -
93.708 - mysql_free_result(msql_res);
93.709 - g_string_free(query_str, TRUE);
93.710 -
93.711 - // Notify the backend of the changes
93.712 - return update_backend(scheduler, record_id);
93.713 -}
93.714 -
93.715 -
93.716 -gboolean gmyth_scheduler_was_recorded_before(GMythScheduler* scheduler, gint channel_id,
93.717 - time_t start_time)
93.718 -{
93.719 - MYSQL_RES *msql_res;
93.720 - GString *query_str = g_string_new("");
93.721 -
93.722 - assert(scheduler);
93.723 - g_string_printf(query_str, "SELECT callsign FROM channel "
93.724 - "WHERE chanid = \"%d\"", channel_id);
93.725 -
93.726 - msql_res = gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
93.727 -
93.728 - if (msql_res) {
93.729 - MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
93.730 - if (msql_row) {
93.731 - GString* callsign = g_string_new(msql_row[0]);
93.732 - GString* startts = gmyth_util_time_to_string(start_time);
93.733 - g_string_printf(query_str, "SELECT * FROM oldrecorded "
93.734 - "WHERE station = \"%s\" AND starttime = \"%s\"",
93.735 - callsign->str, startts->str);
93.736 - msql_res = gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
93.737 - g_string_free(callsign, TRUE);
93.738 - g_string_free(startts, TRUE);
93.739 - g_string_free(query_str, TRUE);
93.740 - if (mysql_fetch_row(msql_res)) return TRUE;
93.741 - }
93.742 - }
93.743 - return FALSE;
93.744 -}
93.745 -
93.746 -
93.747 -gboolean gmyth_scheduler_reactivate_schedule(GMythScheduler* scheduler, gint channel_id,
93.748 - time_t start_time)
93.749 -
93.750 -{
93.751 - MYSQL_RES *msql_res;
93.752 - GString *query_str = g_string_new("");
93.753 -
93.754 - assert(scheduler);
93.755 - g_string_printf(query_str, "SELECT callsign FROM channel "
93.756 - "WHERE chanid = \"%d\"", channel_id);
93.757 -
93.758 - msql_res = gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
93.759 - if (msql_res) {
93.760 - MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
93.761 - if (msql_row) {
93.762 - GString* callsign = g_string_new(msql_row[0]);
93.763 - GString* startts = gmyth_util_time_to_string(start_time);
93.764 - g_string_printf(query_str, "UPDATE oldrecorded SET reactivate = 1 "
93.765 - "WHERE station = \"%s\" AND starttime = \"%s\"",
93.766 - callsign->str, startts->str);
93.767 - gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
93.768 - g_string_free(callsign, TRUE);
93.769 - g_string_free(startts, TRUE);
93.770 - g_string_free(query_str, TRUE);
93.771 - return TRUE;
93.772 - }
93.773 -
93.774 - }
93.775 -
93.776 - return FALSE;
93.777 -}
93.778 -
93.779 -
93.780 -/*
93.781 - * This should only be used in special situations. We do not know the time that
93.782 - * the recording was set. We just know that it is an "ongoing" record and then
93.783 - * we have to use this to get it's info. It's always the oldest one -> first on list
93.784 - *
93.785 - */
93.786 -GMythProgramInfo*
93.787 -gmyth_scheduler_get_recorded_on_time(GMythScheduler* scheduler,
93.788 - guint channel_id)
93.789 -{
93.790 - MYSQL_RES *msql_res;
93.791 - GMythProgramInfo *proginfo = NULL;
93.792 - GString *query_str = g_string_new("");
93.793 -
93.794 - assert(scheduler);
93.795 -
93.796 - g_string_printf(query_str,
93.797 - "SELECT recorded.chanid,starttime,endtime,title,"
93.798 - "subtitle,description,channel.channum,"
93.799 - "channel.callsign,channel.name,channel.commfree,"
93.800 - "channel.outputfilters,seriesid,programid,filesize,"
93.801 - "lastmodified,stars,previouslyshown,originalairdate,"
93.802 - "hostname,recordid,transcoder,playgroup,"
93.803 - "recorded.recpriority,progstart,progend,basename,recgroup,"
93.804 - "category,findid,duplicate "
93.805 - "FROM recorded " "LEFT JOIN channel "
93.806 - "ON recorded.chanid = channel.chanid "
93.807 - "WHERE recorded.chanid = %d "
93.808 - "ORDER BY starttime DESC", channel_id);
93.809 -
93.810 - msql_res =
93.811 - gmyth_query_process_statement(scheduler->msqlquery, query_str->str);
93.812 -
93.813 - if (msql_res) {
93.814 - MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
93.815 -
93.816 - if (msql_row) {
93.817 - proginfo = gmyth_program_info_new();
93.818 -
93.819 - proginfo->channel_id = (gint) g_ascii_strtoull (msql_row[0], NULL, 10);
93.820 - proginfo->recstartts = gmyth_util_string_to_time_val(msql_row[1]);
93.821 - proginfo->recendts = gmyth_util_string_to_time_val(msql_row[2]);
93.822 -
93.823 - proginfo->title = g_string_new(msql_row[3]);
93.824 - proginfo->subtitle = g_string_new(msql_row[4]);
93.825 - proginfo->description = g_string_new(msql_row[5]);
93.826 -
93.827 - proginfo->chanstr = g_string_new(msql_row[6]);
93.828 - proginfo->chansign = g_string_new(msql_row[7]);
93.829 - proginfo->channame = g_string_new(msql_row[8]);
93.830 - proginfo->chancommfree = (gint) g_ascii_strtoull(msql_row[9], NULL, 10);
93.831 - proginfo->chanOutputFilters = g_string_new(msql_row[10]);
93.832 - proginfo->seriesid = g_string_new(msql_row[11]);
93.833 - proginfo->program_id = g_string_new(msql_row[12]);
93.834 - proginfo->filesize = g_ascii_strtoull(msql_row[13], NULL, 10);
93.835 -
93.836 - proginfo->lastmodified = gmyth_util_string_to_time_val(msql_row[14]);
93.837 - proginfo->stars = g_ascii_strtod(msql_row[15], NULL);
93.838 - proginfo->repeat = (gint)g_ascii_strtoull(msql_row[16], NULL, 10);
93.839 -
93.840 - if (msql_row[17] == NULL) {
93.841 - proginfo->originalAirDate = 0;
93.842 - proginfo->hasAirDate = FALSE;
93.843 - } else {
93.844 - proginfo->originalAirDate = gmyth_util_string_to_time_val(msql_row[17]);
93.845 - proginfo->hasAirDate = TRUE;
93.846 - }
93.847 -
93.848 - proginfo->hostname = g_string_new(msql_row[18]);
93.849 - proginfo->recordid = (gint) g_ascii_strtoull(msql_row[19], NULL, 10);
93.850 - proginfo->transcoder = (gint) g_ascii_strtoull(msql_row[20], NULL, 10);
93.851 -
93.852 - proginfo->playgroup = g_string_new(msql_row[21]);
93.853 - proginfo->recpriority = (gint) g_ascii_strtoull(msql_row[22], NULL, 10);
93.854 -
93.855 - proginfo->startts = gmyth_util_string_to_time_val(msql_row[23]);
93.856 - proginfo->endts = gmyth_util_string_to_time_val(msql_row[24]);
93.857 - proginfo->pathname = g_string_new(g_strdup(msql_row[25]));
93.858 - proginfo->recgroup = g_string_new(msql_row[26]);
93.859 - proginfo->category = g_string_new(msql_row[27]);
93.860 - proginfo->findid = (gint) g_ascii_strtoull(msql_row[28], NULL, 10);
93.861 -
93.862 - proginfo->recpriority2 = 0;
93.863 -
93.864 - g_string_printf(query_str,
93.865 - "SELECT dupmethod,dupin,parentid,type "
93.866 - "FROM record WHERE recordid = \"%d\"", proginfo->recordid);
93.867 -
93.868 - msql_res =
93.869 - gmyth_query_process_statement(scheduler->msqlquery,
93.870 - query_str->str);
93.871 -
93.872 - if (msql_res) {
93.873 - MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
93.874 -
93.875 - if (msql_row) {
93.876 - proginfo->dupmethod = (gint) g_ascii_strtoull(msql_row[0], NULL, 10);
93.877 - proginfo->dupin = (gint) g_ascii_strtoull(msql_row[1], NULL, 10);
93.878 - proginfo->parentid = (gint) g_ascii_strtoull(msql_row[2], NULL, 10);
93.879 - proginfo->rectype = 0;
93.880 - }
93.881 - }
93.882 -
93.883 -
93.884 - g_string_printf(query_str,
93.885 - "SELECT sourceid,cardid,cardinputid,shareable "
93.886 - "FROM cardinput");
93.887 -
93.888 - msql_res =
93.889 - gmyth_query_process_statement(scheduler->msqlquery,
93.890 - query_str->str);
93.891 -
93.892 - if (msql_res) {
93.893 - MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
93.894 -
93.895 - if (msql_row) {
93.896 - proginfo->sourceid = 0;
93.897 - proginfo->cardid = 0;
93.898 - proginfo->inputid = 0;
93.899 - if (msql_row[3] != NULL && g_ascii_strcasecmp("Y", msql_row[3]) == 0)
93.900 - proginfo->shareable = 1;
93.901 - else
93.902 - proginfo->shareable = 0;
93.903 - }
93.904 - }
93.905 -
93.906 -
93.907 -
93.908 - }
93.909 - }
93.910 -
93.911 - g_string_free(query_str, TRUE);
93.912 - return proginfo;
93.913 -}
93.914 -
93.915 -/** Retrieves an existing recorded item information from database. The information
93.916 - * is used to fill the returned GMythProgramInfo.
93.917 - *
93.918 - * @param scheduler The GMythScheduler instance.
93.919 - * @param channel The channel associated to the record
93.920 - * @param starttime The record start time
93.921 - * @return A GMythProgramInfo struct with the requested record item
93.922 - * information, or NULL if error.
93.923 - */
93.924 -GMythProgramInfo *
93.925 -gmyth_scheduler_get_recorded(GMythScheduler * scheduler,
93.926 - GString * channel, GTimeVal * starttime)
93.927 -{
93.928 - MYSQL_RES *msql_res;
93.929 - GMythProgramInfo *proginfo = NULL;
93.930 - GString *query_str = g_string_new("");
93.931 - gchar *time_str =
93.932 - gmyth_util_time_to_string_from_time_val(starttime);
93.933 -
93.934 - assert(scheduler);
93.935 -
93.936 - gmyth_debug("[%s] channel: %s", __FUNCTION__, channel->str);
93.937 -
93.938 - if (scheduler->msqlquery == NULL) {
93.939 - g_warning("[%s] Scheduler db connection not initialized",
93.940 - __FUNCTION__);
93.941 - return NULL;
93.942 - }
93.943 -
93.944 - g_string_printf(query_str,
93.945 - "SELECT recorded.chanid,starttime,endtime,title, "
93.946 - "subtitle,description,channel.channum, "
93.947 - "channel.callsign,channel.name,channel.commfree, "
93.948 - "channel.outputfilters,seriesid,programid,filesize, "
93.949 - "lastmodified,stars,previouslyshown,originalairdate, "
93.950 - "hostname,recordid,transcoder,playgroup, "
93.951 - "recorded.recpriority,progstart,progend,basename,recgroup "
93.952 - "FROM recorded " "LEFT JOIN channel "
93.953 - "ON recorded.chanid = channel.chanid "
93.954 - "WHERE recorded.chanid = \"%s\" "
93.955 - "AND starttime = \"%s\" ;", channel->str, time_str);
93.956 -
93.957 - msql_res =
93.958 - gmyth_query_process_statement(scheduler->msqlquery,
93.959 - query_str->str);
93.960 -
93.961 - if (msql_res /* && query.size() > 0 */ ) {
93.962 - MYSQL_ROW msql_row = mysql_fetch_row(msql_res);
93.963 -
93.964 - if (msql_row) {
93.965 - proginfo = gmyth_program_info_new();
93.966 -
93.967 - proginfo->channel_id = (gint) g_ascii_strtoull (msql_row[0], NULL, 10);
93.968 - proginfo->startts =
93.969 - gmyth_util_string_to_time_val(msql_row[23]);
93.970 - proginfo->endts = gmyth_util_string_to_time_val(msql_row[24]);
93.971 - proginfo->recstartts =
93.972 - gmyth_util_string_to_time_val(msql_row[1]);
93.973 - proginfo->recendts =
93.974 - gmyth_util_string_to_time_val(msql_row[2]);
93.975 - proginfo->title = g_string_new(msql_row[3]);
93.976 - proginfo->subtitle = g_string_new(msql_row[4]);
93.977 - proginfo->description = g_string_new(msql_row[5]);
93.978 -
93.979 - proginfo->chanstr = g_string_new(msql_row[6]);
93.980 - proginfo->chansign = g_string_new(msql_row[7]);
93.981 - proginfo->channame = g_string_new(msql_row[0]);
93.982 - proginfo->chancommfree =
93.983 - (gint) g_ascii_strtoull(msql_row[9], NULL, 10);
93.984 - proginfo->chanOutputFilters = g_string_new(msql_row[10]);
93.985 - proginfo->seriesid = g_string_new(msql_row[11]);
93.986 - proginfo->program_id = g_string_new(msql_row[12]);
93.987 - proginfo->filesize = g_ascii_strtoull(msql_row[13], NULL, 10);
93.988 -
93.989 - proginfo->lastmodified =
93.990 - gmyth_util_string_to_time_val(msql_row[14]);
93.991 - proginfo->stars = g_ascii_strtod(msql_row[15], NULL);
93.992 - proginfo->repeat =
93.993 - (gint) g_ascii_strtoull(msql_row[16], NULL, 10);
93.994 -
93.995 - if (msql_row[17] == NULL) {
93.996 - proginfo->originalAirDate = 0;
93.997 - proginfo->hasAirDate = FALSE;
93.998 - } else {
93.999 - proginfo->originalAirDate =
93.1000 - gmyth_util_string_to_time_val(msql_row[17]);
93.1001 - proginfo->hasAirDate = TRUE;
93.1002 - }
93.1003 -
93.1004 - proginfo->hostname = g_string_new(msql_row[18]);
93.1005 - proginfo->recordid =
93.1006 - (gint) g_ascii_strtoull(msql_row[19], NULL, 10);
93.1007 - proginfo->transcoder =
93.1008 - (gint) g_ascii_strtoull(msql_row[20], NULL, 10);
93.1009 - // proginfo->spread = -1;
93.1010 - // proginfo->programflags = proginfo->getProgramFlags();
93.1011 -
93.1012 - proginfo->recgroup = g_string_new(msql_row[26]);
93.1013 - proginfo->playgroup = g_string_new(msql_row[21]);
93.1014 - proginfo->recpriority =
93.1015 - (gint) g_ascii_strtoull(msql_row[22], NULL, 10);
93.1016 -
93.1017 - proginfo->pathname = g_string_new(g_strdup(msql_row[25]));
93.1018 -
93.1019 - gmyth_debug("One program info loaded from mysql database\n");
93.1020 - }
93.1021 - }
93.1022 -
93.1023 - mysql_free_result(msql_res);
93.1024 - g_string_free(query_str, TRUE);
93.1025 - g_free(time_str);
93.1026 -
93.1027 - return proginfo;
93.1028 -}
93.1029 -
93.1030 -gboolean
93.1031 -gmyth_scheduler_stop_recording (GMythScheduler * scheduler,
93.1032 - gint channel_id)
93.1033 -{
93.1034 - GMythProgramInfo *program;
93.1035 - GMythSocket *socket;
93.1036 - gboolean res = FALSE;
93.1037 - GMythStringList *slist;
93.1038 -
93.1039 - socket = gmyth_backend_info_get_connected_socket (scheduler->backend_info);
93.1040 - program = gmyth_scheduler_get_recorded_on_time (scheduler, channel_id);
93.1041 -
93.1042 - if (program) {
93.1043 - slist = gmyth_string_list_new();
93.1044 - gmyth_string_list_append_char_array(slist, "STOP_RECORDING");
93.1045 -
93.1046 - gmyth_string_list_append_string(slist, program->title); /* 0 */
93.1047 - gmyth_string_list_append_string(slist, program->subtitle); /* 1 */
93.1048 - gmyth_string_list_append_string(slist, program->description); /* 2 */
93.1049 - gmyth_string_list_append_string(slist, program->category); /* 3 */
93.1050 - gmyth_string_list_append_int(slist, program->channel_id); /* 4 */
93.1051 - gmyth_string_list_append_string(slist, program->chanstr); /* 5 */
93.1052 - gmyth_string_list_append_string(slist, program->chansign); /* 6 */
93.1053 - gmyth_string_list_append_string(slist, program->channame); /* 7 */
93.1054 - gmyth_string_list_append_string(slist, program->pathname); /* 8 */
93.1055 - gmyth_string_list_append_int64(slist, program->filesize); /* 9 */
93.1056 -
93.1057 - if (program->startts)
93.1058 - gmyth_string_list_append_int(slist, program->startts->tv_sec); /* 10 */
93.1059 - else
93.1060 - gmyth_string_list_append_int(slist, 0);
93.1061 -
93.1062 - if (program->endts)
93.1063 - gmyth_string_list_append_int(slist, program->endts->tv_sec); /* 11 */
93.1064 - else
93.1065 - gmyth_string_list_append_int(slist, 0);
93.1066 -
93.1067 - gmyth_string_list_append_int(slist, program->duplicate); /* 12 */
93.1068 - gmyth_string_list_append_int(slist, program->shareable); /* 13 */
93.1069 - gmyth_string_list_append_int(slist, program->findid); /* 14 */
93.1070 - gmyth_string_list_append_string(slist, program->hostname); /* 15 */
93.1071 - gmyth_string_list_append_int(slist, program->sourceid); /* 16 */
93.1072 - gmyth_string_list_append_int(slist, program->cardid); /* 17 */
93.1073 - gmyth_string_list_append_int(slist, program->inputid); /* 18 */
93.1074 - gmyth_string_list_append_int(slist, program->recpriority); /* 19 */
93.1075 -
93.1076 - // recstatus == recording
93.1077 - gmyth_string_list_append_int(slist, -3); /* 20 */
93.1078 -
93.1079 - gmyth_string_list_append_int(slist, program->recordid); /* 21 */
93.1080 - gmyth_string_list_append_int(slist, program->rectype); /* 22 */
93.1081 - gmyth_string_list_append_int(slist, program->dupin); /* 23 */
93.1082 - gmyth_string_list_append_int(slist, program->dupmethod); /* 24 */
93.1083 -
93.1084 -
93.1085 - //fixme
93.1086 - program->recstartts->tv_sec -= (60*60);
93.1087 -
93.1088 - gmyth_string_list_append_int(slist,
93.1089 - program->recstartts != NULL ?
93.1090 - program->recstartts->tv_sec : 0); /* 26 */
93.1091 -
93.1092 - gmyth_string_list_append_int(slist,
93.1093 - program->recendts != NULL ?
93.1094 - program->recendts->tv_sec : 0); /* 27 */
93.1095 -
93.1096 - gmyth_string_list_append_int(slist, program->repeat); /* 28 */
93.1097 - gmyth_string_list_append_int(slist, program->programflags); /* 29 */
93.1098 -
93.1099 - gmyth_string_list_append_char_array(slist,
93.1100 - program->recgroup != NULL ?
93.1101 - program->recgroup->str : "Default"); /* 30 */
93.1102 -
93.1103 - gmyth_string_list_append_int(slist, program->chancommfree); /* 31 */
93.1104 - gmyth_string_list_append_string(slist, program->chanOutputFilters); /* 32 */
93.1105 - gmyth_string_list_append_string(slist, program->seriesid); /* 33 */
93.1106 - gmyth_string_list_append_string(slist, program->program_id); /* 34 */
93.1107 -
93.1108 - gmyth_string_list_append_int(slist,
93.1109 - program->lastmodified != NULL ?
93.1110 - program->lastmodified->tv_sec : 0); /* 35 */
93.1111 -
93.1112 - gmyth_string_list_append_float(slist, program->stars); /* 36 */
93.1113 -
93.1114 - gmyth_string_list_append_int(slist,
93.1115 - program->originalAirDate != NULL ?
93.1116 - program->originalAirDate->tv_sec : 0); /* 37 */
93.1117 -
93.1118 - gmyth_string_list_append_int(slist, program->hasAirDate); /* 38 */
93.1119 -
93.1120 - gmyth_string_list_append_char_array(slist,
93.1121 - program->playgroup != NULL ?
93.1122 - program->playgroup->str : "Default"); /* 39 */
93.1123 -
93.1124 - gmyth_string_list_append_int(slist, program->recpriority2); /* 40 */
93.1125 - gmyth_string_list_append_int(slist, program->recpriority2); /* 40 */
93.1126 -
93.1127 - gmyth_socket_sendreceive_stringlist(socket, slist);
93.1128 - res = (gmyth_string_list_get_int(slist, 0) == 1);
93.1129 -
93.1130 - g_object_unref (program);
93.1131 - g_object_unref (slist);
93.1132 - }
93.1133 -
93.1134 - g_object_unref (socket);
93.1135 - return res;
93.1136 -}
93.1137 -
93.1138 -
93.1139 -/** Notifies the backend of an update in the db.
93.1140 - *
93.1141 - * @param record_id the id of the modified recording.
93.1142 - */
93.1143 -// fixme: put void and discovery record_id inside
93.1144 -static gboolean
93.1145 -update_backend (GMythScheduler * scheduler,
93.1146 - gint record_id)
93.1147 -{
93.1148 - GMythSocket *socket;
93.1149 - GMythStringList *strlist = gmyth_string_list_new();
93.1150 - GString *datastr = g_string_new("RESCHEDULE_RECORDINGS ");
93.1151 - gboolean ret = FALSE;
93.1152 -
93.1153 - g_string_append_printf(datastr, "%d", record_id);
93.1154 - gmyth_string_list_append_string(strlist, datastr);
93.1155 -
93.1156 - socket = gmyth_backend_info_get_connected_socket (scheduler->backend_info);
93.1157 - if (socket != NULL) {
93.1158 - ret = (gmyth_socket_sendreceive_stringlist(socket, strlist) > 0);
93.1159 - g_object_unref (socket);
93.1160 - } else {
93.1161 - g_warning("[%s] Connection to backend failed!", __FUNCTION__);
93.1162 - }
93.1163 -
93.1164 - g_string_free(datastr, TRUE);
93.1165 - g_object_unref(strlist);
93.1166 - return ret;
93.1167 -}
93.1168 -
93.1169 -void
93.1170 -gmyth_scheduler_recorded_info_get_preview(RecordedInfo * info,
93.1171 - GByteArray * data)
93.1172 -{
93.1173 -}
93.1174 -
93.1175 -void
93.1176 -gmyth_recorded_info_free(RecordedInfo * info)
93.1177 -{
93.1178 - g_return_if_fail (info != NULL);
93.1179 -
93.1180 - if (info->program_id)
93.1181 - g_string_free (info->program_id, TRUE);
93.1182 -
93.1183 - if (info->title != NULL)
93.1184 - g_string_free(info->title, TRUE);
93.1185 -
93.1186 - if (info->subtitle != NULL)
93.1187 - g_string_free(info->subtitle, TRUE);
93.1188 -
93.1189 - if (info->description != NULL)
93.1190 - g_string_free(info->description, TRUE);
93.1191 -
93.1192 - if (info->category != NULL)
93.1193 - g_string_free(info->category, TRUE);
93.1194 -
93.1195 - if (info->basename != NULL)
93.1196 - g_string_free(info->basename, TRUE);
93.1197 -
93.1198 - if (info != NULL)
93.1199 - g_free(info->start_time);
93.1200 -
93.1201 - if (info != NULL)
93.1202 - g_free(info->end_time);
93.1203 -
93.1204 - g_free(info);
93.1205 -}
93.1206 -
93.1207 -static void
93.1208 -free_recorded_info_item(gpointer data, gpointer user_data)
93.1209 -{
93.1210 - RecordedInfo *info = (RecordedInfo *) data;
93.1211 -
93.1212 - gmyth_recorded_info_free(info);
93.1213 -}
93.1214 -
93.1215 -void
93.1216 -gmyth_recorded_info_list_free(GList * list)
93.1217 -{
93.1218 - g_return_if_fail(list != NULL);
93.1219 -
93.1220 - g_list_foreach(list, free_recorded_info_item, NULL);
93.1221 - g_list_free(list);
93.1222 -}
93.1223 -
93.1224 -void
93.1225 -gmyth_schedule_info_free(ScheduleInfo * info)
93.1226 -{
93.1227 -
93.1228 - g_return_if_fail(info != NULL);
93.1229 -
93.1230 - if (info->program_id)
93.1231 - g_string_free (info->program_id, TRUE);
93.1232 -
93.1233 - if (info->title != NULL)
93.1234 - g_string_free(info->title, TRUE);
93.1235 -
93.1236 - if (info->subtitle != NULL)
93.1237 - g_string_free(info->subtitle, TRUE);
93.1238 -
93.1239 - if (info->description != NULL)
93.1240 - g_string_free(info->description, TRUE);
93.1241 -
93.1242 - if (info->category != NULL)
93.1243 - g_string_free(info->category, TRUE);
93.1244 -
93.1245 - if (info != NULL)
93.1246 - g_free(info->start_time);
93.1247 -
93.1248 - if (info != NULL)
93.1249 - g_free(info->end_time);
93.1250 -
93.1251 - g_free(info);
93.1252 -}
93.1253 -
93.1254 -static void
93.1255 -free_schedule_info_item(gpointer data, gpointer user_data)
93.1256 -{
93.1257 - ScheduleInfo *info = (ScheduleInfo *) data;
93.1258 -
93.1259 - gmyth_schedule_info_free(info);
93.1260 -}
93.1261 -
93.1262 -void
93.1263 -gmyth_schedule_info_list_free(GList * list)
93.1264 -{
93.1265 - g_return_if_fail(list != NULL);
93.1266 -
93.1267 - g_list_foreach(list, free_schedule_info_item, NULL);
93.1268 - g_list_free(list);
93.1269 -}
94.1 --- a/gmyth/src/gmyth_scheduler.h Mon Feb 25 17:45:36 2008 +0000
94.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
94.3 @@ -1,194 +0,0 @@
94.4 -/**
94.5 - * GMyth Library
94.6 - *
94.7 - * @file gmyth/gmyth_scheduler.h
94.8 - *
94.9 - * @brief <p> The scheduler encapsulates all functions for browsing, scheduling
94.10 - * and modifying the recorded content.
94.11 - *
94.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
94.13 - * @author Alexsandro Jose Virginio dos Santos <alexsandro.santos@indt.org.br>
94.14 - *
94.15 - *
94.16 - * This program is free software; you can redistribute it and/or modify
94.17 - * it under the terms of the GNU Lesser General Public License as published by
94.18 - * the Free Software Foundation; either version 2 of the License, or
94.19 - * (at your option) any later version.
94.20 - *
94.21 - * This program is distributed in the hope that it will be useful,
94.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
94.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
94.24 - * GNU General Public License for more details.
94.25 - *
94.26 - * You should have received a copy of the GNU Lesser General Public License
94.27 - * along with this program; if not, write to the Free Software
94.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
94.29 - */
94.30 -
94.31 -#ifndef __GMYTH_SCHEDULER_H__
94.32 -#define __GMYTH_SCHEDULER_H__
94.33 -
94.34 -#include <glib-object.h>
94.35 -#include <time.h>
94.36 -
94.37 -#include "gmyth_common.h"
94.38 -#include "gmyth_query.h"
94.39 -#include "gmyth_backendinfo.h"
94.40 -
94.41 -G_BEGIN_DECLS
94.42 -
94.43 -typedef enum {
94.44 - GMYTH_SCHEDULE_ONE_OCCURRENCE,
94.45 - GMYTH_SCHEDULE_ALL_OCCURRENCES,
94.46 - GMYTH_SCHEDULE_EXCEPTION
94.47 -} GMythScheduleType;
94.48 -
94.49 -
94.50 -#define GMYTH_SCHEDULER_TYPE (gmyth_scheduler_get_type ())
94.51 -#define GMYTH_SCHEDULER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SCHEDULER_TYPE, GMythScheduler))
94.52 -#define GMYTH_SCHEDULER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SCHEDULER_TYPE, GMythSchedulerClass))
94.53 -#define IS_GMYTH_SCHEDULER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_SCHEDULER_TYPE))
94.54 -#define IS_GMYTH_SCHEDULER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SCHEDULER_TYPE))
94.55 -#define GMYTH_SCHEDULER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_SCHEDULER_TYPE, GMythSchedulerClass))
94.56 -
94.57 -typedef struct _GMythScheduler GMythScheduler;
94.58 -typedef struct _GMythSchedulerClass GMythSchedulerClass;
94.59 -
94.60 -struct _GMythSchedulerClass {
94.61 - GObjectClass parent_class;
94.62 -};
94.63 -
94.64 -struct _GMythScheduler {
94.65 - GObject parent;
94.66 -
94.67 - unsigned long recordid;
94.68 - unsigned long type;
94.69 - unsigned long search;
94.70 - GString *profile;
94.71 -
94.72 - long dupin;
94.73 - long dupmethod;
94.74 - long autoexpire;
94.75 - short int autotranscode;
94.76 - long transcoder;
94.77 -
94.78 - short int autocommflag;
94.79 - short int autouserjob1;
94.80 - short int autouserjob2;
94.81 - short int autouserjob3;
94.82 - short int autouserjob4;
94.83 -
94.84 - long startoffset;
94.85 - long endoffset;
94.86 - long maxepisodes;
94.87 - long maxnewest;
94.88 -
94.89 - long recpriority;
94.90 - GString *recgroup;
94.91 - GString *playgroup;
94.92 -
94.93 - long prefinput;
94.94 - short int inactive;
94.95 -
94.96 - GString *search_type;
94.97 - GString *search_what;
94.98 -
94.99 - GMythQuery *msqlquery;
94.100 - GMythBackendInfo *backend_info;
94.101 -};
94.102 -
94.103 -typedef struct {
94.104 - guint schedule_id;
94.105 - gint channel_id;
94.106 - GString *program_id;
94.107 -
94.108 - GTimeVal *start_time;
94.109 - GTimeVal *end_time;
94.110 -
94.111 - GString *seriesid;
94.112 - GString *title;
94.113 - GString *subtitle;
94.114 - GString *description;
94.115 - GString *category;
94.116 -
94.117 - GMythScheduleType type;
94.118 -
94.119 - gint parentid;
94.120 -
94.121 -} ScheduleInfo;
94.122 -
94.123 -typedef struct {
94.124 - guint record_id;
94.125 - gint channel_id;
94.126 - GString *program_id;
94.127 -
94.128 - GTimeVal *start_time;
94.129 - GTimeVal *end_time;
94.130 -
94.131 - GString *seriesid;
94.132 - GString *title;
94.133 - GString *subtitle;
94.134 - GString *description;
94.135 - GString *category;
94.136 -
94.137 - GString *basename;
94.138 -
94.139 - guint64 filesize;
94.140 -
94.141 -} RecordedInfo;
94.142 -
94.143 -
94.144 -GType gmyth_scheduler_get_type (void);
94.145 -
94.146 -GMythScheduler* gmyth_scheduler_new (void);
94.147 -gboolean gmyth_scheduler_connect (GMythScheduler * scheduler,
94.148 - GMythBackendInfo * backend_info);
94.149 -gboolean gmyth_scheduler_connect_with_timeout (GMythScheduler * scheduler,
94.150 - GMythBackendInfo * backend_info,
94.151 - guint timeout);
94.152 -gboolean gmyth_scheduler_disconnect (GMythScheduler * scheduler);
94.153 -gint gmyth_scheduler_get_schedule_list (GMythScheduler * scheduler,
94.154 - GList ** sched_list);
94.155 -gint gmyth_scheduler_get_recorded_list (GMythScheduler * scheduler,
94.156 - GList ** rec_list);
94.157 -RecordedInfo* gmyth_scheduler_get_recorded_info (GMythScheduler *scheduler,
94.158 - const char *basename);
94.159 -gboolean gmyth_scheduler_was_recorded_before (GMythScheduler* scheduler,
94.160 - gint channel_id,
94.161 - time_t start_time);
94.162 -gboolean gmyth_scheduler_reactivate_schedule (GMythScheduler* scheduler,
94.163 - gint channel_id,
94.164 - time_t start_time);
94.165 -GMythProgramInfo* gmyth_scheduler_get_recorded_on_time (GMythScheduler* scheduler,
94.166 - guint channel_id);
94.167 -GMythProgramInfo* gmyth_scheduler_get_recorded (GMythScheduler * scheduler,
94.168 - GString * channel,
94.169 - GTimeVal * starttime);
94.170 -ScheduleInfo* gmyth_scheduler_add_schedule_program (GMythScheduler * scheduler,
94.171 - GMythProgramInfo *program,
94.172 - GMythScheduleType type);
94.173 -gint gmyth_scheduler_add_schedule (GMythScheduler * scheduler,
94.174 - ScheduleInfo * schedule_info);
94.175 -gboolean gmyth_scheduler_add_schedule_full (GMythScheduler * scheduler,
94.176 - ScheduleInfo * schedule_info,
94.177 - GMythScheduleType type);
94.178 -gboolean gmyth_scheduler_add_exception (GMythScheduler *scheduler,
94.179 - gint schedule_id,
94.180 - ScheduleInfo *exception_info);
94.181 -gboolean gmyth_scheduler_delete_schedule (GMythScheduler * scheduler,
94.182 - gint record_id);
94.183 -gint gmyth_scheduler_delete_recorded (GMythScheduler * scheduler,
94.184 - gint record_id);
94.185 -gboolean gmyth_scheduler_stop_recording (GMythScheduler * scheduler,
94.186 - gint channel_id);
94.187 -void gmyth_scheduler_recorded_info_get_preview(RecordedInfo * info,
94.188 - GByteArray * data);
94.189 -
94.190 -
94.191 -void gmyth_recorded_info_free (RecordedInfo * info);
94.192 -void gmyth_schedule_info_free (ScheduleInfo * info);
94.193 -void gmyth_recorded_info_list_free (GList * list);
94.194 -void gmyth_schedule_info_list_free (GList * list);
94.195 -
94.196 -G_END_DECLS
94.197 -#endif /* __GMYTH_SCHEDULER_H__ */
95.1 --- a/gmyth/src/gmyth_socket.c Mon Feb 25 17:45:36 2008 +0000
95.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
95.3 @@ -1,1295 +0,0 @@
95.4 -/**
95.5 - * GMyth Library
95.6 - *
95.7 - * @file gmyth/gmyth_socket.c
95.8 - *
95.9 - * @brief <p> MythTV socket implementation, according to the MythTV Project
95.10 - * (www.mythtv.org).
95.11 - *
95.12 - * This component provides basic socket functionalities to interact with
95.13 - * the Mythtv backend.
95.14 - * <p>
95.15 - *
95.16 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
95.17 - * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
95.18 - *
95.19 - *
95.20 - * This program is free software; you can redistribute it and/or modify
95.21 - * it under the terms of the GNU Lesser General Public License as published by
95.22 - * the Free Software Foundation; either version 2 of the License, or
95.23 - * (at your option) any later version.
95.24 - *
95.25 - * This program is distributed in the hope that it will be useful,
95.26 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
95.27 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
95.28 - * GNU General Public License for more details.
95.29 - *
95.30 - * You should have received a copy of the GNU Lesser General Public License
95.31 - * along with this program; if not, write to the Free Software
95.32 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
95.33 - */
95.34 -
95.35 -#ifdef HAVE_CONFIG_H
95.36 -#include "config.h"
95.37 -#endif
95.38 -
95.39 -#include "gmyth_socket.h"
95.40 -
95.41 -#include <glib.h>
95.42 -#include <glib/gprintf.h>
95.43 -
95.44 -#include <arpa/inet.h>
95.45 -#include <sys/types.h>
95.46 -#include <sys/socket.h>
95.47 -#include <sys/param.h>
95.48 -#include <netdb.h>
95.49 -#include <net/if.h>
95.50 -#include <errno.h>
95.51 -#include <assert.h>
95.52 -#include <stdlib.h>
95.53 -
95.54 -#include <unistd.h>
95.55 -#include <netinet/in.h>
95.56 -#include <fcntl.h>
95.57 -#include <signal.h>
95.58 -
95.59 -#include <sys/ioctl.h>
95.60 -
95.61 -#include "gmyth_stringlist.h"
95.62 -#include "gmyth_uri.h"
95.63 -#include "gmyth_debug.h"
95.64 -
95.65 -#define BUFLEN 512
95.66 -#define MYTH_SEPARATOR "[]:[]"
95.67 -#define MYTH_PROTOCOL_FIELD_SIZE 8
95.68 -
95.69 -/*
95.70 - * max number of iterations
95.71 - */
95.72 -#define MYTHTV_MAX_VERSION_CHECKS 40
95.73 -
95.74 -// FIXME: put this in the right place
95.75 -#define MYTHTV_VERSION_DEFAULT 31
95.76 -
95.77 -/*
95.78 - * static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
95.79 - */
95.80 -
95.81 -/*
95.82 - * static GStaticRWLock rwlock = G_STATIC_RW_LOCK_INIT;
95.83 - */
95.84 -
95.85 -static gchar *local_hostname = NULL;
95.86 -
95.87 -static void gmyth_socket_class_init(GMythSocketClass * klass);
95.88 -static void gmyth_socket_init(GMythSocket * object);
95.89 -
95.90 -static void gmyth_socket_dispose(GObject * object);
95.91 -static void gmyth_socket_finalize(GObject * object);
95.92 -
95.93 -G_DEFINE_TYPE(GMythSocket, gmyth_socket, G_TYPE_OBJECT)
95.94 - static void gmyth_socket_class_init(GMythSocketClass * klass)
95.95 -{
95.96 - GObjectClass *gobject_class;
95.97 -
95.98 - gobject_class = (GObjectClass *) klass;
95.99 -
95.100 - gobject_class->dispose = gmyth_socket_dispose;
95.101 - gobject_class->finalize = gmyth_socket_finalize;
95.102 -}
95.103 -
95.104 -static void
95.105 -gmyth_socket_init(GMythSocket * gmyth_socket)
95.106 -{
95.107 -
95.108 - /*
95.109 - * gmyth_socket->local_hostname = NULL;
95.110 - */
95.111 -
95.112 -}
95.113 -
95.114 -/** Gets the some important address translation info, from the client socket
95.115 - * that will open a connection.
95.116 - *
95.117 - * @return gint that represents the error number from getaddrinfo().
95.118 - */
95.119 -static gint
95.120 -gmyth_socket_toaddrinfo(const gchar * addr, gint port,
95.121 - struct addrinfo **addrInfo)
95.122 -{
95.123 - struct addrinfo hints;
95.124 - gchar *portStr = NULL;
95.125 - gint errorn = EADDRNOTAVAIL;
95.126 -
95.127 - g_return_val_if_fail(addr != NULL, -1);
95.128 -
95.129 - memset(&hints, 0, sizeof(struct addrinfo));
95.130 - hints.ai_family = AF_INET;
95.131 - hints.ai_socktype = SOCK_STREAM;
95.132 - /*
95.133 - * hints.ai_flags = AI_NUMERICHOST;
95.134 - */
95.135 -
95.136 - if (port != -1)
95.137 - portStr = g_strdup_printf("%d", port);
95.138 - else
95.139 - portStr = NULL;
95.140 -
95.141 - gmyth_debug("Getting name resolution for: %s, %d\n", addr, port);
95.142 -
95.143 - if ((errorn = getaddrinfo(addr, portStr, &hints, addrInfo)) != 0) {
95.144 - gmyth_debug("[%s] Socket ERROR: %s\n", __FUNCTION__,
95.145 - gai_strerror(errorn));
95.146 - }
95.147 -
95.148 - g_free(portStr);
95.149 -
95.150 - return errorn;
95.151 -}
95.152 -
95.153 -/*
95.154 - * static gint gmyth_socket_find_match_address_uri( GMythURI* uri, gchar
95.155 - * *address ) { if ( g_ascii_strcasecmp( gmyth_uri_get_host( uri ),
95.156 - * address ) == 0 ) { //gmyth_debug( "Found URI: %s !!!\n",
95.157 - * rui_uri_getvalue(uri) ); return 0; } else { return -1; } }
95.158 - */
95.159 -
95.160 -const gchar *PATH_PROC_NET_DEV = "/proc/net/dev";
95.161 -
95.162 -/** Gets the list of all local network interfaces (using the /proc/net/dev directory).
95.163 - *
95.164 - * @param current_connections A list with all the network interfaces are valid,
95.165 - * to be applied just like a filter.
95.166 - * @return List with all the local net interfaces.
95.167 - */
95.168 -GList *
95.169 -gmyth_socket_get_local_addrs(GList * current_connections)
95.170 -{
95.171 -
95.172 - GList *local_addrs = NULL;
95.173 - FILE *fd;
95.174 - gint s;
95.175 - gchar buffer[256 + 1];
95.176 - gchar ifaddr[20 + 1];
95.177 - gchar *ifname;
95.178 - gchar *sep;
95.179 -
95.180 - s = socket(AF_INET, SOCK_DGRAM, 0);
95.181 - if (s < 0)
95.182 - return 0;
95.183 - fd = fopen(PATH_PROC_NET_DEV, "r");
95.184 - fgets(buffer, sizeof(buffer) - 1, fd);
95.185 - fgets(buffer, sizeof(buffer) - 1, fd);
95.186 - while (!feof(fd)) {
95.187 - ifname = buffer;
95.188 -
95.189 - if (fgets(buffer, sizeof(buffer) - 1, fd) == NULL)
95.190 - break;
95.191 - sep = strrchr(buffer, ':');
95.192 - if (sep)
95.193 - *sep = 0;
95.194 - while (*ifname == ' ')
95.195 - ifname++;
95.196 - struct ifreq req;
95.197 -
95.198 - strcpy(req.ifr_name, ifname);
95.199 - if (ioctl(s, SIOCGIFFLAGS, &req) < 0)
95.200 - continue;
95.201 - if (!(req.ifr_flags & IFF_UP))
95.202 - continue;
95.203 - if (req.ifr_flags & IFF_LOOPBACK)
95.204 - continue;
95.205 - if (ioctl(s, SIOCGIFADDR, &req) < 0)
95.206 - continue;
95.207 - g_strlcpy(ifaddr,
95.208 - inet_ntoa(((struct sockaddr_in *) &req.ifr_addr)->
95.209 - sin_addr), sizeof(struct ifaddr) - 1);
95.210 - local_addrs = g_list_append(local_addrs, g_strdup(ifaddr));
95.211 -
95.212 - gmyth_debug
95.213 - ("( from the /proc/net/dev) Interface name: %s, address: %s\n",
95.214 - ifname, ifaddr);
95.215 - }
95.216 - fclose(fd);
95.217 - close(s);
95.218 - return local_addrs;
95.219 -}
95.220 -
95.221 -/**
95.222 - * Get only the local addresses from the primary interface
95.223 - */
95.224 -gchar *
95.225 -gmyth_socket_get_primary_addr(void)
95.226 -{
95.227 - gchar *if_eth0 = g_new0(gchar, sizeof(struct ifaddr) - 1);
95.228 - GList *if_tmp = NULL;
95.229 -
95.230 - GList *interfs = gmyth_socket_get_local_addrs(NULL);
95.231 -
95.232 - if (interfs != NULL && (g_list_length(interfs) > 0)) {
95.233 - // get the first occurrence (primary interface)
95.234 - if_tmp = g_list_first(interfs);
95.235 -
95.236 - if (if_tmp != NULL)
95.237 - g_strlcpy(if_eth0, (gchar *) if_tmp->data,
95.238 - sizeof(struct ifaddr) - 1);
95.239 -
95.240 - }
95.241 -
95.242 - if (interfs != NULL)
95.243 - g_list_free(interfs);
95.244 -
95.245 - return if_eth0;
95.246 -}
95.247 -
95.248 -/** This function retrieves the local hostname of the
95.249 - * client machine.
95.250 - *
95.251 - * @return GString* get local hostname.
95.252 - */
95.253 -GString *
95.254 -gmyth_socket_get_local_hostname(void)
95.255 -{
95.256 - char hname[50];
95.257 - gint res = gethostname(hname, 50);
95.258 -
95.259 - if (res == -1) {
95.260 - gmyth_debug("Error while getting hostname");
95.261 - return g_string_new("default");
95.262 - }
95.263 -
95.264 - return g_string_new(hname);
95.265 -
95.266 -#if 0
95.267 - GString *str = NULL;
95.268 -
95.269 - if (local_hostname != NULL && strlen(local_hostname) > 0)
95.270 - return g_string_new(local_hostname);
95.271 -
95.272 - gchar *localaddr = NULL;
95.273 - gboolean found_addr = FALSE;
95.274 - struct addrinfo *addr_info_data = NULL,
95.275 - *addr_info0 = NULL;
95.276 - struct sockaddr_in *sa = NULL;
95.277 - gchar localhostname[MAXHOSTNAMELEN];
95.278 -
95.279 -
95.280 - if (gethostname(localhostname, MAXHOSTNAMELEN) != 0) {
95.281 - gmyth_debug("Error on gethostname");
95.282 - }
95.283 - localhostname[MAXHOSTNAMELEN - 1] = 0;
95.284 -
95.285 - gint err =
95.286 - gmyth_socket_toaddrinfo(localhostname, -1, &addr_info_data);
95.287 -
95.288 - if (err == EADDRNOTAVAIL) {
95.289 - gmyth_debug("[%s] Address (%s) not available. (reason = %d)\n",
95.290 - __FUNCTION__, localhostname, err);
95.291 - return str;
95.292 - }
95.293 -
95.294 - g_mutex_lock(gmyth_socket->mutex);
95.295 -
95.296 - addr_info0 = addr_info_data;
95.297 -
95.298 - while (addr_info0 != NULL && addr_info0->ai_addr != NULL &&
95.299 - (sa = (struct sockaddr_in *) addr_info0->ai_addr) != NULL
95.300 - && !found_addr) {
95.301 - localaddr = inet_ntoa(sa->sin_addr);
95.302 -
95.303 - if (localaddr != NULL && (g_strrstr(localaddr, "127") == NULL)) {
95.304 - str = g_string_new(localaddr);
95.305 - found_addr = TRUE;
95.306 - g_free(localaddr);
95.307 - break;
95.308 - }
95.309 - /*
95.310 - * if (localaddr != NULL) { g_free (localaddr); localaddr = NULL;
95.311 - * }
95.312 - */
95.313 -
95.314 - addr_info0 = addr_info0->ai_next;
95.315 - };
95.316 -
95.317 - freeaddrinfo(addr_info_data);
95.318 - addr_info_data = NULL;
95.319 -
95.320 - if (found_addr == FALSE) {
95.321 - gchar *prim_addr = gmyth_socket_get_primary_addr();
95.322 -
95.323 - if (prim_addr != NULL) {
95.324 - gmyth_debug
95.325 - ("[%s] Could not determine the local alphanumerical hostname. Setting to %s\n",
95.326 - __FUNCTION__, prim_addr);
95.327 -
95.328 - str = g_string_new(prim_addr);
95.329 - g_free(prim_addr);
95.330 - } else {
95.331 - str = g_string_new(localhostname);
95.332 - }
95.333 - }
95.334 -
95.335 - g_mutex_unlock(gmyth_socket->mutex);
95.336 -
95.337 - if (str != NULL && str->str != NULL)
95.338 - local_hostname = g_strdup(str->str);
95.339 -
95.340 - return str;
95.341 -#endif
95.342 -}
95.343 -
95.344 -static void
95.345 -gmyth_socket_dispose(GObject * object)
95.346 -{
95.347 - GMythSocket *gmyth_socket = GMYTH_SOCKET(object);
95.348 -
95.349 - /*
95.350 - * disconnect socket
95.351 - */
95.352 - gmyth_socket_close_connection(gmyth_socket);
95.353 -
95.354 - g_free(gmyth_socket->hostname);
95.355 -
95.356 - g_free(local_hostname);
95.357 -
95.358 - local_hostname = NULL;
95.359 -
95.360 - if (gmyth_socket->mutex != NULL) {
95.361 - g_mutex_free(gmyth_socket->mutex);
95.362 - gmyth_socket->mutex = NULL;
95.363 - }
95.364 -
95.365 - G_OBJECT_CLASS(gmyth_socket_parent_class)->dispose(object);
95.366 -}
95.367 -
95.368 -static void
95.369 -gmyth_socket_finalize(GObject * object)
95.370 -{
95.371 - g_signal_handlers_destroy(object);
95.372 -
95.373 - G_OBJECT_CLASS(gmyth_socket_parent_class)->finalize(object);
95.374 -}
95.375 -
95.376 -/** Creates a new instance of GMythSocket.
95.377 - *
95.378 - * @return a new instance of GMythSocket.
95.379 - */
95.380 -GMythSocket *
95.381 -gmyth_socket_new()
95.382 -{
95.383 - GMythSocket *gmyth_socket =
95.384 - GMYTH_SOCKET(g_object_new(GMYTH_SOCKET_TYPE, NULL));
95.385 -
95.386 - gmyth_socket->mythtv_version = MYTHTV_VERSION_DEFAULT;
95.387 -
95.388 - gmyth_socket->mutex = g_mutex_new();
95.389 -
95.390 - return gmyth_socket;
95.391 -}
95.392 -
95.393 -/** Try to open an asynchronous connection to the MythTV backend.
95.394 - *
95.395 - * @param fd Socket descriptor.
95.396 - * @param remote Remote address.
95.397 - * @param len Newly created socket length field.
95.398 - * @param timeout Timeval argument with the time interval to timeout before closing.
95.399 - * @param err Error message number.
95.400 - * @return Any numerical value below 0, if an error had been found.
95.401 - */
95.402 -static gint
95.403 -gmyth_socket_try_connect(gint fd, struct sockaddr *remote, gint len,
95.404 - struct timeval *timeout, gint * err)
95.405 -{
95.406 - /*
95.407 - * g_return_val_if_fail( timeout != NULL, 0 );
95.408 - */
95.409 - gint saveflags,
95.410 - ret,
95.411 - back_err;
95.412 -
95.413 - fd_set fd_w;
95.414 -
95.415 - saveflags = fcntl(fd, F_GETFL, 0);
95.416 - if (saveflags < 0) {
95.417 - gmyth_debug("[%s] Problems when getting socket flags on fcntl.\n",
95.418 - __FUNCTION__);
95.419 - *err = errno;
95.420 - return -1;
95.421 - }
95.422 -
95.423 - /*
95.424 - * Set non blocking
95.425 - */
95.426 - if (fcntl(fd, F_SETFL, saveflags | O_NONBLOCK) < 0) {
95.427 - gmyth_debug
95.428 - ("[%s] Problems when setting non-blocking using fcntl.\n",
95.429 - __FUNCTION__);
95.430 - *err = errno;
95.431 - return -1;
95.432 - }
95.433 -
95.434 - /*
95.435 - * This will return immediately
95.436 - */
95.437 - *err = connect(fd, remote, len);
95.438 - back_err = errno;
95.439 -
95.440 - /*
95.441 - * restore flags
95.442 - */
95.443 - if (fcntl(fd, F_SETFL, saveflags) < 0) {
95.444 - gmyth_debug
95.445 - ("[%s] Problems when trying to restore flags with fcntl.\n",
95.446 - __FUNCTION__);
95.447 - *err = errno;
95.448 - return -1;
95.449 - }
95.450 -
95.451 - /*
95.452 - * return unless the connection was successful or the connect is still
95.453 - * in progress.
95.454 - */
95.455 - if (*err < 0 && back_err != EINPROGRESS) {
95.456 - gmyth_debug
95.457 - ("[%s] Connection unsucessfully (it is not in progress).\n",
95.458 - __FUNCTION__);
95.459 - *err = errno;
95.460 - return -1;
95.461 - }
95.462 -
95.463 - FD_ZERO(&fd_w);
95.464 - FD_SET(fd, &fd_w);
95.465 -
95.466 - *err = select(FD_SETSIZE, NULL, &fd_w, NULL, timeout);
95.467 - if (*err < 0) {
95.468 - gmyth_debug("[%s] Connection unsucessfull (timed out).\n",
95.469 - __FUNCTION__);
95.470 - *err = errno;
95.471 - return -1;
95.472 - }
95.473 -
95.474 - /*
95.475 - * 0 means it timeout out & no fds changed
95.476 - */
95.477 - if (*err == 0) {
95.478 - gmyth_debug
95.479 - ("[%s] Connection unsucessfull [%d] - 0 means it timeout out & no fds changed\n",
95.480 - __FUNCTION__, *err);
95.481 - close(fd);
95.482 - *err = ETIMEDOUT;
95.483 - return -1;
95.484 - }
95.485 -
95.486 - /*
95.487 - * Get the return code from the connect
95.488 - */
95.489 - len = sizeof(ret);
95.490 - *err = getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, (socklen_t *) & len);
95.491 -
95.492 - if (*err < 0) {
95.493 - gmyth_debug("[%s] Connection unsucessfull.\n", __FUNCTION__);
95.494 - *err = errno;
95.495 - return -1;
95.496 - }
95.497 -
95.498 - /*
95.499 - * ret=0 means success, otherwise it contains the errno
95.500 - */
95.501 - if (ret) {
95.502 - gmyth_debug
95.503 - ("[%s] Connection unsucessfull - Couldn't connect to remote host!!!\n",
95.504 - __FUNCTION__);
95.505 - *err = ret;
95.506 - return -1;
95.507 - }
95.508 -
95.509 - *err = 0;
95.510 - return 0;
95.511 -}
95.512 -
95.513 -/** Connects to the backend.
95.514 - *
95.515 - * @param gmyth_socket The GMythSocket instance.
95.516 - * @param hostname The backend hostname or IP address.
95.517 - * @param port The backend port.
95.518 - * @return TRUE if success, FALSE if error.
95.519 - */
95.520 -
95.521 -
95.522 -gboolean
95.523 -gmyth_socket_connect(GMythSocket * gmyth_socket,
95.524 - const gchar * hostname, gint port)
95.525 -{
95.526 - return gmyth_socket_connect_with_timeout(gmyth_socket, hostname, port,
95.527 - 30);
95.528 -}
95.529 -
95.530 -gboolean
95.531 -gmyth_socket_connect_with_timeout(GMythSocket * gmyth_socket,
95.532 - const gchar * hostname, gint port,
95.533 - guint timeout)
95.534 -{
95.535 - struct addrinfo *addr_info_data = NULL,
95.536 - *addr_info0 = NULL;
95.537 - struct linger ling;
95.538 - gchar *tmp_str;
95.539 - gint ret_code = 0; /* -1 */
95.540 -
95.541 - /*
95.542 - * FIXME: add as function parameter
95.543 - */
95.544 - gint err;
95.545 - gint errno;
95.546 - gboolean ret = TRUE;
95.547 -
95.548 - gmyth_debug("CONNECTING %s:%d", hostname, port);
95.549 -
95.550 - if (hostname == NULL)
95.551 - gmyth_debug("Invalid hostname parameter!\n");
95.552 -
95.553 - /*
95.554 - * store hostname and port number
95.555 - */
95.556 - gmyth_debug("CONNECTING %s:%d", hostname, port);
95.557 -
95.558 - errno = gmyth_socket_toaddrinfo(hostname, port, &addr_info_data);
95.559 -
95.560 - g_return_val_if_fail(addr_info_data != NULL
95.561 - && hostname != NULL, FALSE);
95.562 -
95.563 - /*
95.564 - * hack to avoid deleting the hostname when gmyth_socket->hostname ==
95.565 - * hostname
95.566 - */
95.567 - tmp_str = gmyth_socket->hostname;
95.568 -
95.569 - gmyth_socket->hostname = g_strdup(hostname);
95.570 - gmyth_socket->port = port;
95.571 -
95.572 - g_free(tmp_str);
95.573 -
95.574 - for (addr_info0 = addr_info_data; addr_info0;
95.575 - addr_info0 = addr_info_data->ai_next) {
95.576 - /*
95.577 - * init socket descriptor
95.578 - */
95.579 -
95.580 - g_debug ("FAMILY: %d, TYPE: %d, PROTOCOL: %d",
95.581 - addr_info0->ai_family,
95.582 - addr_info0->ai_socktype,
95.583 - addr_info0->ai_protocol);
95.584 - gmyth_socket->sd =
95.585 - socket(addr_info0->ai_family, addr_info0->ai_socktype,
95.586 - addr_info0->ai_protocol);
95.587 -
95.588 - if (gmyth_socket->sd < 0)
95.589 - continue;
95.590 -
95.591 - struct timeval *timeout_val = g_new0(struct timeval, 1);
95.592 -
95.593 - if (timeout != 0) {
95.594 - timeout_val->tv_sec = timeout;
95.595 - timeout_val->tv_usec = 0;
95.596 - } else {
95.597 - timeout_val->tv_sec = 5;
95.598 - timeout_val->tv_usec = 100;
95.599 - }
95.600 -
95.601 - if (gmyth_socket_try_connect
95.602 - (gmyth_socket->sd, (struct sockaddr *) addr_info0->ai_addr,
95.603 - addr_info0->ai_addrlen, timeout_val, &ret_code) < 0) {
95.604 - gmyth_debug("[%s] Error connecting to backend!\n",
95.605 - __FUNCTION__);
95.606 - if (ret_code == ETIMEDOUT)
95.607 - gmyth_debug("[%s]\tBackend host unreachable!\n",
95.608 - __FUNCTION__);
95.609 -
95.610 - close(gmyth_socket->sd);
95.611 - gmyth_socket->sd = -1;
95.612 - gmyth_debug("ERROR: %s\n", gai_strerror(ret_code));
95.613 - g_free(timeout_val);
95.614 - continue;
95.615 - }
95.616 -
95.617 - g_free(timeout_val);
95.618 -
95.619 - /*
95.620 - * only will be reached if none of the error above occurred
95.621 - */
95.622 - break;
95.623 - }
95.624 -
95.625 - freeaddrinfo(addr_info_data);
95.626 - addr_info_data = NULL;
95.627 -
95.628 - if (gmyth_socket->sd_io_ch != NULL) {
95.629 - g_io_channel_unref(gmyth_socket->sd_io_ch);
95.630 - gmyth_socket->sd_io_ch = NULL;
95.631 - }
95.632 -
95.633 -
95.634 - memset(&ling, 0, sizeof(struct linger));
95.635 - ling.l_onoff = TRUE;
95.636 - ling.l_linger = 1;
95.637 -
95.638 - err =
95.639 - setsockopt(gmyth_socket->sd, SOL_SOCKET, SO_LINGER, &ling,
95.640 - sizeof(struct linger));
95.641 -
95.642 - if (err < 0) {
95.643 - gmyth_debug("[%s] Setting connection unsucessfull.\n",
95.644 - __FUNCTION__);
95.645 - err = errno;
95.646 - ret = FALSE;
95.647 - goto cleanup;
95.648 - }
95.649 -
95.650 - gmyth_socket->sd_io_ch = g_io_channel_unix_new(gmyth_socket->sd);
95.651 -
95.652 - g_io_channel_set_close_on_unref(gmyth_socket->sd_io_ch, TRUE);
95.653 - // g_io_channel_set_encoding (gmyth_socket->sd_io_ch, NULL, NULL );
95.654 -
95.655 - GIOFlags flags = g_io_channel_get_flags(gmyth_socket->sd_io_ch);
95.656 -
95.657 - /*
95.658 - * unset the nonblock flag
95.659 - */
95.660 - flags &= ~G_IO_FLAG_NONBLOCK;
95.661 - /*
95.662 - * unset the nonblocking stuff for some time, because GNUTLS doesn't
95.663 - * like that
95.664 - */
95.665 - g_io_channel_set_flags(gmyth_socket->sd_io_ch, flags, NULL);
95.666 -
95.667 - ret = (ret_code == 0) ? TRUE : FALSE;
95.668 -
95.669 - cleanup:
95.670 - if (!ret)
95.671 - gmyth_debug("GMythSocket error - return code error!");
95.672 -
95.673 - return ret;
95.674 -}
95.675 -
95.676 -/** Gets the GIOChannel associated to the given GMythSocket.
95.677 - *
95.678 - * @param gmyth_socket The GMythSocket instance.
95.679 - */
95.680 -GIOChannel *
95.681 -gmyth_socket_get_io_channel(GMythSocket * gmyth_socket)
95.682 -{
95.683 - g_return_val_if_fail(gmyth_socket != NULL, NULL);
95.684 -
95.685 - return gmyth_socket->sd_io_ch;
95.686 -}
95.687 -
95.688 -/** Verifies if the socket is able to read.
95.689 - *
95.690 - * @param gmyth_socket The GMythSocket instance.
95.691 - * @return TRUE if the socket is able to read, FALSE if not.
95.692 - */
95.693 -gboolean
95.694 -gmyth_socket_is_able_to_read(GMythSocket * gmyth_socket)
95.695 -{
95.696 - gboolean ret = TRUE;
95.697 -
95.698 - /*
95.699 - * verify if the input (read) buffer is ready to receive data
95.700 - */
95.701 - GIOCondition io_cond =
95.702 - g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch);
95.703 -
95.704 - if ((io_cond & G_IO_IN) == 0) {
95.705 - gmyth_debug("[%s] IO channel is not able to send data!\n",
95.706 - __FUNCTION__);
95.707 - ret = FALSE;
95.708 - }
95.709 -
95.710 - return ret;
95.711 -
95.712 -}
95.713 -
95.714 -/** Verifies if the socket is able to write.
95.715 - *
95.716 - * @param gmyth_socket The GMythSocket instance.
95.717 - * @return TRUE if the socket is able to write, FALSE if not.
95.718 - */
95.719 -gboolean
95.720 -gmyth_socket_is_able_to_write(GMythSocket * gmyth_socket)
95.721 -{
95.722 - gboolean ret = TRUE;
95.723 -
95.724 - /*
95.725 - * verify if the input (read) buffer is ready to receive data
95.726 - */
95.727 - GIOCondition io_cond =
95.728 - g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch);
95.729 -
95.730 - if (((io_cond & G_IO_OUT) == 0) || ((io_cond & G_IO_HUP) == 0)) {
95.731 - gmyth_debug("[%s] IO channel is not able to send data!\n",
95.732 - __FUNCTION__);
95.733 - ret = FALSE;
95.734 - }
95.735 -
95.736 - return ret;
95.737 -
95.738 -}
95.739 -
95.740 -/** Sends a command to the backend.
95.741 - *
95.742 - * @param gmyth_socket the GMythSocket instance.
95.743 - * @param command The string command to be sent.
95.744 - */
95.745 -gboolean
95.746 -gmyth_socket_send_command(GMythSocket * gmyth_socket, GString * command)
95.747 -{
95.748 - gboolean ret = TRUE;
95.749 -
95.750 - GIOStatus io_status = G_IO_STATUS_NORMAL;
95.751 -
95.752 - // GIOCondition io_cond;
95.753 - GError *error = NULL;
95.754 -
95.755 - gchar *buffer = NULL;
95.756 -
95.757 - gsize bytes_written = 0;
95.758 -
95.759 - g_return_val_if_fail(gmyth_socket->sd_io_ch != NULL, FALSE);
95.760 -
95.761 - if (command == NULL || (command->len <= 0) || command->str == NULL) {
95.762 - gmyth_debug("[%s] Invalid NULL command parameter!\n",
95.763 - __FUNCTION__);
95.764 - ret = FALSE;
95.765 - goto done;
95.766 - }
95.767 -
95.768 - g_mutex_lock(gmyth_socket->mutex);
95.769 - gmyth_debug("Sending command to backend: %s\n", command->str);
95.770 -
95.771 - buffer = g_strnfill(BUFLEN, ' ');
95.772 - g_snprintf(buffer, MYTH_PROTOCOL_FIELD_SIZE + 1, "%-8d", command->len);
95.773 -
95.774 - command = g_string_prepend(command, buffer);
95.775 -
95.776 - /*
95.777 - * write bytes to socket
95.778 - */
95.779 - io_status =
95.780 - g_io_channel_write_chars(gmyth_socket->sd_io_ch, command->str,
95.781 - command->len, &bytes_written, &error);
95.782 -
95.783 -
95.784 - if ((io_status == G_IO_STATUS_ERROR) || (bytes_written <= 0)) {
95.785 - gmyth_debug("[%s] Error while writing to socket", __FUNCTION__);
95.786 - ret = FALSE;
95.787 - } else if (bytes_written < command->len) {
95.788 - gmyth_debug("[%s] Not all data was written socket", __FUNCTION__);
95.789 - ret = FALSE;
95.790 - }
95.791 -
95.792 - io_status = g_io_channel_flush(gmyth_socket->sd_io_ch, &error);
95.793 -
95.794 - if ((bytes_written != command->len)
95.795 - || (io_status == G_IO_STATUS_ERROR)) {
95.796 - gmyth_debug
95.797 - ("[%s] Some problem occurred when sending data to the socket\n",
95.798 - __FUNCTION__);
95.799 -
95.800 - ret = TRUE;
95.801 - }
95.802 -
95.803 - g_mutex_unlock(gmyth_socket->mutex);
95.804 - done:
95.805 - if (error != NULL) {
95.806 - gmyth_debug
95.807 - ("[%s] Error found reading data from IO channel: (%d, %s)\n",
95.808 - __FUNCTION__, error->code, error->message);
95.809 - ret = FALSE;
95.810 - g_error_free(error);
95.811 - }
95.812 -
95.813 - if (buffer != NULL)
95.814 - g_free(buffer);
95.815 -
95.816 - return ret;
95.817 -}
95.818 -
95.819 -/** Starts Mythtv protocol level connection. Checks Mythtv protocol version
95.820 - * supported by the backend and send the "ANN" command.
95.821 - *
95.822 - * @param gmyth_socket the GMythSocket instance.
95.823 - * @param hostname_backend The backend hostname or IP address.
95.824 - * @param port The backend port to connect.
95.825 - * @param blocking_client A flag to choose between blocking and non-blocking
95.826 - * @param with_events Sets the connection flag to receive events.
95.827 - * backend connection.
95.828 - */
95.829 -static gboolean
95.830 -gmyth_socket_connect_to_backend_and_events(GMythSocket * gmyth_socket,
95.831 - const gchar * hostname_backend,
95.832 - gint port,
95.833 - gboolean blocking_client,
95.834 - gboolean with_events)
95.835 -{
95.836 - if (!gmyth_socket_connect(gmyth_socket, hostname_backend, port)) {
95.837 - gmyth_debug("[%s] Could not open socket to backend machine [%s]\n",
95.838 - __FUNCTION__, hostname_backend);
95.839 - return FALSE;
95.840 - }
95.841 -
95.842 - if (gmyth_socket_check_protocol_version(gmyth_socket)) {
95.843 - GString *result;
95.844 - GString *base_str = g_string_new("");
95.845 - GString *hostname = NULL;
95.846 -
95.847 - hostname = gmyth_socket_get_local_hostname();
95.848 - if (hostname == NULL) {
95.849 - gmyth_debug
95.850 - ("Hostname not available, setting to n800frontend\n");
95.851 - hostname = g_string_new("n800frontend");
95.852 - }
95.853 -
95.854 - g_string_printf(base_str, "ANN %s %s %u",
95.855 - (blocking_client ? "Playback" : "Monitor"),
95.856 - hostname->str, with_events);
95.857 -
95.858 - gmyth_socket_send_command(gmyth_socket, base_str);
95.859 - result = gmyth_socket_receive_response(gmyth_socket);
95.860 -
95.861 - if (result != NULL) {
95.862 - gmyth_debug("Response received from backend: %s", result->str);
95.863 - g_string_free(result, TRUE);
95.864 - }
95.865 -
95.866 - g_string_free(hostname, TRUE);
95.867 - g_string_free(base_str, TRUE);
95.868 -
95.869 - return TRUE;
95.870 - } else {
95.871 - gmyth_debug("[%s] GMythSocket could not connect to the backend",
95.872 - __FUNCTION__);
95.873 - return FALSE;
95.874 - }
95.875 -}
95.876 -
95.877 -/** Starts Mythtv protocol level connection. Checks Mythtv protocol version
95.878 - * supported by the backend and send the "ANN" command.
95.879 - *
95.880 - * @param gmyth_socket the GMythSocket instance.
95.881 - * @param hostname_backend The backend hostname or IP address.
95.882 - * @param port The backend port to connect.
95.883 - * @param blocking_client A flag to choose between blocking and non-blocking
95.884 - */
95.885 -gboolean
95.886 -gmyth_socket_connect_to_backend(GMythSocket * gmyth_socket,
95.887 - const gchar * hostname_backend, gint port,
95.888 - gboolean blocking_client)
95.889 -{
95.890 - if (!gmyth_socket_connect_to_backend_and_events
95.891 - (gmyth_socket, hostname_backend, port, blocking_client, FALSE)) {
95.892 - gmyth_debug("Could not open socket to backend machine [%s]\n",
95.893 - hostname_backend);
95.894 - return FALSE;
95.895 - }
95.896 -
95.897 - return TRUE;
95.898 -
95.899 -}
95.900 -
95.901 -/** Starts Mythtv protocol level connection. Checks Mythtv protocol version
95.902 - * supported by the backend and send the "ANN" command.
95.903 - *
95.904 - * @param gmyth_socket the GMythSocket instance.
95.905 - * @param hostname_backend The backend hostname or IP address.
95.906 - * @param port The backend port to connect.
95.907 - * @param blocking_client A flag to choose between blocking and non-blocking
95.908 - */
95.909 -gboolean
95.910 -gmyth_socket_connect_to_backend_events(GMythSocket * gmyth_socket,
95.911 - const gchar * hostname_backend,
95.912 - gint port, gboolean blocking_client)
95.913 -{
95.914 - if (!gmyth_socket_connect_to_backend_and_events
95.915 - (gmyth_socket, hostname_backend, port, blocking_client, TRUE)) {
95.916 - gmyth_debug
95.917 - ("Could not open socket to backend machine in order to receive events [%s]\n",
95.918 - hostname_backend);
95.919 - return FALSE;
95.920 - }
95.921 -
95.922 - return TRUE;
95.923 -}
95.924 -
95.925 -/** Closes the socket connection to the backend.
95.926 - *
95.927 - * @param gmyth_socket The GMythSocket instance.
95.928 - */
95.929 -void
95.930 -gmyth_socket_close_connection(GMythSocket * gmyth_socket)
95.931 -{
95.932 - /*
95.933 - * if ( gmyth_socket->sd != -1 ) { close (gmyth_socket->sd);
95.934 - * gmyth_socket->sd = -1; }
95.935 - */
95.936 -
95.937 - if (gmyth_socket->sd_io_ch != NULL) {
95.938 - g_io_channel_shutdown(gmyth_socket->sd_io_ch, TRUE, NULL);
95.939 - g_io_channel_unref(gmyth_socket->sd_io_ch);
95.940 - gmyth_socket->sd_io_ch = NULL;
95.941 - gmyth_socket->sd = -1;
95.942 - }
95.943 -
95.944 -}
95.945 -
95.946 -
95.947 -/** Try the MythTV version numbers, and get the version returned by
95.948 - * the possible REJECT message, in order to contruct a new
95.949 - * MythTV version request.
95.950 - *
95.951 - * @param gmyth_socket The GMythSocket instance.
95.952 - * @param mythtv_version The Mythtv protocol version to be tested
95.953 - *
95.954 - * @return The actual MythTV the client is connected to.
95.955 - */
95.956 -gint
95.957 -gmyth_socket_check_protocol_version_number(GMythSocket * gmyth_socket,
95.958 - gint mythtv_version)
95.959 -{
95.960 - GString *response = NULL;
95.961 - GString *payload = NULL;
95.962 - gboolean res = TRUE;
95.963 - gint mythtv_new_version = MYTHTV_CANNOT_NEGOTIATE_VERSION;
95.964 - guint max_iterations = MYTHTV_MAX_VERSION_CHECKS;
95.965 -
95.966 - assert(gmyth_socket);
95.967 -
95.968 - try_new_version:
95.969 - payload = g_string_new("MYTH_PROTO_VERSION");
95.970 - g_string_append_printf(payload, " %d", mythtv_version);
95.971 -
95.972 - gmyth_socket_send_command(gmyth_socket, payload);
95.973 - response = gmyth_socket_receive_response(gmyth_socket);
95.974 -
95.975 - if (response == NULL) {
95.976 - gmyth_debug("[%s] Check protocol version error! Not answered!",
95.977 - __FUNCTION__);
95.978 - res = FALSE;
95.979 - goto done;
95.980 - }
95.981 -
95.982 - res = g_str_has_prefix(response->str, "ACCEPT");
95.983 - if (!res) {
95.984 - gmyth_debug("[%s] Protocol version request error: %s",
95.985 - __FUNCTION__, response->str);
95.986 - /*
95.987 - * get the version number returned by the REJECT message
95.988 - */
95.989 - if ((res = g_str_has_prefix(response->str, "REJECT")) == TRUE) {
95.990 - gchar *new_version = NULL;
95.991 -
95.992 - new_version = g_strrstr(response->str, "]");
95.993 - if (new_version != NULL) {
95.994 - ++new_version; /* skip ']' character */
95.995 - if (new_version != NULL) {
95.996 - gmyth_debug("[%s] got MythTV version = %s.\n",
95.997 - __FUNCTION__, new_version);
95.998 - mythtv_version =
95.999 - (gint) g_ascii_strtoull(new_version, NULL, 10);
95.1000 - /*
95.1001 - * do reconnection to the socket (socket is closed if
95.1002 - * the MythTV version was wrong)
95.1003 - */
95.1004 - gmyth_socket_connect(gmyth_socket,
95.1005 - gmyth_socket->hostname,
95.1006 - gmyth_socket->port);
95.1007 - new_version = NULL;
95.1008 - if (--max_iterations > 0) {
95.1009 - g_string_free(payload, TRUE);
95.1010 - g_string_free(response, TRUE);
95.1011 - goto try_new_version;
95.1012 - } else
95.1013 - goto done;
95.1014 - }
95.1015 - }
95.1016 - }
95.1017 - }
95.1018 -
95.1019 - /*
95.1020 - * change the return value to a valid one
95.1021 - */
95.1022 - if (res) {
95.1023 - mythtv_new_version = mythtv_version;
95.1024 - gmyth_socket->mythtv_version = mythtv_new_version;
95.1025 - }
95.1026 -
95.1027 - done:
95.1028 - g_string_free(payload, TRUE);
95.1029 - g_string_free(response, TRUE);
95.1030 -
95.1031 - return mythtv_new_version;
95.1032 -}
95.1033 -
95.1034 -/** Verifies if the Mythtv backend supported the GMyth supported version.
95.1035 - *
95.1036 - * @param gmyth_socket The GMythSocket instance.
95.1037 - * @return TRUE if supports, FALSE if not.
95.1038 - */
95.1039 -gboolean
95.1040 -gmyth_socket_check_protocol_version(GMythSocket * gmyth_socket)
95.1041 -{
95.1042 - return ((gmyth_socket->mythtv_version =
95.1043 - gmyth_socket_check_protocol_version_number(gmyth_socket,
95.1044 - MYTHTV_VERSION_DEFAULT))
95.1045 - != MYTHTV_CANNOT_NEGOTIATE_VERSION);
95.1046 -}
95.1047 -
95.1048 -/** Returns the Mythtv backend supported version.
95.1049 - *
95.1050 - * @param gmyth_socket The GMythSocket instance.
95.1051 - * @return The actual MythTV version number.
95.1052 - */
95.1053 -gint
95.1054 -gmyth_socket_get_protocol_version(GMythSocket * gmyth_socket)
95.1055 -{
95.1056 - return gmyth_socket->mythtv_version;
95.1057 -}
95.1058 -
95.1059 -/** Receives a backend answer after a gmyth_socket_send_command_call ().
95.1060 - *
95.1061 - * @param gmyth_socket The GMythSocket instance.
95.1062 - * @return The response received, or NULL if error or nothing was received.
95.1063 - */
95.1064 -GString *
95.1065 -gmyth_socket_receive_response(GMythSocket * gmyth_socket)
95.1066 -{
95.1067 - GIOStatus io_status = G_IO_STATUS_NORMAL;
95.1068 - GError *error = NULL;
95.1069 - gchar *buffer = NULL;
95.1070 -
95.1071 - GString *str = NULL;
95.1072 -
95.1073 - gsize bytes_read = 0;
95.1074 - gint len = 0;
95.1075 -
95.1076 - if (gmyth_socket == NULL)
95.1077 - return NULL;
95.1078 -
95.1079 - GIOCondition io_cond;
95.1080 -
95.1081 - /*
95.1082 - * verify if the input (read) buffer is ready to receive data
95.1083 - */
95.1084 - g_mutex_lock(gmyth_socket->mutex);
95.1085 -
95.1086 - buffer = g_strnfill(MYTH_PROTOCOL_FIELD_SIZE, ' ');
95.1087 - if (NULL == gmyth_socket->sd_io_ch) {
95.1088 - gmyth_socket_connect(gmyth_socket, gmyth_socket->hostname,
95.1089 - gmyth_socket->port);
95.1090 - }
95.1091 -
95.1092 - io_cond = g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch);
95.1093 - /*
95.1094 - * if ( NULL == gmyth_socket->sd_io_ch->read_buf || ( NULL ==
95.1095 - * gmyth_socket->sd_io_ch->read_buf->str ) ) gmyth_socket->sd_io_ch =
95.1096 - * g_io_channel_unix_new( gmyth_socket->sd );
95.1097 - */
95.1098 -
95.1099 - if (gmyth_socket->sd_io_ch->is_readable /* && !( ( io_cond & G_IO_IN )
95.1100 - * == 0 ) */ )
95.1101 - io_status =
95.1102 - g_io_channel_read_chars(gmyth_socket->sd_io_ch, buffer,
95.1103 - MYTH_PROTOCOL_FIELD_SIZE, &bytes_read,
95.1104 - &error);
95.1105 - else
95.1106 - return g_string_new("");
95.1107 -
95.1108 - /*
95.1109 - * verify if the input (read) buffer is ready to receive data
95.1110 - */
95.1111 - io_cond = g_io_channel_get_buffer_condition(gmyth_socket->sd_io_ch);
95.1112 -
95.1113 - // if ( ( io_cond & G_IO_IN ) == 0 )
95.1114 - // return NULL;
95.1115 -
95.1116 - gmyth_debug("[%s] Bytes read = %d\n", __FUNCTION__, bytes_read);
95.1117 -
95.1118 - if ((io_status == G_IO_STATUS_ERROR) || (bytes_read <= 0)) {
95.1119 - gmyth_debug("[%s] Error in mythprotocol response from backend\n",
95.1120 - __FUNCTION__);
95.1121 - str = NULL;
95.1122 - // return NULL;
95.1123 - } else if (buffer != NULL && strlen(buffer) > 0) {
95.1124 -
95.1125 - // io_status = g_io_channel_flush( gmyth_socket->sd_io_ch, &error
95.1126 - // );
95.1127 - /*
95.1128 - * verify if the input (read) buffer is ready to receive data
95.1129 - */
95.1130 - // io_cond = g_io_channel_get_buffer_condition(
95.1131 - // gmyth_socket->sd_io_ch );
95.1132 -
95.1133 - // if ( ( io_cond & G_IO_IN ) != 0 ) {
95.1134 - // gchar *buffer_aux = NULL;
95.1135 -
95.1136 - /*
95.1137 - * removes trailing whitespace
95.1138 - */
95.1139 - // buffer_aux = g_strstrip (buffer);
95.1140 - len = (gint) g_ascii_strtoull(g_strstrip(buffer), NULL, 10);
95.1141 -
95.1142 - g_free(buffer);
95.1143 -
95.1144 - /*
95.1145 - * if (buffer_aux != NULL) { g_free (buffer_aux); buffer_aux =
95.1146 - * NULL; }
95.1147 - */
95.1148 -
95.1149 - buffer = g_new0(gchar, len + 1);
95.1150 -
95.1151 - bytes_read = 0;
95.1152 - if (!(gmyth_socket != NULL && gmyth_socket->sd_io_ch != NULL))
95.1153 - return NULL;
95.1154 -
95.1155 - if (gmyth_socket->sd_io_ch->is_readable)
95.1156 - io_status =
95.1157 - g_io_channel_read_chars(gmyth_socket->sd_io_ch, buffer,
95.1158 - len, &bytes_read, &error);
95.1159 - else
95.1160 - return g_string_new("");
95.1161 -
95.1162 - buffer[bytes_read] = '\0';
95.1163 - // }
95.1164 - }
95.1165 -
95.1166 - g_mutex_unlock(gmyth_socket->mutex);
95.1167 - // g_static_rw_lock_reader_unlock (&rwlock);
95.1168 -
95.1169 - gmyth_debug("Response received from backend: ----- {%s}\n", buffer);
95.1170 - if ((bytes_read != len) || (io_status == G_IO_STATUS_ERROR))
95.1171 - str = NULL;
95.1172 - else
95.1173 - str = g_string_new(buffer);
95.1174 -
95.1175 - if (error != NULL) {
95.1176 - gmyth_debug
95.1177 - ("[%s] Error found receiving response from the IO channel: (%d, %s)\n",
95.1178 - __FUNCTION__, error->code, error->message);
95.1179 - str = NULL;
95.1180 - g_error_free(error);
95.1181 - }
95.1182 -
95.1183 - g_free(buffer);
95.1184 - return str;
95.1185 -}
95.1186 -
95.1187 -/** Format a Mythtv command from the str_list entries and send it to backend.
95.1188 - *
95.1189 - * @param gmyth_socket The GMythSocket instance.
95.1190 - * @param str_list The string list to form the command
95.1191 - * @return TRUE if command was sent, FALSE if any error happens.
95.1192 - */
95.1193 -gboolean
95.1194 -gmyth_socket_write_stringlist(GMythSocket * gmyth_socket,
95.1195 - GMythStringList * str_list)
95.1196 -{
95.1197 -
95.1198 - GList *tmp_list = NULL;
95.1199 - GPtrArray *ptr_array = NULL;
95.1200 - gchar *str_array = NULL;
95.1201 -
95.1202 - g_mutex_lock(gmyth_socket->mutex);
95.1203 - // g_static_rw_lock_writer_lock (&rwlock);
95.1204 -
95.1205 - ptr_array = g_ptr_array_sized_new(g_list_length(str_list->glist));
95.1206 -
95.1207 - // FIXME: change this implementation!
95.1208 - tmp_list = str_list->glist;
95.1209 - for (; tmp_list; tmp_list = tmp_list->next) {
95.1210 - if (tmp_list->data != NULL) {
95.1211 - g_ptr_array_add(ptr_array, ((GString *) tmp_list->data)->str);
95.1212 - } else {
95.1213 - g_ptr_array_add(ptr_array, "");
95.1214 - }
95.1215 - }
95.1216 - g_ptr_array_add(ptr_array, NULL); // g_str_joinv() needs a NULL
95.1217 - // terminated string
95.1218 -
95.1219 - str_array = g_strjoinv(MYTH_SEPARATOR, (gchar **) (ptr_array->pdata));
95.1220 -
95.1221 - g_mutex_unlock(gmyth_socket->mutex);
95.1222 - // g_static_rw_lock_writer_unlock (&rwlock);
95.1223 -
95.1224 - gmyth_debug("[%s] Sending socket request: %s\n", __FUNCTION__,
95.1225 - str_array);
95.1226 -
95.1227 - // Sends message to backend
95.1228 - // TODO: implement looping to send remaining data, and add timeout
95.1229 - // testing!
95.1230 - GString *command = g_string_new(str_array);
95.1231 -
95.1232 - gmyth_socket_send_command(gmyth_socket, command);
95.1233 -
95.1234 - g_string_free(command, TRUE);
95.1235 -
95.1236 - g_free(str_array);
95.1237 -
95.1238 - /*
95.1239 - * ptr_array is pointing to data inside str_list->glist
95.1240 - */
95.1241 - g_ptr_array_free(ptr_array, TRUE);
95.1242 -
95.1243 - return TRUE;
95.1244 -}
95.1245 -
95.1246 -/*
95.1247 - * Receives a backend command response and split it into the given string
95.1248 - * list. @param gmyth_socket The GMythSocket instance. @param str_list
95.1249 - * the string list to be filled. @return The number of received strings.
95.1250 - */
95.1251 -gint
95.1252 -gmyth_socket_read_stringlist(GMythSocket * gmyth_socket,
95.1253 - GMythStringList * str_list)
95.1254 -{
95.1255 - GString *response;
95.1256 - gint i;
95.1257 -
95.1258 - gmyth_string_list_clear_all(str_list);
95.1259 -
95.1260 - response = gmyth_socket_receive_response(gmyth_socket);
95.1261 - if (response != NULL && response->str != NULL && response->len > 0) {
95.1262 - gchar **str_array;
95.1263 -
95.1264 - g_mutex_lock(gmyth_socket->mutex);
95.1265 -
95.1266 - str_array = g_strsplit(response->str, MYTH_SEPARATOR, -1);
95.1267 -
95.1268 - for (i = 0; i < g_strv_length(str_array); i++) {
95.1269 - // if ( str_array[i] != NULL && strlen( str_array[i] ) > 0 )
95.1270 - gmyth_string_list_append_char_array(str_list, str_array[i]);
95.1271 - }
95.1272 -
95.1273 - g_mutex_unlock(gmyth_socket->mutex);
95.1274 - g_strfreev(str_array);
95.1275 - }
95.1276 -
95.1277 - g_string_free(response, TRUE);
95.1278 -
95.1279 - return gmyth_string_list_length(str_list);
95.1280 -}
95.1281 -
95.1282 -/** Formats a Mythtv protocol command based on str_list and sends it to
95.1283 - * the connected backend. The backend response is overwritten into str_list.
95.1284 - *
95.1285 - * @param gmyth_socket The GMythSocket instance.
95.1286 - * @param str_list The string list to be sent, and on which the answer
95.1287 - * will be written.
95.1288 - * @return TRUE if command was sent and an answer was received, FALSE if any
95.1289 - * error happens.
95.1290 - */
95.1291 -gint
95.1292 -gmyth_socket_sendreceive_stringlist(GMythSocket * gmyth_socket,
95.1293 - GMythStringList * str_list)
95.1294 -{
95.1295 - gmyth_socket_write_stringlist(gmyth_socket, str_list);
95.1296 -
95.1297 - return gmyth_socket_read_stringlist(gmyth_socket, str_list);
95.1298 -}
96.1 --- a/gmyth/src/gmyth_socket.h Mon Feb 25 17:45:36 2008 +0000
96.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
96.3 @@ -1,147 +0,0 @@
96.4 -/**
96.5 - * GMyth Library
96.6 - *
96.7 - * @file gmyth/gmyth_socket.h
96.8 - *
96.9 - * @brief <p> MythTV socket implementation, according to the MythTV Project
96.10 - * (www.mythtv.org).
96.11 - *
96.12 - * This component provides basic socket functionalities to interact with
96.13 - * the Mythtv backend.
96.14 - * <p>
96.15 - *
96.16 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
96.17 - * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
96.18 - *
96.19 - *
96.20 - * This program is free software; you can redistribute it and/or modify
96.21 - * it under the terms of the GNU Lesser General Public License as published by
96.22 - * the Free Software Foundation; either version 2 of the License, or
96.23 - * (at your option) any later version.
96.24 - *
96.25 - * This program is distributed in the hope that it will be useful,
96.26 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
96.27 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
96.28 - * GNU General Public License for more details.
96.29 - *
96.30 - * You should have received a copy of the GNU Lesser General Public License
96.31 - * along with this program; if not, write to the Free Software
96.32 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
96.33 - */
96.34 -
96.35 -#ifndef __GMYTH_SOCKET_H__
96.36 -#define __GMYTH_SOCKET_H__
96.37 -
96.38 -#include <glib-object.h>
96.39 -
96.40 -#include <string.h>
96.41 -#include <netdb.h>
96.42 -#include <sys/socket.h>
96.43 -#include <unistd.h>
96.44 -#include <glib.h>
96.45 -
96.46 -#include "gmyth_stringlist.h"
96.47 -
96.48 -G_BEGIN_DECLS
96.49 -#define GMYTH_SOCKET_TYPE (gmyth_socket_get_type ())
96.50 -#define GMYTH_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_SOCKET_TYPE, GMythSocket))
96.51 -#define GMYTH_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SOCKET_TYPE, GMythSocketClass))
96.52 -#define IS_GMYTH_SOCKET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_SOCKET_TYPE))
96.53 -#define IS_GMYTH_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_SOCKET_TYPE))
96.54 -#define GMYTH_SOCKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_SOCKET_TYPE, GMythSocketClass))
96.55 -typedef struct _GMythSocket GMythSocket;
96.56 -typedef struct _GMythSocketClass GMythSocketClass;
96.57 -
96.58 -struct _GMythSocketClass {
96.59 - GObjectClass parent_class;
96.60 -
96.61 - /*
96.62 - * callbacks
96.63 - */
96.64 - /*
96.65 - * no one for now
96.66 - */
96.67 -};
96.68 -
96.69 -struct _GMythSocket {
96.70 - GObject parent;
96.71 -
96.72 - GMutex *mutex;
96.73 -
96.74 - /*
96.75 - * socket descriptor
96.76 - */
96.77 - gint sd;
96.78 - GIOChannel *sd_io_ch;
96.79 -
96.80 - gchar *hostname;
96.81 - gint port;
96.82 - gint mythtv_version;
96.83 -};
96.84 -
96.85 -/*
96.86 - * used when no protocol version number was negotiated
96.87 - */
96.88 -#define MYTHTV_CANNOT_NEGOTIATE_VERSION 0
96.89 -
96.90 -GType gmyth_socket_get_type(void);
96.91 -
96.92 -GMythSocket *gmyth_socket_new();
96.93 -
96.94 -GIOChannel *gmyth_socket_get_io_channel(GMythSocket * gmyth_socket);
96.95 -
96.96 -gboolean gmyth_socket_is_able_to_read(GMythSocket * gmyth_socket);
96.97 -gboolean gmyth_socket_is_able_to_write(GMythSocket * gmyth_socket);
96.98 -
96.99 -gboolean gmyth_socket_send_command(GMythSocket * gmyth_socket,
96.100 - GString * command);
96.101 -GString *gmyth_socket_receive_response(GMythSocket * gmyth_socket);
96.102 -gint gmyth_socket_sendreceive_stringlist(GMythSocket *
96.103 - gmyth_socket,
96.104 - GMythStringList *
96.105 - str_list);
96.106 -
96.107 -gboolean gmyth_socket_connect(GMythSocket * gmyth_socket,
96.108 - const gchar * hostname, gint port);
96.109 -gboolean gmyth_socket_connect_with_timeout(GMythSocket *
96.110 - gmyth_socket,
96.111 - const gchar * hostname,
96.112 - gint port,
96.113 - guint timeout);
96.114 -
96.115 -gboolean gmyth_socket_connect_to_backend(GMythSocket * gmyth_socket,
96.116 - const gchar *
96.117 - hostname_backend,
96.118 - gint port,
96.119 - gboolean blocking_client);
96.120 -
96.121 -gboolean gmyth_socket_connect_to_backend_events(GMythSocket *
96.122 - gmyth_socket,
96.123 - const gchar *
96.124 - hostname_backend,
96.125 - gint port,
96.126 - gboolean
96.127 - blocking_client);
96.128 -
96.129 -gchar *gmyth_socket_get_primary_addr(void);
96.130 -
96.131 -GString *gmyth_socket_get_local_hostname(void);
96.132 -
96.133 -void gmyth_socket_close_connection(GMythSocket * gmyth_socket);
96.134 -
96.135 -gboolean gmyth_socket_check_protocol_version(GMythSocket *
96.136 - gmyth_socket);
96.137 -gint gmyth_socket_check_protocol_version_number(GMythSocket *
96.138 - gmyth_socket,
96.139 - gint
96.140 - mythtv_version);
96.141 -
96.142 -gint gmyth_socket_get_protocol_version(GMythSocket *
96.143 - gmyth_socket);
96.144 -
96.145 -gboolean gmyth_socket_write_stringlist(GMythSocket * gmyth_socket,
96.146 - GMythStringList * str_list);
96.147 -gint gmyth_socket_read_stringlist(GMythSocket * gmyth_socket,
96.148 - GMythStringList * str_list);
96.149 -G_END_DECLS
96.150 -#endif /* __GMYTH_SOCKET_H__ */
97.1 --- a/gmyth/src/gmyth_stringlist.c Mon Feb 25 17:45:36 2008 +0000
97.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
97.3 @@ -1,454 +0,0 @@
97.4 -/**
97.5 - * GMyth Library
97.6 - *
97.7 - * @file gmyth/gmyth_stringlist.c
97.8 - *
97.9 - * @brief <p> This component contains functions for dealing with the stringlist
97.10 - * format of the mythprotocol.
97.11 - *
97.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
97.13 - * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
97.14 - *
97.15 - *
97.16 - * This program is free software; you can redistribute it and/or modify
97.17 - * it under the terms of the GNU Lesser General Public License as published by
97.18 - * the Free Software Foundation; either version 2 of the License, or
97.19 - * (at your option) any later version.
97.20 - *
97.21 - * This program is distributed in the hope that it will be useful,
97.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
97.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
97.24 - * GNU General Public License for more details.
97.25 - *
97.26 - * You should have received a copy of the GNU Lesser General Public License
97.27 - * along with this program; if not, write to the Free Software
97.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
97.29 - */
97.30 -
97.31 -#ifdef HAVE_CONFIG_H
97.32 -#include "config.h"
97.33 -#endif
97.34 -
97.35 -#include "gmyth_stringlist.h"
97.36 -
97.37 -#include "gmyth_debug.h"
97.38 -
97.39 -static void gmyth_string_list_class_init(GMythStringListClass * klass);
97.40 -static void gmyth_string_list_init(GMythStringList * object);
97.41 -
97.42 -static void gmyth_string_list_dispose(GObject * object);
97.43 -static void gmyth_string_list_finalize(GObject * object);
97.44 -
97.45 -G_DEFINE_TYPE(GMythStringList, gmyth_string_list, G_TYPE_OBJECT)
97.46 - static void gmyth_string_list_class_init(GMythStringListClass *
97.47 - klass)
97.48 -{
97.49 - GObjectClass *gobject_class;
97.50 -
97.51 - gobject_class = (GObjectClass *) klass;
97.52 -
97.53 - gobject_class->dispose = gmyth_string_list_dispose;
97.54 - gobject_class->finalize = gmyth_string_list_finalize;
97.55 -}
97.56 -
97.57 -static void
97.58 -gmyth_string_list_init(GMythStringList * gmyth_string_list)
97.59 -{
97.60 - gmyth_string_list->glist = NULL;
97.61 -}
97.62 -
97.63 -static void
97.64 -gmyth_string_list_dispose(GObject * object)
97.65 -{
97.66 - GMythStringList *gmyth_string_list = GMYTH_STRING_LIST(object);
97.67 -
97.68 - gmyth_string_list_clear_all(gmyth_string_list);
97.69 -
97.70 - G_OBJECT_CLASS(gmyth_string_list_parent_class)->dispose(object);
97.71 -}
97.72 -
97.73 -static void
97.74 -gmyth_string_list_finalize(GObject * object)
97.75 -{
97.76 - // GMythStringList *gmyth_string_list = GMYTH_STRING_LIST(object);
97.77 -
97.78 - g_signal_handlers_destroy(object);
97.79 -
97.80 - G_OBJECT_CLASS(gmyth_string_list_parent_class)->finalize(object);
97.81 -}
97.82 -
97.83 -/** Creates a new instance of GStringList.
97.84 - *
97.85 - * @return a new instance of GStringList.
97.86 - */
97.87 -GMythStringList *
97.88 -gmyth_string_list_new()
97.89 -{
97.90 - GMythStringList *gmyth_string_list =
97.91 - GMYTH_STRING_LIST(g_object_new(GMYTH_STRING_LIST_TYPE, NULL));
97.92 -
97.93 - return gmyth_string_list;
97.94 -}
97.95 -
97.96 -/** Appends a guint64 to the string list.
97.97 - *
97.98 - * @param strlist The GMythStringList instance.
97.99 - * @param value The guint64 to be appended.
97.100 - *
97.101 - * @return The appended guint64 converted to a GString object.
97.102 - */
97.103 -GString *
97.104 -gmyth_string_list_append_int(GMythStringList * strlist, const gint value)
97.105 -{
97.106 - GString *value_str = g_string_new("");
97.107 -
97.108 - g_string_printf(value_str, "%d", value);
97.109 -
97.110 - strlist->glist = g_list_append(strlist->glist, value_str);
97.111 -
97.112 - return value_str;
97.113 -}
97.114 -
97.115 -
97.116 -/** Appends a gdouble to the string list.
97.117 - *
97.118 - * @param strlist The GMythStringList instance.
97.119 - * @param value The gdouble to be appended.
97.120 - *
97.121 - * @return The appended gdouble converted to a GString object.
97.122 - */
97.123 -GString *
97.124 -gmyth_string_list_append_float(GMythStringList * strlist, const gdouble value)
97.125 -{
97.126 - GString *value_str = g_string_new("");
97.127 - g_string_printf(value_str, "%f", value);
97.128 - strlist->glist = g_list_append(strlist->glist, value_str);
97.129 - return value_str;
97.130 -}
97.131 -
97.132 -
97.133 -/** Appends a guint64 to the string list.
97.134 - *
97.135 - * @param strlist The GMythStringList instance.
97.136 - * @param value The guint64 to be appended.
97.137 - *
97.138 - * @return The appended guint64 converted to a GString object.
97.139 - */
97.140 -GString *
97.141 -gmyth_string_list_append_uint64(GMythStringList * strlist,
97.142 - const guint64 value)
97.143 -{
97.144 - GString *tmp_str1 = g_string_new("");
97.145 - GString *tmp_str2 = g_string_new("");
97.146 -
97.147 - gmyth_debug("value = %llu.\n", value);
97.148 -
97.149 - gulong l2 = ((guint64) value & 0xffffffff);
97.150 - gulong l1 = ((guint64) value >> 32);
97.151 -
97.152 - /*
97.153 - * high order part of guint64 value
97.154 - */
97.155 - g_string_printf(tmp_str1, "%lu", l1);
97.156 -
97.157 - gmyth_debug("[%s] uint64 (high) = %s\n", __FUNCTION__, tmp_str1->str);
97.158 -
97.159 - strlist->glist = g_list_append(strlist->glist, tmp_str1);
97.160 -
97.161 - /*
97.162 - * low order part of guint64 value
97.163 - */
97.164 - g_string_printf(tmp_str2, "%lu", l2);
97.165 -
97.166 - gmyth_debug("[%s] uint64 (low) = %s\n", __FUNCTION__, tmp_str2->str);
97.167 -
97.168 - strlist->glist = g_list_append(strlist->glist, tmp_str2);
97.169 -
97.170 - return tmp_str2;
97.171 -}
97.172 -
97.173 -/** Appends a gint64 to the string list.
97.174 - *
97.175 - * @param strlist The GMythStringList instance.
97.176 - * @param value The gint64 to be appended.
97.177 - *
97.178 - * @return The appended gint64 converted to a GString object.
97.179 - */
97.180 -GString *
97.181 -gmyth_string_list_append_int64(GMythStringList * strlist,
97.182 - const gint64 value)
97.183 -{
97.184 - GString *tmp_str1 = g_string_new("");
97.185 - GString *tmp_str2 = g_string_new("");
97.186 -
97.187 - gmyth_debug("value = %lld.\n", value);
97.188 -
97.189 - glong l2 = ((gint64) value & 0xffffffff);
97.190 - glong l1 = ((gint64) value >> 32);
97.191 -
97.192 - /*
97.193 - * high order part of gint64 value
97.194 - */
97.195 - g_string_printf(tmp_str1, "%ld", l1);
97.196 -
97.197 - gmyth_debug("[%s] int64 (high) = %s\n", __FUNCTION__, tmp_str1->str);
97.198 -
97.199 - strlist->glist = g_list_append(strlist->glist, tmp_str1);
97.200 -
97.201 - /*
97.202 - * low order part of gint64 value
97.203 - */
97.204 - g_string_printf(tmp_str2, "%ld", l2);
97.205 -
97.206 - gmyth_debug("[%s] int64 (low) = %s\n", __FUNCTION__, tmp_str2->str);
97.207 -
97.208 - strlist->glist = g_list_append(strlist->glist, tmp_str2);
97.209 -
97.210 - return tmp_str2;
97.211 -}
97.212 -
97.213 -/** Appends a char array to the string list.
97.214 - *
97.215 - * @param strlist The GMythStringList instance.
97.216 - * @param value The char array to be appended.
97.217 - *
97.218 - * @return The appended char array converted to a GString object.
97.219 - */
97.220 -GString *
97.221 -gmyth_string_list_append_char_array(GMythStringList * strlist,
97.222 - const gchar * value)
97.223 -{
97.224 - GString *tmp_str = NULL;
97.225 -
97.226 - g_return_val_if_fail(strlist != NULL, NULL);
97.227 -
97.228 - tmp_str = g_string_new(value);
97.229 -
97.230 - strlist->glist = g_list_append(strlist->glist, tmp_str);
97.231 -
97.232 - return tmp_str;
97.233 -}
97.234 -
97.235 -/** Appends a string to the string list.
97.236 - *
97.237 - * @param strlist The GMythStringList instance.
97.238 - * @param value The string to be appended.
97.239 - *
97.240 - * @return The appended string itself.
97.241 - */
97.242 -GString *
97.243 -gmyth_string_list_append_string(GMythStringList * strlist, GString * value)
97.244 -{
97.245 - g_return_val_if_fail(strlist != NULL, NULL);
97.246 -
97.247 - if (value != NULL) {
97.248 - strlist->glist =
97.249 - g_list_append(strlist->glist, g_string_new(value->str));
97.250 - } else {
97.251 - strlist->glist = g_list_append(strlist->glist, NULL);
97.252 - }
97.253 -
97.254 - return value;
97.255 -}
97.256 -
97.257 -/** Gets an integer value from the string list at the given position.
97.258 - *
97.259 - * @param strlist The GMythStringList instance.
97.260 - * @param index the integer position in the list, starting with zero.
97.261 - * @return The integer value.
97.262 - */
97.263 -gint
97.264 -gmyth_string_list_get_int(GMythStringList * strlist, const gint index)
97.265 -{
97.266 - // TODO: Create static method check_index()
97.267 - GString *tmp_str = NULL;
97.268 -
97.269 - g_return_val_if_fail(strlist != NULL, 0);
97.270 -
97.271 - tmp_str = (GString *) g_list_nth_data(strlist->glist, index);
97.272 -
97.273 - if (NULL == tmp_str || NULL == tmp_str->str
97.274 - || strlen(tmp_str->str) <= 0)
97.275 - return 0;
97.276 -
97.277 - return (gint) ( /* 0x00000000ffffffffL & (gint64) */
97.278 - g_ascii_strtoull(tmp_str->str, NULL, 10));
97.279 -}
97.280 -
97.281 -/** Gets a guint64 value from the string list at the given position.
97.282 - * According to the Mythtv protocol, the 64 bits value is formed by
97.283 - * two strings.
97.284 - *
97.285 - * @param strlist The GMythStringList instance.
97.286 - * @param index the index of the first string forming the 64 bits value.
97.287 - * Index starts with zero.
97.288 - * @return The guint64 value.
97.289 - */
97.290 -guint64
97.291 -gmyth_string_list_get_uint64(GMythStringList * strlist, const gint index)
97.292 -{
97.293 - // TODO: Create static method check_index()
97.294 - guint64 ret_value = 0;
97.295 - guint64 l2 = 0;
97.296 -
97.297 - g_return_val_if_fail(strlist != NULL, 0);
97.298 -
97.299 - const GString *tmp_str1 =
97.300 - (GString *) g_list_nth_data(strlist->glist, index);
97.301 - const GString *tmp_str2 =
97.302 - (GString *) g_list_nth_data(strlist->glist, index + 1);
97.303 -
97.304 - if (tmp_str1 != NULL)
97.305 - gmyth_debug("[%s] seek high bytes = %s\n", __FUNCTION__,
97.306 - tmp_str1->str);
97.307 - if (tmp_str2 == NULL || strlen(tmp_str2->str) > 0) {
97.308 - } else {
97.309 - gmyth_debug("[%s] seek low bytes = %s\n", __FUNCTION__,
97.310 - tmp_str2->str);
97.311 - }
97.312 -
97.313 - guint64 l1 = ((guint64) g_ascii_strtoull(tmp_str1->str, NULL, 10) /* &
97.314 - * 0xffffffff
97.315 - */
97.316 - );
97.317 -
97.318 - if (tmp_str2 != NULL && tmp_str2->str != NULL
97.319 - && strlen(tmp_str2->str) > 0) {
97.320 - l2 = ((guint64) g_ascii_strtoull(tmp_str2->str, NULL, 10)
97.321 - /*
97.322 - * & 0xffffffff
97.323 - */
97.324 - );
97.325 - } else {
97.326 - l2 = l1;
97.327 - l1 = 0;
97.328 - }
97.329 -
97.330 - gmyth_debug("[%s]\t[l1 == %llu, l2 == %llu]\n", __FUNCTION__, l1, l2);
97.331 -
97.332 - ret_value =
97.333 - ((guint64) (l2) /* & 0xffffffff */ ) | ((guint64) l1 << 32);
97.334 -
97.335 - gmyth_debug("[%s] returning uint64 value = %llu\n", __FUNCTION__,
97.336 - ret_value);
97.337 -
97.338 - return ret_value;
97.339 -}
97.340 -
97.341 -/** Gets a gint64 value from the string list at the given position.
97.342 - * According to the Mythtv protocol, the 64 bits value is formed by
97.343 - * two strings.
97.344 - *
97.345 - * @param strlist The GMythStringList instance.
97.346 - * @param index the index of the first string forming the 64 bits value.
97.347 - * Index starts with zero.
97.348 - * @return The gint64 value.
97.349 - */
97.350 -gint64
97.351 -gmyth_string_list_get_int64(GMythStringList * strlist, const gint index)
97.352 -{
97.353 - // TODO: Create static method check_index()
97.354 - gint64 ret_value = 0;
97.355 - gint64 l2 = 0;
97.356 -
97.357 - g_return_val_if_fail(strlist != NULL, 0);
97.358 -
97.359 - const GString *tmp_str1 =
97.360 - (GString *) g_list_nth_data(strlist->glist, index);
97.361 - const GString *tmp_str2 =
97.362 - (GString *) g_list_nth_data(strlist->glist, index + 1);
97.363 -
97.364 - if (tmp_str1 != NULL)
97.365 - gmyth_debug("[%s] seek high bytes = %s\n", __FUNCTION__,
97.366 - tmp_str1->str);
97.367 - if (tmp_str2 == NULL || strlen(tmp_str2->str) > 0) {
97.368 - } else {
97.369 - gmyth_debug("[%s] seek low bytes = %s\n", __FUNCTION__,
97.370 - tmp_str2->str);
97.371 - }
97.372 -
97.373 - gint64 l1 = ((guint64) g_ascii_strtoull(tmp_str1->str, NULL, 10) /* &
97.374 - * 0xffffffff
97.375 - */
97.376 - );
97.377 -
97.378 - if (tmp_str2 != NULL && tmp_str2->str != NULL
97.379 - && strlen(tmp_str2->str) > 0) {
97.380 - l2 = ((gint64) g_ascii_strtoull(tmp_str2->str, NULL, 10)
97.381 - /*
97.382 - * & 0xffffffff
97.383 - */
97.384 - );
97.385 - } else {
97.386 - l2 = l1;
97.387 - l1 = 0;
97.388 - }
97.389 -
97.390 - gmyth_debug("[%s]\t[l1 == %lld, l2 == %lld]\n", __FUNCTION__, l1, l2);
97.391 -
97.392 - ret_value = ((gint64) (l2) /* & 0xffffffff */ ) | ((gint64) l1 << 32);
97.393 -
97.394 - gmyth_debug("[%s] returning int64 value = %lld\n", __FUNCTION__,
97.395 - ret_value);
97.396 -
97.397 - return ret_value;
97.398 -}
97.399 -
97.400 -
97.401 -/** Gets a string from the string list at the given position. The GString must be deallocated.
97.402 - *
97.403 - * @param strlist The GMythStringList instance.
97.404 - * @param index the string position in the list, starting with zero.
97.405 - * @return A pointer to the string data.
97.406 - */
97.407 -GString *
97.408 -gmyth_string_list_get_string(GMythStringList * strlist, const gint index)
97.409 -{
97.410 - GString *ret;
97.411 -
97.412 - if (!strlist || !(strlist->glist)) {
97.413 - gmyth_debug("%s received Null arguments", __FUNCTION__);
97.414 - return NULL;
97.415 - }
97.416 -
97.417 - ret = (GString *) g_list_nth_data(strlist->glist, index);
97.418 -
97.419 - return g_string_new(ret->str);
97.420 -}
97.421 -
97.422 -
97.423 -static void
97.424 -gmyth_string_list_clear_element(GString * str_elem, void *data_aux)
97.425 -{
97.426 - if (str_elem != NULL)
97.427 - g_string_free(str_elem, TRUE);
97.428 -}
97.429 -
97.430 -/** Removes all strings from the string list.
97.431 - *
97.432 - * @param strlist The GMythStringList instance.
97.433 - */
97.434 -void
97.435 -gmyth_string_list_clear_all(GMythStringList * strlist)
97.436 -{
97.437 - if (strlist != NULL && strlist->glist) {
97.438 - g_list_foreach(strlist->glist,
97.439 - (GFunc) gmyth_string_list_clear_element, NULL);
97.440 - g_list_free(strlist->glist);
97.441 - strlist->glist = NULL;
97.442 - }
97.443 -}
97.444 -
97.445 -/** Retrieves the number of elements in the string list.
97.446 - *
97.447 - * @param strlist The GMythStringList instance.
97.448 - * @return the string list length.
97.449 - */
97.450 -gint
97.451 -gmyth_string_list_length(GMythStringList * strlist)
97.452 -{
97.453 - if (!(strlist != NULL && strlist->glist != NULL))
97.454 - return 0;
97.455 -
97.456 - return g_list_length(strlist->glist);
97.457 -}
98.1 --- a/gmyth/src/gmyth_stringlist.h Mon Feb 25 17:45:36 2008 +0000
98.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
98.3 @@ -1,108 +0,0 @@
98.4 -/**
98.5 - * GMyth Library
98.6 - *
98.7 - * @file gmyth/gmyth_stringlist.h
98.8 - *
98.9 - * @brief <p> This component contains functions for dealing with the stringlist
98.10 - * format of the mythprotocol.
98.11 - *
98.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
98.13 - * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
98.14 - *
98.15 - *
98.16 - * This program is free software; you can redistribute it and/or modify
98.17 - * it under the terms of the GNU Lesser General Public License as published by
98.18 - * the Free Software Foundation; either version 2 of the License, or
98.19 - * (at your option) any later version.
98.20 - *
98.21 - * This program is distributed in the hope that it will be useful,
98.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
98.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
98.24 - * GNU General Public License for more details.
98.25 - *
98.26 - * You should have received a copy of the GNU Lesser General Public License
98.27 - * along with this program; if not, write to the Free Software
98.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
98.29 - */
98.30 -
98.31 -#ifndef GMYTH_STRING_LIST_H_
98.32 -#define GMYTH_STRING_LIST_H_
98.33 -
98.34 -#include <glib-object.h>
98.35 -
98.36 -#include <stdio.h>
98.37 -#include <stdlib.h>
98.38 -#include <string.h>
98.39 -#include <netdb.h>
98.40 -#include <sys/socket.h>
98.41 -#include <unistd.h>
98.42 -
98.43 -G_BEGIN_DECLS
98.44 -#define GMYTH_STRING_LIST_TYPE (gmyth_string_list_get_type ())
98.45 -#define GMYTH_STRING_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_STRING_LIST_TYPE, GMythStringList))
98.46 -#define GMYTH_STRING_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_STRING_LIST_TYPE, GMythStringListClass))
98.47 -#define IS_GMYTH_STRING_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_STRING_LIST_TYPE))
98.48 -#define IS_GMYTH_STRING_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_STRING_LIST_TYPE))
98.49 -#define GMYTH_STRING_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_STRING_LIST_TYPE, GMythStringListClass))
98.50 -typedef struct _GMythStringList GMythStringList;
98.51 -typedef struct _GMythStringListClass GMythStringListClass;
98.52 -
98.53 -struct _GMythStringListClass {
98.54 - GObjectClass parent_class;
98.55 -
98.56 - /*
98.57 - * callbacks
98.58 - */
98.59 - /*
98.60 - * no one for now
98.61 - */
98.62 -};
98.63 -
98.64 -struct _GMythStringList {
98.65 - GObject parent;
98.66 -
98.67 - /*
98.68 - * string list
98.69 - */
98.70 - GList *glist;
98.71 -};
98.72 -
98.73 -
98.74 -GType gmyth_string_list_get_type(void);
98.75 -
98.76 -GMythStringList *gmyth_string_list_new(void);
98.77 -
98.78 -void gmyth_string_list_clear_all(GMythStringList * strlist);
98.79 -int gmyth_string_list_length(GMythStringList * strlist);
98.80 -
98.81 -GString *gmyth_string_list_append_float(GMythStringList * strlist,
98.82 - const gdouble value);
98.83 -
98.84 -GString *gmyth_string_list_append_int(GMythStringList * strlist,
98.85 - const gint value);
98.86 -GString *gmyth_string_list_append_uint64(GMythStringList * strlist,
98.87 - const guint64 value);
98.88 -
98.89 -GString *gmyth_string_list_append_int64(GMythStringList * strlist,
98.90 - const gint64 value);
98.91 -
98.92 -GString *gmyth_string_list_append_char_array(GMythStringList *
98.93 - strlist,
98.94 - const char *value);
98.95 -GString *gmyth_string_list_append_string(GMythStringList * strlist,
98.96 - GString * value);
98.97 -
98.98 -int gmyth_string_list_get_int(GMythStringList * strlist,
98.99 - const gint index);
98.100 -guint64 gmyth_string_list_get_uint64(GMythStringList * strlist,
98.101 - const gint index);
98.102 -gint64 gmyth_string_list_get_int64(GMythStringList * strlist,
98.103 - const gint index);
98.104 -GString *gmyth_string_list_get_string(GMythStringList * strlist,
98.105 - const gint index);
98.106 -
98.107 -#define gmyth_string_list_get_char_array(strlist, index) \
98.108 - (gmyth_string_list_get_string(strlist, index))->str
98.109 -
98.110 -G_END_DECLS
98.111 -#endif /* GMYTH_STRING_LIST_H_ */
99.1 --- a/gmyth/src/gmyth_transcoder.c Mon Feb 25 17:45:36 2008 +0000
99.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
99.3 @@ -1,272 +0,0 @@
99.4 -/**
99.5 - * GMyth Library
99.6 - *
99.7 - * @file gmyth/gmyth_transcoder.c
99.8 - *
99.9 - * @brief <p> This file contains the transcoder class.
99.10 - *
99.11 - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
99.12 - * @author Artur Duque de Souza <artur.souza@indt.org.br>
99.13 - *
99.14 - *
99.15 - * This program is free software; you can redistribute it and/or modify
99.16 - * it under the terms of the GNU Lesser General Public License as published by
99.17 - * the Free Software Foundation; either version 2 of the License, or
99.18 - * (at your option) any later version.
99.19 - *
99.20 - * This program is distributed in the hope that it will be useful,
99.21 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
99.22 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
99.23 - * GNU General Public License for more details.
99.24 - *
99.25 - * You should have received a copy of the GNU Lesser General Public License
99.26 - * along with this program; if not, write to the Free Software
99.27 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
99.28 - */
99.29 -
99.30 -
99.31 -#ifdef HAVE_CONFIG_H
99.32 -#include "config.h"
99.33 -#endif
99.34 -
99.35 -#include <stdlib.h>
99.36 -#include <string.h>
99.37 -#include <assert.h>
99.38 -
99.39 -#include "gmyth_util.h"
99.40 -#include "gmyth_debug.h"
99.41 -
99.42 -#include "gmyth_jobqueue.h"
99.43 -#include "gmyth_transcoder.h"
99.44 -
99.45 -static void gmyth_transcoder_class_init(GMythTranscoderClass * klass);
99.46 -static void gmyth_transcoder_init(GMythTranscoder * object);
99.47 -
99.48 -static void gmyth_transcoder_dispose(GObject * object);
99.49 -static void gmyth_transcoder_finalize(GObject * object);
99.50 -
99.51 -G_DEFINE_TYPE(GMythTranscoder, gmyth_transcoder, G_TYPE_OBJECT)
99.52 - static void gmyth_transcoder_class_init(GMythTranscoderClass *
99.53 - klass)
99.54 -{
99.55 - GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
99.56 -
99.57 - gobject_class->dispose = gmyth_transcoder_dispose;
99.58 - gobject_class->finalize = gmyth_transcoder_finalize;
99.59 -}
99.60 -
99.61 -static void
99.62 -gmyth_transcoder_init(GMythTranscoder * transcoder)
99.63 -{
99.64 - transcoder->started = FALSE;
99.65 -}
99.66 -
99.67 -static void
99.68 -gmyth_transcoder_dispose(GObject * object)
99.69 -{
99.70 - GMythTranscoder *transcoder = GMYTH_TRANSCODER(object);
99.71 -
99.72 - g_free(transcoder->output_filename);
99.73 - g_free(transcoder->filename);
99.74 - g_free(transcoder->profile);
99.75 - g_free(transcoder->starttime);
99.76 -
99.77 - if (transcoder->backend_info)
99.78 - g_object_unref(transcoder->backend_info);
99.79 -
99.80 - G_OBJECT_CLASS(gmyth_transcoder_parent_class)->dispose(object);
99.81 -}
99.82 -
99.83 -static void
99.84 -gmyth_transcoder_finalize(GObject * object)
99.85 -{
99.86 - g_signal_handlers_destroy(object);
99.87 - G_OBJECT_CLASS(gmyth_transcoder_parent_class)->finalize(object);
99.88 -}
99.89 -
99.90 -/**
99.91 - * Creates a new instance of GMythTranscoder.
99.92 - *
99.93 - * @return a new instance of GMythTranscoder.
99.94 - **/
99.95 -GMythTranscoder *
99.96 -gmyth_transcoder_new(GMythBackendInfo * backend_info)
99.97 -{
99.98 - GMythTranscoder *transcoder = GMYTH_TRANSCODER
99.99 - (g_object_new(GMYTH_TRANSCODER_TYPE, NULL));
99.100 -
99.101 - if (backend_info != NULL) {
99.102 - g_object_ref(backend_info);
99.103 - transcoder->backend_info = backend_info;
99.104 - }
99.105 -
99.106 - return transcoder;
99.107 -}
99.108 -
99.109 -/**
99.110 - *
99.111 - * gmyth_transcoder_date_change_format
99.112 - * @brief converts a string like YYYY-MM-DDTHH:MM:SS into YYYYMMDDHHMMSS (vice versa)
99.113 - * @param date_s gchar*
99.114 - * @return gchar* with file or iso format
99.115 - *
99.116 - **/
99.117 -static gchar *
99.118 -gmyth_transcoder_date_change_format(gchar * date_s, int format)
99.119 -{
99.120 - if (date_s != NULL) {
99.121 - gint length = strlen(date_s);
99.122 -
99.123 - // create the right date format
99.124 - gchar *src = (gchar *) g_malloc0(sizeof(gchar) * length);
99.125 -
99.126 - strncpy(src, date_s, length);
99.127 -
99.128 - gchar *dst;
99.129 -
99.130 - if (format == DATE_FILE) {
99.131 - dst = (gchar *) g_malloc0(sizeof(gchar) * 16);
99.132 - snprintf(dst, 16, "%.4s%.2s%.2s%.2s%.2s%.2s", src, src + 5,
99.133 - src + 7, src + 9, src + 11, src + 13);
99.134 - dst[15] = '\0';
99.135 - } else if (format == DATE_ISO) {
99.136 - dst = (gchar *) g_malloc0(sizeof(gchar) * 20);
99.137 - snprintf(dst, 20, "%.4s-%.2s-%.2sT%.2s:%.2s:%.2s", src,
99.138 - src + 4, src + 6, src + 8, src + 10, src + 12);
99.139 - dst[19] = '\0';
99.140 - }
99.141 -
99.142 - gchar *ret = g_strdup(dst);
99.143 -
99.144 - g_free(src);
99.145 - g_free(dst);
99.146 -
99.147 - return ret;
99.148 - } else
99.149 - return NULL;
99.150 -}
99.151 -
99.152 -/**
99.153 - * gmyth_transcoder_set_output
99.154 - * @brief set transcoder to use output
99.155 - * @param value gboolean
99.156 - * @param outfile filename of output
99.157 - * @return void set's up the var to value
99.158 - *
99.159 - **/
99.160 -void
99.161 -gmyth_transcoder_set_output(GMythTranscoder * transcoder,
99.162 - gboolean value, const gchar * outputfile)
99.163 -{
99.164 - transcoder->output = value;
99.165 - transcoder->output_filename = g_strdup(outputfile);
99.166 -}
99.167 -
99.168 -/**
99.169 - * gmyth_transcoder_set_file
99.170 - * @brief set the file to transcoder
99.171 - * @param file filename
99.172 - * @return void set's up the var to value
99.173 - *
99.174 - **/
99.175 -void
99.176 -gmyth_transcoder_set_filename(GMythTranscoder * transcoder,
99.177 - const gchar * file)
99.178 -{
99.179 - // fixme: if this method is called twice, memory will not be
99.180 - // dealocated
99.181 - // one transcoder can be used only for one file request?
99.182 - if (file != NULL) {
99.183 - gchar **splited = g_strsplit(file, "_", 2);
99.184 -
99.185 - // Get chanid
99.186 - sscanf(splited[0], "%d", &(transcoder->chanid));
99.187 -
99.188 - // Get starttime
99.189 - gchar **date = g_strsplit(splited[1], ".", 2);
99.190 -
99.191 - transcoder->starttime =
99.192 - gmyth_transcoder_date_change_format(date[0], DATE_ISO);
99.193 -
99.194 - transcoder->filename = g_strdup(file);
99.195 - }
99.196 -}
99.197 -
99.198 -
99.199 -/**
99.200 - *
99.201 - * gmyth_transcoder_set_profile
99.202 - * @brief set transcoder's profile
99.203 - * @param rec GMythTranscoder*
99.204 - * @param value the value
99.205 - * @return gint representing the result
99.206 - *
99.207 - **/
99.208 -gint
99.209 -gmyth_transcoder_set_profile(GMythTranscoder * trans, const gchar * value)
99.210 -{
99.211 - g_return_val_if_fail(value != NULL, -1);
99.212 -
99.213 - trans->profile = g_strndup(value, strlen(value));
99.214 -
99.215 - return 0;
99.216 -}
99.217 -
99.218 -gboolean
99.219 -gmyth_transcoder_start(GMythTranscoder * trans)
99.220 -{
99.221 - g_return_val_if_fail(trans != NULL, FALSE);
99.222 - g_return_val_if_fail(trans->backend_info != NULL, FALSE);
99.223 - g_return_val_if_fail(trans->filename != NULL, FALSE);
99.224 -
99.225 - if (trans->started == FALSE) { // not started yet
99.226 - if (!gmyth_util_file_exists(trans->backend_info, trans->filename)) {
99.227 - gmyth_debug("File %s does not exist", trans->filename);
99.228 - }
99.229 - trans->started = gmyth_jobqueue_add_job(trans, "JOB_TRANSCODE");
99.230 - if (trans->started == FALSE)
99.231 - gmyth_debug("Error while starting GMythTranscoder to file: %s",
99.232 - trans->output_filename);
99.233 - } else {
99.234 - gmyth_debug("GMythTransfer already started!");
99.235 - }
99.236 -
99.237 - return trans->started;
99.238 -}
99.239 -
99.240 -gboolean
99.241 -gmyth_transcoder_pause(GMythTranscoder * trans)
99.242 -{
99.243 - g_return_val_if_fail(trans != NULL, FALSE);
99.244 - g_return_val_if_fail(trans->started == TRUE, FALSE);
99.245 -
99.246 - return gmyth_jobqueue_change_cmd(trans, "PAUSE", "JOB_TRANSCODE");
99.247 -}
99.248 -
99.249 -gboolean
99.250 -gmyth_transcoder_resume(GMythTranscoder * trans)
99.251 -{
99.252 - g_return_val_if_fail(trans != NULL, FALSE);
99.253 -
99.254 - return gmyth_jobqueue_change_cmd(trans, "RESUME", "JOB_TRANSCODE");
99.255 -}
99.256 -
99.257 -gboolean
99.258 -gmyth_transcoder_cancel(GMythTranscoder * trans)
99.259 -{
99.260 - g_return_val_if_fail(trans != NULL, FALSE);
99.261 - g_return_val_if_fail(trans->started == TRUE, FALSE);
99.262 -
99.263 - trans->started = FALSE;
99.264 -
99.265 - return gmyth_jobqueue_change_cmd(trans, "STOP", "JOB_TRANSCODE");
99.266 -}
99.267 -
99.268 -// fixme: implement this method
99.269 -gint
99.270 -gmyth_transcoder_get_progress(GMythTranscoder * trans)
99.271 -{
99.272 - static int fixme = 0;
99.273 -
99.274 - return (fixme++) % 101;
99.275 -}
100.1 --- a/gmyth/src/gmyth_transcoder.h Mon Feb 25 17:45:36 2008 +0000
100.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
100.3 @@ -1,104 +0,0 @@
100.4 -/**
100.5 - * GMyth Library
100.6 - *
100.7 - * @file gmyth/gmyth_transcoder.h
100.8 - *
100.9 - * @brief <p> This file contains the transcoder class.
100.10 - *
100.11 - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
100.12 - * @author Artur Duque de Souza <artur.souza@indt.org.br>
100.13 - *
100.14 - * This program is free software; you can redistribute it and/or modify
100.15 - * it under the terms of the GNU Lesser General Public License as published by
100.16 - * the Free Software Foundation; either version 2 of the License, or
100.17 - * (at your option) any later version.
100.18 - *
100.19 - * This program is distributed in the hope that it will be useful,
100.20 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
100.21 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
100.22 - * GNU General Public License for more details.
100.23 - *
100.24 - * You should have received a copy of the GNU Lesser General Public License
100.25 - * along with this program; if not, write to the Free Software
100.26 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
100.27 - */
100.28 -
100.29 -#ifndef _GMYTH_TRANSCODER_H
100.30 -#define _GMYTH_TRANSCODER_H
100.31 -
100.32 -#include <glib.h>
100.33 -#include <glib-object.h>
100.34 -
100.35 -#include "gmyth_stringlist.h"
100.36 -#include "gmyth_backendinfo.h"
100.37 -#include "gmyth_socket.h"
100.38 -#include "gmyth_http.h"
100.39 -#include "gmyth_recprofile.h"
100.40 -
100.41 -G_BEGIN_DECLS
100.42 -#define GMYTH_TRANSCODER_TYPE (gmyth_transcoder_get_type ())
100.43 -#define GMYTH_TRANSCODER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TRANSCODER_TYPE, GMythTranscoder))
100.44 -#define GMYTH_TRANSCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TRANSCODER_TYPE, GMythTranscoderClass))
100.45 -#define IS_GMYTH_TRANSCODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_TRANSCODER_TYPE))
100.46 -#define IS_GMYTH_TRANSCODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TRANSCODER_TYPE))
100.47 -#define GMYTH_TRANSCODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_TRANSCODER_TYPE, GMythTranscoderClass))
100.48 -#define DATE_ISO 0
100.49 -#define DATE_FILE 1
100.50 -typedef struct _GMythTranscoder GMythTranscoder;
100.51 -typedef struct _GMythTranscoderClass GMythTranscoderClass;
100.52 -
100.53 -struct _GMythTranscoderClass {
100.54 - GObjectClass parent_class;
100.55 -
100.56 - /*
100.57 - * callbacks
100.58 - */
100.59 -};
100.60 -
100.61 -/**
100.62 - * The GMythTranscoder structure is a class to implement functions
100.63 - * related to transcoding.
100.64 - */
100.65 -struct _GMythTranscoder {
100.66 - GObject parent;
100.67 -
100.68 - gboolean cutlist;
100.69 - gboolean output;
100.70 - gboolean started;
100.71 -
100.72 - /*
100.73 - * private begin
100.74 - */
100.75 - gchar *output_filename;
100.76 - gchar *filename;
100.77 - gchar *profile;
100.78 - /*
100.79 - * private end
100.80 - */
100.81 -
100.82 - gchar *starttime;
100.83 -
100.84 - gint chanid;
100.85 -
100.86 - GMythBackendInfo *backend_info;
100.87 -};
100.88 -
100.89 -GType gmyth_transcoder_type(void);
100.90 -
100.91 -GMythTranscoder *gmyth_transcoder_new(GMythBackendInfo * backend_info);
100.92 -void gmyth_transcoder_set_output(GMythTranscoder * transcode,
100.93 - gboolean value,
100.94 - const gchar * outputfile);
100.95 -void gmyth_transcoder_set_filename(GMythTranscoder * transcode,
100.96 - const gchar * file);
100.97 -gint gmyth_transcoder_set_profile(GMythTranscoder * trans,
100.98 - const gchar * value);
100.99 -gboolean gmyth_transcoder_start(GMythTranscoder * trans);
100.100 -gboolean gmyth_transcoder_pause(GMythTranscoder * trans);
100.101 -gboolean gmyth_transcoder_resume(GMythTranscoder * trans);
100.102 -gboolean gmyth_transcoder_cancel(GMythTranscoder * trans);
100.103 -gint gmyth_transcoder_get_progress(GMythTranscoder * trans);
100.104 -
100.105 -
100.106 -G_END_DECLS
100.107 -#endif /*_GMYTH_TRANSCODER_H*/
101.1 --- a/gmyth/src/gmyth_tvchain.c Mon Feb 25 17:45:36 2008 +0000
101.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
101.3 @@ -1,620 +0,0 @@
101.4 -/**
101.5 - * GMyth Library
101.6 - *
101.7 - * @file gmyth/gmyth_tvchain.c
101.8 - *
101.9 - * @brief <p> This component contains functions for creating and accessing
101.10 - * the tvchain functions for live tv playback.
101.11 - *
101.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
101.13 - * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
101.14 - *
101.15 - *
101.16 - * This program is free software; you can redistribute it and/or modify
101.17 - * it under the terms of the GNU Lesser General Public License as published by
101.18 - * the Free Software Foundation; either version 2 of the License, or
101.19 - * (at your option) any later version.
101.20 - *
101.21 - * This program is distributed in the hope that it will be useful,
101.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
101.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
101.24 - * GNU General Public License for more details.
101.25 - *
101.26 - * You should have received a copy of the GNU Lesser General Public License
101.27 - * along with this program; if not, write to the Free Software
101.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
101.29 - */
101.30 -
101.31 -#ifdef HAVE_CONFIG_H
101.32 -#include "config.h"
101.33 -#endif
101.34 -
101.35 -#include "gmyth_tvchain.h"
101.36 -
101.37 -#include <glib.h>
101.38 -#include <time.h>
101.39 -#include <stdio.h>
101.40 -#include <stdlib.h>
101.41 -#include <assert.h>
101.42 -
101.43 -#include "gmyth_epg.h"
101.44 -#include "gmyth_util.h"
101.45 -#include "gmyth_query.h"
101.46 -#include "gmyth_scheduler.h"
101.47 -#include "gmyth_debug.h"
101.48 -
101.49 -static void gmyth_tvchain_class_init(GMythTVChainClass * klass);
101.50 -static void gmyth_tvchain_init(GMythTVChain * object);
101.51 -
101.52 -static void gmyth_tvchain_dispose(GObject * object);
101.53 -static void gmyth_tvchain_finalize(GObject * object);
101.54 -
101.55 -static void free_tvchain_entry(gpointer data, gpointer user_data);
101.56 -
101.57 -G_DEFINE_TYPE(GMythTVChain, gmyth_tvchain, G_TYPE_OBJECT)
101.58 - static void gmyth_tvchain_class_init(GMythTVChainClass * klass)
101.59 -{
101.60 - GObjectClass *gobject_class;
101.61 -
101.62 - gobject_class = (GObjectClass *) klass;
101.63 -
101.64 - gobject_class->dispose = gmyth_tvchain_dispose;
101.65 - gobject_class->finalize = gmyth_tvchain_finalize;
101.66 -}
101.67 -
101.68 -static void
101.69 -gmyth_tvchain_init(GMythTVChain * tvchain)
101.70 -{
101.71 - tvchain->tvchain_id = NULL;
101.72 -
101.73 - tvchain->cur_chanid = g_string_new("");
101.74 - tvchain->cur_startts = NULL;
101.75 -
101.76 - tvchain->mutex = g_mutex_new();
101.77 -}
101.78 -
101.79 -GMythTVChain *
101.80 -gmyth_tvchain_new()
101.81 -{
101.82 - GMythTVChain *tvchain =
101.83 - GMYTH_TVCHAIN(g_object_new(GMYTH_TVCHAIN_TYPE, NULL));
101.84 -
101.85 - return tvchain;
101.86 -}
101.87 -
101.88 -static void
101.89 -gmyth_tvchain_dispose(GObject * object)
101.90 -{
101.91 - GMythTVChain *tvchain = GMYTH_TVCHAIN(object);
101.92 -
101.93 - if (tvchain->tvchain_id != NULL) {
101.94 - g_string_free(tvchain->tvchain_id, TRUE);
101.95 - tvchain->tvchain_id = NULL;
101.96 - }
101.97 -
101.98 - if (tvchain->mutex != NULL) {
101.99 - g_mutex_free(tvchain->mutex);
101.100 - tvchain->mutex = NULL;
101.101 - }
101.102 -
101.103 - if (tvchain->tvchain_list != NULL) {
101.104 - g_list_foreach(tvchain->tvchain_list, free_tvchain_entry, NULL);
101.105 - g_list_free(tvchain->tvchain_list);
101.106 - }
101.107 -
101.108 - if (tvchain->cur_chanid != NULL) {
101.109 - g_string_free(tvchain->cur_chanid, TRUE);
101.110 - tvchain->cur_chanid = NULL;
101.111 - }
101.112 -
101.113 - if (tvchain->backend_info) {
101.114 - g_object_unref(tvchain->backend_info);
101.115 - tvchain->backend_info = NULL;
101.116 - }
101.117 -
101.118 -
101.119 - G_OBJECT_CLASS(gmyth_tvchain_parent_class)->dispose(object);
101.120 -}
101.121 -
101.122 -static void
101.123 -gmyth_tvchain_finalize(GObject * object)
101.124 -{
101.125 - g_signal_handlers_destroy(object);
101.126 -
101.127 - G_OBJECT_CLASS(gmyth_tvchain_parent_class)->finalize(object);
101.128 -}
101.129 -
101.130 -/** Initializes the tvchain and generates the tvchain id.
101.131 - *
101.132 - * @param tvchain The GMythTVChain instance.
101.133 - * @param hostname The local hostname used to generate the tvchain id.
101.134 - */
101.135 -gboolean
101.136 -gmyth_tvchain_initialize(GMythTVChain * tvchain,
101.137 - GMythBackendInfo * backend_info)
101.138 -{
101.139 - const char *hostname;
101.140 -
101.141 - assert(tvchain);
101.142 - g_return_val_if_fail(backend_info != NULL, FALSE);
101.143 -
101.144 - g_object_ref(backend_info);
101.145 - tvchain->backend_info = backend_info;
101.146 -
101.147 - hostname = gmyth_backend_info_get_hostname(backend_info);
101.148 -
101.149 - if (tvchain->tvchain_id == NULL) {
101.150 - gchar *isodate = NULL;
101.151 - GTimeVal *cur_time = g_new0(GTimeVal, 1);
101.152 -
101.153 - // struct tm* gmyth_util_time_val_to_date ( const GTimeVal* time )
101.154 -
101.155 - g_get_current_time(cur_time);
101.156 - isodate =
101.157 - gmyth_util_time_to_isoformat_from_time_val_fmt
101.158 - ("%Y-%m-%dT%H:%M:%S", cur_time);
101.159 -
101.160 - tvchain->tvchain_id =
101.161 - g_string_sized_new(7 + strlen(hostname) + strlen(isodate));
101.162 - g_string_printf(tvchain->tvchain_id, "live-%s-%s", hostname,
101.163 - isodate);
101.164 -
101.165 - gmyth_debug("[%s] tv_chain_id: %s", __FUNCTION__,
101.166 - tvchain->tvchain_id->str);
101.167 -
101.168 - g_free(isodate);
101.169 - g_free(cur_time);
101.170 - } else {
101.171 - gmyth_debug("[%s] TVchain already initialized", __FUNCTION__);
101.172 - }
101.173 -
101.174 - return TRUE;
101.175 -}
101.176 -
101.177 -/** Gets the tvchain id.
101.178 - *
101.179 - * @param tvchain The GMythTVChain instance.
101.180 - * @return The tvchain id.
101.181 - */
101.182 -GString *
101.183 -gmyth_tvchain_get_id(GMythTVChain * tvchain)
101.184 -{
101.185 - g_return_val_if_fail(tvchain != NULL
101.186 - && tvchain->tvchain_id != NULL, NULL);
101.187 -
101.188 - return tvchain->tvchain_id;
101.189 -}
101.190 -
101.191 -/** Reloads all tvchain entries in the database.
101.192 - *
101.193 - * @param tvchain The GMythTVChain instance.
101.194 - * @return TRUE if success, or FALSE if error.
101.195 - */
101.196 -gboolean
101.197 -gmyth_tvchain_reload_all(GMythTVChain * tvchain)
101.198 -{
101.199 - MYSQL_ROW msql_row;
101.200 - MYSQL_RES *msql_res = NULL;
101.201 - GMythQuery *gmyth_query = NULL;
101.202 - gboolean ret = TRUE;
101.203 - GString *stmt_str = NULL;
101.204 -
101.205 - g_mutex_lock(tvchain->mutex);
101.206 -
101.207 - /*
101.208 - * gets the initial size of the TVChain entries list
101.209 - */
101.210 - guint prev_size = g_list_length(tvchain->tvchain_list);
101.211 -
101.212 - gmyth_debug("[%s] chainid: %s", __FUNCTION__,
101.213 - tvchain->tvchain_id->str);
101.214 -
101.215 - if (tvchain != NULL && tvchain->tvchain_list != NULL) {
101.216 - g_list_free(tvchain->tvchain_list);
101.217 - tvchain->tvchain_list = NULL;
101.218 - }
101.219 -
101.220 - /*
101.221 - * TODO: Reuse gmyth_query already connected from context
101.222 - */
101.223 - gmyth_query = gmyth_query_new();
101.224 - if (!gmyth_query_connect(gmyth_query, tvchain->backend_info)) {
101.225 - gmyth_debug("[%s] Could not connect to db", __FUNCTION__);
101.226 - g_mutex_unlock(tvchain->mutex);
101.227 - ret = FALSE;
101.228 - goto done;
101.229 - }
101.230 -
101.231 - stmt_str = g_string_new("");
101.232 - g_string_printf(stmt_str,
101.233 - "SELECT chanid, starttime, endtime, discontinuity, "
101.234 - "chainpos, hostprefix, cardtype, channame, input "
101.235 - "FROM tvchain "
101.236 - "WHERE chainid = \"%s\" ORDER BY chainpos;",
101.237 - tvchain->tvchain_id->str);
101.238 -
101.239 - msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str);
101.240 - if (msql_res != NULL) {
101.241 -
101.242 - while ((msql_row = mysql_fetch_row(msql_res)) != NULL) {
101.243 - struct LiveTVChainEntry *entry =
101.244 - g_new0(struct LiveTVChainEntry, 1);
101.245 - entry->chanid = g_string_new(msql_row[0]);
101.246 - entry->starttime =
101.247 - gmyth_util_string_to_time_val((const gchar *) msql_row[1]);
101.248 - entry->endtime =
101.249 - gmyth_util_string_to_time_val((const gchar *) msql_row[2]);
101.250 - entry->discontinuity =
101.251 - g_ascii_strtoull(msql_row[3], NULL, 10) != 0;
101.252 - entry->hostprefix = g_string_new(msql_row[5]);
101.253 - entry->cardtype = g_string_new(msql_row[6]);
101.254 - entry->channum = g_string_new(msql_row[7]);
101.255 - entry->inputname = g_string_new(msql_row[8]);
101.256 -
101.257 - // m_maxpos = query.value(4).toInt() + 1;
101.258 - gmyth_debug
101.259 - ("[%s] Reading TV chain entry (channel %s): [%s, %s, %s]\n",
101.260 - __FUNCTION__, entry->channum->str, entry->chanid->str,
101.261 - (gchar *) msql_row[1], (gchar *) msql_row[2]);
101.262 -
101.263 - /*
101.264 - * add this to get the actual start timestamp of the last
101.265 - * recording
101.266 - */
101.267 - if (tvchain->cur_startts < entry->starttime)
101.268 - tvchain->cur_startts = entry->starttime;
101.269 -
101.270 - tvchain->tvchain_list =
101.271 - g_list_append(tvchain->tvchain_list, entry);
101.272 - }
101.273 - } else {
101.274 - gmyth_debug("gmyth_tvchain_reload_all query error!\n");
101.275 - g_mutex_unlock(tvchain->mutex);
101.276 -
101.277 - ret = FALSE;
101.278 - goto done;
101.279 - }
101.280 -
101.281 - g_mutex_unlock(tvchain->mutex);
101.282 -
101.283 - tvchain->cur_pos =
101.284 - gmyth_tvchain_program_is_at(tvchain, tvchain->cur_chanid,
101.285 - tvchain->cur_startts);
101.286 - gmyth_debug("[%s] TVChain current position = %d.\n", __FUNCTION__,
101.287 - tvchain->cur_pos);
101.288 -
101.289 - if (tvchain->cur_pos < 0)
101.290 - tvchain->cur_pos = 0;
101.291 -
101.292 - // if (m_switchid >= 0)
101.293 - // m_switchid =
101.294 - // ProgramIsAt(m_switchentry.chanid,m_switchentry.starttime);
101.295 -
101.296 - if (prev_size != g_list_length(tvchain->tvchain_list)) {
101.297 - gmyth_debug("[%s] Added new recording", __FUNCTION__);
101.298 - }
101.299 -
101.300 - done:
101.301 - if (stmt_str != NULL)
101.302 - g_string_free(stmt_str, TRUE);
101.303 -
101.304 - if (msql_res != NULL)
101.305 - mysql_free_result(msql_res);
101.306 -
101.307 - if (gmyth_query != NULL)
101.308 - g_object_unref(gmyth_query);
101.309 -
101.310 - return ret;
101.311 -}
101.312 -
101.313 -/**
101.314 - * Get all the program info entries in the database.
101.315 - *
101.316 - * @param tvchain The GMythTVChain instance.
101.317 - *
101.318 - * @return A program info listage.
101.319 - */
101.320 -GList *
101.321 -gmyth_tvchain_get_program_info_list(GMythTVChain * tvchain)
101.322 -{
101.323 - GList *prog_list = NULL;
101.324 - MYSQL_ROW msql_row;
101.325 - MYSQL_RES *msql_res = NULL;
101.326 - GMythQuery *gmyth_query = NULL;
101.327 - GString *stmt_str = NULL;
101.328 -
101.329 - g_mutex_lock(tvchain->mutex);
101.330 -
101.331 - gmyth_query = gmyth_query_new();
101.332 - if (!gmyth_query_connect(gmyth_query, tvchain->backend_info)) {
101.333 - gmyth_debug("Could not connect to db.");
101.334 - goto done;
101.335 - }
101.336 -
101.337 - stmt_str = g_string_new("");
101.338 - g_string_printf(stmt_str,
101.339 - "SELECT channum, icon " "FROM channel "
101.340 - "ORDER BY channum;");
101.341 -
101.342 - msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str);
101.343 - if (msql_res != NULL) {
101.344 -
101.345 - while ((msql_row = mysql_fetch_row(msql_res)) != NULL) {
101.346 - GMythProgramInfo *entry = gmyth_program_info_new();
101.347 -
101.348 - entry->channame = g_string_new(msql_row[0]);
101.349 - entry->chansign = g_string_new(msql_row[1]);
101.350 -
101.351 - gmyth_debug
101.352 - ("Reading TV program info entry (channel %s): [%s - {%s, %s}]\n",
101.353 - entry->channame->str, entry->chansign->str,
101.354 - (gchar *) msql_row[0], (gchar *) msql_row[1]);
101.355 -
101.356 - prog_list = g_list_append(prog_list, entry);
101.357 - }
101.358 - } else {
101.359 - gmyth_debug
101.360 - ("Query error when trying to get the channel list from database!\n");
101.361 - goto done;
101.362 - }
101.363 -
101.364 - done:
101.365 - g_mutex_unlock(tvchain->mutex);
101.366 -
101.367 - if (stmt_str != NULL)
101.368 - g_string_free(stmt_str, TRUE);
101.369 -
101.370 - if (msql_res != NULL)
101.371 - mysql_free_result(msql_res);
101.372 -
101.373 - if (gmyth_query != NULL)
101.374 - g_object_unref(gmyth_query);
101.375 -
101.376 - return prog_list;
101.377 -}
101.378 -
101.379 -/**
101.380 - * Get all the program info entries in the database, given a channel name.
101.381 - *
101.382 - * @param tvchain The GMythTVChain instance.
101.383 - * @param channel The channel name.
101.384 - *
101.385 - * @return A program info listage, based on a given channel name.
101.386 - */
101.387 -GList *
101.388 -gmyth_tvchain_get_program_info_from_channel(GMythTVChain * tvchain,
101.389 - const gchar * channel)
101.390 -{
101.391 - GList *prog_list = NULL;
101.392 - MYSQL_ROW msql_row;
101.393 - MYSQL_RES *msql_res = NULL;
101.394 - GMythQuery *gmyth_query = NULL;
101.395 - GString *stmt_str = NULL;
101.396 -
101.397 - g_mutex_lock(tvchain->mutex);
101.398 -
101.399 - gmyth_query = gmyth_query_new();
101.400 - if (!gmyth_query_connect(gmyth_query, tvchain->backend_info)) {
101.401 - gmyth_debug("Could not connect to db.");
101.402 - goto done;
101.403 - }
101.404 -
101.405 - stmt_str = g_string_new("");
101.406 - g_string_printf(stmt_str,
101.407 - "SELECT channum, icon "
101.408 - "FROM channel "
101.409 - "WHERE channum = \"%s\" ORDER BY channum;", channel);
101.410 -
101.411 - msql_res = gmyth_query_process_statement(gmyth_query, stmt_str->str);
101.412 - if (msql_res != NULL) {
101.413 -
101.414 - while ((msql_row = mysql_fetch_row(msql_res)) != NULL) {
101.415 - GMythProgramInfo *entry = gmyth_program_info_new();
101.416 -
101.417 - entry->channame = g_string_new(msql_row[0]);
101.418 - entry->chansign = g_string_new(msql_row[1]);
101.419 -
101.420 - gmyth_debug
101.421 - ("Reading TV program info entry (channel %s): [%s - {%s, %s}]\n",
101.422 - entry->channame->str, entry->chansign->str,
101.423 - (gchar *) msql_row[0], (gchar *) msql_row[1]);
101.424 -
101.425 - prog_list = g_list_append(prog_list, entry);
101.426 - }
101.427 - } else {
101.428 - gmyth_debug
101.429 - ("Query error when trying to get the channel list from database!\n");
101.430 - goto done;
101.431 - }
101.432 -
101.433 - done:
101.434 - g_mutex_unlock(tvchain->mutex);
101.435 -
101.436 - if (stmt_str != NULL)
101.437 - g_string_free(stmt_str, TRUE);
101.438 -
101.439 - if (msql_res != NULL)
101.440 - mysql_free_result(msql_res);
101.441 -
101.442 - if (gmyth_query != NULL)
101.443 - g_object_unref(gmyth_query);
101.444 -
101.445 - return prog_list;
101.446 -}
101.447 -
101.448 -/**
101.449 - * Returns the internal index for the TV chain related to the given
101.450 - * channel and start time.
101.451 - *
101.452 - * @param tvchain The GMythTVChain instance.
101.453 - * @param chanid The channel id.
101.454 - * @param startts The program start time.
101.455 - *
101.456 - * @return The position of the related program info in the TV chain.
101.457 - */
101.458 -gint
101.459 -gmyth_tvchain_program_is_at(GMythTVChain * tvchain, GString * chanid,
101.460 - GTimeVal * startts)
101.461 -{
101.462 - gint count = 0;
101.463 - struct LiveTVChainEntry *entry;
101.464 - GList *tmp_list = tvchain->tvchain_list;
101.465 - guint list_size = g_list_length(tvchain->tvchain_list);
101.466 -
101.467 - g_mutex_lock(tvchain->mutex);
101.468 -
101.469 - for (; tmp_list && (count < list_size);
101.470 - tmp_list = tvchain->tvchain_list->next, count++) {
101.471 - entry = (struct LiveTVChainEntry *) tmp_list->data;
101.472 - if (!g_strncasecmp(entry->chanid->str, chanid->str, chanid->len)
101.473 - && entry->starttime == startts) {
101.474 - g_mutex_unlock(tvchain->mutex);
101.475 - return count;
101.476 - }
101.477 - }
101.478 - g_mutex_unlock(tvchain->mutex);
101.479 -
101.480 - return -1;
101.481 -}
101.482 -
101.483 -/** Get the program info associated to the tvchain.
101.484 - *
101.485 - * @param tvchain The GMythTVChain instance.
101.486 - * @param index The tvchain index.
101.487 - *
101.488 - * @return The program info structure.
101.489 - */
101.490 -GMythProgramInfo *
101.491 -gmyth_tvchain_get_program_at(GMythTVChain * tvchain, gint index)
101.492 -{
101.493 - struct LiveTVChainEntry *entry;
101.494 -
101.495 - entry = gmyth_tvchain_get_entry_at(tvchain, index);
101.496 -
101.497 - if (entry)
101.498 - return gmyth_tvchain_entry_to_program(tvchain, entry);
101.499 -
101.500 - return NULL;
101.501 -}
101.502 -
101.503 -/** Gets a LiveTVChainEntry associated to the tvchain by its index.
101.504 - *
101.505 - * @param tvchain The GMythTVChain instance.
101.506 - * @param index The tvchain entry index
101.507 - * @return The LiveTVchainEntry structure.
101.508 - */
101.509 -struct LiveTVChainEntry *
101.510 -gmyth_tvchain_get_entry_at(GMythTVChain * tvchain, gint index)
101.511 -{
101.512 - struct LiveTVChainEntry *chain_entry = NULL;
101.513 -
101.514 - g_return_val_if_fail(tvchain != NULL
101.515 - && tvchain->tvchain_list != NULL, NULL);
101.516 -
101.517 - g_mutex_lock(tvchain->mutex);
101.518 -
101.519 - gint size = g_list_length(tvchain->tvchain_list);
101.520 - gint new_index = (index < 0
101.521 - || index >= size) ? size - 1 : index;
101.522 -
101.523 - if (new_index >= 0)
101.524 - chain_entry =
101.525 - (struct LiveTVChainEntry *) g_list_nth_data(tvchain->
101.526 - tvchain_list,
101.527 - new_index);
101.528 -
101.529 - g_mutex_unlock(tvchain->mutex);
101.530 -
101.531 - if (chain_entry != NULL) {
101.532 - gmyth_debug("[%s] Got TV Chain entry at %d.\n", __FUNCTION__,
101.533 - new_index);
101.534 -
101.535 - } else {
101.536 - gmyth_debug("[%s] failed to get entry at index %d", __FUNCTION__,
101.537 - index);
101.538 - }
101.539 -
101.540 - return chain_entry;
101.541 -}
101.542 -
101.543 -/**
101.544 - * Gets the program info from backend database associated to the tv chain entry.
101.545 - *
101.546 - * @param tvchain The GMythTVChain instance.
101.547 - * @param entry the LiveTVChainEntry to be converted.
101.548 - *
101.549 - * @return The program info.
101.550 - */
101.551 -GMythProgramInfo *
101.552 -gmyth_tvchain_entry_to_program(GMythTVChain * tvchain,
101.553 - struct LiveTVChainEntry * entry)
101.554 -{
101.555 - GMythProgramInfo *proginfo = NULL;
101.556 -
101.557 - g_return_val_if_fail(tvchain != NULL, NULL);
101.558 -
101.559 - if (!entry || !tvchain) {
101.560 - gmyth_debug
101.561 - ("gmyth_tvchain_entry_to_program() received NULL argument");
101.562 - return NULL;
101.563 - }
101.564 -
101.565 - GMythScheduler *scheduler = gmyth_scheduler_new();
101.566 -
101.567 - gmyth_scheduler_connect(scheduler, tvchain->backend_info);
101.568 - proginfo = gmyth_scheduler_get_recorded(scheduler,
101.569 - entry->chanid,
101.570 - entry->starttime);
101.571 - gmyth_scheduler_disconnect(scheduler);
101.572 -
101.573 - if (proginfo) {
101.574 - proginfo->pathname =
101.575 - g_string_prepend(proginfo->pathname, entry->hostprefix->str);
101.576 - } else {
101.577 - gmyth_debug
101.578 - ("tvchain_entry_to_program( chan id = %s, starttime = %ld) failed!",
101.579 - entry->chanid->str, entry->starttime->tv_sec);
101.580 - }
101.581 -
101.582 - return proginfo;
101.583 -}
101.584 -
101.585 -static void
101.586 -free_tvchain_entry(gpointer data, gpointer user_data)
101.587 -{
101.588 - struct LiveTVChainEntry *entry;
101.589 -
101.590 - g_return_if_fail(data != NULL);
101.591 -
101.592 - entry = (struct LiveTVChainEntry *) data;
101.593 -
101.594 - if (entry->chanid != NULL) {
101.595 - g_string_free(entry->chanid, TRUE);
101.596 - }
101.597 -
101.598 - if (entry->starttime != NULL) {
101.599 - g_free(entry->starttime);
101.600 - }
101.601 -
101.602 - if (entry->endtime != NULL) {
101.603 - g_free(entry->endtime);
101.604 - }
101.605 -
101.606 - if (entry->hostprefix) {
101.607 - g_string_free(entry->hostprefix, TRUE);
101.608 - }
101.609 -
101.610 - if (entry->cardtype) {
101.611 - g_string_free(entry->cardtype, TRUE);
101.612 - }
101.613 -
101.614 - if (entry->channum) {
101.615 - g_string_free(entry->channum, TRUE);
101.616 - }
101.617 -
101.618 - if (entry->inputname) {
101.619 - g_string_free(entry->inputname, TRUE);
101.620 - }
101.621 -
101.622 - g_free(entry);
101.623 -}
102.1 --- a/gmyth/src/gmyth_tvchain.h Mon Feb 25 17:45:36 2008 +0000
102.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
102.3 @@ -1,118 +0,0 @@
102.4 -/**
102.5 - * GMyth Library
102.6 - *
102.7 - * @file gmyth/gmyth_tvchain.h
102.8 - *
102.9 - * @brief <p> This component contains functions for creating and accessing
102.10 - * the tvchain functions for live tv playback.
102.11 - *
102.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
102.13 - * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
102.14 - *
102.15 - *
102.16 - * This program is free software; you can redistribute it and/or modify
102.17 - * it under the terms of the GNU Lesser General Public License as published by
102.18 - * the Free Software Foundation; either version 2 of the License, or
102.19 - * (at your option) any later version.
102.20 - *
102.21 - * This program is distributed in the hope that it will be useful,
102.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
102.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
102.24 - * GNU General Public License for more details.
102.25 - *
102.26 - * You should have received a copy of the GNU Lesser General Public License
102.27 - * along with this program; if not, write to the Free Software
102.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
102.29 - */
102.30 -
102.31 -#ifndef LIVETVCHAIN_H_
102.32 -#define LIVETVCHAIN_H_
102.33 -
102.34 -#include <glib-object.h>
102.35 -#include <time.h>
102.36 -
102.37 -#include "gmyth_common.h"
102.38 -#include "gmyth_backendinfo.h"
102.39 -
102.40 -G_BEGIN_DECLS
102.41 -#define GMYTH_TVCHAIN_TYPE (gmyth_tvchain_get_type ())
102.42 -#define GMYTH_TVCHAIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_TVCHAIN_TYPE, GMythTVChain))
102.43 -#define GMYTH_TVCHAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVCHAIN_TYPE, GMythTVChainClass))
102.44 -#define IS_GMYTH_TVCHAIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_TVCHAIN_TYPE))
102.45 -#define IS_GMYTH_TVCHAIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_TVCHAIN_TYPE))
102.46 -#define GMYTH_TVCHAIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_TVCHAIN_TYPE, GMythTVChainClass))
102.47 -typedef struct _GMythTVChain GMythTVChain;
102.48 -typedef struct _GMythTVChainClass GMythTVChainClass;
102.49 -
102.50 -
102.51 -struct LiveTVChainEntry {
102.52 - GString *chanid;
102.53 -
102.54 - GTimeVal *starttime;
102.55 - GTimeVal *endtime;
102.56 -
102.57 - gboolean discontinuity; // if true, can't play smooth from
102.58 - // last entry
102.59 - GString *hostprefix;
102.60 - GString *cardtype;
102.61 - GString *channum;
102.62 - GString *inputname;
102.63 -};
102.64 -
102.65 -
102.66 -struct _GMythTVChainClass {
102.67 - GObjectClass parent_class;
102.68 -
102.69 - /*
102.70 - * callbacks
102.71 - */
102.72 - /*
102.73 - * no one for now
102.74 - */
102.75 -};
102.76 -
102.77 -struct _GMythTVChain {
102.78 - GObject parent;
102.79 -
102.80 - GString *tvchain_id;
102.81 - GList *tvchain_list;
102.82 -
102.83 - GTimeVal *cur_startts;
102.84 - GString *cur_chanid;
102.85 - gint cur_pos;
102.86 -
102.87 - GMythBackendInfo *backend_info;
102.88 -
102.89 - GMutex *mutex;
102.90 -};
102.91 -
102.92 -GType gmyth_tvchain_get_type(void);
102.93 -
102.94 -GMythTVChain *gmyth_tvchain_new();
102.95 -
102.96 -gboolean gmyth_tvchain_initialize(GMythTVChain * tvchain,
102.97 - GMythBackendInfo * backend_info);
102.98 -gboolean gmyth_tvchain_reload_all(GMythTVChain * tvchain);
102.99 -GString *gmyth_tvchain_get_id(GMythTVChain * tvchain);
102.100 -gint gmyth_tvchain_program_is_at(GMythTVChain * tvchain,
102.101 - GString * chanid,
102.102 - GTimeVal * startts);
102.103 -
102.104 -struct LiveTVChainEntry *gmyth_tvchain_get_entry_at(GMythTVChain * tvchain,
102.105 - gint index);
102.106 -
102.107 -GMythProgramInfo *gmyth_tvchain_entry_to_program(GMythTVChain * tvchain, struct LiveTVChainEntry
102.108 - *entry);
102.109 -GMythProgramInfo *gmyth_tvchain_get_program_at(GMythTVChain * tvchain,
102.110 - gint index);
102.111 -
102.112 -GList *gmyth_tvchain_get_program_info_from_channel(GMythTVChain *
102.113 - tvchain,
102.114 - const gchar *
102.115 - channel);
102.116 -
102.117 -GList *gmyth_tvchain_get_program_info_list(GMythTVChain *
102.118 - tvchain);
102.119 -
102.120 -G_END_DECLS
102.121 -#endif /* LIVETVCHAIN_H_ */
103.1 --- a/gmyth/src/gmyth_uri.c Mon Feb 25 17:45:36 2008 +0000
103.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
103.3 @@ -1,604 +0,0 @@
103.4 -/**
103.5 - * GMyth Library
103.6 - *
103.7 - * @file gmyth/gmyth_uri.c
103.8 - *
103.9 - * @brief <p> GMythURI utils
103.10 - * - Extracts and parses a URI char string, in according with the RFC 2396
103.11 - * [http://www.ietf.org/rfc/rfc2396.txt]
103.12 - *
103.13 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
103.14 - * @author Rosfran Borges <rosfran.borges@indt.org.br>
103.15 - *
103.16 - *
103.17 - * This program is free software; you can redistribute it and/or modify
103.18 - * it under the terms of the GNU Lesser General Public License as published by
103.19 - * the Free Software Foundation; either version 2 of the License, or
103.20 - * (at your option) any later version.
103.21 - *
103.22 - * This program is distributed in the hope that it will be useful,
103.23 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
103.24 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
103.25 - * GNU General Public License for more details.
103.26 - *
103.27 - * You should have received a copy of the GNU Lesser General Public License
103.28 - * along with this program; if not, write to the Free Software
103.29 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
103.30 - */
103.31 -
103.32 -#ifdef HAVE_CONFIG_H
103.33 -#include "config.h"
103.34 -#endif
103.35 -
103.36 -#include "gmyth_uri.h"
103.37 -#include "gmyth_socket.h"
103.38 -
103.39 -#include <glib.h>
103.40 -#include <string.h>
103.41 -#include <stdlib.h>
103.42 -
103.43 -#include "gmyth_debug.h"
103.44 -
103.45 -/****************************************
103.46 -* Define
103.47 -****************************************/
103.48 -
103.49 -#define GMYTH_URI_KNKOWN_PORT (-1)
103.50 -#define GMYTH_URI_DEFAULT_HTTP_PORT 80
103.51 -#define GMYTH_URI_DEFAULT_FTP_PORT 21
103.52 -#define GMYTH_URI_DEFAULT_MYTH_PORT 6543
103.53 -#define GMYTH_URI_DEFAULT_PATH "/"
103.54 -#define GMYTH_URI_MAXLEN 256
103.55 -
103.56 -#define GMYTH_URI_PROTOCOL_DELIM "://"
103.57 -#define GMYTH_URI_USER_DELIM "@"
103.58 -#define GMYTH_URI_COLON_DELIM ":"
103.59 -#define GMYTH_URI_SLASH_DELIM "/"
103.60 -#define GMYTH_URI_SBLACET_DELIM "["
103.61 -#define GMYTH_URI_EBLACET_DELIM "]"
103.62 -#define GMYTH_URI_SHARP_DELIM "#"
103.63 -#define GMYTH_URI_QUESTION_DELIM "?"
103.64 -#define GMYTH_URI_E_DELIM "&"
103.65 -#define GMYTH_URI_ESCAPING_CHAR "%"
103.66 -
103.67 -#define GMYTH_URI_PROTOCOL_MYTH "myth"
103.68 -#define GMYTH_URI_PROTOCOL_HTTP "http"
103.69 -#define GMYTH_URI_PROTOCOL_FTP "ftp"
103.70 -
103.71 -
103.72 -static void gmyth_uri_class_init(GMythURIClass * klass);
103.73 -static void gmyth_uri_init(GMythURI * object);
103.74 -
103.75 -static void gmyth_uri_dispose(GObject * object);
103.76 -static void gmyth_uri_finalize(GObject * object);
103.77 -
103.78 -static void gmyth_uri_parser_setup_and_new(GMythURI * uri,
103.79 - const gchar * value);
103.80 -static gchar *gmyth_uri_print_field(const GString * field);
103.81 -
103.82 -G_DEFINE_TYPE(GMythURI, gmyth_uri, G_TYPE_OBJECT)
103.83 - static void gmyth_uri_class_init(GMythURIClass * klass)
103.84 -{
103.85 - GObjectClass *gobject_class;
103.86 -
103.87 - gobject_class = (GObjectClass *) klass;
103.88 -
103.89 - gobject_class->dispose = gmyth_uri_dispose;
103.90 - gobject_class->finalize = gmyth_uri_finalize;
103.91 -}
103.92 -
103.93 -static void
103.94 -gmyth_uri_init(GMythURI * gmyth_uri)
103.95 -{
103.96 -}
103.97 -
103.98 -static void
103.99 -gmyth_uri_dispose(GObject * object)
103.100 -{
103.101 - GMythURI *gmyth_uri = GMYTH_URI(object);
103.102 -
103.103 - if (gmyth_uri->host != NULL) {
103.104 - g_string_free(gmyth_uri->host, TRUE);
103.105 - gmyth_uri->host = NULL;
103.106 - }
103.107 -
103.108 - if (gmyth_uri->protocol != NULL) {
103.109 - g_string_free(gmyth_uri->protocol, TRUE);
103.110 - gmyth_uri->protocol = NULL;
103.111 - }
103.112 -
103.113 - if (gmyth_uri->path != NULL) {
103.114 - g_string_free(gmyth_uri->path, TRUE);
103.115 - gmyth_uri->path = NULL;
103.116 - }
103.117 -
103.118 - if (gmyth_uri->fragment != NULL) {
103.119 - g_string_free(gmyth_uri->fragment, TRUE);
103.120 - gmyth_uri->fragment = NULL;
103.121 - }
103.122 -
103.123 - if (gmyth_uri->user != NULL) {
103.124 - g_string_free(gmyth_uri->user, TRUE);
103.125 - gmyth_uri->user = NULL;
103.126 - }
103.127 -
103.128 - if (gmyth_uri->password != NULL) {
103.129 - g_string_free(gmyth_uri->password, TRUE);
103.130 - gmyth_uri->password = NULL;
103.131 - }
103.132 -
103.133 - if (gmyth_uri->query != NULL) {
103.134 - g_string_free(gmyth_uri->query, TRUE);
103.135 - gmyth_uri->query = NULL;
103.136 - }
103.137 -
103.138 - if (gmyth_uri->uri != NULL) {
103.139 - g_string_free(gmyth_uri->uri, TRUE);
103.140 - gmyth_uri->uri = NULL;
103.141 - }
103.142 -
103.143 -
103.144 - G_OBJECT_CLASS(gmyth_uri_parent_class)->dispose(object);
103.145 -}
103.146 -
103.147 -static void
103.148 -gmyth_uri_finalize(GObject * object)
103.149 -{
103.150 - // GMythURI *gmyth_uri = GMYTH_URI(object);
103.151 -
103.152 - g_signal_handlers_destroy(object);
103.153 -
103.154 - G_OBJECT_CLASS(gmyth_uri_parent_class)->finalize(object);
103.155 -}
103.156 -
103.157 -/**
103.158 - * Creates a new instance of GMythURI.
103.159 - *
103.160 - * @return a new instance of GMythURI.
103.161 - */
103.162 -GMythURI *
103.163 -gmyth_uri_new(void)
103.164 -{
103.165 - GMythURI *gmyth_uri =
103.166 - GMYTH_URI(g_object_new(GMYTH_URI_TYPE, NULL));
103.167 -
103.168 - return gmyth_uri;
103.169 -}
103.170 -
103.171 -/**
103.172 - * Creates a new instance of GMythURI.
103.173 - *
103.174 - * @param uri_str The URI string representing this URI instance.
103.175 - *
103.176 - * @return a new instance of GMythURI.
103.177 - */
103.178 -GMythURI *
103.179 -gmyth_uri_new_with_value(const gchar * uri_str)
103.180 -{
103.181 - GMythURI *gmyth_uri =
103.182 - GMYTH_URI(g_object_new(GMYTH_URI_TYPE, NULL));
103.183 -
103.184 - gmyth_uri_parser_setup_and_new(gmyth_uri, uri_str);
103.185 -
103.186 - return gmyth_uri;
103.187 -}
103.188 -
103.189 -/**
103.190 - * Gets the starting offset of a substring inside a given string.
103.191 - *
103.192 - * @param haystack The given string to be searched for patterns.
103.193 - * @param needle The substring that should be matched over the haystack.
103.194 - *
103.195 - * @return The starting offset to the given substring, or <code>-1</code> if the
103.196 - * haystack function parameter doesn't contains the needle string argument.
103.197 - */
103.198 -static gint
103.199 -gmyth_strstr(const gchar * haystack, const gchar * needle)
103.200 -{
103.201 -
103.202 - gchar *strPos;
103.203 -
103.204 - if (haystack == NULL || needle == NULL)
103.205 - return -1;
103.206 - strPos = strstr(haystack, needle);
103.207 - if (strPos == NULL)
103.208 - return -1;
103.209 -
103.210 - return (strPos - haystack);
103.211 -
103.212 -}
103.213 -
103.214 -/**
103.215 - * Checks if a URI is absolute.
103.216 - *
103.217 - * @param uri The GMythURI instance.
103.218 - *
103.219 - * @return <code>true</code>, if the URI is absolute.
103.220 - */
103.221 -static gboolean
103.222 -gmyth_uri_isabsolute(const GMythURI * uri)
103.223 -{
103.224 - gboolean ret = FALSE;
103.225 -
103.226 - g_return_val_if_fail(uri != NULL && uri->uri != NULL
103.227 - && uri->protocol != NULL, FALSE);
103.228 -
103.229 - if (gmyth_strstr(uri->uri->str, GMYTH_URI_PROTOCOL_DELIM) == 0
103.230 - || strlen(uri->protocol->str) > 0)
103.231 - ret = TRUE;
103.232 -
103.233 - return ret;
103.234 -}
103.235 -
103.236 -/**
103.237 - * Searches for the first reverse character occurrence, from a given
103.238 - * list of characters, inside a given string.
103.239 - *
103.240 - * @param str The given string to be searched for characters occurrence.
103.241 - * @param chars The characters list. If this string returns 4 on strlen, there are
103.242 - * four possible characters to be matched.
103.243 - * @param nchars The number of characters to be matched, which has at most
103.244 - * strlen(chars).
103.245 - *
103.246 - * @return The starting offset to the first character occurrence,
103.247 - * or <code>-1</code> if the no character of the list could be found.
103.248 - */
103.249 -static gint
103.250 -gmyth_strrchr(const gchar * str, const gchar * chars, const gint nchars)
103.251 -{
103.252 -
103.253 - gint strLen;
103.254 - gint i,
103.255 - j;
103.256 -
103.257 - if (str == NULL || chars == NULL)
103.258 - return -1;
103.259 -
103.260 - strLen = strlen(str);
103.261 - for (i = (strLen - 1); 0 <= i; i--) {
103.262 - for (j = 0; j < nchars; j++) {
103.263 - if (str[i] == chars[j])
103.264 - return i;
103.265 - }
103.266 - }
103.267 -
103.268 - return -1;
103.269 -
103.270 -}
103.271 -
103.272 -static gchar *
103.273 -gmyth_uri_print_field(const GString * field)
103.274 -{
103.275 - if (field != NULL && field->str != NULL && strlen(field->str) > 0)
103.276 - return field->str;
103.277 - else
103.278 - return "";
103.279 -}
103.280 -
103.281 -static gint
103.282 -gmyth_uri_get_default_port (GMythURI * uri)
103.283 -{
103.284 - const gchar *protocol = gmyth_uri_get_protocol(uri);
103.285 -
103.286 - if (strcmp(protocol, GMYTH_URI_PROTOCOL_HTTP) == 0)
103.287 - return GMYTH_URI_DEFAULT_HTTP_PORT;
103.288 - if (strcmp(protocol, GMYTH_URI_PROTOCOL_FTP) == 0)
103.289 - return GMYTH_URI_DEFAULT_FTP_PORT;
103.290 - if (strcmp(protocol, GMYTH_URI_PROTOCOL_MYTH) == 0)
103.291 - return GMYTH_URI_DEFAULT_MYTH_PORT;
103.292 -
103.293 - return GMYTH_URI_KNKOWN_PORT;
103.294 -}
103.295 -
103.296 -/**
103.297 - * Parses a URI string into a GMythURI instance.
103.298 - *
103.299 - * @param uri The GMythURI instance.
103.300 - * @param value The URI string to be parsed.
103.301 - *
103.302 - */
103.303 -static void
103.304 -gmyth_uri_parser_setup_and_new(GMythURI * uri, const gchar * value)
103.305 -{
103.306 -
103.307 - gint uriLen;
103.308 - gint currIdx;
103.309 - gint protoIdx;
103.310 - gint atIdx;
103.311 - gint colonIdx;
103.312 - gint shashIdx;
103.313 - gint eIdx;
103.314 - gchar *host;
103.315 - gint eblacketIdx;
103.316 - gint hostLen;
103.317 - gint sharpIdx;
103.318 -
103.319 - /*
103.320 - * gint questionIdx; gint queryLen;
103.321 - */
103.322 -
103.323 - uriLen = strlen(value);
103.324 - uri->uri = g_string_new(value);
103.325 -
103.326 - currIdx = 0;
103.327 -
103.328 - /*** Protocol ****/
103.329 - protoIdx = gmyth_strstr(value, GMYTH_URI_PROTOCOL_DELIM);
103.330 - if (0 < protoIdx) {
103.331 - uri->protocol = g_string_new_len(value, protoIdx);
103.332 - currIdx += protoIdx + strlen(GMYTH_URI_PROTOCOL_DELIM);
103.333 - }
103.334 -
103.335 - /*** User (Password) ****/
103.336 - atIdx = gmyth_strstr(value + currIdx, GMYTH_URI_USER_DELIM);
103.337 - if (0 < atIdx) {
103.338 - colonIdx = gmyth_strstr(value + currIdx, GMYTH_URI_COLON_DELIM);
103.339 -
103.340 - if (0 < colonIdx && colonIdx < atIdx) {
103.341 - uri->user = g_string_new_len(value + currIdx, colonIdx);
103.342 - uri->password =
103.343 - g_string_new_len(value + currIdx + colonIdx + 1,
103.344 - atIdx - (colonIdx + 1));
103.345 - } else
103.346 - uri->user = g_string_new_len(value + currIdx, atIdx - currIdx);
103.347 - currIdx += atIdx + 1;
103.348 - }
103.349 -
103.350 - /*** Host (Port) ****/
103.351 - shashIdx = gmyth_strstr(value + currIdx, GMYTH_URI_SLASH_DELIM);
103.352 - if (0 < shashIdx)
103.353 - uri->host = g_string_new_len(value + currIdx, shashIdx);
103.354 - else if (gmyth_uri_isabsolute(uri) == TRUE)
103.355 - uri->host =
103.356 - g_string_new_len(value + currIdx, strlen(value) - currIdx);
103.357 -
103.358 - host = gmyth_uri_get_host(uri);
103.359 - colonIdx = gmyth_strrchr(host, GMYTH_URI_COLON_DELIM, 1);
103.360 - eblacketIdx = gmyth_strrchr(host, GMYTH_URI_EBLACET_DELIM, 1);
103.361 - if ((0 < colonIdx) && (eblacketIdx < colonIdx)) {
103.362 - GString *portStr = NULL;
103.363 - GString *hostStr = g_string_new(host != NULL ? host : "");
103.364 -
103.365 - hostLen = hostStr->len;
103.366 - /**** host ****/
103.367 - uri->host = g_string_erase(uri->host, 0, hostLen);
103.368 - uri->host =
103.369 - g_string_insert_len(uri->host, 0, hostStr->str, colonIdx);
103.370 - if (0 < hostLen) {
103.371 - if (host[0] == '[' && host[hostLen - 1] == ']')
103.372 - uri->host =
103.373 - g_string_new_len(hostStr->str + 1, colonIdx - 2);
103.374 - }
103.375 -
103.376 - /**** port ****/
103.377 - portStr = g_string_new_len(hostStr->str + colonIdx + 1,
103.378 - hostLen - colonIdx - 1);
103.379 - uri->port = (gint) g_ascii_strtoull(portStr->str, NULL, 10);
103.380 - g_string_free(portStr, TRUE);
103.381 - g_string_free(hostStr, TRUE);
103.382 - } else {
103.383 - uri->port = gmyth_uri_get_default_port (uri);
103.384 - }
103.385 -
103.386 - if (shashIdx > 0)
103.387 - currIdx += shashIdx;
103.388 -
103.389 - /*
103.390 - * Handle relative URL
103.391 - */
103.392 - if (gmyth_uri_isabsolute(uri) == FALSE) {
103.393 -
103.394 - if (shashIdx != 0) {
103.395 - /*
103.396 - * Add slash delimiter at the beginning of the URL, if it
103.397 - * doesn't exist
103.398 - */
103.399 - uri->path = g_string_new(GMYTH_URI_SLASH_DELIM);
103.400 - }
103.401 - uri->path = g_string_append(uri->path, value);
103.402 -
103.403 - } else {
103.404 - /*
103.405 - * First set path simply to the rest of URI
103.406 - */
103.407 - uri->path = g_string_new_len(value + currIdx, uriLen - currIdx);
103.408 - }
103.409 -
103.410 - // gmyth_debug( "uri value: %s", value );
103.411 - uri->query =
103.412 - g_string_new(g_strstr_len
103.413 - (value, strlen(value), GMYTH_URI_QUESTION_DELIM));
103.414 -
103.415 - eIdx = gmyth_strstr(value + currIdx, GMYTH_URI_QUESTION_DELIM);
103.416 -
103.417 - if (0 < eIdx) {
103.418 - uri->query =
103.419 - g_string_new(g_strstr_len
103.420 - (value, strlen(value), GMYTH_URI_QUESTION_DELIM));
103.421 - gmyth_debug("query = %s", uri->query->str);
103.422 - }
103.423 -
103.424 - /**** Path (Query/Fragment) ****/
103.425 - sharpIdx = gmyth_strstr(value + currIdx, GMYTH_URI_E_DELIM);
103.426 - if (0 < sharpIdx) {
103.427 - uri->path =
103.428 - g_string_append_len(uri->path, value + currIdx, sharpIdx);
103.429 - uri->fragment =
103.430 - g_string_new_len(value + currIdx + sharpIdx + 1,
103.431 - uriLen - (currIdx + sharpIdx + 1));
103.432 - }
103.433 -
103.434 - gmyth_debug
103.435 - ("[%s] GMythURI: host = %s, port = %d, path = %s, query = %s, fragment = %s, "
103.436 - "user = %s, password = %s.\n", __FUNCTION__,
103.437 - gmyth_uri_print_field(uri->host), uri->port,
103.438 - gmyth_uri_print_field(uri->path),
103.439 - gmyth_uri_print_field(uri->query),
103.440 - gmyth_uri_print_field(uri->fragment),
103.441 - gmyth_uri_print_field(uri->user),
103.442 - gmyth_uri_print_field(uri->password));
103.443 -
103.444 -}
103.445 -
103.446 -/**
103.447 - * Compares 2 URI instances, and checks them for equality.
103.448 - *
103.449 - * @param uri The first GMythURI instance for comparison.
103.450 - * @param uri The second GMythURI instance for comparison.
103.451 - *
103.452 - * @return <code>true</code>, if these two URI instances are equals.
103.453 - */
103.454 -gboolean
103.455 -gmyth_uri_is_equals(GMythURI * uri1, GMythURI * uri2)
103.456 -{
103.457 - return (g_ascii_strcasecmp
103.458 - (gmyth_uri_get_host(uri1), gmyth_uri_get_host(uri2)) == 0
103.459 - && gmyth_uri_get_port(uri1) == gmyth_uri_get_port(uri2));
103.460 -}
103.461 -
103.462 -/**
103.463 - * Checks if the URI instance represents a LiveTV recording.
103.464 - *
103.465 - * @param uri The GMythURI instance.
103.466 - *
103.467 - * @return <code>true</code>, if the URI points to LiveTV content.
103.468 - */
103.469 -gboolean
103.470 -gmyth_uri_is_livetv(GMythURI * uri)
103.471 -{
103.472 - gboolean ret = TRUE;
103.473 -
103.474 - g_return_val_if_fail(uri != NULL, FALSE);
103.475 - g_return_val_if_fail(uri->uri != NULL, FALSE);
103.476 - g_return_val_if_fail(uri->uri->str != NULL, FALSE);
103.477 -
103.478 - if ((strstr(uri->uri->str, "channel=") == NULL) &&
103.479 - (strstr(uri->uri->str, "livetv") == NULL))
103.480 - ret = FALSE;
103.481 -
103.482 - if (ret)
103.483 - gmyth_debug("This URI is a LiveTV recording...");
103.484 - else
103.485 - gmyth_debug("This URI is a stored remote recording.");
103.486 -
103.487 - return ret;
103.488 -
103.489 -}
103.490 -
103.491 -/**
103.492 - * Gets the channel name fro a URI instance.
103.493 - *
103.494 - * @param uri The GMythURI instance.
103.495 - *
103.496 - * @return The channel name, got from the substring "?channel=[channel_name]"
103.497 - * of the URI string.
103.498 - */
103.499 -gchar *
103.500 -gmyth_uri_get_channel_name(GMythURI * uri)
103.501 -{
103.502 - gchar *channel = NULL;
103.503 -
103.504 - g_return_val_if_fail(uri != NULL && uri->uri != NULL
103.505 - && uri->uri->str != NULL, FALSE);
103.506 -
103.507 - gchar *channel_query = g_strstr_len(gmyth_uri_get_query(uri),
103.508 - strlen(gmyth_uri_get_query
103.509 - (uri)),
103.510 - "channel");
103.511 -
103.512 - if (channel_query != NULL) {
103.513 - gchar **chan_key_value =
103.514 - g_strsplit(gmyth_uri_get_query(uri), "=", 2);
103.515 -
103.516 - /*
103.517 - * gmyth_debug( "Channel tuple is [ %s, %s ]", chan_key_value[0],
103.518 - * chan_key_value[1] );
103.519 - */
103.520 -
103.521 - if (chan_key_value[1] != NULL && strlen(chan_key_value[1]) > 0) {
103.522 - channel = g_strdup(chan_key_value[1]);
103.523 - }
103.524 -
103.525 - if (chan_key_value != NULL)
103.526 - g_strfreev(chan_key_value);
103.527 - }
103.528 -
103.529 - gmyth_debug("Got channel decimal value from the URI: %s", channel);
103.530 -
103.531 - return channel;
103.532 -
103.533 -}
103.534 -
103.535 -/**
103.536 - * Gets the channel number from a URI instance.
103.537 - *
103.538 - * @param uri The GMythURI instance.
103.539 - *
103.540 - * @return The channel number, got from the substring "?channel=[channel_number]"
103.541 - * of the URI string, or <code>-1</code> it if couldn't be converted.
103.542 - */
103.543 -gint
103.544 -gmyth_uri_get_channel_num(GMythURI * uri)
103.545 -{
103.546 - gchar *channel_name = gmyth_uri_get_channel_name(uri);
103.547 -
103.548 - if (channel_name != NULL) {
103.549 - return g_ascii_strtoull(channel_name, NULL, 10);
103.550 - }
103.551 -
103.552 - return -1;
103.553 -
103.554 -}
103.555 -
103.556 -/**
103.557 - * Checks if the URI instance represents a reference to a local file.
103.558 - *
103.559 - * @param uri The GMythURI instance.
103.560 - *
103.561 - * @return <code>true</code>, if the URI points to a local file.
103.562 - */
103.563 -gboolean
103.564 -gmyth_uri_is_local_file(const GMythURI * uri)
103.565 -{
103.566 - gboolean ret = FALSE;
103.567 - gint len = -1;
103.568 -
103.569 - GString *hostname = gmyth_socket_get_local_hostname();
103.570 -
103.571 - g_return_val_if_fail(uri != NULL, FALSE);
103.572 -
103.573 - len = strlen(gmyth_uri_get_host(uri));
103.574 -
103.575 - // gmyth_debug("URI: host = %s, hostname = %s.", uri->host->str,
103.576 - // hostname != NULL ? hostname->str : "[no hostname]");
103.577 -
103.578 - ret = (NULL != hostname && (g_ascii_strncasecmp(uri->host->str, (hostname)->str, len) == 0) /* ||
103.579 - * (
103.580 - * g_ascii_strncasecmp(
103.581 - * gmyth_uri_get_host(uri),
103.582 - * gmyth_socket_get_primary_addr(),
103.583 - * len
103.584 - * )
103.585 - * ==
103.586 - * 0
103.587 - * )
103.588 - */
103.589 - );
103.590 -
103.591 - if (ret)
103.592 - gmyth_debug("This URI is a local file...");
103.593 - else
103.594 - gmyth_debug("This URI is NOT a local file...");
103.595 -
103.596 - return ret;
103.597 -
103.598 -}
103.599 -
103.600 -char *
103.601 -gmyth_uri_to_string(const GMythURI * uri)
103.602 -{
103.603 - g_return_val_if_fail(uri != NULL, NULL);
103.604 - g_return_val_if_fail(uri->uri != NULL, NULL);
103.605 -
103.606 - return g_strdup(uri->uri->str);
103.607 -}
104.1 --- a/gmyth/src/gmyth_uri.h Mon Feb 25 17:45:36 2008 +0000
104.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
104.3 @@ -1,101 +0,0 @@
104.4 -/**
104.5 - * GMyth Library
104.6 - *
104.7 - * @file gmyth/gmyth_uri.h
104.8 - *
104.9 - * @brief <p> GMythURI utils
104.10 - * - Extracts and parses a URI char string, in according with the RFC 2396
104.11 - * [http://www.ietf.org/rfc/rfc2396.txt]
104.12 - *
104.13 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
104.14 - * @author Rosfran Borges <rosfran.borges@indt.org.br>
104.15 - *
104.16 - *
104.17 - * This program is free software; you can redistribute it and/or modify
104.18 - * it under the terms of the GNU Lesser General Public License as published by
104.19 - * the Free Software Foundation; either version 2 of the License, or
104.20 - * (at your option) any later version.
104.21 - *
104.22 - * This program is distributed in the hope that it will be useful,
104.23 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
104.24 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
104.25 - * GNU General Public License for more details.
104.26 - *
104.27 - * You should have received a copy of the GNU Lesser General Public License
104.28 - * along with this program; if not, write to the Free Software
104.29 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
104.30 - */
104.31 -
104.32 -#ifndef _GMYTH_URI_H_
104.33 -#define _GMYTH_URI_H_
104.34 -
104.35 -#include <glib.h>
104.36 -#include <glib-object.h>
104.37 -
104.38 -#include <stdlib.h>
104.39 -#include <stdio.h>
104.40 -#include <string.h>
104.41 -
104.42 -G_BEGIN_DECLS
104.43 -#define GMYTH_URI_TYPE (gmyth_uri_get_type ())
104.44 -#define GMYTH_URI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_URI_TYPE, GMythURI))
104.45 -#define GMYTH_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_URI_TYPE, GMythURIClass))
104.46 -#define IS_GMYTH_URI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMYTH_URI_TYPE))
104.47 -#define IS_GMYTH_URI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_URI_TYPE))
104.48 -#define GMYTH_URI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_URI_TYPE, GMythURIClass))
104.49 -typedef struct _GMythURI GMythURI;
104.50 -typedef struct _GMythURIClass GMythURIClass;
104.51 -
104.52 -
104.53 - /****************************************
104.54 - * Data Type
104.55 - ****************************************/
104.56 -
104.57 -struct _GMythURIClass {
104.58 - GObjectClass parent_class;
104.59 -
104.60 - /*
104.61 - * callbacks
104.62 - */
104.63 - /*
104.64 - * no one for now
104.65 - */
104.66 -};
104.67 -
104.68 -struct _GMythURI {
104.69 -
104.70 - GObject parent;
104.71 -
104.72 - GString *uri;
104.73 - GString *host;
104.74 - gint port;
104.75 - GString *protocol;
104.76 - GString *path;
104.77 - GString *fragment;
104.78 - GString *user;
104.79 - GString *password;
104.80 - GString *query;
104.81 -
104.82 -};
104.83 -
104.84 -GType gmyth_uri_get_type(void);
104.85 -GMythURI *gmyth_uri_new(void);
104.86 -GMythURI *gmyth_uri_new_with_value(const gchar * value);
104.87 -gboolean gmyth_uri_is_equals(GMythURI * uri1, GMythURI * uri2);
104.88 -gboolean gmyth_uri_is_livetv(GMythURI * uri);
104.89 -gint gmyth_uri_get_channel_num(GMythURI * uri);
104.90 -gchar *gmyth_uri_get_channel_name(GMythURI * uri);
104.91 -char *gmyth_uri_to_string(const GMythURI * uri);
104.92 -gboolean gmyth_uri_is_local_file(const GMythURI * uri);
104.93 -
104.94 -#define gmyth_uri_get_host(urip) ( urip->host != NULL ? urip->host->str : "" )
104.95 -#define gmyth_uri_get_port(urip) ( urip->port )
104.96 -#define gmyth_uri_get_protocol(urip) ( urip->protocol != NULL ? urip->protocol->str : "" )
104.97 -#define gmyth_uri_get_path(urip) ( urip->path != NULL ? urip->path->str : "" )
104.98 -#define gmyth_uri_get_user(urip) ( urip->user != NULL ? urip->user->str : "" )
104.99 -#define gmyth_uri_get_password(urip) ( urip->password != NULL ? urip->password->str : "" )
104.100 -#define gmyth_uri_get_fragment(urip) ( urip->fragment != NULL ? urip->fragment->str : "" )
104.101 -#define gmyth_uri_get_query(urip) ( urip->query != NULL ? urip->query->str : "" )
104.102 -
104.103 -G_END_DECLS
104.104 -#endif /* _GMYTH_URI_H_ */
105.1 --- a/gmyth/src/gmyth_util.c Mon Feb 25 17:45:36 2008 +0000
105.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
105.3 @@ -1,957 +0,0 @@
105.4 -/**
105.5 - * GMyth Library
105.6 - *
105.7 - * @file gmyth/gmyth_util.c
105.8 - *
105.9 - * @brief <p> This component provides utility functions
105.10 - * (dealing with dates, time, string formatting, etc.).
105.11 - *
105.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
105.13 - * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
105.14 - * @author Rosfran Borges <rosfran.borges@indt.org.br>
105.15 - *
105.16 - *
105.17 - * This program is free software; you can redistribute it and/or modify
105.18 - * it under the terms of the GNU Lesser General Public License as published by
105.19 - * the Free Software Foundation; either version 2 of the License, or
105.20 - * (at your option) any later version.
105.21 - *
105.22 - * This program is distributed in the hope that it will be useful,
105.23 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
105.24 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
105.25 - * GNU General Public License for more details.
105.26 - *
105.27 - * You should have received a copy of the GNU Lesser General Public License
105.28 - * along with this program; if not, write to the Free Software
105.29 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
105.30 - */
105.31 -
105.32 -#ifdef HAVE_CONFIG_H
105.33 -#include "config.h"
105.34 -#endif
105.35 -
105.36 -#define _XOPEN_SOURCE
105.37 -#define _XOPEN_SOURCE_EXTENDED
105.38 -#define __USE_MISC
105.39 -
105.40 -#include <glib.h>
105.41 -#include <glib/gprintf.h>
105.42 -#include <time.h>
105.43 -#include <sys/time.h>
105.44 -#include <sys/timex.h>
105.45 -
105.46 -#include "gmyth_socket.h"
105.47 -#include "gmyth_recorder.h"
105.48 -#include "gmyth_common.h"
105.49 -#include "gmyth_debug.h"
105.50 -
105.51 -#include "gmyth_util.h"
105.52 -
105.53 -#if !GLIB_CHECK_VERSION (2, 10, 0)
105.54 -gchar *g_time_val_to_iso8601(GTimeVal * time_);
105.55 -gboolean g_time_val_from_iso8601(const gchar * iso_date,
105.56 - GTimeVal * time_);
105.57 -void g_date_set_time_val(GDate * date, GTimeVal * timeval);
105.58 -
105.59 -#endif
105.60 -
105.61 -/** Converts a time_t struct in a GString at ISO standard format
105.62 - * (e.g. 2006-07-20T09:56:41).
105.63 - *
105.64 - * The returned GString memory should be deallocated from
105.65 - * the calling function.
105.66 - *
105.67 - * @param time_value the time value to be converted
105.68 - * @return GString* the converted isoformat string
105.69 - */
105.70 -GString *
105.71 -gmyth_util_time_to_isoformat(time_t time_value)
105.72 -{
105.73 - struct tm tm_time;
105.74 - GString *result;
105.75 -
105.76 - if (localtime_r(&time_value, &tm_time) == NULL) {
105.77 - gmyth_debug("gmyth_util_time_to_isoformat convertion error!\n");
105.78 - return NULL;
105.79 - }
105.80 -
105.81 - result = g_string_sized_new(20);
105.82 - g_string_printf(result, "%04d-%02d-%02dT%02d:%02d:%02d",
105.83 - tm_time.tm_year + 1900, tm_time.tm_mon + 1,
105.84 - tm_time.tm_mday, tm_time.tm_hour, tm_time.tm_min,
105.85 - tm_time.tm_sec);
105.86 -
105.87 - gmyth_debug("Result (ISO 8601) = %s", result->str);
105.88 -
105.89 - return result;
105.90 -}
105.91 -
105.92 -/** Converts a time_t struct in a GString at ISO standard format
105.93 - * (e.g. 2006-07-20T09:56:41).
105.94 - *
105.95 - * The returned GString memory should be deallocated from
105.96 - * the calling function.
105.97 - *
105.98 - * @param time_value the GTimeValue to be converted
105.99 - * @return GString* the converted isoformat string
105.100 - */
105.101 -gchar *
105.102 -gmyth_util_time_to_isoformat_from_time_val_fmt(const gchar * fmt_string,
105.103 - const GTimeVal * time_val)
105.104 -{
105.105 - gchar *result = NULL;
105.106 - struct tm *tm_time = NULL;
105.107 - time_t time;
105.108 -
105.109 - gint buffer_len = 0;
105.110 -
105.111 - g_return_val_if_fail(fmt_string != NULL, NULL);
105.112 -
105.113 - g_return_val_if_fail(time_val != NULL, NULL);
105.114 -
105.115 - time = time_val->tv_sec; // + (gint)( time_val->tv_usec /
105.116 - // G_USEC_PER_SEC );
105.117 -
105.118 - tm_time = g_malloc0(sizeof(struct tm));
105.119 -
105.120 - if (NULL == localtime_r(&time, tm_time)) {
105.121 - gmyth_debug("gmyth_util_time_to_isoformat convertion error!\n");
105.122 - } else {
105.123 - /*
105.124 - * we first check the return of strftime to allocate a buffer of
105.125 - * the correct size
105.126 - */
105.127 - buffer_len = strftime(NULL, SSIZE_MAX, fmt_string, tm_time);
105.128 - if (buffer_len > 0) {
105.129 - result = g_malloc0(buffer_len + 1);
105.130 - if (result == NULL) {
105.131 - gmyth_debug
105.132 - ("gmyth_util_time_to_isoformat convertion error!\n");
105.133 - return NULL;
105.134 - }
105.135 - strftime(result, buffer_len + 1, fmt_string, tm_time);
105.136 - gmyth_debug("Dateline (ISO result): %s", result);
105.137 - }
105.138 - } /* if */
105.139 -
105.140 - gmyth_debug("Result (strftime) = %s", result);
105.141 -
105.142 - // strptime( result, "%Y-%m-%dT%H:%M:%SZ", tm_time );
105.143 -
105.144 - // strftime( result, strlen(result), fmt_string, tm_time );
105.145 -
105.146 - g_free(tm_time);
105.147 -
105.148 - gmyth_debug("Result (ISO 8601) = %s", result);
105.149 -
105.150 - return result;
105.151 -}
105.152 -
105.153 -/** Converts a time_t struct in a GString at ISO standard format
105.154 - * (e.g. 2006-07-20 09:56:41).
105.155 - *
105.156 - * The returned GString memory should be deallocated from
105.157 - * the calling function.
105.158 - *
105.159 - * @param time_value the GTimeValue to be converted
105.160 - * @return GString* the converted isoformat string
105.161 - */
105.162 -gchar *
105.163 -gmyth_util_time_to_isoformat_from_time_val(const GTimeVal * time)
105.164 -{
105.165 - gchar *result =
105.166 - gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%d %H:%M:%S",
105.167 - time);
105.168 -
105.169 - // result[10] = ' ';
105.170 - // result[ strlen(result) - 1] = '\0';
105.171 -
105.172 - return result;
105.173 -}
105.174 -
105.175 -/** Converts a time_t struct in a GString at ISO standard format 2
105.176 - * (e.g. 2006-07-20T09:56:41).
105.177 - *
105.178 - * The returned GString memory should be deallocated from
105.179 - * the calling function.
105.180 - *
105.181 - * @param time_value the GTimeValue to be converted
105.182 - * @return GString* the converted isoformat string
105.183 - */
105.184 -gchar *
105.185 -gmyth_util_time_to_mythformat_from_time_val(const GTimeVal * time)
105.186 -{
105.187 - gchar *result =
105.188 - gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%dT%H:%M:%S",
105.189 - time);
105.190 -
105.191 - return result;
105.192 -}
105.193 -
105.194 -/** Converts a time_t struct in a GString at ISO standard format
105.195 - * (e.g. 2006-07-20T09:56:41).
105.196 - *
105.197 - * The returned GString memory should be deallocated from
105.198 - * the calling function.
105.199 - *
105.200 - * @param time_value the GTimeValue to be converted
105.201 - * @return GString* the converted isoformat string
105.202 - */
105.203 -gchar *
105.204 -gmyth_util_time_to_string_only_date(const GTimeVal * time)
105.205 -{
105.206 - gchar *result =
105.207 - gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%d", time);
105.208 - // result[10] = ' ';
105.209 - // result[ strlen(result) - 1] = '\0';
105.210 - return result;
105.211 -}
105.212 -
105.213 -/** Converts a time_t struct in a GString at ISO standard format
105.214 - * (e.g. 2006-07-20T09:56:41).
105.215 - *
105.216 - * The returned GString memory should be deallocated from
105.217 - * the calling function.
105.218 - *
105.219 - * @param time_value the GTimeValue to be converted
105.220 - * @return GString* the converted isoformat string
105.221 - */
105.222 -gchar *
105.223 -gmyth_util_time_to_string_only_time(const GTimeVal * time)
105.224 -{
105.225 - gchar *result =
105.226 - gmyth_util_time_to_isoformat_from_time_val_fmt("%H:%M:%S", time);
105.227 - // result[10] = ' ';
105.228 - // result[ strlen(result) - 1] = '\0';
105.229 - return result;
105.230 -}
105.231 -
105.232 -/** Converts a time_t struct in a GString to the following
105.233 - * format (e.g. 2006-07-20 09:56:41).
105.234 - *
105.235 - * The returned GString memory should be deallocated from
105.236 - * the calling function.
105.237 - *
105.238 - * @param time_value the time value to be converted
105.239 - * @return GString* the converted string
105.240 - */
105.241 -GString *
105.242 -gmyth_util_time_to_string(time_t time_value)
105.243 -{
105.244 - GString *result = gmyth_util_time_to_isoformat(time_value);
105.245 -
105.246 - result->str[10] = ' ';
105.247 - result->str[strlen(result->str) - 1] = '\0';
105.248 -
105.249 - return result;
105.250 -}
105.251 -
105.252 -/** Converts a time_t struct in a GString to the following
105.253 - * format (e.g. 2006-07-20 09:56:41).
105.254 - *
105.255 - * The returned GString memory should be deallocated from
105.256 - * the calling function.
105.257 - *
105.258 - * @param time_value the time value to be converted
105.259 - * @return GString* the converted string
105.260 - */
105.261 -gchar *
105.262 -gmyth_util_time_to_string_from_time_val(const GTimeVal * time_val)
105.263 -{
105.264 - gchar *result =
105.265 - gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%d %H:%M:%S",
105.266 - time_val);
105.267 -
105.268 - // result[10] = ' ';
105.269 -
105.270 - return result;
105.271 -}
105.272 -
105.273 -/** Converts a GString in the following format
105.274 - * (e.g. 2006-07-20 09:56:41) to a time_t struct.
105.275 - *
105.276 - * @param time_str the string to be converted
105.277 - * @return time_t the time converted value
105.278 - */
105.279 -time_t
105.280 -gmyth_util_string_to_time(GString * time_str)
105.281 -{
105.282 - gint year,
105.283 - month,
105.284 - day,
105.285 - hour,
105.286 - min,
105.287 - sec;
105.288 -
105.289 - gmyth_debug("[%s] time_str = %s. [%s]", __FUNCTION__,
105.290 - time_str !=
105.291 - NULL ? time_str->str : "[time string is NULL!]",
105.292 - time_str->str);
105.293 -
105.294 - if (sscanf(time_str->str, "%04d-%02d-%02d %02d:%02d:%02d",
105.295 - &year, &month, &day, &hour, &min, &sec) < 3) {
105.296 - gmyth_debug("GMythUtil: isoformat_to_time converter error!\n");
105.297 - return 0;
105.298 - }
105.299 -
105.300 - struct tm *tm_time = g_malloc0(sizeof(struct tm));
105.301 -
105.302 - tm_time->tm_year = year - 1900;
105.303 - tm_time->tm_mon = month - 1;
105.304 - tm_time->tm_mday = day;
105.305 - tm_time->tm_hour = hour;
105.306 - tm_time->tm_min = min;
105.307 - tm_time->tm_sec = sec;
105.308 -
105.309 - return mktime(tm_time);
105.310 -}
105.311 -
105.312 -/** Converts a GString in the following format
105.313 - * (e.g. 2006-07-20 09:56:41) to a time_t struct.
105.314 - *
105.315 - * @param time_str the string to be converted
105.316 - * @return time_t the time converted value
105.317 - */
105.318 -struct tm *
105.319 -gmyth_util_time_val_to_date(const GTimeVal * time)
105.320 -{
105.321 - struct tm *date = g_malloc0(sizeof(struct tm));
105.322 - time_t time_micros = time->tv_sec; // + (gint)( time->tv_usec
105.323 - //
105.324 - //
105.325 - // / G_USEC_PER_SEC );
105.326 -
105.327 - if (NULL == date) {
105.328 - gmyth_debug
105.329 - ("GMythUtil: GDate *gmyth_util_time_val_to_date (GTimeVal* time) - converter error!\n");
105.330 - return NULL;
105.331 - }
105.332 -
105.333 - if (NULL == localtime_r(&time_micros, date)) {
105.334 - gmyth_debug("gmyth_util_time_to_isoformat convertion error!\n");
105.335 - return NULL;
105.336 - }
105.337 -
105.338 - gmyth_debug("Converted from GTimeVal == %s to GDate", asctime(date));
105.339 -
105.340 - return date;
105.341 -}
105.342 -
105.343 -/** Converts a GString in the following format
105.344 - * (e.g. 2006-07-20 09:56:41) to a time_t struct.
105.345 - *
105.346 - * @param time_str the string to be converted
105.347 - * @return time_t the time converted value
105.348 - */
105.349 -GTimeVal *
105.350 -gmyth_util_string_to_time_val_fmt(const gchar * fmt_string,
105.351 - const gchar * time_str)
105.352 -{
105.353 - GTimeVal *time = g_new0(GTimeVal, 1);
105.354 - struct tm *tm_time = NULL;
105.355 - time_t time_micros;
105.356 - gchar *result;
105.357 -
105.358 - gmyth_debug("[%s] time_str = %s. [%s]", time_str, time_str != NULL ?
105.359 - time_str : "[time string is NULL!]", time_str);
105.360 -
105.361 - if (NULL == time_str) {
105.362 - gmyth_debug("GMythUtil: isoformat_to_time converter error!\n");
105.363 - return NULL;
105.364 - }
105.365 -
105.366 - tm_time = g_malloc0(sizeof(struct tm));
105.367 -
105.368 - /*
105.369 - * we first check the return of strftime to allocate a buffer of the
105.370 - * correct size
105.371 - */
105.372 - result = strptime(time_str, "%Y-%m-%dT%H:%M:%S", tm_time);
105.373 - if (NULL == result) {
105.374 - /*
105.375 - * we first check the return of strftime to allocate a buffer of
105.376 - * the correct size
105.377 - */
105.378 - result = strptime(time_str, "%Y-%m-%dT%H:%M:%SZ", tm_time);
105.379 - if (NULL == result) {
105.380 - /*
105.381 - * we first check the return of strftime to allocate a buffer
105.382 - * of the correct size
105.383 - */
105.384 - result = strptime(time_str, "%Y-%m-%d %H:%M:%S", tm_time);
105.385 - if (NULL == result) {
105.386 - result = strptime(time_str, "%Y-%m-%dT%H:%M", tm_time);
105.387 - if (NULL == result) {
105.388 - gmyth_debug("Dateline (ISO result): %s", result);
105.389 - g_free(tm_time);
105.390 - return NULL;
105.391 - // goto done;
105.392 - }
105.393 - }
105.394 - }
105.395 - }
105.396 -
105.397 - time_micros = mktime(tm_time);
105.398 -
105.399 - time->tv_sec = time_micros; // + (gint)( time_val->tv_usec /
105.400 - // G_USEC_PER_SEC );
105.401 -
105.402 - gmyth_debug("After mktime call... = %s", asctime(tm_time));
105.403 -
105.404 - g_free(tm_time);
105.405 -
105.406 - return time;
105.407 -}
105.408 -
105.409 -/** Converts a GString in the following format
105.410 - * (e.g. 2006-07-20 09:56:41) to a time_t struct.
105.411 - *
105.412 - * @param time_str the string to be converted
105.413 - * @return time_t the time converted value
105.414 - */
105.415 -GTimeVal *
105.416 -gmyth_util_string_to_time_val(const gchar * time_str)
105.417 -{
105.418 - GTimeVal *time =
105.419 - gmyth_util_string_to_time_val_fmt("%Y-%m-%d %H:%M:%S", time_str);
105.420 -
105.421 - return time;
105.422 -}
105.423 -
105.424 -/**
105.425 - * Checks if the given remote file exists.
105.426 - *
105.427 - * @param backend_info The GMythBackendInfo instance.
105.428 - * @param filename The file name of the remote file.
105.429 - *
105.430 - * @return <code>true</code>, if the remote file exists.
105.431 - */
105.432 -gboolean
105.433 -gmyth_util_file_exists(GMythBackendInfo * backend_info,
105.434 - const gchar * filename)
105.435 -{
105.436 - GMythSocket *socket;
105.437 - gboolean res = FALSE;
105.438 -
105.439 - gmyth_debug("Check if file %s exists", filename);
105.440 -
105.441 - g_return_val_if_fail(backend_info != NULL, FALSE);
105.442 - g_return_val_if_fail(filename != NULL, FALSE);
105.443 -
105.444 - socket = gmyth_backend_info_get_connected_socket (backend_info);
105.445 - if (socket != NULL) {
105.446 - res = gmyth_util_file_exists_from_socket (socket, filename);
105.447 - g_object_unref(socket);
105.448 - }
105.449 - return res;
105.450 -}
105.451 -
105.452 -gboolean
105.453 -gmyth_util_file_exists_from_socket (GMythSocket *sock,
105.454 - const gchar *filename)
105.455 -{
105.456 - gboolean res = FALSE;
105.457 - gint length = 0;
105.458 - GMythStringList *slist;
105.459 - GMythProgramInfo *program = NULL;
105.460 -
105.461 - program = gmyth_program_info_new();
105.462 - program->pathname = g_string_new(filename);
105.463 -
105.464 - slist = gmyth_string_list_new();
105.465 - gmyth_string_list_append_char_array(slist, "QUERY_CHECKFILE");
105.466 - gmyth_program_info_to_string_list(program, slist);
105.467 -
105.468 - length = gmyth_socket_sendreceive_stringlist (sock, slist);
105.469 - if (length > 0)
105.470 - res = (gmyth_string_list_get_int(slist, 0) == 1);
105.471 -
105.472 - g_object_unref(program);
105.473 - g_object_unref(slist);
105.474 -
105.475 - return res;
105.476 -}
105.477 -
105.478 -gboolean
105.479 -gmyth_util_get_backend_details (GMythSocket *sock, GMythBackendDetails **details)
105.480 -{
105.481 - gboolean res = FALSE;
105.482 - gint length = 0;
105.483 - GMythStringList *slist;
105.484 -
105.485 - slist = gmyth_string_list_new();
105.486 - gmyth_string_list_append_char_array(slist, "QUERY_FREE_SPACE");
105.487 -
105.488 - length = gmyth_socket_sendreceive_stringlist (sock, slist);
105.489 - if (length >= 8) {
105.490 - *details = g_new0 (GMythBackendDetails, 1);
105.491 - (*details)->total_space = gmyth_string_list_get_uint64 (slist, 4) * 1024;
105.492 - (*details)->used_space = gmyth_string_list_get_uint64 (slist, 6) * 1024;
105.493 - res = TRUE;
105.494 - }
105.495 -
105.496 - g_object_unref(slist);
105.497 -
105.498 - return res;
105.499 -}
105.500 -
105.501 -void
105.502 -gmyth_util_backend_details_free (GMythBackendDetails *details)
105.503 -{
105.504 - g_free (details);
105.505 -}
105.506 -
105.507 -
105.508 -/**
105.509 - * Checks if the given remote file exists, and gets its remote directory.
105.510 - *
105.511 - * @param backend_info The GMythBackendInfo instance.
105.512 - * @param filename The file name of the remote file.
105.513 - * @param current_dir String pointer to the directory where the remote file is stored.
105.514 - *
105.515 - * @return <code>true</code>, if the remote file exists.
105.516 - */
105.517 -gboolean
105.518 -gmyth_util_file_exists_and_get_remote_dir(GMythBackendInfo * backend_info,
105.519 - const gchar * filename,
105.520 - gchar ** current_dir)
105.521 -{
105.522 - GMythSocket *socket;
105.523 - gboolean res;
105.524 -
105.525 - *current_dir = NULL;
105.526 -
105.527 - socket = gmyth_socket_new();
105.528 - res = gmyth_socket_connect_to_backend(socket, backend_info->hostname,
105.529 - backend_info->port, TRUE);
105.530 -
105.531 - if (res == TRUE) {
105.532 - GMythStringList *slist;
105.533 - GMythProgramInfo *program = NULL;
105.534 -
105.535 - program = gmyth_program_info_new();
105.536 - program->pathname = g_string_new(filename);
105.537 -
105.538 - slist = gmyth_string_list_new();
105.539 - gmyth_string_list_append_char_array(slist, "QUERY_CHECKFILE");
105.540 -
105.541 - gmyth_program_info_to_string_list(program, slist);
105.542 -
105.543 - gmyth_socket_sendreceive_stringlist(socket, slist);
105.544 -
105.545 - res = (gmyth_string_list_get_int(slist, 0) == 1);
105.546 -
105.547 - if ((gmyth_string_list_length(slist) > 1) &&
105.548 - gmyth_string_list_get_char_array(slist, 1) != NULL)
105.549 - *current_dir =
105.550 - g_strdup(gmyth_string_list_get_char_array(slist, 1));
105.551 -
105.552 - if (*current_dir != NULL)
105.553 - gmyth_debug("Current directory = %s.", (*current_dir != NULL)
105.554 - ? *current_dir : "[directory not found]");
105.555 -
105.556 - g_object_unref(program);
105.557 -
105.558 - g_object_unref(slist);
105.559 -
105.560 - gmyth_socket_close_connection(socket);
105.561 - }
105.562 - g_object_unref(socket);
105.563 - return res;
105.564 -}
105.565 -
105.566 -/**
105.567 - * Creates a file name to a possible existing remote file,
105.568 - * based on some fields of the LiveTV/recorded program info.
105.569 - *
105.570 - * @param chan_id The channel ID number.
105.571 - * @param start_time The start time of the recording.
105.572 - *
105.573 - * @return The string representing the file name.
105.574 - */
105.575 -gchar *
105.576 -gmyth_util_create_filename(const gint chan_id, const GTimeVal * start_time)
105.577 -{
105.578 - gchar *basename = NULL;
105.579 -
105.580 - g_return_val_if_fail(start_time != NULL, NULL);
105.581 -
105.582 - gchar *isodate =
105.583 - gmyth_util_time_to_isoformat_from_time_val_fmt("%Y%m%d%H%M%S",
105.584 - start_time);
105.585 -
105.586 - basename = g_strdup_printf("%d_%s", chan_id, isodate);
105.587 -
105.588 - gmyth_debug("Basename (from chan_id and start_time): %s", basename);
105.589 -
105.590 - if (isodate)
105.591 - g_free(isodate);
105.592 -
105.593 - return basename;
105.594 -}
105.595 -
105.596 -/**
105.597 - * Gets the channel list.
105.598 - *
105.599 - * @param backend_info The GMythBackendInfo instance.
105.600 - *
105.601 - * @return a pointer to a GList with all the channels.
105.602 - */
105.603 -GList *
105.604 -gmyth_util_get_channel_list(GMythBackendInfo * backend_info)
105.605 -{
105.606 - GMythRecorder *recorder;
105.607 - GList *channel_list = NULL;
105.608 - gboolean res = FALSE;
105.609 -
105.610 - gmyth_debug("Gets channel list.");
105.611 -
105.612 - g_return_val_if_fail(backend_info != NULL, FALSE);
105.613 -
105.614 - recorder =
105.615 - gmyth_recorder_new(1,
105.616 - g_string_new(gmyth_backend_info_get_hostname
105.617 - (backend_info)),
105.618 - gmyth_backend_info_get_port(backend_info));
105.619 - res = gmyth_recorder_setup(recorder);
105.620 -
105.621 - if (res == TRUE) {
105.622 - // GList* channel_list = gmyth_recorder_get_channel_list( recorder
105.623 - //
105.624 - //
105.625 - // );
105.626 - gmyth_debug("Yeah, got channel list!!!");
105.627 - GList *ch = NULL;
105.628 - GMythChannelInfo *channel_info = NULL;
105.629 -
105.630 - for (ch = gmyth_recorder_get_channel_list(recorder); ch != NULL;) {
105.631 - channel_info = g_malloc0(sizeof(GMythChannelInfo));
105.632 - channel_info->channel_ID = 0;
105.633 - channel_info->channel_num =
105.634 - g_string_new(g_strdup((gchar *) ch->data));
105.635 - channel_info->channel_name = g_string_new("");
105.636 - gmyth_debug("Printing channel info... (%s)",
105.637 - channel_info->channel_num->str);
105.638 - channel_list =
105.639 - g_list_append(channel_list,
105.640 - g_memdup(channel_info,
105.641 - sizeof(GMythChannelInfo)));
105.642 -
105.643 - ch = g_list_next(ch);
105.644 -
105.645 - if (channel_info != NULL)
105.646 - g_free(channel_info);
105.647 - }
105.648 -
105.649 - } /* if */
105.650 - else {
105.651 - gmyth_debug("No, couldn't get the channel list!!!");
105.652 - }
105.653 -
105.654 - gmyth_debug("Got %d channels!!!", g_list_length(channel_list));
105.655 -
105.656 -
105.657 - g_object_unref(recorder);
105.658 -
105.659 - return channel_list;
105.660 -}
105.661 -
105.662 -/**
105.663 - * Gets all the recordings from remote encoder.
105.664 - *
105.665 - * @param backend_info The GMythBackendInfo instance.
105.666 - *
105.667 - * @return The program info's listage.
105.668 - */
105.669 -GSList *
105.670 -gmyth_util_get_all_recordings(GMythBackendInfo * backend_info)
105.671 -{
105.672 - GSList *program_list = NULL;
105.673 - GMythSocket *socket;
105.674 - gboolean res;
105.675 -
105.676 - socket = gmyth_socket_new();
105.677 - res = gmyth_socket_connect_to_backend(socket, backend_info->hostname,
105.678 - backend_info->port, TRUE);
105.679 -
105.680 - if (res == TRUE) {
105.681 - GMythStringList *slist = gmyth_string_list_new();
105.682 - guint pos = 0;
105.683 -
105.684 - gmyth_string_list_append_char_array(slist,
105.685 - "QUERY_RECORDINGS Play");
105.686 -
105.687 - gmyth_socket_sendreceive_stringlist(socket, slist);
105.688 -
105.689 - if (slist != NULL && (gmyth_string_list_length(slist) > 0)) {
105.690 - GMythProgramInfo *program = NULL;
105.691 -
105.692 - gmyth_debug("OK! Got the program list [size=%d].",
105.693 - gmyth_string_list_length(slist));
105.694 -
105.695 - do {
105.696 - program =
105.697 - gmyth_program_info_from_string_list_from_pos(slist,
105.698 - pos);
105.699 -
105.700 - if (program != NULL) {
105.701 - pos += 41;
105.702 -
105.703 - program_list = g_slist_append(program_list, program);
105.704 - } else
105.705 - break;
105.706 -
105.707 - }
105.708 - while (gmyth_string_list_length(slist) > pos);
105.709 -
105.710 - }
105.711 - /*
105.712 - * if
105.713 - */
105.714 - g_object_unref(slist);
105.715 -
105.716 - gmyth_socket_close_connection(socket);
105.717 - }
105.718 - g_object_unref(socket);
105.719 -
105.720 - return program_list;
105.721 -}
105.722 -
105.723 -/**
105.724 - * Checks if the given remote file exists, and gets its remote directory.
105.725 - *
105.726 - * @param backend_info The GMythBackendInfo instance.
105.727 - * @param channel The channel name of the program info.
105.728 - *
105.729 - * @return The requested program info.
105.730 - */
105.731 -GMythProgramInfo *
105.732 -gmyth_util_get_recording_from_channel(GMythBackendInfo * backend_info,
105.733 - const gchar * channel)
105.734 -{
105.735 - GSList *program_list = NULL;
105.736 - GMythProgramInfo *program = NULL;
105.737 -
105.738 - program_list = gmyth_util_get_all_recordings(backend_info);
105.739 -
105.740 - if (program_list != NULL && g_slist_length(program_list) > 0) {
105.741 - GMythProgramInfo *program = NULL;
105.742 - guint pos = 0;
105.743 -
105.744 - gmyth_debug("OK! Got the program list [size=%d].",
105.745 - g_slist_length(program_list));
105.746 -
105.747 - while (pos < g_slist_length(program_list)) {
105.748 - program =
105.749 - (GMythProgramInfo *) g_slist_nth_data(program_list, pos);
105.750 -
105.751 - if (program != NULL && program->channame != NULL &&
105.752 - g_ascii_strncasecmp(program->channame->str, channel,
105.753 - strlen(channel)) == 0) {
105.754 - break;
105.755 - }
105.756 -
105.757 - ++pos;
105.758 -
105.759 - } /* while */
105.760 -
105.761 - }
105.762 - /*
105.763 - * if
105.764 - */
105.765 - return program;
105.766 -}
105.767 -
105.768 -#if !GLIB_CHECK_VERSION (2, 10, 0)
105.769 -
105.770 -/*
105.771 - * Hacked from glib 2.10 <gtime.c>
105.772 - */
105.773 -
105.774 -static time_t
105.775 -mktime_utc(struct tm *tm)
105.776 -{
105.777 - time_t retval;
105.778 -
105.779 -#ifndef HAVE_TIMEGM
105.780 - static const gint days_before[] = {
105.781 - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
105.782 - };
105.783 -#endif
105.784 -
105.785 -#ifndef HAVE_TIMEGM
105.786 - if (tm->tm_mon < 0 || tm->tm_mon > 11)
105.787 - return (time_t) - 1;
105.788 -
105.789 - retval = (tm->tm_year - 70) * 365;
105.790 - retval += (tm->tm_year - 68) / 4;
105.791 - retval += days_before[tm->tm_mon] + tm->tm_mday - 1;
105.792 -
105.793 - if (tm->tm_year % 4 == 0 && tm->tm_mon < 2)
105.794 - retval -= 1;
105.795 -
105.796 - retval =
105.797 - ((((retval * 24) + tm->tm_hour) * 60) + tm->tm_min) * 60 +
105.798 - tm->tm_sec;
105.799 -#else
105.800 - retval = timegm(tm);
105.801 -#endif /* !HAVE_TIMEGM */
105.802 -
105.803 - return retval;
105.804 -}
105.805 -
105.806 -gboolean
105.807 -g_time_val_from_iso8601(const gchar * iso_date, GTimeVal * time_)
105.808 -{
105.809 - struct tm tm;
105.810 - long val;
105.811 -
105.812 - g_return_val_if_fail(iso_date != NULL, FALSE);
105.813 - g_return_val_if_fail(time_ != NULL, FALSE);
105.814 -
105.815 - val = strtoul(iso_date, (char **) &iso_date, 10);
105.816 - if (*iso_date == '-') {
105.817 - /*
105.818 - * YYYY-MM-DD
105.819 - */
105.820 - tm.tm_year = val - 1900;
105.821 - iso_date++;
105.822 - tm.tm_mon = strtoul(iso_date, (char **) &iso_date, 10) - 1;
105.823 -
105.824 - if (*iso_date++ != '-')
105.825 - return FALSE;
105.826 -
105.827 - tm.tm_mday = strtoul(iso_date, (char **) &iso_date, 10);
105.828 - } else {
105.829 - /*
105.830 - * YYYYMMDD
105.831 - */
105.832 - tm.tm_mday = val % 100;
105.833 - tm.tm_mon = (val % 10000) / 100 - 1;
105.834 - tm.tm_year = val / 10000 - 1900;
105.835 - }
105.836 -
105.837 - if (*iso_date++ != 'T')
105.838 - return FALSE;
105.839 -
105.840 - val = strtoul(iso_date, (char **) &iso_date, 10);
105.841 - if (*iso_date == ':') {
105.842 - /*
105.843 - * hh:mm:ss
105.844 - */
105.845 - tm.tm_hour = val;
105.846 - iso_date++;
105.847 - tm.tm_min = strtoul(iso_date, (char **) &iso_date, 10);
105.848 -
105.849 - if (*iso_date++ != ':')
105.850 - return FALSE;
105.851 -
105.852 - tm.tm_sec = strtoul(iso_date, (char **) &iso_date, 10);
105.853 - } else {
105.854 - /*
105.855 - * hhmmss
105.856 - */
105.857 - tm.tm_sec = val % 100;
105.858 - tm.tm_min = (val % 10000) / 100;
105.859 - tm.tm_hour = val / 10000;
105.860 - }
105.861 -
105.862 - time_->tv_sec = mktime_utc(&tm);
105.863 - time_->tv_usec = 1;
105.864 -
105.865 - if (*iso_date == '.')
105.866 - time_->tv_usec = strtoul(iso_date + 1, (char **) &iso_date, 10);
105.867 -
105.868 - if (*iso_date == '+' || *iso_date == '-') {
105.869 - gint sign = (*iso_date == '+') ? -1 : 1;
105.870 -
105.871 - val = 60 * strtoul(iso_date + 1, (char **) &iso_date, 10);
105.872 -
105.873 - if (*iso_date == ':')
105.874 - val = 60 * val + strtoul(iso_date + 1, NULL, 10);
105.875 - else
105.876 - val = 60 * (val / 100) + (val % 100);
105.877 -
105.878 - time_->tv_sec += (time_t) (val * sign);
105.879 - }
105.880 -
105.881 - return TRUE;
105.882 -}
105.883 -
105.884 -
105.885 -gchar *
105.886 -g_time_val_to_iso8601(GTimeVal * time_)
105.887 -{
105.888 - gchar *retval;
105.889 -
105.890 - g_return_val_if_fail(time_->tv_usec >= 0
105.891 - && time_->tv_usec < G_USEC_PER_SEC, NULL);
105.892 -
105.893 -#define ISO_8601_LEN 21
105.894 -#define ISO_8601_FORMAT "%Y-%m-%dT%H:%M:%SZ"
105.895 - retval = g_new0(gchar, ISO_8601_LEN + 1);
105.896 -
105.897 - strftime(retval, ISO_8601_LEN, ISO_8601_FORMAT,
105.898 - gmtime(&(time_->tv_sec)));
105.899 -
105.900 - return retval;
105.901 -}
105.902 -
105.903 -
105.904 -/*
105.905 - * Hacked from glib 2.10 <gdate.c>
105.906 - */
105.907 -
105.908 -void
105.909 -g_date_set_time_t(GDate * date, time_t timet)
105.910 -{
105.911 - struct tm tm;
105.912 -
105.913 - g_return_if_fail(date != NULL);
105.914 -
105.915 -#ifdef HAVE_LOCALTIME_R
105.916 - localtime_r(&timet, &tm);
105.917 -#else
105.918 - {
105.919 - struct tm *ptm = localtime(&timet);
105.920 -
105.921 - if (ptm == NULL) {
105.922 - /*
105.923 - * Happens at least in Microsoft's C library if you pass a
105.924 - * negative time_t. Use 2000-01-01 as default date.
105.925 - */
105.926 -#ifndef G_DISABLE_CHECKS
105.927 - g_return_if_fail_warning(G_LOG_DOMAIN, "g_date_set_time",
105.928 - "ptm != NULL");
105.929 -#endif
105.930 -
105.931 - tm.tm_mon = 0;
105.932 - tm.tm_mday = 1;
105.933 - tm.tm_year = 100;
105.934 - } else
105.935 - memcpy((void *) &tm, (void *) ptm, sizeof(struct tm));
105.936 - }
105.937 -#endif
105.938 -
105.939 - date->julian = FALSE;
105.940 -
105.941 - date->month = tm.tm_mon + 1;
105.942 - date->day = tm.tm_mday;
105.943 - date->year = tm.tm_year + 1900;
105.944 -
105.945 - g_return_if_fail(g_date_valid_dmy(date->day, date->month, date->year));
105.946 -
105.947 - date->dmy = TRUE;
105.948 -}
105.949 -
105.950 -
105.951 -void
105.952 -g_date_set_time_val(GDate * date, GTimeVal * timeval)
105.953 -{
105.954 - g_date_set_time_t(date, (time_t) timeval->tv_sec);
105.955 -}
105.956 -
105.957 -
105.958 -
105.959 -
105.960 -#endif
106.1 --- a/gmyth/src/gmyth_util.h Mon Feb 25 17:45:36 2008 +0000
106.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
106.3 @@ -1,82 +0,0 @@
106.4 -/**
106.5 - * GMyth Library
106.6 - *
106.7 - * @file gmyth/gmyth_util.h
106.8 - *
106.9 - * @brief <p> This component provides utility functions
106.10 - * (dealing with dates, time, string formatting, etc.).
106.11 - *
106.12 - * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
106.13 - * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
106.14 - * @author Rosfran Borges <rosfran.borges@indt.org.br>
106.15 - *
106.16 - *
106.17 - * This program is free software; you can redistribute it and/or modify
106.18 - * it under the terms of the GNU Lesser General Public License as published by
106.19 - * the Free Software Foundation; either version 2 of the License, or
106.20 - * (at your option) any later version.
106.21 - *
106.22 - * This program is distributed in the hope that it will be useful,
106.23 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
106.24 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
106.25 - * GNU General Public License for more details.
106.26 - *
106.27 - * You should have received a copy of the GNU Lesser General Public License
106.28 - * along with this program; if not, write to the Free Software
106.29 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
106.30 - */
106.31 -
106.32 -#ifndef GMYTH_UTIL_H_
106.33 -#define GMYTH_UTIL_H_
106.34 -
106.35 -#include <time.h>
106.36 -#include <glib.h>
106.37 -
106.38 -#include "gmyth_stringlist.h"
106.39 -#include "gmyth_backendinfo.h"
106.40 -#include "gmyth_programinfo.h"
106.41 -
106.42 -G_BEGIN_DECLS
106.43 -
106.44 -typedef struct {
106.45 - guint64 total_space;
106.46 - guint64 used_space;
106.47 -} GMythBackendDetails;
106.48 -
106.49 -
106.50 -GString* gmyth_util_time_to_isoformat (time_t time_value);
106.51 -GString* gmyth_util_time_to_string (time_t time_value);
106.52 -time_t gmyth_util_string_to_time (GString *time_str);
106.53 -gchar* gmyth_util_time_to_isoformat_from_time_val_fmt
106.54 - (const gchar *fmt_string,
106.55 - const GTimeVal *time_val);
106.56 -GTimeVal* gmyth_util_string_to_time_val_fmt (const gchar *fmt_string,
106.57 - const gchar *time_str);
106.58 -GTimeVal* gmyth_util_string_to_time_val (const gchar *time_str);
106.59 -gchar* gmyth_util_time_to_isoformat_from_time_val (const GTimeVal *time);
106.60 -gchar* gmyth_util_time_to_mythformat_from_time_val (const GTimeVal *time);
106.61 -gchar* gmyth_util_time_to_string_only_date (const GTimeVal *time);
106.62 -gchar* gmyth_util_time_to_string_only_time (const GTimeVal *time);
106.63 -gchar* gmyth_util_time_to_string_from_time_val (const GTimeVal *time_val);
106.64 -struct tm* gmyth_util_time_val_to_date (const GTimeVal * time);
106.65 -
106.66 -gboolean gmyth_util_get_backend_details (GMythSocket *sock, GMythBackendDetails **details);
106.67 -void gmyth_util_backend_details_free (GMythBackendDetails *details);
106.68 -
106.69 -gboolean gmyth_util_file_exists (GMythBackendInfo *backend_info,
106.70 - const gchar * filename);
106.71 -gboolean gmyth_util_file_exists_from_socket (GMythSocket *sock,
106.72 - const gchar *filename);
106.73 -gboolean gmyth_util_file_exists_and_get_remote_dir (GMythBackendInfo *backend_info,
106.74 - const gchar *filename,
106.75 - gchar **current_dir);
106.76 -gchar* gmyth_util_create_filename (const gint chan_id,
106.77 - const GTimeVal * start_time);
106.78 -GList* gmyth_util_get_channel_list (GMythBackendInfo *backend_info);
106.79 -GSList* gmyth_util_get_all_recordings (GMythBackendInfo *backend_info);
106.80 -GMythProgramInfo*
106.81 - gmyth_util_get_recording_from_channel (GMythBackendInfo *backend_info,
106.82 - const gchar *channel);
106.83 -
106.84 -G_END_DECLS
106.85 -#endif /* GMYTH_UTIL_H_ */
107.1 --- a/gmyth/src/gmyth_vlc.c Mon Feb 25 17:45:36 2008 +0000
107.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
107.3 @@ -1,290 +0,0 @@
107.4 -/**
107.5 - * GMyth Library
107.6 - *
107.7 - * @file gmyth/gmyth_vlc.c
107.8 - *
107.9 - * @brief <p> GMythVLC library provides functions that
107.10 - * interact with a VLC server running telnet interface.
107.11 - *
107.12 - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
107.13 - * @author Artur Duque de Souza <artur.souza@indt.org.br>
107.14 - *
107.15 - *
107.16 - * This program is free software; you can redistribute it and/or modify
107.17 - * it under the terms of the GNU Lesser General Public License as published by
107.18 - * the Free Software Foundation; either version 2 of the License, or
107.19 - * (at your option) any later version.
107.20 - *
107.21 - * This program is distributed in the hope that it will be useful,
107.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
107.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
107.24 - * GNU General Public License for more details.
107.25 - *
107.26 - * You should have received a copy of the GNU Lesser General Public License
107.27 - * along with this program; if not, write to the Free Software
107.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
107.29 - */
107.30 -
107.31 -#ifdef HAVE_CONFIG_H
107.32 -#include "config.h"
107.33 -#endif
107.34 -
107.35 -#include <assert.h>
107.36 -
107.37 -#include "gmyth_vlc.h"
107.38 -#include "gmyth_debug.h"
107.39 -#include "gmyth_socket.h"
107.40 -
107.41 -/*
107.42 - * static functions
107.43 - */
107.44 -static int _socket_send(int socket, gchar * msg);
107.45 -static int _socket_recv(int socket, gchar * buf);
107.46 -
107.47 -/** Primitive function to send a message through the socket
107.48 - *
107.49 - * @param socket
107.50 - * @param msg the message itself
107.51 - * @return 0 if success
107.52 - */
107.53 -static int
107.54 -_socket_send(int socket, gchar * msg)
107.55 -{
107.56 - size_t size = strlen(msg) + 2; // (\n + \0)
107.57 - gchar *final = (gchar *) g_malloc0(sizeof(gchar) * size);
107.58 -
107.59 - g_snprintf(final, size, "%s\n", msg);
107.60 -
107.61 - if (send(socket, final, strlen(final), 0) == -1)
107.62 - perror("GMyth_VLC: send error");
107.63 -
107.64 - g_free(final);
107.65 - return 0;
107.66 -}
107.67 -
107.68 -
107.69 -/** Primitive function to receive a message through the socket
107.70 - *
107.71 - * @param socket
107.72 - * @param buf Buffer to put the message
107.73 - * @return 0 if success
107.74 - */
107.75 -static int
107.76 -_socket_recv(int socket, gchar * buf)
107.77 -{
107.78 - int numbytes = 0;
107.79 -
107.80 - if ((numbytes = recv(socket, buf, BUFFER - 1, 0)) == -1) {
107.81 - perror("GMyth_VLC: recv error");
107.82 - return -1;
107.83 - }
107.84 -
107.85 - buf[numbytes - 1] = '\0';
107.86 - return numbytes;
107.87 -}
107.88 -
107.89 -
107.90 -/** Function that adds options to the output media
107.91 - *
107.92 - * @param vlc structure with options for vlc
107.93 - * @param output the number of the output media
107.94 - * @param kind the type of option we'll change
107.95 - * @param the params for the option
107.96 - * @return 0 if success
107.97 - */
107.98 -int
107.99 -gmyth_vlc_setup_output(GMythVlc * vlc, int output, gchar * kind,
107.100 - gchar * opts)
107.101 -{
107.102 - int ret;
107.103 -
107.104 - size_t size = strlen(opts) + 25;
107.105 - gchar *msg = g_malloc0(sizeof(gchar) * size);
107.106 -
107.107 - g_snprintf(msg, size, "setup output%d %s %s", output, kind, opts);
107.108 -
107.109 - ret = _socket_send(vlc->sockfd, msg);
107.110 -
107.111 - g_free(msg);
107.112 - return ret;
107.113 -}
107.114 -
107.115 -
107.116 -/** Function to clean the playlist
107.117 - *
107.118 - * @param vlc structure with options for vlc
107.119 - * @param output the number of the output media
107.120 - * @param file the file we want to insert in the playlist
107.121 - * @return 0 if success
107.122 - */
107.123 -int
107.124 -gmyth_vlc_clean_playlist(GMythVlc * vlc)
107.125 -{
107.126 - return _socket_send(vlc->sockfd, "del all");
107.127 -}
107.128 -
107.129 -
107.130 -/** Function to control the playlist
107.131 - *
107.132 - * @param vlc structure with options for vlc
107.133 - * @param output the number of the output media
107.134 - * @param command play, stop or pause(just for vod)
107.135 - * @return 0 if success
107.136 - */
107.137 -int
107.138 -gmyth_vlc_control_input(GMythVlc * vlc, int output, gchar * command)
107.139 -{
107.140 - size_t size = 25;
107.141 - gchar *msg = g_malloc0(sizeof(gchar) * size);
107.142 -
107.143 - g_snprintf(msg, size, "control output%d %s", output, command);
107.144 -
107.145 - int ret = _socket_send(vlc->sockfd, msg);
107.146 -
107.147 - g_free(msg);
107.148 - return ret;
107.149 -}
107.150 -
107.151 -
107.152 -
107.153 -/** Function to insert an item in the playlist
107.154 - *
107.155 - * @param vlc structure with options for vlc
107.156 - * @param output the number of the output media
107.157 - * @param file the file we want to insert in the playlist
107.158 - * @return 0 if success
107.159 - */
107.160 -int
107.161 -gmyth_vlc_create_input(GMythVlc * vlc, int output, gchar * file)
107.162 -{
107.163 - return gmyth_vlc_setup_output(vlc, output, "input", file);
107.164 -}
107.165 -
107.166 -
107.167 -/** Function to create a channel in vlc
107.168 - *
107.169 - * @param vlc structure with options for vlc
107.170 - * @param type the type of channel (broadcast, vod...)
107.171 - * @param port
107.172 - * @return 0 if success
107.173 - */
107.174 -int
107.175 -gmyth_vlc_create_channel(GMythVlc * vlc, gchar * type, int port,
107.176 - int vcodec)
107.177 -{
107.178 - int ret;
107.179 - size_t size = 40;
107.180 - gchar *msg = (gchar *) g_malloc0(sizeof(gchar) * size);
107.181 -
107.182 - g_snprintf(msg, size, "new output%d %s enabled loop", vlc->n_outputs,
107.183 - type);
107.184 -
107.185 - ret = _socket_send(vlc->sockfd, msg);
107.186 -
107.187 - if (ret > -1) {
107.188 - gmyth_vlc_setup_output(vlc, vlc->n_outputs, "option",
107.189 - "sout-keep=1");
107.190 -
107.191 - g_free(msg);
107.192 - size = 256;
107.193 - msg = (gchar *) g_malloc0(sizeof(gchar) * size);
107.194 -
107.195 - if (vcodec == MPEG1)
107.196 - // Best transcode option for N800 (MP1V)
107.197 - g_snprintf(msg, size, "#transcode{vcodec=mp1v,vb=384,"
107.198 - "fps=25.0,scale=1,acodec=mpga,"
107.199 - "ab=64,channels=1}:duplicate{dst="
107.200 - "std{access=http,mux=mpeg1,dst=" ":%d}}", port);
107.201 - else
107.202 - // Best transcode option for N800 (THEORA)
107.203 - g_snprintf(msg, size, "#transcode{vcodec=theo,vb=384,"
107.204 - "fps=25.0,scale=1,acodec=vorb,"
107.205 - "ab=64,channels=1}:duplicate{dst="
107.206 - "std{access=http,mux=ogg,dst=" ":%d}}", port);
107.207 -
107.208 - ret = gmyth_vlc_setup_output(vlc, vlc->n_outputs, "output", msg);
107.209 -
107.210 - vlc->n_outputs++;
107.211 - }
107.212 -
107.213 - g_free(msg);
107.214 -
107.215 - return ret;
107.216 -}
107.217 -
107.218 -
107.219 -/** Function to connect to vlc on the backend
107.220 - *
107.221 - * @param vlc structure with options for vlc
107.222 - * @param backend_info infos about the backend
107.223 - * @param passwd the password for telnet interface
107.224 - * @return 0 if success
107.225 - */
107.226 -int
107.227 -gmyth_vlc_connect(GMythVlc * vlc, GMythBackendInfo * backend_info,
107.228 - gchar * passwd, int port)
107.229 -{
107.230 - int numbytes;
107.231 -
107.232 - if ((vlc->he = gethostbyname(backend_info->hostname)) == NULL) {
107.233 - herror("GMyth_VLC: gethostbyname error");
107.234 - return -1;
107.235 - }
107.236 -
107.237 - if ((vlc->sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
107.238 - perror("GMyth_VLC: socket error");
107.239 - return -1;
107.240 - }
107.241 - // Socket properties
107.242 - vlc->their_addr.sin_family = AF_INET;
107.243 - vlc->their_addr.sin_port = htons(port);
107.244 - vlc->their_addr.sin_addr = *((struct in_addr *) vlc->he->h_addr);
107.245 - memset(&(vlc->their_addr.sin_zero), '\0', 8);
107.246 -
107.247 - if (connect(vlc->sockfd, (struct sockaddr *) &(vlc->their_addr),
107.248 - sizeof(struct sockaddr)) == -1) {
107.249 - perror("GMyth_VLC: connect error. Check VLC's telnet interface");
107.250 - return -1;
107.251 - }
107.252 - // Receive the Password's Prompt
107.253 - numbytes = _socket_recv(vlc->sockfd, vlc->buf);
107.254 -
107.255 - // Send the Password. We don't have to
107.256 - // care about passwords being sent in plain text
107.257 - // because telnet protocol does it.
107.258 - _socket_send(vlc->sockfd, passwd);
107.259 -
107.260 - // Receive the Welcome msg
107.261 - numbytes = _socket_recv(vlc->sockfd, vlc->buf);
107.262 - if (numbytes > -1)
107.263 - if (strncmp(vlc->buf, "\r\nWrong password.", 17) == 0) {
107.264 - perror("Gmyth_VLC: passwd error. Check your passwd");
107.265 - return -2;
107.266 - }
107.267 -
107.268 -
107.269 - return 0;
107.270 -}
107.271 -
107.272 -
107.273 -/** Function to disconnect from vlc
107.274 - *
107.275 - * @param vlc structure with options for vlc
107.276 - * @param backend_info infos about the backend
107.277 - * @return 0 if success
107.278 - */
107.279 -int
107.280 -gmyth_vlc_disconnect(GMythVlc * vlc)
107.281 -{
107.282 -
107.283 - int ret;
107.284 -
107.285 - ret = gmyth_vlc_clean_playlist(vlc);
107.286 -
107.287 - if (ret > -1) {
107.288 - vlc->n_outputs = 0;
107.289 - vlc->n_inputs = 0;
107.290 - }
107.291 -
107.292 - return close(vlc->sockfd);
107.293 -}
108.1 --- a/gmyth/src/gmyth_vlc.h Mon Feb 25 17:45:36 2008 +0000
108.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
108.3 @@ -1,96 +0,0 @@
108.4 -/**
108.5 - * GMyth Library
108.6 - *
108.7 - * @file gmyth/gmyth_vlc.h
108.8 - *
108.9 - * @brief <p> GMythVLC library provides functions that
108.10 - * interact with a VLC server running telnet interface.
108.11 - *
108.12 - * Copyright (C) 2007 INdT - Instituto Nokia de Tecnologia.
108.13 - * @author Artur Duque de Souza <artur.souza@indt.org.br>
108.14 - *
108.15 - *
108.16 - * This program is free software; you can redistribute it and/or modify
108.17 - * it under the terms of the GNU Lesser General Public License as published by
108.18 - * the Free Software Foundation; either version 2 of the License, or
108.19 - * (at your option) any later version.
108.20 - *
108.21 - * This program is distributed in the hope that it will be useful,
108.22 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
108.23 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
108.24 - * GNU General Public License for more details.
108.25 - *
108.26 - * You should have received a copy of the GNU Lesser General Public License
108.27 - * along with this program; if not, write to the Free Software
108.28 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
108.29 - */
108.30 -
108.31 -#ifndef __GMYTH_VLC_H__
108.32 -#define __GMYTH_VLC_H__
108.33 -
108.34 -#include <glib-object.h>
108.35 -
108.36 -#include <glib.h>
108.37 -#include <stdio.h>
108.38 -#include <stdlib.h>
108.39 -#include <unistd.h>
108.40 -#include <errno.h>
108.41 -#include <string.h>
108.42 -#include <netdb.h>
108.43 -#include <sys/types.h>
108.44 -#include <netinet/in.h>
108.45 -#include <sys/socket.h>
108.46 -
108.47 -
108.48 -#include "gmyth_backendinfo.h"
108.49 -#include "gmyth_util.h"
108.50 -
108.51 -G_BEGIN_DECLS
108.52 -#define VLC_TELNET_PORT 4212
108.53 -#define BUFFER 512
108.54 -#define MPEG1 0
108.55 -#define THEORA 1
108.56 -typedef struct _GMythVlc GMythVlc;
108.57 -
108.58 -struct _GMythVlc {
108.59 - int sockfd;
108.60 -
108.61 - // Number of outputs used
108.62 - int n_outputs;
108.63 -
108.64 - // Number of inputs
108.65 - int n_inputs;
108.66 -
108.67 - // Socket vars
108.68 - struct hostent *he;
108.69 - struct sockaddr_in their_addr;
108.70 -
108.71 - char buf[BUFFER];
108.72 -};
108.73 -
108.74 -
108.75 -
108.76 -int gmyth_vlc_setup_output(GMythVlc * vlc, int output,
108.77 - gchar * kind, gchar * opts);
108.78 -
108.79 -
108.80 -int gmyth_vlc_clean_playlist(GMythVlc * vlc);
108.81 -
108.82 -
108.83 -int gmyth_vlc_control_input(GMythVlc * vlc, int output,
108.84 - gchar * command);
108.85 -
108.86 -int gmyth_vlc_create_input(GMythVlc * vlc, int output,
108.87 - gchar * file);
108.88 -
108.89 -int gmyth_vlc_create_channel(GMythVlc * vlc, gchar * type,
108.90 - int port, int vcodec);
108.91 -
108.92 -int gmyth_vlc_connect(GMythVlc * vlc,
108.93 - GMythBackendInfo * backend_info,
108.94 - gchar * passwd, int port);
108.95 -
108.96 -int gmyth_vlc_disconnect(GMythVlc * vlc);
108.97 -
108.98 -G_END_DECLS
108.99 -#endif /* __GMYTH_VLC_H__ */
109.1 --- a/gmyth/src/gst-indent.sh Mon Feb 25 17:45:36 2008 +0000
109.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
109.3 @@ -1,16 +0,0 @@
109.4 -#!/bin/sh
109.5 -indent \
109.6 - --braces-on-if-line \
109.7 - --blank-lines-after-declarations \
109.8 - --case-brace-indentation0 \
109.9 - --case-indentation4 \
109.10 - --braces-after-struct-decl-line \
109.11 - --line-length80 \
109.12 - --no-tabs \
109.13 - --cuddle-else \
109.14 - --dont-line-up-parentheses \
109.15 - --continuation-indentation4 \
109.16 - --honour-newlines \
109.17 - --tab-size4 \
109.18 - --indent-level4 \
109.19 - $*
110.1 --- a/gmyth/tests/Makefile.am Mon Feb 25 17:45:36 2008 +0000
110.2 +++ b/gmyth/tests/Makefile.am Mon Feb 25 17:51:43 2008 +0000
110.3 @@ -1,5 +1,5 @@
110.4 LDADD = \
110.5 - $(top_srcdir)/src/libgmyth.la
110.6 + $(top_srcdir)/gmyth/libgmyth.la
110.7
110.8 AM_LDFLAGS = \
110.9 @GLIB_LIBS@ @GOBJECT_LIBS@ @GTHREAD_LIBS@ @LIBCURL_LIBS@
110.10 @@ -7,8 +7,8 @@
110.11 INCLUDES = \
110.12 -I$(top_srcdir) \
110.13 -I$(top_builddir) \
110.14 - -I$(top_srcdir)/src \
110.15 - -I$(top_builddir)/src \
110.16 + -I$(top_srcdir)/gmyth \
110.17 + -I$(top_builddir)/gmyth \
110.18 $(MYSQL_CFLAGS) \
110.19 $(GLIB_CFLAGS) \
110.20 $(GOBJECT_CFLAGS) \