4 * @file gmyth/gmyth_context.c
6 * @brief <p> GMythContext class contains general attributes and functions
7 * that express the connection state of each mythtvfrontend.
9 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
10 * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "gmyth_context.h"
31 #include <arpa/inet.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
38 #include "gmyth_query.h"
39 #include "gmyth_socket.h"
41 static void gmyth_context_class_init (GMythContextClass *klass);
42 static void gmyth_context_init (GMythContext *object);
44 static void gmyth_context_dispose (GObject *object);
45 static void gmyth_context_finalize (GObject *object);
48 G_DEFINE_TYPE(GMythContext, gmyth_context, G_TYPE_OBJECT)
50 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
52 static GMythContext *gcontext = NULL;
55 gmyth_context_class_init (GMythContextClass *klass)
57 GObjectClass *gobject_class;
59 gobject_class = (GObjectClass *) klass;
61 gobject_class->dispose = gmyth_context_dispose;
62 gobject_class->finalize = gmyth_context_finalize;
66 gmyth_context_init (GMythContext *gmyth_context)
72 gmyth_context_dispose (GObject *object)
74 GMythContext *gmyth_context = GMYTH_CONTEXT(object);
76 if ( gmyth_context->gmyth_settings != NULL ) {
77 g_object_unref (gmyth_context->gmyth_settings);
78 gmyth_context->gmyth_settings = NULL;
81 if ( gmyth_context->localhostname != NULL ) {
82 g_string_free ( gmyth_context->localhostname, TRUE );
83 gmyth_context->localhostname = NULL;
86 if (gmyth_context->server_socket != NULL) {
87 g_object_unref (gmyth_context->server_socket);
88 gmyth_context->server_socket = NULL;
91 G_OBJECT_CLASS (gmyth_context_parent_class)->dispose (object);
95 gmyth_context_finalize (GObject *object)
97 g_signal_handlers_destroy (object);
99 G_OBJECT_CLASS (gmyth_context_parent_class)->finalize (object);
102 /** Gets the some important address translation info,
103 * from the client socket that will open a connection.
105 * @return gint error number
108 myth_context_toaddrinfo( gchar *addr, gint port, struct addrinfo **addrInfo )
110 struct addrinfo hints;
111 gchar *portStr = g_strnfill( 32, ' ' );
112 gint errorn = EADDRNOTAVAIL;
114 memset( &hints, 0, sizeof(hints) );
115 hints.ai_family = AF_INET;
116 hints.ai_socktype = SOCK_STREAM;
118 /* hints.ai_flags = AI_NUMERICHOST; */
120 sprintf(portStr, "%d", port);
124 g_debug( "[%s] Address: %s, port: %s\n", __FUNCTION__, addr, portStr );
125 if ( ( errorn = getaddrinfo(addr, portStr, &hints, addrInfo) ) != 0 ) {
126 g_printerr( "[%s] Socket ERROR: %s\n", __FUNCTION__, gai_strerror(errorn) );
133 /** Initializes the GMythContext object. It reads local system information
134 * load gmyth user settings and start connection to the database.
136 * @return TRUE if initialization was successfull,
137 * FALSE if any error happens.
140 gmyth_context_initialize ()
142 GString *localhost = NULL;
144 if (gcontext == NULL) {
145 gcontext = GMYTH_CONTEXT ( g_object_new (GMYTH_CONTEXT_TYPE, FALSE));
148 localhost = gmyth_socket_get_local_hostname( );
150 if (localhost==NULL || localhost->len <=0 ) {
151 g_warning ("[%s] Could not determine local hostname. Setting to 127.0.0.1", __FUNCTION__);
152 gcontext->localhostname = g_string_new ("127.0.0.1");
154 gcontext->localhostname = localhost;
157 if (gcontext->gmyth_settings) {
158 g_object_unref (gcontext->gmyth_settings);
159 gcontext->gmyth_settings = NULL;
162 gcontext->gmyth_settings = gmyth_settings_new ();
163 if (!gmyth_settings_load (gcontext->gmyth_settings)) {
164 g_warning ("GMythContext: Settings file not opened!\n");
166 g_debug ("GMythContext: Settings file loaded");
169 if (gcontext->server_socket != NULL) {
170 g_object_unref (gcontext->server_socket);
171 gcontext->server_socket = NULL;
174 GString *server_hostname =
175 gmyth_settings_get_backend_hostname(gcontext->gmyth_settings);
176 int server_port = gmyth_settings_get_backend_port(gcontext->gmyth_settings);
178 gcontext->server_socket = gmyth_socket_new ();
179 if (!gmyth_socket_connect_to_backend (gcontext->server_socket,
180 server_hostname->str, server_port, FALSE)) {
181 g_warning ("[%s] Socket connection to backend error!", __FUNCTION__);
182 g_object_unref (gcontext->server_socket);
183 gcontext->server_socket = NULL;
190 /** Formats a Mythtv protocol command based on strlist and sends it to
191 * the connected backend. The backend response is overwritten into strlist.
193 * @param strlist the string list to be sent,
194 * and on which the answer will be written.
195 * @return TRUE if command was sent and an answer was received, FALSE if any
199 gmyth_context_send_receive_stringlist (GMythStringList *strlist)
203 if (!gcontext || !(gcontext->server_socket)) {
204 g_warning ("[%s] GMythContext not initialized", __FUNCTION__);
208 //g_static_mutex_lock( &mutex );
210 ok = gmyth_socket_sendreceive_stringlist (gcontext->server_socket, strlist);
212 //g_static_mutex_unlock( &mutex );
215 g_warning ("Connection to backend server lost");
218 return (ok ? TRUE : FALSE);
221 /** Gets the GMythSettings object associated to this context.
223 * @return The GMythSettings object currently valid or NULL if the settings
227 gmyth_context_get_settings ()
230 g_warning ("[%s] GMythContext not initialized\n", __FUNCTION__);
234 return gcontext->gmyth_settings;
237 /** Gets the machine local hostname.
239 * @param hostname a valid GString object to be overwritten with the local
241 * @return true if the hostname was read, false if any error happened.
244 gmyth_context_get_local_hostname (GString *hostname)
247 g_warning ("[%s] Received null argument", __FUNCTION__);
251 g_string_assign (hostname, gcontext->localhostname->str);
256 /** Gets a setting information from the backend mysql database.
258 * @param key The setting key to be retrieved.
259 * @param host the hostname associated to the desired setting.
260 * @param default_value the default setting value if could not query from
262 * @return The setting value loaded from database, or the given default value
263 * if the query fails.
266 gmyth_context_get_setting_onhost (GString *key, GString *host, GString *default_value)
270 // TODO: Reuse msql query in gmyth_context
271 GMythQuery *gmyth_query = gmyth_query_new ();
273 if (gmyth_query_connect (gmyth_query)) {
277 query_str = g_string_new ("");
278 g_string_printf (query_str, "SELECT data FROM settings WHERE value = \"%s\" "
279 "AND hostname = \"%s\" ;", key->str, host->str);
281 msql_res = gmyth_query_process_statement (gmyth_query, query_str->str);
283 msql_row = mysql_fetch_row (msql_res);
284 if (msql_row != NULL) {
285 return g_string_new (msql_row[0]);
289 g_object_unref (gmyth_query);
291 g_warning ("Database not open while trying to load setting: %s", key->str);
295 return default_value;
298 /** Verify if the context is currently connected to a backend.
300 * @return true if connection was opened, false if not.
303 gmyth_context_check_connection ()
305 // FIXME: Check this based on socket states
307 g_warning ("[%s] GMythContext not initialized", __FUNCTION__);
311 return (gcontext->server_socket != NULL);