1 /* EasyTAG - tag editor for audio files
2  * Copyright (C) 2014 Victor A. Santos <victoraur.santos@gmail.com>
3  * Copyright (C) 2014 David King <amigadave@amigadave.com>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "config.h"
20 
21 #include <string.h>
22 #include <gio/gio.h>
23 #include <gio/gdesktopappinfo.h>
24 #include <glib/gi18n-lib.h>
25 #include <libnautilus-extension/nautilus-extension-types.h>
26 #include <libnautilus-extension/nautilus-file-info.h>
27 #include <libnautilus-extension/nautilus-menu-provider.h>
28 
29 #define NAUTILUS_TYPE_EASYTAG (nautilus_easytag_get_type ())
30 #define NAUTILUS_EASYTAG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NAUTILUS_TYPE_EASYTAG, NautilusEasytag))
31 #define NAUTILUS_IS_EASYTAG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NAUTILUS_TYPE_EASYTAG))
32 
33 typedef struct _NautilusEasytag NautilusEasytag;
34 typedef struct _NautilusEasytagClass NautilusEasytagClass;
35 
36 struct _NautilusEasytag
37 {
38     GObject parent;
39 };
40 
41 struct _NautilusEasytagClass
42 {
43     GObjectClass parent_class;
44 };
45 
46 GType nautilus_easytag_get_type (void);
47 
48 typedef struct
49 {
50     gboolean is_directory;
51     gboolean is_file;
52 } FileMimeInfo;
53 
54 static struct
55 {
56     const gchar *mime_type;
57     gboolean is_directory;
58     gboolean is_file;
59 } easytag_mime_types[] =
60 {
61     { "inode/directory", TRUE, FALSE },
62     { "audio/x-mp3", FALSE, TRUE },
63     { "audio/x-mpeg", FALSE, TRUE },
64     { "audio/mpeg", FALSE, TRUE },
65     { "application/ogg", FALSE, TRUE },
66     { "audio/x-vorbis+ogg", FALSE, TRUE },
67     { "audio/x-flac", FALSE, TRUE },
68     { "audio/x-musepack", FALSE, TRUE },
69     { "audio/x-ape", FALSE, TRUE },
70     { "audio/x-speex+ogg", FALSE, TRUE },
71     { "audio/x-opus+ogg", FALSE, TRUE },
72     { NULL, FALSE }
73 };
74 
75 static gboolean
unsupported_scheme(NautilusFileInfo * file)76 unsupported_scheme (NautilusFileInfo *file)
77 {
78     gboolean result = FALSE;
79     GFile *location;
80     gchar *scheme;
81 
82     location = nautilus_file_info_get_location (file);
83     scheme = g_file_get_uri_scheme (location);
84 
85     if (scheme != NULL)
86     {
87         const gchar *unsupported[] = { "trash", "computer", NULL };
88         gsize i;
89 
90         for (i = 0; unsupported[i] != NULL; i++)
91         {
92             if (strcmp (scheme, unsupported[i]) == 0)
93             {
94                 result = TRUE;
95             }
96         }
97     }
98 
99     g_free (scheme);
100     g_object_unref (location);
101 
102     return result;
103 }
104 
105 static FileMimeInfo
get_file_mime_info(NautilusFileInfo * file)106 get_file_mime_info (NautilusFileInfo *file)
107 {
108     FileMimeInfo file_mime_info;
109     gsize i;
110 
111     file_mime_info.is_directory = FALSE;
112     file_mime_info.is_file = FALSE;
113 
114     for (i = 0; easytag_mime_types[i].mime_type != NULL; i++)
115     {
116         if (nautilus_file_info_is_mime_type (file,
117                                              easytag_mime_types[i].mime_type))
118         {
119             file_mime_info.is_directory = easytag_mime_types[i].is_directory;
120             file_mime_info.is_file = easytag_mime_types[i].is_file;
121 
122             return file_mime_info;
123         }
124     }
125 
126     return file_mime_info;
127 }
128 
129 static void
on_open_in_easytag(NautilusMenuItem * item,gpointer data)130 on_open_in_easytag (NautilusMenuItem *item,
131                     gpointer data)
132 {
133     NautilusFileInfo *dir;
134     GDesktopAppInfo *appinfo;
135 
136     dir = g_object_get_data (G_OBJECT (item), "dir");
137 
138     appinfo = g_desktop_app_info_new ("easytag.desktop");
139 
140     if (appinfo)
141     {
142         GdkAppLaunchContext *context;
143         GList *uris = NULL;
144 
145         uris = g_list_append (uris, nautilus_file_info_get_uri (dir));
146         context = gdk_display_get_app_launch_context (gdk_display_get_default ());
147 
148         g_app_info_launch_uris (G_APP_INFO (appinfo), uris,
149                                 G_APP_LAUNCH_CONTEXT (context), NULL);
150     }
151 }
152 
153 static void
on_open_with_easytag(NautilusMenuItem * item,gpointer data)154 on_open_with_easytag (NautilusMenuItem *item,
155                       gpointer data)
156 {
157     GList *files;
158     GDesktopAppInfo *appinfo;
159 
160     files = g_object_get_data (G_OBJECT (item), "files");
161 
162     appinfo = g_desktop_app_info_new ("easytag.desktop");
163 
164     if (appinfo)
165     {
166         GdkAppLaunchContext *context;
167         GList *l;
168         GList *uris = NULL;
169 
170         for (l = files; l != NULL; l = g_list_next (l))
171         {
172             uris = g_list_append (uris,
173                                   nautilus_file_info_get_uri (l->data));
174         }
175 
176         context = gdk_display_get_app_launch_context (gdk_display_get_default ());
177 
178         g_app_info_launch_uris (G_APP_INFO (appinfo), uris,
179                                 G_APP_LAUNCH_CONTEXT (context), NULL);
180     }
181 }
182 
183 static GList *
nautilus_easytag_get_file_items(NautilusMenuProvider * provider,GtkWidget * window,GList * files)184 nautilus_easytag_get_file_items (NautilusMenuProvider *provider,
185                                  GtkWidget *window,
186                                  GList *files)
187 {
188     GList *items = NULL;
189     GList *l;
190     gboolean one_item;
191     gboolean one_directory = TRUE;
192     gboolean all_files = TRUE;
193 
194     if (files == NULL)
195     {
196         return NULL;
197     }
198 
199     if (unsupported_scheme ((NautilusFileInfo *)files->data))
200     {
201         return NULL;
202     }
203 
204     for (l = files; l != NULL; l = g_list_next (l))
205     {
206         FileMimeInfo file_mime_info;
207         NautilusFileInfo *file = l->data;
208 
209         file_mime_info = get_file_mime_info (file);
210 
211         if (all_files && !file_mime_info.is_file)
212         {
213             all_files = FALSE;
214         }
215 
216         if (one_directory && !file_mime_info.is_directory)
217         {
218             one_directory = FALSE;
219         }
220     }
221 
222     one_item = (files != NULL) && (files->next == NULL);
223 
224     if (one_directory && one_item)
225     {
226         NautilusMenuItem *item;
227 
228         item = nautilus_menu_item_new ("NautilusEasytag::open_directory",
229                                        _("Open in EasyTAG"),
230                                        _("Open the selected directory in EasyTAG"),
231                                        "easytag");
232         g_signal_connect (item,
233                           "activate",
234                           G_CALLBACK (on_open_in_easytag),
235                           provider);
236         g_object_set_data (G_OBJECT (item),
237                            "dir",
238                            files->data);
239 
240         items = g_list_append (items, item);
241     }
242     else if (all_files)
243     {
244         NautilusMenuItem *item;
245 
246         item = nautilus_menu_item_new ("NautilusEasytag::open_files",
247                                        _("Open with EasyTAG"),
248                                        _("Open the selected files in EasyTAG"),
249                                        "easytag");
250         g_signal_connect (item,
251                           "activate",
252                           G_CALLBACK (on_open_with_easytag),
253                           provider);
254         g_object_set_data_full (G_OBJECT (item),
255                                 "files",
256                                 nautilus_file_info_list_copy (files),
257                                 (GDestroyNotify) nautilus_file_info_list_free);
258 
259         items = g_list_append (items, item);
260     }
261 
262     return items;
263 }
264 
265 static void
nautilus_easytag_menu_provider_iface_init(NautilusMenuProviderIface * iface)266 nautilus_easytag_menu_provider_iface_init (NautilusMenuProviderIface *iface)
267 {
268     iface->get_file_items = nautilus_easytag_get_file_items;
269 }
270 
271 G_DEFINE_DYNAMIC_TYPE_EXTENDED (NautilusEasytag,
272                                 nautilus_easytag,
273                                 G_TYPE_OBJECT,
274                                 0,
275                                 G_IMPLEMENT_INTERFACE_DYNAMIC (NAUTILUS_TYPE_MENU_PROVIDER,
276                                                                nautilus_easytag_menu_provider_iface_init));
277 
278 static void
nautilus_easytag_init(NautilusEasytag * self)279 nautilus_easytag_init (NautilusEasytag *self)
280 {
281 }
282 
283 static void
nautilus_easytag_class_init(NautilusEasytagClass * class)284 nautilus_easytag_class_init (NautilusEasytagClass *class)
285 {
286     bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
287     bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
288 }
289 
290 static void
nautilus_easytag_class_finalize(NautilusEasytagClass * class)291 nautilus_easytag_class_finalize (NautilusEasytagClass *class)
292 {
293 }
294 
295 /* Nautilus extension module. */
296 static GType type_list[1];
297 
298 void
nautilus_module_initialize(GTypeModule * module)299 nautilus_module_initialize (GTypeModule *module)
300 {
301     nautilus_easytag_register_type (module);
302 
303     type_list[0] = NAUTILUS_TYPE_EASYTAG;
304 }
305 
306 void
nautilus_module_shutdown(void)307 nautilus_module_shutdown (void)
308 {
309 }
310 
311 void
nautilus_module_list_types(const GType ** types,int * num_types)312 nautilus_module_list_types (const GType **types,
313                             int *num_types)
314 {
315     *types = type_list;
316     *num_types = G_N_ELEMENTS (type_list);
317 }
318