From 893bbd516e7c0b7e6b7e49fe472e49284134cc1f Mon Sep 17 00:00:00 2001 From: waker Date: Thu, 2 Dec 2010 22:23:43 +0100 Subject: converter prototype --- plugins/gtkui/Makefile.am | 3 +- plugins/gtkui/callbacks.h | 26 +++++ plugins/gtkui/converter.c | 203 ++++++++++++++++++++++++++++++++++++++ plugins/gtkui/converter.h | 26 +++++ plugins/gtkui/deadbeef.glade | 226 +++++++++++++++++++++++++++++++++++++++++++ plugins/gtkui/interface.c | 111 +++++++++++++++++++++ plugins/gtkui/interface.h | 1 + plugins/gtkui/plcommon.c | 15 +++ 8 files changed, 610 insertions(+), 1 deletion(-) create mode 100644 plugins/gtkui/converter.c create mode 100644 plugins/gtkui/converter.h (limited to 'plugins') diff --git a/plugins/gtkui/Makefile.am b/plugins/gtkui/Makefile.am index cea8e94dc..90e89008 100644 --- a/plugins/gtkui/Makefile.am +++ b/plugins/gtkui/Makefile.am @@ -32,7 +32,8 @@ GTKUI_SOURCES = gtkui.c gtkui.h\ plcommon.c plcommon.h\ prefwin.c\ eq.c eq.h\ - actions.c actions.h + actions.c actions.h\ + converter.c converter.h EXTRA_DIST = $(gtkui_VALASOURCES) deadbeef.glade diff --git a/plugins/gtkui/callbacks.h b/plugins/gtkui/callbacks.h index b88df53c..e994734c 100644 --- a/plugins/gtkui/callbacks.h +++ b/plugins/gtkui/callbacks.h @@ -983,3 +983,29 @@ on_jump_to_current_track1_activate (GtkMenuItem *menuitem, void on_translators1_activate (GtkMenuItem *menuitem, gpointer user_data); + +void +on_converter_output_browse_clicked (GtkButton *button, + gpointer user_data); + +void +on_converter_cancel_clicked (GtkButton *button, + gpointer user_data); + +void +on_converter_ok_clicked (GtkButton *button, + gpointer user_data); + +void +on_converterdlg_close (GtkDialog *dialog, + gpointer user_data); + +void +on_converterdlg_response (GtkDialog *dialog, + gint response_id, + gpointer user_data); + +gboolean +on_converterdlg_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); diff --git a/plugins/gtkui/converter.c b/plugins/gtkui/converter.c new file mode 100644 index 00000000..f1a5031d --- /dev/null +++ b/plugins/gtkui/converter.c @@ -0,0 +1,203 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009-2010 Alexey Yakovenko + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#include +#include +#include +#include "converter.h" +#include "support.h" +#include "interface.h" +#include "gtkui.h" + +static GtkWidget *converter; + +void +converter_show (void) { + if (!converter) { + converter = create_converterdlg (); + gtk_entry_set_text (GTK_ENTRY (lookup_widget (converter, "output_folder")), deadbeef->conf_get_str ("converter.output_folder", "")); + gtk_entry_set_text (GTK_ENTRY (lookup_widget (converter, "encoder_cmd_line")), deadbeef->conf_get_str ("converter.encoder", "")); + } + gtk_widget_show (converter); +} + +void +on_converter_output_browse_clicked (GtkButton *button, + gpointer user_data) +{ + GtkWidget *dlg = gtk_file_chooser_dialog_new (_("Select folder..."), GTK_WINDOW (converter), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL); + + gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dlg), FALSE); + // restore folder + gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dlg), deadbeef->conf_get_str ("filechooser.lastdir", "")); + int response = gtk_dialog_run (GTK_DIALOG (dlg)); + // store folder + gchar *folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dlg)); + if (folder) { + deadbeef->conf_set_str ("filechooser.lastdir", folder); + g_free (folder); + deadbeef->sendmessage (M_CONFIGCHANGED, 0, 0, 0); + } + if (response == GTK_RESPONSE_OK) { + folder = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dlg)); + gtk_widget_destroy (dlg); + if (folder) { + GtkWidget *entry = lookup_widget (converter, "output_folder"); + gtk_entry_set_text (GTK_ENTRY (entry), folder); + g_free (folder); + } + } + else { + gtk_widget_destroy (dlg); + } + converter = NULL; +} + + +void +on_converter_cancel_clicked (GtkButton *button, + gpointer user_data) +{ + gtk_widget_destroy (converter); + converter = NULL; +} + +DB_decoder_t * +plug_get_decoder_for_id (const char *id) { + DB_decoder_t **plugins = deadbeef->plug_get_decoder_list (); + for (int c = 0; plugins[c]; c++) { + if (!strcmp (id, plugins[c]->plugin.id)) { + return plugins[c]; + } + } + return NULL; +} + + +void +on_converter_ok_clicked (GtkButton *button, + gpointer user_data) +{ + char *outfolder = strdup (gtk_entry_get_text (GTK_ENTRY (lookup_widget (converter, "output_folder")))); + deadbeef->conf_set_str ("converter.output_folder", outfolder); + char *encoder = strdup (gtk_entry_get_text (GTK_ENTRY (lookup_widget (converter, "encoder_cmd_line")))); + deadbeef->conf_set_str ("converter.encoder", encoder); + deadbeef->conf_save (); + gtk_widget_destroy (converter); + converter = NULL; + + deadbeef->pl_lock (); + + // copy list + int nsel = deadbeef->pl_getselcount (); + if (0 < nsel) { + DB_playItem_t **items = malloc (sizeof (DB_playItem_t *) * nsel); + if (items) { + int n = 0; + DB_playItem_t *it = deadbeef->pl_get_first (PL_MAIN); + while (it) { + if (deadbeef->pl_is_selected (it)) { + assert (n < nsel); + deadbeef->pl_item_ref (it); + items[n++] = it; + } + DB_playItem_t *next = deadbeef->pl_get_next (it, PL_MAIN); + deadbeef->pl_item_unref (it); + it = next; + } + deadbeef->pl_unlock (); + + // ... convert ... + for (n = 0; n < nsel; n++) { + it = items[n]; + DB_decoder_t *dec = NULL; + dec = plug_get_decoder_for_id (items[n]->decoder_id); + if (dec) { + DB_fileinfo_t *fileinfo = dec->open (0); + if (fileinfo && dec->init (fileinfo, DB_PLAYITEM (it)) != 0) { + dec->free (fileinfo); + fileinfo = NULL; + } + if (fileinfo) { + char *fname = strrchr (it->fname, '/'); + if (!fname) { + fname = it->fname; + } + else { + fname++; + } + char out[1024]; + snprintf (out, sizeof (out), "%s/%s", outfolder, fname); + char enc[1024]; + snprintf (enc, sizeof (enc), encoder, out); + printf ("executing: %s\n", enc); + FILE *fp = popen (enc, "w"); + if (!fp) { + fprintf (stderr, "converter: failed to open encoder: %s\n", encoder); + } + else { + // write wave header + char wavehdr[] = { + 0x52, 0x49, 0x46, 0x46, 0x24, 0x70, 0x0d, 0x00, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x44, 0xac, 0x00, 0x00, 0x10, 0xb1, 0x02, 0x00, 0x04, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61 + }; + fwrite (wavehdr, 1, sizeof (wavehdr), fp); + uint32_t size = (it->endsample-it->startsample) * fileinfo->fmt.channels * fileinfo->fmt.bps / 8; + fwrite (&size, 1, sizeof (size), fp); + + int bs = 8192; + char buffer[bs]; + for (;;) { + int sz = dec->read (fileinfo, buffer, bs); + fwrite (buffer, 1, sz, fp); + if (sz != bs) { + break; + } + } + + pclose (fp); + } + dec->free (fileinfo); + } + } + } + + for (n = 0; n < nsel; n++) { + deadbeef->pl_item_unref (items[n]); + } + free (items); + } + else { + fprintf (stderr, "converter: error allocating memory to store %d tracks\n", nsel); + deadbeef->pl_unlock (); + } + } + + + free (outfolder); + free (encoder); +} + +gboolean +on_converterdlg_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + converter = NULL; + return FALSE; +} + diff --git a/plugins/gtkui/converter.h b/plugins/gtkui/converter.h new file mode 100644 index 00000000..56bcfe12 --- /dev/null +++ b/plugins/gtkui/converter.h @@ -0,0 +1,26 @@ +/* + DeaDBeeF - ultimate music player for GNU/Linux systems with X11 + Copyright (C) 2009-2010 Alexey Yakovenko + + 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, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#ifndef __CONVERTER_H +#define __CONVERTER_H + +void +converter_show (void); + +#endif + diff --git a/plugins/gtkui/deadbeef.glade b/plugins/gtkui/deadbeef.glade index 4f38af30..c994b913 100644 --- a/plugins/gtkui/deadbeef.glade +++ b/plugins/gtkui/deadbeef.glade @@ -6057,4 +6057,230 @@ Example: %a - %t [%l] + + True + Converter + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_DIALOG + GDK_GRAVITY_NORTH_WEST + True + False + False + + + + + True + False + 0 + + + + True + GTK_BUTTONBOX_END + + + + True + True + True + gtk-cancel + True + GTK_RELIEF_NORMAL + True + -6 + + + + + + + True + True + True + gtk-ok + True + GTK_RELIEF_NORMAL + True + -5 + + + + + + 0 + False + True + GTK_PACK_END + + + + + + 12 + True + False + 8 + + + + True + False + 8 + + + + True + Output folder + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + False + 0 + + + + True + True + True + True + 0 + + True + + False + + + 0 + True + True + + + + + + True + True + ... + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + False + + + + + 0 + True + True + + + + + 0 + False + True + + + + + + True + False + 8 + + + + True + Encoder command line + False + False + GTK_JUSTIFY_LEFT + False + False + 0.5 + 0.5 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + 0 + False + False + + + + + + True + True + True + True + 0 + + True + + False + + + 0 + True + True + + + + + 0 + False + False + + + + + 0 + True + True + + + + + + diff --git a/plugins/gtkui/interface.c b/plugins/gtkui/interface.c index 1b255c52..6cd54855 100644 --- a/plugins/gtkui/interface.c +++ b/plugins/gtkui/interface.c @@ -3184,3 +3184,114 @@ create_groupbydlg (void) return groupbydlg; } +GtkWidget* +create_converterdlg (void) +{ + GtkWidget *converterdlg; + GtkWidget *dialog_vbox6; + GtkWidget *vbox26; + GtkWidget *hbox67; + GtkWidget *label103; + GtkWidget *hbox68; + GtkWidget *output_folder; + GtkWidget *converter_output_browse; + GtkWidget *hbox69; + GtkWidget *label104; + GtkWidget *encoder_cmd_line; + GtkWidget *dialog_action_area5; + GtkWidget *converter_cancel; + GtkWidget *converter_ok; + + converterdlg = gtk_dialog_new (); + gtk_window_set_title (GTK_WINDOW (converterdlg), _("Converter")); + gtk_window_set_type_hint (GTK_WINDOW (converterdlg), GDK_WINDOW_TYPE_HINT_DIALOG); + gtk_dialog_set_has_separator (GTK_DIALOG (converterdlg), FALSE); + + dialog_vbox6 = GTK_DIALOG (converterdlg)->vbox; + gtk_widget_show (dialog_vbox6); + + vbox26 = gtk_vbox_new (FALSE, 8); + gtk_widget_show (vbox26); + gtk_box_pack_start (GTK_BOX (dialog_vbox6), vbox26, TRUE, TRUE, 0); + gtk_container_set_border_width (GTK_CONTAINER (vbox26), 12); + + hbox67 = gtk_hbox_new (FALSE, 8); + gtk_widget_show (hbox67); + gtk_box_pack_start (GTK_BOX (vbox26), hbox67, FALSE, TRUE, 0); + + label103 = gtk_label_new (_("Output folder")); + gtk_widget_show (label103); + gtk_box_pack_start (GTK_BOX (hbox67), label103, FALSE, FALSE, 0); + + hbox68 = gtk_hbox_new (FALSE, 0); + gtk_widget_show (hbox68); + gtk_box_pack_start (GTK_BOX (hbox67), hbox68, TRUE, TRUE, 0); + + output_folder = gtk_entry_new (); + gtk_widget_show (output_folder); + gtk_box_pack_start (GTK_BOX (hbox68), output_folder, TRUE, TRUE, 0); + gtk_entry_set_invisible_char (GTK_ENTRY (output_folder), 9679); + + converter_output_browse = gtk_button_new_with_mnemonic (_("...")); + gtk_widget_show (converter_output_browse); + gtk_box_pack_start (GTK_BOX (hbox68), converter_output_browse, FALSE, FALSE, 0); + + hbox69 = gtk_hbox_new (FALSE, 8); + gtk_widget_show (hbox69); + gtk_box_pack_start (GTK_BOX (vbox26), hbox69, FALSE, FALSE, 0); + + label104 = gtk_label_new (_("Encoder command line")); + gtk_widget_show (label104); + gtk_box_pack_start (GTK_BOX (hbox69), label104, FALSE, FALSE, 0); + + encoder_cmd_line = gtk_entry_new (); + gtk_widget_show (encoder_cmd_line); + gtk_box_pack_start (GTK_BOX (hbox69), encoder_cmd_line, TRUE, TRUE, 0); + gtk_entry_set_invisible_char (GTK_ENTRY (encoder_cmd_line), 9679); + + dialog_action_area5 = GTK_DIALOG (converterdlg)->action_area; + gtk_widget_show (dialog_action_area5); + gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area5), GTK_BUTTONBOX_END); + + converter_cancel = gtk_button_new_from_stock ("gtk-cancel"); + gtk_widget_show (converter_cancel); + gtk_dialog_add_action_widget (GTK_DIALOG (converterdlg), converter_cancel, GTK_RESPONSE_CANCEL); + GTK_WIDGET_SET_FLAGS (converter_cancel, GTK_CAN_DEFAULT); + + converter_ok = gtk_button_new_from_stock ("gtk-ok"); + gtk_widget_show (converter_ok); + gtk_dialog_add_action_widget (GTK_DIALOG (converterdlg), converter_ok, GTK_RESPONSE_OK); + GTK_WIDGET_SET_FLAGS (converter_ok, GTK_CAN_DEFAULT); + + g_signal_connect ((gpointer) converterdlg, "delete_event", + G_CALLBACK (on_converterdlg_delete_event), + NULL); + g_signal_connect ((gpointer) converter_output_browse, "clicked", + G_CALLBACK (on_converter_output_browse_clicked), + NULL); + g_signal_connect ((gpointer) converter_cancel, "clicked", + G_CALLBACK (on_converter_cancel_clicked), + NULL); + g_signal_connect ((gpointer) converter_ok, "clicked", + G_CALLBACK (on_converter_ok_clicked), + NULL); + + /* Store pointers to all widgets, for use by lookup_widget(). */ + GLADE_HOOKUP_OBJECT_NO_REF (converterdlg, converterdlg, "converterdlg"); + GLADE_HOOKUP_OBJECT_NO_REF (converterdlg, dialog_vbox6, "dialog_vbox6"); + GLADE_HOOKUP_OBJECT (converterdlg, vbox26, "vbox26"); + GLADE_HOOKUP_OBJECT (converterdlg, hbox67, "hbox67"); + GLADE_HOOKUP_OBJECT (converterdlg, label103, "label103"); + GLADE_HOOKUP_OBJECT (converterdlg, hbox68, "hbox68"); + GLADE_HOOKUP_OBJECT (converterdlg, output_folder, "output_folder"); + GLADE_HOOKUP_OBJECT (converterdlg, converter_output_browse, "converter_output_browse"); + GLADE_HOOKUP_OBJECT (converterdlg, hbox69, "hbox69"); + GLADE_HOOKUP_OBJECT (converterdlg, label104, "label104"); + GLADE_HOOKUP_OBJECT (converterdlg, encoder_cmd_line, "encoder_cmd_line"); + GLADE_HOOKUP_OBJECT_NO_REF (converterdlg, dialog_action_area5, "dialog_action_area5"); + GLADE_HOOKUP_OBJECT (converterdlg, converter_cancel, "converter_cancel"); + GLADE_HOOKUP_OBJECT (converterdlg, converter_ok, "converter_ok"); + + return converterdlg; +} + diff --git a/plugins/gtkui/interface.h b/plugins/gtkui/interface.h index 5c4b5923..07494690 100644 --- a/plugins/gtkui/interface.h +++ b/plugins/gtkui/interface.h @@ -13,3 +13,4 @@ GtkWidget* create_prefwin (void); GtkWidget* create_editplaylistdlg (void); GtkWidget* create_addlocationdlg (void); GtkWidget* create_groupbydlg (void); +GtkWidget* create_converterdlg (void); diff --git a/plugins/gtkui/plcommon.c b/plugins/gtkui/plcommon.c index beff39bb..3c28be8b 100644 --- a/plugins/gtkui/plcommon.c +++ b/plugins/gtkui/plcommon.c @@ -30,6 +30,7 @@ #include "interface.h" #include "parser.h" #include "actions.h" +#include "converter.h" #define min(x,y) ((x)<(y)?(x):(y)) //#define trace(...) { fprintf(stderr, __VA_ARGS__); } @@ -353,6 +354,12 @@ on_remove_from_disk_activate (GtkMenuItem *menuitem, search_refresh (); } +void +on_convert_activate (GtkMenuItem *menuitem, + gpointer user_data) { + converter_show (); +} + void actionitem_activate (GtkMenuItem *menuitem, DB_plugin_action_t *action) @@ -397,6 +404,7 @@ list_context_menu (DdbListview *listview, DdbListviewIter it, int idx) { GtkWidget *separator8; GtkWidget *properties1; GtkWidget *reload_metadata; + GtkWidget *convert; playlist_menu = gtk_menu_new (); add_to_playback_queue1 = gtk_menu_item_new_with_mnemonic (_("Add to playback queue")); @@ -436,6 +444,10 @@ list_context_menu (DdbListview *listview, DdbListviewIter it, int idx) { gtk_container_add (GTK_CONTAINER (playlist_menu), remove_from_disk); g_object_set_data (G_OBJECT (remove_from_disk), "ps", listview); } + convert = gtk_menu_item_new_with_mnemonic (_("Convert...")); + gtk_widget_show (convert); + gtk_container_add (GTK_CONTAINER (playlist_menu), convert); + g_object_set_data (G_OBJECT (convert), "ps", listview); separator8 = gtk_separator_menu_item_new (); gtk_widget_show (separator8); @@ -523,6 +535,9 @@ list_context_menu (DdbListview *listview, DdbListviewIter it, int idx) { G_CALLBACK (on_remove_from_disk_activate), NULL); } + g_signal_connect ((gpointer) convert, "activate", + G_CALLBACK (on_convert_activate), + NULL); g_signal_connect ((gpointer) properties1, "activate", G_CALLBACK (main_properties_activate), NULL); -- cgit v1.2.3