You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

dialog-main.c 9.3 KiB

4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
  2. *
  3. * Copyright (C) 2008 Red Hat, Inc.
  4. * Copyright (C) 2014 Michal Ratajsky <michal.ratajsky@gmail.com>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation; either version 2 of the
  9. * License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  19. * 02110-1301, USA.
  20. */
  21. #include "config.h"
  22. #include <glib.h>
  23. #include <glib/gi18n.h>
  24. #include <gtk/gtk.h>
  25. #include <libintl.h>
  26. #include <unique/uniqueapp.h>
  27. #include <libmatemixer/matemixer.h>
  28. #include "gvc-mixer-dialog.h"
  29. #define DIALOG_POPUP_TIMEOUT 3
  30. static guint popup_id = 0;
  31. static gboolean debug = FALSE;
  32. static gboolean show_version = FALSE;
  33. static gchar *page = NULL;
  34. static GtkWidget *app_dialog = NULL;
  35. static GtkWidget *warning_dialog = NULL;
  36. static void
  37. on_dialog_response (GtkDialog *dialog, guint response_id, gpointer data)
  38. {
  39. gboolean destroy = GPOINTER_TO_INT (data);
  40. if (destroy == TRUE)
  41. gtk_widget_destroy (GTK_WIDGET (dialog));
  42. gtk_main_quit ();
  43. }
  44. static void
  45. on_dialog_close (GtkDialog *dialog, gpointer data)
  46. {
  47. gboolean destroy = GPOINTER_TO_INT (data);
  48. if (destroy == TRUE)
  49. gtk_widget_destroy (GTK_WIDGET (dialog));
  50. gtk_main_quit ();
  51. }
  52. static UniqueResponse
  53. on_app_message_received (UniqueApp *app,
  54. int command,
  55. UniqueMessageData *message_data,
  56. guint time_,
  57. gpointer user_data)
  58. {
  59. gtk_window_present (GTK_WINDOW (user_data));
  60. return UNIQUE_RESPONSE_OK;
  61. }
  62. static void
  63. remove_warning_dialog (void)
  64. {
  65. if (popup_id != 0) {
  66. g_source_remove (popup_id);
  67. popup_id = 0;
  68. }
  69. g_clear_pointer (&warning_dialog, gtk_widget_destroy);
  70. }
  71. static void
  72. context_ready (MateMixerContext *context, UniqueApp *app)
  73. {
  74. /* The dialog might be already created, e.g. when reconnected
  75. * to a sound server */
  76. if (app_dialog != NULL)
  77. return;
  78. app_dialog = GTK_WIDGET (gvc_mixer_dialog_new (context));
  79. g_signal_connect (G_OBJECT (app_dialog),
  80. "response",
  81. G_CALLBACK (on_dialog_response),
  82. GINT_TO_POINTER (FALSE));
  83. g_signal_connect (G_OBJECT (app_dialog),
  84. "close",
  85. G_CALLBACK (on_dialog_close),
  86. GINT_TO_POINTER (FALSE));
  87. gvc_mixer_dialog_set_page (GVC_MIXER_DIALOG (app_dialog), page);
  88. g_signal_connect (G_OBJECT (app),
  89. "message-received",
  90. G_CALLBACK (on_app_message_received),
  91. app_dialog);
  92. gtk_widget_show (app_dialog);
  93. }
  94. static void
  95. on_context_state_notify (MateMixerContext *context,
  96. GParamSpec *pspec,
  97. UniqueApp *app)
  98. {
  99. MateMixerState state = mate_mixer_context_get_state (context);
  100. if (state == MATE_MIXER_STATE_READY) {
  101. remove_warning_dialog ();
  102. context_ready (context, app);
  103. }
  104. else if (state == MATE_MIXER_STATE_FAILED) {
  105. GtkWidget *dialog;
  106. remove_warning_dialog ();
  107. dialog = gtk_message_dialog_new (GTK_WINDOW (app_dialog),
  108. 0,
  109. GTK_MESSAGE_ERROR,
  110. GTK_BUTTONS_CLOSE,
  111. _("Sound system is not available"));
  112. g_signal_connect (G_OBJECT (dialog),
  113. "response",
  114. G_CALLBACK (on_dialog_response),
  115. GINT_TO_POINTER (TRUE));
  116. g_signal_connect (G_OBJECT (dialog),
  117. "close",
  118. G_CALLBACK (on_dialog_close),
  119. GINT_TO_POINTER (TRUE));
  120. gtk_widget_show (dialog);
  121. }
  122. }
  123. static gboolean
  124. dialog_popup_timeout (gpointer data)
  125. {
  126. warning_dialog = gtk_message_dialog_new (GTK_WINDOW (app_dialog),
  127. 0,
  128. GTK_MESSAGE_INFO,
  129. GTK_BUTTONS_CANCEL,
  130. _("Waiting for sound system to respond"));
  131. g_signal_connect (G_OBJECT (warning_dialog),
  132. "response",
  133. G_CALLBACK (on_dialog_response),
  134. GINT_TO_POINTER (TRUE));
  135. g_signal_connect (G_OBJECT (warning_dialog),
  136. "close",
  137. G_CALLBACK (on_dialog_close),
  138. GINT_TO_POINTER (TRUE));
  139. gtk_widget_show (warning_dialog);
  140. return FALSE;
  141. }
  142. int
  143. main (int argc, char **argv)
  144. {
  145. GError *error = NULL;
  146. gchar *backend = NULL;
  147. MateMixerContext *context;
  148. UniqueApp *app;
  149. GOptionEntry entries[] = {
  150. { "backend", 'b', 0, G_OPTION_ARG_STRING, &backend, N_("Sound system backend"), "pulse|alsa|oss|null" },
  151. { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, N_("Enable debug"), NULL },
  152. { "page", 'p', 0, G_OPTION_ARG_STRING, &page, N_("Startup page"), "effects|hardware|input|output|applications" },
  153. { "version", 'v', 0, G_OPTION_ARG_NONE, &show_version, N_("Version of this application"), NULL },
  154. { NULL }
  155. };
  156. bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR);
  157. bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
  158. textdomain (GETTEXT_PACKAGE);
  159. gtk_init_with_args (&argc, &argv,
  160. _(" — MATE Volume Control"),
  161. entries, GETTEXT_PACKAGE,
  162. &error);
  163. if (error != NULL) {
  164. g_warning ("%s", error->message);
  165. return 1;
  166. }
  167. if (show_version == TRUE) {
  168. g_print ("%s %s\n", argv[0], VERSION);
  169. return 0;
  170. }
  171. if (debug == TRUE) {
  172. g_setenv ("G_MESSAGES_DEBUG", "all", FALSE);
  173. }
  174. app = unique_app_new (GVC_DIALOG_DBUS_NAME, NULL);
  175. if (unique_app_is_running (app) == TRUE) {
  176. unique_app_send_message (app, UNIQUE_ACTIVATE, NULL);
  177. return 0;
  178. }
  179. if (mate_mixer_init () == FALSE) {
  180. g_warning ("libmatemixer initialization failed, exiting");
  181. return 1;
  182. }
  183. context = mate_mixer_context_new ();
  184. if (backend != NULL) {
  185. if (strcmp (backend, "pulse") == 0)
  186. mate_mixer_context_set_backend_type (context, MATE_MIXER_BACKEND_PULSEAUDIO);
  187. else if (strcmp (backend, "alsa") == 0)
  188. mate_mixer_context_set_backend_type (context, MATE_MIXER_BACKEND_ALSA);
  189. else if (strcmp (backend, "oss") == 0)
  190. mate_mixer_context_set_backend_type (context, MATE_MIXER_BACKEND_OSS);
  191. else if (strcmp (backend, "null") == 0)
  192. mate_mixer_context_set_backend_type (context, MATE_MIXER_BACKEND_NULL);
  193. else {
  194. g_warning ("Invalid backend: %s", backend);
  195. g_object_unref (context);
  196. g_object_unref (app);
  197. g_free (backend);
  198. return 1;
  199. }
  200. g_free (backend);
  201. }
  202. mate_mixer_context_set_app_name (context, _("Volume Control"));
  203. mate_mixer_context_set_app_id (context, GVC_DIALOG_DBUS_NAME);
  204. mate_mixer_context_set_app_version (context, VERSION);
  205. mate_mixer_context_set_app_icon (context, "multimedia-volume-control");
  206. g_signal_connect (G_OBJECT (context),
  207. "notify::state",
  208. G_CALLBACK (on_context_state_notify),
  209. app);
  210. mate_mixer_context_open (context);
  211. if (mate_mixer_context_get_state (context) == MATE_MIXER_STATE_CONNECTING) {
  212. popup_id = g_timeout_add_seconds (DIALOG_POPUP_TIMEOUT,
  213. dialog_popup_timeout,
  214. NULL);
  215. }
  216. gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (),
  217. ICON_DATA_DIR);
  218. gtk_window_set_default_icon_name ("multimedia-volume-control");
  219. gtk_main ();
  220. g_object_unref (context);
  221. g_object_unref (app);
  222. return 0;
  223. }