ladish/clients/panel/panel.c

466 lines
13 KiB
C

/* LASH Control Panel
* Copyright (C) 2006 Dave Robillard <drobilla@connect.carleton.ca>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <lash/lash.h>
#include <gtk/gtk.h>
#include "panel.h"
#include "project.h"
#include "config.h"
#define WINDOW_TITLE "LASH Control Panel"
void quit_cb(GtkButton * button, void *data);
project_t *
get_project(panel_t * panel, const char *const name)
{
project_t *project = NULL;
GtkTreeModel *tree_model = GTK_TREE_MODEL(panel->projects);
GtkTreeIter iter;
if (gtk_tree_model_get_iter_first(tree_model, &iter))
do {
gtk_tree_model_get(tree_model, &iter, PROJECT_PROJECT_COLUMN,
&project, -1);
if (!strcmp(name, project->name))
return project;
} while (gtk_tree_model_iter_next(tree_model, &iter));
fprintf(stderr, "Error: Unable to find project '%s'!", name);
return NULL;
}
void
error_dialog(panel_t * client, const char *message)
{
GtkWidget *dialog;
gint response;
dialog =
gtk_message_dialog_new(GTK_WINDOW(client->window),
GTK_DIALOG_DESTROY_WITH_PARENT |
GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK, "%s", message);
response = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
void
about_cb(GtkButton* button, void* client)
{
/*panel_t* panel = (panel_t*)client;*/
GtkWidget *dialog;
gint response;
dialog = gtk_about_dialog_new();
gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(dialog), "LASH Panel");
gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), PACKAGE_VERSION);
gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(dialog),
"Copyright (C) 2006 Dave Robillard");
gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(dialog),
"http://www.nongnu.org/lash");
response = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
void
server_disconnect(panel_t * panel)
{
error_dialog(panel, "The server disconnected!");
exit(0);
}
void
event_project_add(panel_t * panel, lash_event_t * event)
{
project_t *project = NULL;
const char *name = lash_event_get_string(event);
GtkTreeIter iter;
printf("Add project: %s\n", name);
if (panel->num_projects == 0)
gtk_label_set_text(GTK_LABEL(panel->no_projects_label), "");
gtk_list_store_append(panel->projects, &iter);
project = project_create(panel->lash_client, name);
gtk_list_store_set(panel->projects, &iter,
PROJECT_PROJECT_COLUMN, project, -1);
project->page_number =
gtk_notebook_append_page(GTK_NOTEBOOK(panel->project_notebook),
project->box, project->tab_label);
panel->num_projects++;
}
void
event_project_remove(panel_t * panel, lash_event_t * event)
{
const char *name = lash_event_get_string(event);
project_t *project = get_project(panel, name);
GtkTreeModel *tree_model = GTK_TREE_MODEL(panel->projects);
GtkTreeIter iter;
printf("Remove project: %s\n", name);
if (panel->num_projects == 1)
gtk_label_set_text(GTK_LABEL(panel->no_projects_label),
"(No projects open. Start a LASH client, or load a project from the File menu)");
if (project != NULL)
if (gtk_tree_model_get_iter_first(tree_model, &iter))
do {
gtk_tree_model_get(tree_model, &iter, PROJECT_PROJECT_COLUMN,
&project, -1);
if (!strcmp(name, project->name)) {
gtk_list_store_remove(panel->projects, &iter);
gtk_notebook_remove_page(GTK_NOTEBOOK
(panel->project_notebook),
project->page_number);
project_destroy(project);
break;
}
} while (gtk_tree_model_iter_next(tree_model, &iter));
panel->num_projects--;
}
void
event_project_dir(panel_t * panel, lash_event_t * event)
{
const char *name = lash_event_get_project(event);
const char *dir = lash_event_get_string(event);
project_t *project = get_project(panel, name);
printf("Change project dir: %s = %s\n", name, dir);
if (project != NULL) {
project_set_dir(project, dir);
}
}
void
event_project_name(panel_t * panel, lash_event_t * event)
{
const char *old_name = lash_event_get_project(event);
const char *new_name = lash_event_get_string(event);
project_t *project = get_project(panel, old_name);
printf("Change project name: %s = %s\n", old_name, new_name);
if (project != NULL)
project_set_name(project, new_name);
}
void
event_client_add(panel_t * panel, lash_event_t * event)
{
const char *project_name = lash_event_get_project(event);
project_t *project = get_project(panel, project_name);
char *client_id_str = malloc(37);
char *search_id_str = NULL;
uuid_t client_id;
GtkTreeIter iter;
GtkTreeModel *tree_model;
int client_exists = FALSE;
lash_event_get_client_id(event, client_id);
uuid_unparse(client_id, client_id_str);
printf("Add client (%s): %s\n", project_name, client_id_str);
if (client_id != NULL && project != NULL) {
tree_model = GTK_TREE_MODEL(project->clients);
if (gtk_tree_model_get_iter_first(tree_model, &iter)) {
do {
gtk_tree_model_get(tree_model, &iter, CLIENT_ID_COLUMN, &search_id_str, -1);
if (!strcmp(search_id_str, client_id_str)) {
client_exists = TRUE;
break;
}
} while (gtk_tree_model_iter_next(tree_model, &iter));
}
if (!client_exists) {
gtk_list_store_append(project->clients, &iter);
gtk_list_store_set(project->clients, &iter,
CLIENT_ID_COLUMN, client_id_str, -1);
}
}
}
void
event_client_name(panel_t * panel, lash_event_t * event)
{
const char *project_name = lash_event_get_project(event);
const char *client_name = lash_event_get_string(event);
project_t *project = get_project(panel, project_name);
GtkTreeModel *tree_model = NULL;
GtkTreeIter iter;
uuid_t client_id;
char *search_id_str = NULL;
char *client_id_str = malloc(37);
lash_event_get_client_id(event, client_id);
uuid_unparse(client_id, client_id_str);
printf("Change client name (%s): %s = %s\n", project_name, client_id_str,
client_name);
if (project != NULL) {
tree_model = GTK_TREE_MODEL(project->clients);
if (gtk_tree_model_get_iter_first(tree_model, &iter))
do {
gtk_tree_model_get(tree_model, &iter, CLIENT_ID_COLUMN,
&search_id_str, -1);
if (!strcmp(search_id_str, client_id_str)) {
gtk_list_store_set(project->clients, &iter,
CLIENT_NAME_COLUMN, client_name, -1);
break;
}
} while (gtk_tree_model_iter_next(tree_model, &iter));
}
}
void
deal_with_event(panel_t * panel, lash_event_t * event)
{
switch (lash_event_get_type(event)) {
case LASH_Project_Add:
event_project_add(panel, event);
break;
case LASH_Project_Remove:
event_project_remove(panel, event);
break;
case LASH_Project_Dir:
event_project_dir(panel, event);
break;
case LASH_Project_Name:
event_project_name(panel, event);
break;
case LASH_Client_Add:
event_client_add(panel, event);
break;
case LASH_Client_Name:
event_client_name(panel, event);
break;
case LASH_Jack_Client_Name:
break;
case LASH_Alsa_Client_ID:
break;
case LASH_Percentage:
break;
default:
break;
}
}
gboolean
idle_cb(gpointer data)
{
panel_t *panel;
lash_event_t *event;
/*lash_config_t * config; */
panel = (panel_t *) data;
while ((event = lash_get_event(panel->lash_client))) {
deal_with_event(panel, event);
}
/*while ((config = lash_get_config(panel->lash_client)) ) {
* add_config(panel, config);
* } */
return TRUE;
}
void
quit_cb(GtkButton * button, void *data)
{
gtk_main_quit();
}
void
open_cb(GtkButton * button, void *data)
{
panel_t *panel = (panel_t *) data;
int response = GTK_RESPONSE_NONE;
char *filename = NULL;
lash_event_t *event = NULL;
GtkWidget *open_dialog =
gtk_file_chooser_dialog_new("Open Project", GTK_WINDOW(panel->window),
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
response = gtk_dialog_run(GTK_DIALOG(open_dialog));
if (response == GTK_RESPONSE_OK) {
filename =
gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(open_dialog));
event = lash_event_new_with_type(LASH_Project_Add);
lash_event_set_string(event, filename);
lash_send_event(panel->lash_client, event);
}
gtk_widget_destroy(open_dialog);
}
panel_t *
panel_create(lash_client_t * lash_client)
{
panel_t *panel = NULL;
GtkWidget *main_box = NULL;
GtkWidget *menu_bar = NULL;
GtkWidget *file_menu = NULL;
GtkWidget *file_menuitem = NULL;
GtkWidget *help_menu = NULL;
GtkWidget *help_menuitem = NULL;
GtkWidget *open_menu_item = NULL;
GtkWidget *menu_separator = NULL;
GtkWidget *quit_menu_item = NULL;
GtkWidget *about_menu_item = NULL;
guint status_context;
panel = lash_malloc(sizeof(panel_t));
panel->lash_client = lash_client;
panel->projects = gtk_list_store_new(PROJECT_NUM_COLUMNS, G_TYPE_POINTER);
panel->num_projects = 0;
panel->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(panel->window), WINDOW_TITLE);
gtk_window_set_default_size(GTK_WINDOW(panel->window), 450, 282);
g_signal_connect(G_OBJECT(panel->window), "delete_event",
G_CALLBACK(quit_cb), NULL);
main_box = gtk_vbox_new(FALSE, 0);
gtk_widget_show(main_box);
gtk_container_add(GTK_CONTAINER(panel->window), main_box);
/*
* menu bar
*/
file_menu = gtk_menu_new();
open_menu_item = gtk_image_menu_item_new_with_label("Open Project...");
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(open_menu_item),
gtk_image_new_from_stock(GTK_STOCK_OPEN,
GTK_ICON_SIZE_MENU));
gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), open_menu_item);
g_signal_connect(G_OBJECT(open_menu_item), "activate",
G_CALLBACK(open_cb), panel);
gtk_widget_show(open_menu_item);
menu_separator = gtk_separator_menu_item_new();
gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), menu_separator);
gtk_widget_show(menu_separator);
quit_menu_item = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL);
gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), quit_menu_item);
g_signal_connect(G_OBJECT(quit_menu_item), "activate",
G_CALLBACK(quit_cb), panel);
gtk_widget_show(quit_menu_item);
file_menuitem = gtk_menu_item_new_with_label("File");
gtk_widget_show(file_menuitem);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(file_menuitem), file_menu);
help_menu = gtk_menu_new();
help_menuitem = gtk_menu_item_new_with_label("Help");
gtk_widget_show(help_menuitem);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(help_menuitem), help_menu);
about_menu_item = gtk_image_menu_item_new_with_label("About...");
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(about_menu_item),
gtk_image_new_from_stock(GTK_STOCK_ABOUT,
GTK_ICON_SIZE_MENU));
gtk_menu_shell_append(GTK_MENU_SHELL(help_menu), about_menu_item);
g_signal_connect(G_OBJECT(about_menu_item), "activate",
G_CALLBACK(about_cb), panel);
gtk_widget_show(about_menu_item);
menu_bar = gtk_menu_bar_new();
gtk_widget_show(menu_bar);
gtk_box_pack_start(GTK_BOX(main_box), menu_bar, FALSE, TRUE, 0);
gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), file_menuitem);
gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), help_menuitem);
/*
* projects notebook
*/
panel->project_notebook = gtk_notebook_new();
gtk_notebook_set_tab_pos(GTK_NOTEBOOK(panel->project_notebook),
GTK_POS_TOP);
gtk_widget_show(panel->project_notebook);
gtk_box_pack_start(GTK_BOX(main_box), panel->project_notebook, TRUE, TRUE, 0);
/*
* "no project" label (shown instead of a notebook tab when no projects are present)
*/
panel->no_projects_label = gtk_label_new("No projects open. Start a LASH client, or load a project from the File menu.");
gtk_widget_show(panel->no_projects_label);
gtk_box_pack_start(GTK_BOX(main_box), panel->no_projects_label, FALSE, TRUE, 10);
/*
* status bar
*/
panel->status_bar = gtk_statusbar_new();
gtk_widget_show(panel->status_bar);
status_context =
gtk_statusbar_get_context_id(GTK_STATUSBAR(panel->status_bar),
"connected");
gtk_statusbar_push(GTK_STATUSBAR(panel->status_bar), status_context,
g_strdup_printf("Connected to server %s",
lash_get_server_name(lash_client)));
gtk_box_pack_start(GTK_BOX(main_box), panel->status_bar, FALSE, TRUE, 0);
gtk_timeout_add(1000, idle_cb, panel);
gtk_widget_show(panel->window);
return panel;
}