Description: Error handling
 * Guard against reinitializing the builtin milkdrop functions.
   Hides a deeper issue where something is double loading the preset factories, most
   likely.
 * Playlist file / directory error handling fixes, resize playlist refresh fix
 
Forwarded: yes
Author: Carmelo Piccione <carmelo.piccione@gmail.com>
Last-Update: 2010-07-29
--- a/src/libprojectM/MilkdropPresetFactory/BuiltinFuncs.cpp
+++ b/src/libprojectM/MilkdropPresetFactory/BuiltinFuncs.cpp
@@ -29,7 +29,7 @@
   /* Create new function */
   func = new Func(name, func_ptr, num_args);
 
-  if (func == NULL)
+  if (func == 0)
     return PROJECTM_OUTOFMEM_ERROR;
 
   retval = insert_func( func );
@@ -115,12 +115,18 @@
   return PROJECTM_SUCCESS;
 }
 
+volatile bool BuiltinFuncs::initialized = false;
 
 /* Initialize the builtin function database.
    Should only be necessary once */
 int BuiltinFuncs::init_builtin_func_db() {
   int retval;
 
+  if (initialized) {
+    return 0;
+  } else
+    initialized = true;
+  
   retval = load_all_builtin_func();
   return retval;
 }
@@ -134,7 +140,7 @@
 traverse<TraverseFunctors::Delete<Func> >(builtin_func_tree);
 
 builtin_func_tree.clear();
-
+initialized = false;
 return PROJECTM_SUCCESS;
 }
 
@@ -142,13 +148,24 @@
 int BuiltinFuncs::insert_func( Func *func ) {
 
   assert(func);
-  std::pair<std::map<std::string, Func*>::iterator, bool> inserteePair =
-  	builtin_func_tree.insert(std::make_pair(std::string(func->getName()), func));
   
+  if (func == 0) {
+      std::cerr << "Received a null function object, ignoring...." << std::endl;
+      return PROJECTM_ERROR;
+  }
+  
+//   //std::cout << "inserting function " << func->getName() << std::endl;
+  
+  const std::pair<std::string, Func*> pair = std::make_pair(std::string(func->getName()), func);
+  
+  assert(pair.second);
+  
+  const std::pair<std::map<std::string, Func*>::iterator, bool> inserteePair =
+  	builtin_func_tree.insert(pair);
+  	
   if (!inserteePair.second) {
 	std::cerr << "Failed to insert builtin function \"" << func->getName() << "\" into collection! Bailing..." << std::endl;
 	abort();
-
   }
 
   return PROJECTM_SUCCESS;
--- a/src/libprojectM/MilkdropPresetFactory/BuiltinFuncs.hpp
+++ b/src/libprojectM/MilkdropPresetFactory/BuiltinFuncs.hpp
@@ -229,6 +229,7 @@
     static Func *find_func( const std::string & name );
 private:
      static std::map<std::string, Func*> builtin_func_tree;
+     static volatile bool initialized;
 };
 
 #endif
--- a/src/libprojectM/MilkdropPresetFactory/MilkdropPresetFactory.cpp
+++ b/src/libprojectM/MilkdropPresetFactory/MilkdropPresetFactory.cpp
@@ -26,7 +26,7 @@
 	Eval::init_infix_ops();
 
 	_presetOutputs = createPresetOutputs(gx,gy);
-    _presetOutputs2 = createPresetOutputs(gx, gy);
+	_presetOutputs2 = createPresetOutputs(gx, gy);
 }
 
 MilkdropPresetFactory::~MilkdropPresetFactory() {
@@ -37,13 +37,13 @@
 	BuiltinFuncs::destroy_builtin_func_db();
 	std::cerr << "[~MilkdropPresetFactory] delete preset out puts" << std::endl;
 	delete(_presetOutputs);
-    delete(_presetOutputs2);
+        delete(_presetOutputs2);
 	std::cerr << "[~MilkdropPresetFactory] done" << std::endl;
 
 }
 
 /* Reinitializes the engine variables to a default (conservative and sane) value */
-void resetPresetOutputs(PresetOutputs *presetOutputs)
+void resetPresetOutputs(PresetOutputs * presetOutputs)
 {
 
     presetOutputs->zoom=1.0;
--- a/src/libprojectM/PresetFactoryManager.cpp
+++ b/src/libprojectM/PresetFactoryManager.cpp
@@ -20,7 +20,7 @@
 #endif
 
 #include <sstream>
-PresetFactoryManager::PresetFactoryManager() : _gx(0), _gy(0) {}
+PresetFactoryManager::PresetFactoryManager() : _gx(0), _gy(0), initialized(false) {}
 
 PresetFactoryManager::~PresetFactoryManager() {
 	for (std::vector<PresetFactory *>::iterator pos = _factoryList.begin(); 
@@ -29,11 +29,20 @@
 		delete(*pos);
 	}
 
-
+  initialized = false;
 }
+
 void PresetFactoryManager::initialize(int gx, int gy) {
 	_gx = gx;
 	_gy = gy;
+	
+	if (!initialized) {
+	  initialized = true;
+	} else {
+	  std::cout << "already initialized " << std::endl;
+	  return;
+	}
+	  
 	PresetFactory * factory;
 	
 	#ifndef DISABLE_MILKDROP_PRESETS
--- a/src/libprojectM/PresetFactoryManager.hpp
+++ b/src/libprojectM/PresetFactoryManager.hpp
@@ -21,7 +21,7 @@
 		virtual ~PresetFactoryException() throw() {}
 		const std::string & message() const { return _message; } 
 
-	private:	
+	private:
 		std::string _message;
 };
 
@@ -54,6 +54,6 @@
 		mutable std::map<std::string, PresetFactory *> _factoryMap;
 		mutable std::vector<PresetFactory *> _factoryList;
 		void registerFactory(const std::string & extension, PresetFactory * factory);
-
+		volatile bool initialized;
 };
 #endif
--- a/src/libprojectM/projectM.cpp
+++ b/src/libprojectM/projectM.cpp
@@ -222,7 +222,6 @@
     projectM_init ( _settings.meshX, _settings.meshY, _settings.fps,
                     _settings.textureSize, _settings.windowWidth,_settings.windowHeight);
 
-
                     _settings.beatSensitivity = beatDetect->beat_sensitivity = config.read<float> ( "Hard Cut Sensitivity", 10.0 );
 
                     if ( config.read ( "Aspect Correction", true ) )
--- a/src/projectM-pulseaudio/QPulseAudioThread.cpp
+++ b/src/projectM-pulseaudio/QPulseAudioThread.cpp
@@ -296,9 +296,7 @@
 {
 	assert ( mainloop_api );
 	mainloop_api->quit ( mainloop_api, ret );
-	if (*s_qprojectM_MainWindowPtr)
-		delete(*s_qprojectM_MainWindowPtr);
-	*s_qprojectM_MainWindowPtr = 0;
+	
 }
 
 
@@ -315,7 +313,8 @@
 	{
 		fprintf ( stderr, "pa_stream_peek() failed: %s\n", pa_strerror ( pa_context_errno ( context ) ) );
 		pulseQuit ( 1 );
-		return;
+		return
+;
 	}
 
 	if ((!s_qprojectM_MainWindowPtr) || (!*s_qprojectM_MainWindowPtr))
@@ -352,16 +351,16 @@
 	switch ( pa_stream_get_state ( s ) )
 	{
 		case PA_STREAM_UNCONNECTED:
-//			qDebug() << "UNCONNECTED";
+			qDebug() << "UNCONNECTED";
 			break;
 		case PA_STREAM_CREATING:
-//			qDebug() << "CREATED";
+		  qDebug() << "CREATED";
 			break;
 		case PA_STREAM_TERMINATED:
-//			qDebug() << "TERMINATED";
+			qDebug() << "TERMINATED";
 			break;
 		case PA_STREAM_READY:
-//			qDebug() << "READY";
+			qDebug() << "READY";
 			if ( verbose )
 			{
 				const pa_buffer_attr *a;
--- a/src/projectM-qt/qplaylisttableview.hpp
+++ b/src/projectM-qt/qplaylisttableview.hpp
@@ -93,14 +93,14 @@
 	 }
 	 
 	 inline void resizeEvent(QResizeEvent * event) {
-
+		QTableView::resizeEvent(event);
 		emit(resized(event));
 	 }	
 	 
 	 inline void mousePressEvent(QMouseEvent * event) {
 		QAbstractItemView::mousePressEvent(event);
 		if (event->button() == Qt::RightButton) {
-			emit(mousePressed(event, selectedIndexes()));			
+			emit(mousePressed(event, selectedIndexes()));
 		}
 		else
 				;
--- a/src/projectM-qt/qprojectm_mainwindow.cpp
+++ b/src/projectM-qt/qprojectm_mainwindow.cpp
@@ -98,7 +98,8 @@
 
 	connect(ui->tableView, SIGNAL(resized(QResizeEvent *)), this, SLOT(refreshHeaders(QResizeEvent*)));
 	
-	connect(ui->tableView, SIGNAL(mousePressed(QMouseEvent*, const QModelIndexList &)), this, SLOT(popupPlaylistContextMenu(QMouseEvent*, const QModelIndexList &)));
+	connect(ui->tableView, SIGNAL(mousePressed(QMouseEvent*, const QModelIndexList &)), this,
+		SLOT(popupPlaylistContextMenu(QMouseEvent*, const QModelIndexList &)));
 	
 	connect ( m_QProjectMWidget, SIGNAL ( projectM_Initialized(QProjectM*) ), 
 		  this, SLOT ( postProjectM_Initialize() ) );
@@ -662,7 +663,7 @@
 		// Add 1 to skip the Name column
 		hHeader->setResizeMode (i+1, QHeaderView::ResizeToContents);
 		sizeTotal += hHeader->sectionSize(i+1);
-	}				
+	}
 	hHeader->resizeSection(0, ui->tableView->size().width()-20-sizeTotal);
 	
 	
@@ -883,11 +884,13 @@
 		QString url = m_QPlaylistFileDialog->selectedFiles() [0];
 
 		
-		if ( !playlistModel->readPlaylist ( url ) ) { 
+		const bool loadedOk = playlistModel->readPlaylist ( url );
+		
+		if (!loadedOk) { 
 			qDebug() << "could not open playlist";
 			url = QString();
-			
-		}
+		} 
+		
 		qDebug() << "url: " << url;
 		updatePlaylistUrl(url);
 		
--- a/src/projectM-qt/qprojectmwidget.hpp
+++ b/src/projectM-qt/qprojectmwidget.hpp
@@ -22,6 +22,7 @@
 #ifndef QPROJECTM_WIDGET_HPP
 #define QPROJECTM_WIDGET_HPP
 
+#include <iostream>
 #include "qprojectm.hpp"
 #include <QGLWidget>
 #include <QMutex>
@@ -111,7 +112,7 @@
 
 		void resetProjectM()
 		{
-
+			std::cout << "reseting" << std::endl;
 			qDebug() << "reset start";
 
 			emit ( projectM_BeforeDestroy() );
@@ -246,8 +247,10 @@
 		void initializeGL()
 		{
 
-			this->m_projectM = new QProjectM ( m_config_file );
-			projectM_Initialized ( m_projectM );
+		        if (m_projectM == 0) {
+			    this->m_projectM = new QProjectM ( m_config_file );
+			    projectM_Initialized ( m_projectM );
+			}
 		}
 
 		inline void paintGL()