New joystick plugin
Mark Pustjens <[email protected]> Thu, 20 Jan 2005 16:44:50 +0100 (CET)
| Newsgroups | gmane.comp.multimedia.xmms.devel |
|---|---|
| Message-ID | <[email protected]> |
Hello everyone I have completely rewritten the joystick plugin. The most changes to the origional plugin are: - support for more axes (autodetected) - adds a few new commands. - some commands now accept values (eg. vol-up, 5%) - key-down and key-up sensitivity adjustable. - key-down and key-up detection uses a hysteresis - new interface A screenshot of the new interface: http://unkie.org/e107_files/imagegallery/8-Public%20Upload/20-01-2005-xmms2.png The new files are attached to this message. Place them in the joystick plugin folder and compile. This plugin still has a few bugs, but i don't know how to use gdb so finding them is really difficult. If you can, please try this patch and comment on it. Also, if any of you know a good gdb tutorial, let me know. greetings -- Racism was not a problem on the Discworld, because -- what with trolls and dwarfs and so on -- speciesism was more interesting. Black and white lived in perfect harmony and ganged up on green. (Witches Abroad) _______________________________________________ xmms-devel mailing list [email protected] http://lists.xmms.org/mailman/listinfo/xmms-devel
configure.c
(text/plain, 28.7 KB)
/* Joystick plugin for xmms by Tim Ferguson ([email protected] * http://www.dgs.monash.edu.au/~timf/) ... * 14/12/2000 - patched to allow 5 or more buttons to be used (Justin Wake <[email protected]>) * * 20/01/2004 - complete rewrite by Mark Pustjens <[email protected]> * * XMMS is Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies * * 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. */ #include "xmms/i18n.h" #include "joy.h" #include "string.h" /* all widgets associated with an entry field */ typedef struct joyconf_entry { GtkWidget *entry, *spin, *boolean, *boolean_option, *toggle, *toggle_option; } joyconf_entry; /* things we need to remember */ static GtkWidget *joyconf_window, *joy_frame_general, *joy_frame_buttons, *joy_frame_axes, *joy_joystick, *joy_general_device, *joy_general_sensitivity_up, *joy_general_sensitivity_down, *joy_detected_btns, *joy_detected_axes, *joy_button, *joy_button_action_option, *joy_button_action, *joy_axis, *joy_axis_action_neg_option, *joy_axis_action_pos_option, *joy_axis_action_neg, *joy_axis_action_pos; static joyconf_entry joy_button_value, joy_axis_value_neg, joy_axis_value_pos; static joy_config cfg_joysticks[JOY_MAX_JOYSTICKS]; static int cfg_cur_js, cfg_cur_button, cfg_cur_axis; /* function prototypes */ static void joyconf_ok_button(GtkWidget *w, gpointer data); static void joyconf_cancel_button(GtkWidget *w, gpointer data); static void joyconf_apply_button(GtkWidget *w, gpointer data); static void joyconf_changed_joystick(GtkWidget *w, gpointer data); static void joyconf_changed_device(GtkWidget *w, gpointer data); static void joyconf_changed_button(GtkWidget *w, gpointer data); static void joyconf_changed_axis(GtkWidget *w, gpointer data); static void joyconf_changed_button_action(GtkWidget *w, gpointer data); static void joyconf_changed_axis_neg_action(GtkWidget *w, gpointer data); static void joyconf_changed_axis_pos_action(GtkWidget *w, gpointer data); static void joyconf_changed_general_sensitivity_down(GtkWidget *w, gpointer data); static void joyconf_changed_general_sensitivity_up(GtkWidget *w, gpointer data); static void joyconf_changed_button_value(GtkWidget *w, gpointer data); static void joyconf_changed_axis_value_neg(GtkWidget *w, gpointer data); static void joyconf_changed_axis_value_pos(GtkWidget *w, gpointer data); static void joyconf_changed_boolean(GtkWidget *w, gpointer data); static void joyconf_changed_toggle(GtkWidget *w, gpointer data); static void joyconf_changed_spin(GtkWidget *w, gpointer data); static void joyconf_create_button_menu(int buttons); static void joyconf_create_axis_menu(int axes); static GtkWidget* joyconf_create_actions_menu(GtkWidget *option, GtkSignalFunc func, GtkWidget *entry); static GtkWidget* joyconf_create_toggle_menu(GtkWidget *option, GtkSignalFunc func, joyconf_entry *entry); static GtkWidget* joyconf_create_boolean_menu(GtkWidget *option, GtkSignalFunc func, joyconf_entry *entry); static GtkWidget* joyconf_create_spin_button(GtkSignalFunc func, joyconf_entry *entry); static int joyconf_get_menu_data(GtkWidget *w, gchar *key); static void joy_configure_table_default(GtkWidget *table); static void joy_configure_table_add_row(GtkTable *table, int row, const gchar *label_text, GtkWidget *widget); static void joyconf_setup_action_value_entry(int cmd, joyconf_entry *entry); void joy_configure(void); /**************************************************************/ /* if the ok button is pressed */ static void joyconf_ok_button(GtkWidget * w, gpointer data) { joyconf_apply_button(NULL, NULL); joyconf_cancel_button(NULL, NULL); } /* if the cancel button is pressed */ static void joyconf_cancel_button(GtkWidget *w, gpointer data) { gtk_widget_destroy(joyconf_window); } /* when the apply button is pressed */ static void joyconf_apply_button(GtkWidget *w, gpointer data) { joy_save_config(cfg_joysticks); joy_update_config(); } /**************************************************************/ /* when a different joystick is chosen */ static void joyconf_changed_joystick(GtkWidget *w, gpointer data) { gchar *sens; cfg_cur_js = joyconf_get_menu_data(joy_joystick, "joystick"); gtk_entry_set_text(GTK_ENTRY(joy_general_device), cfg_joysticks[cfg_cur_js].device); sens = g_strdup_printf("%i", cfg_joysticks[cfg_cur_js].sensitivity_down); gtk_entry_set_text(GTK_ENTRY(joy_general_sensitivity_down), sens); g_free(sens); sens = g_strdup_printf("%i", cfg_joysticks[cfg_cur_js].sensitivity_up); gtk_entry_set_text(GTK_ENTRY(joy_general_sensitivity_up), sens); g_free(sens); gtk_signal_emit_by_name(GTK_OBJECT(joy_general_device), "changed"); } /* when the device is changed */ static void joyconf_changed_device(GtkWidget *w, gpointer data) { gchar *device, *num; gboolean joy_ok; device = gtk_editable_get_chars(GTK_EDITABLE(joy_general_device), 0, -1); cfg_joysticks[cfg_cur_js].device = g_strdup(device); if (strlen(device)) { joy_ok = joy_detect_capabilities(&cfg_joysticks[cfg_cur_js]); if (!joy_ok) { gtk_object_set(GTK_OBJECT(joy_general_sensitivity_down), "sensitive", FALSE, NULL); gtk_object_set(GTK_OBJECT(joy_general_sensitivity_up), "sensitive", FALSE, NULL); } else { gtk_object_set(GTK_OBJECT(joy_general_sensitivity_down), "sensitive", TRUE, NULL); gtk_object_set(GTK_OBJECT(joy_general_sensitivity_up), "sensitive", TRUE, NULL); } joyconf_create_button_menu(cfg_joysticks[cfg_cur_js].num_btns); joyconf_create_axis_menu(cfg_joysticks[cfg_cur_js].num_axes); if (joy_ok && cfg_joysticks[cfg_cur_js].num_btns) { num = g_strdup_printf("%i", cfg_joysticks[cfg_cur_js].num_btns); gtk_label_set_text(GTK_LABEL(joy_detected_btns), num); g_free(num); gtk_object_set(GTK_OBJECT(joy_frame_buttons), "sensitive", TRUE, NULL); } else { gtk_label_set_text(GTK_LABEL(joy_detected_btns), "-"); gtk_object_set(GTK_OBJECT(joy_frame_buttons), "sensitive", FALSE, NULL); } if (joy_ok && cfg_joysticks[cfg_cur_js].num_axes) { num = g_strdup_printf("%i", cfg_joysticks[cfg_cur_js].num_axes); gtk_label_set_text(GTK_LABEL(joy_detected_axes), num); g_free(num); gtk_object_set(GTK_OBJECT(joy_frame_axes), "sensitive", TRUE, NULL); } else { gtk_label_set_text(GTK_LABEL(joy_detected_axes), "-"); gtk_object_set(GTK_OBJECT(joy_frame_axes), "sensitive", FALSE, NULL); } } g_free(device); } /* when a different button to edit is chosen */ static void joyconf_changed_button(GtkWidget *w, gpointer data) { int cmd; cfg_cur_button = joyconf_get_menu_data(w, "button"); cmd = cfg_joysticks[cfg_cur_js].btns[cfg_cur_button].cmd; gtk_option_menu_set_history(GTK_OPTION_MENU(joy_button_action_option), joy_cmd_to_index(cmd)); gtk_signal_emit_by_name(GTK_OBJECT(joy_button_action), "deactivate"); } /* when a different axis to edit is chosen */ static void joyconf_changed_axis(GtkWidget *w, gpointer data) { int cmd; cfg_cur_axis = joyconf_get_menu_data(w, "axis"); cmd = cfg_joysticks[cfg_cur_js].axes[cfg_cur_axis].minus_cmd; gtk_option_menu_set_history(GTK_OPTION_MENU(joy_axis_action_neg_option), joy_cmd_to_index(cmd)); cmd = cfg_joysticks[cfg_cur_js].axes[cfg_cur_axis].plus_cmd; gtk_option_menu_set_history(GTK_OPTION_MENU(joy_axis_action_pos_option), joy_cmd_to_index(cmd)); gtk_signal_emit_by_name(GTK_OBJECT(joy_axis_action_neg), "deactivate"); gtk_signal_emit_by_name(GTK_OBJECT(joy_axis_action_pos), "deactivate"); } /* */ static void joyconf_changed_button_action(GtkWidget *w, gpointer data) { int cmd; cmd = joyconf_get_menu_data(w, "cmd"); cfg_joysticks[cfg_cur_js].btns[cfg_cur_button].cmd = cmd; joyconf_setup_action_value_entry(cmd, data); } /* */ static void joyconf_changed_axis_neg_action(GtkWidget *w, gpointer data) { int cmd; cmd = joyconf_get_menu_data(w, "cmd"); cfg_joysticks[cfg_cur_js].axes[cfg_cur_axis].minus_cmd = cmd; joyconf_setup_action_value_entry(cmd, data); } /* */ static void joyconf_changed_axis_pos_action(GtkWidget *w, gpointer data) { int cmd; cmd = joyconf_get_menu_data(w, "cmd"); cfg_joysticks[cfg_cur_js].axes[cfg_cur_axis].plus_cmd = cmd; joyconf_setup_action_value_entry(cmd, data); } /* */ static void joyconf_changed_general_sensitivity_down(GtkWidget *w, gpointer data) { gchar *sens; sens = gtk_editable_get_chars(GTK_EDITABLE(joy_general_sensitivity_down), 0, -1); cfg_joysticks[cfg_cur_js].sensitivity_down = atoi(sens); g_free(sens); } /* */ static void joyconf_changed_general_sensitivity_up(GtkWidget *w, gpointer data) { gchar *sens; sens = gtk_editable_get_chars(GTK_EDITABLE(joy_general_sensitivity_up), 0, -1); cfg_joysticks[cfg_cur_js].sensitivity_up = atoi(sens); g_free(sens); } static void joyconf_changed_button_value(GtkWidget *w, gpointer data) { gchar *s; joyconf_entry *entry = data; int i; s = gtk_editable_get_chars(GTK_EDITABLE(entry->entry), 0, -1); i = atoi(s); cfg_joysticks[cfg_cur_js].btns[cfg_cur_button].cmd_value = i; g_free(s); gtk_option_menu_set_history(GTK_OPTION_MENU(entry->boolean_option), i); gtk_option_menu_set_history(GTK_OPTION_MENU(entry->toggle_option), i+1); } static void joyconf_changed_axis_value_neg(GtkWidget *w, gpointer data) { gchar *value; joyconf_entry *entry = data; value = gtk_editable_get_chars(GTK_EDITABLE(entry->entry), 0, -1); cfg_joysticks[cfg_cur_js].axes[cfg_cur_axis].minus_cmd_value = atoi(value); g_free(value); } static void joyconf_changed_axis_value_pos(GtkWidget *w, gpointer data) { gchar *value; joyconf_entry *entry = data; value = gtk_editable_get_chars(GTK_EDITABLE(entry->entry), 0, -1); cfg_joysticks[cfg_cur_js].axes[cfg_cur_axis].plus_cmd_value = atoi(value); g_free(value); } static void joyconf_changed_boolean(GtkWidget *w, gpointer data) { int v; gchar *s; joyconf_entry *entry = data; v = joyconf_get_menu_data(entry->boolean, "value"); s = g_strdup_printf("%i", v); gtk_entry_set_text(GTK_ENTRY(entry->entry), s); g_free(s); } static void joyconf_changed_toggle(GtkWidget *w, gpointer data) { int v; gchar *s; joyconf_entry *entry = data; v = joyconf_get_menu_data(entry->toggle, "value"); s = g_strdup_printf("%i", v); gtk_entry_set_text(GTK_ENTRY(entry->entry), s); g_free(s); } static void joyconf_changed_spin(GtkWidget *w, gpointer data) { int v; gchar *s; joyconf_entry *entry = data; v = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(entry->spin)); s = g_strdup_printf("%i", v); gtk_entry_set_text(GTK_ENTRY(entry->entry), s); g_free(s); } /**************************************************************/ /* create a button selection menu */ static void joyconf_create_button_menu(int buttons) { int i; GtkWidget *menu, *item; menu = gtk_menu_new(); for (i = 0; i < buttons; i++) { item = gtk_menu_item_new_with_label(g_strdup_printf(_("Button %i"), i+1)); gtk_object_set_data(GTK_OBJECT(item), "button", (gpointer)i); gtk_widget_show(item); gtk_menu_append(GTK_MENU(menu), item); } if (!buttons){ item = gtk_menu_item_new_with_label(_("-")); gtk_widget_show(item); gtk_menu_append(GTK_MENU(menu), item); } gtk_option_menu_remove_menu(GTK_OPTION_MENU(joy_button)); gtk_option_menu_set_menu(GTK_OPTION_MENU(joy_button), menu); gtk_signal_connect(GTK_OBJECT(menu), "deactivate", GTK_SIGNAL_FUNC(joyconf_changed_button), NULL); gtk_signal_emit_by_name(GTK_OBJECT(menu), "deactivate"); } /* create an axis selection menu */ static void joyconf_create_axis_menu(int axes) { int i; GtkWidget *menu, *item; menu = gtk_menu_new(); for (i = 0; i < axes; i++) { item = gtk_menu_item_new_with_label(g_strdup_printf(_("Axis %i"), i+1)); gtk_object_set_data(GTK_OBJECT(item), "axis", (gpointer)i); gtk_widget_show(item); gtk_menu_append(GTK_MENU(menu), item); } if (!axes){ item = gtk_menu_item_new_with_label(_("-")); gtk_widget_show(item); gtk_menu_append(GTK_MENU(menu), item); } gtk_option_menu_remove_menu(GTK_OPTION_MENU(joy_axis)); gtk_option_menu_set_menu(GTK_OPTION_MENU(joy_axis), menu); gtk_signal_connect(GTK_OBJECT(menu), "deactivate", GTK_SIGNAL_FUNC(joyconf_changed_axis), NULL); gtk_signal_emit_by_name(GTK_OBJECT(menu), "deactivate"); } /* create a menu with all possible actions */ static GtkWidget* joyconf_create_actions_menu(GtkWidget *option, GtkSignalFunc func, GtkWidget *entry) { int i = 0; GtkWidget *menu, *item; menu = gtk_menu_new(); i = 0; while (joy_commands[i].name) { item = gtk_menu_item_new_with_label(_(joy_commands[i].name)); gtk_object_set_data(GTK_OBJECT(item), "cmd", (gpointer)joy_commands[i].cmd); gtk_widget_show(item); gtk_menu_append(GTK_MENU(menu), item); i++; } gtk_option_menu_set_menu(GTK_OPTION_MENU(option), menu); gtk_signal_connect(GTK_OBJECT(menu), "deactivate", func, entry); return menu; } static GtkWidget* joyconf_create_boolean_menu(GtkWidget *option, GtkSignalFunc func, joyconf_entry *entry) { GtkWidget *menu, *item; menu = gtk_menu_new(); item = gtk_menu_item_new_with_label(_("off")); gtk_object_set_data(GTK_OBJECT(item), "value", (gpointer)0); gtk_widget_show(item); gtk_menu_append(GTK_MENU(menu), item); item = gtk_menu_item_new_with_label(_("on")); gtk_object_set_data(GTK_OBJECT(item), "value", (gpointer)1); gtk_widget_show(item); gtk_menu_append(GTK_MENU(menu), item); gtk_option_menu_set_menu(GTK_OPTION_MENU(option), menu); gtk_signal_connect(GTK_OBJECT(menu), "deactivate", func, entry); return menu; } static GtkWidget* joyconf_create_toggle_menu(GtkWidget *option, GtkSignalFunc func, joyconf_entry *entry) { GtkWidget *menu, *item; menu = gtk_menu_new(); item = gtk_menu_item_new_with_label(_("off")); gtk_object_set_data(GTK_OBJECT(item), "value", (gpointer)-1); gtk_widget_show(item); gtk_menu_append(GTK_MENU(menu), item); item = gtk_menu_item_new_with_label(_("toggle")); gtk_object_set_data(GTK_OBJECT(item), "value", (gpointer)0); gtk_widget_show(item); gtk_menu_append(GTK_MENU(menu), item); item = gtk_menu_item_new_with_label(_("on")); gtk_object_set_data(GTK_OBJECT(item), "value", (gpointer)1); gtk_widget_show(item); gtk_menu_append(GTK_MENU(menu), item); gtk_option_menu_set_menu(GTK_OPTION_MENU(option), menu); gtk_signal_connect(GTK_OBJECT(menu), "deactivate", func, entry); return menu; } static GtkWidget* joyconf_create_spin_button(GtkSignalFunc func, joyconf_entry *entry) { GtkWidget *spin; GtkAdjustment *adj; adj = (GtkAdjustment *)gtk_adjustment_new(0, 0, 100, 1, 5, 1); spin = gtk_spin_button_new(adj, 1, 0); gtk_widget_show(spin); return spin; } /**************************************************************/ /* get the data of a specific menu's activated item */ static int joyconf_get_menu_data(GtkWidget *w, gchar *key) { return (gint)gtk_object_get_data(GTK_OBJECT(gtk_menu_get_active(GTK_MENU(w))), key); } /* setup a table with default settings */ static void joy_configure_table_default(GtkWidget *table) { gtk_container_border_width(GTK_CONTAINER(table), 5); gtk_table_set_row_spacings(GTK_TABLE(table), 5); gtk_table_set_col_spacings(GTK_TABLE(table), 5); } /* add a new row to a table */ static void joy_configure_table_add_row(GtkTable *table, int row, const gchar *label_text, GtkWidget *widget) { GtkWidget *label; label = gtk_label_new(_(label_text)); gtk_table_attach_defaults(table, label, 0, 1, row, row + 1); gtk_table_attach_defaults(table, widget, 1, 2, row, row + 1); gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); gtk_widget_show(label); gtk_widget_show(widget); } /* setup the entry widget of an action selection menu */ static void joyconf_setup_action_value_entry(int cmd, joyconf_entry *entry) { int argtype; argtype = joy_cmd_has_args(cmd); switch (argtype) { case JOY_ARG_NONE: gtk_object_set(GTK_OBJECT(entry->entry), "visible", TRUE, "sensitive", FALSE, NULL); gtk_object_set(GTK_OBJECT(entry->spin), "visible", FALSE, NULL); gtk_object_set(GTK_OBJECT(entry->boolean_option), "visible", FALSE, NULL); gtk_object_set(GTK_OBJECT(entry->toggle_option), "visible", FALSE, NULL); gtk_entry_set_text(GTK_ENTRY(entry->entry), ""); break; case JOY_ARG_INT: gtk_object_set(GTK_OBJECT(entry->entry), "visible", FALSE, "sensitive", FALSE, NULL); gtk_object_set(GTK_OBJECT(entry->spin), "visible", TRUE, NULL); gtk_object_set(GTK_OBJECT(entry->boolean_option), "visible", FALSE, NULL); gtk_object_set(GTK_OBJECT(entry->toggle_option), "visible", FALSE, NULL); break; case JOY_ARG_BOOLEAN: gtk_object_set(GTK_OBJECT(entry->entry), "visible", FALSE, "sensitive", FALSE, NULL); gtk_object_set(GTK_OBJECT(entry->spin), "visible", FALSE, NULL); gtk_object_set(GTK_OBJECT(entry->boolean_option), "visible", TRUE, NULL); gtk_object_set(GTK_OBJECT(entry->toggle_option), "visible", FALSE, NULL); break; case JOY_ARG_TOGGLE: gtk_object_set(GTK_OBJECT(entry->entry), "visible", FALSE, "sensitive", FALSE, NULL); gtk_object_set(GTK_OBJECT(entry->spin), "visible", FALSE, NULL); gtk_object_set(GTK_OBJECT(entry->boolean_option), "visible", FALSE, NULL); gtk_object_set(GTK_OBJECT(entry->toggle_option), "visible", TRUE, NULL); break; } if (argtype != JOY_ARG_NONE) { gchar *value; value = g_strdup_printf("%i", cfg_joysticks[cfg_cur_js].btns[cfg_cur_button].cmd_value); gtk_entry_set_text(GTK_ENTRY(entry->entry), value); g_free(value); gtk_signal_emit_by_name(GTK_OBJECT(entry->entry), "changed"); } } /**************************************************************/ /* the configuration window */ void joy_configure(void) { joy_read_config(cfg_joysticks); if (!joyconf_window) { GtkWidget *joyconf_container, *box, *button, *table, *frame, *item, *menu, *option, *entry, *spin; int i; gchar *s; /* create the window with container */ joyconf_window = gtk_window_new(GTK_WINDOW_DIALOG); gtk_signal_connect(GTK_OBJECT(joyconf_window), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &joyconf_window); gtk_window_set_title(GTK_WINDOW(joyconf_window), _("XMMS Joystick Configuration")); gtk_window_set_policy(GTK_WINDOW(joyconf_window), FALSE, FALSE, FALSE); joyconf_container = gtk_vbox_new(FALSE, 10); gtk_container_border_width(GTK_CONTAINER(joyconf_container), 10); gtk_container_add(GTK_CONTAINER(joyconf_window), joyconf_container); /* the joystick selection box */ frame = gtk_frame_new(_("Joystick:")); gtk_container_add(GTK_CONTAINER(joyconf_container), frame); gtk_widget_show(frame); table = gtk_table_new(1, 2, FALSE); joy_configure_table_default(table); gtk_container_add(GTK_CONTAINER(frame), table); gtk_widget_show(table); menu = gtk_option_menu_new(); joy_joystick = gtk_menu_new(); for (i = 0; i < JOY_MAX_JOYSTICKS; i++) { s = g_strdup_printf(_("Joystick %i"), i); item = gtk_menu_item_new_with_label(s); gtk_object_set_data(GTK_OBJECT(item), "joystick", (gpointer)i); gtk_widget_show(item); gtk_menu_append(GTK_MENU(joy_joystick), item); g_free(s); } gtk_option_menu_set_menu(GTK_OPTION_MENU(menu), joy_joystick); gtk_signal_connect(GTK_OBJECT(joy_joystick), "deactivate", GTK_SIGNAL_FUNC(joyconf_changed_joystick), NULL); joy_configure_table_add_row(GTK_TABLE(table), 0, _("Choose joystick"), menu); /* the joystick configuration box */ joy_frame_general = gtk_frame_new(_("General joystick configuration:")); gtk_container_add(GTK_CONTAINER(joyconf_container), joy_frame_general); gtk_widget_show(joy_frame_general); table = gtk_table_new(3, 2, FALSE); joy_configure_table_default(table); gtk_container_add(GTK_CONTAINER(joy_frame_general), table); gtk_widget_show(table); joy_general_device = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(joy_general_device), 20); gtk_signal_connect(GTK_OBJECT(joy_general_device), "changed", GTK_SIGNAL_FUNC(joyconf_changed_device), NULL); joy_configure_table_add_row(GTK_TABLE(table), 0, _("Device"), joy_general_device); joy_general_sensitivity_down = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(joy_general_sensitivity_down), 5); gtk_signal_connect(GTK_OBJECT(joy_general_sensitivity_down), "changed", GTK_SIGNAL_FUNC(joyconf_changed_general_sensitivity_down), NULL); joy_configure_table_add_row(GTK_TABLE(table), 1, _("Key-down sensitivity"), joy_general_sensitivity_down); joy_general_sensitivity_up = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(joy_general_sensitivity_up), 5); gtk_signal_connect(GTK_OBJECT(joy_general_sensitivity_up), "changed", GTK_SIGNAL_FUNC(joyconf_changed_general_sensitivity_up), NULL); joy_configure_table_add_row(GTK_TABLE(table), 2, _("Key-up sensitivity"), joy_general_sensitivity_up); /* the button configuration box */ joy_frame_buttons = gtk_frame_new(_("Button configuration:")); gtk_container_add(GTK_CONTAINER(joyconf_container), joy_frame_buttons); gtk_widget_show(joy_frame_buttons); table = gtk_table_new(6, 2, FALSE); joy_configure_table_default(table); gtk_container_add(GTK_CONTAINER(joy_frame_buttons), table); gtk_widget_show(table); joy_detected_btns = gtk_label_new("-"); joy_configure_table_add_row(GTK_TABLE(table), 0, _("Buttons detected"), joy_detected_btns); joy_button = gtk_option_menu_new(); joy_configure_table_add_row(GTK_TABLE(table), 1, _("Choose button"), joy_button); entry = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(entry), 3); gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(joyconf_changed_button_value), &joy_button_value); joy_configure_table_add_row(GTK_TABLE(table), 3, _("Value"), entry); joy_button_value.entry = entry; spin = joyconf_create_spin_button(joyconf_changed_spin, &joy_button_value); gtk_table_attach_defaults(GTK_TABLE(table), spin, 1, 2, 3, 4); joy_button_value.spin = spin; option = gtk_option_menu_new(); menu = joyconf_create_boolean_menu(option, joyconf_changed_boolean, &joy_button_value); gtk_widget_show(option); gtk_table_attach_defaults(GTK_TABLE(table), option, 1, 2, 3, 4); joy_button_value.boolean = menu; joy_button_value.boolean_option = option; option = gtk_option_menu_new(); menu = joyconf_create_toggle_menu(option, joyconf_changed_toggle, &joy_button_value); gtk_widget_show(option); gtk_table_attach_defaults(GTK_TABLE(table), option, 1, 2, 3, 4); joy_button_value.toggle = menu; joy_button_value.toggle_option = option; joy_button_action_option = gtk_option_menu_new(); joy_button_action = joyconf_create_actions_menu(joy_button_action_option, GTK_SIGNAL_FUNC(joyconf_changed_button_action), (gpointer)&joy_button_value); joy_configure_table_add_row(GTK_TABLE(table), 2, _("Action"), joy_button_action_option); /* the axis configuration box */ joy_frame_axes = gtk_frame_new(_("Axis configuration:")); gtk_container_add(GTK_CONTAINER(joyconf_container), joy_frame_axes); gtk_widget_show(joy_frame_axes); table = gtk_table_new(6, 2, FALSE); joy_configure_table_default(table); gtk_container_add(GTK_CONTAINER(joy_frame_axes), table); gtk_widget_show(table); joy_detected_axes = gtk_label_new("-"); joy_configure_table_add_row(GTK_TABLE(table), 0, _("Axes detected"), joy_detected_axes); joy_axis = gtk_option_menu_new(); joy_configure_table_add_row(GTK_TABLE(table), 1, _("Choose axis"), joy_axis); entry = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(entry), 3); gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(joyconf_changed_axis_value_neg), &joy_axis_value_neg); joy_configure_table_add_row(GTK_TABLE(table), 3, _("Value"), entry); joy_axis_value_neg.entry = entry; spin = joyconf_create_spin_button(joyconf_changed_spin, &joy_axis_value_neg); gtk_table_attach_defaults(GTK_TABLE(table), spin, 1, 2, 3, 4); joy_axis_value_neg.spin = spin; option = gtk_option_menu_new(); menu = joyconf_create_boolean_menu(option, joyconf_changed_boolean, &joy_axis_value_neg); gtk_widget_show(option); gtk_table_attach_defaults(GTK_TABLE(table), option, 1, 2, 3, 4); joy_axis_value_neg.boolean = menu; joy_axis_value_neg.boolean_option = option; option = gtk_option_menu_new(); menu = joyconf_create_toggle_menu(option, joyconf_changed_toggle, &joy_axis_value_neg); gtk_widget_show(option); gtk_table_attach_defaults(GTK_TABLE(table), option, 1, 2, 3, 4); joy_axis_value_neg.toggle = menu; joy_axis_value_neg.toggle_option = option; joy_axis_action_neg_option = gtk_option_menu_new(); joy_axis_action_neg = joyconf_create_actions_menu(joy_axis_action_neg_option, GTK_SIGNAL_FUNC(joyconf_changed_axis_neg_action), (gpointer)&joy_axis_value_neg); joy_configure_table_add_row(GTK_TABLE(table), 2, _("Action for negative values"), joy_axis_action_neg_option); entry = gtk_entry_new(); gtk_entry_set_max_length(GTK_ENTRY(entry), 3); gtk_signal_connect(GTK_OBJECT(entry), "changed", GTK_SIGNAL_FUNC(joyconf_changed_axis_value_pos), &joy_axis_value_pos); joy_configure_table_add_row(GTK_TABLE(table), 5, _("Value"), entry); joy_axis_value_pos.entry = entry; spin = joyconf_create_spin_button(joyconf_changed_spin, &joy_axis_value_pos); gtk_table_attach_defaults(GTK_TABLE(table), spin, 1, 2, 5, 6); joy_axis_value_pos.spin = spin; option = gtk_option_menu_new(); menu = joyconf_create_boolean_menu(option, joyconf_changed_boolean, &joy_axis_value_pos); gtk_widget_show(option); gtk_table_attach_defaults(GTK_TABLE(table), option, 1, 2, 5, 6); joy_axis_value_pos.boolean = menu; joy_axis_value_pos.boolean_option = option; option = gtk_option_menu_new(); menu = joyconf_create_toggle_menu(option, joyconf_changed_toggle, &joy_axis_value_pos); gtk_widget_show(option); gtk_table_attach_defaults(GTK_TABLE(table), option, 1, 2, 5, 6); joy_axis_value_pos.toggle = menu; joy_axis_value_pos.toggle_option = option; joy_axis_action_pos_option = gtk_option_menu_new(); joy_axis_action_pos = joyconf_create_actions_menu(joy_axis_action_pos_option, GTK_SIGNAL_FUNC(joyconf_changed_axis_pos_action), (gpointer)&joy_axis_value_pos); joy_configure_table_add_row(GTK_TABLE(table), 4, _("Action for positive values"), joy_axis_action_pos_option); /* ok, cancel, apply */ box = gtk_hbutton_box_new(); gtk_container_add(GTK_CONTAINER(joyconf_container), box); gtk_widget_show(box); button = gtk_button_new_with_label(_("Ok")); GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); gtk_widget_grab_default(button); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(joyconf_ok_button), NULL); gtk_box_pack_start(GTK_BOX(box), button, TRUE, TRUE, 0); gtk_widget_show(button); button = gtk_button_new_with_label(_("Cancel")); GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(joyconf_cancel_button), NULL); gtk_box_pack_start(GTK_BOX(box), button, TRUE, TRUE, 0); gtk_widget_show(button); button = gtk_button_new_with_label(_("Apply")); GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(joyconf_apply_button), NULL); gtk_box_pack_start(GTK_BOX(box), button, TRUE, TRUE, 0); gtk_widget_show(button); /* show the window - finally*/ gtk_widget_show(joyconf_window); gtk_widget_show(joyconf_container); /* change the initial status */ gtk_signal_emit_by_name(GTK_OBJECT(joy_joystick), "deactivate"); } }
joy.c
(text/plain, 19.3 KB)
/* Joystick plugin for xmms by Tim Ferguson ([email protected] * http://www.dgs.monash.edu.au/~timf/) ... * 14/12/2000 - patched to allow 5 or more buttons to be used (Justin Wake <[email protected]>) * * 20/01/2004 - complete rewrite by Mark Pustjens <[email protected]> * * XMMS is Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies * * 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. */ #include <stdio.h> #include <string.h> #include "xmms/i18n.h" #include "joy.h" /* array with joystick device handles */ joy_config joysticks[JOY_MAX_JOYSTICKS]; /* all know commands including arguments and default values */ joy_commands_t joy_commands[] = { {JOY_CMD_NONE, N_("nothing"), JOY_ARG_NONE, 0}, {JOY_CMD_PLAY, N_("start playback"), JOY_ARG_NONE, 0}, {JOY_CMD_PAUSE, N_("pause playback"), JOY_ARG_NONE, 0}, {JOY_CMD_PLAY_PAUSE, N_("unpause playback"), JOY_ARG_NONE, 0}, {JOY_CMD_STOP, N_("stop playback"), JOY_ARG_NONE, 0}, {JOY_CMD_STOP_PLAY, N_("restart playback"), JOY_ARG_NONE, 0}, {JOY_CMD_VOL_UP, N_("volume up"), JOY_ARG_INT, 5}, {JOY_CMD_VOL_DOWN, N_("volume down"), JOY_ARG_INT, 5}, {JOY_CMD_BAL_LEFT, N_("balance to the left"), JOY_ARG_INT, 5}, {JOY_CMD_BAL_RIGHT, N_("balance to the right"), JOY_ARG_INT, 5}, {JOY_CMD_MAIN_WIN, N_("display main window"), JOY_ARG_TOGGLE, 0}, {JOY_CMD_PL_WIN, N_("display playlist"), JOY_ARG_TOGGLE, 0}, {JOY_CMD_EQ_WIN, N_("display equalizer"), JOY_ARG_TOGGLE, 0}, {JOY_CMD_EJECT_FILE, N_("file selection"), JOY_ARG_NONE, 0}, {JOY_CMD_PREV, N_("previous song"), JOY_ARG_NONE, 0}, {JOY_CMD_NEXT, N_("next song"), JOY_ARG_NONE, 0}, {JOY_CMD_BWD, N_("forward n song"), JOY_ARG_INT, 5}, {JOY_CMD_FWD, N_("backwards n songs"), JOY_ARG_INT, 5}, {JOY_CMD_REPEAT, N_("repeat"), JOY_ARG_TOGGLE, 0}, {JOY_CMD_SHUFFLE, N_("shuffle"), JOY_ARG_TOGGLE, 0}, {JOY_CMD_QUIT, N_("shutdown XMMS"), JOY_ARG_NONE, 0}, {0, NULL, 0, 0} }; /* function prototypes */ GeneralPlugin *get_gplugin_info(void); static void joy_init(void); static void joy_init_joystick(joy_config *joystick); static void joy_cleanup(void); static void *joy_run_joystick(void *arg); /* our thread */ static void joy_read_joystick(joy_config *joystick); static void joy_execute_command(int cmd, int value); /* xmms plugin info */ GeneralPlugin joy_plugin = { NULL, /* handle */ NULL, /* filename */ -1, /* xmms_session */ NULL, /* Description */ joy_init, joy_about, joy_configure, joy_cleanup }; /* ---------------------------------------------------------------------- */ GeneralPlugin *get_gplugin_info(void) { joy_plugin.description = g_strdup_printf(_("Joystick Control %s"), VERSION); return &joy_plugin; } int joy_cmd_to_index(int cmd) { int i; i = 0; while (joy_commands[i].name) { if (cmd == joy_commands[i].cmd) return i; i++; } return -1; } int joy_cmd_has_args(int cmd) { int i; i = 0; while (joy_commands[i].name) { if (cmd == joy_commands[i].cmd) return joy_commands[i].type; i++; } return JOY_ARG_NONE; } void joy_update_config() { int i; fprintf(stderr,"updating config\n"); fprintf(stderr,"updating config:cleanup\n"); joy_cleanup(); fprintf(stderr,"updating config:initializing\n"); for (i = 0; i < JOY_MAX_JOYSTICKS; i++) { if (joysticks[i].thread_go) { fprintf(stderr,"pdating config:initializing: active thread(s) found\n"); joy_init(); fprintf(stderr,"done\n"); return; } } fprintf(stderr,"done\n"); } /* find out how many buttons and axes the joystick has */ gboolean joy_detect_capabilities(joy_config *joystick) { gboolean wasopen = FALSE; fprintf(stderr,"detecting buttons and axes\n"); if (joystick->fd < 0) joystick->fd = open(joystick->device, O_RDONLY); else wasopen = TRUE; if (joystick->fd < 0) { joystick->num_btns = joystick->num_axes = 0; return FALSE; } else { ioctl(joystick->fd, JSIOCGAXES, &joystick->num_axes); ioctl(joystick->fd, JSIOCGBUTTONS, &joystick->num_btns); if (joystick->num_axes > JOY_MAX_AXES) joystick->num_axes = JOY_MAX_AXES; if (joystick->num_btns > JOY_MAX_BTNS) joystick->num_btns = JOY_MAX_BTNS; } if (!wasopen) { close(joystick->fd); joystick->fd = -1; } fprintf(stderr,"done detecting\n"); if (joystick->num_axes || joystick->num_btns) return TRUE; else return FALSE; } /****************************************************************/ /* read the configuration file */ void joy_read_config(joy_config *config) { gchar *joystick; gchar *button; gchar *axis; ConfigFile *cfile; int i,j; fprintf(stderr,"reading config\n"); cfile = xmms_cfg_open_default_file(); for (i = 0; i < JOY_MAX_JOYSTICKS; i++){ joystick = g_strdup_printf("joystick%i", i); if (!xmms_cfg_read_string(cfile, joystick, "device", &config[i].device)) config[i].device = g_strdup_printf("/dev/js%i", i); config[i].fd = -1; if (!xmms_cfg_read_int(cfile, joystick, "sensitivity_down", &config[i].sensitivity_down)) config[i].sensitivity_down = JOY_SENSITIVITY_DOWN; if (!xmms_cfg_read_int(cfile, joystick, "sensitivity_up", &config[i].sensitivity_up)) config[i].sensitivity_up = JOY_SENSITIVITY_UP; for (j = 0; j < JOY_MAX_AXES; j++){ axis = g_strdup_printf("axis%i_minus_cmd", j); if (!xmms_cfg_read_int(cfile, joystick, axis, &config[i].axes[j].minus_cmd)) config[i].axes[j].minus_cmd = JOY_CMD_NONE; config[i].axes[j].value = 0; g_free(axis); axis = g_strdup_printf("axis%i_minus_cmd_value", j); if (!xmms_cfg_read_int(cfile, joystick, axis, &config[i].axes[j].minus_cmd_value)) config[i].axes[j].minus_cmd_value = 0; g_free(axis); axis = g_strdup_printf("axis%i_plus_cmd", j); if (!xmms_cfg_read_int(cfile, joystick, axis, &config[i].axes[j].plus_cmd)) config[i].axes[j].plus_cmd = JOY_CMD_NONE; config[i].axes[j].value = 0; g_free(axis); axis = g_strdup_printf("axis%i_plus_cmd_value", j); if (!xmms_cfg_read_int(cfile, joystick, axis, &config[i].axes[j].plus_cmd_value)) config[i].axes[j].plus_cmd_value = 0; g_free(axis); } for (j = 0; j < JOY_MAX_BTNS; j++){ button = g_strdup_printf("button%i_cmd", j); if (!xmms_cfg_read_int(cfile, joystick, button, &config[i].btns[j].cmd)) config[i].btns[j].cmd = JOY_CMD_NONE; config[i].btns[j].value = 0; g_free(button); button = g_strdup_printf("button%i_cmd_value", j); if (!xmms_cfg_read_int(cfile, joystick, button, &config[i].btns[j].cmd_value)) config[i].btns[j].cmd_value = 0; g_free(button); } g_free(joystick); } xmms_cfg_free(cfile); } /* write the configuration file */ void joy_save_config(joy_config *config) { gchar *joystick; gchar *button; gchar *axis; ConfigFile *cfile; int i,j; fprintf(stderr,"writing config\n"); cfile = xmms_cfg_open_default_file(); for (i = 0; i < JOY_MAX_JOYSTICKS; i++){ if (!strlen(config[i].device)) continue; joystick = g_strdup_printf("joystick%i", i); xmms_cfg_write_string(cfile, joystick, "device", config[i].device); xmms_cfg_write_int(cfile, joystick, "sensitivity_down", config[i].sensitivity_down); xmms_cfg_write_int(cfile, joystick, "sensitivity_up", config[i].sensitivity_up); for (j = 0; j < JOY_MAX_AXES; j++){ if (config[i].axes[j].minus_cmd != JOY_CMD_NONE) { axis = g_strdup_printf("axis%i_minus_cmd", j); xmms_cfg_write_int(cfile, joystick, axis, config[i].axes[j].minus_cmd); g_free(axis); if (joy_cmd_has_args(config[i].axes[j].minus_cmd) != JOY_ARG_NONE) { axis = g_strdup_printf("axis%i_minus_cmd_value", j); xmms_cfg_write_int(cfile, joystick, axis, config[i].axes[j].minus_cmd_value); g_free(axis); } } if (config[i].axes[j].plus_cmd != JOY_CMD_NONE) { axis = g_strdup_printf("axis%i_plus_cmd", j); xmms_cfg_write_int(cfile, joystick, axis, config[i].axes[j].plus_cmd); g_free(axis); if (joy_cmd_has_args(config[i].axes[j].plus_cmd) != JOY_ARG_NONE) { axis = g_strdup_printf("axis%i_plus_cmd_value", j); xmms_cfg_write_int(cfile, joystick, axis, config[i].axes[j].plus_cmd_value); g_free(axis); } } } for (j = 0; j < JOY_MAX_BTNS; j++){ if (config[i].btns[j].cmd != JOY_CMD_NONE) { button = g_strdup_printf("button%i_cmd", j); xmms_cfg_write_int(cfile, joystick, button, config[i].btns[j].cmd); g_free(button); if (joy_cmd_has_args(config[i].btns[j].cmd) != JOY_ARG_NONE) { button = g_strdup_printf("button%i_cmd_value", j); xmms_cfg_write_int(cfile, joystick, button, config[i].btns[j].cmd_value); g_free(button); } } } g_free(joystick); } xmms_cfg_write_default_file(cfile); xmms_cfg_free(cfile); } /****************************************************************/ /* initialize joysticks */ static void joy_init(void) { int i; fprintf(stderr,"starting joysticks...\n"); joy_read_config(joysticks); for (i = 0; i < JOY_MAX_JOYSTICKS; i++) { joysticks[i].thread_go = TRUE; joysticks[i].thread = 0; fprintf(stderr,"starting thread for js %i\n", i); errno = pthread_create(&joysticks[i].thread, NULL, joy_run_joystick, (void *)&joysticks[i]); fprintf(stderr,"thread started\n"); if (errno) perror(_("Joystick Control")); } fprintf(stderr,"all joysticks started\n"); } /* ---------------------------------------------------------------------- */ static void joy_init_joystick(joy_config *joystick) { int l = 0; gboolean inited = FALSE; struct js_event ev; fprintf(stderr,"initializing joystick (%s)\n", joystick->device); if (!strlen(joystick->device)) return; joystick->fd = open(joystick->device, O_RDONLY | O_NONBLOCK); if (joystick->fd < 0) { g_warning(_("Joystick Control: coudn't open joystick device at %s"), joystick->device); return; } if (!joy_detect_capabilities(joystick)) return; while (!inited) { l = 0; while ((unsigned int)l < sizeof(struct js_event)) { int r = read(joystick->fd, ((char*)&ev)+l, sizeof(struct js_event)-l); if (r < 0) { if (errno == EINTR) continue; else if (errno == EAGAIN) { inited = 1; break; } g_warning(_("Error while reading joystick device : %s"), strerror(errno)); close(joystick->fd); joystick->fd = -1; return; } l += r; } if ((unsigned int)l < sizeof(struct js_event)){ if (l > 0) g_warning(_("Joystick Control: we loose %d bytes of data"), l); break; } ev.type &= ~JS_EVENT_INIT; switch (ev.type){ case JS_EVENT_BUTTON: joystick->btns[ev.number].value = ev.value; break; case JS_EVENT_AXIS: joystick->axes[ev.number].value = ev.value; break; default: g_warning(_("Joystick Control: unknown event %i"), ev.type); break; } } close(joystick->fd); fprintf(stderr,"reopening device (%s)\n", joystick->device); joystick->fd = open(joystick->device, O_RDONLY); fprintf(stderr,"done initializing\n"); } /* ---------------------------------------------------------------------- */ static void joy_cleanup(void) { int i; fprintf(stderr,"cleaning up the mess...\n"); for (i = 0; i < JOY_MAX_JOYSTICKS; i++){ if (joysticks[i].thread) { joysticks[i].thread_go = FALSE; fprintf(stderr,"closing thread\n"); pthread_cancel(joysticks[i].thread); pthread_join(joysticks[i].thread, NULL); fprintf(stderr,"thread closed\n"); close(joysticks[i].fd); joysticks[i].fd = -1; joysticks[i].thread = 0; g_free(joysticks[i].device); } } fprintf(stderr,"threads all closed\n"); } /* ---------------------------------------------------------------------- */ static void *joy_run_joystick(void *arg) { joy_config *joystick; joystick = arg; fprintf(stderr,"now in thread\n"); joy_init_joystick(joystick); if (joystick->fd >= 0) { while (joystick->thread_go) joy_read_joystick(joystick); } pthread_exit(NULL); fprintf(stderr,"now out thread\n"); } /* ---------------------------------------------------------------------- */ static void joy_read_joystick(joy_config *joystick) { int l = 0, sensitivity_down, sensitivity_up; struct js_event ev; sensitivity_down = joystick->sensitivity_down; sensitivity_up = joystick->sensitivity_up; while((unsigned int)l < sizeof(struct js_event)) { int r = read(joystick->fd, &ev + l, sizeof(struct js_event) - l); if (r <= 0) { if (errno == EINTR) /* thread was interrupted */ return; else if (errno == EAGAIN) /* queue is empty */ return; if (r < 0) g_warning(_("Joystick error while reading joystick device : %s"), strerror(errno)); else { g_warning(_("Joystick error while reading joystick device : EOF")); } g_warning(_("Disabling joystick device: %s"), joystick->device); close(joystick->fd); joystick->fd = -1; g_free(joystick->device); joystick->thread_go = FALSE; return; } l += r; } fprintf(stderr,"event read. type: %i, value: %5i\n", ev.type, ev.value); if ((unsigned int)l < sizeof(struct js_event)) { if(l > 0) g_warning(_("Joystick Control: we loose %d bytes of data"), l); return; } /* discard init events */ if (ev.type & JS_EVENT_INIT) { g_warning(_("Joystick : warning init event, we have lost sync with driver\n")); return; } if (ev.type & JS_EVENT_BUTTON) { joystick->btns[ev.number].value = ev.value; if(ev.value == 1) { joy_execute_command(joystick->btns[ev.number].cmd, joystick->btns[ev.number].cmd_value); } else { /* no keyup events possible yet */ } } else if (ev.type & JS_EVENT_AXIS) { if (ev.value < -sensitivity_down && joystick->axes[ev.number].value != -1) { joystick->axes[ev.number].value = -1; joy_execute_command(joystick->axes[ev.number].minus_cmd, joystick->axes[ev.number].minus_cmd_value); } else if (ev.value > sensitivity_down && joystick->axes[ev.number].value != 1) { joystick->axes[ev.number].value = 1; joy_execute_command(joystick->axes[ev.number].plus_cmd, joystick->axes[ev.number].plus_cmd_value); } else if (ev.value >= -sensitivity_up && joystick->axes[ev.number].value == -1) { joystick->axes[ev.number].value = 0; /* no keyup events possible yet */ } else if (ev.value <= sensitivity_up && joystick->axes[ev.number].value == 1) { joystick->axes[ev.number].value = 0; /* no keyup events possible yet */ } } else { g_warning(_("Joystick warning unknown event type %d"), ev.type); } } static void joy_execute_command(int cmd, int value) { int vl, vr, pos, len, bal; fprintf(stderr,"executing command %i\n", cmd); switch (cmd){ case JOY_CMD_NONE: break; case JOY_CMD_PLAY: xmms_remote_play(joy_plugin.xmms_session); break; case JOY_CMD_PAUSE: xmms_remote_pause(joy_plugin.xmms_session); break; case JOY_CMD_PLAY_PAUSE: xmms_remote_play_pause(joy_plugin.xmms_session); break; case JOY_CMD_STOP: xmms_remote_stop(joy_plugin.xmms_session); break; case JOY_CMD_STOP_PLAY: xmms_remote_stop(joy_plugin.xmms_session); xmms_remote_play(joy_plugin.xmms_session); break; case JOY_CMD_VOL_UP: xmms_remote_get_volume(joy_plugin.xmms_session, &vl, &vr); if (vl > (100 - value)) vl = 100 - value; if (vr > (100 - value)) vr = 100 - value; xmms_remote_set_volume(joy_plugin.xmms_session, vl + value, vr + value); break; case JOY_CMD_VOL_DOWN: xmms_remote_get_volume(joy_plugin.xmms_session, &vl, &vr); if (vl < value) vl = value; if (vr < value) vr = value; xmms_remote_set_volume(joy_plugin.xmms_session, vl - value, vr - value); break; case JOY_CMD_BAL_LEFT: bal = xmms_remote_get_balance(joy_plugin.xmms_session); if (bal < 5) bal = 5; xmms_remote_set_balance(joy_plugin.xmms_session, bal - 5); break; case JOY_CMD_BAL_RIGHT: bal = xmms_remote_get_balance(joy_plugin.xmms_session); if (bal > 95) bal = 95; xmms_remote_set_balance(joy_plugin.xmms_session, bal + 5); break; case JOY_CMD_MAIN_WIN: switch (value){ case -1: xmms_remote_main_win_toggle(joy_plugin.xmms_session, FALSE); break; case 0: if (xmms_remote_is_main_win(joy_plugin.xmms_session)) xmms_remote_main_win_toggle(joy_plugin.xmms_session, FALSE); else xmms_remote_main_win_toggle(joy_plugin.xmms_session, TRUE); break; case 1: xmms_remote_main_win_toggle(joy_plugin.xmms_session, TRUE); break; } break; case JOY_CMD_PL_WIN: switch (value){ case -1: xmms_remote_pl_win_toggle(joy_plugin.xmms_session, FALSE); break; case 0: if (xmms_remote_is_pl_win(joy_plugin.xmms_session)) xmms_remote_pl_win_toggle(joy_plugin.xmms_session, FALSE); else xmms_remote_pl_win_toggle(joy_plugin.xmms_session, TRUE); break; case 1: xmms_remote_pl_win_toggle(joy_plugin.xmms_session, TRUE); break; } break; case JOY_CMD_EQ_WIN: switch (value){ case -1: xmms_remote_eq_win_toggle(joy_plugin.xmms_session, FALSE); break; case 0: if (xmms_remote_is_eq_win(joy_plugin.xmms_session)) xmms_remote_eq_win_toggle(joy_plugin.xmms_session, FALSE); else xmms_remote_eq_win_toggle(joy_plugin.xmms_session, TRUE); break; case 1: xmms_remote_eq_win_toggle(joy_plugin.xmms_session, TRUE); break; } break; case JOY_CMD_EJECT_FILE: xmms_remote_eject(joy_plugin.xmms_session); break; case JOY_CMD_PREV: xmms_remote_playlist_prev(joy_plugin.xmms_session); break; case JOY_CMD_NEXT: xmms_remote_playlist_next(joy_plugin.xmms_session); break; case JOY_CMD_BWD: pos = xmms_remote_get_playlist_pos(joy_plugin.xmms_session); if (pos < value) pos = value; xmms_remote_set_playlist_pos(joy_plugin.xmms_session, pos - value); break; case JOY_CMD_FWD: pos = xmms_remote_get_playlist_pos(joy_plugin.xmms_session); len = xmms_remote_get_playlist_length(joy_plugin.xmms_session); if (len - value < pos) pos = len - value; xmms_remote_set_playlist_pos(joy_plugin.xmms_session, pos + value); break; case JOY_CMD_REPEAT: xmms_remote_toggle_repeat(joy_plugin.xmms_session); break; case JOY_CMD_SHUFFLE: xmms_remote_toggle_shuffle(joy_plugin.xmms_session); break; case JOY_CMD_QUIT: if (xmms_remote_is_running(joy_plugin.xmms_session)) xmms_remote_quit(joy_plugin.xmms_session); break; default: break; } fprintf(stderr,"command executed\n"); }
joy.h
(text/plain, 4.1 KB)
/* Joystick plugin for xmms by Tim Ferguson ([email protected] * http://www.dgs.monash.edu.au/~timf/) ... * 14/12/2000 - patched to allow 5 or more buttons to be used (Justin Wake <[email protected]>) * * 20/01/2004 - complete rewrite by Mark Pustjens <[email protected]> * * XMMS is Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies * * 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. */ #ifndef _JOY_H_ #define _JOY_H_ #include "config.h" /* System general includes */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <fcntl.h> #include <termios.h> #include <sys/time.h> #include <errno.h> #include <sys/types.h> #include <unistd.h> #include <sys/ioctl.h> #include <linux/joystick.h> /* XMMS-required includes (glib, threads) */ #include <glib.h> #include <gtk/gtk.h> #include <pthread.h> #include "xmms/plugin.h" #include "libxmms/xmmsctrl.h" #include "libxmms/configfile.h" /* some default values */ #define JOY_MAX_JOYSTICKS 2 #define JOY_MAX_AXES 10 #define JOY_MAX_BTNS 12 #define JOY_SENSITIVITY_DOWN 30000 #define JOY_SENSITIVITY_UP 10000 /* all supported commands */ #define JOY_CMD_NONE 0 #define JOY_CMD_PLAY 1 #define JOY_CMD_PAUSE 2 #define JOY_CMD_PLAY_PAUSE 3 #define JOY_CMD_STOP 4 #define JOY_CMD_STOP_PLAY 5 #define JOY_CMD_VOL_UP 6 #define JOY_CMD_VOL_DOWN 7 #define JOY_CMD_BAL_LEFT 8 #define JOY_CMD_BAL_RIGHT 9 #define JOY_CMD_MAIN_WIN 10 #define JOY_CMD_PL_WIN 11 #define JOY_CMD_EQ_WIN 12 #define JOY_CMD_EJECT_FILE 13 #define JOY_CMD_PREV 14 #define JOY_CMD_NEXT 15 #define JOY_CMD_BWD 16 #define JOY_CMD_FWD 17 #define JOY_CMD_REPEAT 18 #define JOY_CMD_SHUFFLE 19 #define JOY_CMD_QUIT 20 /* argument types */ #define JOY_ARG_NONE 0 #define JOY_ARG_INT 1 #define JOY_ARG_TOGGLE 2 #define JOY_ARG_BOOLEAN 3 /* typedef for command strcture */ typedef struct joy_commands { unsigned int cmd; /* command id */ gchar *name; /* full name of command */ int type; /* argument type */ int value; /* default value */ } joy_commands_t; /* actions for one event of a button */ typedef struct joy_action_btns { int value; /* what was the last seen value */ int cmd; /* execute what command */ int cmd_value; /* with which value */ } joy_action_btns; /* actions for the events of an axis */ typedef struct joy_action_axis { int value; /* what was the last seen value */ int minus_cmd; /* command if the axis gets a negative value */ int minus_cmd_value; int plus_cmd; /* command if the axis get a positive value */; int plus_cmd_value; } joy_action_axis; /* configuration of one joystick */ typedef struct joy_config { pthread_t thread; /* thread of control */ gboolean thread_go; gchar *device; /* device file string */ int fd; /* device file destriptor */ unsigned int sensitivity_down; /* sensitivity */ unsigned int sensitivity_up; int num_axes; joy_action_axis axes[JOY_MAX_AXES]; /* actions for axes */ int num_btns; joy_action_btns btns[JOY_MAX_BTNS]; /* actions for buttons */ } joy_config; /* config needs to be edited by the configuration panel */ extern joy_config joysticks[JOY_MAX_JOYSTICKS]; extern joy_commands_t joy_commands[]; /* function prototypes */ int joy_cmd_to_index(int cmd); int joy_cmd_has_args(int cmd); void joy_update_config(void); void joy_read_config(joy_config *joysticks); void joy_save_config(joy_config *joysticks); gboolean joy_detect_capabilities(joy_config *joystick); void joy_about(void); void joy_configure(void); #endif