815 lines
18 KiB
C
815 lines
18 KiB
C
/* blccc - Blinkenlights Chaos Control Center
|
|
*
|
|
* Copyright (c) 2001-2002 Sven Neumann <sven@gimp.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <blib/blib.h>
|
|
|
|
#include "bltypes.h"
|
|
|
|
#include "blapp.h"
|
|
#include "blccc.h"
|
|
#include "blconfig.h"
|
|
#include "blisdn.h"
|
|
#include "blondemand.h"
|
|
#include "blplaylist.h"
|
|
#include "blplaylistitem.h"
|
|
#include "bltheater.h"
|
|
|
|
|
|
static void bl_ccc_class_init (BlCccClass *class);
|
|
static void bl_ccc_init (BlCcc *ccc);
|
|
static void bl_ccc_finalize (GObject *object);
|
|
|
|
|
|
static GObjectClass *parent_class = NULL;
|
|
|
|
|
|
GType
|
|
bl_ccc_get_type (void)
|
|
{
|
|
static GType ccc_type = 0;
|
|
|
|
if (!ccc_type)
|
|
{
|
|
static const GTypeInfo ccc_info =
|
|
{
|
|
sizeof (BlCccClass),
|
|
(GBaseInitFunc) NULL,
|
|
(GBaseFinalizeFunc) NULL,
|
|
(GClassInitFunc) bl_ccc_class_init,
|
|
NULL, /* class_finalize */
|
|
NULL, /* class_data */
|
|
sizeof (BlCcc),
|
|
0, /* n_preallocs */
|
|
(GInstanceInitFunc) bl_ccc_init,
|
|
};
|
|
|
|
ccc_type = g_type_register_static (G_TYPE_OBJECT,
|
|
"BlCcc", &ccc_info, 0);
|
|
}
|
|
|
|
return ccc_type;
|
|
}
|
|
|
|
static void
|
|
bl_ccc_class_init (BlCccClass *class)
|
|
{
|
|
GObjectClass *object_class;
|
|
|
|
parent_class = g_type_class_peek_parent (class);
|
|
|
|
object_class = G_OBJECT_CLASS (class);
|
|
|
|
object_class->finalize = bl_ccc_finalize;
|
|
}
|
|
|
|
static void
|
|
bl_ccc_init (BlCcc *ccc)
|
|
{
|
|
ccc->config = NULL;
|
|
ccc->mutex = g_mutex_new ();
|
|
ccc->theater = NULL;
|
|
ccc->playlist = NULL;
|
|
ccc->effects = NULL;
|
|
ccc->isdn = NULL;
|
|
ccc->active_app = NULL;
|
|
|
|
g_type_class_ref (B_TYPE_MOVIE_PLAYER);
|
|
}
|
|
|
|
static void
|
|
bl_ccc_finalize (GObject *object)
|
|
{
|
|
BlCcc *ccc;
|
|
|
|
ccc = BL_CCC (object);
|
|
|
|
if (ccc->mutex)
|
|
{
|
|
g_mutex_free (ccc->mutex);
|
|
ccc->mutex = NULL;
|
|
}
|
|
if (ccc->isdn)
|
|
{
|
|
g_object_unref (ccc->isdn);
|
|
ccc->isdn = NULL;
|
|
}
|
|
if (ccc->theater)
|
|
{
|
|
g_object_unref (ccc->theater);
|
|
ccc->theater = NULL;
|
|
}
|
|
if (ccc->playlist)
|
|
{
|
|
g_object_unref (ccc->playlist);
|
|
ccc->playlist = NULL;
|
|
}
|
|
if (ccc->effects)
|
|
{
|
|
g_object_unref (ccc->effects);
|
|
ccc->effects = NULL;
|
|
}
|
|
|
|
g_type_class_unref (g_type_class_peek (B_TYPE_MOVIE_PLAYER));
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
isdn_incoming_call (BlIsdn *isdn,
|
|
BlIsdnLine *line,
|
|
BlCcc *ccc)
|
|
{
|
|
BlApp *active;
|
|
BlApp *app;
|
|
|
|
g_printerr ("Incoming call on line %d: %s for %s\n",
|
|
line->channel, line->calling_number, line->called_number);
|
|
|
|
active = ccc->active_app;
|
|
|
|
/* if the line matches this is the call we already handle */
|
|
if (active && active->line == line)
|
|
return;
|
|
|
|
app = bl_config_select_app (ccc->config, line->called_number);
|
|
|
|
if (!app)
|
|
{
|
|
g_printerr (" -> no matching number, go away.\n");
|
|
bl_isdn_call_hangup (isdn, line, BL_ISDN_REASON_NO_USER_RESPONSE);
|
|
return;
|
|
}
|
|
|
|
if (app->disabled)
|
|
{
|
|
g_printerr (" -> this application is temporarily disabled, go away.\n");
|
|
bl_isdn_call_hangup (isdn, line, BL_ISDN_REASON_NO_USER_RESPONSE);
|
|
return;
|
|
}
|
|
|
|
if (!app->public &&
|
|
!bl_config_authorize_caller (ccc->config, line->calling_number))
|
|
{
|
|
g_printerr (" -> I don't know you, go away.\n");
|
|
bl_isdn_call_hangup (isdn, line, BL_ISDN_REASON_NO_USER_RESPONSE);
|
|
return;
|
|
}
|
|
|
|
if (active)
|
|
{
|
|
if (app == active)
|
|
{
|
|
if (ccc->theater->item && ccc->theater->item->module)
|
|
{
|
|
BModule *module = ccc->theater->item->module;
|
|
|
|
if (module->num_players <
|
|
B_MODULE_GET_CLASS (module)->max_players)
|
|
{
|
|
#if 0
|
|
BModuleEvent event;
|
|
|
|
bl_isdn_call_accept (isdn, line, app->vamp);
|
|
|
|
app->line2 = line;
|
|
|
|
/* add a player to the module */
|
|
event.device_id = line->channel - 1;
|
|
event.type = B_EVENT_TYPE_PLAYER_ENTERED;
|
|
event.key = 0;
|
|
|
|
bl_ccc_event (ccc, &event);
|
|
|
|
return;
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
if (app->priority > active->priority)
|
|
{
|
|
/* FIXME: change apps */
|
|
}
|
|
|
|
g_printerr (" -> sorry, we are busy.\n");
|
|
bl_isdn_call_hangup (isdn, line, BL_ISDN_REASON_USER_BUSY);
|
|
return;
|
|
}
|
|
|
|
bl_isdn_call_accept (isdn, line, app->vamp);
|
|
|
|
line->app = app;
|
|
}
|
|
|
|
static void
|
|
isdn_state_changed (BlIsdn *isdn,
|
|
BlIsdnLine *line,
|
|
BlCcc *ccc)
|
|
{
|
|
BModuleEvent event;
|
|
|
|
g_printerr ("Line %d went %s.\n",
|
|
line->channel, line->offhook ? "offhook" : "onhook");
|
|
|
|
if (! line->app)
|
|
return;
|
|
|
|
if (line->offhook)
|
|
{
|
|
BlApp *app = line->app;
|
|
BlPlaylistItem *item = BL_PLAYLIST_ITEM (app);
|
|
|
|
g_mutex_lock (ccc->mutex);
|
|
|
|
ccc->active_app = app;
|
|
app->line = line;
|
|
|
|
bl_theater_push_item (ccc->theater, item);
|
|
bl_theater_play (ccc->theater);
|
|
|
|
g_mutex_unlock (ccc->mutex);
|
|
|
|
/* add a player to the module */
|
|
event.device_id = line->channel - 1;
|
|
event.type = B_EVENT_TYPE_PLAYER_ENTERED;
|
|
event.key = 0;
|
|
|
|
bl_ccc_event (ccc, &event);
|
|
}
|
|
else
|
|
{
|
|
gboolean item_pushed;
|
|
|
|
/* EEK */
|
|
item_pushed = (ccc->theater->item == BL_PLAYLIST_ITEM (line->app));
|
|
|
|
if (item_pushed)
|
|
{
|
|
/* remove the player from the module */
|
|
event.device_id = line->channel - 1;
|
|
event.type = B_EVENT_TYPE_PLAYER_LEFT;
|
|
event.key = 0;
|
|
|
|
bl_ccc_event (ccc, &event);
|
|
}
|
|
|
|
g_mutex_lock (ccc->mutex);
|
|
|
|
line->app->line = NULL;
|
|
line->app = NULL;
|
|
|
|
if (item_pushed)
|
|
bl_theater_finish (ccc->theater);
|
|
|
|
g_mutex_unlock (ccc->mutex);
|
|
}
|
|
}
|
|
|
|
static void
|
|
isdn_key_pressed (BlIsdn *isdn,
|
|
BlIsdnLine *line,
|
|
BModuleKey key,
|
|
BlCcc *ccc)
|
|
{
|
|
BModuleEvent event;
|
|
|
|
if (! ccc->active_app)
|
|
return;
|
|
|
|
/* FIXME: should remap ids */
|
|
event.device_id = line->channel - 1;
|
|
event.type = B_EVENT_TYPE_KEY;
|
|
event.key = key;
|
|
|
|
bl_ccc_event (ccc, &event);
|
|
}
|
|
|
|
static void
|
|
bl_ccc_set_item (BlCcc *ccc,
|
|
BlPlaylistItem *item)
|
|
{
|
|
bl_theater_set_item (ccc->theater, item);
|
|
|
|
bl_theater_play (ccc->theater);
|
|
}
|
|
|
|
static void
|
|
theater_item_finished (BlTheater *theater,
|
|
BlPlaylistItem *item,
|
|
gboolean pushed,
|
|
BlCcc *ccc)
|
|
{
|
|
if (ccc->active_app)
|
|
{
|
|
if (ccc->isdn && ccc->active_app->line)
|
|
{
|
|
bl_isdn_call_hangup (ccc->isdn,
|
|
ccc->active_app->line,
|
|
BL_ISDN_REASON_NORMAL_CALL_CLEARING);
|
|
}
|
|
|
|
ccc->active_app = NULL;
|
|
}
|
|
|
|
if (pushed)
|
|
{
|
|
bl_theater_pop_item (ccc->theater);
|
|
bl_theater_play (ccc->theater);
|
|
}
|
|
else
|
|
{
|
|
if (ccc->playlist)
|
|
{
|
|
item = bl_playlist_load_next_item (ccc->playlist, FALSE);
|
|
|
|
if (! item)
|
|
{
|
|
/* reload the playlist menually because calling
|
|
* bl_ccc_reload() will cause a recursive mutex
|
|
* deadlock
|
|
*/
|
|
BlPlaylist *new;
|
|
const gchar *filename;
|
|
|
|
g_print ("Playlist returned no item, reloading it...\n");
|
|
|
|
filename = b_object_get_filename (B_OBJECT (ccc->playlist));
|
|
|
|
new = bl_playlist_new_from_file (filename, ccc->config,
|
|
bl_theater_paint_callback,
|
|
ccc->theater);
|
|
|
|
if (new)
|
|
{
|
|
g_object_unref (ccc->playlist);
|
|
ccc->playlist = new;
|
|
|
|
item = bl_playlist_load_next_item (ccc->playlist, FALSE);
|
|
}
|
|
}
|
|
|
|
if (item)
|
|
bl_ccc_set_item (ccc, item);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
bl_ccc_setup_applications (BlCcc *ccc)
|
|
{
|
|
GList *list;
|
|
|
|
for (list = ccc->config->applications; list; list = list->next)
|
|
{
|
|
BModule *module = BL_PLAYLIST_ITEM (list->data)->module;
|
|
|
|
module->width = ccc->config->width;
|
|
module->height = ccc->config->height;
|
|
module->channels = 1;
|
|
module->maxval = 255;
|
|
module->aspect = ccc->config->aspect;
|
|
module->buffer = g_new0 (guchar, module->width * module->height);
|
|
module->owns_buffer = TRUE;
|
|
module->paint_callback = bl_theater_paint_callback;
|
|
module->paint_data = ccc->theater;
|
|
}
|
|
}
|
|
|
|
BlCcc *
|
|
bl_ccc_new (BlConfig *config)
|
|
{
|
|
BlCcc *ccc;
|
|
BlTheater *theater;
|
|
GError *error = NULL;
|
|
|
|
g_return_val_if_fail (BL_IS_CONFIG (config), NULL);
|
|
|
|
theater = bl_theater_new (config);
|
|
if (!theater)
|
|
return NULL;
|
|
|
|
ccc = BL_CCC (g_object_new (BL_TYPE_CCC, NULL));
|
|
ccc->config = g_object_ref (config);
|
|
ccc->theater = theater;
|
|
|
|
bl_theater_set_frame_data (theater, NULL);
|
|
|
|
g_signal_connect (G_OBJECT (theater), "item_finished",
|
|
G_CALLBACK (theater_item_finished),
|
|
ccc);
|
|
|
|
if (config->isdn_host)
|
|
{
|
|
ccc->isdn = bl_isdn_new (config, &error);
|
|
if (!ccc->isdn)
|
|
{
|
|
g_printerr ("Could not setup connection to ISDN system "
|
|
"on %s port %d:\n %s\n",
|
|
config->isdn_host, config->isdn_port,
|
|
error->message);
|
|
g_object_unref (ccc);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if (ccc->isdn)
|
|
{
|
|
bl_ccc_setup_applications (ccc);
|
|
|
|
g_signal_connect (G_OBJECT (ccc->isdn), "incoming_call",
|
|
G_CALLBACK (isdn_incoming_call),
|
|
ccc);
|
|
g_signal_connect (G_OBJECT (ccc->isdn), "state_changed",
|
|
G_CALLBACK (isdn_state_changed),
|
|
ccc);
|
|
g_signal_connect (G_OBJECT (ccc->isdn), "key_pressed",
|
|
G_CALLBACK (isdn_key_pressed),
|
|
ccc);
|
|
}
|
|
|
|
bl_ccc_load (ccc, config->playlist, FALSE);
|
|
|
|
ccc->effects = b_effects_new ();
|
|
|
|
bl_theater_set_effects (ccc->theater, ccc->effects);
|
|
|
|
return ccc;
|
|
}
|
|
|
|
gchar *
|
|
bl_ccc_status (BlCcc *ccc)
|
|
{
|
|
GString *status;
|
|
|
|
g_return_val_if_fail (BL_IS_CCC (ccc), NULL);
|
|
|
|
status = g_string_new (NULL);
|
|
|
|
g_mutex_lock (ccc->mutex);
|
|
|
|
if (ccc->playlist)
|
|
{
|
|
g_string_append_printf (status, "Playlist is '%s' with %d items.\n",
|
|
b_object_get_name (B_OBJECT (ccc->playlist)),
|
|
g_list_length (ccc->playlist->items));
|
|
}
|
|
else
|
|
{
|
|
g_string_append (status, "No playlist loaded.\n");
|
|
}
|
|
|
|
if (ccc->effects)
|
|
{
|
|
g_string_append_printf (status, "Current effects: "
|
|
"invert=%s vflip=%s hflip=%s lmirror=%s rmirror=%s.\n",
|
|
ccc->effects->invert ? "ON" : "OFF",
|
|
ccc->effects->vflip ? "ON" : "OFF",
|
|
ccc->effects->hflip ? "ON" : "OFF",
|
|
ccc->effects->lmirror ? "ON" : "OFF",
|
|
ccc->effects->rmirror ? "ON" : "OFF");
|
|
}
|
|
|
|
if (ccc->theater->item)
|
|
{
|
|
gchar *str;
|
|
|
|
str = bl_playlist_item_describe (ccc->theater->item);
|
|
g_string_append_printf (status, "Current item is a %s.\n", str);
|
|
g_free (str);
|
|
|
|
if (bl_theater_is_playing (ccc->theater))
|
|
g_string_append_printf (status, "The movie is playing%s.\n",
|
|
ccc->active_app ? " on demand" : "");
|
|
else
|
|
g_string_append (status, "The movie is paused.\n");
|
|
}
|
|
else
|
|
{
|
|
g_string_append (status, "No movie.\n");
|
|
}
|
|
|
|
{
|
|
GType *module_types;
|
|
gint n_module_types;
|
|
gint i;
|
|
|
|
g_string_append (status, "Modules: ");
|
|
|
|
module_types = g_type_children (B_TYPE_MODULE, &n_module_types);
|
|
|
|
for (i = 0; i < n_module_types; i++)
|
|
{
|
|
if (i > 0)
|
|
g_string_append (status, ", ");
|
|
|
|
g_string_append (status, g_type_name (module_types[i]));
|
|
}
|
|
|
|
g_free (module_types);
|
|
|
|
g_string_append (status, "\n");
|
|
}
|
|
|
|
{
|
|
GList *recipients;
|
|
|
|
recipients = b_sender_list_recipients (ccc->theater->sender);
|
|
|
|
if (recipients)
|
|
{
|
|
GList *list;
|
|
|
|
g_string_append (status, "Recipients: ");
|
|
|
|
for (list = recipients; list; list = g_list_next (list))
|
|
{
|
|
if (list->prev)
|
|
g_string_append (status, ", ");
|
|
|
|
g_string_append (status, (gchar *) list->data);
|
|
}
|
|
|
|
g_string_append (status, ".\n");
|
|
|
|
g_list_foreach (recipients, (GFunc) g_free, NULL);
|
|
g_list_free (recipients);
|
|
}
|
|
else
|
|
{
|
|
g_string_append (status, "No recipients.\n");
|
|
}
|
|
}
|
|
|
|
if (ccc->isdn)
|
|
{
|
|
gint i;
|
|
|
|
g_string_append_printf (status, "Control through isdn is %s.\n",
|
|
ccc->isdn->blocked ? "blocked" : "allowed");
|
|
|
|
g_string_append_printf (status, "The %d isdn lines are:\n",
|
|
ccc->isdn->num_lines);
|
|
|
|
for (i = 0; i < ccc->isdn->num_lines; i++)
|
|
{
|
|
if (ccc->isdn->lines[i].offhook)
|
|
g_string_append_printf (status, " %d: offhook (%s for %s)\n", i,
|
|
ccc->isdn->lines[i].calling_number,
|
|
ccc->isdn->lines[i].called_number);
|
|
else
|
|
g_string_append_printf (status, " %d: onhook\n", i);
|
|
}
|
|
}
|
|
|
|
g_mutex_unlock (ccc->mutex);
|
|
|
|
return g_string_free (status, FALSE);
|
|
}
|
|
|
|
gboolean
|
|
bl_ccc_reload (BlCcc *ccc)
|
|
{
|
|
gchar *filename = NULL;
|
|
gboolean retval = FALSE;
|
|
|
|
g_return_val_if_fail (BL_IS_CCC (ccc), FALSE);
|
|
|
|
g_mutex_lock (ccc->mutex);
|
|
|
|
if (ccc->playlist)
|
|
filename = g_strdup (b_object_get_filename (B_OBJECT (ccc->playlist)));
|
|
|
|
g_mutex_unlock (ccc->mutex);
|
|
|
|
retval = bl_ccc_load (ccc, filename, FALSE);
|
|
g_free (filename);
|
|
|
|
return retval;
|
|
}
|
|
|
|
gboolean
|
|
bl_ccc_load (BlCcc *ccc,
|
|
const gchar *filename,
|
|
gboolean instant_change)
|
|
{
|
|
BlConfig *config;
|
|
BlPlaylist *new;
|
|
BlPlaylistItem *item;
|
|
|
|
g_return_val_if_fail (BL_IS_CCC (ccc), FALSE);
|
|
g_return_val_if_fail (filename != NULL, FALSE);
|
|
|
|
g_mutex_lock (ccc->mutex);
|
|
|
|
config = ccc->config;
|
|
|
|
new = bl_playlist_new_from_file (filename, config,
|
|
bl_theater_paint_callback, ccc->theater);
|
|
|
|
if (new)
|
|
{
|
|
if (ccc->playlist)
|
|
g_object_unref (ccc->playlist);
|
|
ccc->playlist = new;
|
|
|
|
if (!ccc->theater->item)
|
|
{
|
|
item = bl_playlist_load_next_item (ccc->playlist, FALSE);
|
|
|
|
if (item)
|
|
bl_ccc_set_item (ccc, item);
|
|
}
|
|
else if (instant_change)
|
|
{
|
|
bl_theater_finish (ccc->theater);
|
|
}
|
|
}
|
|
|
|
g_mutex_unlock (ccc->mutex);
|
|
|
|
return (new != NULL);
|
|
}
|
|
|
|
gchar *
|
|
bl_ccc_list (BlCcc *ccc)
|
|
{
|
|
gchar *retval = NULL;
|
|
|
|
g_return_val_if_fail (BL_IS_CCC (ccc), NULL);
|
|
|
|
g_mutex_lock (ccc->mutex);
|
|
|
|
if (ccc->playlist)
|
|
retval = bl_playlist_item_describe (BL_PLAYLIST_ITEM (ccc->playlist));
|
|
|
|
g_mutex_unlock (ccc->mutex);
|
|
|
|
return retval;
|
|
}
|
|
|
|
gchar *
|
|
bl_ccc_next (BlCcc *ccc)
|
|
{
|
|
gchar *retval = NULL;
|
|
|
|
g_return_val_if_fail (BL_IS_CCC (ccc), NULL);
|
|
|
|
g_mutex_lock (ccc->mutex);
|
|
|
|
bl_theater_finish (ccc->theater);
|
|
|
|
if (ccc->theater->item)
|
|
retval = bl_playlist_item_describe (ccc->theater->item);
|
|
|
|
g_mutex_unlock (ccc->mutex);
|
|
|
|
return retval;
|
|
}
|
|
|
|
void
|
|
bl_ccc_kill (BlCcc *ccc)
|
|
{
|
|
g_return_if_fail (BL_IS_CCC (ccc));
|
|
|
|
g_mutex_lock (ccc->mutex);
|
|
|
|
if (ccc->theater)
|
|
bl_theater_kill (ccc->theater);
|
|
|
|
g_mutex_unlock (ccc->mutex);
|
|
}
|
|
|
|
void
|
|
bl_ccc_event (BlCcc *ccc,
|
|
BModuleEvent *event)
|
|
{
|
|
g_return_if_fail (BL_IS_CCC (ccc));
|
|
g_return_if_fail (event != NULL);
|
|
|
|
g_mutex_lock (ccc->mutex);
|
|
|
|
bl_theater_event (ccc->theater, event);
|
|
|
|
g_mutex_unlock (ccc->mutex);
|
|
}
|
|
|
|
gboolean
|
|
bl_ccc_add (BlCcc *ccc,
|
|
const gchar *host,
|
|
GError **error)
|
|
{
|
|
gboolean success;
|
|
|
|
g_return_val_if_fail (BL_IS_CCC (ccc), FALSE);
|
|
g_return_val_if_fail (host != NULL, FALSE);
|
|
|
|
g_mutex_lock (ccc->mutex);
|
|
|
|
success = bl_theater_add_recipient (ccc->theater, host, error);
|
|
|
|
g_mutex_unlock (ccc->mutex);
|
|
|
|
return success;
|
|
}
|
|
|
|
gboolean
|
|
bl_ccc_remove (BlCcc *ccc,
|
|
const gchar *host,
|
|
GError **error)
|
|
{
|
|
gboolean success;
|
|
|
|
g_return_val_if_fail (BL_IS_CCC (ccc), FALSE);
|
|
g_return_val_if_fail (host != NULL, FALSE);
|
|
|
|
g_mutex_lock (ccc->mutex);
|
|
|
|
success = bl_theater_remove_recipient (ccc->theater, host, error);
|
|
|
|
g_mutex_unlock (ccc->mutex);
|
|
|
|
return success;
|
|
}
|
|
|
|
gboolean
|
|
bl_ccc_app_enable (BlCcc *ccc,
|
|
const gchar *number)
|
|
{
|
|
BlApp *app;
|
|
|
|
g_return_val_if_fail (BL_IS_CCC (ccc), FALSE);
|
|
g_return_val_if_fail (number != NULL, FALSE);
|
|
|
|
app = bl_config_select_app (ccc->config, number);
|
|
if (!app)
|
|
return FALSE;
|
|
|
|
if (!app->disabled)
|
|
return TRUE;
|
|
|
|
app->disabled = FALSE;
|
|
g_printerr ("Enabled application %s (%s)\n", app->name, app->number);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
bl_ccc_app_disable (BlCcc *ccc,
|
|
const gchar *number)
|
|
{
|
|
BlApp *app;
|
|
|
|
g_return_val_if_fail (BL_IS_CCC (ccc), FALSE);
|
|
g_return_val_if_fail (number != NULL, FALSE);
|
|
|
|
app = bl_config_select_app (ccc->config, number);
|
|
if (!app)
|
|
return FALSE;
|
|
|
|
if (app->disabled)
|
|
return TRUE;
|
|
|
|
app->disabled = TRUE;
|
|
g_printerr ("Disabled application %s (%s)\n", app->name, app->number);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
bl_ccc_isdn_block (BlCcc *ccc)
|
|
{
|
|
g_return_if_fail (BL_IS_CCC (ccc));
|
|
|
|
if (ccc->isdn)
|
|
bl_isdn_block (ccc->isdn);
|
|
|
|
bl_theater_finish (ccc->theater);
|
|
}
|
|
|
|
void
|
|
bl_ccc_isdn_unblock (BlCcc *ccc)
|
|
{
|
|
g_return_if_fail (BL_IS_CCC (ccc));
|
|
|
|
if (ccc->isdn)
|
|
bl_isdn_unblock (ccc->isdn);
|
|
}
|