diff options
author | Viktor Semykin <thesame.ml@gmail.com> | 2010-05-25 03:37:44 +0300 |
---|---|---|
committer | Viktor Semykin <thesame.ml@gmail.com> | 2010-05-25 03:37:44 +0300 |
commit | 8c012917f5530d947c1a31adfc6aba4b0cf3853c (patch) | |
tree | f9183ee845fd497006dde0c5f80049714a15d9a4 /plugins | |
parent | be0f4b1926f7e77c7e03eae7b70ec12f1b905025 (diff) |
Misc plugin actions
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/gtkui/plcommon.c | 48 | ||||
-rw-r--r-- | plugins/lastfm/lastfm.c | 62 | ||||
-rw-r--r-- | plugins/shellexec/Makefile.am | 9 | ||||
-rw-r--r-- | plugins/shellexec/shellexec.c | 125 |
4 files changed, 238 insertions, 6 deletions
diff --git a/plugins/gtkui/plcommon.c b/plugins/gtkui/plcommon.c index 96ddff69..3b72b901 100644 --- a/plugins/gtkui/plcommon.c +++ b/plugins/gtkui/plcommon.c @@ -346,6 +346,14 @@ on_remove_from_disk_activate (GtkMenuItem *menuitem, } void +actionitem_activate (GtkMenuItem *menuitem, + DB_single_action_t *action) +{ + DB_playItem_t *it = deadbeef->pl_get_for_idx_and_iter (clicked_idx, PL_MAIN); + action->callback (it, action->data); +} + +void list_context_menu (DdbListview *listview, DdbListviewIter it, int idx) { clicked_idx = deadbeef->pl_get_idx_of (it); int inqueue = deadbeef->pl_playqueue_test (it); @@ -399,6 +407,46 @@ list_context_menu (DdbListview *listview, DdbListviewIter it, int idx) { gtk_container_add (GTK_CONTAINER (playlist_menu), separator8); gtk_widget_set_sensitive (separator8, FALSE); + /// + int count; + int i, j; + GtkWidget *actionitem; + DB_single_action_t *actions[4]; + DB_plugin_t **plugins = deadbeef->plug_get_list(); + for (i = 0; plugins[i]; i++) + { + if (plugins[i]->type != DB_PLUGIN_MISC) + continue; + + DB_misc_t *misc = (DB_misc_t*)plugins[i]; + if (!misc->get_single_actions) + continue; + + count = 4; + if (!misc->get_single_actions (it, actions, &count)) + continue; + + if (count == 0) + continue; + + for (j = 0; j < count; j++) + { + actionitem = gtk_menu_item_new_with_mnemonic (actions[j]->title); + gtk_widget_show (actionitem); + gtk_container_add (GTK_CONTAINER (playlist_menu), actionitem); + g_object_set_data (G_OBJECT (actionitem), "ps", listview); + + g_signal_connect ((gpointer) actionitem, "activate", + G_CALLBACK (actionitem_activate), + actions[j]); + } + separator8 = gtk_separator_menu_item_new (); + gtk_widget_show (separator8); + gtk_container_add (GTK_CONTAINER (playlist_menu), separator8); + gtk_widget_set_sensitive (separator8, FALSE); + } + /// + properties1 = gtk_menu_item_new_with_mnemonic ("Properties"); gtk_widget_show (properties1); gtk_container_add (GTK_CONTAINER (playlist_menu), properties1); diff --git a/plugins/lastfm/lastfm.c b/plugins/lastfm/lastfm.c index 3ba8def8..02dff618 100644 --- a/plugins/lastfm/lastfm.c +++ b/plugins/lastfm/lastfm.c @@ -334,26 +334,31 @@ lfm_fetch_song_info (DB_playItem_t *song, const char **a, const char **t, const static int lfm_uri_encode (char *out, int outl, const char *str) { int l = outl; - static const char echars[] = " ;/?:@=#&+"; //trace ("lfm_uri_encode %p %d %s\n", out, outl, str); while (*str) { if (outl <= 1) { //trace ("no space left for 1 byte in buffer\n"); return -1; } - if (strchr (echars, *str)) { + + if (!( + (*str >= '0' && *str <= '9') || + (*str >= 'a' && *str <= 'z') || + (*str >= 'A' && *str <= 'Z') || + (*str == ' ') + )) + { if (outl <= 3) { //trace ("no space left for 3 bytes in the buffer\n"); return -1; } - //trace ("adding escaped value for %c\n", *str); - snprintf (out, outl, "%%%02x", (int)*str); + snprintf (out, outl, "%%%02x", (uint8_t)*str); outl -= 3; str++; out += 3; } else { - *out = *str; + *out = *str == ' ' ? '+' : *str; out++; str++; outl--; @@ -819,6 +824,50 @@ lastfm_stop (void) { return 0; } +static int +lfm_action_lookup (DB_playItem_t *it, void *data) +{ + const char *artist = deadbeef->pl_find_meta (it, "artist"); + const char *title = deadbeef->pl_find_meta (it, "title"); + + if (!title || !artist) + return 0; + + char eartist [strlen (artist) * 3 + 1]; + char etitle [strlen (title) * 3 + 1]; + + if (-1 == lfm_uri_encode (eartist, sizeof (eartist), artist)) + return 0; + + if (-1 == lfm_uri_encode (etitle, sizeof (etitle), title)) + return 0; + + char *command = NULL; + if (-1 == asprintf (&command, "xdg-open http://www.last.fm/music/%s/_/%s", eartist, etitle)) + return 0; + system (command); + free (command); +} + +static DB_single_action_t lookup_action = { + .title = "Lookup at Last.fm", + .callback = lfm_action_lookup +}; + +static int +lfm_get_single_actions (DB_playItem_t *it, DB_single_action_t *actions[], int *size) +{ + if (deadbeef->pl_find_meta (it, "artist") && + deadbeef->pl_find_meta (it, "title")) + { + actions[0] = &lookup_action; + *size = 1; + } + else + *size = 0; + return 1; +} + static const char settings_dlg[] = "property \"Enable scrobbler\" checkbox lastfm.enable 0;" "property \"Disable nowplaying\" checkbox lastfm.disable_np 0;" @@ -840,5 +889,6 @@ static DB_misc_t plugin = { .plugin.website = "http://deadbeef.sf.net", .plugin.start = lastfm_start, .plugin.stop = lastfm_stop, - .plugin.configdialog = settings_dlg + .plugin.configdialog = settings_dlg, + .get_single_actions = lfm_get_single_actions }; diff --git a/plugins/shellexec/Makefile.am b/plugins/shellexec/Makefile.am new file mode 100644 index 00000000..65d6a5b8 --- /dev/null +++ b/plugins/shellexec/Makefile.am @@ -0,0 +1,9 @@ +if HAVE_SHELLEXEC +shxdir = $(libdir)/$(PACKAGE) +pkglib_LTLIBRARIES = shellexec.la +shellexec_la_SOURCES = shellexec.c +shellexec_la_LDFLAGS = -module + +shellexec_la_LIBADD = $(LDADD) $(HOTKEYS_LIBS) +AM_CFLAGS = $(CFLAGS) -std=c99 +endif diff --git a/plugins/shellexec/shellexec.c b/plugins/shellexec/shellexec.c new file mode 100644 index 00000000..39e7f4da --- /dev/null +++ b/plugins/shellexec/shellexec.c @@ -0,0 +1,125 @@ +/* + Shellexec plugin for DeaDBeeF + Copyright (C) 2009 Viktor Semykin <thesame.ml@gmail.com> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +#include <stdio.h> +#include <string.h> + +#include "../../deadbeef.h" + +#define MAX_COMMANDS 128 + +#define trace(...) { fprintf(stderr, __VA_ARGS__); } +//#define trace(fmt,...) + +static DB_misc_t plugin; +static DB_functions_t *deadbeef; + +DB_single_action_t shx_actions [MAX_COMMANDS]; +static int single_action_count; + +DB_plugin_t * +shellexec_load (DB_functions_t *api) { + deadbeef = api; + return DB_PLUGIN (&plugin); +} + +static int +shx_get_single_actions (DB_playItem_t *it, DB_single_action_t *actions[], int *size) +{ + if (*size < single_action_count) + return 0; + + int i; + *size = single_action_count; + trace ("Shellexec: %d actions\n", single_action_count); + for (i=0; i < single_action_count; i++) + actions[i] = &shx_actions[i]; + return 1; +} + +static int +shx_callback (DB_playItem_t *it, void *data) +{ + char fmt[1024]; //FIXME: possible stack corruption + deadbeef->pl_format_title (it, -1, fmt, sizeof (fmt), -1, data); + printf ("%s\n", fmt); + return 0; +} + +static char* +trim (char* s) +{ + char *h, *t; + + for (h = s; *h == ' ' || *h == '\t'; h++); + for (t = s + strlen (s); *t == ' ' || *t == '\t'; t--); + * (t+1) = 0; + return h; +} + +static int +shellexec_start (void) +{ + trace ("Starting shellexec\n"); + single_action_count = 0; + DB_conf_item_t *item = deadbeef->conf_find ("shellexec.", NULL); + while (item) + { + if (single_action_count == MAX_COMMANDS) + { + fprintf (stdout, "Shellexec: max number of commands (%d) exceeded\n", MAX_COMMANDS); + break; + } + size_t l = strlen (item->value) + 1; + char tmp[l]; + strcpy (tmp, item->value); + trace ("Shellexec: %s\n", tmp); + + char *semicolon = strchr (tmp, ':'); + if (!semicolon) + { + fprintf (stdout, "Shellexec: wrong option <%s>\n", tmp); + continue; + } + + *semicolon = 0; + + shx_actions[single_action_count].title = strdup (trim (semicolon + 1)); + shx_actions[single_action_count].callback = shx_callback; + shx_actions[single_action_count].data = strdup (trim (tmp)); + + item = deadbeef->conf_find ("shellexec.", item); + single_action_count++; + } +} + +// define plugin interface +static DB_misc_t plugin = { + .plugin.api_vmajor = DB_API_VERSION_MAJOR, + .plugin.api_vminor = DB_API_VERSION_MINOR, + .plugin.type = DB_PLUGIN_MISC, + .plugin.id = "shellexec", + .plugin.name = "Shell commands for tracks", + .plugin.descr = "Executes configurable shell commands for tracks", + .plugin.author = "Viktor Semykin", + .plugin.email = "thesame.ml@gmail.com", + .plugin.website = "http://deadbeef.sf.net", + .plugin.start = shellexec_start, + + .get_single_actions = shx_get_single_actions +}; + |