856 lines
28 KiB
C
856 lines
28 KiB
C
/*
|
|
* gtk GUI functions
|
|
*
|
|
* This file is part of ANT (Ant is Not a Telephone)
|
|
*
|
|
* Copyright 2002, 2003 Roland Stigge
|
|
*
|
|
* ANT 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.
|
|
*
|
|
* ANT 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 ANT; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
/* regular GNU system includes */
|
|
#include <stdio.h>
|
|
#include <signal.h>
|
|
#ifdef HAVE_STDLIB_H
|
|
#include <stdlib.h>
|
|
#endif
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
/* GTK */
|
|
#include <gtk/gtk.h>
|
|
#include <gdk/gdkkeysyms.h>
|
|
|
|
/* capi support */
|
|
#ifdef HAVE_LIBCAPI20
|
|
#include "isdn_capi.h"
|
|
#endif
|
|
|
|
/* own header files */
|
|
#include "globals.h"
|
|
#include "gtk.h"
|
|
#include "session.h"
|
|
#include "isdn.h"
|
|
#include "util.h"
|
|
#include "sound.h"
|
|
#include "callerid.h"
|
|
#include "llcheck.h"
|
|
#include "settings.h"
|
|
#include "gtksettings.h"
|
|
#include "controlpad.h"
|
|
|
|
/* graphical symbols */
|
|
#include "hangup.xpm"
|
|
#include "pickup.xpm"
|
|
#include "aboutlogo.xpm"
|
|
/*
|
|
#include "icon16x16.xpm"
|
|
#include "icon32x32.xpm"
|
|
*/
|
|
#include "icon48x48.xpm"
|
|
/*
|
|
#include "icon64x64.xpm"
|
|
*/
|
|
|
|
/* call timeout_callback each <this number> of milliseconds */
|
|
#define TIMER_DELAY 300
|
|
|
|
volatile int interrupted = 0; /* the caught signal will be stored here */
|
|
|
|
/*
|
|
* the quit (e.g. menu entry) callback
|
|
* prototype is this way to standardize to GtkItemFactoryCallback2
|
|
*
|
|
* this function will always be called when gtk is to finish
|
|
*
|
|
* input: data: session
|
|
*/
|
|
static void quit(GtkWidget *widget _U_, gpointer data, guint action _U_) {
|
|
session_t *session = (session_t *) data;
|
|
|
|
settings_history_write(session); /* write history */
|
|
settings_callerid_write(session); /* write callerid history */
|
|
|
|
gtk_handle_hang_up_button(NULL, data); /* simulate hang_up_button */
|
|
|
|
/* some (GUI) de-initialization, not directly session related */
|
|
llcheck_bar_deinit(session->llcheck_in);
|
|
llcheck_bar_deinit(session->llcheck_out);
|
|
|
|
gtk_main_quit();
|
|
}
|
|
|
|
/*
|
|
* main window delete_event callback
|
|
*
|
|
* input: data: session
|
|
*/
|
|
gint delete_event(GtkWidget *widget,
|
|
GdkEvent *event _U_,
|
|
gpointer data)
|
|
{
|
|
quit(widget, data, 0);
|
|
return FALSE; /* continue event handling */
|
|
}
|
|
|
|
/* handler for SIGTERM and SIGINT */
|
|
void terminate_signal_callback(int sig) {
|
|
interrupted = sig;
|
|
}
|
|
|
|
/*
|
|
* periodically (e.g. each 300 milliseconds) from gtk main loop called function
|
|
*/
|
|
gint timeout_callback(gpointer data) {
|
|
session_t *session = (session_t *) data;
|
|
|
|
if (interrupted) {
|
|
switch(interrupted) {
|
|
case SIGINT:
|
|
if (debug)
|
|
fprintf(stderr, "Ctrl-C caught.\n");
|
|
break;
|
|
case SIGTERM:
|
|
if (debug)
|
|
fprintf(stderr, "SIGTERM caught.\n");
|
|
break;
|
|
default:
|
|
fprintf(stderr, "Warning: Unknown signal caught.\n");
|
|
}
|
|
quit(NULL, data, 0);
|
|
}
|
|
|
|
if (session->state == STATE_CONVERSATION) {
|
|
char *timediff = timediff_str(time(NULL), session->vcon_time);
|
|
char *buf;
|
|
|
|
if (0 > asprintf(&buf, "%s %s",
|
|
state_data[session->state].status_bar, timediff))
|
|
fprintf(stderr, "Warning: timeout_callback: asprintf error.\n");
|
|
|
|
gtk_statusbar_pop(GTK_STATUSBAR(session->status_bar),
|
|
session->phone_context_id);
|
|
gtk_statusbar_push(GTK_STATUSBAR(session->status_bar),
|
|
session->phone_context_id,
|
|
buf);
|
|
free(buf);
|
|
free(timediff);
|
|
}
|
|
|
|
if (session->state == STATE_PLAYBACK) {
|
|
char *timediff = timediff_str(time(NULL),
|
|
session->effect_playback_start_time);
|
|
char *buf;
|
|
|
|
if (0 > asprintf(&buf, "%s %s",
|
|
state_data[session->state].status_bar, timediff))
|
|
fprintf(stderr, "Warning: timeout_callback: asprintf error.\n");
|
|
|
|
gtk_statusbar_pop(GTK_STATUSBAR(session->status_bar),
|
|
session->phone_context_id);
|
|
gtk_statusbar_push(GTK_STATUSBAR(session->status_bar),
|
|
session->phone_context_id,
|
|
buf);
|
|
free(buf);
|
|
free(timediff);
|
|
}
|
|
|
|
#ifdef HAVE_LIBCAPI20
|
|
/* use periodic timer to handle CAPI messages */
|
|
if (session->capi_contr) {
|
|
printf ("capi messages\n");
|
|
ant_capi_messages(session);
|
|
}
|
|
#endif
|
|
|
|
return TRUE; /* call it again */
|
|
}
|
|
|
|
|
|
/*
|
|
* some GUI tools
|
|
*/
|
|
|
|
/*
|
|
* return a dialog window with a (big) label and an ok button to close
|
|
* (good for displaying a note)
|
|
*
|
|
* justification: justification of label (e.g. GTK_JUSTIFY_LEFT)
|
|
*
|
|
* NOTE: caller has to show the window itself with gtk_widget_show()
|
|
* and maybe want to make it modal with
|
|
* gtk_window_set_modal(GTK_WINDOW(window), TRUE);
|
|
*/
|
|
GtkWidget *ok_dialog_get(char *title, char *contents,
|
|
GtkJustification justification) {
|
|
GtkWidget *window;
|
|
GtkWidget *button_box;
|
|
GtkWidget *button;
|
|
GtkWidget *label;
|
|
|
|
window = gtk_dialog_new();
|
|
gtk_window_set_title(GTK_WINDOW(window), title);
|
|
|
|
/* vbox area */
|
|
gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(window)->vbox), 0);
|
|
label = gtk_label_new(contents);
|
|
gtk_label_set_justify(GTK_LABEL(label), justification);
|
|
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), label,
|
|
TRUE, FALSE, 0);
|
|
gtk_misc_set_padding(GTK_MISC(label), 10, 10);
|
|
gtk_widget_show(label);
|
|
|
|
/* action area */
|
|
button_box = gtk_hbutton_box_new();
|
|
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window)->action_area),
|
|
button_box);
|
|
gtk_widget_show(button_box);
|
|
|
|
/* OK button */
|
|
button = gtk_button_new_with_label(_("OK"));
|
|
gtk_box_pack_start_defaults(GTK_BOX(button_box), button);
|
|
gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
|
|
GTK_SIGNAL_FUNC(gtk_widget_destroy),
|
|
GTK_OBJECT(window));
|
|
gtk_widget_show(button);
|
|
|
|
/* caller has to show the window itself */
|
|
|
|
return window;
|
|
}
|
|
|
|
/*
|
|
* shortcut to display a note about audio devices not available
|
|
*/
|
|
void show_audio_error_dialog(void) {
|
|
GtkWidget *dialog;
|
|
|
|
dialog = ok_dialog_get(_("ANT Note"),
|
|
_("Can't open audio device.\n"
|
|
"Please stop other applications using\n"
|
|
"the audio device(s) or check your\n"
|
|
"device settings and try again."),
|
|
GTK_JUSTIFY_CENTER);
|
|
gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
|
|
gtk_widget_show(dialog);
|
|
}
|
|
|
|
/**********************
|
|
* some GUI callbacks *
|
|
**********************/
|
|
|
|
/*
|
|
* File Menu entries
|
|
*/
|
|
|
|
struct info_row_t {
|
|
gchar *tag;
|
|
gchar *value;
|
|
};
|
|
|
|
/* Info window */
|
|
static void cb_info_window(GtkWidget *widget _U_, gpointer data,
|
|
guint action _U_) {
|
|
session_t *session = (session_t *) data;
|
|
int inactive = session->option_release_devices &&
|
|
(session->state == STATE_READY || session->state == STATE_RINGING_QUIET);
|
|
struct info_row_t rows[] = {
|
|
{ N_("Sound input device:"), strdup(session->audio_device_name_in)},
|
|
{ N_("Input speed:"), inactive ? strdup(_("[inactive]")) :
|
|
ltostr(session->audio_speed_in) },
|
|
{ N_("Input sample size (bits):"), inactive ?
|
|
strdup(_("[inactive]")) : ltostr(session->audio_sample_size_in * 8)},
|
|
{ N_("Input fragment size (samples):"), inactive ? strdup(_("[inactive]")) :
|
|
ltostr(session->fragment_size_in / session->audio_sample_size_in)},
|
|
{ N_("Input channels:"), inactive ? strdup(_("[inactive]")) : ltostr(1) },
|
|
{ "", strdup("") },
|
|
|
|
{ N_("Sound output device:"), strdup(session->audio_device_name_out)},
|
|
{ N_("Output speed:"), inactive ? strdup(_("[inactive]")) :
|
|
ltostr(session->audio_speed_out) },
|
|
{ N_("Output sample size (bits):"), inactive ?
|
|
strdup(_("[inactive]")) : ltostr(session->audio_sample_size_out*8)},
|
|
{ N_("Input fragment size (samples):"), inactive ? strdup(_("[inactive]")) :
|
|
ltostr(session->fragment_size_out / session->audio_sample_size_out)},
|
|
{ N_("Output channels:"), inactive ? strdup(_("[inactive]")) : ltostr(1) },
|
|
{ "", strdup("") },
|
|
|
|
{ N_("ISDN device:"), strdup(session->isdn_device_name) },
|
|
{ N_("ISDN speed (samples):"), ltostr(8000) },
|
|
{ N_("ISDN sample size (bits):"), ltostr(8) },
|
|
{ N_("ISDN fragment size (bytes):"), ltostr(255) }
|
|
};
|
|
unsigned int i;
|
|
|
|
GtkWidget *window; /* the window itself, actually a GtkDialog */
|
|
GtkWidget *table; /* for tag->value pairs */
|
|
GtkWidget *label;
|
|
GtkWidget *button_box;
|
|
GtkWidget *button;
|
|
GtkWidget *separator;
|
|
|
|
window = gtk_dialog_new();
|
|
gtk_window_set_title(GTK_WINDOW(window), _("ANT Info"));
|
|
|
|
/* the info area */
|
|
table = gtk_table_new(sizeof(rows) / sizeof(struct info_row_t), 2, FALSE);
|
|
gtk_container_set_border_width(GTK_CONTAINER(table), 10);
|
|
gtk_table_set_col_spacings(GTK_TABLE(table), 10);
|
|
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window)->vbox), table);
|
|
gtk_widget_show(table);
|
|
|
|
for (i = 0; i < sizeof(rows) / sizeof(struct info_row_t); i++) {
|
|
if (strcmp(rows[i].tag, "")) { /* normal data */
|
|
label = gtk_label_new(_(rows[i].tag));
|
|
gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, i, i + 1);
|
|
gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
|
|
gtk_widget_show(label);
|
|
|
|
label = gtk_label_new(rows[i].value);
|
|
gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 2, i, i + 1);
|
|
gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
|
|
gtk_widget_show(label);
|
|
} else { /* separator */
|
|
separator = gtk_hseparator_new();
|
|
gtk_table_attach(GTK_TABLE(table), separator, 0, 2, i, i + 1,
|
|
GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 5);
|
|
gtk_widget_show(separator);
|
|
}
|
|
|
|
free(rows[i].value); /* free stdrup() mem */
|
|
}
|
|
|
|
/* action area */
|
|
button_box = gtk_hbutton_box_new();
|
|
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window)->action_area),
|
|
button_box);
|
|
gtk_widget_show(button_box);
|
|
|
|
button = gtk_button_new_with_label(_("OK"));
|
|
gtk_box_pack_start_defaults(GTK_BOX(button_box), button);
|
|
gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
|
|
GTK_SIGNAL_FUNC(gtk_widget_destroy),
|
|
GTK_OBJECT(window));
|
|
gtk_widget_show(button);
|
|
|
|
gtk_window_set_modal(GTK_WINDOW(window), TRUE);
|
|
|
|
/* show everything */
|
|
gtk_widget_show(window);
|
|
}
|
|
|
|
/*
|
|
* Options menu entries
|
|
*/
|
|
/*
|
|
* Help menu entries
|
|
*/
|
|
|
|
/* the about menu entry callback */
|
|
static void cb_about(GtkWidget *widget _U_, gpointer data _U_, guint action _U_) {
|
|
GtkWidget *window;
|
|
GtkWidget *button_box;
|
|
GtkWidget *button;
|
|
GtkWidget *label;
|
|
|
|
GdkPixmap* pixmap;
|
|
GdkBitmap* mask;
|
|
GtkStyle* style;
|
|
GtkWidget* pixmapwidget;
|
|
|
|
char *message;
|
|
|
|
window = gtk_dialog_new();
|
|
gtk_window_set_title(GTK_WINDOW(window), _("About ANT"));
|
|
|
|
/* vbox area */
|
|
gtk_container_set_border_width(GTK_CONTAINER(GTK_DIALOG(window)->vbox), 0);
|
|
|
|
gtk_widget_realize(window);
|
|
style = gtk_widget_get_style(window);
|
|
pixmap = gdk_pixmap_create_from_xpm_d(window->window,
|
|
&mask,
|
|
NULL,
|
|
(gchar**) aboutlogo_xpm);
|
|
pixmapwidget = gtk_pixmap_new(pixmap, mask);
|
|
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox),
|
|
pixmapwidget, TRUE, TRUE, 0);
|
|
gtk_widget_show(pixmapwidget);
|
|
|
|
asprintf(&message, _("ANT (ANT is Not a Telephone) Version %s\n"
|
|
"Copyright 2002, 2003 Roland Stigge\n\n"
|
|
"This is an ISDN telephone application\n"
|
|
"written for GNU/Linux and ISDN4Linux for\n"
|
|
"communicating via a full duplex soundcard (or\n"
|
|
"multiple sound devices if you like) and an\n"
|
|
"audio capable ISDN4Linux ISDN device\n\n"
|
|
"Contact:\n"
|
|
"Roland Stigge, stigge@antcom.de\n"
|
|
"http://www.antcom.de/\n"
|
|
"Mailing list: ant-phone-devel@nongnu.org"), VERSION);
|
|
label = gtk_label_new(message);
|
|
free(message);
|
|
gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
|
|
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(window)->vbox), label,
|
|
TRUE, FALSE, 0);
|
|
gtk_misc_set_padding(GTK_MISC(label), 10, 10);
|
|
gtk_widget_show(label);
|
|
|
|
/* action area */
|
|
button_box = gtk_hbutton_box_new();
|
|
gtk_container_add(GTK_CONTAINER(GTK_DIALOG(window)->action_area),
|
|
button_box);
|
|
gtk_widget_show(button_box);
|
|
|
|
/* OK button */
|
|
button = gtk_button_new_with_label(_("OK"));
|
|
gtk_box_pack_start_defaults(GTK_BOX(button_box), button);
|
|
gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
|
|
GTK_SIGNAL_FUNC(gtk_widget_destroy),
|
|
GTK_OBJECT(window));
|
|
gtk_widget_show(button);
|
|
|
|
gtk_widget_show(window);
|
|
}
|
|
|
|
/* the about menu entry callback */
|
|
static void cb_license(GtkWidget *widget _U_, gpointer data _U_, guint action _U_) {
|
|
GtkWidget *window = ok_dialog_get(_("ANT License"),
|
|
_("ANT (ANT is Not a Telephone)\n"
|
|
"Copyright (C) 2002, 2003 Roland Stigge\n"
|
|
"\n"
|
|
"This program is free software; you can redistribute it and/or\n"
|
|
"modify it under the terms of the GNU General Public License\n"
|
|
"as published by the Free Software Foundation; either version 2\n"
|
|
"of the License, or (at your option) any later version.\n"
|
|
"\n"
|
|
"This program is distributed in the hope that it will be useful,\n"
|
|
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
|
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
|
"GNU General Public License for more details.\n"
|
|
"\n"
|
|
"You should have received a copy of the GNU General Public License\n"
|
|
"along with this program; if not, write to the Free Software\n"
|
|
"Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, "
|
|
"USA."), GTK_JUSTIFY_CENTER);
|
|
|
|
gtk_widget_show(window);
|
|
}
|
|
|
|
/*
|
|
* get the main menu widget
|
|
*
|
|
* input: window: parent window to integrate accelerators
|
|
* returns: the widget yet to pack
|
|
*
|
|
* NOTE: assumes other parts to be initialized (maybe not shown already)
|
|
*/
|
|
GtkWidget *get_main_menu(GtkWidget *window, session_t *session) {
|
|
/* The main menu structure */
|
|
GtkItemFactoryEntry main_menu_items[] = {
|
|
/*path accel. callb. cb par. kind extra */
|
|
{_("/Phon_e"), NULL, NULL, 0, "<Branch>", NULL},
|
|
{_("/Phone/_Info Window"),NULL, cb_info_window,0, NULL, NULL},
|
|
{_("/Phone/_Line Level Check"),
|
|
NULL, llcheck, 0, NULL, NULL},
|
|
{_("/Phone/"), NULL, NULL, 0, "<Separator>", NULL},
|
|
{_("/Phone/_Quit"), "<alt>X", quit, 0, NULL, NULL},
|
|
|
|
{_("/_View"), NULL, NULL, 0, "<Branch>", NULL},
|
|
{_("/View/_Caller ID Monitor"),
|
|
NULL, cid_toggle_cb, 0, "<CheckItem>", NULL},
|
|
{_("/View/_Line Level Meters"),
|
|
NULL, llcheck_toggle_cb,0, "<CheckItem>", NULL},
|
|
{_("/View/Control _Pad"), NULL, controlpad_toggle_cb,0,"<CheckItem>", NULL},
|
|
|
|
{_("/_Options"), NULL, NULL, 0, "<Branch>", NULL},
|
|
{_("/Options/_Settings"), NULL, gtksettings_cb,0, NULL, NULL},
|
|
|
|
{_("/_Help"), NULL, NULL, 0, "<LastBranch>",NULL},
|
|
{_("/Help/_About"), NULL, cb_about, 0, NULL, NULL},
|
|
{_("/Help/_License"), NULL, cb_license, 0, NULL, NULL}
|
|
/* set to session by ..._create_items_ac -^ */
|
|
};
|
|
|
|
GtkItemFactory *item_factory;
|
|
GtkAccelGroup *accel_group;
|
|
char* temp;
|
|
|
|
gint nmenu_items = sizeof(main_menu_items) / sizeof(main_menu_items[0]);
|
|
|
|
accel_group = gtk_accel_group_new();
|
|
item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>",
|
|
accel_group);
|
|
gtk_item_factory_create_items_ac(item_factory, nmenu_items, main_menu_items,
|
|
session, 2);
|
|
gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
|
|
|
|
/* save connection to menu item(s), set defaults */
|
|
session->cid_check_menu_item = gtk_item_factory_get_item(item_factory,
|
|
temp = stripchr(_("/View/_Caller ID Monitor"), '_'));
|
|
free(temp);
|
|
session->llcheck_check_menu_item = gtk_item_factory_get_item(item_factory,
|
|
temp = stripchr(_("/View/_Line Level Meters"), '_'));
|
|
free(temp);
|
|
session->controlpad_check_menu_item = gtk_item_factory_get_item(item_factory,
|
|
temp = stripchr(_("/View/Control _Pad"), '_'));
|
|
free(temp);
|
|
session->menuitem_settings = gtk_item_factory_get_item(item_factory,
|
|
temp = stripchr(_("/Options/_Settings"), '_'));
|
|
free(temp);
|
|
session->menuitem_line_check = gtk_item_factory_get_item(item_factory,
|
|
temp = stripchr(_("/Phone/_Line Level Check"), '_'));
|
|
free(temp);
|
|
gtk_check_menu_item_set_active(
|
|
GTK_CHECK_MENU_ITEM(session->cid_check_menu_item),
|
|
session->option_show_callerid);
|
|
gtk_check_menu_item_set_active(
|
|
GTK_CHECK_MENU_ITEM(session->llcheck_check_menu_item),
|
|
session->option_show_llcheck);
|
|
gtk_check_menu_item_set_active(
|
|
GTK_CHECK_MENU_ITEM(session->controlpad_check_menu_item),
|
|
session->option_show_controlpad);
|
|
|
|
return gtk_item_factory_get_widget(item_factory, "<main>");
|
|
}
|
|
|
|
/*
|
|
* called on key pressed in combo box entry
|
|
*/
|
|
static gint entry_key_cb(GtkWidget *entry, GdkEventKey *event, gpointer data) {
|
|
session_t *session = (session_t *) data;
|
|
|
|
if (event->keyval == GDK_KP_Enter) { /* catch keyboard keypad Enter */
|
|
gtk_button_clicked(GTK_BUTTON(session->pick_up_button));
|
|
/* the keyboard keypad Enter generates an unneeded character, so
|
|
discard it: */
|
|
gtk_signal_emit_stop_by_name(GTK_OBJECT(entry), "key-press-event");
|
|
return TRUE; /* event handled */
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Get the basic dial box with entry and dial / hang up buttons
|
|
* sets dial box members in session
|
|
* NOTE: caller has to gtk_widget_show it itself
|
|
*/
|
|
GtkWidget *get_dial_box(session_t *session) {
|
|
GtkWidget *frame;
|
|
GtkWidget *hbox;
|
|
GtkWidget *label;
|
|
GtkWidget *label_hbox;
|
|
GdkPixmap *pixmap;
|
|
GdkBitmap *mask;
|
|
GtkStyle *style;
|
|
GtkWidget *pixmapwid;
|
|
|
|
frame = gtk_frame_new(_("Dialing"));
|
|
gtk_container_set_border_width(GTK_CONTAINER(frame), 8);
|
|
|
|
/* dial hbox */
|
|
hbox = gtk_hbox_new(FALSE, 10);
|
|
gtk_container_add(GTK_CONTAINER(frame), hbox);
|
|
gtk_container_set_border_width(GTK_CONTAINER(hbox), 8);
|
|
gtk_widget_show(hbox);
|
|
|
|
/* dial label */
|
|
label = gtk_label_new(_("Number:"));
|
|
gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
|
|
gtk_widget_show(label);
|
|
|
|
/* dial number combo box */
|
|
session->dial_number_box = gtk_combo_new();
|
|
gtk_combo_set_popdown_strings(GTK_COMBO(session->dial_number_box),
|
|
session->dial_number_history);
|
|
gtk_combo_set_use_arrows_always(GTK_COMBO(session->dial_number_box), TRUE);
|
|
gtk_widget_set_size_request(session->dial_number_box, 180, -1);
|
|
gtk_box_pack_start(GTK_BOX(hbox), session->dial_number_box,
|
|
TRUE, TRUE, 0);
|
|
gtk_widget_show(session->dial_number_box);
|
|
gtk_signal_disconnect(GTK_OBJECT(GTK_COMBO(session->dial_number_box)->entry),
|
|
GTK_COMBO(session->dial_number_box)->activate_id);
|
|
|
|
/* pick up button */
|
|
session->pick_up_button = gtk_button_new();
|
|
gtk_box_pack_start(GTK_BOX(hbox), session->pick_up_button, FALSE, FALSE, 0);
|
|
gtk_signal_connect(GTK_OBJECT(session->pick_up_button), "clicked",
|
|
GTK_SIGNAL_FUNC(gtk_handle_pick_up_button),
|
|
(gpointer) session);
|
|
gtk_widget_show(session->pick_up_button);
|
|
|
|
/* activate dial button when pressing enter in entry widget */
|
|
gtk_signal_connect_object(GTK_OBJECT(GTK_COMBO(session->dial_number_box)
|
|
->entry),
|
|
"activate",
|
|
GTK_SIGNAL_FUNC(gtk_button_clicked),
|
|
GTK_OBJECT(session->pick_up_button));
|
|
/* handle special keys */
|
|
gtk_signal_connect(GTK_OBJECT(GTK_COMBO(session->dial_number_box)->entry),
|
|
"key-press-event", GTK_SIGNAL_FUNC(entry_key_cb), session);
|
|
|
|
/* pick up button hbox */
|
|
label_hbox = gtk_hbox_new(FALSE, 0);
|
|
gtk_container_add(GTK_CONTAINER(session->pick_up_button), label_hbox);
|
|
gtk_widget_show(label_hbox);
|
|
|
|
/* pick up button symbol */
|
|
style = gtk_widget_get_style(session->main_window);
|
|
pixmap = gdk_pixmap_create_from_xpm_d(session->main_window->window,
|
|
&mask,
|
|
&style->bg[GTK_STATE_NORMAL],
|
|
(gchar **) pickup_xpm);
|
|
|
|
pixmapwid = gtk_pixmap_new(pixmap, mask);
|
|
gtk_box_pack_start(GTK_BOX(label_hbox), pixmapwid, FALSE, FALSE, 2);
|
|
gtk_widget_show(pixmapwid);
|
|
|
|
/* pick up button label */
|
|
session->pick_up_label = gtk_label_new(NULL);
|
|
gtk_box_pack_start(GTK_BOX(label_hbox), session->pick_up_label,
|
|
TRUE, FALSE, 16); /* expand but fill up outside label */
|
|
gtk_widget_show(session->pick_up_label);
|
|
|
|
/* hang up button */
|
|
session->hang_up_button = gtk_button_new();
|
|
gtk_box_pack_start(GTK_BOX(hbox), session->hang_up_button, FALSE, FALSE, 0);
|
|
gtk_signal_connect(GTK_OBJECT(session->hang_up_button), "clicked",
|
|
GTK_SIGNAL_FUNC(gtk_handle_hang_up_button),
|
|
(gpointer) session);
|
|
gtk_widget_show(session->hang_up_button);
|
|
|
|
/* pick up button hbox */
|
|
label_hbox = gtk_hbox_new(FALSE, 0);
|
|
gtk_container_add(GTK_CONTAINER(session->hang_up_button),
|
|
label_hbox);
|
|
gtk_widget_show(label_hbox);
|
|
|
|
/* pick up button symbol*/
|
|
/* style = gtk_widget_get_style(session->main_window); */
|
|
/* (already done for pickup button) */
|
|
|
|
pixmap = gdk_pixmap_create_from_xpm_d(session->main_window->window,
|
|
&mask,
|
|
&style->bg[GTK_STATE_NORMAL],
|
|
(gchar **) hangup_xpm);
|
|
|
|
pixmapwid = gtk_pixmap_new(pixmap, mask);
|
|
gtk_box_pack_start(GTK_BOX(label_hbox), pixmapwid, FALSE, FALSE, 2);
|
|
gtk_widget_show(pixmapwid);
|
|
|
|
/* hang up button label */
|
|
session->hang_up_label = gtk_label_new(NULL);
|
|
gtk_box_pack_start(GTK_BOX(label_hbox), session->hang_up_label,
|
|
TRUE, FALSE, 16); /* expand but fill up outside label */
|
|
gtk_widget_show(session->hang_up_label);
|
|
|
|
return frame;
|
|
}
|
|
|
|
/*
|
|
* main function for gtk GUI
|
|
*
|
|
* returns int to be returned from main()
|
|
*/
|
|
int main_gtk(session_t *session) {
|
|
GList* icon_list = NULL;
|
|
|
|
GtkWidget *main_window;
|
|
GtkWidget *main_vbox;
|
|
GtkWidget *main_menu;
|
|
|
|
GtkWidget *dialbox;
|
|
GtkWidget *cidbox;
|
|
|
|
GtkWidget *dummy_label; /* needed to calculate the length of a text label */
|
|
GtkRequisition requisition;
|
|
|
|
GtkRcStyle *rc_style;
|
|
GdkColor color;
|
|
|
|
/* the main window */
|
|
session->main_window = main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
|
gtk_window_set_title(GTK_WINDOW(main_window), "ANT " VERSION);
|
|
|
|
/* seems to cause window managers only to use the first one as icon (e.g.FVWM)
|
|
icon_list = g_list_append(icon_list,
|
|
(gpointer) gdk_pixbuf_new_from_xpm_data((const char**) icon16x16));
|
|
icon_list = g_list_append(icon_list,
|
|
(gpointer) gdk_pixbuf_new_from_xpm_data((const char**) icon32x32));
|
|
*/
|
|
icon_list = g_list_append(icon_list,
|
|
(gpointer) gdk_pixbuf_new_from_xpm_data((const char**) icon48x48));
|
|
/*
|
|
icon_list = g_list_append(icon_list,
|
|
(gpointer) gdk_pixbuf_new_from_xpm_data((const char**) icon64x64));
|
|
*/
|
|
gtk_window_set_icon_list(GTK_WINDOW(session->main_window), icon_list);
|
|
|
|
gtk_signal_connect(GTK_OBJECT(main_window), "delete_event",
|
|
GTK_SIGNAL_FUNC(delete_event), (gpointer) session);
|
|
|
|
gtk_container_set_border_width(GTK_CONTAINER(main_window), 0);
|
|
gtk_widget_realize(main_window);
|
|
|
|
gtk_object_set(GTK_OBJECT(main_window), "allow_shrink", FALSE, NULL);
|
|
gtk_object_set(GTK_OBJECT(main_window), "allow_grow", TRUE, NULL);
|
|
|
|
/* set some defaults */
|
|
gtk_hbutton_box_set_spacing_default(16); /* space between buttons */
|
|
gtk_hbutton_box_set_layout_default(GTK_BUTTONBOX_SPREAD);
|
|
|
|
/* main vbox */
|
|
main_vbox = gtk_vbox_new(FALSE, 0); /* not homogeneous, spacing = 0 */
|
|
gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 0);
|
|
gtk_container_add(GTK_CONTAINER(main_window), main_vbox);
|
|
gtk_widget_show(main_vbox);
|
|
|
|
/* contents of main vbox (wrong order to let menu depend on others): */
|
|
|
|
/* the dial hbox */
|
|
dialbox = get_dial_box(session);
|
|
gtk_widget_show(dialbox);
|
|
|
|
/* key pad */
|
|
session->controlpad = controlpad_new(session); /* show later */
|
|
|
|
/* the caller id section */
|
|
cidbox = cid_new(session); /* show later */
|
|
|
|
/* status bar */
|
|
session->status_bar = gtk_statusbar_new();
|
|
gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(session->status_bar), FALSE);
|
|
gtk_widget_show(session->status_bar);
|
|
session->phone_context_id =
|
|
gtk_statusbar_get_context_id(GTK_STATUSBAR(session->status_bar), "phone");
|
|
gtk_statusbar_push(GTK_STATUSBAR(session->status_bar),
|
|
session->phone_context_id, "");
|
|
|
|
/* line level check inside status bar */
|
|
session->llcheck = gtk_vbox_new(FALSE, 0);
|
|
gtk_box_pack_end(GTK_BOX(session->status_bar),
|
|
session->llcheck, FALSE, FALSE, 0);
|
|
|
|
session->llcheck_in =
|
|
llcheck_bar_new(66, 10, 0, 200, 0);
|
|
gtk_box_pack_start(GTK_BOX(session->llcheck),
|
|
session->llcheck_in, FALSE, FALSE, 0);
|
|
gtk_widget_show(session->llcheck_in);
|
|
session->llcheck_out =
|
|
llcheck_bar_new(66, 10, 200, 0, 0);
|
|
gtk_box_pack_start(GTK_BOX(session->llcheck),
|
|
session->llcheck_out, FALSE, FALSE, 0);
|
|
gtk_widget_show(session->llcheck_out);
|
|
|
|
/* audio warning inside status bar */
|
|
session->audio_warning = gtk_statusbar_new();
|
|
gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(session->audio_warning),
|
|
FALSE);
|
|
gdk_color_parse("#B00000", &color);
|
|
rc_style = gtk_rc_style_new();
|
|
rc_style->fg[GTK_STATE_NORMAL] = color;
|
|
rc_style->color_flags[GTK_STATE_NORMAL] |= GTK_RC_FG;
|
|
gtk_widget_modify_style(GTK_STATUSBAR(session->audio_warning)->label,
|
|
rc_style);
|
|
gtk_rc_style_unref(rc_style);
|
|
gtk_box_pack_end(GTK_BOX(session->status_bar),
|
|
session->audio_warning, FALSE, FALSE, 0);
|
|
session->audio_context_id =
|
|
gtk_statusbar_get_context_id(GTK_STATUSBAR(session->audio_warning),
|
|
"audio");
|
|
gtk_statusbar_push(GTK_STATUSBAR(session->audio_warning),
|
|
session->audio_context_id, "");
|
|
/* mute warning inside status bar */
|
|
session->muted_warning = gtk_statusbar_new();
|
|
gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(session->muted_warning),
|
|
FALSE);
|
|
gdk_color_parse("#008000", &color);
|
|
rc_style = gtk_rc_style_new();
|
|
rc_style->fg[GTK_STATE_NORMAL] = color;
|
|
rc_style->color_flags[GTK_STATE_NORMAL] |= GTK_RC_FG;
|
|
gtk_widget_modify_style(GTK_STATUSBAR(session->muted_warning)->label,
|
|
rc_style);
|
|
gtk_rc_style_unref(rc_style);
|
|
gtk_box_pack_end(GTK_BOX(session->status_bar),
|
|
session->muted_warning, FALSE, FALSE, 0);
|
|
session->muted_context_id =
|
|
gtk_statusbar_get_context_id(GTK_STATUSBAR(session->muted_warning),
|
|
"muted");
|
|
gtk_statusbar_push(GTK_STATUSBAR(session->muted_warning),
|
|
session->muted_context_id, _("MUTED"));
|
|
dummy_label = gtk_label_new(_("MUTED"));
|
|
gtk_widget_show(dummy_label);
|
|
gtk_widget_size_request(dummy_label, &requisition);
|
|
gtk_widget_set_size_request(session->muted_warning,
|
|
requisition.width + 4, -1);
|
|
|
|
/* main menu bar */
|
|
main_menu = get_main_menu(main_window, session); /* main menu */
|
|
gtk_widget_show(main_menu);
|
|
|
|
/* pack items into main vbox (after main menu bar creation) */
|
|
gtk_box_pack_start(GTK_BOX(main_vbox), main_menu, FALSE, FALSE, 0);
|
|
gtk_box_pack_start(GTK_BOX(main_vbox), dialbox, FALSE, FALSE, 0);
|
|
gtk_box_pack_start(GTK_BOX(main_vbox), session->controlpad, FALSE, FALSE, 0);
|
|
gtk_box_pack_start(GTK_BOX(main_vbox), cidbox, TRUE, TRUE, 0);
|
|
gtk_box_pack_end(GTK_BOX(main_vbox), session->status_bar, FALSE, FALSE, 2);
|
|
|
|
/* show items on demand */
|
|
if (GTK_CHECK_MENU_ITEM(session->controlpad_check_menu_item)->active)
|
|
gtk_widget_show(session->controlpad);
|
|
if (GTK_CHECK_MENU_ITEM(session->cid_check_menu_item)->active)
|
|
gtk_widget_show(cidbox);
|
|
if (GTK_CHECK_MENU_ITEM(session->llcheck_check_menu_item)->active)
|
|
gtk_widget_show(session->llcheck);
|
|
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(session->mute_button)))
|
|
gtk_widget_show(session->muted_warning);
|
|
|
|
/* show everything */
|
|
gtk_widget_show(main_window);
|
|
|
|
settings_history_read(session); /* get history from home dir dotfile */
|
|
gtk_clist_freeze(GTK_CLIST(session->cid_list));
|
|
settings_callerid_read(session); /* get callerid history */
|
|
if (session->option_calls_merge)
|
|
cid_calls_merge(session); /* merge history from isdnlog */
|
|
gtk_clist_thaw(GTK_CLIST(session->cid_list));
|
|
cid_jump_to_end(session);
|
|
cid_jump_to_end(session);
|
|
|
|
/* connect isdn and sound input handlers to gdk pseudo select */
|
|
session_io_handlers_start(session);
|
|
|
|
/* set up for initial state */
|
|
session_set_state(session, STATE_READY); /* state is already in session */
|
|
|
|
/* set up additional handlers */
|
|
gtk_timeout_add(TIMER_DELAY, timeout_callback, (gpointer) session);
|
|
signal(SIGINT, &terminate_signal_callback);
|
|
signal(SIGTERM, &terminate_signal_callback);
|
|
|
|
/* gtk main loop */
|
|
gtk_main();
|
|
|
|
/* some deinit */
|
|
session_io_handlers_stop(session);
|
|
|
|
return 0;
|
|
}
|
|
|