From 0a6148b06f9095c4da60bbb15899c797eed3e735 Mon Sep 17 00:00:00 2001 From: LRN1986 Date: Sun, 4 Apr 2010 08:19:53 +0000 Subject: [PATCH] Extended import filtering --- src/Makefile.in | 1 + src/ShuttleGui.cpp | 14 + src/ShuttleGui.h | 1 + src/import/Import.cpp | 265 ++++++++++++++-- src/import/Import.h | 82 ++++- src/import/ImportFFmpeg.cpp | 1 + src/import/ImportFLAC.cpp | 1 + src/import/ImportLOF.cpp | 1 + src/import/ImportMP3.cpp | 1 + src/import/ImportOGG.cpp | 1 + src/import/ImportPCM.cpp | 1 + src/import/ImportPlugin.h | 6 + src/prefs/ExtImportPrefs.cpp | 421 ++++++++++++++++++++++++++ src/prefs/ExtImportPrefs.h | 62 ++++ src/prefs/PrefsDialog.cpp | 3 + win/Projects/Audacity/Audacity.vcproj | 8 + 16 files changed, 850 insertions(+), 19 deletions(-) create mode 100644 src/prefs/ExtImportPrefs.cpp create mode 100644 src/prefs/ExtImportPrefs.h diff --git a/src/Makefile.in b/src/Makefile.in index 9cbf513ee..68328ef65 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -222,6 +222,7 @@ OBJS = \ prefs/ThemePrefs.o \ prefs/TracksPrefs.o \ prefs/WarningsPrefs.o \ + prefs/ExtImportPrefs.o \ toolbars/ControlToolBar.o \ toolbars/DeviceToolBar.o \ toolbars/EditToolBar.o \ diff --git a/src/ShuttleGui.cpp b/src/ShuttleGui.cpp index acb86c60c..74fce31ce 100644 --- a/src/ShuttleGui.cpp +++ b/src/ShuttleGui.cpp @@ -572,6 +572,20 @@ wxListCtrl * ShuttleGuiBase::AddListControl() return pListCtrl; } +wxGrid * ShuttleGuiBase::AddGrid() +{ + UseUpId(); + if( mShuttleMode != eIsCreating ) + return wxDynamicCast(wxWindow::FindWindowById( miId, mpDlg), wxGrid); + wxGrid * pGrid; + SetProportions( 1 ); + mpWind = pGrid = new wxGrid(mpParent, miId, wxDefaultPosition, + wxDefaultSize, Style( wxWANTS_CHARS )); + pGrid->SetMinSize( wxSize( 120, 150 )); + UpdateSizers(); + return pGrid; +} + wxListCtrl * ShuttleGuiBase::AddListControlReportMode() { UseUpId(); diff --git a/src/ShuttleGui.h b/src/ShuttleGui.h index e7155a5a8..c4ce965d9 100644 --- a/src/ShuttleGui.h +++ b/src/ShuttleGui.h @@ -93,6 +93,7 @@ public: wxListBox * AddListBox(const wxArrayString * pChoices, long style = 0); wxListCtrl * AddListControl(); wxListCtrl * AddListControlReportMode(); + wxGrid * AddGrid(); wxCheckBox * AddCheckBox( const wxString &Prompt, const wxString &Selected); wxCheckBox * AddCheckBoxOnRight( const wxString &Prompt, const wxString &Selected); wxComboBox * AddCombo( const wxString &Prompt, const wxString &Selected,const wxArrayString * pChoices ); diff --git a/src/import/Import.cpp b/src/import/Import.cpp index df472cca7..04c6f1807 100644 --- a/src/import/Import.cpp +++ b/src/import/Import.cpp @@ -67,6 +67,7 @@ Importer::Importer() { mImportPluginList = new ImportPluginList; mUnusableImportPluginList = new UnusableImportPluginList; + mExtImportItems = NULL; // build the list of import plugin and/or unusableImporters. // order is significant. If none match, they will all be tried @@ -87,14 +88,18 @@ Importer::Importer() GetGStreamerImportPlugin(mImportPluginList, mUnusableImportPluginList); #endif + ReadImportItems(); } Importer::~Importer() { + WriteImportItems(); mImportPluginList->DeleteContents(true); delete mImportPluginList; mUnusableImportPluginList->DeleteContents(true);//JKC delete mUnusableImportPluginList; + if (this->mExtImportItems != NULL) + delete this->mExtImportItems; } void Importer::GetSupportedImportFormats(FormatList *formatList) @@ -109,6 +114,201 @@ void Importer::GetSupportedImportFormats(FormatList *formatList) } } +void Importer::StringToList(wxString &str, wxString &delims, wxArrayString &list, wxStringTokenizerMode mod) +{ + wxStringTokenizer toker; + + for (toker.SetString(str, delims, mod); + toker.HasMoreTokens(); list.Add (toker.GetNextToken())); +} + +void Importer::ReadImportItems() +{ + int item_counter = 0; + wxStringTokenizer toker; + wxString item_name; + wxString item_value; + ExtImportItem *new_item; + ImportPluginList::compatibility_iterator importPluginNode; + + if (this->mExtImportItems != NULL) + delete this->mExtImportItems; + + this->mExtImportItems = new ExtImportItems(); + /* Rule string format is: + * extension1:extension2:extension3\mime_type1:mime_type2:mime_type3|filter1:filter2:filter3\unusedfilter1:unusedfilter2 + * backslashes are escaped and unescaped internally + */ + for (item_counter = 0; true; item_counter++) + { + wxString condition, filters, used_filters, unused_filters = wxEmptyString, extensions, mime_types = wxEmptyString; + item_name.Printf (wxT("/ExtImportItems/Item%d"), item_counter); + /* Break at first non-existent item */ + if (!gPrefs->Read(item_name, &item_value)) + break; + + toker.SetString(item_value, wxT("|"), wxTOKEN_RET_EMPTY_ALL); + /* Break at first broken item */ + if (toker.CountTokens() != 2) + break; + + new_item = new ExtImportItem(); + + /* First token is the filtering condition, second - the filter list */ + condition = toker.GetNextToken(); + filters = toker.GetNextToken(); + + /* Condition token consists of extension list and mime type list + * mime type list can be omitted entirely (complete with '\' separator)*/ + toker.SetString(condition, wxT("\\"), wxTOKEN_RET_EMPTY_ALL); + extensions = toker.GetNextToken(); + if (toker.HasMoreTokens()) + mime_types = toker.GetNextToken(); + + StringToList (extensions, wxString(wxT(":")), new_item->extensions); + + if (mime_types != wxEmptyString) + StringToList (mime_types, wxString(wxT(":")), new_item->mime_types); + + /* Filter token consists of used and unused filter lists */ + toker.SetString(filters, wxT("\\"), wxTOKEN_RET_EMPTY_ALL); + used_filters = toker.GetNextToken(); + if (toker.HasMoreTokens()) + unused_filters = toker.GetNextToken(); + + StringToList (used_filters, wxString(wxT(":")), new_item->filters); + + if (unused_filters != wxEmptyString) + { + /* Filters are stored in one list, but the position at which + * unused filters start is remembered + */ + new_item->divider = new_item->filters.Count(); + StringToList (unused_filters, wxString(wxT(":")), new_item->filters); + } + else + new_item->divider = -1; + + /* Find corresponding filter object for each filter ID */ + for (size_t i = 0; i < new_item->filters.Count(); i++) + { + for (importPluginNode = mImportPluginList->GetFirst(); + importPluginNode; importPluginNode = importPluginNode->GetNext()) + { + ImportPlugin *importPlugin = importPluginNode->GetData(); + if (importPlugin->GetPluginStringID().Cmp(new_item->filters[i]) == 0) + { + new_item->filter_objects.Add (importPlugin); + break; + } + } + /* IDs that do not have corresponding filters, will be shown as-is */ + if (!importPluginNode) + new_item->filter_objects.Add (NULL); + } + /* Find all filter objects that are not present in the filter list */ + for (importPluginNode = mImportPluginList->GetFirst(); + importPluginNode; importPluginNode = importPluginNode->GetNext()) + { + bool found = false; + ImportPlugin *importPlugin = importPluginNode->GetData(); + for (size_t i = 0; i < new_item->filter_objects.Count(); i++) + { + if (importPlugin == new_item->filter_objects[i]) + { + found = true; + break; + } + } + /* Add these filters at the bottom of used filter list */ + if (!found) + { + int index = new_item->divider; + if (new_item->divider < 0) + index = new_item->filters.Count(); + new_item->filters.Insert(importPlugin->GetPluginStringID(),index); + new_item->filter_objects.Insert (importPlugin, index); + if (new_item->divider >= 0) + new_item->divider++; + } + } + this->mExtImportItems->Add (new_item); + } +} + +void Importer::WriteImportItems() +{ + size_t i; + wxString val, name; + for (i = 0; i < this->mExtImportItems->Count(); i++) + { + ExtImportItem *item = &(mExtImportItems->Item(i)); + val.Clear(); + + for (size_t j = 0; j < item->extensions.Count(); j++) + { + val.Append (item->extensions[j]); + if (j < item->extensions.Count() - 1) + val.Append (wxT(":")); + } + val.Append (wxT("\\")); + for (size_t j = 0; j < item->mime_types.Count(); j++) + { + val.Append (item->mime_types[j]); + if (j < item->mime_types.Count() - 1) + val.Append (wxT(":")); + } + val.Append (wxT("|")); + for (size_t j = 0; j < item->filters.Count() && ((int) j < item->divider || item->divider < 0); j++) + { + val.Append (item->filters[j]); + if (j < item->filters.Count() - 1 && ((int) j < item->divider - 1 || item->divider < 0)) + val.Append (wxT(":")); + } + if (item->divider >= 0) + { + val.Append (wxT("\\")); + for (size_t j = item->divider; j < item->filters.Count(); j++) + { + val.Append (item->filters[j]); + if (j < item->filters.Count() - 1) + val.Append (wxT(":")); + } + } + name.Printf (wxT("/ExtImportItems/Item%d"), i); + gPrefs->Write (name, val); + } + /* If we had more items than we have now, delete the excess */ + for (i = this->mExtImportItems->Count(); i >= 0; i++) + { + name.Printf (wxT("/ExtImportItems/Item%d"), i); + if (gPrefs->Read(name, &val)) + gPrefs->DeleteEntry (name, false); + else + break; + } +} + +ExtImportItem *Importer::CreateDefaultImportItem() +{ + ExtImportItem *new_item; + ImportPluginList::compatibility_iterator importPluginNode; + + new_item = new ExtImportItem(); + new_item->extensions.Add(wxT("*")); + new_item->mime_types.Add(wxT("*")); + + for (importPluginNode = mImportPluginList->GetFirst(); + importPluginNode; importPluginNode = importPluginNode->GetNext()) + { + ImportPlugin *importPlugin = importPluginNode->GetData(); + new_item->filters.Add (importPlugin->GetPluginStringID()); + new_item->filter_objects.Add (importPlugin); + } + new_item->divider = -1; + return new_item; +} + // returns number of tracks imported int Importer::Import(wxString fName, TrackFactory *trackFactory, @@ -131,8 +331,11 @@ int Importer::Import(wxString fName, // If user explicitly selected a filter, // then we should try importing via corresponding plugin first wxString type = gPrefs->Read(wxT("/LastOpenType"),wxT("")); + + // Not implemented (yet?) + wxString mime_type = wxT("*"); - // First, add all explicitly compatible plugins + // First, add user-selected filter importPluginNode = mImportPluginList->GetFirst(); while(importPluginNode) { @@ -142,29 +345,57 @@ int Importer::Import(wxString fName, // This plugin corresponds to user-selected filter, try it first. importPlugins.Insert(plugin); } - else if (plugin->SupportsExtension(extension)) - { - importPlugins.Append(plugin); - } - if (plugin->SupportsExtension(extension)) - compatiblePlugins.Append(plugin); importPluginNode = importPluginNode->GetNext(); } + bool foundItem = false; - // Next, add all other plugins - importPluginNode = mImportPluginList->GetFirst(); - while(importPluginNode) + for (size_t i = 0; i < mExtImportItems->Count(); i++) { - ImportPlugin *plugin = importPluginNode->GetData(); - if (importPlugins.Find(plugin) == NULL) + ExtImportItem *item = &(*mExtImportItems)[i]; + bool matches_ext = false, matches_mime = false; + for (size_t j = 0; j < item->extensions.Count(); j++) { - // Skip MP3 import plugin. Opens some non-mp3 audio files (ac3 for example) as garbage. - if (plugin->GetPluginFormatDescription().CompareTo( _("MP3 files") ) != 0) + if (wxMatchWild (item->extensions[j],fName, false)) { - importPlugins.Append(plugin); - } + matches_ext = true; + break; + } + } + for (size_t j = 0; matches_ext && j < item->mime_types.Count(); j++) + { + if (wxMatchWild (item->mime_types[j],mime_type, false)) + { + matches_mime = true; + break; + } + } + if (matches_ext && matches_mime) + { + for (size_t j = 0; j < item->filter_objects.Count() && (item->divider < 0 || (int) j < item->divider); j++) + { + importPlugins.Append(item->filter_objects[j]); + } + foundItem = true; + } + } + + if (!foundItem) + { + // By default just add all plugins (except for MP3) + importPluginNode = mImportPluginList->GetFirst(); + while(importPluginNode) + { + ImportPlugin *plugin = importPluginNode->GetData(); + if (importPlugins.Find(plugin) == NULL) + { + // Skip MP3 import plugin. Opens some non-mp3 audio files (ac3 for example) as garbage. + if (plugin->GetPluginFormatDescription().CompareTo( _("MP3 files") ) != 0) + { + importPlugins.Append(plugin); + } + } + importPluginNode = importPluginNode->GetNext(); } - importPluginNode = importPluginNode->GetNext(); } importPluginNode = importPlugins.GetFirst(); diff --git a/src/import/Import.h b/src/import/Import.h index 4e23f9aa3..80eeae781 100644 --- a/src/import/Import.h +++ b/src/import/Import.h @@ -17,6 +17,7 @@ #include #include #include +#include class Tags; class TrackFactory; @@ -38,19 +39,94 @@ public: } }; -class ImportPluginList; -class UnusableImportPluginList; +class ExtImportItem; WX_DECLARE_LIST(Format, FormatList); +WX_DEFINE_ARRAY_PTR(ImportPlugin *, ImportPluginPtrArray); +WX_DECLARE_OBJARRAY(ExtImportItem, ExtImportItems); +class ExtImportItem +{ + public: + /** + * Unique string ID exists for each filter, it is not translateable + * and can be stored in config. This ID is matched internally with a + * translated name of a filter. + * Unknown IDs will be presented and saved as-is. + * Unused filters will not be used for matching files, unless forced. + */ + wxArrayString filters; + + /** + * The index of first unused filter in @filters array + * 0 - divider is at the top of the list (in the list control + * it will be the highest item), all filters are unused + * -1 - divider is at the bottom of the list (in the list control + * it will be the lowest item), all filters are used + */ + int divider; + + /** + * Array of pointers to import plugins (members of FormatList) + */ + ImportPluginPtrArray filter_objects; + + /** + * File extensions. Each one is a string with simple wildcards, + * i.e. "*.wav". + */ + wxArrayString extensions; + + /** + * Mime-types. Each one is a string in form of "foo/bar-baz" or + * something like that. + */ + wxArrayString mime_types; +}; + +class ImportPluginList; +class UnusableImportPluginList; class Importer { public: Importer(); ~Importer(); + /** + * Fills @formatList with a list of supported import formats + */ void GetSupportedImportFormats(FormatList *formatList); + /** + * Reads extended import filters from gPrefs into internal + * list mExtImportItems + */ + void ReadImportItems(); + + /** + * Writes mExtImportItems into gPrefs + */ + void WriteImportItems(); + + /** + * Helper function - uses wxStringTokenizer to tokenize + * @str string and appends string-tokens to a list @list. + * @mod deifines tokenizer's behaviour. + */ + void StringToList(wxString &str, wxString &delims, wxArrayString &list, wxStringTokenizerMode mod = wxTOKEN_RET_EMPTY_ALL); + + /** + * Returns a pointer to internal items array. + * External objects are allowed to change the array contents. + */ + ExtImportItems *GetImportItems() { return mExtImportItems; }; + + /** + * Allocates new ExtImportItem, fills it with default data + * and returns a pointer to it. + */ + ExtImportItem *CreateDefaultImportItem(); + // returns number of tracks imported // if zero, the import failed and errorMessage will be set. int Import(wxString fName, @@ -60,6 +136,8 @@ public: wxString &errorMessage); private: + + ExtImportItems *mExtImportItems; ImportPluginList *mImportPluginList; UnusableImportPluginList *mUnusableImportPluginList; }; diff --git a/src/import/ImportFFmpeg.cpp b/src/import/ImportFFmpeg.cpp index 6917e289b..7196a160c 100644 --- a/src/import/ImportFFmpeg.cpp +++ b/src/import/ImportFFmpeg.cpp @@ -198,6 +198,7 @@ public: ~FFmpegImportPlugin() { } + wxString GetPluginStringID() { return wxT("libav"); } wxString GetPluginFormatDescription(); ///! Probes the file and opens it if appropriate diff --git a/src/import/ImportFLAC.cpp b/src/import/ImportFLAC.cpp index 758b44dc6..a3259b2e1 100644 --- a/src/import/ImportFLAC.cpp +++ b/src/import/ImportFLAC.cpp @@ -136,6 +136,7 @@ class FLACImportPlugin : public ImportPlugin ~FLACImportPlugin() { } + wxString GetPluginStringID() { return wxT("libflac"); } wxString GetPluginFormatDescription(); ImportFileHandle *Open(wxString Filename); }; diff --git a/src/import/ImportLOF.cpp b/src/import/ImportLOF.cpp index 9d4a2a99e..a5d11c472 100644 --- a/src/import/ImportLOF.cpp +++ b/src/import/ImportLOF.cpp @@ -112,6 +112,7 @@ public: ~LOFImportPlugin() { } + wxString GetPluginStringID() { return wxT("lof"); } wxString GetPluginFormatDescription(); ImportFileHandle *Open(wxString Filename); }; diff --git a/src/import/ImportMP3.cpp b/src/import/ImportMP3.cpp index c4fa3466b..dcc15ed0d 100644 --- a/src/import/ImportMP3.cpp +++ b/src/import/ImportMP3.cpp @@ -112,6 +112,7 @@ public: ~MP3ImportPlugin() { } + wxString GetPluginStringID() { return wxT("libmad"); } wxString GetPluginFormatDescription(); ImportFileHandle *Open(wxString Filename); }; diff --git a/src/import/ImportOGG.cpp b/src/import/ImportOGG.cpp index 0fa75f9be..6bdbdbe7f 100644 --- a/src/import/ImportOGG.cpp +++ b/src/import/ImportOGG.cpp @@ -87,6 +87,7 @@ public: ~OggImportPlugin() { } + wxString GetPluginStringID() { return wxT("liboggvorbis"); } wxString GetPluginFormatDescription(); ImportFileHandle *Open(wxString Filename); }; diff --git a/src/import/ImportPCM.cpp b/src/import/ImportPCM.cpp index f379105cb..e1febfd73 100644 --- a/src/import/ImportPCM.cpp +++ b/src/import/ImportPCM.cpp @@ -80,6 +80,7 @@ public: ~PCMImportPlugin() { } + wxString GetPluginStringID() { return wxT("libsndfile"); } wxString GetPluginFormatDescription(); ImportFileHandle *Open(wxString Filename); }; diff --git a/src/import/ImportPlugin.h b/src/import/ImportPlugin.h index a0d6e76ef..fba698f2c 100644 --- a/src/import/ImportPlugin.h +++ b/src/import/ImportPlugin.h @@ -72,6 +72,12 @@ class ImportPlugin { public: + // Get unique string ID of this plugin, usually it corresponds + // to the underlying library, i.e. "libsndfile", "libflac", "libav" + // These MUST NOT change across Audacity versions (but new IDs can + // be added). + virtual wxString GetPluginStringID() = 0; + // Get a description of the file type this importer can import. // Examples: "Ogg Vorbis", "MP3", "Uncompressed PCM" virtual wxString GetPluginFormatDescription() = 0; diff --git a/src/prefs/ExtImportPrefs.cpp b/src/prefs/ExtImportPrefs.cpp new file mode 100644 index 000000000..df239bb8f --- /dev/null +++ b/src/prefs/ExtImportPrefs.cpp @@ -0,0 +1,421 @@ +/********************************************************************** + + Audacity: A Digital Audio Editor + + ExtImportPrefs.cpp + + LRN + +*******************************************************************//** + +\class ExtImportPrefs +\brief A PrefsPanel used to select extended import filter options. + +*//*******************************************************************/ + +#include "../Audacity.h" + +#include + +#include "../Prefs.h" +#include "../ShuttleGui.h" + +#include "ExtImportPrefs.h" + +#include // this is a magic incantation which must be done! + +#define EXTIMPORT_MIME_SUPPORT 0 + +WX_DEFINE_OBJARRAY(ExtImportItems); + +enum ExtImportPrefsControls +{ + EIPPluginList = 20000, + EIPRuleTable, + EIPAddRule, + EIPDelRule +}; + +BEGIN_EVENT_TABLE(ExtImportPrefs, PrefsPanel) + EVT_LIST_KEY_DOWN(EIPPluginList,ExtImportPrefs::OnPluginKeyDown) + EVT_KEY_DOWN (ExtImportPrefs::OnRuleTableKeyDown) + EVT_GRID_EDITOR_HIDDEN (ExtImportPrefs::OnRuleTableEdit) + EVT_GRID_SELECT_CELL (ExtImportPrefs::OnRuleTableSelect) + EVT_GRID_RANGE_SELECT (ExtImportPrefs::OnRuleTableSelectRange) + EVT_BUTTON(EIPAddRule,ExtImportPrefs::OnAddRule) + EVT_BUTTON(EIPDelRule,ExtImportPrefs::OnDelRule) +END_EVENT_TABLE() + +ExtImportPrefs::ExtImportPrefs(wxWindow * parent) +: PrefsPanel(parent, _("Extended Import")) +{ + last_selected = -1; + Populate(); +} + +ExtImportPrefs::~ExtImportPrefs() +{ +} + +/// Creates the dialog and its contents. +void ExtImportPrefs::Populate() +{ + //------------------------- Main section -------------------- + // Now construct the GUI itself. + // Use 'eIsCreatingFromPrefs' so that the GUI is + // initialised with values from gPrefs. + ShuttleGui S(this, eIsCreatingFromPrefs); + PopulateOrExchange(S); +#if EXTIMPORT_MIME_SUPPORT + RuleTable->CreateGrid (0, 2, wxGrid::wxGridSelectRows); +#else + RuleTable->CreateGrid (0, 1, wxGrid::wxGridSelectRows); +#endif + RuleTable->DisableDragColMove (); + RuleTable->DisableDragRowSize (); + RuleTable->SetColLabelValue (0, _("File extensions")); +#if EXTIMPORT_MIME_SUPPORT + RuleTable->SetColLabelValue (1, _("Mime-types")); +#endif + RuleTable->SetRowLabelSize (0); + RuleTable->SetSelectionMode (wxGrid::wxGridSelectRows); + ExtImportItems *items = wxGetApp().mImporter->GetImportItems(); + + for (int i = 0; i < items->Count(); i++) + AddItemToTable (i, &(*items)[i]); + // ----------------------- End of main section -------------- +} + +void ExtImportPrefs::PopulateOrExchange(ShuttleGui & S) +{ + S.SetBorder(2); + + S.StartStatic(_("Rules to choose import filters"), 1); + { + S.SetSizerProportion(1); + S.StartHorizontalLay (wxEXPAND, 1); + { + RuleTable = S.Id(EIPRuleTable).AddGrid (); + RuleTable->SetWindowStyle (wxBORDER_SUNKEN); + PluginList = S.Id(EIPPluginList).AddListControl (); + PluginList->SetSingleStyle (wxLC_REPORT, true); + PluginList->SetSingleStyle (wxLC_SINGLE_SEL, true); + PluginList->InsertColumn (0, _("Importer")); + } + S.EndHorizontalLay(); + S.StartHorizontalLay (wxSHRINK, 0); + { + AddRule = S.Id (EIPAddRule).AddButton (_("Add new rule")); + DelRule = S.Id (EIPDelRule).AddButton (_("Delete selected rule")); + } + S.EndHorizontalLay(); + } + S.EndStatic(); + Layout(); + Fit(); + SetMinSize(GetSize()); +} + +bool ExtImportPrefs::Apply() +{ + ShuttleGui S(this, eIsSavingToPrefs); + PopulateOrExchange(S); + + return true; +} + +void ExtImportPrefs::OnPluginKeyDown(wxListEvent& event) +{ + for (int i = 0; i < 1; i++) + { +#ifdef __WXMAC__ + if (!wxGetKeyState(WXK_COMMAND)) + break; +#else + if (!wxGetKeyState(WXK_CONTROL)) + break; +#endif + + int code = event.GetKeyCode(); + + if (code != WXK_UP && code != WXK_DOWN) + break; + + long itemIndex = -1; + itemIndex = PluginList->GetNextItem(itemIndex, + wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); + if (itemIndex == -1) + break; + + if (last_selected == -1) + break; + + ExtImportItems *items = wxGetApp().mImporter->GetImportItems(); + ExtImportItem *item = &(*items)[last_selected]; + + if (code == WXK_UP && itemIndex == 0) + break; + else if (code == WXK_DOWN && itemIndex == PluginList->GetItemCount() - 1) + break; + + wxString t, t2; + long d, d2; + ImportPlugin *ip1, *ip2; + if (code == WXK_UP) + { + t = PluginList->GetItemText (itemIndex); + d = PluginList->GetItemData (itemIndex); + d2 = PluginList->GetItemData (itemIndex - 1); + PluginList->SetItemText (itemIndex, PluginList->GetItemText (itemIndex - 1)); + PluginList->SetItemText (itemIndex - 1, t); + if (d == -1 || d2 == -1) + { + PluginList->SetItemData (itemIndex, PluginList->GetItemData (itemIndex - 1)); + PluginList->SetItemData (itemIndex - 1, d); + if (d == -1) + { + item->divider--; + } + else if (d2 == -1) + { + item->divider++; + } + } + else + { + ip1 = item->filter_objects[d]; + ip2 = item->filter_objects[d2]; + item->filter_objects[d] = ip2; + item->filter_objects[d2] = ip1; + t = item->filters[d]; + t2 = item->filters[d2]; + item->filters[d] = t2; + item->filters[d2] = t; + } + } + else if (code == WXK_DOWN) + { + t = PluginList->GetItemText (itemIndex); + d = PluginList->GetItemData (itemIndex); + d2 = PluginList->GetItemData (itemIndex + 1); + PluginList->SetItemText (itemIndex, PluginList->GetItemText (itemIndex + 1)); + PluginList->SetItemText (itemIndex + 1, t); + if (d == -1 || d2 == -1) + { + PluginList->SetItemData (itemIndex, PluginList->GetItemData (itemIndex + 1)); + PluginList->SetItemData (itemIndex + 1, d); + if (d == -1) + { + item->divider++; + } + else if (d2 == -1) + { + item->divider--; + } + } + else + { + ip1 = item->filter_objects[d]; + ip2 = item->filter_objects[d2]; + item->filter_objects[d] = ip2; + item->filter_objects[d2] = ip1; + t = item->filters[d]; + t2 = item->filters[d2]; + item->filters[d] = t2; + item->filters[d2] = t; + } + } + int fcount = item->filter_objects.Count(); + if (item->divider >= fcount) + { + item->divider = -1; + } + if (item->divider < -1) + item->divider = item->filter_objects.Count() - 1; + } + event.Skip(); +} + +void ExtImportPrefs::OnRuleTableKeyDown(wxKeyEvent& event) +{ + int mods = event.GetModifiers(); + if (mods & wxMOD_CMD && (event.GetKeyCode() == WXK_UP || event.GetKeyCode() == WXK_DOWN)) + { + ExtImportItems *items = wxGetApp().mImporter->GetImportItems(); + ExtImportItem *t1, *t2; + int selrow = RuleTable->GetGridCursorRow (); + wxString ts; + if (event.GetKeyCode() == WXK_UP) + { + if (selrow == 0) + return; + t1 = items->Detach(selrow - 1); + t2 = items->Detach(selrow - 1); + items->Insert (t1, selrow - 1); + items->Insert (t2, selrow - 1); + for (int i = 0; i < RuleTable->GetNumberCols(); i++) + { + ts = RuleTable->GetCellValue (selrow, i); + RuleTable->SetCellValue (selrow, i, RuleTable->GetCellValue (selrow - 1, i)); + RuleTable->SetCellValue (selrow - 1, i, ts); + } + RuleTable->MoveCursorUp (false); + } + else if (event.GetKeyCode() == WXK_DOWN) + { + if (selrow == RuleTable->GetNumberRows() - 1) + return; + t1 = items->Detach(selrow); + t2 = items->Detach(selrow); + items->Insert (t2, selrow); + items->Insert (t1, selrow); + for (int i = 0; i < RuleTable->GetNumberCols(); i++) + { + ts = RuleTable->GetCellValue (selrow, i); + RuleTable->SetCellValue (selrow, i, RuleTable->GetCellValue (selrow + 1, i)); + RuleTable->SetCellValue (selrow + 1, i, ts); + } + RuleTable->MoveCursorDown (false); + } + } + else + event.Skip(); +} + +void ExtImportPrefs::OnRuleTableSelect (wxGridEvent& event) +{ + int toprow; + if (!event.Selecting()) + return; + toprow = event.GetRow(); + DoOnRuleTableSelect (toprow); + event.Skip(); +} + +void ExtImportPrefs::OnRuleTableSelectRange (wxGridRangeSelectEvent& event) +{ + int toprow; + if (!event.Selecting()) + return; + toprow = event.GetTopRow(); + DoOnRuleTableSelect (toprow); + event.Skip(); +} + +void ExtImportPrefs::DoOnRuleTableSelect (int toprow) +{ + ExtImportItems *items = wxGetApp().mImporter->GetImportItems(); + ExtImportItem *item = &(*items)[toprow]; + PluginList->DeleteAllItems(); + + int fcount; + fcount = item->filters.Count(); + int shift = 0; + for (int i = 0; i < fcount; i++) + { + if (item->divider == i) + { + PluginList->InsertItem (i, _("Unused filters:")); + PluginList->SetItemData (i, -1); + shift = 1; + } + if (item->filter_objects[i] != NULL) + { + PluginList->InsertItem (i + shift, item->filter_objects[i]->GetPluginFormatDescription()); + } + else + { + PluginList->InsertItem (i + shift, item->filters[i]); + } + PluginList->SetItemData (i + shift, i); + } + if (item->divider == -1) + { + PluginList->InsertItem (fcount, _("Unused filters:")); + PluginList->SetItemData (fcount, -1); + } + PluginList->SetColumnWidth (0, wxLIST_AUTOSIZE); + last_selected = toprow; +} + +void ExtImportPrefs::OnRuleTableEdit (wxGridEvent& event) +{ + int row = event.GetRow(); + int col = event.GetCol(); + ExtImportItems *items = wxGetApp().mImporter->GetImportItems(); + ExtImportItem *item = &(*items)[row]; + RuleTable->SaveEditControlValue(); + wxString val = RuleTable->GetCellValue (row, col); + switch (col) + { + case 0: + item->extensions.Clear(); + wxGetApp().mImporter->StringToList (val, wxString(wxT(":")), item->extensions); + break; + case 1: + item->mime_types.Clear(); + wxGetApp().mImporter->StringToList (val, wxString(wxT(":")), item->mime_types); + break; + } + RuleTable->AutoSizeColumns (); +} + +void ExtImportPrefs::AddItemToTable (int index, ExtImportItem *item) +{ + wxString extensions, mime_types; + if (item->extensions.Count() > 0) + { + extensions.Append (item->extensions[0]); + for (int i = 1; i < item->extensions.Count(); i++) + { + extensions.Append (wxT(":")); + extensions.Append (item->extensions[i]); + } + } + if (item->mime_types.Count() > 0) + { + mime_types.Append (item->mime_types[0]); + for (int i = 1; i < item->mime_types.Count(); i++) + { + mime_types.Append (wxT(":")); + mime_types.Append (item->mime_types[i]); + } + } + + RuleTable->InsertRows (index, 1); + RuleTable->SetCellValue (index, 0, extensions); +#if EXTIMPORT_MIME_SUPPORT + RuleTable->SetCellValue (index, 1, mime_types); +#endif + RuleTable->AutoSizeColumns (); +} + +void ExtImportPrefs::OnAddRule(wxCommandEvent& event) +{ + ExtImportItems *items = wxGetApp().mImporter->GetImportItems(); + ExtImportItem *item = wxGetApp().mImporter->CreateDefaultImportItem(); + items->Add (item); + + AddItemToTable (RuleTable->GetNumberRows (), item); +} + +void ExtImportPrefs::OnDelRule(wxCommandEvent& event) +{ + if (last_selected < 0) + return; + ExtImportItems *items = wxGetApp().mImporter->GetImportItems(); + RuleTable->DeleteRows (last_selected); + items->RemoveAt (last_selected); + RuleTable->AutoSizeColumns (); +} + +// Indentation settings for Vim and Emacs and unique identifier for Arch, a +// version control system. Please do not modify past this point. +// +// Local Variables: +// c-basic-offset: 3 +// indent-tabs-mode: nil +// End: +// +// vim: et sts=3 sw=3 +// arch-tag: 427b9e64-3fc6-40ef-bbf8-e6fff1d442f0 diff --git a/src/prefs/ExtImportPrefs.h b/src/prefs/ExtImportPrefs.h new file mode 100644 index 000000000..5229d060d --- /dev/null +++ b/src/prefs/ExtImportPrefs.h @@ -0,0 +1,62 @@ +/********************************************************************** + + Audacity: A Digital Audio Editor + + ExtImportPrefs.h + + LRN + +**********************************************************************/ + +#ifndef __AUDACITY_EXT_IMPORT_PREFS__ +#define __AUDACITY_EXT_IMPORT_PREFS__ + +#include + +#include + +#include "../ShuttleGui.h" + +#include "PrefsPanel.h" + +#include "../Import/Import.h" +#include "../Import/ImportPlugin.h" + + +class ExtImportPrefs:public PrefsPanel +{ + public: + ExtImportPrefs(wxWindow * parent); + ~ExtImportPrefs(); + virtual bool Apply(); + + void OnPluginKeyDown(wxListEvent& event); + void OnRuleTableKeyDown(wxKeyEvent& event); + void OnRuleTableSelect(wxGridEvent& event); + void OnRuleTableEdit(wxGridEvent& event); + void OnRuleTableSelectRange(wxGridRangeSelectEvent& event); +/* void OnRuleTableKeyDown(wxListEvent& event); + void OnRuleTableFocus(wxListEvent& event); + void OnRuleTableActivate(wxListEvent& event); + void OnRuleTableRightClick(wxListEvent& event);*/ + void OnAddRule(wxCommandEvent& event); + void OnDelRule(wxCommandEvent& event); + + private: + + wxGrid *RuleTable; + wxListCtrl *PluginList; + + wxButton *AddRule; + wxButton *DelRule; + + int last_selected; + + void DoOnRuleTableSelect (int toprow); + void AddItemToTable (int index, ExtImportItem *item); + void Populate(); + void PopulateOrExchange(ShuttleGui & S); + DECLARE_EVENT_TABLE() +}; + +#endif \ No newline at end of file diff --git a/src/prefs/PrefsDialog.cpp b/src/prefs/PrefsDialog.cpp index 96dc41605..359ab1ef3 100644 --- a/src/prefs/PrefsDialog.cpp +++ b/src/prefs/PrefsDialog.cpp @@ -59,6 +59,7 @@ #include "ThemePrefs.h" #include "TracksPrefs.h" #include "WarningsPrefs.h" +#include "ExtImportPrefs.h" #ifdef EXPERIMENTAL_MIDI_OUT #include "MidiIOPrefs.h" @@ -112,6 +113,8 @@ PrefsDialog::PrefsDialog(wxWindow * parent) // w = new BatchPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); w = new KeyConfigPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); w = new MousePrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); + + w = new ExtImportPrefs(mCategories); mCategories->AddPage(w, w->GetName(), false, 0); } S.EndHorizontalLay(); } diff --git a/win/Projects/Audacity/Audacity.vcproj b/win/Projects/Audacity/Audacity.vcproj index 72c06e840..7f8995a33 100644 --- a/win/Projects/Audacity/Audacity.vcproj +++ b/win/Projects/Audacity/Audacity.vcproj @@ -1615,6 +1615,14 @@ RelativePath="..\..\..\src\prefs\EffectsPrefs.h" > + + + +