Add a GTK+ GUI
This commit is contained in:
		
							parent
							
								
									2c25091639
								
							
						
					
					
						commit
						c05d522a1d
					
				| @ -6,13 +6,66 @@ find_package (PkgConfig REQUIRED) | ||||
| pkg_check_modules (dependencies REQUIRED libusb-1.0) | ||||
| include_directories (${dependencies_INCLUDE_DIRS}) | ||||
| 
 | ||||
| configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config.h.in | ||||
| 	${CMAKE_CURRENT_BINARY_DIR}/config.h) | ||||
| include_directories (${CMAKE_CURRENT_BINARY_DIR}) | ||||
| 
 | ||||
| add_executable (${CMAKE_PROJECT_NAME} ${CMAKE_PROJECT_NAME}.c) | ||||
| target_link_libraries (${CMAKE_PROJECT_NAME} ${dependencies_LIBRARIES}) | ||||
| option (DEVELOPER_MODE "Developer mode" OFF) | ||||
| 
 | ||||
| include (GNUInstallDirs) | ||||
| install (TARGETS ${CMAKE_PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) | ||||
| configure_file (${PROJECT_SOURCE_DIR}/config.h.in | ||||
| 	${PROJECT_BINARY_DIR}/config.h) | ||||
| include_directories (${PROJECT_BINARY_DIR}) | ||||
| 
 | ||||
| add_executable (${PROJECT_NAME} ${PROJECT_NAME}.c) | ||||
| target_link_libraries (${PROJECT_NAME} ${dependencies_LIBRARIES}) | ||||
| install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) | ||||
| 
 | ||||
| pkg_check_modules (gtk3 gtk+-3.0) | ||||
| set (BUILD_GUI ${gtk3_FOUND} CACHE BOOL "Whether to build the GTK+ frontend") | ||||
| 
 | ||||
| if (BUILD_GUI) | ||||
| 	include_directories (${gtk3_INCLUDE_DIRS}) | ||||
| 	link_directories (${gtk3_LIBRARY_DIRS}) | ||||
| 
 | ||||
| 	set (ui_in  ${PROJECT_SOURCE_DIR}/${PROJECT_NAME}-gui.ui) | ||||
| 	set (ui_out ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-gui-ui.c) | ||||
| 	add_custom_command (OUTPUT ${ui_out} | ||||
| 		COMMAND ${CMAKE_COMMAND} -D "input=${ui_in}" -D "output=${ui_out}" | ||||
| 			-D var_name=ui -P "${PROJECT_SOURCE_DIR}/quote-file.cmake" | ||||
| 		DEPENDS ${ui_in} | ||||
| 		COMMENT "Wrapping the UI file into a source file" VERBATIM) | ||||
| 
 | ||||
| 	configure_file (${PROJECT_SOURCE_DIR}/${PROJECT_NAME}-gui.desktop.in | ||||
| 		${PROJECT_BINARY_DIR}/${PROJECT_NAME}-gui.desktop) | ||||
| 	install (FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}-gui.desktop | ||||
| 		DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) | ||||
| 	install (FILES ${PROJECT_SOURCE_DIR}/${PROJECT_NAME}-gui.svg | ||||
| 		DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps) | ||||
| 
 | ||||
| 	set (polkit_id "org.${PROJECT_NAME}.policy") | ||||
| 	configure_file (${PROJECT_SOURCE_DIR}/${polkit_id}.in | ||||
| 		${PROJECT_BINARY_DIR}/${polkit_id}) | ||||
| 	install (FILES ${PROJECT_BINARY_DIR}/${polkit_id} | ||||
| 		DESTINATION ${CMAKE_INSTALL_DATADIR}/polkit-1/actions) | ||||
| 
 | ||||
| 	add_executable (${PROJECT_NAME}-gui ${PROJECT_NAME}-gui.c ${ui_out}) | ||||
| 	set_target_properties (${PROJECT_NAME}-gui PROPERTIES | ||||
| 		COMPILE_FLAGS "${gtk3_CFLAGS_OTHER}") | ||||
| 	target_link_libraries (${PROJECT_NAME}-gui ${gtk3_LIBRARIES}) | ||||
| 	install (TARGETS ${PROJECT_NAME}-gui | ||||
| 		DESTINATION ${CMAKE_INSTALL_BINDIR}) | ||||
| endif (BUILD_GUI) | ||||
| 
 | ||||
| set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "SteelSeries Sensei Raw control utility") | ||||
| set (CPACK_PACKAGE_VERSION ${project_VERSION}) | ||||
| set (CPACK_PACKAGE_VENDOR "Premysl Janouch") | ||||
| set (CPACK_PACKAGE_CONTACT "Přemysl Janouch <p.janouch@gmail.com>") | ||||
| set (CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") | ||||
| 
 | ||||
| set (CPACK_GENERATOR "TGZ;ZIP") | ||||
| set (CPACK_PACKAGE_FILE_NAME | ||||
| 	"${PROJECT_NAME}-${project_VERSION}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") | ||||
| 
 | ||||
| set (CPACK_SOURCE_GENERATOR "TGZ;ZIP") | ||||
| set (CPACK_SOURCE_IGNORE_FILES "/\\\\.git;/build;/CMakeLists.txt.user") | ||||
| set (CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${project_VERSION}") | ||||
| 
 | ||||
| set (CPACK_SET_DESTDIR TRUE) | ||||
| include (CPack) | ||||
|  | ||||
| @ -4,6 +4,11 @@ | ||||
| #define PROJECT_NAME "${CMAKE_PROJECT_NAME}" | ||||
| #define PROJECT_VERSION "${project_VERSION}" | ||||
| 
 | ||||
| #endif /* ! CONFIG_H */ | ||||
| 
 | ||||
| #cmakedefine DEVELOPER_MODE | ||||
| #ifdef DEVELOPER_MODE | ||||
| 	#define PROJECT_INSTALL_BINDIR "${PROJECT_BINARY_DIR}" | ||||
| #else // ! DEVELOPER_MODE
 | ||||
| 	#define PROJECT_INSTALL_BINDIR "${CMAKE_INSTALL_FULL_BINDIR}" | ||||
| #endif // ! DEVELOPER MODE
 | ||||
| 
 | ||||
| #endif // ! CONFIG_H
 | ||||
|  | ||||
							
								
								
									
										17
									
								
								org.sensei-raw-ctl.policy.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								org.sensei-raw-ctl.policy.in
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!DOCTYPE policyconfig PUBLIC | ||||
|  "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" | ||||
|  "http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd"> | ||||
| <policyconfig> | ||||
| 	<icon_name>${PROJECT_NAME}-gui</icon_name> | ||||
| 	<action id="org.${PROJECT_NAME}.access-device"> | ||||
| 		<description>Device access</description> | ||||
| 		<message>Authentication is required to access the USB device</message> | ||||
| 		<defaults> | ||||
| 			<allow_any>no</allow_any> | ||||
| 			<allow_inactive>no</allow_inactive> | ||||
| 			<allow_active>auth_admin_keep</allow_active> | ||||
| 		</defaults> | ||||
| 		<annotate key="org.freedesktop.policykit.exec.path">${CMAKE_INSTALL_FULL_BINDIR}/${PROJECT_NAME}</annotate> | ||||
| 	</action> | ||||
| </policyconfig> | ||||
							
								
								
									
										4
									
								
								quote-file.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								quote-file.cmake
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | ||||
| file (READ ${input} contents) | ||||
| string (REPLACE "\n" "\\n\"\n\"" contents "${contents}") | ||||
| file (WRITE ${output} | ||||
| 	"const char ${var_name}[] = \n\"${contents}\";\n") | ||||
							
								
								
									
										379
									
								
								sensei-raw-ctl-gui.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										379
									
								
								sensei-raw-ctl-gui.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,379 @@ | ||||
| /*
 | ||||
|  * sensei-raw-ctl-gui.c: SteelSeries Sensei Raw control utility - GTK+ GUI | ||||
|  * | ||||
|  * Very tightly coupled with the sensei-raw-ctl utility. | ||||
|  * | ||||
|  * Copyright (c) 2013, Přemysl Janouch <p.janouch@gmail.com> | ||||
|  * All rights reserved. | ||||
|  * | ||||
|  * Permission to use, copy, modify, and/or distribute this software for any | ||||
|  * purpose with or without fee is hereby granted, provided that the above | ||||
|  * copyright notice and this permission notice appear in all copies. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||||
|  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||||
|  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||||
|  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <gtk/gtk.h> | ||||
| #include <glib/gi18n.h> | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| #include <sys/wait.h> | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| /** User interface string for GtkBuilder. */ | ||||
| extern const char ui[]; | ||||
| 
 | ||||
| /* To translate combo box entries into sensei-raw-ctl arguments. */ | ||||
| static gchar *pulsation_list[] = { "steady", "slow", "medium", "fast", NULL }; | ||||
| static gchar *intensity_list[] = { "off", "low", "medium", "high", NULL }; | ||||
| 
 | ||||
| /* GtkNotebook pages within the UI. */ | ||||
| enum | ||||
| { | ||||
| 	PAGE_PROBING, | ||||
| 	PAGE_NO_DEVICE, | ||||
| 	PAGE_SETTINGS, | ||||
| 	PAGE_COUNT | ||||
| }; | ||||
| 
 | ||||
| /* sensei-raw-ctl output values. */ | ||||
| enum | ||||
| { | ||||
| 	OUT_INTENSITY, | ||||
| 	OUT_PULSATION, | ||||
| 	OUT_CPI_LED_OFF, | ||||
| 	OUT_CPI_LED_ON, | ||||
| 	OUT_POLLING, | ||||
| 	OUT_COUNT | ||||
| }; | ||||
| 
 | ||||
| // ----- User interface -------------------------------------------------------
 | ||||
| 
 | ||||
| static void | ||||
| fatal (GtkWidget *parent, const gchar *message) | ||||
| { | ||||
| 	GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (parent), | ||||
| 		GTK_DIALOG_DESTROY_WITH_PARENT, | ||||
| 		GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("Fatal error")); | ||||
| 	gtk_message_dialog_format_secondary_text | ||||
| 		(GTK_MESSAGE_DIALOG (dialog), "%s", message); | ||||
| 	gtk_dialog_run (GTK_DIALOG (dialog)); | ||||
| 	gtk_widget_destroy (dialog); | ||||
| 	gtk_main_quit (); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| set_page (GtkBuilder *builder, gint page) | ||||
| { | ||||
| 	GtkNotebook *notebook = GTK_NOTEBOOK | ||||
| 		(gtk_builder_get_object (builder, "notebook")); | ||||
| 	gtk_notebook_set_current_page (notebook, page); | ||||
| } | ||||
| 
 | ||||
| static gboolean | ||||
| spawn_ctl (gchar **argv, gchar **out, GtkBuilder *builder) | ||||
| { | ||||
| 	GError *error = NULL; | ||||
| 	gint status; | ||||
| 	gchar *err; | ||||
| 
 | ||||
| 	GtkWidget *win = GTK_WIDGET (gtk_builder_get_object (builder, "win")); | ||||
| 	if (!g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, | ||||
| 		out, &err, &status, &error)) | ||||
| 	{ | ||||
| 		fatal (win, error->message); | ||||
| 		g_error_free (error); | ||||
| 		return FALSE; | ||||
| 	} | ||||
| 
 | ||||
| 	if (WIFEXITED (status) && WEXITSTATUS (status) == 0) | ||||
| 		return TRUE; | ||||
| 
 | ||||
| 	if (strstr (err, "no suitable device")) | ||||
| 		set_page (builder, PAGE_NO_DEVICE); | ||||
| 	else | ||||
| 		fatal (win, err); | ||||
| 
 | ||||
| 	g_clear_pointer (out, g_free); | ||||
| 	g_free (err); | ||||
| 	return FALSE; | ||||
| } | ||||
| 
 | ||||
| static gboolean | ||||
| set_combo (GtkComboBox *combo, gchar *list[], const gchar *word) | ||||
| { | ||||
| 	gint i; | ||||
| 	for (i = 0; list[i]; i++) | ||||
| 		if (!strcmp (word, list[i])) | ||||
| 		{ | ||||
| 			gtk_combo_box_set_active (combo, i); | ||||
| 			return TRUE; | ||||
| 		} | ||||
| 	return FALSE; | ||||
| } | ||||
| 
 | ||||
| static gboolean | ||||
| set_scale (GtkRange *scale, const gchar *word, const gchar *follows) | ||||
| { | ||||
| 	gchar *end; | ||||
| 	gint64 value = g_ascii_strtoll (word, &end, 10); | ||||
| 	if (strcmp (end, follows)) | ||||
| 		return FALSE; | ||||
| 
 | ||||
| 	gtk_range_set_value (scale, value); | ||||
| 	return TRUE; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| load_configuration (GtkBuilder *builder) | ||||
| { | ||||
| 	gchar *argv[] = { "pkexec", | ||||
| 		PROJECT_INSTALL_BINDIR "/" PROJECT_NAME, "--show", NULL }; | ||||
| 
 | ||||
| 	gchar *out; | ||||
| 	if (!spawn_ctl (argv, &out, builder)) | ||||
| 		return; | ||||
| 
 | ||||
| 	GRegex *regex = g_regex_new ("(?<=: ).*$", G_REGEX_MULTILINE, 0, NULL); | ||||
| 	GMatchInfo *info; | ||||
| 	g_regex_match (regex, out, 0, &info); | ||||
| 
 | ||||
| 	gint line = 0; | ||||
| 	gchar *word = NULL; | ||||
| 
 | ||||
| 	while (g_match_info_matches (info)) | ||||
| 	{ | ||||
| 		g_free (word); | ||||
| 		word = g_match_info_fetch (info, 0); | ||||
| 		switch (line++) | ||||
| 		{ | ||||
| 		case OUT_INTENSITY: | ||||
| 			if (!set_combo (GTK_COMBO_BOX (gtk_builder_get_object | ||||
| 				(builder, "intensity_combo")), intensity_list, word)) | ||||
| 				goto out; | ||||
| 			break; | ||||
| 		case OUT_PULSATION: | ||||
| 			if (!set_combo (GTK_COMBO_BOX (gtk_builder_get_object | ||||
| 				(builder, "pulsation_combo")), pulsation_list, word)) | ||||
| 				goto out; | ||||
| 			break; | ||||
| 		case OUT_CPI_LED_OFF: | ||||
| 			if (!set_scale (GTK_RANGE (gtk_builder_get_object | ||||
| 				(builder, "cpi_off_scale")), word, "")) | ||||
| 				goto out; | ||||
| 			break; | ||||
| 		case OUT_CPI_LED_ON: | ||||
| 			if (!set_scale (GTK_RANGE (gtk_builder_get_object | ||||
| 				(builder, "cpi_on_scale")), word, "")) | ||||
| 				goto out; | ||||
| 			break; | ||||
| 		case OUT_POLLING: | ||||
| 			if (!set_scale (GTK_RANGE (gtk_builder_get_object | ||||
| 				(builder, "polling_scale")), word, "Hz")) | ||||
| 				goto out; | ||||
| 		} | ||||
| 		g_match_info_next (info, NULL); | ||||
| 	} | ||||
| 
 | ||||
| 	set_page (builder, PAGE_SETTINGS); | ||||
| 
 | ||||
| out: | ||||
| 	g_free (word); | ||||
| 	g_match_info_free (info); | ||||
| 	g_regex_unref (regex); | ||||
| 	g_free (out); | ||||
| 
 | ||||
| 	if (line != OUT_COUNT) | ||||
| 		fatal (GTK_WIDGET (gtk_builder_get_object (builder, "win")), | ||||
| 			_("Internal error")); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| retry_load (GtkBuilder *builder) | ||||
| { | ||||
| 	set_page (builder, PAGE_PROBING); | ||||
| 	load_configuration (builder); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| save_configuration (GtkBuilder *builder) | ||||
| { | ||||
| 	gchar *polling = g_strdup_printf ("%.0f", gtk_range_get_value | ||||
| 		(GTK_RANGE (gtk_builder_get_object (builder, "polling_scale")))); | ||||
| 	gchar *cpi_on  = g_strdup_printf ("%.0f", gtk_range_get_value | ||||
| 		(GTK_RANGE (gtk_builder_get_object (builder, "cpi_on_scale")))); | ||||
| 	gchar *cpi_off = g_strdup_printf ("%.0f", gtk_range_get_value | ||||
| 		(GTK_RANGE (gtk_builder_get_object (builder, "cpi_off_scale")))); | ||||
| 
 | ||||
| 	GtkComboBox *combo; | ||||
| 	gint active; | ||||
| 
 | ||||
| 	combo = GTK_COMBO_BOX (gtk_builder_get_object (builder, "pulsation_combo")); | ||||
| 	active = gtk_combo_box_get_active (combo); | ||||
| 	g_assert (active >= 0 && active < G_N_ELEMENTS (pulsation_list) - 1); | ||||
| 	gchar *pulsation = pulsation_list[active]; | ||||
| 
 | ||||
| 	combo = GTK_COMBO_BOX (gtk_builder_get_object (builder, "intensity_combo")); | ||||
| 	active = gtk_combo_box_get_active (combo); | ||||
| 	g_assert (active >= 0 && active < G_N_ELEMENTS (intensity_list) - 1); | ||||
| 	gchar *intensity = intensity_list[active]; | ||||
| 
 | ||||
| 	gchar *argv[] = { "pkexec", PROJECT_INSTALL_BINDIR "/" PROJECT_NAME, | ||||
| 		"--polling", polling, "--cpi-on", cpi_on, "--cpi-off", cpi_off, | ||||
| 		"--pulsation", pulsation, "--intensity", intensity, "--save", NULL }; | ||||
| 
 | ||||
| 	gchar *out; | ||||
| 	if (spawn_ctl (argv, &out, builder)) | ||||
| 		g_free (out); | ||||
| 
 | ||||
| 	g_free (polling); | ||||
| 	g_free (cpi_on); | ||||
| 	g_free (cpi_off); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| on_set_mode_normal (GtkBuilder *builder) | ||||
| { | ||||
| 	gchar *out, *argv[] = { "pkexec", | ||||
| 		PROJECT_INSTALL_BINDIR "/" PROJECT_NAME, "--mode", "normal", NULL }; | ||||
| 	if (spawn_ctl (argv, &out, builder)) | ||||
| 		g_free (out); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| on_set_mode_legacy (GtkBuilder *builder) | ||||
| { | ||||
| 	gchar *out, *argv[] = { "pkexec", | ||||
| 		PROJECT_INSTALL_BINDIR "/" PROJECT_NAME, "--mode", "compat", NULL }; | ||||
| 	if (spawn_ctl (argv, &out, builder)) | ||||
| 		g_free (out); | ||||
| } | ||||
| 
 | ||||
| // ----- User interface -------------------------------------------------------
 | ||||
| 
 | ||||
| static gboolean | ||||
| on_change_value (GtkRange *range, GtkScrollType scroll, gdouble value, | ||||
| 	gpointer user_data) | ||||
| { | ||||
| 	GtkAdjustment *adjustment = gtk_range_get_adjustment (range); | ||||
| 	static const gint steps[] = { 125, 250, 500, 1000 }; | ||||
| 
 | ||||
| 	switch (scroll) | ||||
| 	{ | ||||
| 		gint i; | ||||
| 	case GTK_SCROLL_NONE: | ||||
| 	case GTK_SCROLL_JUMP: | ||||
| 		for (i = 0; i < G_N_ELEMENTS (steps); i++) | ||||
| 			if (i == G_N_ELEMENTS (steps) - 1 || | ||||
| 				value < (steps[i] + steps[i + 1]) / 2) | ||||
| 			{ | ||||
| 				value = steps[i]; | ||||
| 				break; | ||||
| 			} | ||||
| 		break; | ||||
| 	case GTK_SCROLL_STEP_BACKWARD: | ||||
| 	case GTK_SCROLL_PAGE_BACKWARD: | ||||
| 		value = gtk_adjustment_get_value (adjustment); | ||||
| 		for (i = 0; i < G_N_ELEMENTS (steps) - 1; i++) | ||||
| 			if (steps[i + 1] >= value) | ||||
| 			{ | ||||
| 				value = steps[i]; | ||||
| 				break; | ||||
| 			} | ||||
| 		break; | ||||
| 	case GTK_SCROLL_STEP_FORWARD: | ||||
| 	case GTK_SCROLL_PAGE_FORWARD: | ||||
| 		value = gtk_adjustment_get_value (adjustment); | ||||
| 		for (i = 0; i < G_N_ELEMENTS (steps); i++) | ||||
| 			if (steps[i] > value) | ||||
| 			{ | ||||
| 				value = steps[i]; | ||||
| 				break; | ||||
| 			} | ||||
| 		break; | ||||
| 	case GTK_SCROLL_START: | ||||
| 		value = steps[0]; | ||||
| 		break; | ||||
| 	case GTK_SCROLL_END: | ||||
| 		value = steps[G_N_ELEMENTS (steps) - 1]; | ||||
| 		break; | ||||
| 	default: | ||||
| 		g_assert_not_reached (); | ||||
| 	} | ||||
| 
 | ||||
| 	gtk_adjustment_set_value (adjustment, value); | ||||
| 	return TRUE; | ||||
| } | ||||
| 
 | ||||
| static gboolean | ||||
| on_change_value_steps (GtkRange *range, GtkScrollType scroll, gdouble value, | ||||
| 	gpointer user_data) | ||||
| { | ||||
| 	GtkAdjustment *adjustment = gtk_range_get_adjustment (range); | ||||
| 	gdouble lower = gtk_adjustment_get_lower (adjustment); | ||||
| 	gdouble step  = gtk_adjustment_get_step_increment (adjustment); | ||||
| 	value = lower + (int) ((value - lower) / step + 0.5) * step; | ||||
| 	gtk_adjustment_set_value (adjustment, value); | ||||
| 	return TRUE; | ||||
| } | ||||
| 
 | ||||
| static gchar * | ||||
| on_format_value (GtkScale *scale, gdouble value) | ||||
| { | ||||
| 	return g_strdup_printf (_("%gHz"), value); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| main (int argc, char *argv[]) | ||||
| { | ||||
| 	gtk_init (&argc, &argv); | ||||
| 	gtk_window_set_default_icon_name (PROJECT_NAME "-gui"); | ||||
| 
 | ||||
| 	GError *error = NULL; | ||||
| 	GtkBuilder *builder = gtk_builder_new (); | ||||
| 	if (!gtk_builder_add_from_string (builder, ui, -1, &error)) | ||||
| 	{ | ||||
| 		g_printerr ("%s: %s\n", _("Error"), error->message); | ||||
| 		exit (EXIT_FAILURE); | ||||
| 	} | ||||
| 
 | ||||
| 	GtkWidget *win = GTK_WIDGET (gtk_builder_get_object (builder, "win")); | ||||
| 	g_signal_connect (win, "destroy", G_CALLBACK (gtk_main_quit), NULL); | ||||
| 	g_signal_connect_swapped (win, "map-event", | ||||
| 		G_CALLBACK (load_configuration), builder); | ||||
| 	gtk_widget_show_all (win); | ||||
| 
 | ||||
| 	g_signal_connect (gtk_builder_get_object (builder, "polling_scale"), | ||||
| 		"change-value", G_CALLBACK (on_change_value), NULL); | ||||
| 	g_signal_connect (gtk_builder_get_object (builder, "polling_scale"), | ||||
| 		"format-value", G_CALLBACK (on_format_value), NULL); | ||||
| 
 | ||||
| 	g_signal_connect (gtk_builder_get_object (builder, "cpi_off_scale"), | ||||
| 		"change-value", G_CALLBACK (on_change_value_steps), NULL); | ||||
| 	g_signal_connect (gtk_builder_get_object (builder, "cpi_on_scale"), | ||||
| 		"change-value", G_CALLBACK (on_change_value_steps), NULL); | ||||
| 
 | ||||
| 	g_signal_connect_swapped (gtk_builder_get_object (builder, "retry_button"), | ||||
| 		"clicked", G_CALLBACK (retry_load), builder); | ||||
| 
 | ||||
| 	g_signal_connect_swapped (gtk_builder_get_object (builder, "normal_button"), | ||||
| 		"clicked", G_CALLBACK (on_set_mode_normal), builder); | ||||
| 	g_signal_connect_swapped (gtk_builder_get_object (builder, "legacy_button"), | ||||
| 		"clicked", G_CALLBACK (on_set_mode_legacy), builder); | ||||
| 	g_signal_connect_swapped (gtk_builder_get_object (builder, "apply_button"), | ||||
| 		"clicked", G_CALLBACK (save_configuration), builder); | ||||
| 
 | ||||
| 	gtk_main (); | ||||
| 	g_object_unref (builder); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										8
									
								
								sensei-raw-ctl-gui.desktop.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								sensei-raw-ctl-gui.desktop.in
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| [Desktop Entry] | ||||
| Type=Application | ||||
| Name=${CMAKE_PROJECT_NAME}-gui | ||||
| GenericName=SteelSeries Sensei Raw control utility | ||||
| Icon=${CMAKE_PROJECT_NAME}-gui | ||||
| Exec=${CMAKE_PROJECT_NAME}-gui | ||||
| StartupNotify=true | ||||
| Categories=Settings;System;Utility;GTK; | ||||
							
								
								
									
										37
									
								
								sensei-raw-ctl-gui.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								sensei-raw-ctl-gui.svg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||||
| <svg id="svg2985" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="736.37" width="736.37" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/"> | ||||
|  <metadata id="metadata2991"> | ||||
|   <rdf:RDF> | ||||
|    <cc:Work rdf:about=""> | ||||
|     <dc:format>image/svg+xml</dc:format> | ||||
|     <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> | ||||
|     <dc:title/> | ||||
|    </cc:Work> | ||||
|   </rdf:RDF> | ||||
|  </metadata> | ||||
|  <defs id="defs2989"> | ||||
|   <radialGradient id="radialGradient3038" gradientUnits="userSpaceOnUse" cy="217.19" cx="419.35" gradientTransform="matrix(.76481 .51336 -.27157 .40459 157.37 17.832)" r="342.71"> | ||||
|    <stop id="stop3945" stop-color="#727272" offset="0"/> | ||||
|    <stop id="stop3953" stop-color="#686868" offset=".27273"/> | ||||
|    <stop id="stop3947" stop-color="#505050" offset="1"/> | ||||
|   </radialGradient> | ||||
|  </defs> | ||||
|  <path id="path3803" d="m42.234 287.72s1.3324 24.287 24.733 49.169c26.857 28.556 113.67 64.523 171.64 105.49 39.461 27.885 81.259 66.523 118.6 102.51 39.921 38.472 122.61 63.385 185.65 57.214 62.313-6.099 175.54-64.824 172.19-157.71-1.87-52.06-89.18-163.98-174.95-233.66-95.17-77.327-278.7-86.87-342.45-70.826-75.06 18.89-157.46 87.106-155.41 147.82z" stroke="#000" stroke-width="12.5" fill="url(#radialGradient3038)"/> | ||||
|  <path id="path3807" d="m111.67 182.53s220.06 30.601 227.66 14c6.8508-14.966-48.97-42.6-129.44-44.719m-32.375 0.53125c-6.1593 0.36638-14.541 1.7452-20.888 2.4366" stroke="#000" stroke-width="6.25" fill="none"/> | ||||
|  <path id="path3801" d="m42.83 286.23s-4.4479 22.581 44.103 31.885c143.2 27.44 174.62 50.573 222 74.796 47.383 24.222 92.273 54.102 114.98 89.576 21.682 33.872 16.814 77.139-17.537 94.284" stroke="#000" stroke-width="9.375" fill="none"/> | ||||
|  <path id="path3805" d="m309.01 393.3c-8.0458 11.324-21.367 24.74-32.41 18.824-43.84-23.48-67.31-33.53-106.42-47.73-32.05-11.64-31.71-35.4-31.71-35.4" stroke="#000" stroke-width="9.375" fill="none"/> | ||||
|  <path id="path3809" style="color:#000000" d="m264.62 176.27a5.5675 9.6378 68.704 1 1 -17.149 0 5.5675 9.6378 68.704 1 1 17.149 0z" stroke="#000" stroke-width="6.25" fill="#808080"/> | ||||
|  <path id="path3811" d="m266.32 188.22c-0.89287-3.1921 15.198-17.5 25.031-17.766 9.8337-0.26516 36.455 17.578 33.971 20.417-2.4629 2.8148-58.004 0.91769-59.002-2.6516z" stroke="#000" stroke-width="6.25" fill="none"/> | ||||
|  <path id="path3813" stroke-width="9.375" stroke="#000" d="m89.615 198.62-84.928-34.269v-14.602l95.655 39.633"/> | ||||
|  <path id="path3821" d="m212.22 349.85c-1.0536 10.395-1.2643 20.79 0 30.553" stroke="#000" stroke-width="9.375" fill="none"/> | ||||
|  <g id="g3907" transform="matrix(1.3437 0 0 1.3437 -197.37 -33.586)" stroke="#000" stroke-width="6.9768" fill="#d9f2f2"> | ||||
|   <path id="path3833" style="color:#000000" d="m539.22 313.34c-14.663-0.3514-19.887 22.088-7.75 29.25 10.097 8.9596 28.655-2.5224 24.625-15.656-1.3502-7.8103-8.8921-14.071-16.875-13.594z"/> | ||||
|   <path id="path3837" style="color:#000000" d="m601.91 314.22c-15.654 0.99942-23.881 19.598-19.75 33.438 2.5122 14.815 17.456 28.995 33.125 24.312 15.624-5.6514 19.06-26.505 12.125-40.062-4.5716-9.7284-14.114-18.318-25.5-17.688zm4.1875 24.469c4.2661 0.0772 5.6916 9.8135 0.8125 8.9375-2.7488-1.2745-4.8667-8.3346-0.8125-8.9375z"/> | ||||
|   <path id="path3823" style="color:#000000" d="m566.09 272.81c-12.501-0.28498-17.982 17.775-9.3438 25.875 0.67212 3.3821 5.4476 4.5421 5.6875 7.875-9.8723 17.226-9.1845 39.403-1.7812 57.438-8.0296 4.9007-17.38 13.603-14 24.062 3.5128 11.04 19.77 12.655 26.875 4.0938 2.0881-1.4275 3.663-5.9277 5.8438-1.9375 15.177 14.041 42.239 17.106 57.375 1.5 19.994-19.121 19.764-51.958 6.9375-75.125-10.017-18.999-31.185-34.628-53.5-30.656-2.8064 1.0224-5.8445 2.2538-6.75-1.625-3.7345-6.1023-9.4907-12.336-17.344-11.5zm34.812 39c21.941 1.0293 34.728 27.102 28.969 46.688-2.9256 10.676-14.115 20.024-25.469 15.75-22.594-6.8244-32.316-40.245-15.656-57.312 3.2348-3.1548 7.6468-5.1563 12.156-5.125z"/> | ||||
|  </g> | ||||
|  <path id="path3857" d="m157.16 170.01s-9.1804 4.5359-6.9557 9.5821c1.8241 4.1375 9.4611 6.6054 15.554 7.3877 31.185 4.0035 53.918-2.1806 68.654-14.539 16.622-13.94-14.711-15.803-14.711-15.803" stroke="#000" stroke-width="6.25" fill="none"/> | ||||
|  <path id="path3859" d="m151.97 181.64c10.25-34.199 53.67-47.58 83.46-10.474" stroke="#000" stroke-width="6.25" fill="none"/> | ||||
|  <path id="path3861" d="m156.44 184.4c6.2526-19.691 36.314-16.509 51.673 0.47035" stroke="#000" stroke-width="6.25" fill="none"/> | ||||
|  <path id="path3955" d="m176.95 170.84c-9.4273 0.1133-17.6 4.3323-20.531 13.562 0.002 0.0524-0.002 0.10406 0 0.15625 2.891 1.223 6.3103 2.0168 9.3438 2.4062 16.423 2.1084 30.48 1.3938 42.281-1.5625 0.0224-0.17829 0.0432-0.35045 0.0625-0.53125-8.1596-9.0203-20.472-14.16-31.156-14.031z" stroke="#000" stroke-width="6.25" fill="#d9f2f3"/> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 4.8 KiB | 
							
								
								
									
										199
									
								
								sensei-raw-ctl-gui.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								sensei-raw-ctl-gui.ui
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,199 @@ | ||||
| <interface> | ||||
|  <object class='GtkAdjustment' id='polling_adj'> | ||||
|   <property name='lower'>125</property> | ||||
|   <property name='upper'>1000</property> | ||||
|  </object> | ||||
|  <object class='GtkAdjustment' id='cpi_on_adj'> | ||||
|   <property name='lower'>90</property> | ||||
|   <property name='upper'>5670</property> | ||||
|   <property name='step-increment'>90</property> | ||||
|   <property name='page-increment'>90</property> | ||||
|  </object> | ||||
|  <object class='GtkAdjustment' id='cpi_off_adj'> | ||||
|   <property name='lower'>90</property> | ||||
|   <property name='upper'>5670</property> | ||||
|   <property name='step-increment'>90</property> | ||||
|   <property name='page-increment'>90</property> | ||||
|  </object> | ||||
|  <object class='GtkSizeGroup' id='label_size_group'> | ||||
|   <property name='mode'>GTK_SIZE_GROUP_HORIZONTAL</property> | ||||
|   <widgets> | ||||
|    <widget name='polling_label' /> | ||||
|    <widget name='cpi_off_label' /> | ||||
|    <widget name='cpi_on_label' /> | ||||
|    <widget name='pulsation_label' /> | ||||
|    <widget name='intensity_label' /> | ||||
|   </widgets> | ||||
|  </object> | ||||
|  <object class='GtkWindow' id='win'> | ||||
|   <property name='window-position'>GTK_WIN_POS_CENTER</property> | ||||
|   <property name='title' translatable='TRUE'>SteelSeries Sensei Raw control utility</property> | ||||
|   <property name='border-width'>10</property> | ||||
|   <child><object class='GtkNotebook' id='notebook'> | ||||
|    <property name='show-tabs'>FALSE</property> | ||||
|    <child><object class='GtkHBox' id='probing_box'> | ||||
|     <property name='halign'>GTK_ALIGN_CENTER</property> | ||||
|     <property name='valign'>GTK_ALIGN_CENTER</property> | ||||
|     <property name='spacing'>10</property> | ||||
|     <child><object class='GtkSpinner' id='probing_spinner'> | ||||
|      <property name='halign'>GTK_ALIGN_CENTER</property> | ||||
|      <property name='valign'>GTK_ALIGN_CENTER</property> | ||||
|      <property name='active'>TRUE</property> | ||||
|     </object></child> | ||||
|     <child><object class='GtkLabel' id='probing_label'> | ||||
|      <property name='label' translatable='TRUE'>Probing the device...</property> | ||||
|     </object></child> | ||||
|    </object></child> | ||||
|    <child><object class='GtkVBox' id='no_device_box'> | ||||
|     <property name='spacing'>10</property> | ||||
|     <property name='halign'>GTK_ALIGN_CENTER</property> | ||||
|     <property name='valign'>GTK_ALIGN_CENTER</property> | ||||
|     <child><object class='GtkLabel' id='no_device_label'> | ||||
|      <property name='label' translatable='TRUE'>No suitable device found.</property> | ||||
|     </object></child> | ||||
|     <child><object class='GtkButton' id='retry_button'> | ||||
|      <property name='label' translatable='TRUE'>Retry</property> | ||||
|      <property name='halign'>GTK_ALIGN_CENTER</property> | ||||
|     </object></child> | ||||
|    </object></child> | ||||
|    <child><object class='GtkVBox' id='vbox'> | ||||
|     <property name='spacing'>10</property> | ||||
|     <child><object class='GtkHBox' id='hbox'> | ||||
|      <property name='spacing'>10</property> | ||||
|      <child> | ||||
|       <object class='GtkLabel' id='polling_label'> | ||||
|        <property name='label' translatable='TRUE'>Polling</property> | ||||
|       </object> | ||||
|      </child><child> | ||||
|       <object class='GtkScale' id='polling_scale'> | ||||
|        <property name='width-request'>200</property> | ||||
|        <property name='digits'>0</property> | ||||
|        <property name='adjustment'>polling_adj</property> | ||||
|        <marks> | ||||
|         <mark value='125' /> | ||||
|         <mark value='250' /> | ||||
|         <mark value='500' /> | ||||
|         <mark value='1000' /> | ||||
|        </marks> | ||||
|       </object> | ||||
|      </child> | ||||
|     </object></child> | ||||
|     <child><object class='GtkFrame' id='cpi_frame'> | ||||
|      <property name='label' translatable='TRUE'>CPI</property> | ||||
|      <property name='label-xalign'>0.5</property> | ||||
|      <child><object class='GtkVBox' id='cpi_vbox'> | ||||
|       <property name='border-width'>5</property> | ||||
|       <child><object class='GtkHBox' id='cpi_off_hbox'> | ||||
|        <property name='spacing'>10</property> | ||||
|        <child> | ||||
|         <object class='GtkLabel' id='cpi_off_label'> | ||||
|          <property name='label' translatable='TRUE'>LED off</property> | ||||
|         </object><packing> | ||||
|          <property name='expand'>FALSE</property> | ||||
|          <property name='fill'>FALSE</property> | ||||
|         </packing> | ||||
|        </child><child> | ||||
|         <object class='GtkScale' id='cpi_off_scale'> | ||||
|          <property name='width-request'>200</property> | ||||
|          <property name='digits'>0</property> | ||||
|          <property name='adjustment'>cpi_off_adj</property> | ||||
|         </object><packing> | ||||
|          <property name='expand'>TRUE</property> | ||||
|          <property name='fill'>TRUE</property> | ||||
|         </packing> | ||||
|        </child> | ||||
|       </object></child> | ||||
|       <child><object class='GtkHBox' id='cpi_on_hbox'> | ||||
|        <property name='spacing'>10</property> | ||||
|        <child> | ||||
|         <object class='GtkLabel' id='cpi_on_label'> | ||||
|          <property name='label' translatable='TRUE'>LED on</property> | ||||
|         </object><packing> | ||||
|          <property name='expand'>FALSE</property> | ||||
|          <property name='fill'>FALSE</property> | ||||
|         </packing> | ||||
|        </child><child> | ||||
|         <object class='GtkScale' id='cpi_on_scale'> | ||||
|          <property name='width-request'>200</property> | ||||
|          <property name='digits'>0</property> | ||||
|          <property name='adjustment'>cpi_on_adj</property> | ||||
|         </object><packing> | ||||
|          <property name='expand'>TRUE</property> | ||||
|          <property name='fill'>TRUE</property> | ||||
|         </packing> | ||||
|        </child> | ||||
|       </object></child> | ||||
|      </object></child> | ||||
|     </object></child> | ||||
|     <child><object class='GtkFrame' id='backlight_frame'> | ||||
|      <property name='label' translatable='TRUE'>Backlight</property> | ||||
|      <property name='label-xalign'>0.5</property> | ||||
|      <child><object class='GtkVBox' id='backlight_box'> | ||||
|       <property name='border-width'>5</property> | ||||
|       <child><object class='GtkHBox' id='pulsation_box'> | ||||
|        <property name='spacing'>10</property> | ||||
|        <child> | ||||
|         <object class='GtkLabel' id='pulsation_label'> | ||||
|          <property name='label' translatable='TRUE'>Pulsation</property> | ||||
|         </object><packing> | ||||
|          <property name='expand'>FALSE</property> | ||||
|          <property name='fill'>FALSE</property> | ||||
|         </packing> | ||||
|        </child><child> | ||||
|         <object class='GtkComboBoxText' id='pulsation_combo'> | ||||
|          <items> | ||||
|           <item translatable='TRUE'>Steady</item> | ||||
|           <item translatable='TRUE'>Slow</item> | ||||
|           <item translatable='TRUE'>Medium</item> | ||||
|           <item translatable='TRUE'>Fast</item> | ||||
|          </items> | ||||
|         </object><packing> | ||||
|          <property name='expand'>TRUE</property> | ||||
|          <property name='fill'>TRUE</property> | ||||
|         </packing> | ||||
|        </child> | ||||
|       </object></child> | ||||
|       <child><object class='GtkHBox' id='intensity_box'> | ||||
|        <property name='spacing'>10</property> | ||||
|        <child> | ||||
|         <object class='GtkLabel' id='intensity_label'> | ||||
|          <property name='label' translatable='TRUE'>Intensity</property> | ||||
|         </object><packing> | ||||
|          <property name='expand'>FALSE</property> | ||||
|          <property name='fill'>FALSE</property> | ||||
|         </packing> | ||||
|        </child><child> | ||||
|         <object class='GtkComboBoxText' id='intensity_combo'> | ||||
|          <items> | ||||
|           <item translatable='TRUE'>Off</item> | ||||
|           <item translatable='TRUE'>Low</item> | ||||
|           <item translatable='TRUE'>Medium</item> | ||||
|           <item translatable='TRUE'>High</item> | ||||
|          </items> | ||||
|         </object><packing> | ||||
|          <property name='expand'>TRUE</property> | ||||
|          <property name='fill'>TRUE</property> | ||||
|         </packing> | ||||
|        </child> | ||||
|       </object></child> | ||||
|      </object></child> | ||||
|     </object></child> | ||||
|     <child><object class='GtkHBox' id='buttons_box'> | ||||
|      <child><object class='GtkButton' id='normal_button'> | ||||
|       <property name='label' translatable='TRUE'>Normal mode</property> | ||||
|      </object></child> | ||||
|      <child><object class='GtkButton' id='legacy_button'> | ||||
|       <property name='label' translatable='TRUE'>Legacy mode</property> | ||||
|      </object></child> | ||||
|      <child><object class='GtkButton' id='apply_button'> | ||||
|       <property name='label'>gtk-apply</property> | ||||
|       <property name='use-stock'>TRUE</property> | ||||
|       <property name='margin-left'>15</property> | ||||
|       <property name='can-default'>TRUE</property> | ||||
|      </object></child> | ||||
|     </object></child> | ||||
|    </object></child> | ||||
|   </object></child> | ||||
|  </object> | ||||
| </interface> | ||||
| 
 | ||||
| @ -86,8 +86,8 @@ out: | ||||
| #define USB_VENDOR_STEELSERIES  0x1038 | ||||
| #define USB_PRODUCT_STEELSERIES_SENSEI  0x1369 | ||||
| 
 | ||||
| #define GET_REPORT  0x01 | ||||
| #define SET_REPORT  0x09 | ||||
| #define USB_GET_REPORT  0x01 | ||||
| #define USB_SET_REPORT  0x09 | ||||
| 
 | ||||
| #define SENSEI_CTL_IFACE  0 | ||||
| 
 | ||||
| @ -108,7 +108,7 @@ enum sensei_pulsation | ||||
| /* Just guessing the names, could be anything */ | ||||
| enum sensei_mode | ||||
| { | ||||
| 	MODE_COMPATIBILITY = 1, | ||||
| 	MODE_LEGACY = 1, | ||||
| 	MODE_NORMAL | ||||
| }; | ||||
| 
 | ||||
| @ -148,7 +148,7 @@ sensei_send_command (libusb_device_handle *device, | ||||
| { | ||||
| 	int result = libusb_control_transfer (device, LIBUSB_ENDPOINT_OUT | ||||
| 		| LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, | ||||
| 		SET_REPORT, 0x0200, 0x0000, data, length, 0); | ||||
| 		USB_SET_REPORT, 0x0200, 0x0000, data, length, 0); | ||||
| 	return result < 0 ? result : 0; | ||||
| } | ||||
| 
 | ||||
| @ -215,7 +215,7 @@ sensei_load_config (libusb_device_handle *device, | ||||
| 
 | ||||
| 	int result = libusb_control_transfer (device, LIBUSB_ENDPOINT_IN | ||||
| 		| LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE, | ||||
| 		GET_REPORT, 0x0300, 0x0000, data, sizeof data, 0); | ||||
| 		USB_GET_REPORT, 0x0300, 0x0000, data, sizeof data, 0); | ||||
| 	if (result < 0) | ||||
| 		return result; | ||||
| 
 | ||||
| @ -287,7 +287,7 @@ show_usage (const char *program_name) | ||||
| 	printf ("  --version       Show program version and exit\n"); | ||||
| 	printf ("  --show          Show current mouse settings and exit\n"); | ||||
| 	printf ("  --mode X        Set the mode of the mouse" | ||||
| 			                 " (can be either 'compat' or 'normal')\n"); | ||||
| 	                         " (can be either 'legacy' or 'normal')\n"); | ||||
| 	printf ("  --polling X     Set polling to X Hz (1000, 500, 250, 125)\n"); | ||||
| 	printf ("  --cpi-on X      Set CPI with the LED on to X\n"); | ||||
| 	printf ("  --cpi-off X     Set CPI with the LED off to X\n"); | ||||
| @ -369,8 +369,8 @@ parse_options (int argc, char *argv[], | ||||
| 		options->save_to_rom = true; | ||||
| 		break; | ||||
| 	case 'm': | ||||
| 		if (!strcasecmp (optarg, "compat")) | ||||
| 			new_config->mode = MODE_COMPATIBILITY; | ||||
| 		if (!strcasecmp (optarg, "legacy")) | ||||
| 			new_config->mode = MODE_LEGACY; | ||||
| 		else if (!strcasecmp (optarg, "normal")) | ||||
| 			new_config->mode = MODE_NORMAL; | ||||
| 		else | ||||
|  | ||||
							
								
								
									
										37
									
								
								sensei-raw.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								sensei-raw.svg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||||
| <svg id="svg2985" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="534" width="745" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/"> | ||||
|  <metadata id="metadata2991"> | ||||
|   <rdf:RDF> | ||||
|    <cc:Work rdf:about=""> | ||||
|     <dc:format>image/svg+xml</dc:format> | ||||
|     <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> | ||||
|     <dc:title/> | ||||
|    </cc:Work> | ||||
|   </rdf:RDF> | ||||
|  </metadata> | ||||
|  <defs id="defs2989"> | ||||
|   <radialGradient id="radialGradient3949" gradientUnits="userSpaceOnUse" cy="217.19" cx="419.35" gradientTransform="matrix(.76481 .51336 -.27157 .40459 152.39 -64.575)" r="342.71"> | ||||
|    <stop id="stop3945" stop-color="#666" offset="0"/> | ||||
|    <stop id="stop3953" stop-color="#5c5c5c" offset=".27273"/> | ||||
|    <stop id="stop3947" stop-color="#363636" offset="1"/> | ||||
|   </radialGradient> | ||||
|  </defs> | ||||
|  <path id="path3803" d="m37.249 205.32s1.3324 24.287 24.733 49.169c26.857 28.556 113.67 64.523 171.64 105.49 39.461 27.885 81.259 66.523 118.6 102.51 39.921 38.472 122.61 63.385 185.65 57.214 62.32-6.1 175.54-64.83 172.19-157.72-1.88-52.05-89.19-163.97-174.95-233.65-95.17-77.329-278.71-86.873-342.46-70.828-75.05 18.889-157.46 87.108-155.4 147.82z" stroke="#000" stroke-width="12.5" fill="url(#radialGradient3949)"/> | ||||
|  <path id="path3807" d="m106.69 100.12s220.06 30.601 227.66 14c6.8508-14.966-48.97-42.6-129.44-44.719m-32.375 0.53125c-6.1593 0.36638-14.541 1.7452-20.888 2.4366" stroke="#000" stroke-width="6.25" fill="none"/> | ||||
|  <path id="path3801" d="m37.845 203.83s-4.4479 22.581 44.103 31.885c143.2 27.44 174.62 50.573 222 74.796 47.383 24.222 92.273 54.102 114.98 89.576 21.682 33.872 16.814 77.139-17.537 94.284" stroke="#000" stroke-width="12.5" fill="none"/> | ||||
|  <path id="path3805" d="m304.02 310.89c-8.0458 11.324-21.367 24.74-32.41 18.824-43.83-23.47-67.3-33.52-106.41-47.72-32.05-11.64-31.72-35.4-31.72-35.4" stroke="#000" stroke-width="6.25" fill="none"/> | ||||
|  <path id="path3809" style="color:#000000" d="m260.74 93.867a9.6847 8.0458 0 1 1 -19.369 0 9.6847 8.0458 0 1 1 19.369 0z" transform="matrix(.88538 0 -.41595 .77778 67.821 20.859)" stroke="#000" stroke-width="7.5316" fill="#808080"/> | ||||
|  <path id="path3811" d="m261.34 105.82c-0.89287-3.1921 15.198-17.5 25.031-17.766 9.8337-0.26516 36.455 17.578 33.971 20.417-2.4629 2.8148-58.004 0.91769-59.002-2.6516z" stroke="#000" stroke-width="6.25" fill="none"/> | ||||
|  <path id="path3813" d="m84.629 116.22-84.927-34.269v-14.602l95.655 39.633" stroke="#000" stroke-width="6.25"/> | ||||
|  <path id="path3821" d="m207.24 267.45c-1.0536 10.395-1.2643 20.79 0 30.553" stroke="#000" stroke-width="6.25" fill="none"/> | ||||
|  <g id="g3907" stroke="#000" stroke-width="6.25" fill="#d9f2f2"> | ||||
|   <path id="path3823" style="color:#000000" d="m566.09 274.81c-11.143-0.11809-15.265 15.938-7.5938 22.812 0.86005 3.7648 7.1709 5.6488 5.8125 9.6562-9.9502 17.328-9.0598 39.519-1.0938 57.438-7.462 4.8318-17.522 11.901-14.812 22.219 2.6628 9.6895 16.903 11.655 22.969 4.2188 2.4499-1.0825 4.007-5.0961 6.625-5.0938 13.798 15.034 40.627 20.142 56.469 5.0312 18.675-16.707 19.927-46.107 10.156-67.938-8.4425-20.203-28.581-37.875-51.656-35.688-2.9622 0.28099-6.1056 1.8574-8.8438 1.8438-3.9485-6.6062-8.9402-15.392-18.031-14.5zm34.812 35c20.704 0.6059 33.816 22.941 32.219 42.125-0.61601 12.738-11.104 27.212-25.312 25.094-21.409-3.1028-33.655-28.662-28.031-48.656 2.6556-9.5719 10.528-18.557 21.125-18.562z"/> | ||||
|   <path id="path3833" style="color:#000000" d="m539.22 315.34c-12.596-0.2111-17.137 18.904-6.9062 25.312 8.723 8.3121 25.23-1.4896 21.844-13.188-1.0936-6.9642-7.8416-12.584-14.938-12.125z"/> | ||||
|   <path id="path3837" style="color:#000000" d="m601.91 314.22c-15.654 0.99942-23.881 19.598-19.75 33.438 2.5122 14.815 17.456 28.995 33.125 24.312 15.624-5.6514 19.06-26.505 12.125-40.062-4.5716-9.7284-14.114-18.318-25.5-17.688zm4.1875 24.469c4.2661 0.0772 5.6916 9.8135 0.8125 8.9375-2.7488-1.2745-4.8667-8.3346-0.8125-8.9375z"/> | ||||
|  </g> | ||||
|  <path id="path3857" d="m152.17 87.6s-9.1804 4.5359-6.9557 9.5821c1.8241 4.1375 9.4611 6.6054 15.554 7.3877 31.185 4.0035 53.918-2.1806 68.654-14.539 16.622-13.94-14.711-15.803-14.711-15.803" stroke="#000" stroke-width="6.25" fill="none"/> | ||||
|  <path id="path3859" d="m146.99 99.23c10.24-34.199 53.66-47.581 83.45-10.474" stroke="#000" stroke-width="6.25" fill="none"/> | ||||
|  <path id="path3861" d="m151.45 101.99c6.2526-19.691 36.314-16.509 51.673 0.47035" stroke="#000" stroke-width="6.25" fill="none"/> | ||||
|  <path id="path3955" d="m171.97 88.438c-9.43 0.113-17.6 4.332-20.53 13.562v0.16c2.89 1.22 6.31 2.01 9.34 2.4 16.42 2.11 30.48 1.4 42.28-1.56 0.02-0.18 0.05-0.35 0.06-0.53-8.15-9.022-20.47-14.161-31.15-14.032z" stroke="#000" stroke-width="6.25" fill="#d9f2f3"/> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 4.7 KiB | 
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user