diff --git a/aegisub/audio_display.cpp b/aegisub/audio_display.cpp
index 1b3a3058ea006392eaa840c1a46601f4076249a6..714f6da6a051b198faad8b976c664b76bb96adbb 100644
--- a/aegisub/audio_display.cpp
+++ b/aegisub/audio_display.cpp
@@ -878,15 +878,15 @@ void AudioDisplay::SetFile(wxString file) {
 				is_dummy = true;
 				provider = new DummyAudioProvider(150*60*1000, true); // 150 minutes noise
 			} else {
-				provider = AudioProviderFactory::GetAudioProvider(file);
+				provider = AudioProviderFactoryManager::GetAudioProvider(file);
 			}
 #else
-			provider = AudioProviderFactory::GetAudioProvider(file);
+			provider = AudioProviderFactoryManager::GetAudioProvider(file);
 #endif
 
 			// Get player
 			wxLogDebug(_T("AudioDisplay::SetFile: get audio player"));
-			player = AudioPlayerFactory::GetAudioPlayer();
+			player = AudioPlayerFactoryManager::GetAudioPlayer();
 			player->SetDisplayTimer(&UpdateTimer);
 			player->SetProvider(provider);
 			player->OpenStream();
@@ -1022,12 +1022,12 @@ void AudioDisplay::Play(int start,int end) {
 			try {
 				// Get provider
 				if (!VideoContext::Get()->videoName.StartsWith(_T("?dummy")))
-					provider = AudioProviderFactory::GetAudioProvider(VideoContext::Get()->videoName, 0);
+					provider = AudioProviderFactoryManager::GetAudioProvider(VideoContext::Get()->videoName, 0);
 				else
 					return;
 
 				// Get player
-				player = AudioPlayerFactory::GetAudioPlayer();
+				player = AudioPlayerFactoryManager::GetAudioPlayer();
 				player->SetDisplayTimer(&UpdateTimer);
 				player->SetProvider(provider);
 				player->OpenStream();
diff --git a/aegisub/audio_player.cpp b/aegisub/audio_player.cpp
index ec71f70f02ba3bf2c60cbadc30643d6b9d9fedf5..37a0114ab3c92cee40cca11ef398357798982a71 100644
--- a/aegisub/audio_player.cpp
+++ b/aegisub/audio_player.cpp
@@ -126,7 +126,7 @@ void AudioPlayer::OnStopAudio(wxCommandEvent &event) {
 
 //////////////
 // Get player
-AudioPlayer* AudioPlayerFactory::GetAudioPlayer() {
+AudioPlayer* AudioPlayerFactoryManager::GetAudioPlayer() {
 	// List of providers
 	wxArrayString list = GetFactoryList(Options.AsText(_T("Audio player")));
 
@@ -152,26 +152,26 @@ AudioPlayer* AudioPlayerFactory::GetAudioPlayer() {
 
 //////////////////////////
 // Register all factories
-void AudioPlayerFactory::RegisterProviders() {
+void AudioPlayerFactoryManager::RegisterProviders() {
 #ifdef WITH_ALSA
-	new AlsaPlayerFactory();
+	RegisterFactory(new AlsaPlayerFactory(),_T("ALSA"));
 #endif
 #ifdef WITH_DIRECTSOUND
-	new DirectSoundPlayerFactory();
+	RegisterFactory(new DirectSoundPlayerFactory(),_T("DirectSound"));
 #endif
 #ifdef WITH_OPENAL
-	new OpenALPlayerFactory();
+	RegisterFactory(new OpenALPlayerFactory(),_T("OpenAL"));
 #endif
 #ifdef WITH_PORTAUDIO
-	new PortAudioPlayerFactory();
+	RegisterFactory(new PortAudioPlayerFactory(),_T("PortAudio"));
 #endif
 #ifdef WITH_PULSEAUDIO
-	new PulseAudioPlayerFactory();
+	RegisterFactory(new PulseAudioPlayerFactory(),_T("PulseAudio"));
 #endif
 }
 
 
 //////////
 // Static
-template <class AudioPlayerFactory> std::map<wxString,AudioPlayerFactory*>* AegisubFactory<AudioPlayerFactory>::factories=NULL;
+template <class AudioPlayerFactory> std::map<wxString,AudioPlayerFactory*>* FactoryManager<AudioPlayerFactory>::factories=NULL;
 
diff --git a/aegisub/audio_player.h b/aegisub/audio_player.h
index d9fe29a0b70543a48705ad8e9ed6ff860b6ddca2..ae4c6ae6874956611c0931461ff89bdafebe451d 100644
--- a/aegisub/audio_player.h
+++ b/aegisub/audio_player.h
@@ -44,7 +44,7 @@
 #include <wx/timer.h>
 #include <wx/thread.h>
 #include <stdint.h>
-#include "factory.h"
+#include "factory_manager.h"
 
 
 //////////////
@@ -96,18 +96,22 @@ public:
 
 ///////////
 // Factory
-class AudioPlayerFactory : public AegisubFactory<AudioPlayerFactory> {
-protected:
+class AudioPlayerFactory {
+public:
 	virtual AudioPlayer *CreatePlayer()=0;
-	AudioPlayerFactory(wxString name) { RegisterFactory(name); }
+};
 
+
+///////////////////
+// Factory Manager
+class AudioPlayerFactoryManager : public FactoryManager<AudioPlayerFactory> {
 public:
-	virtual ~AudioPlayerFactory() {}
 	static AudioPlayer *GetAudioPlayer();
 	static void RegisterProviders();
 };
 
 
+
 /////////
 // Event
 DECLARE_EVENT_TYPE(wxEVT_STOP_AUDIO, -1)
diff --git a/aegisub/audio_player_dsound.h b/aegisub/audio_player_dsound.h
index 105d2833c4db7d358e5542f07afdd576f4b8f36a..6643413fca58b5e878e467ae35aefd93da05104c 100644
--- a/aegisub/audio_player_dsound.h
+++ b/aegisub/audio_player_dsound.h
@@ -137,7 +137,6 @@ public:
 class DirectSoundPlayerFactory : public AudioPlayerFactory {
 public:
 	AudioPlayer *CreatePlayer() { return new DirectSoundPlayer(); }
-	DirectSoundPlayerFactory() : AudioPlayerFactory(_T("dsound")) {}
 };
 
 #endif
diff --git a/aegisub/audio_provider.cpp b/aegisub/audio_provider.cpp
index 15e76c29dd8822456b5d169e38e955891f334c28..c702614993d9ab578a4c1022118bbfd32521a66e 100644
--- a/aegisub/audio_provider.cpp
+++ b/aegisub/audio_provider.cpp
@@ -191,7 +191,7 @@ void AudioProvider::GetAudioWithVolume(void *buf, int64_t start, int64_t count,
 
 ////////////////
 // Get provider
-AudioProvider *AudioProviderFactory::GetAudioProvider(wxString filename, int cache) {
+AudioProvider *AudioProviderFactoryManager::GetAudioProvider(wxString filename, int cache) {
 	// Prepare provider
 	AudioProvider *provider = NULL;
 
@@ -254,16 +254,16 @@ AudioProvider *AudioProviderFactory::GetAudioProvider(wxString filename, int cac
 
 ///////////////////////////
 // Register all providers
-void AudioProviderFactory::RegisterProviders() {
+void AudioProviderFactoryManager::RegisterProviders() {
 #ifdef WITH_AVISYNTH
-	new AvisynthAudioProviderFactory();
+	RegisterFactory(new AvisynthAudioProviderFactory(),_T("Avisynth"));
 #endif
 #ifdef WITH_FFMPEG
-	new LAVCAudioProviderFactory();
+	RegisterFactory(new LAVCAudioProviderFactory(),_T("FFMPEG"));
 #endif
 }
 
 
 //////////
 // Static
-template <class AudioProviderFactory> std::map<wxString,AudioProviderFactory*>* AegisubFactory<AudioProviderFactory>::factories=NULL;
+template <class AudioProviderFactory> std::map<wxString,AudioProviderFactory*>* FactoryManager<AudioProviderFactory>::factories=NULL;
diff --git a/aegisub/audio_provider.h b/aegisub/audio_provider.h
index 6a1d39b839d327fc71e28b9bf0cbb208d19ad42a..0f6e3eee105e0b0d65abc203840676c6b1a36168 100644
--- a/aegisub/audio_provider.h
+++ b/aegisub/audio_provider.h
@@ -41,7 +41,7 @@
 // Headers
 #include <wx/wxprec.h>
 #include <stdint.h>
-#include "factory.h"
+#include "factory_manager.h"
 
 
 //////////////
@@ -84,13 +84,16 @@ public:
 
 ///////////
 // Factory
-class AudioProviderFactory : public AegisubFactory<AudioProviderFactory> {
-protected:
+class AudioProviderFactory {
+public:
 	virtual AudioProvider *CreateProvider(wxString filename)=0;
-	AudioProviderFactory(wxString name) { RegisterFactory(name); }
+};
 
+
+///////////////////
+// Factory Manager
+class AudioProviderFactoryManager : public FactoryManager<AudioProviderFactory> {
 public:
-	virtual ~AudioProviderFactory() {}
-	static AudioProvider *GetAudioProvider(wxString filename, int cache=-1);
 	static void RegisterProviders();
+	static AudioProvider *GetAudioProvider(wxString filename, int cache=-1);
 };
diff --git a/aegisub/audio_provider_avs.h b/aegisub/audio_provider_avs.h
index 1699f8e42e2780d38b0a12b06d71577fb092c96a..3c29c947131649624942b9bf825b2d018bedb150 100644
--- a/aegisub/audio_provider_avs.h
+++ b/aegisub/audio_provider_avs.h
@@ -71,7 +71,6 @@ public:
 class AvisynthAudioProviderFactory : public AudioProviderFactory {
 public:
 	AudioProvider *CreateProvider(wxString file) { return new AvisynthAudioProvider(file); }
-	AvisynthAudioProviderFactory() : AudioProviderFactory(_T("avisynth")) {}
 };
 
 #endif
diff --git a/aegisub/dialog_options.cpp b/aegisub/dialog_options.cpp
index dce9abe5acbfa312c7cc6f2ad52d206d8cf7971b..c949f575eeba9bece0afe1a6dd2177b423356607 100644
--- a/aegisub/dialog_options.cpp
+++ b/aegisub/dialog_options.cpp
@@ -390,12 +390,12 @@ DialogOptions::DialogOptions(wxWindow *parent)
 
 		// Second sizer
 		videoSizer4->Add(new wxStaticText(videoPage,-1,_("Video provider: ")),0,wxALIGN_CENTER_VERTICAL | wxRIGHT,10);
-		wxArrayString choices4 = VideoProviderFactory::GetFactoryList();
+		wxArrayString choices4 = VideoProviderFactoryManager::GetFactoryList();
 		control = new wxComboBox(videoPage,-1,_T(""),wxDefaultPosition,wxDefaultSize,choices4,wxCB_DROPDOWN | wxCB_READONLY);
 		Bind(control,_T("Video provider"),1);
 		videoSizer4->Add(control,1,wxEXPAND);
 		videoSizer4->Add(new wxStaticText(videoPage,-1,_("Subtitles provider: ")),0,wxALIGN_CENTER_VERTICAL | wxRIGHT,10);
-		wxArrayString choices5 = SubtitlesProviderFactory::GetFactoryList();
+		wxArrayString choices5 = SubtitlesProviderFactoryManager::GetFactoryList();
 		control = new wxComboBox(videoPage,-1,_T(""),wxDefaultPosition,wxDefaultSize,choices5,wxCB_DROPDOWN | wxCB_READONLY);
 		Bind(control,_T("Subtitles provider"),1);
 		videoSizer4->Add(control,1,wxEXPAND);
@@ -529,8 +529,8 @@ DialogOptions::DialogOptions(wxWindow *parent)
 		wxString choices3[3] = { _T("ConvertToMono"), _T("GetLeftChannel"), _T("GetRightChannel") };
 #endif
 		
-		AddComboControl(audioAdvPage,audioAdvSizer1,_("Audio provider"),_T("Audio Provider"),AudioProviderFactory::GetFactoryList(),true,1);
-		AddComboControl(audioAdvPage,audioAdvSizer1,_("Audio player"),_T("Audio Player"),AudioPlayerFactory::GetFactoryList(),true,1);
+		AddComboControl(audioAdvPage,audioAdvSizer1,_("Audio provider"),_T("Audio Provider"),AudioProviderFactoryManager::GetFactoryList(),true,1);
+		AddComboControl(audioAdvPage,audioAdvSizer1,_("Audio player"),_T("Audio Player"),AudioPlayerFactoryManager::GetFactoryList(),true,1);
 		AddComboControl(audioAdvPage,audioAdvSizer1,_("Cache type"),_T("Audio Cache"),wxArrayString(3,choices2),true);
 #ifdef WIN32
 		AddComboControl(audioAdvPage,audioAdvSizer1,_("Avisynth down-mixer"),_T("Audio Downmixer"),wxArrayString(3,choices3),false);
diff --git a/aegisub/dialog_spellchecker.cpp b/aegisub/dialog_spellchecker.cpp
index 9d83b3c77f2357fdf931d631ab3af3c967b7ae71..1cc41b4747874b9a37ae48af4771ed3c76f5955d 100644
--- a/aegisub/dialog_spellchecker.cpp
+++ b/aegisub/dialog_spellchecker.cpp
@@ -70,7 +70,7 @@ DialogSpellChecker::DialogSpellChecker(wxFrame *parent)
 	SetIcon(BitmapToIcon(wxBITMAP(spellcheck_toolbutton)));
 
 	// Get spell checker
-	spellchecker = SpellCheckerFactory::GetSpellChecker();
+	spellchecker = SpellCheckerFactoryManager::GetSpellChecker();
 	if (!spellchecker) {
 		wxMessageBox(_T("No spellchecker available."),_T("Error"),wxICON_ERROR);
 		Destroy();
diff --git a/aegisub/dialog_style_editor.cpp b/aegisub/dialog_style_editor.cpp
index 67ceacff64658a1ef762cf9bf8bda33d6dfda87e..d162f774a019784e1e8d4d161319aa08572e95fb 100644
--- a/aegisub/dialog_style_editor.cpp
+++ b/aegisub/dialog_style_editor.cpp
@@ -299,7 +299,7 @@ DialogStyleEditor::DialogStyleEditor (wxWindow *parent, AssStyle *_style, Subtit
 	// Preview
 	SubsPreview = NULL;
 	PreviewText = NULL;
-	if (SubtitlesProviderFactory::ProviderAvailable()) {
+	if (SubtitlesProviderFactoryManager::ProviderAvailable()) {
 		PreviewText = new wxTextCtrl(this,TEXT_PREVIEW,Options.AsText(_T("Style editor preview text")));
 		previewButton = new ColourButton(this,BUTTON_PREVIEW_COLOR,wxSize(45,16),Options.AsColour(_T("Style editor preview background")));
 		SubsPreview = new SubtitlesPreview(this,-1,wxDefaultPosition,wxSize(100,60),wxSUNKEN_BORDER,Options.AsColour(_T("Style editor preview background")));
diff --git a/aegisub/factory_manager.h b/aegisub/factory_manager.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a0fab148a7091daf23e60875e92f3c3633cf510
--- /dev/null
+++ b/aegisub/factory_manager.h
@@ -0,0 +1,107 @@
+// Copyright (c) 2007-2008, Rodrigo Braz Monteiro
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of the Aegisub Group nor the names of its contributors
+//     may be used to endorse or promote products derived from this software
+//     without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// -----------------------------------------------------------------------------
+//
+// AEGISUB
+//
+// Website: http://aegisub.cellosoft.com
+// Contact: mailto:zeratul@cellosoft.com
+//
+
+
+#pragma once
+
+
+///////////
+// Headers
+#include <map>
+#include <wx/string.h>
+#include <wx/arrstr.h>
+
+
+/////////////////
+// Factory class
+template <class T>
+class FactoryManager {
+protected:
+	// Static map of all factories
+	static std::map<wxString,T*> *factories;
+
+	// Register one factory type (with possible subtypes)
+	static void RegisterFactory(T* factory,wxString name, wxArrayString subTypes=wxArrayString()) {
+		// Create factories if it doesn't exist
+		if (factories == NULL) factories = new std::map<wxString,T*>;
+
+		// Prepare subtypes
+		if (subTypes.GetCount() == 0) subTypes.Add(_T(""));
+		else {
+			for (unsigned int i=0;i<subTypes.GetCount();i++) {
+				subTypes[i] = _T("/") + subTypes[i];
+			}
+		}
+
+		// Insert each subtype
+		for (unsigned int i=0;i<subTypes.GetCount();i++) {
+			factories->insert(std::make_pair(name.Lower() + subTypes[i],factory));
+		}
+	}
+
+	// Get a factory with name
+	static T *GetFactory(wxString name) {
+		// No factories
+		if (factories == NULL) {
+			factories = new std::map<wxString,T*>;
+			return NULL;
+		}
+
+		// Search for factory that matches
+		typename std::map<wxString,T*>::iterator cur;
+		for (cur = factories->begin();cur != factories->end();cur++) {
+			if (cur->first.StartsWith(name)) return cur->second;
+		}
+
+		// None found
+		return NULL;
+	}
+
+public:
+	// Virtual destructor
+	virtual ~FactoryManager() {}
+
+	// Get list of all factories, with favourite as first
+	static wxArrayString GetFactoryList(wxString favourite=_T("")) {
+		if (factories == NULL) factories = new std::map<wxString,T*>;
+		wxArrayString list;
+		favourite = favourite.Lower();
+		for (typename std::map<wxString,T*>::iterator cur=factories->begin();cur!=factories->end();cur++) {
+			if (cur->first == favourite) list.Insert(cur->first,0);
+			else list.Add(cur->first);
+		}
+		return list;
+	}
+};
diff --git a/aegisub/options.cpp b/aegisub/options.cpp
index d2b316f92f285a144c6d345d5727ace02ca716a3..f9c7eadd4e349844bb6dfc15b71cd1ab750c8689 100644
--- a/aegisub/options.cpp
+++ b/aegisub/options.cpp
@@ -160,7 +160,11 @@ void OptionsManager::LoadDefaults(bool onlyDefaults,bool doOverride) {
 	SetModificationType(MOD_VIDEO_RELOAD);
 	SetInt(_T("Avisynth MemoryMax"),64,1700);
 	SetBool(_T("Threaded Video"),false,1700);
+	#ifdef __WINDOWS__
 	SetText(_T("Video Provider"),_T("Avisynth"),1700);
+	#else
+	SetText(_T("Video Provider"),_T("FFMPEG"),1945);
+	#endif
 	SetBool(_T("Allow Ancient Avisynth"),false,1700);
 	SetText(_T("Avisynth subs renderer"),_T("vsfilter"),1700);
 	SetBool(_T("Avisynth render own subs"),true,1700);
@@ -190,13 +194,15 @@ void OptionsManager::LoadDefaults(bool onlyDefaults,bool doOverride) {
 	SetModificationType(MOD_AUDIO_RELOAD);
 	SetInt(_T("Audio Cache"),1,1700);
 	#if defined(__WINDOWS__)
-	SetText(_T("Audio Player"),_T("dsound"),1700);
+	SetText(_T("Audio Player"),_T("DirectSound"),1945);
+	SetText(_T("Audio Provider"),_T("avisynth"),1700);
 	#elif defined(__APPLE__)
 	SetText(_T("Audio Player"), _T("openal"));
+	SetText(_T("Audio Provider"),_T("FFMPEG"),1945);
 	#else
 	SetText(_T("Audio Player"),_T("portaudio")); // FIXME: should this be something else? perhaps alsa on linux and portaudio on everything else?
+	SetText(_T("Audio Provider"),_T("FFMPEG"),1945);
 	#endif
-	SetText(_T("Audio Provider"),_T("avisynth"),1700); // TODO: proper default on non-windows
 	SetText(_T("Audio Downmixer"),_T("ConvertToMono"),1700);
 	SetText(_T("Audio Alsa Device"), _T("plughw:0,0"));
 	SetText(_T("Audio HD Cache Location"),_T("default"),1700);
diff --git a/aegisub/plugin_manager.cpp b/aegisub/plugin_manager.cpp
index 20aafe94600380ae93bcbcebe698b3368bd300af..60a229fdf1fe5d0bff47b55d614d3ba841923354 100644
--- a/aegisub/plugin_manager.cpp
+++ b/aegisub/plugin_manager.cpp
@@ -41,6 +41,7 @@
 #include "audio_provider.h"
 #include "audio_player.h"
 #include "subtitles_provider.h"
+#include "spellchecker.h"
 
 
 ///////////////
@@ -60,10 +61,11 @@ PluginManager::~PluginManager() {
 // Registers all built-in plugins
 void PluginManager::RegisterBuiltInPlugins() {
 	if (!init) {
-		VideoProviderFactory::RegisterProviders();
-		AudioProviderFactory::RegisterProviders();
-		AudioPlayerFactory::RegisterProviders();
-		SubtitlesProviderFactory::RegisterProviders();
+		VideoProviderFactoryManager::RegisterProviders();
+		AudioProviderFactoryManager::RegisterProviders();
+		AudioPlayerFactoryManager::RegisterProviders();
+		SubtitlesProviderFactoryManager::RegisterProviders();
+		SpellCheckerFactoryManager::RegisterProviders();
 	}
 
 	// Done
diff --git a/aegisub/spellchecker.cpp b/aegisub/spellchecker.cpp
index d02f80b7b440d8c39e26cbd498de7d2650da8c20..e30a2ad3f5c9f644a271ee369ae2db45f6a3126d 100644
--- a/aegisub/spellchecker.cpp
+++ b/aegisub/spellchecker.cpp
@@ -37,12 +37,15 @@
 ///////////
 // Headers
 #include "spellchecker.h"
+#ifdef WITH_HUNSPELL
+#include "spellchecker_hunspell.h"
+#endif
 #include "options.h"
 
 
 /////////////////////
 // Get spell checker
-SpellChecker *SpellCheckerFactory::GetSpellChecker() {
+SpellChecker *SpellCheckerFactoryManager::GetSpellChecker() {
 	// List of providers
 	wxArrayString list = GetFactoryList(Options.AsText(_T("Spell Checker")));
 
@@ -66,6 +69,15 @@ SpellChecker *SpellCheckerFactory::GetSpellChecker() {
 }
 
 
+//////////////////////////
+// Register all providers
+void SpellCheckerFactoryManager::RegisterProviders() {
+#ifdef WITH_HUNSPELL
+	RegisterFactory(new HunspellSpellCheckerFactory(),_T("Hunspell"));
+#endif
+}
+
+
 //////////
 // Static
-template <class SpellCheckerFactory> std::map<wxString,SpellCheckerFactory*>* AegisubFactory<SpellCheckerFactory>::factories=NULL;
+template <class SpellCheckerFactory> std::map<wxString,SpellCheckerFactory*>* FactoryManager<SpellCheckerFactory>::factories=NULL;
diff --git a/aegisub/spellchecker.h b/aegisub/spellchecker.h
index 71fa86acbfec24568cf2731ca6b57bba572d0163..692fc1148f0fc7343d3a445ae1dc838d11438605 100644
--- a/aegisub/spellchecker.h
+++ b/aegisub/spellchecker.h
@@ -40,7 +40,7 @@
 ///////////
 // Headers
 #include <wx/wxprec.h>
-#include "factory.h"
+#include "factory_manager.h"
 
 
 ///////////////////////////
@@ -63,12 +63,16 @@ public:
 
 ///////////
 // Factory
-class SpellCheckerFactory : public AegisubFactory<SpellCheckerFactory> {
-protected:
+class SpellCheckerFactory {
+public:
 	virtual SpellChecker *CreateSpellChecker()=0;
-	SpellCheckerFactory(wxString name) { RegisterFactory(name); }
+};
+
 
+///////////////////
+// Factory Manager
+class SpellCheckerFactoryManager : public FactoryManager<SpellCheckerFactory> {
 public:
-	virtual ~SpellCheckerFactory() {}
 	static SpellChecker *GetSpellChecker();
+	static void RegisterProviders();
 };
diff --git a/aegisub/spellchecker_hunspell.cpp b/aegisub/spellchecker_hunspell.cpp
index 11c1f90e691993b1f8d466f778a585b6eee2ab26..faf35416720f3ad29f50f743897e348abea87d3e 100644
--- a/aegisub/spellchecker_hunspell.cpp
+++ b/aegisub/spellchecker_hunspell.cpp
@@ -39,7 +39,7 @@
 
 #ifdef WITH_HUNSPELL
 
-#include "spellchecker.h"
+#include "spellchecker_hunspell.h"
 #include "standard_paths.h"
 #include "utils.h"
 #include "options.h"
@@ -52,42 +52,6 @@
 #include <wx/txtstrm.h>
 
 
-//////////////////
-// Hunspell class
-class HunspellSpellChecker : public SpellChecker {
-private:
-	Hunspell *hunspell;
-	wxCSConv *conv;
-	wxString affpath;
-	wxString dicpath;
-	wxString usrdicpath;
-
-	void Reset();
-
-public:
-	HunspellSpellChecker();
-	~HunspellSpellChecker();
-
-	void AddWord(wxString word);
-	bool CanAddWord(wxString word);
-
-	bool CheckWord(wxString word);
-	wxArrayString GetSuggestions(wxString word);
-
-	wxArrayString GetLanguageList();
-	void SetLanguage(wxString language);
-};
-
-
-///////////
-// Factory
-class HunspellSpellCheckerFactory : public SpellCheckerFactory {
-public:
-	SpellChecker *CreateSpellChecker() { return new HunspellSpellChecker(); }
-	HunspellSpellCheckerFactory() : SpellCheckerFactory(_T("hunspell")) {}
-} registerHunspell;
-
-
 ///////////////
 // Constructor
 HunspellSpellChecker::HunspellSpellChecker() {
diff --git a/aegisub/spellchecker_hunspell.h b/aegisub/spellchecker_hunspell.h
new file mode 100644
index 0000000000000000000000000000000000000000..bd98c902d82c5119f2dca136de15a301fd1698e6
--- /dev/null
+++ b/aegisub/spellchecker_hunspell.h
@@ -0,0 +1,82 @@
+// Copyright (c) 2008, Rodrigo Braz Monteiro
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//   * Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//   * Redistributions in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//   * Neither the name of the Aegisub Group nor the names of its contributors
+//     may be used to endorse or promote products derived from this software
+//     without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// -----------------------------------------------------------------------------
+//
+// AEGISUB
+//
+// Website: http://aegisub.cellosoft.com
+// Contact: mailto:zeratul@cellosoft.com
+//
+
+
+///////////
+// Headers
+
+#ifdef WITH_HUNSPELL
+
+#include "spellchecker.h"
+#include <hunspell/hunspell.hxx>
+#include <wx/wxprec.h>
+
+
+
+//////////////////
+// Hunspell class
+class HunspellSpellChecker : public SpellChecker {
+private:
+	Hunspell *hunspell;
+	wxCSConv *conv;
+	wxString affpath;
+	wxString dicpath;
+	wxString usrdicpath;
+
+	void Reset();
+
+public:
+	HunspellSpellChecker();
+	~HunspellSpellChecker();
+
+	void AddWord(wxString word);
+	bool CanAddWord(wxString word);
+
+	bool CheckWord(wxString word);
+	wxArrayString GetSuggestions(wxString word);
+
+	wxArrayString GetLanguageList();
+	void SetLanguage(wxString language);
+};
+
+
+///////////
+// Factory
+class HunspellSpellCheckerFactory : public SpellCheckerFactory {
+public:
+	SpellChecker *CreateSpellChecker() { return new HunspellSpellChecker(); }
+};
+
+#endif
diff --git a/aegisub/subs_edit_ctrl.cpp b/aegisub/subs_edit_ctrl.cpp
index fc93a3c4a68230a68eed93cfb59cf15619d2c42c..4bec872bc500fb9020bb662ac1e164a5663e3207 100644
--- a/aegisub/subs_edit_ctrl.cpp
+++ b/aegisub/subs_edit_ctrl.cpp
@@ -70,7 +70,7 @@ SubsTextEditCtrl::SubsTextEditCtrl(wxWindow* parent, wxWindowID id, const wxStri
 	CmdKeyClear('U',wxSTC_SCMOD_CTRL);
 
 	// Set spellchecker
-	spellchecker = SpellCheckerFactory::GetSpellChecker();
+	spellchecker = SpellCheckerFactoryManager::GetSpellChecker();
 
 	// Set thesaurus
 	thesaurus = Thesaurus::GetThesaurus();
diff --git a/aegisub/subs_preview.cpp b/aegisub/subs_preview.cpp
index 7f85b2595efc74f86302085739f5c11c7383b138..4dbb73611dc041229a52260fc3e1429a5d89eee0 100644
--- a/aegisub/subs_preview.cpp
+++ b/aegisub/subs_preview.cpp
@@ -143,7 +143,7 @@ void SubtitlesPreview::UpdateBitmap(int w,int h) {
 	// Try to get subtitles provider
 	SubtitlesProvider *provider = NULL;
 	try {
-		provider = SubtitlesProviderFactory::GetProvider();
+		provider = SubtitlesProviderFactoryManager::GetProvider();
 	} 
 	catch (...) {
 		wxMessageBox(_T("Could not get any subtitles provider for the preview box. Make sure that you have a provider installed."),_T("No subtitles provider"),wxICON_ERROR);
diff --git a/aegisub/subtitle_format_dvd.cpp b/aegisub/subtitle_format_dvd.cpp
index c98132be4668c0dfd34552aa3707f2447795bc65..b6a2a52169d91bcebce18af1ad5c888ac1fea4a5 100644
--- a/aegisub/subtitle_format_dvd.cpp
+++ b/aegisub/subtitle_format_dvd.cpp
@@ -97,7 +97,7 @@ void DVDSubtitleFormat::GetSubPictureList(std::vector<SubPicture> &pics) {
 	pics.resize(count);
 
 	SubtitlesProvider *provider = NULL;
-	provider = SubtitlesProviderFactory::GetProvider();
+	provider = SubtitlesProviderFactoryManager::GetProvider();
 	provider->LoadSubtitles(GetAssFile());
 
 	// Write lines
diff --git a/aegisub/subtitles_provider.cpp b/aegisub/subtitles_provider.cpp
index 59792158ea27bb087c7d95d8abf12a6fb170d0a8..1960988d5618469ade439889fde8b926aca8ded8 100644
--- a/aegisub/subtitles_provider.cpp
+++ b/aegisub/subtitles_provider.cpp
@@ -54,7 +54,7 @@ SubtitlesProvider::~SubtitlesProvider() {
 
 ////////////////////////////////////////////////////////////////
 // Check if provider available (doesn't verify provider works!)
-bool SubtitlesProviderFactory::ProviderAvailable() {
+bool SubtitlesProviderFactoryManager::ProviderAvailable() {
 	// List of providers
 	wxArrayString list = GetFactoryList(Options.AsText(_T("Subtitles provider")));
 
@@ -65,7 +65,7 @@ bool SubtitlesProviderFactory::ProviderAvailable() {
 
 ////////////////
 // Get provider
-SubtitlesProvider* SubtitlesProviderFactory::GetProvider() {
+SubtitlesProvider* SubtitlesProviderFactoryManager::GetProvider() {
 	// List of providers
 	wxArrayString list = GetFactoryList(Options.AsText(_T("Subtitles provider")));
 
@@ -94,16 +94,17 @@ SubtitlesProvider* SubtitlesProviderFactory::GetProvider() {
 
 //////////////////////
 // Register providers
-void SubtitlesProviderFactory::RegisterProviders() {
+void SubtitlesProviderFactoryManager::RegisterProviders() {
 #ifdef WITH_CSRI
-	new CSRISubtitlesProviderFactory();
+	CSRISubtitlesProviderFactory *csri = new CSRISubtitlesProviderFactory();
+	RegisterFactory(csri,_T("CSRI"),csri->GetSubTypes());
 #endif
 #ifdef WITH_LIBASS
-	new LibassSubtitlesProviderFactory();
+	RegisterFactory(new LibassSubtitlesProviderFactory(),_T("libass"));
 #endif
 }
 
 
 //////////
 // Static
-template <class SubtitlesProviderFactory> std::map<wxString,SubtitlesProviderFactory*>* AegisubFactory<SubtitlesProviderFactory>::factories=NULL;
+template <class SubtitlesProviderFactory> std::map<wxString,SubtitlesProviderFactory*>* FactoryManager<SubtitlesProviderFactory>::factories=NULL;
diff --git a/aegisub/subtitles_provider.h b/aegisub/subtitles_provider.h
index af320dca64dbb4ccbbc43ef87321908f7be09d8a..7781d77039d5a662601bc6b79cccb89f28be79cb 100644
--- a/aegisub/subtitles_provider.h
+++ b/aegisub/subtitles_provider.h
@@ -41,7 +41,7 @@
 // Headers
 #include <wx/wxprec.h>
 #include "video_frame.h"
-#include "factory.h"
+#include "factory_manager.h"
 
 
 //////////////
@@ -65,16 +65,19 @@ public:
 
 ///////////
 // Factory
-class SubtitlesProviderFactory : public AegisubFactory<SubtitlesProviderFactory> {
-protected:
+class SubtitlesProviderFactory {
+public:
+	virtual ~SubtitlesProviderFactory() {}
 	virtual SubtitlesProvider *CreateProvider(wxString subType=_T(""))=0;
-	SubtitlesProviderFactory(wxString name,wxArrayString subTypes=wxArrayString()) {
-		RegisterFactory(name,subTypes);
-	}
+};
 
+
+///////////////////
+// Factory Manager
+class SubtitlesProviderFactoryManager : public FactoryManager<SubtitlesProviderFactory> {
 public:
-	virtual ~SubtitlesProviderFactory() {}
 	static SubtitlesProvider *GetProvider();
 	static void RegisterProviders();
 	static bool ProviderAvailable();
 };
+
diff --git a/aegisub/subtitles_provider_csri.h b/aegisub/subtitles_provider_csri.h
index 003c160147015107b66dfb58cb5d5a7c9e8c8386..8a03f045f59c5d6744711608166de887e2510ad0 100644
--- a/aegisub/subtitles_provider_csri.h
+++ b/aegisub/subtitles_provider_csri.h
@@ -75,7 +75,6 @@ class CSRISubtitlesProviderFactory : public SubtitlesProviderFactory {
 public:
 	SubtitlesProvider *CreateProvider(wxString subType=_T("")) { return new CSRISubtitlesProvider(subType); }
 	wxArrayString GetSubTypes();
-	CSRISubtitlesProviderFactory() : SubtitlesProviderFactory(_T("csri"),GetSubTypes()) {}
 };
 
 #endif
diff --git a/aegisub/video_context.cpp b/aegisub/video_context.cpp
index a76d3600e0ebea3c275de25ef71d431b0bae9606..2d066e79391528456db66736d988baeb0171c2b8 100644
--- a/aegisub/video_context.cpp
+++ b/aegisub/video_context.cpp
@@ -329,13 +329,13 @@ void VideoContext::SetVideo(const wxString &filename) {
 #endif
 
 			// Choose a provider
-			provider = VideoProviderFactory::GetProvider(filename,overFps);
+			provider = VideoProviderFactoryManager::GetProvider(filename,overFps);
 			loaded = provider != NULL;
 
 			// Get subtitles provider
 			try {
 				subsProvider = provider->GetAsSubtitlesProvider();
-				if (!subsProvider) subsProvider = SubtitlesProviderFactory::GetProvider();
+				if (!subsProvider) subsProvider = SubtitlesProviderFactoryManager::GetProvider();
 			}
 			catch (wxString err) { wxMessageBox(_T("Error while loading subtitles provider: ") + err,_T("Subtitles provider"));	}
 			catch (const wchar_t *err) { wxMessageBox(_T("Error while loading subtitles provider: ") + wxString(err),_T("Subtitles provider"));	}
diff --git a/aegisub/video_provider.cpp b/aegisub/video_provider.cpp
index 92486d4649cc01341dbf0a7ec0d14a575d355568..b70cb339f60edba852906a6d74071ed3b979211e 100644
--- a/aegisub/video_provider.cpp
+++ b/aegisub/video_provider.cpp
@@ -55,7 +55,7 @@
 
 ////////////////
 // Get provider
-VideoProvider *VideoProviderFactory::GetProvider(wxString video,double fps) {
+VideoProvider *VideoProviderFactoryManager::GetProvider(wxString video,double fps) {
 	// First check special case of dummy video
 	if (video.StartsWith(_T("?dummy:"))) {
 		return new DummyVideoProvider(video, fps);
@@ -93,19 +93,19 @@ VideoProvider *VideoProviderFactory::GetProvider(wxString video,double fps) {
 
 //////////////////////////
 // Register all providers
-void VideoProviderFactory::RegisterProviders() {
+void VideoProviderFactoryManager::RegisterProviders() {
 #ifdef WITH_AVISYNTH
-	new AvisynthVideoProviderFactory();
+	RegisterFactory(new AvisynthVideoProviderFactory(),_T("Avisynth"));
 #endif
 #ifdef WITH_DIRECTSHOW
-	new DirectShowVideoProviderFactory();
+	RegisterFactory(new DirectShowVideoProviderFactory(),_T("DirectShow"));
 #endif
 #ifdef WITH_FFMPEG
-	new LAVCVideoProviderFactory();
+	RegisterFactory(new LAVCVideoProviderFactory(),_T("FFMPEG"));
 #endif
 }
 
 
 //////////
 // Static
-template <class VideoProviderFactory> std::map<wxString,VideoProviderFactory*>* AegisubFactory<VideoProviderFactory>::factories=NULL;
+template <class VideoProviderFactory> std::map<wxString,VideoProviderFactory*>* FactoryManager<VideoProviderFactory>::factories=NULL;
diff --git a/aegisub/video_provider.h b/aegisub/video_provider.h
index 49a4bdded400d4e27b2656d06737936ba5ca5bb9..c8ce3af59d3d47c0e5cded3e4d785f25306a21cd 100644
--- a/aegisub/video_provider.h
+++ b/aegisub/video_provider.h
@@ -41,7 +41,7 @@
 // Headers
 #include <wx/intl.h>
 #include "video_frame.h"
-#include "factory.h"
+#include "factory_manager.h"
 
 
 //////////////
@@ -86,14 +86,16 @@ public:
 
 ///////////
 // Factory
-class VideoProviderFactory : public AegisubFactory<VideoProviderFactory> {
-protected:
+class VideoProviderFactory {
+public:
 	virtual VideoProvider *CreateProvider(wxString video,double fps=0.0)=0;
-	VideoProviderFactory(wxString name) { RegisterFactory(name); }
+};
 
-public:
-	virtual ~VideoProviderFactory() {}
-	static VideoProvider *GetProvider(wxString video,double fps=0.0);
 
+///////////////////
+// Factory Manager
+class VideoProviderFactoryManager : public FactoryManager<VideoProviderFactory> {
+public:
 	static void RegisterProviders();
+	static VideoProvider *GetProvider(wxString video,double fps=0.0);
 };
diff --git a/aegisub/video_provider_avs.h b/aegisub/video_provider_avs.h
index 963afb445c95ea19804f66e882aeed8a56246b94..efdd176007521dc85e84b5ef1dff42e0c62c7906 100644
--- a/aegisub/video_provider_avs.h
+++ b/aegisub/video_provider_avs.h
@@ -101,7 +101,6 @@ public:
 class AvisynthVideoProviderFactory : public VideoProviderFactory {
 public:
 	VideoProvider *CreateProvider(wxString video,double fps=0.0) { return new AvisynthVideoProvider(video,fps); }
-	AvisynthVideoProviderFactory() : VideoProviderFactory(_T("avisynth")) {}
 };
 
 
diff --git a/aegisub/video_provider_dshow.h b/aegisub/video_provider_dshow.h
index f8cc29a5b0bd06c385aed1960ef97bd54172b97d..a774bd0dfadc35a5d6833cb042092450564a6c48 100644
--- a/aegisub/video_provider_dshow.h
+++ b/aegisub/video_provider_dshow.h
@@ -124,7 +124,6 @@ public:
 class DirectShowVideoProviderFactory : public VideoProviderFactory {
 public:
 	VideoProvider *CreateProvider(wxString video,double fps=0.0) { return new DirectShowVideoProvider(video,fps); }
-	DirectShowVideoProviderFactory() : VideoProviderFactory(_T("dshow")) {}
 };
 
 #endif
diff --git a/build/aegisub_vs2008/aegisub_vs2008.vcproj b/build/aegisub_vs2008/aegisub_vs2008.vcproj
index a284007a64291007a76bae593fddeaddba810bcb..cde59070af11199f81409ffe3ca4b2eb28d55d0a 100644
--- a/build/aegisub_vs2008/aegisub_vs2008.vcproj
+++ b/build/aegisub_vs2008/aegisub_vs2008.vcproj
@@ -222,10 +222,11 @@
 				OpenMP="true"
 				UsePrecompiledHeader="2"
 				PrecompiledHeaderThrough="stdwx.h"
+				ProgramDataBaseFileName="$(IntDir)\vc90.pdb"
 				WarningLevel="3"
 				WarnAsError="true"
 				Detect64BitPortabilityProblems="false"
-				DebugInformationFormat="3"
+				DebugInformationFormat="0"
 				DisableSpecificWarnings="4267"
 				ForcedIncludeFiles="stdwx.h;config.h"
 			/>
@@ -917,7 +918,7 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\aegisub\factory.h"
+				RelativePath="..\..\aegisub\factory_manager.h"
 				>
 			</File>
 			<File
@@ -1672,6 +1673,10 @@
 				RelativePath="..\..\aegisub\spellchecker_hunspell.cpp"
 				>
 			</File>
+			<File
+				RelativePath="..\..\aegisub\spellchecker_hunspell.h"
+				>
+			</File>
 			<File
 				RelativePath="..\..\aegisub\thesaurus.cpp"
 				>