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.
 
 
 
 
 
 

306 lines
8.7 KiB

  1. /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
  2. * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2, or (at your option)
  7. * any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. */
  19. #include <config.h>
  20. #include <glib/gstdio.h>
  21. #include <glib/gi18n.h>
  22. #include <gio/gio.h>
  23. #include <utime.h>
  24. #include <strings.h>
  25. #include "sound-theme-file-utils.h"
  26. #define CUSTOM_THEME_NAME "__custom"
  27. /* This function needs to be called after each individual
  28. * changeset to the theme */
  29. void
  30. custom_theme_update_time (void)
  31. {
  32. char *path;
  33. path = custom_theme_dir_path (NULL);
  34. utime (path, NULL);
  35. g_free (path);
  36. }
  37. char *
  38. custom_theme_dir_path (const char *child)
  39. {
  40. static char *dir = NULL;
  41. const char *data_dir;
  42. if (dir == NULL) {
  43. data_dir = g_get_user_data_dir ();
  44. dir = g_build_filename (data_dir, "sounds", CUSTOM_THEME_NAME, NULL);
  45. }
  46. if (child == NULL)
  47. return g_strdup (dir);
  48. return g_build_filename (dir, child, NULL);
  49. }
  50. static gboolean
  51. directory_delete_recursive (GFile *directory, GError **error)
  52. {
  53. GFileEnumerator *enumerator;
  54. GFileInfo *info;
  55. gboolean success = TRUE;
  56. enumerator = g_file_enumerate_children (directory,
  57. G_FILE_ATTRIBUTE_STANDARD_NAME ","
  58. G_FILE_ATTRIBUTE_STANDARD_TYPE,
  59. G_FILE_QUERY_INFO_NONE,
  60. NULL, error);
  61. if (enumerator == NULL)
  62. return FALSE;
  63. while (success &&
  64. (info = g_file_enumerator_next_file (enumerator, NULL, NULL))) {
  65. GFile *child;
  66. child = g_file_get_child (directory, g_file_info_get_name (info));
  67. if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
  68. success = directory_delete_recursive (child, error);
  69. }
  70. g_object_unref (info);
  71. if (success)
  72. success = g_file_delete (child, NULL, error);
  73. }
  74. g_file_enumerator_close (enumerator, NULL, NULL);
  75. if (success)
  76. success = g_file_delete (directory, NULL, error);
  77. return success;
  78. }
  79. /**
  80. * capplet_file_delete_recursive :
  81. * @file :
  82. * @error :
  83. *
  84. * A utility routine to delete files and/or directories,
  85. * including non-empty directories.
  86. **/
  87. static gboolean
  88. capplet_file_delete_recursive (GFile *file, GError **error)
  89. {
  90. GFileInfo *info;
  91. GFileType type;
  92. g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
  93. info = g_file_query_info (file,
  94. G_FILE_ATTRIBUTE_STANDARD_TYPE,
  95. G_FILE_QUERY_INFO_NONE,
  96. NULL, error);
  97. if (info == NULL)
  98. return FALSE;
  99. type = g_file_info_get_file_type (info);
  100. g_object_unref (info);
  101. if (type == G_FILE_TYPE_DIRECTORY)
  102. return directory_delete_recursive (file, error);
  103. else
  104. return g_file_delete (file, NULL, error);
  105. }
  106. void
  107. delete_custom_theme_dir (void)
  108. {
  109. char *dir;
  110. GFile *file;
  111. dir = custom_theme_dir_path (NULL);
  112. file = g_file_new_for_path (dir);
  113. g_free (dir);
  114. capplet_file_delete_recursive (file, NULL);
  115. g_object_unref (file);
  116. g_debug ("deleted the custom theme dir");
  117. }
  118. gboolean
  119. custom_theme_dir_is_empty (void)
  120. {
  121. char *dir;
  122. GFile *file;
  123. gboolean is_empty;
  124. GFileEnumerator *enumerator;
  125. GFileInfo *info;
  126. GError *error = NULL;
  127. dir = custom_theme_dir_path (NULL);
  128. file = g_file_new_for_path (dir);
  129. g_free (dir);
  130. is_empty = TRUE;
  131. enumerator = g_file_enumerate_children (file,
  132. G_FILE_ATTRIBUTE_STANDARD_NAME ","
  133. G_FILE_ATTRIBUTE_STANDARD_TYPE,
  134. G_FILE_QUERY_INFO_NONE,
  135. NULL, &error);
  136. if (enumerator == NULL) {
  137. g_warning ("Unable to enumerate files: %s", error->message);
  138. g_error_free (error);
  139. goto out;
  140. }
  141. while (is_empty &&
  142. (info = g_file_enumerator_next_file (enumerator, NULL, NULL))) {
  143. if (strcmp ("index.theme", g_file_info_get_name (info)) != 0) {
  144. is_empty = FALSE;
  145. }
  146. g_object_unref (info);
  147. }
  148. g_file_enumerator_close (enumerator, NULL, NULL);
  149. out:
  150. g_object_unref (file);
  151. return is_empty;
  152. }
  153. static void
  154. delete_one_file (const char *sound_name, const char *pattern)
  155. {
  156. GFile *file;
  157. char *name, *filename;
  158. name = g_strdup_printf (pattern, sound_name);
  159. filename = custom_theme_dir_path (name);
  160. g_free (name);
  161. file = g_file_new_for_path (filename);
  162. g_free (filename);
  163. capplet_file_delete_recursive (file, NULL);
  164. g_object_unref (file);
  165. }
  166. void
  167. delete_old_files (const char **sounds)
  168. {
  169. guint i;
  170. for (i = 0; sounds[i] != NULL; i++) {
  171. delete_one_file (sounds[i], "%s.ogg");
  172. }
  173. }
  174. void
  175. delete_disabled_files (const char **sounds)
  176. {
  177. guint i;
  178. for (i = 0; sounds[i] != NULL; i++)
  179. delete_one_file (sounds[i], "%s.disabled");
  180. }
  181. static void
  182. create_one_file (GFile *file)
  183. {
  184. GFileOutputStream* stream;
  185. stream = g_file_create (file, G_FILE_CREATE_NONE, NULL, NULL);
  186. if (stream != NULL) {
  187. g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, NULL);
  188. g_object_unref (stream);
  189. }
  190. }
  191. void
  192. add_disabled_file (const char **sounds)
  193. {
  194. guint i;
  195. for (i = 0; sounds[i] != NULL; i++) {
  196. GFile *file;
  197. char *name, *filename;
  198. name = g_strdup_printf ("%s.disabled", sounds[i]);
  199. filename = custom_theme_dir_path (name);
  200. g_free (name);
  201. file = g_file_new_for_path (filename);
  202. g_free (filename);
  203. create_one_file (file);
  204. g_object_unref (file);
  205. }
  206. }
  207. void
  208. add_custom_file (const char **sounds, const char *filename)
  209. {
  210. guint i;
  211. for (i = 0; sounds[i] != NULL; i++) {
  212. GFile *file;
  213. char *name, *path;
  214. /* We use *.ogg because it's the first type of file that
  215. * libcanberra looks at */
  216. name = g_strdup_printf ("%s.ogg", sounds[i]);
  217. path = custom_theme_dir_path (name);
  218. g_free (name);
  219. /* In case there's already a link there, delete it */
  220. g_unlink (path);
  221. file = g_file_new_for_path (path);
  222. g_free (path);
  223. /* Create the link */
  224. g_file_make_symbolic_link (file, filename, NULL, NULL);
  225. g_object_unref (file);
  226. }
  227. }
  228. void
  229. create_custom_theme (const char *parent)
  230. {
  231. GKeyFile *keyfile;
  232. char *data;
  233. char *path;
  234. /* Create the custom directory */
  235. path = custom_theme_dir_path (NULL);
  236. g_mkdir_with_parents (path, 0755);
  237. g_free (path);
  238. /* Set the data for index.theme */
  239. keyfile = g_key_file_new ();
  240. g_key_file_set_string (keyfile, "Sound Theme", "Name", _("Custom"));
  241. g_key_file_set_string (keyfile, "Sound Theme", "Inherits", parent);
  242. g_key_file_set_string (keyfile, "Sound Theme", "Directories", ".");
  243. data = g_key_file_to_data (keyfile, NULL, NULL);
  244. g_key_file_free (keyfile);
  245. /* Save the index.theme */
  246. path = custom_theme_dir_path ("index.theme");
  247. g_file_set_contents (path, data, -1, NULL);
  248. g_free (path);
  249. g_free (data);
  250. custom_theme_update_time ();
  251. }