1 /*
2  * Copyright (C) 2007 Jonh Wendell <wendell@bani.com.br>
3  *
4  * Sound Juicer - sj-genres.c
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU 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, see <http://www.gnu.org/licenses/>.
18  *
19  * Authors: Jonh Wendell <wendell@bani.com.br>
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 
26 #include <string.h>
27 #include <stdlib.h>
28 #include <glib/gi18n.h>
29 
30 #include "sj-genres.h"
31 
32 static const char* const known_genres[] = {
33   N_("Ambient"),
34   N_("Blues"),
35   N_("Classical"),
36   N_("Country"),
37   N_("Dance"),
38   N_("Electronica"),
39   N_("Folk"),
40   N_("Funk"),
41   N_("Jazz"),
42   N_("Latin"),
43   N_("Pop"),
44   N_("Rap"),
45   N_("Reggae"),
46   N_("Rock"),
47   N_("Soul"),
48   N_("Spoken Word")
49 };
50 
is_known_genre(const char * str)51 static gboolean is_known_genre (const char *str) {
52   guint i;
53 
54   for (i = 0; i < G_N_ELEMENTS(known_genres); i++) {
55     if (strcasecmp (str, _(known_genres[i])) == 0)
56       return TRUE;
57   }
58   return FALSE;
59 }
60 
in_array(const char * str,const char ** array)61 static gboolean in_array (const char *str, const char** array) {
62   const char **list = array;
63   gboolean found = FALSE;
64 
65   while (*list != NULL)
66     if (strcasecmp (str, *list++) == 0)
67       return TRUE;
68 
69   return found;
70 }
71 
genre_filename(void)72 static char* genre_filename (void) {
73   return g_build_filename (g_get_user_config_dir (),
74 			   "sound-juicer",
75 			   "genres",
76 			   NULL);
77 }
78 
saved_genres(void)79 static char** saved_genres (void) {
80   char *filename, *file_contents = NULL;
81   char **genres_from_file = NULL;
82   gboolean success;
83   int len;
84 
85   filename = genre_filename ();
86   success = g_file_get_contents (filename,
87 				 &file_contents,
88 				 NULL,
89 				 NULL);
90 
91   g_free (filename);
92 
93   if (success) {
94     genres_from_file = g_strsplit (file_contents, "\n", 0);
95     len = g_strv_length (genres_from_file);
96     if (len >= 1) {
97       if (strlen (genres_from_file[len-1]) == 0) {
98         g_free (genres_from_file[len-1]);
99         genres_from_file[len-1] = NULL;
100       }
101     }
102 
103     g_free (file_contents);
104   }
105 
106   return genres_from_file;
107 }
108 
create_genre_list(void)109 static GtkTreeModel* create_genre_list (void) {
110   GtkListStore *store;
111   guint i;
112   char **genres;
113 
114   store = gtk_list_store_new (1, G_TYPE_STRING);
115 
116   for (i = 0; i < G_N_ELEMENTS(known_genres); i++) {
117     gtk_list_store_insert_with_values (store, NULL, -1,
118                                        0, _(known_genres[i]),
119                                        -1);
120   }
121 
122   genres = saved_genres ();
123   if (genres) {
124     for (i = 0; genres[i] != NULL; i++) {
125       gtk_list_store_insert_with_values (store, NULL, -1,
126                                          0, genres[i],
127                                          -1);
128     }
129 
130     g_strfreev (genres);
131   }
132 
133   return GTK_TREE_MODEL (store);
134 }
135 
setup_genre_entry(GtkWidget * entry)136 void setup_genre_entry (GtkWidget *entry) {
137   GtkEntryCompletion *completion;
138 
139   g_return_if_fail (GTK_IS_ENTRY (entry));
140 
141   completion = gtk_entry_get_completion (GTK_ENTRY (entry));
142   if (completion != NULL)
143     g_object_unref (completion);
144 
145   completion = gtk_entry_completion_new ();
146   gtk_entry_completion_set_model (completion, create_genre_list ());
147   gtk_entry_completion_set_text_column (completion, 0);
148   gtk_entry_completion_set_inline_completion (completion, TRUE);
149   gtk_entry_set_completion (GTK_ENTRY (entry), completion);
150 }
151 
save_genre(GtkWidget * entry)152 void save_genre (GtkWidget *entry) {
153   const char *genre;
154   char **genres;
155   int len;
156   char *content, *filename, *path;
157   GError *error = NULL;
158 
159   g_return_if_fail (GTK_IS_ENTRY (entry));
160 
161   genre = gtk_entry_get_text (GTK_ENTRY (entry));
162 
163   if (is_known_genre (genre))
164     return;
165 
166   len = 0;
167   genres = saved_genres ();
168   if (genres) {
169     if (in_array ((const char *)genre, (const char **) genres)) {
170       g_strfreev (genres);
171       return;
172     }
173     len = g_strv_length (genres);
174   }
175 
176   genres = realloc (genres, (len + 2) * sizeof (char *));
177   genres[len] = g_strjoin (NULL, genre, "\n", NULL);
178   genres[len+1] = NULL;
179 
180   content = g_strjoinv ("\n", genres);
181   filename = genre_filename ();
182 
183   path = g_path_get_dirname (filename);
184   g_mkdir_with_parents (path, 0755);
185   g_free (path);
186 
187   g_file_set_contents (filename,
188 		       content,
189 		       -1,
190 		       &error);
191 
192   g_free (filename);
193   g_free (content);
194   g_strfreev (genres);
195 
196   if (error) {
197     g_warning (_("Error while saving custom genre: %s"), error->message);
198     g_error_free (error);
199   }
200 
201   setup_genre_entry (entry);
202 }
203