[Scummvm-cvs-logs] SF.net SVN: scummvm: [31101] residual/trunk

aquadran at users.sourceforge.net aquadran at users.sourceforge.net
Tue Mar 11 00:06:08 CET 2008


Revision: 31101
          http://scummvm.svn.sourceforge.net/scummvm/?rev=31101&view=rev
Author:   aquadran
Date:     2008-03-10 16:06:07 -0700 (Mon, 10 Mar 2008)

Log Message:
-----------
synced imuse digital with scummvm imuse and related stuff 

Modified Paths:
--------------
    residual/trunk/common/sys.h
    residual/trunk/common/timer.h
    residual/trunk/dists/msvc9/residual.vcproj
    residual/trunk/engine/backend/driver.h
    residual/trunk/engine/backend/sdl/driver_sdl.cpp
    residual/trunk/engine/backend/sdl/driver_sdl.h
    residual/trunk/engine/font.cpp
    residual/trunk/engine/imuse/imuse.cpp
    residual/trunk/engine/imuse/imuse.h
    residual/trunk/engine/imuse/imuse_mcmp_mgr.cpp
    residual/trunk/engine/imuse/imuse_music.cpp
    residual/trunk/engine/imuse/imuse_script.cpp
    residual/trunk/engine/imuse/imuse_sndmgr.cpp
    residual/trunk/engine/imuse/imuse_sndmgr.h
    residual/trunk/engine/imuse/imuse_track.cpp
    residual/trunk/engine/lua.cpp
    residual/trunk/engine/main.cpp
    residual/trunk/engine/savegame.cpp
    residual/trunk/engine/smush/blocky16.cpp
    residual/trunk/engine/smush/smush.cpp
    residual/trunk/engine/smush/smush.h
    residual/trunk/engine/textobject.cpp

Added Paths:
-----------
    residual/trunk/common/frac.h
    residual/trunk/common/list.h
    residual/trunk/common/mutex.cpp
    residual/trunk/common/mutex.h
    residual/trunk/common/noncopyable.h
    residual/trunk/engine/backend/default-timer.cpp
    residual/trunk/engine/backend/default-timer.h
    residual/trunk/engine/imuse/imuse_tables.h
    residual/trunk/engine/imuse/imuse_track.h

Removed Paths:
-------------
    residual/trunk/common/timer.cpp

Added: residual/trunk/common/frac.h
===================================================================
--- residual/trunk/common/frac.h	                        (rev 0)
+++ residual/trunk/common/frac.h	2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,52 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef COMMON_FRAC_H
+#define COMMON_FRAC_H
+
+#include "common/sys.h"
+
+/**
+ * The precision of the fractional (fixed point) type we define below.
+ * Normally you should never have to modify this value.
+ */
+enum {
+	FRAC_BITS = 16,
+	FRAC_LO_MASK = ((1L << FRAC_BITS) - 1),
+	FRAC_HI_MASK = ((1L << FRAC_BITS) - 1) << FRAC_BITS,
+
+	FRAC_ONE = (1L << FRAC_BITS),		// 1.0
+	FRAC_HALF = (1L << (FRAC_BITS-1))	// 0.5
+};
+
+/**
+ * Fixed-point fractions, used by the sound rate converter and other code.
+ */
+typedef int32 frac_t;
+
+inline frac_t doubleToFrac(double value) { return (frac_t)(value * FRAC_ONE); }
+inline double fracToDouble(frac_t value) { return ((double)value) / FRAC_ONE; }
+
+inline frac_t intToFrac(int16 value) { return value << FRAC_BITS; }
+inline int16 fracToInt(frac_t value) { return value >> FRAC_BITS; }
+
+#endif


Property changes on: residual/trunk/common/frac.h
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Added: residual/trunk/common/list.h
===================================================================
--- residual/trunk/common/list.h	                        (rev 0)
+++ residual/trunk/common/list.h	2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,264 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef COMMON_LIST_H
+#define COMMON_LIST_H
+
+#include "common/sys.h"
+
+namespace Common {
+
+/**
+ * Simple double linked list, modeled after the list template of the standard
+ * C++ library. 
+ */
+template <class t_T>
+class List {
+protected:
+#if defined (_WIN32_WCE) || defined (_MSC_VER)
+//FIXME evc4 and msvc7 doesn't like it as protected member
+public:
+#endif
+	struct NodeBase {
+		NodeBase *_prev;
+		NodeBase *_next;
+	};
+	
+	template <class t_T2>
+	struct Node : public NodeBase {
+		t_T2 _data;
+		
+		Node(const t_T2 &x) : _data(x) {}
+	};
+
+	template <class t_T2>
+	class Iterator {
+		friend class List<t_T>;
+		NodeBase *_node;
+
+#if !defined (__WINSCW__)
+		explicit Iterator(NodeBase *node) : _node(node) {}
+#else
+		Iterator(NodeBase *node) : _node(node) {}
+#endif
+
+	public:
+		Iterator() : _node(0) {}
+
+		// Prefix inc
+		Iterator<t_T2> &operator++() {
+			if (_node)
+				_node = _node->_next;
+			return *this;
+		}
+		// Postfix inc
+		Iterator<t_T2> operator++(int) {
+			Iterator tmp(_node);
+			++(*this);
+			return tmp;
+		}
+		// Prefix dec
+		Iterator<t_T2> &operator--() {
+			if (_node)
+				_node = _node->_prev;
+			return *this;
+		}
+		// Postfix dec
+		Iterator<t_T2> operator--(int) {
+			Iterator tmp(_node);
+			--(*this);
+			return tmp;
+		}
+		t_T2& operator*() const {
+			assert(_node);
+#if (__GNUC__ == 2) && (__GNUC_MINOR__ >= 95)
+			return static_cast<List<t_T>::Node<t_T2> *>(_node)->_data;
+#else
+			return static_cast<Node<t_T2>*>(_node)->_data;
+#endif
+		}
+		t_T2* operator->() const {
+			return &(operator*());
+		}
+		
+		bool operator==(const Iterator<t_T2>& x) const {
+			return _node == x._node;
+		}
+		
+		bool operator!=(const Iterator<t_T2>& x) const {
+			return _node != x._node;
+		}
+	};
+
+	NodeBase *_anchor;
+
+public:
+	typedef Iterator<t_T>			iterator;
+	typedef Iterator<const t_T>	const_iterator;
+
+	typedef t_T value_type;
+
+public:
+	List() {
+		_anchor = new NodeBase;
+		_anchor->_prev = _anchor;
+		_anchor->_next = _anchor;
+	}
+	List(const List<t_T>& list) {
+		_anchor = new NodeBase;
+		_anchor->_prev = _anchor;
+		_anchor->_next = _anchor;
+
+		insert(begin(), list.begin(), list.end());
+	}
+
+	~List() {
+		clear();
+		delete _anchor;
+	}
+
+	void push_front(const t_T& element) {
+		insert(begin(), element);
+	}
+
+	void push_back(const t_T& element) {
+		insert(end(), element);
+	}
+
+	void insert(iterator pos, const t_T& element) {
+		NodeBase *newNode = new Node<t_T>(element);
+		
+		newNode->_next = pos._node;
+		newNode->_prev = pos._node->_prev;
+		newNode->_prev->_next = newNode;
+		newNode->_next->_prev = newNode;
+	}
+
+    template <typename iterator2>
+	void insert(iterator pos, iterator2 first, iterator2 last) {
+		for (; first != last; ++first)
+			insert(pos, *first);
+	}
+
+	iterator erase(iterator pos) {
+		assert(pos != end());
+
+		NodeBase *next = pos._node->_next;
+		NodeBase *prev = pos._node->_prev;
+		Node<t_T> *node = static_cast<Node<t_T> *>(pos._node);
+		prev->_next = next;
+		next->_prev = prev;
+		delete node;
+		return iterator(next);
+	}
+
+	iterator reverse_erase(iterator pos) {
+		assert(pos != end());
+
+		NodeBase *next = pos._node->_next;
+		NodeBase *prev = pos._node->_prev;
+		Node<t_T> *node = static_cast<Node<t_T> *>(pos._node);
+		prev->_next = next;
+		next->_prev = prev;
+		delete node;
+		return iterator(prev);
+	}
+
+	iterator erase(iterator first, iterator last) {
+		while (first != last)
+			erase(first++);
+
+		return last;
+	}
+
+	void remove(const t_T &val) {
+		iterator i = begin();
+		while (i != end())
+			if (val == i.operator*())
+				i = erase(i);
+			else
+				++i;
+	}
+
+
+	List<t_T>& operator  =(const List<t_T>& list) {
+		if (this != &list) {
+			iterator i;
+			const_iterator j;
+
+			for (i = begin(), j = list.begin();  (i != end()) && (j != list.end()) ; ++i, ++j) {
+				static_cast<Node<t_T> *>(i._node)->_data = static_cast<Node<t_T> *>(j._node)->_data;
+			}
+
+			if (i == end())
+				insert(i, j, list.end());
+			else
+				erase(i, end());
+		}
+		
+		return *this;
+	}
+
+	uint size() const {
+		int n = 0;
+		for (const_iterator i = begin(); i != end(); ++i)
+			++n;
+		return n;
+	}
+
+	void clear() {
+		erase(begin(), end());
+	}
+	
+	bool empty() const { 
+		return (_anchor == _anchor->_next);
+	}
+
+
+	iterator		begin() {
+		return iterator(_anchor->_next);
+	}
+
+	iterator		reverse_begin() {
+		return iterator(_anchor->_prev);
+	}
+
+	iterator		end() {
+		return iterator(_anchor);
+	}
+
+	const_iterator	begin() const {
+		return const_iterator(_anchor->_next);
+	}
+
+	const_iterator	reverse_begin() const {
+		return const_iterator(_anchor->_prev);
+	}
+
+	const_iterator	end() const {
+		return const_iterator(_anchor);
+	}
+};
+
+} // End of namespace Common
+
+#endif


Property changes on: residual/trunk/common/list.h
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Added: residual/trunk/common/mutex.cpp
===================================================================
--- residual/trunk/common/mutex.cpp	                        (rev 0)
+++ residual/trunk/common/mutex.cpp	2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,72 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/mutex.h"
+#include "common/debug.h"
+
+#include "engine/backend/driver.h"
+
+namespace Common {
+
+Mutex::Mutex() {
+	_mutex = g_driver->createMutex();
+}
+
+Mutex::~Mutex() {
+	g_driver->deleteMutex(_mutex);
+}
+
+void Mutex::lock() {
+	g_driver->lockMutex(_mutex);
+}
+
+void Mutex::unlock() {
+	g_driver->unlockMutex(_mutex);
+}
+
+
+#pragma mark -
+
+
+StackLock::StackLock(MutexRef mutex, const char *mutexName)
+	: _mutex(mutex), _mutexName(mutexName) {
+	lock();
+}
+
+StackLock::StackLock(const Mutex &mutex, const char *mutexName)
+	: _mutex(mutex._mutex), _mutexName(mutexName) {
+	lock();
+}
+
+StackLock::~StackLock() {
+	unlock();
+}
+
+void StackLock::lock() {
+	g_driver->lockMutex(_mutex);
+}
+
+void StackLock::unlock() {
+	g_driver->unlockMutex(_mutex);
+}
+
+}	// End of namespace Common


Property changes on: residual/trunk/common/mutex.cpp
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Added: residual/trunk/common/mutex.h
===================================================================
--- residual/trunk/common/mutex.h	                        (rev 0)
+++ residual/trunk/common/mutex.h	2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,73 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef COMMON_MUTEX_H
+#define COMMON_MUTEX_H
+
+#include "common/sys.h"
+
+namespace Common {
+
+class Mutex;
+
+/**
+ * An pseudo-opaque mutex type.
+ */
+typedef struct OpaqueMutex *MutexRef;
+
+
+/**
+ * Auxillary class to (un)lock a mutex on the stack.
+ */
+class StackLock {
+	MutexRef _mutex;
+	const char *_mutexName;
+
+	void lock();
+	void unlock();
+public:
+	StackLock(MutexRef mutex, const char *mutexName = NULL);
+	StackLock(const Mutex &mutex, const char *mutexName = NULL);
+	~StackLock();
+};
+
+
+/**
+ * Wrapper class.
+ */
+class Mutex {
+	friend class StackLock;
+
+	MutexRef _mutex;
+
+public:
+	Mutex();
+	~Mutex();
+
+	void lock();
+	void unlock();
+};
+
+
+} // End of namespace Common
+
+#endif


Property changes on: residual/trunk/common/mutex.h
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Added: residual/trunk/common/noncopyable.h
===================================================================
--- residual/trunk/common/noncopyable.h	                        (rev 0)
+++ residual/trunk/common/noncopyable.h	2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,43 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef COMMON_NONCOPYABLE_H
+#define COMMON_NONCOPYABLE_H
+
+namespace Common {
+
+/**
+ * Subclass of NonCopyable can not be copied due to the fact that
+ * we made the copy constructor and assigment operator private.
+ */
+class NonCopyable {
+public:
+	NonCopyable() {}
+private:
+	// Prevent copying instances by accident
+	NonCopyable(const NonCopyable&);
+	NonCopyable& operator= (const NonCopyable&);
+};
+
+} // End of namespace Common
+
+#endif


Property changes on: residual/trunk/common/noncopyable.h
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Modified: residual/trunk/common/sys.h
===================================================================
--- residual/trunk/common/sys.h	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/common/sys.h	2008-03-10 23:06:07 UTC (rev 31101)
@@ -24,8 +24,6 @@
 #define COMMON_SYS_H
 
 
-typedef struct Mutex *MutexRef;
-
 #ifndef _MSC_VER
 #include <unistd.h>
 #endif

Deleted: residual/trunk/common/timer.cpp
===================================================================
--- residual/trunk/common/timer.cpp	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/common/timer.cpp	2008-03-10 23:06:07 UTC (rev 31101)
@@ -1,135 +0,0 @@
-/* Residual - Virtual machine to run LucasArts' 3D adventure games
- * Copyright (C) 2003-2006 The ScummVM-Residual Team (www.scummvm.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
-
- * This library 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
- * Lesser General Public License for more details.
-
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/sys.h"
-#include "common/platform.h"
-#include "common/debug.h"
-#include "common/timer.h"
-
-#include "engine/backend/driver.h"
-
-Timer *g_timer = NULL;
-
-Timer::Timer() :
-	_mutex(0),
-	_timerHandler(0),
-	_lastTime(0) {
-
-	_mutex = g_driver->createMutex();
-
-	g_timer = this;
-
-	for (int i = 0; i < MAX_TIMERS; i++) {
-		_timerSlots[i].procedure = NULL;
-		_timerSlots[i].interval = 0;
-		_timerSlots[i].counter = 0;
-	}
-
-	_thisTime = g_driver->getMillis();
-
-	// Set the timer last, after everything has been initialised
-	g_driver->setTimerCallback(timer_handler, 10);
-}
-
-Timer::~Timer() {
-	g_driver->setTimerCallback(NULL, 0);
-
-	{
-		StackLock lock(_mutex);
-		for (int i = 0; i < MAX_TIMERS; i++) {
-			_timerSlots[i].procedure = NULL;
-			_timerSlots[i].interval = 0;
-			_timerSlots[i].counter = 0;
-		}
-	}
-
-	g_driver->deleteMutex(_mutex);
-}
-
-int Timer::timer_handler(int t) {
-	if (g_timer)
-		return g_timer->handler(t);
-	return 0;
-}
-
-int Timer::handler(int t) {
-	StackLock lock(_mutex);
-	uint32 interval, l;
-
-	_lastTime = _thisTime;
-	_thisTime = g_driver->getMillis();
-	interval = 1000 * (_thisTime - _lastTime);
-
-	// If the timer has been frozen for a long time, don't
-	// call the procedures a silly number of times, just resynchronize
-	if(interval > 1000000) {
-		interval = 0;
-		warning("Timer skipped forward");
-	}
-
-	for (l = 0; l < MAX_TIMERS; l++) {
-		if (_timerSlots[l].procedure && _timerSlots[l].interval > 0) {
-			_timerSlots[l].counter -= interval;
-			while (_timerSlots[l].counter <= 0) {
-				// A small paranoia check which catches the case where
-				// a timer removes itself (which it never should do).
-				assert(_timerSlots[l].procedure && _timerSlots[l].interval > 0);
-				_timerSlots[l].counter += _timerSlots[l].interval;
-				_timerSlots[l].procedure(_timerSlots[l].refCon);
-			}
-		}
-	}
-
-	return t;
-}
-
-bool Timer::installTimerProc(TimerProc procedure, int32 interval, void *refCon) {
-	assert(interval > 0);
-	StackLock lock(_mutex);
-
-	for (int l = 0; l < MAX_TIMERS; l++) {
-		if (!_timerSlots[l].procedure) {
-			_timerSlots[l].procedure = procedure;
-			_timerSlots[l].interval = interval;
-			_timerSlots[l].counter = interval;
-			_timerSlots[l].refCon = refCon;
-			return true;
-		}
-	}
-
-	if (debugLevel == DEBUG_WARN || debugLevel == DEBUG_ALL)
-		warning("Couldn't find free timer slot!");
-	return false;
-}
-
-void Timer::removeTimerProc(TimerProc procedure) {
-	StackLock lock(_mutex);
-
-	for (int l = 0; l < MAX_TIMERS; l++) {
-		if (_timerSlots[l].procedure == procedure) {
-			_timerSlots[l].procedure = 0;
-			_timerSlots[l].interval = 0;
-			_timerSlots[l].counter = 0;
-			_timerSlots[l].refCon = 0;
-		}
-	}
-}

Modified: residual/trunk/common/timer.h
===================================================================
--- residual/trunk/common/timer.h	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/common/timer.h	2008-03-10 23:06:07 UTC (rev 31101)
@@ -1,19 +1,19 @@
 /* Residual - Virtual machine to run LucasArts' 3D adventure games
- * Copyright (C) 2003-2006 The ScummVM-Residual Team (www.scummvm.org)
+ * Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
  *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
+ * 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 library is distributed in the hope that it will be useful,
+ * 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
- * Lesser General Public License for more details.
+ * 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 Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ * 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.
  *
  * $URL$
  * $Id$
@@ -24,31 +24,16 @@
 #define COMMON_TIMER_H
 
 #include "common/sys.h"
-#include "common/platform.h"
+#include "common/noncopyable.h"
 
-#define MAX_TIMERS 3
+namespace Common {
 
-typedef void (*TimerProc)(void *refCon);
-
-class Timer {
-
-private:
-	MutexRef _mutex;
-	void *_timerHandler;
-	int32 _thisTime;
-	int32 _lastTime;
-
-	struct TimerSlots {
-		TimerProc procedure;
-		int32 interval;
-		int32 counter;
-		void *refCon;
-	} _timerSlots[MAX_TIMERS];
-
+class TimerManager : NonCopyable {
 public:
-	Timer();
-	~Timer();
+	typedef void (*TimerProc)(void *refCon);
 
+	virtual ~TimerManager() {}
+
 	/**
 	 * Install a new timer callback. It will from now be called every interval microseconds.
 	 * The timer may be invoked from a separate thread. Hence any timer code should be
@@ -61,19 +46,14 @@
 	 * @param refCon	an arbitrary void pointer; will be passed to the timer callback
 	 * @return	true if the timer was installed successfully, false otherwise
 	 */
-	bool installTimerProc(TimerProc proc, int32 interval, void *refCon);
+	virtual bool installTimerProc(TimerProc proc, int32 interval, void *refCon) = 0;
 
 	/**
 	 * Remove the given timer callback. It will not be invoked anymore.
 	 */
-	void removeTimerProc(TimerProc proc);
-
-protected:
-	static int timer_handler(int t);
-	int handler(int t);
+	virtual void removeTimerProc(TimerProc proc) = 0;
 };
 
-extern Timer *g_timer;
+} // End of namespace Common
 
 #endif
-

Modified: residual/trunk/dists/msvc9/residual.vcproj
===================================================================
--- residual/trunk/dists/msvc9/residual.vcproj	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/dists/msvc9/residual.vcproj	2008-03-10 23:06:07 UTC (rev 31101)
@@ -199,6 +199,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\..\common\frac.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\common\list.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\common\matrix3.cpp"
 				>
 			</File>
@@ -215,18 +223,26 @@
 				>
 			</File>
 			<File
-				RelativePath="..\..\common\platform.h"
+				RelativePath="..\..\common\mutex.cpp"
 				>
 			</File>
 			<File
-				RelativePath="..\..\common\sys.h"
+				RelativePath="..\..\common\mutex.h"
 				>
 			</File>
 			<File
-				RelativePath="..\..\common\timer.cpp"
+				RelativePath="..\..\common\noncopyable.h"
 				>
 			</File>
 			<File
+				RelativePath="..\..\common\platform.h"
+				>
+			</File>
+			<File
+				RelativePath="..\..\common\sys.h"
+				>
+			</File>
+			<File
 				RelativePath="..\..\common\timer.h"
 				>
 			</File>
@@ -782,9 +798,17 @@
 					>
 				</File>
 				<File
+					RelativePath="..\..\engine\imuse\imuse_tables.h"
+					>
+				</File>
+				<File
 					RelativePath="..\..\engine\imuse\imuse_track.cpp"
 					>
 				</File>
+				<File
+					RelativePath="..\..\engine\imuse\imuse_track.h"
+					>
+				</File>
 			</Filter>
 			<Filter
 				Name="smush"
@@ -814,6 +838,14 @@
 				Name="backend"
 				>
 				<File
+					RelativePath="..\..\engine\backend\default-timer.cpp"
+					>
+				</File>
+				<File
+					RelativePath="..\..\engine\backend\default-timer.h"
+					>
+				</File>
+				<File
 					RelativePath="..\..\engine\backend\driver.h"
 					>
 				</File>

Added: residual/trunk/engine/backend/default-timer.cpp
===================================================================
--- residual/trunk/engine/backend/default-timer.cpp	                        (rev 0)
+++ residual/trunk/engine/backend/default-timer.cpp	2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,144 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/sys.h"
+
+#include "engine/backend/driver.h"
+#include "engine/backend/default-timer.h"
+
+struct TimerSlot {
+	Common::TimerManager::TimerProc callback;
+	void *refCon;
+	uint32 interval;	// in microseconds
+
+	uint32 nextFireTime;	// in milliseconds
+	uint32 nextFireTimeMicro;	// mircoseconds part of nextFire
+
+	TimerSlot *next;
+};
+
+void insertPrioQueue(TimerSlot *head, TimerSlot *newSlot) {
+	// The head points to a fake anchor TimerSlot; this common
+	// trick allows us to get rid of many special cases.
+
+	const uint32 nextFireTime = newSlot->nextFireTime;
+	TimerSlot *slot = head;
+	newSlot->next = 0;
+
+	// Insert the new slot into the sorted list of already scheduled
+	// timers in such a way that the list stays sorted...
+	while (true) {
+		assert(slot);
+		if (slot->next == 0 || nextFireTime < slot->next->nextFireTime) {
+			newSlot->next = slot->next;
+			slot->next = newSlot;
+			return;
+		}
+		slot = slot->next;
+	}
+}
+
+
+DefaultTimerManager::DefaultTimerManager() :
+	_timerHandler(0),
+	_head(0) {
+
+	_head = new TimerSlot();
+	memset(_head, 0, sizeof(TimerSlot));
+}
+
+DefaultTimerManager::~DefaultTimerManager() {
+	Common::StackLock lock(_mutex);
+
+	TimerSlot *slot = _head;
+	while (slot) {
+		TimerSlot *next = slot->next;
+		delete slot;
+		slot = next;
+	}
+	_head = 0;
+}
+
+void DefaultTimerManager::handler() {
+	Common::StackLock lock(_mutex);
+
+	const uint32 curTime = g_driver->getMillis();
+
+	// Repeat as long as there is a TimerSlot that is scheduled to fire.
+	TimerSlot *slot = _head->next;
+	while (slot && slot->nextFireTime < curTime) {
+		// Remove the slot from the priority queue
+		_head->next = slot->next;
+
+		// Update the fire time and reinsert the TimerSlot into the priority
+		// queue. Has to be done before the timer callback is invoked, in case
+		// the callback wants to remove itself.
+		assert(slot->interval > 0);
+		slot->nextFireTime += (slot->interval / 1000);
+		slot->nextFireTimeMicro += (slot->interval % 1000);
+		if (slot->nextFireTimeMicro > 1000) {
+			slot->nextFireTime += slot->nextFireTimeMicro / 1000;
+			slot->nextFireTimeMicro %= 1000;
+		}
+		insertPrioQueue(_head, slot);
+
+		// Invoke the timer callback
+		assert(slot->callback);
+		slot->callback(slot->refCon);
+
+		// Look at the next scheduled timer
+		slot = _head->next;
+	}
+}
+
+bool DefaultTimerManager::installTimerProc(TimerProc callback, int32 interval, void *refCon) {
+	assert(interval > 0);
+	Common::StackLock lock(_mutex);
+
+	TimerSlot *slot = new TimerSlot;
+	slot->callback = callback;
+	slot->refCon = refCon;
+	slot->interval = interval;
+	slot->nextFireTime = g_driver->getMillis() + interval / 1000;
+	slot->nextFireTimeMicro = interval % 1000;
+	slot->next = 0;
+
+	insertPrioQueue(_head, slot);
+
+	return true;
+}
+
+void DefaultTimerManager::removeTimerProc(TimerProc callback) {
+	Common::StackLock lock(_mutex);
+
+	TimerSlot *slot = _head;
+
+	while (slot->next) {
+		if (slot->next->callback == callback) {
+			TimerSlot *next = slot->next->next;
+			delete slot->next;
+			slot->next = next;
+		} else {
+			slot = slot->next;
+		}
+	}
+}


Property changes on: residual/trunk/engine/backend/default-timer.cpp
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Added: residual/trunk/engine/backend/default-timer.h
===================================================================
--- residual/trunk/engine/backend/default-timer.h	                        (rev 0)
+++ residual/trunk/engine/backend/default-timer.h	2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,48 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef BACKENDS_TIMER_DEFAULT_H
+#define BACKENDS_TIMER_DEFAULT_H
+
+#include "common/timer.h"
+#include "common/mutex.h"
+
+struct TimerSlot;
+	
+class DefaultTimerManager : public Common::TimerManager {
+private:
+	Common::Mutex _mutex;
+	void *_timerHandler;
+	TimerSlot *_head;
+	
+
+public:
+	DefaultTimerManager();
+	~DefaultTimerManager();
+	bool installTimerProc(TimerProc proc, int32 interval, void *refCon);
+	void removeTimerProc(TimerProc proc);
+
+	// Timer callback, to be invoked at regular time intervals by the backend.
+	void handler();
+};
+
+#endif


Property changes on: residual/trunk/engine/backend/default-timer.h
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Modified: residual/trunk/engine/backend/driver.h
===================================================================
--- residual/trunk/engine/backend/driver.h	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/backend/driver.h	2008-03-10 23:06:07 UTC (rev 31101)
@@ -25,6 +25,7 @@
 
 #include "common/platform.h"
 #include "common/vector3d.h"
+#include "common/mutex.h"
 
 #include "engine/color.h"
 #include "engine/model.h"
@@ -33,10 +34,16 @@
 #include "engine/font.h"
 #include "engine/primitives.h"
 #include "engine/actor.h"
+#include "engine/backend/default-timer.h"
 
 class Material;
 class Bitmap;
+class Timer;
 
+namespace Audio {
+	class Mixer;
+}
+
 class Driver {
 public:
 	Driver() { ; }
@@ -116,7 +123,7 @@
 	/** @name Events and Time */
 	//@{
 
-	typedef int (*TimerProc)(int interval);
+	typedef unsigned int (*TimerProc)(unsigned int interval, void *param);
 
 	/**
 	 * The types of events backends may generate.
@@ -239,25 +246,22 @@
 	 * @param interval	the interval (in milliseconds) between invocations
 	 *                  of the callback
 	 */
-	virtual void setTimerCallback(TimerProc callback, int interval) = 0;
+	virtual void setTimerCallback() = 0;
 
+	virtual void clearTimerCallback() = 0;
+
 	//@}
 
 	/**
 	 * @name Mutex handling
-	 * Historically, the OSystem API used to have a method which allowed
-	 * creating threads. Hence mutex support was needed for thread syncing.
-	 * To ease portability, though, we decided to remove the threading API.
-	 * Instead, we now use timers (see setTimerCallback() and Timer).
-	 * But since those may be implemented using threads (and in fact, that's
-	 * how our primary backend, the SDL one, does it on many systems), we
-	 * still have to do mutex syncing in our timer callbacks.
 	 *
 	 * Hence backends which do not use threads to implement the timers simply
 	 * can use dummy implementations for these methods.
 	 */
 	//@{
 
+	typedef Common::MutexRef	MutexRef;
+
 	/**
 	 * Create a new mutex.
 	 * @return the newly created mutex, or 0 if an error occured.
@@ -266,6 +270,12 @@
 
 	/**
 	 * Lock the given mutex.
+	 *
+	 * @note Code assumes that the mutex implementation supports
+	 * recursive locking. That is, a thread may lock a mutex twice w/o
+	 * deadlocking. In case of a multilock, the mutex has to be unlocked
+	 * as many times as it was locked befored it really becomes unlocked.
+	 *
 	 * @param mutex	the mutex to lock.
 	 */
 	virtual void lockMutex(MutexRef mutex) = 0;
@@ -329,16 +339,7 @@
 };
 
 extern Driver *g_driver;
+extern DefaultTimerManager *g_timer;
+extern Audio::Mixer *g_mixer;
 
-class StackLock {
-	MutexRef _mutex;
-public:
-	StackLock(MutexRef mutex) : _mutex(mutex) {
-		g_driver->lockMutex(_mutex);
-	}
-	~StackLock() {
-		g_driver->unlockMutex(_mutex);
-	}
-};
-
 #endif

Modified: residual/trunk/engine/backend/sdl/driver_sdl.cpp
===================================================================
--- residual/trunk/engine/backend/sdl/driver_sdl.cpp	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/backend/sdl/driver_sdl.cpp	2008-03-10 23:06:07 UTC (rev 31101)
@@ -359,11 +359,22 @@
 	SDL_Delay(msecs);
 }
 
-void DriverSDL::setTimerCallback(TimerProc callback, int timer) {
-	SDL_SetTimer(timer, (SDL_TimerCallback) callback);
+static SDL_TimerID _timerID = NULL;
+
+static Uint32 timer_handler(Uint32 interval, void *param) {
+	((DefaultTimerManager *)param)->handler();
+	return interval;
 }
 
-MutexRef DriverSDL::createMutex() {
+void DriverSDL::setTimerCallback() {
+	_timerID = SDL_AddTimer(10, &timer_handler, g_timer);
+}
+
+void DriverSDL::clearTimerCallback() {
+	SDL_RemoveTimer(_timerID);
+}
+
+Common::MutexRef DriverSDL::createMutex() {
 	return (MutexRef)SDL_CreateMutex();
 }
 
@@ -382,12 +393,20 @@
 bool DriverSDL::setSoundCallback(SoundProc proc, void *param) {
 	SDL_AudioSpec desired;
 
+	// Determine the sample buffer size. We want it to store enough data for
+	// about 1/10th of a second. Note that it must be a power of two.
+	// So e.g. at 22050 Hz, we request a sample buffer size of 2048.
+	int samples = 0x8000;
+	while (10 * samples >= _samplesPerSec) {
+		samples >>= 1;
+	}
+
 	memset(&desired, 0, sizeof(desired));
 
 	desired.freq = _samplesPerSec;
 	desired.format = AUDIO_S16SYS;
 	desired.channels = 2;
-	desired.samples = 2048;
+	desired.samples = (uint16)samples;
 	desired.callback = proc;
 	desired.userdata = param;
 

Modified: residual/trunk/engine/backend/sdl/driver_sdl.h
===================================================================
--- residual/trunk/engine/backend/sdl/driver_sdl.h	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/backend/sdl/driver_sdl.h	2008-03-10 23:06:07 UTC (rev 31101)
@@ -52,7 +52,8 @@
 	bool pollEvent(Event &event);
 	uint32 getMillis();
 	void delayMillis(uint msecs);
-	void setTimerCallback(TimerProc callback, int interval);
+	void setTimerCallback();
+	void clearTimerCallback();
 
 	MutexRef createMutex();
 	void lockMutex(MutexRef mutex);

Modified: residual/trunk/engine/font.cpp
===================================================================
--- residual/trunk/engine/font.cpp	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/font.cpp	2008-03-10 23:06:07 UTC (rev 31101)
@@ -42,7 +42,7 @@
 	data += 32;
 
 	// Read character indexes - are the key/value reversed?
-	_charIndex = (uint16 *)malloc(sizeof(_charIndex) * _numChars);
+	_charIndex = new uint16[_numChars];
 	if (!_charIndex)
 		error("Could not load font %s. Out of memory\n", filename);
 	for (uint i = 0; i < _numChars; ++i) {
@@ -52,7 +52,7 @@
 	data += _numChars * 2;
 
 	// Read character headers
-	_charHeaders = (CharHeader *)malloc(sizeof(CharHeader) * _numChars);
+	_charHeaders = new CharHeader[_numChars];
 	if (!_charHeaders)
 		error("Could not load font %s. Out of memory\n", filename);
 	for (uint i = 0; i < _numChars; ++i) {
@@ -65,7 +65,7 @@
 		data += 16;
 	}
 	// Read font data
-	_fontData = (byte *)malloc(_dataSize);
+	_fontData = new byte[_dataSize];
 	if (!_fontData)
 		error("Could not load font %s. Out of memory\n", filename);
 
@@ -73,9 +73,9 @@
 }
 
 Font::~Font() {
-	free(_charIndex);
-	free(_charHeaders);
-	free(_fontData);
+	delete[] _charIndex;
+	delete[] _charHeaders;
+	delete[] _fontData;
 }
 
 uint16 Font::getCharIndex(unsigned char c) {

Modified: residual/trunk/engine/imuse/imuse.cpp
===================================================================
--- residual/trunk/engine/imuse/imuse.cpp	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/imuse/imuse.cpp	2008-03-10 23:06:07 UTC (rev 31101)
@@ -24,6 +24,7 @@
 #include "common/platform.h"
 #include "common/debug.h"
 #include "common/timer.h"
+#include "common/mutex.h"
 
 #include "engine/engine.h"
 #include "engine/savegame.h"
@@ -42,26 +43,20 @@
 extern ImuseTable grimDemoStateMusicTable[];
 extern ImuseTable grimDemoSeqMusicTable[];
 
-Imuse::Track::Track()
-	: used(false), stream(NULL) {
-}
-
 void Imuse::timerHandler(void *refCon) {
 	Imuse *imuse = (Imuse *)refCon;
 	imuse->callback();
 }
 
 Imuse::Imuse(int fps) {
-	_mutex = g_driver->createMutex();
 	_pause = false;
 	_sound = new ImuseSndMgr();
-	_volVoice = 0;
-	_volSfx = 0;
-	_volMusic = 0;
+	assert(_sound);
 	_callbackFps = fps;
 	resetState();
 	for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
 		_track[l] = new Track;
+		assert(_track[l]);
 		_track[l]->trackId = l;
 		_track[l]->used = false;
 		strcpy(_track[l]->soundName, "");
@@ -73,13 +68,12 @@
 }
 
 Imuse::~Imuse() {
-	stopAllSounds();
 	g_timer->removeTimerProc(timerHandler);
+	stopAllSounds();
 	for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
 		delete _track[l];
 	}
 	delete _sound;
-	g_driver->deleteMutex(_mutex);
 }
 
 void Imuse::resetState() {
@@ -89,19 +83,18 @@
 }
 
 void Imuse::restoreState(SaveGame *savedState) {
-	StackLock lock(_mutex);
+	Common::StackLock lock(_mutex);
 	printf("Imuse::restoreState() started.\n");
 
 	savedState->beginSection('IMUS');
-	savedState->read(&_volVoice, sizeof(int32));
-	savedState->read(&_volSfx, sizeof(int32));
-	savedState->read(&_volMusic, sizeof(int32));
 	savedState->read(&_curMusicState, sizeof(int32));
 	savedState->read(&_curMusicSeq, sizeof(int32));
 	savedState->read(_attributes, sizeof(int32) * 185);
 
 	for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
 		Track *track = _track[l];
+		memset(track, 0, sizeof(Track));
+		track->trackId = l;
 		savedState->read(&track->pan, sizeof(int32));
 		savedState->read(&track->panFadeDest, sizeof(int32));
 		savedState->read(&track->panFadeDelay, sizeof(int32));
@@ -113,50 +106,51 @@
 		savedState->read(track->soundName, 32);
 		savedState->read(&track->used, sizeof(bool));
 		savedState->read(&track->toBeRemoved, sizeof(bool));
-		savedState->read(&track->readyToRemove, sizeof(bool));
-		savedState->read(&track->started, sizeof(bool));
 		savedState->read(&track->priority, sizeof(int32));
 		savedState->read(&track->regionOffset, sizeof(int32));
 		savedState->read(&track->dataOffset, sizeof(int32));
 		savedState->read(&track->curRegion, sizeof(int32));
 		savedState->read(&track->curHookId, sizeof(int32));
 		savedState->read(&track->volGroupId, sizeof(int32));
-		savedState->read(&track->iteration, sizeof(int32));
+		savedState->read(&track->feedSize, sizeof(int32));
 		savedState->read(&track->mixerFlags, sizeof(int32));
-		savedState->read(&track->mixerVol, sizeof(int32));
-		savedState->read(&track->mixerPan, sizeof(int32));
 
 		if (!track->used)
 			continue;
 
-		track->readyToRemove = false;
-		if (track->toBeRemoved) {
-			track->stream = NULL;
+		if (track->toBeRemoved || track->curRegion == -1) {
 			track->used = false;
 			continue;
 		}
 
-		track->soundHandle = _sound->openSound(track->soundName, track->volGroupId);
-		assert(track->soundHandle);
+		track->soundDesc = _sound->openSound(track->soundName, track->volGroupId);
+		if (!track->soundDesc) {
+			warning("Imuse::restoreState: Can't open sound so will not be resumed");
+			track->used = false;
+			continue;
+		}
 
-		int32 streamBufferSize = track->iteration;
-		int	freq = _sound->getFreq(track->soundHandle);
+		int channels = _sound->getChannels(track->soundDesc);
+		int freq = _sound->getFreq(track->soundDesc);
+		track->mixerFlags = kFlag16Bits;
+		if (channels == 2)
+			track->mixerFlags |= kFlagStereo | kFlagReverseStereo;
 
-		track->stream = makeAppendableAudioStream(freq, track->mixerFlags, streamBufferSize);
-		g_mixer->playInputStream(&track->handle, track->stream, false, -1, track->mixerVol, track->mixerPan, false);
+		track->stream = Audio::makeAppendableAudioStream(freq,  makeMixerFlags(track->mixerFlags));
+		g_mixer->playInputStream(track->getType(), &track->handle, track->stream, -1, track->getVol(), track->getPan());
+		g_mixer->pauseHandle(track->handle, true);
 	}
 	savedState->endSection();
+	g_mixer->pauseAll(false);
+
 	printf("Imuse::restoreState() finished.\n");
 }
 
 void Imuse::saveState(SaveGame *savedState) {
-	StackLock lock(_mutex);
+	Common::StackLock lock(_mutex);
 	printf("Imuse::saveState() started.\n");
 
 	savedState->beginSection('IMUS');
-	savedState->write(&_volVoice, sizeof(int32));
-	savedState->write(&_volSfx, sizeof(int32));
-	savedState->write(&_volMusic, sizeof(int32));
 	savedState->write(&_curMusicState, sizeof(int32));
 	savedState->write(&_curMusicSeq, sizeof(int32));
 	savedState->write(_attributes, sizeof(int32) * 185);
@@ -174,31 +168,43 @@
 		savedState->write(track->soundName, 32);
 		savedState->write(&track->used, sizeof(bool));
 		savedState->write(&track->toBeRemoved, sizeof(bool));
-		savedState->write(&track->readyToRemove, sizeof(bool));
-		savedState->write(&track->started, sizeof(bool));
 		savedState->write(&track->priority, sizeof(int32));
 		savedState->write(&track->regionOffset, sizeof(int32));
 		savedState->write(&track->dataOffset, sizeof(int32));
 		savedState->write(&track->curRegion, sizeof(int32));
 		savedState->write(&track->curHookId, sizeof(int32));
 		savedState->write(&track->volGroupId, sizeof(int32));
-		savedState->write(&track->iteration, sizeof(int32));
+		savedState->write(&track->feedSize, sizeof(int32));
 		savedState->write(&track->mixerFlags, sizeof(int32));
-		savedState->write(&track->mixerVol, sizeof(int32));
-		savedState->write(&track->mixerPan, sizeof(int32));
 	}
 	savedState->endSection();
 	printf("Imuse::saveState() finished.\n");
 }
 
+int32 Imuse::makeMixerFlags(int32 flags) {
+	int32 mixerFlags = 0;
+	if (flags & kFlag16Bits)
+		mixerFlags |= Audio::Mixer::FLAG_16BITS;
+	if (flags & kFlagLittleEndian)
+		mixerFlags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;
+	if (flags & kFlagStereo)
+		mixerFlags |= Audio::Mixer::FLAG_STEREO;
+	if (flags & kFlagReverseStereo)
+		mixerFlags |= Audio::Mixer::FLAG_REVERSE_STEREO;
+	return mixerFlags;
+}
+
 void Imuse::callback() {
-	StackLock lock(_mutex);
+	Common::StackLock lock(_mutex);
 
 	for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
 		Track *track = _track[l];
-		if (track->used && !track->readyToRemove) {
-			if (track->toBeRemoved) {
-				track->readyToRemove = true;
+		if (track->used) {
+			// Ignore tracks which are about to finish. Also, if it did finish in the meantime,
+			// mark it as unused.
+			if (!track->stream) {
+				if (!g_mixer->isSoundHandleActive(track->handle))
+					memset(track, 0, sizeof(Track));
 				continue;
 			}
 
@@ -209,17 +215,21 @@
 				if (track->volFadeStep < 0) {
 					if (track->vol > track->volFadeDest) {
 						track->vol += track->volFadeStep;
+						//warning("fade: %d", track->vol);
 						if (track->vol < track->volFadeDest) {
 							track->vol = track->volFadeDest;
 							track->volFadeUsed = false;
 						}
 						if (track->vol == 0) {
-							track->toBeRemoved = true;
+							// Fade out complete -> remove this track
+							flushTrack(track);
+							continue;
 						}
 					}
 				} else if (track->volFadeStep > 0) {
 					if (track->vol < track->volFadeDest) {
 						track->vol += track->volFadeStep;
+						//warning("fade: %d", track->vol);
 						if (track->vol > track->volFadeDest) {
 							track->vol = track->volFadeDest;
 							track->volFadeUsed = false;
@@ -248,74 +258,60 @@
 				}
 			}
 
-			int pan = track->pan / 1000;
-			pan = (pan != 64) ? 2 * pan - 127 : 0;
-			int vol = track->vol / 1000;
+			assert(track->stream);
+			byte *data = NULL;
+			int32 result = 0;
 
-			if (track->volGroupId == 1)
-				vol = (vol * _volVoice) / 128;
-			if (track->volGroupId == 2)
-				vol = (vol * _volSfx) / 128;
-			if (track->volGroupId == 3)
-				vol = (vol * _volMusic) / 128;
+			if (track->curRegion == -1) {
+				switchToNextRegion(track);
+				if (!track->stream)	// Seems we reached the end of the stream
+					continue;
+			}
 
-			track->mixerVol = vol;
-			track->mixerPan = pan;
+			int channels = _sound->getChannels(track->soundDesc);
+			int32 mixer_size = track->feedSize / _callbackFps;
 
-			if (track->stream) {
-				byte *data = NULL;
-				int32 result = 0;
+			if (track->stream->endOfData()) {
+				mixer_size *= 2;
+			}
 
-				if (track->curRegion == -1) {
-					switchToNextRegion(track);
-					if (track->toBeRemoved)
-						continue;
-				}
+			if (channels == 1)
+				mixer_size &= ~1;
+			if (channels == 2)
+				mixer_size &= ~3;
 
-				int channels = _sound->getChannels(track->soundHandle);
+			if (mixer_size == 0)
+				continue;
 
-				int32 mixer_size = track->iteration / _callbackFps;
-
-				if (track->stream->endOfData()) {
-					mixer_size *= 2;
+			do {
+				result = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &data, track->regionOffset, mixer_size);
+				if (channels == 1) {
+					result &= ~1;
 				}
+				if (channels == 2) {
+					result &= ~3;
+				}
 
-				if (channels == 1)
-					mixer_size &= ~1;
-				if (channels == 2)
-					mixer_size &= ~3;
+				if (result > mixer_size)
+					result = mixer_size;
 
-				if (mixer_size == 0)
-					continue;
+				if (g_mixer->isReady()) {
+					track->stream->queueBuffer(data, result);
+					track->regionOffset += result;
+				} else
+					delete[] data;
 
-				do {
-					result = _sound->getDataFromRegion(track->soundHandle, track->curRegion, &data, track->regionOffset, mixer_size);
-					if (channels == 1) {
-						result &= ~1;
-					}
-					if (channels == 2) {
-						result &= ~3;
-					}
-
-					if (result > mixer_size)
-						result = mixer_size;
-
-					if (g_mixer->isReady()) {
-						g_mixer->setChannelVolume(track->handle, vol);
-						g_mixer->setChannelBalance(track->handle, pan);
-						track->stream->append(data, result);
-						track->regionOffset += result;
-						free(data);
-					}
-
-					if (_sound->isEndOfRegion(track->soundHandle, track->curRegion)) {
-						switchToNextRegion(track);
-						if (track->toBeRemoved)
-							break;
-					}
-					mixer_size -= result;
-					assert(mixer_size >= 0);
-				} while (mixer_size != 0);
+				if (_sound->isEndOfRegion(track->soundDesc, track->curRegion)) {
+					switchToNextRegion(track);
+					if (!track->stream)
+						break;
+				}
+				mixer_size -= result;
+				assert(mixer_size >= 0);
+			} while (mixer_size);
+			if (g_mixer->isReady()) {
+				g_mixer->setChannelVolume(track->handle, track->getVol());
+				g_mixer->setChannelBalance(track->handle, track->getPan());
 			}
 		}
 	}
@@ -325,51 +321,51 @@
 	assert(track);
 
 	if (track->trackId >= MAX_IMUSE_TRACKS) {
-		track->toBeRemoved = true;
+		if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+			printf("Imuse::switchToNextRegion(): fadeTrack end: soundName:%s\n", track->soundName);
+		flushTrack(track);
 		return;
 	}
 
-	int numRegions = _sound->getNumRegions(track->soundHandle);
+	int numRegions = _sound->getNumRegions(track->soundDesc);
 
 	if (++track->curRegion == numRegions) {
-		track->toBeRemoved = true;
+		if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+			printf("Imuse::switchToNextRegion(): end of tracks: soundName:%s\n", track->soundName);
+		flushTrack(track);
 		return;
 	}
 
-	ImuseSndMgr::SoundStruct *soundHandle = track->soundHandle;
-	int jumpId = _sound->getJumpIdByRegionAndHookId(soundHandle, track->curRegion, track->curHookId);
+	ImuseSndMgr::SoundDesc *soundDesc = track->soundDesc;
+	int jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, track->curHookId);
 	if (jumpId == -1)
-		jumpId = _sound->getJumpIdByRegionAndHookId(soundHandle, track->curRegion, 0);
+		jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, 0);
 	if (jumpId != -1) {
-		int region = _sound->getRegionIdByJumpId(soundHandle, jumpId);
+		if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+			printf("Imuse::switchToNextRegion(): JUMP: soundName:%s\n", track->soundName);
+		int region = _sound->getRegionIdByJumpId(soundDesc, jumpId);
 		assert(region != -1);
-		int sampleHookId = _sound->getJumpHookId(soundHandle, jumpId);
+		int sampleHookId = _sound->getJumpHookId(soundDesc, jumpId);
 		assert(sampleHookId != -1);
-		int fadeDelay = (60 * _sound->getJumpFade(soundHandle, jumpId)) / 1000;
-		if (sampleHookId != 0) {
-			if (track->curHookId == sampleHookId) {
-				if (fadeDelay != 0) {
-					Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);
-					fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundHandle, fadeTrack->curRegion);
-					fadeTrack->regionOffset = 0;
-					fadeTrack->curHookId = 0;
-				}
-				track->curRegion = region;
-				track->curHookId = 0;
-			}
-		} else {
-			if (fadeDelay != 0) {
-				Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);
-				fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundHandle, fadeTrack->curRegion);
+		int fadeDelay = (60 * _sound->getJumpFade(soundDesc, jumpId)) / 1000;
+		if (fadeDelay) {
+			Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);
+			if (fadeTrack) {
+				fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundDesc, fadeTrack->curRegion);
 				fadeTrack->regionOffset = 0;
+				fadeTrack->curHookId = 0;
 			}
-			track->curRegion = region;
-			if (track->curHookId == 0x80) {
-				track->curHookId = 0;
-			}
 		}
+		track->curRegion = region;
+		if (track->curHookId == sampleHookId)
+			track->curHookId = 0;
+		else
+			if (track->curHookId == 0x80)
+				track->curHookId = 0;
 	}
 
-	track->dataOffset = _sound->getRegionOffset(soundHandle, track->curRegion);
+	if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+		printf("Imuse::switchToNextRegion(): REGION %d: soundName:%s\n", track->curRegion, track->soundName);
+	track->dataOffset = _sound->getRegionOffset(soundDesc, track->curRegion);
 	track->regionOffset = 0;
 }

Modified: residual/trunk/engine/imuse/imuse.h
===================================================================
--- residual/trunk/engine/imuse/imuse.h	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/imuse/imuse.h	2008-03-10 23:06:07 UTC (rev 31101)
@@ -34,21 +34,12 @@
 
 #include "engine/imuse/imuse_sndmgr.h"
 #include "engine/imuse/imuse_mcmp_mgr.h"
+#include "engine/imuse/imuse_track.h"
+#include "engine/imuse/imuse_tables.h"
 
 #define MAX_IMUSE_TRACKS 16
 #define MAX_IMUSE_FADETRACKS 16
 
-struct ImuseTable {
-	byte opcode;
-	int16 soundId;
-	byte atribPos;
-	byte hookId;
-	int16 fadeOut60TicksDelay;
-	byte volume;
-	byte pan;
-	char filename[32];
-};
-
 class SaveGame;
 
 class Imuse {
@@ -56,52 +47,11 @@
 
 	int _callbackFps;
 
-	struct Track {
-		int trackId;
-
-		int32 pan;
-		int32 panFadeDest;
-		int32 panFadeStep;
-		int32 panFadeDelay;
-		bool panFadeUsed;
-		int32 vol;
-		int32 volFadeDest;
-		int32 volFadeStep;
-		int32 volFadeDelay;
-		bool volFadeUsed;
-
-		char soundName[32];
-		bool used;
-		bool toBeRemoved;
-		bool readyToRemove;
-		bool started;
-		int32 priority;
-		int32 regionOffset;
-		int32 dataOffset;
-		int32 curRegion;
-		int32 curHookId;
-		int32 volGroupId;
-		int32 iteration;
-		int32 mixerFlags;
-		int32 mixerVol;
-		int32 mixerPan;
-
-		ImuseSndMgr::SoundStruct *soundHandle;
-		PlayingSoundHandle handle;
-		AppendableAudioStream *stream;
-
-		Track();
-	};
-
 	Track *_track[MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS];
 
-	MutexRef _mutex;
+	Common::Mutex _mutex;
 	ImuseSndMgr *_sound;
 
-	int32 _volVoice;
-	int32 _volSfx;
-	int32 _volMusic;
-
 	bool _pause;
 
 	int32 _attributes[185];
@@ -111,6 +61,7 @@
 	const ImuseTable *_stateMusicTable;
 	const ImuseTable *_seqMusicTable;
 
+	int32 makeMixerFlags(int32 flags);
 	static void timerHandler(void *refConf);
 	void callback();
 	void switchToNextRegion(Track *track);
@@ -118,30 +69,27 @@
 	void selectVolumeGroup(const char *soundName, int volGroupId);
 
 	void fadeOutMusic(int fadeDelay);
+	void fadeOutMusicAndStartNew(int fadeDelay, const char *filename, int hookId, int vol, int pan);
 	Track *cloneToFadeOutTrack(Track *track, int fadeDelay);
 
 	void playMusic(const ImuseTable *table, int atribPos, bool sequence);
 
+	void flushTrack(Track *track);
+
 public:
 	Imuse(int fps);
 	~Imuse();
 
-	bool startSound(const char *soundName, int volGroupId, int hookId, int volume, int pan, int priority);
+	bool startSound(const char *soundName, int volGroupId, int hookId, int volume, int pan, int priority, Track *otherTrack);
 	void startVoice(const char *soundName, int volume = 127, int pan = 64);
 	void startMusic(const char *soundName, int hookId, int volume, int pan);
+	void startMusicWithOtherPos(const char *soundName, int hookId, int volume, int pan, Track *otherTrack);
 	void startSfx(const char *soundName, int priority = 127);
 
 	void restoreState(SaveGame *savedState);
 	void saveState(SaveGame *savedState);
 	void resetState();
 
-	void setGroupVoiceVolume(int volume) { _volVoice = volume; }
-	void setGroupSfxVolume(int volume) { _volSfx = volume; }
-	void setGroupMusicVolume(int volume) { _volMusic = volume; }
-	int getGroupVoiceVolume() { return _volVoice; }
-	int getGroupSfxVolume() { return _volSfx; }
-	int getGroupMusicVolume() { return _volMusic; }
-
 	Track *findTrack(const char *soundName);
 	void setPriority(const char *soundName, int priority);
 	void setVolume(const char *soundName, int volume);
@@ -160,6 +108,8 @@
 	void flushTracks();
 	bool isVoicePlaying();
 	char *getCurMusicSoundName();
+	int getCurMusicPan();
+	int getCurMusicVol();
 	bool getSoundStatus(const char *soundName);
 	int32 getPosIn60HzTicks(const char *soundName);
 };

Modified: residual/trunk/engine/imuse/imuse_mcmp_mgr.cpp
===================================================================
--- residual/trunk/engine/imuse/imuse_mcmp_mgr.cpp	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/imuse/imuse_mcmp_mgr.cpp	2008-03-10 23:06:07 UTC (rev 31101)
@@ -45,10 +45,8 @@
 McmpMgr::~McmpMgr() {
 	if (_file)
 		fclose(_file);
-	if (_compTable)
-		free(_compTable);
-	if (_compInput)
-		free(_compInput);
+	delete[] _compTable;
+	delete[] _compInput;
 }
 
 bool McmpMgr::openSound(const char *filename, byte **resPtr, int &offsetData) {
@@ -72,7 +70,7 @@
 
 	int offset = ftell(_file) + (_numCompItems * 9) + 2;
 	_numCompItems--;
-	_compTable = (CompTable *)malloc(sizeof(CompTable) * _numCompItems);
+	_compTable = new CompTable[_numCompItems];
 	fseek(_file, 5, SEEK_CUR);
 	fread(&_compTable[0].decompSize, 1, 4, _file);
 	int headerSize = _compTable[0].decompSize = READ_BE_UINT32(&_compTable[0].decompSize);
@@ -98,7 +96,7 @@
 		_compTable[i].offset += sizeCodecs;
 	}
 	fseek(_file, sizeCodecs, SEEK_CUR);
-	_compInput = (byte *)malloc(maxSize);
+	_compInput = new byte[maxSize];
 	fread(_compInput, 1, headerSize, _file);
 	*resPtr = _compInput;
 	offsetData = headerSize;
@@ -123,7 +121,7 @@
 		last_block = _numCompItems - 1;
 
 	int32 blocks_final_size = 0x2000 * (1 + last_block - first_block);
-	*comp_final = (byte *)malloc(blocks_final_size);
+	*comp_final = new byte[blocks_final_size];
 	final_size = 0;
 
 	for (i = first_block; i <= last_block; i++) {

Modified: residual/trunk/engine/imuse/imuse_music.cpp
===================================================================
--- residual/trunk/engine/imuse/imuse_music.cpp	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/imuse/imuse_music.cpp	2008-03-10 23:06:07 UTC (rev 31101)
@@ -40,10 +40,13 @@
 	}
 	assert(num != -1);
 
+	if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+		printf("Imuse::setMusicState(): SoundId %d, filename: %s\n", _stateMusicTable[l].soundId, _stateMusicTable[l].filename);
+
 	if (_curMusicState == num)
 		return;
 
-	if (_curMusicSeq == 0) {
+	if (!_curMusicSeq) {
 		playMusic(&_stateMusicTable[num], num, false);
 	}
 
@@ -68,10 +71,13 @@
 
 	assert(num != -1);
 
+	if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+		printf("Imuse::setMusicSequence(): SoundId %d, filename: %s\n", _seqMusicTable[l].soundId, _seqMusicTable[l].filename);
+
 	if (_curMusicSeq == num)
 		return _seqMusicTable[_curMusicSeq].soundId;
 
-	if (num != 0) {
+	if (num) {
 		playMusic(&_seqMusicTable[num], 0, true);
 	} else {
 		playMusic(&_stateMusicTable[_curMusicState], _curMusicState, true);
@@ -85,12 +91,12 @@
 void Imuse::playMusic(const ImuseTable *table, int atribPos, bool sequence) {
 	int hookId = 0;
 
-	if (atribPos != 0) {
-		if (table->atribPos != 0)
+	if (atribPos) {
+		if (table->atribPos)
 			atribPos = table->atribPos;
 		hookId = _attributes[atribPos];
-		if (table->hookId != 0) {
-			if ((hookId == 0) && (table->hookId > 1)) {
+		if (table->hookId) {
+			if (hookId && table->hookId > 1) {
 				_attributes[atribPos] = 2;
 			} else {
 				_attributes[atribPos] = hookId + 1;
@@ -104,27 +110,51 @@
 
 	if (table->opcode == 0) {
 		fadeOutMusic(120);
-	} else if ((table->opcode == 2) || (table->opcode == 3)) {
+		return;
+	}
+
+	if (table->opcode == 2 || table->opcode == 3) {
 		if (table->filename[0] == 0) {
 			fadeOutMusic(60);
-		} else {
-			char *soundName = getCurMusicSoundName();
-			int pan;
+			return;
+		}
+		char *soundName = getCurMusicSoundName();
+		int pan;
 			
-			if (table->pan == 0)
-				pan = 64;
-			else
-				pan = table->pan;
-			if (soundName != NULL && (table->opcode == 3) && (!sequence)
-			 && (strcmp(soundName, table->filename) == 0) && (table->atribPos != 0)
-			 && table->atribPos == _stateMusicTable[_curMusicState].atribPos) {
-				setFadeVolume(soundName, table->volume, table->fadeOut60TicksDelay);
-				setFadePan(soundName, pan, table->fadeOut60TicksDelay);
-				setHookId(soundName, hookId);
-			} else {
-				fadeOutMusic(table->fadeOut60TicksDelay);
-				startMusic(table->filename, hookId, table->volume, pan);
-			}
+		if (table->pan == 0)
+			pan = 64;
+		else
+			pan = table->pan;
+		if (!soundName) {
+			startMusic(table->filename, hookId, 0, pan);
+			setFadeVolume(table->filename, table->volume, table->fadeOut60TicksDelay);
+			return;
 		}
+		int old_pan = getCurMusicPan();
+		int old_vol = getCurMusicVol();
+		if (old_pan == -1)
+			old_pan = 64;
+		if (old_vol == -1)
+			old_vol = 127;
+
+		if (table->opcode == 2) {
+			fadeOutMusic(table->fadeOut60TicksDelay);
+			startMusic(table->filename, hookId, table->volume, pan);
+			return;
+		}
+		if (strcmp(soundName, table->filename) == 0) {
+			setFadeVolume(soundName, table->volume, table->fadeOut60TicksDelay);
+			setFadePan(soundName, pan, table->fadeOut60TicksDelay);
+			return;
+		}
+
+		if (!sequence && table->atribPos && table->atribPos == _stateMusicTable[_curMusicState].atribPos) {
+			fadeOutMusicAndStartNew(table->fadeOut60TicksDelay, table->filename, hookId, old_vol, old_pan);
+			setFadeVolume(table->filename, table->volume, table->fadeOut60TicksDelay);
+			setFadePan(table->filename, pan, table->fadeOut60TicksDelay);
+		} else {
+			fadeOutMusic(table->fadeOut60TicksDelay);
+			startMusic(table->filename, hookId, table->volume, pan);
+		}
 	}
 }

Modified: residual/trunk/engine/imuse/imuse_script.cpp
===================================================================
--- residual/trunk/engine/imuse/imuse_script.cpp	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/imuse/imuse_script.cpp	2008-03-10 23:06:07 UTC (rev 31101)
@@ -24,6 +24,7 @@
 #include "common/platform.h"
 #include "common/debug.h"
 #include "common/timer.h"
+#include "common/mutex.h"
 
 #include "engine/backend/driver.h"
 
@@ -33,34 +34,41 @@
 #include "engine/imuse/imuse.h"
 #include "engine/imuse/imuse_sndmgr.h"
 
+void Imuse::flushTrack(Track *track) {
+	track->toBeRemoved = true;
+
+	if (track->stream) {
+		// Finalize the appendable stream, then remove our reference to it.
+		// Note that there might still be some data left in the buffers of the
+		// appendable stream. We play it nice and wait till all of it
+		// played. The audio mixer will take care of it afterwards (and dispose it).
+		track->stream->finish();
+		track->stream = 0;
+		if (track->soundDesc) {
+			_sound->closeSound(track->soundDesc);
+			track->soundDesc = 0;
+		}
+	}
+
+	if (!g_mixer->isSoundHandleActive(track->handle)) {
+		memset(track, 0, sizeof(Track));
+	}
+}
+
 void Imuse::flushTracks() {
-	// flushTracks should not lock the stack since all the functions
-	// that call it already do (stopAllSounds, startSound)
+	Common::StackLock lock(_mutex);
 	for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
 		Track *track = _track[l];
-		if (track->used && track->readyToRemove) {
-			if (track->stream) {
-				if (!track->stream->endOfStream()) {
-	 				track->stream->finish();
-	 			}
-				if (track->stream->endOfStream()) {
-					g_mixer->stopHandle(track->handle);
-					delete track->stream;
-					track->stream = NULL;
-					_sound->closeSound(track->soundHandle);
-					track->soundHandle = NULL;
-					track->used = false;
-					strcpy(track->soundName, "");
-				}
-			}
+		if (track->used && track->toBeRemoved && !g_mixer->isSoundHandleActive(track->handle)) {
+			memset(track, 0, sizeof(Track));
 		}
 	}
 }
 
 void Imuse::refreshScripts() {
+	Common::StackLock lock(_mutex);
 	bool found = false;
-	
-	StackLock lock(_mutex);
+
 	for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
 		Track *track = _track[l];
 		if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
@@ -68,52 +76,58 @@
 		}
 	}
 
-	if (!found && (_curMusicSeq != 0)) {
-		setMusicSequence(2000);
+	if (!found && _curMusicState) {
+		setMusicSequence(0);
 	}
 }
 
 void Imuse::startVoice(const char *soundName, int volume, int pan) {
-	startSound(soundName, IMUSE_VOLGRP_VOICE, 0, volume, pan, 127);
+	if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+		printf("Imuse::startVoice(): SoundName %s, vol:%d, pan:%d\n", soundName, volume, pan);
+	startSound(soundName, IMUSE_VOLGRP_VOICE, 0, volume, pan, 127, NULL);
 }
 
 void Imuse::startMusic(const char *soundName, int hookId, int volume, int pan) {
-	startSound(soundName, IMUSE_VOLGRP_MUSIC, hookId, volume, pan, 126);
+	if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+		printf("Imuse::startMusic(): SoundName %s, hookId:%d, vol:%d, pan:%d\n", soundName, hookId, volume, pan);
+	startSound(soundName, IMUSE_VOLGRP_MUSIC, hookId, volume, pan, 126, NULL);
 }
 
+void Imuse::startMusicWithOtherPos(const char *soundName, int hookId, int volume, int pan, Track *otherTrack) {
+	if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+		printf("Imuse::startMusicWithOtherPos(): SoundName %s, hookId:%d, vol:%d, pan:%d\n", soundName, volume, pan);
+	startSound(soundName, IMUSE_VOLGRP_MUSIC, hookId, volume, pan, 126, otherTrack);
+}
+
 void Imuse::startSfx(const char *soundName, int priority) {
-	startSound(soundName, IMUSE_VOLGRP_SFX, 0, 127, 0, priority);
+	if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+		printf("Imuse::startSfx(): SoundName %s, priority:%d\n", soundName, priority);
+	startSound(soundName, IMUSE_VOLGRP_SFX, 0, 127, 0, priority, NULL);
 }
 
 int32 Imuse::getPosIn60HzTicks(const char *soundName) {
+	Common::StackLock lock(_mutex);
 	Track *getTrack = NULL;
 	
 	getTrack = findTrack(soundName);
 	// Warn the user if the track was not found
 	if (getTrack == NULL) {
 		if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_WARN || debugLevel == DEBUG_ALL)
-			warning("Music track '%s' could not be found to get ticks!", soundName);
+			warning("Sound '%s' could not be found to get ticks!", soundName);
 		return false;
 	}
 
-	if (getTrack->handle.isActive()) {
-		int32 pos = (5 * (getTrack->dataOffset + getTrack->regionOffset)) / (getTrack->iteration / 12);
-		return pos;
-	}
-	return -1;
+	int32 pos = (5 * (getTrack->dataOffset + getTrack->regionOffset)) / (getTrack->feedSize / 200);
+	return pos;
 }
 
 bool Imuse::isVoicePlaying() {
-	StackLock lock(_mutex);
+	Common::StackLock lock(_mutex);
 	for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
 		Track *track = _track[l];
-		// Make sure the track is in use before checking the group ID,
-		// otherwise volGroupId can be uninitialized or reference an
-		// old track.
 		if (track->used && track->volGroupId == IMUSE_VOLGRP_VOICE) {
-			if (track->handle.isActive()) {
+			if (g_mixer->isSoundHandleActive(track->handle))
 				return true;
-			}
 		}
 	}
 
@@ -121,51 +135,55 @@
 }
 
 bool Imuse::getSoundStatus(const char *soundName) {
-	Track *statusTrack = NULL;
+	Common::StackLock lock(_mutex);
+	Track *track = NULL;
 	
 	// If there's no name then don't try to get the status!
 	if (strlen(soundName) == 0)
 		return false;
 	
-	statusTrack = findTrack(soundName);
+	track = findTrack(soundName);
 	// Warn the user if the track was not found
-	if (statusTrack == NULL) {
+	if (track == NULL || !g_mixer->isSoundHandleActive(track->handle)) {
 		// This debug warning should be "light" since this function gets called
 		// on occassion to see if a sound has stopped yet
 		if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_NORMAL || debugLevel == DEBUG_ALL)
-			printf("Music track '%s' could not be found to get status, assume inactive.\n", soundName);
+			printf("Sound '%s' could not be found to get status, assume inactive.\n", soundName);
 		return false;
 	}
-	return statusTrack->handle.isActive();
+	return true;
 }
 
 void Imuse::stopSound(const char *soundName) {
+	Common::StackLock lock(_mutex);
+	if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+		printf("Imuse::stopSound(): SoundName %s\n", soundName);
 	Track *removeTrack = NULL;
 	
 	removeTrack = findTrack(soundName);
 	// Warn the user if the track was not found
 	if (removeTrack == NULL) {
 		if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_WARN || debugLevel == DEBUG_ALL)
-			warning("Music track '%s' could not be found to stop!", soundName);
+			warning("Sound track '%s' could not be found to stop!", soundName);
 		return;
 	}
-	removeTrack->toBeRemoved = true;
+	flushTrack(removeTrack);
 }
 
 void Imuse::stopAllSounds() {
-	for (;;) {
-		bool foundNotRemoved = false;
-		for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
-			Track *track = _track[l];
-			if (track->used) {
-				track->toBeRemoved = true;
-				foundNotRemoved = true;
+	Common::StackLock lock(_mutex);
+	if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
+		printf("Imuse::stopAllSounds()\n");
+
+	for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
+		Track *track = _track[l];
+		if (track->used) {
+			g_mixer->stopHandle(track->handle);
+			if (track->soundDesc) {
+				_sound->closeSound(track->soundDesc);
 			}
+			memset(track, 0, sizeof(Track));
 		}
-		if (!foundNotRemoved)
-			break;
-		flushTracks();
-		g_driver->delayMillis(50);
 	}
 }
 

Modified: residual/trunk/engine/imuse/imuse_sndmgr.cpp
===================================================================
--- residual/trunk/engine/imuse/imuse_sndmgr.cpp	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/imuse/imuse_sndmgr.cpp	2008-03-10 23:06:07 UTC (rev 31101)
@@ -35,7 +35,7 @@
 
 ImuseSndMgr::ImuseSndMgr() {
 	for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
-		memset(&_sounds[l], 0, sizeof(SoundStruct));
+		memset(&_sounds[l], 0, sizeof(SoundDesc));
 	}
 }
 
@@ -72,10 +72,10 @@
 	} while (tag != MKID_BE('DATA'));
 }
 
-void ImuseSndMgr::parseSoundHeader(byte *ptr, SoundStruct *sound, int &headerSize) {
+void ImuseSndMgr::parseSoundHeader(byte *ptr, SoundDesc *sound, int &headerSize) {
 	if (READ_UINT32(ptr) == MKID('RIFF')) {
-		sound->region = (Region *)malloc(sizeof(Region));
-		sound->jump = (Jump *)malloc(0);
+		sound->region = new Region[1];
+		sound->jump = new Jump[0];
 		sound->numJumps = 0;
 		sound->numRegions = 1;
 		sound->region[0].offset = 0;
@@ -96,8 +96,8 @@
 		sound->numRegions = 0;
 		sound->numJumps = 0;
 		countElements(ptr, sound->numRegions, sound->numJumps);
-		sound->region = (Region *)malloc(sizeof(Region) * sound->numRegions);
-		sound->jump = (Jump *)malloc(sizeof(Jump) * sound->numJumps);
+		sound->region = new Region [sound->numRegions];
+		sound->jump = new Jump [sound->numJumps];
 
 		do {
 			tag = READ_BE_UINT32(ptr); ptr += 4;
@@ -147,7 +147,7 @@
 	}
 }
 
-ImuseSndMgr::SoundStruct *ImuseSndMgr::allocSlot() {
+ImuseSndMgr::SoundDesc *ImuseSndMgr::allocSlot() {
 	for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
 		if (!_sounds[l].inUse) {
 			_sounds[l].inUse = true;
@@ -158,12 +158,12 @@
 	return NULL;
 }
 
-ImuseSndMgr::SoundStruct *ImuseSndMgr::openSound(const char *soundName, int volGroupId) {
+ImuseSndMgr::SoundDesc *ImuseSndMgr::openSound(const char *soundName, int volGroupId) {
 	const char *extension = soundName + std::strlen(soundName) - 3;
 	byte *ptr = NULL;
 	int headerSize = 0;
 
-	SoundStruct *sound = allocSlot();
+	SoundDesc *sound = allocSlot();
 	if (!sound) {
 		error("ImuseSndMgr::openSound() Can't alloc free sound slot");
 	}
@@ -197,94 +197,94 @@
 	return sound;
 }
 
-void ImuseSndMgr::closeSound(SoundStruct *soundHandle) {
-	assert(checkForProperHandle(soundHandle));
+void ImuseSndMgr::closeSound(SoundDesc *sound) {
+	assert(checkForProperHandle(sound));
 
-	if (soundHandle->mcmpMgr) {
-		delete soundHandle->mcmpMgr;
-		soundHandle->mcmpMgr = NULL;
+	if (sound->mcmpMgr) {
+		delete sound->mcmpMgr;
+		sound->mcmpMgr = NULL;
 	}
 
-	if (soundHandle->blockRes) {
-		delete soundHandle->blockRes;
-		soundHandle->blockRes = NULL;
+	if (sound->blockRes) {
+		delete sound->blockRes;
+		sound->blockRes = NULL;
 	}
 
-	if (soundHandle->region) {
-		free(soundHandle->region);
-		soundHandle->region = NULL;
+	if (sound->region) {
+		delete[] sound->region;
+		sound->region = NULL;
 	}
 
-	if (soundHandle->jump) {
-		free(soundHandle->jump);
-		soundHandle->jump = NULL;
+	if (sound->jump) {
+		delete[] sound->jump;
+		sound->jump = NULL;
 	}
 
-	memset(soundHandle, 0, sizeof(SoundStruct));
+	memset(sound, 0, sizeof(SoundDesc));
 }
 
-ImuseSndMgr::SoundStruct *ImuseSndMgr::cloneSound(SoundStruct *soundHandle) {
-	assert(checkForProperHandle(soundHandle));
+ImuseSndMgr::SoundDesc *ImuseSndMgr::cloneSound(SoundDesc *sound) {
+	assert(checkForProperHandle(sound));
 
-	return openSound(soundHandle->name, soundHandle->volGroupId);
+	return openSound(sound->name, sound->volGroupId);
 }
 
-bool ImuseSndMgr::checkForProperHandle(SoundStruct *soundHandle) {
-	if (!soundHandle)
+bool ImuseSndMgr::checkForProperHandle(SoundDesc *sound) {
+	if (!sound)
 		return false;
 
 	for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
-		if (soundHandle == &_sounds[l])
+		if (sound == &_sounds[l])
 			return true;
 	}
 
 	return false;
 }
 
-int ImuseSndMgr::getFreq(SoundStruct *soundHandle) {
-	assert(checkForProperHandle(soundHandle));
-	return soundHandle->freq;
+int ImuseSndMgr::getFreq(SoundDesc *sound) {
+	assert(checkForProperHandle(sound));
+	return sound->freq;
 }
 
-int ImuseSndMgr::getBits(SoundStruct *soundHandle) {
-	assert(checkForProperHandle(soundHandle));
-	return soundHandle->bits;
+int ImuseSndMgr::getBits(SoundDesc *sound) {
+	assert(checkForProperHandle(sound));
+	return sound->bits;
 }
 
-int ImuseSndMgr::getChannels(SoundStruct *soundHandle) {
-	assert(checkForProperHandle(soundHandle));
-	return soundHandle->channels;
+int ImuseSndMgr::getChannels(SoundDesc *sound) {
+	assert(checkForProperHandle(sound));
+	return sound->channels;
 }
 
-bool ImuseSndMgr::isEndOfRegion(SoundStruct *soundHandle, int region) {
-	assert(checkForProperHandle(soundHandle));
-	assert(region >= 0 && region < soundHandle->numRegions);
-	return soundHandle->endFlag;
+bool ImuseSndMgr::isEndOfRegion(SoundDesc *sound, int region) {
+	assert(checkForProperHandle(sound));
+	assert(region >= 0 && region < sound->numRegions);
+	return sound->endFlag;
 }
 
-int ImuseSndMgr::getNumRegions(SoundStruct *soundHandle) {
-	assert(checkForProperHandle(soundHandle));
-	return soundHandle->numRegions;
+int ImuseSndMgr::getNumRegions(SoundDesc *sound) {
+	assert(checkForProperHandle(sound));
+	return sound->numRegions;
 }
 
-int ImuseSndMgr::getNumJumps(SoundStruct *soundHandle) {
-	assert(checkForProperHandle(soundHandle));
-	return soundHandle->numJumps;
+int ImuseSndMgr::getNumJumps(SoundDesc *sound) {
+	assert(checkForProperHandle(sound));
+	return sound->numJumps;
 }
 
-int ImuseSndMgr::getRegionOffset(SoundStruct *soundHandle, int region) {
-	assert(checkForProperHandle(soundHandle));
-	assert(region >= 0 && region < soundHandle->numRegions);
-	return soundHandle->region[region].offset;
+int ImuseSndMgr::getRegionOffset(SoundDesc *sound, int region) {
+	assert(checkForProperHandle(sound));
+	assert(region >= 0 && region < sound->numRegions);
+	return sound->region[region].offset;
 }
 
-int ImuseSndMgr::getJumpIdByRegionAndHookId(SoundStruct *soundHandle, int region, int hookId) {
-	assert(checkForProperHandle(soundHandle));
-	assert(region >= 0 && region < soundHandle->numRegions);
-	int32 offset = soundHandle->region[region].offset;
-	for (int l = 0; l < soundHandle->numJumps; l++) {
-		if (offset == soundHandle->jump[l].offset) {
-			if (soundHandle->jump[l].hookId == hookId)
+int ImuseSndMgr::getJumpIdByRegionAndHookId(SoundDesc *sound, int region, int hookId) {
+	assert(checkForProperHandle(sound));
+	assert(region >= 0 && region < sound->numRegions);
+	int32 offset = sound->region[region].offset;
+	for (int l = 0; l < sound->numJumps; l++) {
+		if (offset == sound->jump[l].offset) {
+			if (sound->jump[l].hookId == hookId)
 				return l;
 		}
 	}
@@ -292,12 +292,12 @@
 	return -1;
 }
 
-int ImuseSndMgr::getRegionIdByJumpId(SoundStruct *soundHandle, int jumpId) {
-	assert(checkForProperHandle(soundHandle));
-	assert(jumpId >= 0 && jumpId < soundHandle->numJumps);
-	int32 dest = soundHandle->jump[jumpId].dest;
-	for (int l = 0; l < soundHandle->numRegions; l++) {
-		if (dest == soundHandle->region[l].offset) {
+int ImuseSndMgr::getRegionIdByJumpId(SoundDesc *sound, int jumpId) {
+	assert(checkForProperHandle(sound));
+	assert(jumpId >= 0 && jumpId < sound->numJumps);
+	int32 dest = sound->jump[jumpId].dest;
+	for (int l = 0; l < sound->numRegions; l++) {
+		if (dest == sound->region[l].offset) {
 			return l;
 		}
 	}
@@ -305,38 +305,38 @@
 	return -1;
 }
 
-int ImuseSndMgr::getJumpHookId(SoundStruct *soundHandle, int number) {
-	assert(checkForProperHandle(soundHandle));
-	assert(number >= 0 && number < soundHandle->numJumps);
-	return soundHandle->jump[number].hookId;
+int ImuseSndMgr::getJumpHookId(SoundDesc *sound, int number) {
+	assert(checkForProperHandle(sound));
+	assert(number >= 0 && number < sound->numJumps);
+	return sound->jump[number].hookId;
 }
 
-int ImuseSndMgr::getJumpFade(SoundStruct *soundHandle, int number) {
-	assert(checkForProperHandle(soundHandle));
-	assert(number >= 0 && number < soundHandle->numJumps);
-	return soundHandle->jump[number].fadeDelay;
+int ImuseSndMgr::getJumpFade(SoundDesc *sound, int number) {
+	assert(checkForProperHandle(sound));
+	assert(number >= 0 && number < sound->numJumps);
+	return sound->jump[number].fadeDelay;
 }
 
-int32 ImuseSndMgr::getDataFromRegion(SoundStruct *soundHandle, int region, byte **buf, int32 offset, int32 size) {
-	assert(checkForProperHandle(soundHandle));
+int32 ImuseSndMgr::getDataFromRegion(SoundDesc *sound, int region, byte **buf, int32 offset, int32 size) {
+	assert(checkForProperHandle(sound));
 	assert(buf && offset >= 0 && size >= 0);
-	assert(region >= 0 && region < soundHandle->numRegions);
+	assert(region >= 0 && region < sound->numRegions);
 
-	int32 region_offset = soundHandle->region[region].offset;
-	int32 region_length = soundHandle->region[region].length;
+	int32 region_offset = sound->region[region].offset;
+	int32 region_length = sound->region[region].length;
 
 	if (offset + size > region_length) {
 		size = region_length - offset;
-		soundHandle->endFlag = true;
+		sound->endFlag = true;
 	} else {
-		soundHandle->endFlag = false;
+		sound->endFlag = false;
 	}
 
-	if (soundHandle->mcmpData) {
-		size = soundHandle->mcmpMgr->decompressSample(region_offset + offset, size, buf);
+	if (sound->mcmpData) {
+		size = sound->mcmpMgr->decompressSample(region_offset + offset, size, buf);
 	} else {
-		*buf = (byte *)malloc(size);
-		memcpy(*buf, soundHandle->resPtr + region_offset + offset, size);
+		*buf = new byte[size];
+		memcpy(*buf, sound->resPtr + region_offset + offset, size);
 	}
 	
 	return size;

Modified: residual/trunk/engine/imuse/imuse_sndmgr.h
===================================================================
--- residual/trunk/engine/imuse/imuse_sndmgr.h	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/imuse/imuse_sndmgr.h	2008-03-10 23:06:07 UTC (rev 31101)
@@ -64,7 +64,7 @@
 	
 public:
 
-	struct SoundStruct {
+	struct SoundDesc {
 		uint16 freq;		// frequency
 		byte channels;		// stereo or mono
 		byte bits;			// 8, 12, 16
@@ -77,6 +77,7 @@
 		char name[32];
 		McmpMgr *mcmpMgr;
 		Block *blockRes;
+		int type;
 		int volGroupId;
 		byte *resPtr;
 		bool mcmpData;
@@ -84,11 +85,11 @@
 
 private:
 
-	SoundStruct _sounds[MAX_IMUSE_SOUNDS];
+	SoundDesc _sounds[MAX_IMUSE_SOUNDS];
 
-	bool checkForProperHandle(SoundStruct *soundHandle);
-	SoundStruct *allocSlot();
-	void parseSoundHeader(byte *ptr, SoundStruct *sound, int &headerSize);
+	bool checkForProperHandle(SoundDesc *soundDesc);
+	SoundDesc *allocSlot();
+	void parseSoundHeader(byte *ptr, SoundDesc *sound, int &headerSize);
 	void countElements(byte *ptr, int &numRegions, int &numJumps);
 
 public:
@@ -96,23 +97,23 @@
 	ImuseSndMgr();
 	~ImuseSndMgr();
 
-	SoundStruct *openSound(const char *soundName, int volGroupId);
-	void closeSound(SoundStruct *soundHandle);
-	SoundStruct *cloneSound(SoundStruct *soundHandle);
+	SoundDesc *openSound(const char *soundName, int volGroupId);
+	void closeSound(SoundDesc *sound);
+	SoundDesc *cloneSound(SoundDesc *sound);
 
-	int getFreq(SoundStruct *soundHandle);
-	int getBits(SoundStruct *soundHandle);
-	int getChannels(SoundStruct *soundHandle);
-	bool isEndOfRegion(SoundStruct *soundHandle, int region);
-	int getNumRegions(SoundStruct *soundHandle);
-	int getNumJumps(SoundStruct *soundHandle);
-	int getRegionOffset(SoundStruct *soundHandle, int region);
-	int getJumpIdByRegionAndHookId(SoundStruct *soundHandle, int region, int hookId);
-	int getRegionIdByJumpId(SoundStruct *soundHandle, int jumpId);
-	int getJumpHookId(SoundStruct *soundHandle, int number);
-	int getJumpFade(SoundStruct *soundHandle, int number);
+	int getFreq(SoundDesc *sound);
+	int getBits(SoundDesc *sound);
+	int getChannels(SoundDesc *sound);
+	bool isEndOfRegion(SoundDesc *sound, int region);
+	int getNumRegions(SoundDesc *sound);
+	int getNumJumps(SoundDesc *sound);
+	int getRegionOffset(SoundDesc *sound, int region);
+	int getJumpIdByRegionAndHookId(SoundDesc *sound, int region, int hookId);
+	int getRegionIdByJumpId(SoundDesc *sound, int jumpId);
+	int getJumpHookId(SoundDesc *sound, int number);
+	int getJumpFade(SoundDesc *sound, int number);
 
-	int32 getDataFromRegion(SoundStruct *soundHandle, int region, byte **buf, int32 offset, int32 size);
+	int32 getDataFromRegion(SoundDesc *sound, int region, byte **buf, int32 offset, int32 size);
 };
 
 #endif

Added: residual/trunk/engine/imuse/imuse_tables.h
===================================================================
--- residual/trunk/engine/imuse/imuse_tables.h	                        (rev 0)
+++ residual/trunk/engine/imuse/imuse_tables.h	2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,49 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2006 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library 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
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef IMUSE_TABLES_H
+#define IMUSE_TABLES_H
+
+#include "common/sys.h"
+#include "common/platform.h"
+#include "common/debug.h"
+
+#include "engine/lua.h"
+
+#include "mixer/mixer.h"
+#include "mixer/audiostream.h"
+
+#include "engine/imuse/imuse_sndmgr.h"
+#include "engine/imuse/imuse_mcmp_mgr.h"
+
+struct ImuseTable {
+	byte opcode;
+	int16 soundId;
+	byte atribPos;
+	byte hookId;
+	int16 fadeOut60TicksDelay;
+	byte volume;
+	byte pan;
+	char filename[32];
+};
+
+#endif


Property changes on: residual/trunk/engine/imuse/imuse_tables.h
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Modified: residual/trunk/engine/imuse/imuse_track.cpp
===================================================================
--- residual/trunk/engine/imuse/imuse_track.cpp	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/imuse/imuse_track.cpp	2008-03-10 23:06:07 UTC (rev 31101)
@@ -23,6 +23,7 @@
 #include "common/sys.h"
 #include "common/platform.h"
 #include "common/debug.h"
+#include "common/mutex.h"
 
 #include "engine/backend/driver.h"
 
@@ -31,6 +32,7 @@
 
 #include "engine/imuse/imuse.h"
 #include "engine/imuse/imuse_sndmgr.h"
+#include "engine/imuse/imuse_track.h"
 
 int Imuse::allocSlot(int priority) {
 	int l, lowest_priority = 127;
@@ -39,35 +41,46 @@
 	// allocSlot called by startSound so no locking is necessary
 	for (l = 0; l < MAX_IMUSE_TRACKS; l++) {
 		if (!_track[l]->used) {
-			return l; // Found an unused track
+			trackId = l;
+			break;
 		}
 	}
 
-	warning("Imuse::startSound(): All slots are full");
-	for (l = 0; l < MAX_IMUSE_TRACKS; l++) {
-		Track *track = _track[l];
-		if (track->used && !track->toBeRemoved && lowest_priority > track->priority) {
-			lowest_priority = track->priority;
-			trackId = l;
+	if (trackId == -1) {
+		warning("Imuse::startSound(): All slots are full");
+		for (l = 0; l < MAX_IMUSE_TRACKS; l++) {
+			Track *track = _track[l];
+			if (track->used && !track->toBeRemoved &&
+					(lowest_priority > track->priority)) {
+				lowest_priority = track->priority;
+				trackId = l;
+			}
 		}
+		if (lowest_priority <= priority) {
+			assert(trackId != -1);
+			Track *track = _track[trackId];
+
+			// Stop the track immediately
+			g_mixer->stopHandle(track->handle);
+			if (track->soundDesc) {
+				_sound->closeSound(track->soundDesc);
+			}
+
+			// Mark it as unused
+			memset(track, 0, sizeof(Track));
+		} else {
+			return -1;
+		}
 	}
-	if (lowest_priority <= priority) {
-		assert(trackId != -1);
-		_track[trackId]->toBeRemoved = true;
-		warning("Imuse::startSound(): Removed sound %s from track %d", _track[trackId]->soundName, trackId);
-	} else {
-		warning("Imuse::startSound(): Priority sound too low");
-		return -1;
-	}
 
 	return trackId;
 }
 
-bool Imuse::startSound(const char *soundName, int volGroupId, int hookId, int volume, int pan, int priority) {
+bool Imuse::startSound(const char *soundName, int volGroupId, int hookId, int volume, int pan, int priority, Track *otherTrack) {
+	Common::StackLock lock(_mutex);
 	Track *track = NULL;
-	int i, l = -1;
-	
-	StackLock lock(_mutex);
+	int i;
+
 	// If the track is already playing then there is absolutely no
 	// reason to start it again, the existing track should be modified
 	// instead of starting a new copy of the track
@@ -79,111 +92,73 @@
 			return true;
 		}
 	}
+
 	// Priority Level 127 appears to mean "load but don't play", so
 	// within our paradigm this is a much lower priority than everything
 	// else we're doing
 	if (priority == 127)
 		priority = -1;
-	l = allocSlot(priority);
+
+	int l = allocSlot(priority);
 	if (l == -1) {
-		warning("Imuse::startSound(): Can't start sound - no free slots");
+		warning("Imuse::startSound() Can't start sound - no free slots");
 		return false;
 	}
+
 	track = _track[l];
-	i = 5;
-	// At this time it is inappropriate to assume that this will always
-	// succeed, so set a limit of 5 tries on running flushTracks
-	while (track->used && i > 0) {
-		// The designated track is not yet available. So, we call flushTracks()
-		// to get it processed (and thus made ready for us). Since the actual
-		// processing is done by another thread, we also call parseEvents to
-		// give it some time (and to avoid busy waiting/looping).
-		flushTracks();
-		i--;
-	}
-	if (i == 0) {
-		if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_WARN || debugLevel == DEBUG_ALL)
-			warning("Imuse::startSound(): flushTracks was unable to free up a track for %s!", soundName);
-		return false;
-	}
+	// Reset the track
+	memset(track, 0, sizeof(Track));
 
 	track->pan = pan * 1000;
-	track->panFadeDest = 0;
-	track->panFadeStep = 0;
-	track->panFadeDelay = 0;
-	track->panFadeUsed = false;
 	track->vol = volume * 1000;
-	track->volFadeDest = 0;
-	track->volFadeStep = 0;
-	track->volFadeDelay = 0;
-	track->volFadeUsed = false;
-	track->started = false;
 	track->volGroupId = volGroupId;
 	track->curHookId = hookId;
 	track->priority = priority;
 	track->curRegion = -1;
-	track->dataOffset = 0;
-	track->regionOffset = 0;
-	track->mixerFlags = 0;
-	track->mixerPan = 0;
-	track->mixerVol = volume;
-	track->toBeRemoved = false;
-	track->readyToRemove = false;
 
 	int bits = 0, freq = 0, channels = 0;
 
 	strcpy(track->soundName, soundName);
-	track->soundHandle = _sound->openSound(soundName, volGroupId);
+	track->soundDesc = _sound->openSound(soundName, volGroupId);
 
-	if (track->soundHandle == NULL)
+	if (!track->soundDesc)
 		return false;
 
-	bits = _sound->getBits(track->soundHandle);
-	channels = _sound->getChannels(track->soundHandle);
-	freq = _sound->getFreq(track->soundHandle);
+	bits = _sound->getBits(track->soundDesc);
+	channels = _sound->getChannels(track->soundDesc);
+	freq = _sound->getFreq(track->soundDesc);
 
 	assert(bits == 8 || bits == 12 || bits == 16);
 	assert(channels == 1 || channels == 2);
 	assert(0 < freq && freq <= 65535);
 
-	track->iteration = freq * channels * 2;
-	track->mixerFlags = SoundMixer::FLAG_16BITS;
+	track->feedSize = freq * channels * 2;
+	track->mixerFlags = kFlag16Bits;
 	if (channels == 2)
-		track->mixerFlags |= SoundMixer::FLAG_STEREO | SoundMixer::FLAG_REVERSE_STEREO;
+		track->mixerFlags |= kFlagStereo | kFlagReverseStereo;
 
-	pan = track->pan / 1000;
-	pan = (pan != 64) ? 2 * pan - 127 : 0;
-	volume = track->vol / 1000;
+	if (otherTrack && otherTrack->used && !otherTrack->toBeRemoved) {
+		track->curRegion = otherTrack->curRegion;
+		track->dataOffset = otherTrack->dataOffset;
+		track->regionOffset = otherTrack->regionOffset;
+	}
 
-	if (track->volGroupId == 1)
-		volume = (volume * _volVoice) / 128;
-	if (track->volGroupId == 2)
-		volume = (volume * _volSfx) / 128;
-	if (track->volGroupId == 3)
-		volume = (volume * _volMusic) / 128;
-
-	track->mixerPan = pan;
-	track->mixerVol = volume;
-
-	// setup 1 second stream wrapped buffer
-	int32 streamBufferSize = track->iteration;
-	track->stream = makeAppendableAudioStream(freq, track->mixerFlags, streamBufferSize);
-	g_mixer->playInputStream(&track->handle, track->stream, false, -1, track->mixerVol, track->mixerPan, false);
-	track->started = true;
+	track->stream = Audio::makeAppendableAudioStream(freq, makeMixerFlags(track->mixerFlags));
+	g_mixer->playInputStream(track->getType(), &track->handle, track->stream, -1, track->getVol(), track->getPan());
 	track->used = true;
 
 	return true;
 }
 
-Imuse::Track *Imuse::findTrack(const char *soundName) {
-	StackLock lock(_mutex);
+Track *Imuse::findTrack(const char *soundName) {
 	for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
 		Track *track = _track[l];
 		
 		// Since the audio (at least for Eva's keystrokes) can be referenced
 		// two ways: keyboard.IMU and keyboard.imu, make a case insensitive
 		// search for the track to make sure we can find it
-		if (strlen(track->soundName) != 0 && strcasecmp(track->soundName, soundName) == 0) {
+		if (track->used && !track->toBeRemoved
+				&& strlen(track->soundName) != 0 && strcasecmp(track->soundName, soundName) == 0) {
 			return track;
 		}
 	}
@@ -191,6 +166,7 @@
 }
 
 void Imuse::setPriority(const char *soundName, int priority) {
+	Common::StackLock lock(_mutex);
 	Track *changeTrack = NULL;
 	assert ((priority >= 0) && (priority <= 127));
 	
@@ -204,6 +180,7 @@
 }
 
 void Imuse::setVolume(const char *soundName, int volume) {
+	Common::StackLock lock(_mutex);
 	Track *changeTrack;
 	
 	changeTrack = findTrack(soundName);
@@ -215,17 +192,19 @@
 }
 
 void Imuse::setPan(const char *soundName, int pan) {
+	Common::StackLock lock(_mutex);
 	Track *changeTrack;
 	
 	changeTrack = findTrack(soundName);
 	if (changeTrack == NULL) {
-		warning("Unable to find track '%s' to change volume!", soundName);
+		warning("Unable to find track '%s' to change pan!", soundName);
 		return;
 	}
-	changeTrack->pan = pan;
+	changeTrack->pan = pan * 1000;
 }
 
 int Imuse::getVolume(const char *soundName) {
+	Common::StackLock lock(_mutex);
 	Track *getTrack;
 	
 	getTrack = findTrack(soundName);
@@ -237,6 +216,7 @@
 }
 
 void Imuse::setHookId(const char *soundName, int hookId) {
+	Common::StackLock lock(_mutex);
 	Track *changeTrack;
 	
 	changeTrack = findTrack(soundName);
@@ -248,12 +228,12 @@
 }
 
 int Imuse::getCountPlayedTracks(const char *soundName) {
+	Common::StackLock lock(_mutex);
 	int count = 0;
 	
-	StackLock lock(_mutex);
 	for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
 		Track *track = _track[l];
-		if (track->used && !track->toBeRemoved && (strcmp(track->soundName, soundName) == 0)) {
+		if (track->used && !track->toBeRemoved && (strcasecmp(track->soundName, soundName) == 0)) {
 			count++;
 		}
 	}
@@ -262,6 +242,7 @@
 }
 
 void Imuse::selectVolumeGroup(const char *soundName, int volGroupId) {
+	Common::StackLock lock(_mutex);
 	Track *changeTrack;
 	assert((volGroupId >= 1) && (volGroupId <= 4));
 
@@ -277,6 +258,7 @@
 }
 
 void Imuse::setFadeVolume(const char *soundName, int destVolume, int duration) {
+	Common::StackLock lock(_mutex);
 	Track *changeTrack;
 
 	changeTrack = findTrack(soundName);
@@ -291,6 +273,7 @@
 }
 
 void Imuse::setFadePan(const char *soundName, int destPan, int duration) {
+	Common::StackLock lock(_mutex);
 	Track *changeTrack;
 
 	changeTrack = findTrack(soundName);
@@ -305,7 +288,7 @@
 }
 
 char *Imuse::getCurMusicSoundName() {
-	StackLock lock(_mutex);
+	Common::StackLock lock(_mutex);
 	for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
 		Track *track = _track[l];
 		if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
@@ -315,65 +298,90 @@
 	return NULL;
 }
 
+int Imuse::getCurMusicPan() {
+	Common::StackLock lock(_mutex);
+	for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
+		Track *track = _track[l];
+		if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
+			return track->pan / 1000;
+		}
+	}
+	return NULL;
+}
+
+int Imuse::getCurMusicVol() {
+	Common::StackLock lock(_mutex);
+	for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
+		Track *track = _track[l];
+		if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
+			return track->vol / 1000;
+		}
+	}
+	return NULL;
+}
+
 void Imuse::fadeOutMusic(int duration) {
-	StackLock lock(_mutex);
+	Common::StackLock lock(_mutex);
 	for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
 		Track *track = _track[l];
 		if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
 			cloneToFadeOutTrack(track, duration);
-			track->toBeRemoved = true;
+			flushTrack(track);
+			return;
 		}
 	}
 }
 
-Imuse::Track *Imuse::cloneToFadeOutTrack(Track *track, int fadeDelay) {
-	assert(track);
-	Track *fadeTrack = 0;
+void Imuse::fadeOutMusicAndStartNew(int fadeDelay, const char *filename, int hookId, int vol, int pan) {
+	Common::StackLock lock(_mutex);
 
-	{
-		StackLock lock(_mutex);
-		for (int l = MAX_IMUSE_TRACKS; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
-			if (!_track[l]->used) {
-				fadeTrack = _track[l];
-				break;
-			}
+	for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
+		Track *track = _track[l];
+		if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
+			startMusicWithOtherPos(filename, 0, vol, pan, track);
+			cloneToFadeOutTrack(track, fadeDelay);
+			flushTrack(track);
+			break;
 		}
-		if (fadeTrack == 0)
-			error("Imuse::cloneTofadeTrackId() Can't find free fade track");
+	}
+}
 
-		fadeTrack->pan = track->pan;
-		fadeTrack->vol = track->vol;
-		fadeTrack->volGroupId = track->volGroupId;
-		fadeTrack->priority = track->priority;
-		fadeTrack->dataOffset = track->dataOffset;
-		fadeTrack->regionOffset = track->regionOffset;
-		fadeTrack->curRegion = track->curRegion;
-		fadeTrack->curHookId = track->curHookId;
-		fadeTrack->iteration = track->iteration;
-		fadeTrack->mixerFlags = track->mixerFlags;
-		fadeTrack->mixerVol = track->mixerVol;
-		fadeTrack->mixerPan = track->mixerPan;
-		fadeTrack->toBeRemoved = track->toBeRemoved;
-		fadeTrack->readyToRemove = track->readyToRemove;
-		fadeTrack->started = track->started;
-		strcpy(fadeTrack->soundName, track->soundName);
-		fadeTrack->soundHandle = _sound->cloneSound(track->soundHandle);
-		assert(fadeTrack->soundHandle);
-		fadeTrack->volFadeDelay = fadeDelay;
-		fadeTrack->volFadeDest = 0;
-		fadeTrack->volFadeStep = (fadeTrack->volFadeDest - fadeTrack->vol) * 60 * (1000 / _callbackFps) / (1000 * fadeDelay);
-		fadeTrack->volFadeUsed = true;
-		fadeTrack->panFadeDelay = 0;
-		fadeTrack->panFadeDest = 0;
-		fadeTrack->panFadeStep = 0;
-		fadeTrack->panFadeUsed = false;
+Track *Imuse::cloneToFadeOutTrack(Track *track, int fadeDelay) {
+	assert(track);
+	Track *fadeTrack;
+
+	if (track->toBeRemoved) {
+		error("cloneToFadeOutTrack: Tried to clone a track to be removed, please bug report");
+		return NULL;
 	}
 
-	// setup 1 second stream wrapped buffer
-	int32 streamBufferSize = fadeTrack->iteration;
-	fadeTrack->stream = makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundHandle), fadeTrack->mixerFlags, streamBufferSize);
-	g_mixer->playInputStream(&fadeTrack->handle, fadeTrack->stream, false, -1, fadeTrack->vol / 1000, fadeTrack->pan, false);
-	fadeTrack->started = true;
+	assert(track->trackId < MAX_IMUSE_TRACKS);
+	fadeTrack = _track[track->trackId + MAX_IMUSE_TRACKS];
+
+	if (fadeTrack->used) {
+		flushTrack(fadeTrack);
+		g_mixer->stopHandle(fadeTrack->handle);
+	}
+
+	// Clone the settings of the given track
+	memcpy(fadeTrack, track, sizeof(Track));
+	fadeTrack->trackId = track->trackId + MAX_IMUSE_TRACKS;
+
+	// Clone the sound.
+	// leaving bug number for now #1635361
+	ImuseSndMgr::SoundDesc *soundDesc = _sound->cloneSound(track->soundDesc);
+	assert(soundDesc);
+	track->soundDesc = soundDesc;
+
+	// Set the volume fading parameters to indicate a fade out
+	fadeTrack->volFadeDelay = fadeDelay;
+	fadeTrack->volFadeDest = 0;
+	fadeTrack->volFadeStep = (fadeTrack->volFadeDest - fadeTrack->vol) * 60 * (1000 / _callbackFps) / (1000 * fadeDelay);
+	fadeTrack->volFadeUsed = true;
+
+	// Create an appendable output buffer
+	fadeTrack->stream = Audio::makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundDesc), makeMixerFlags(fadeTrack->mixerFlags));
+	g_mixer->playInputStream(track->getType(), &fadeTrack->handle, fadeTrack->stream, -1, fadeTrack->getVol(), fadeTrack->getPan());
 	fadeTrack->used = true;
 
 	return fadeTrack;

Added: residual/trunk/engine/imuse/imuse_track.h
===================================================================
--- residual/trunk/engine/imuse/imuse_track.h	                        (rev 0)
+++ residual/trunk/engine/imuse/imuse_track.h	2008-03-10 23:06:07 UTC (rev 31101)
@@ -0,0 +1,98 @@
+/* Residual - Virtual machine to run LucasArts' 3D adventure games
+ * Copyright (C) 2003-2006 The ScummVM-Residual Team (www.scummvm.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library 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
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef IMUSE_TRACK_H
+#define IMUSE_TRACK_H
+
+#include "common/sys.h"
+#include "common/platform.h"
+#include "common/debug.h"
+
+#include "engine/lua.h"
+
+#include "mixer/mixer.h"
+#include "mixer/audiostream.h"
+
+#include "engine/imuse/imuse_sndmgr.h"
+#include "engine/imuse/imuse_mcmp_mgr.h"
+
+enum {
+	kFlagUnsigned = 1 << 0,
+	kFlag16Bits = 1 << 1,
+	kFlagLittleEndian = 1 << 2,
+	kFlagStereo = 1 << 3,
+	kFlagReverseStereo = 1 << 4
+};
+
+struct Track {
+	int trackId;
+
+	int32 pan;
+	int32 panFadeDest;
+	int32 panFadeStep;
+	int32 panFadeDelay;
+	bool panFadeUsed;
+	int32 vol;
+	int32 volFadeDest;
+	int32 volFadeStep;
+	int32 volFadeDelay;
+	bool volFadeUsed;
+
+	char soundName[32];
+	bool used;
+	bool toBeRemoved;
+	int32 priority;
+	int32 regionOffset;
+	int32 dataOffset;
+	int32 curRegion;
+	int32 curHookId;
+	int32 volGroupId;
+	int32 feedSize;
+	int32 mixerFlags;
+
+	ImuseSndMgr::SoundDesc *soundDesc;
+	Audio::SoundHandle handle;
+	Audio::AppendableAudioStream *stream;
+
+	Track() : used(false), stream(NULL) {
+		soundName[0] = 0;
+	}
+
+	int getPan() const { return (pan != 6400) ? 2 * (pan / 1000) - 127 : 0; }
+	int getVol() const { return vol / 1000; }
+	Audio::Mixer::SoundType getType() const {
+		Audio::Mixer::SoundType type = Audio::Mixer::kPlainSoundType;
+		if (volGroupId == IMUSE_VOLGRP_VOICE)
+			type = Audio::Mixer::kSpeechSoundType;
+		else if (volGroupId == IMUSE_VOLGRP_SFX)
+			type = Audio::Mixer::kSFXSoundType;
+		else if (volGroupId == IMUSE_VOLGRP_MUSIC)
+			type = Audio::Mixer::kMusicSoundType;
+		else if (volGroupId == IMUSE_VOLGRP_BGND)
+			type = Audio::Mixer::kPlainSoundType;
+		else if (volGroupId == IMUSE_VOLGRP_ACTION)
+			type = Audio::Mixer::kPlainSoundType;
+		return type;
+	}
+};
+
+#endif


Property changes on: residual/trunk/engine/imuse/imuse_track.h
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + Date Rev Author URL Id
Name: svn:eol-style
   + native

Modified: residual/trunk/engine/lua.cpp
===================================================================
--- residual/trunk/engine/lua.cpp	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/lua.cpp	2008-03-10 23:06:07 UTC (rev 31101)
@@ -42,6 +42,8 @@
 
 #include "engine/imuse/imuse.h"
 
+#include "mixer/mixer.h"
+
 #include <cstdio>
 #include <cmath>
 #include <zlib.h>
@@ -1880,7 +1882,7 @@
 	group = check_int(3);
 	
 	// Start the sound with the appropriate settings
-	if (g_imuse->startSound(soundName, group, 0, 127, 0, priority)) {
+	if (g_imuse->startSound(soundName, group, 0, 127, 0, priority, NULL)) {
 		lua_pushstring(soundName);
 	} else {
 		// Allow soft failing when loading sounds, hard failing when not
@@ -1929,32 +1931,32 @@
 
 static void ImSetMusicVol() {
 	DEBUG_FUNCTION();
-	g_imuse->setGroupMusicVolume(check_int(1));
+	g_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, check_int(1));
 }
 
 static void ImGetMusicVol() {
 	DEBUG_FUNCTION();
-	lua_pushnumber(g_imuse->getGroupMusicVolume());
+	lua_pushnumber(g_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType));
 }
 
 static void ImSetVoiceVol() {
 	DEBUG_FUNCTION();
-	g_imuse->setGroupVoiceVolume(check_int(1));
+	g_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, check_int(1));
 }
 
 static void ImGetVoiceVol() {
 	DEBUG_FUNCTION();
-	lua_pushnumber(g_imuse->getGroupVoiceVolume());
+	lua_pushnumber(g_mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType));
 }
 
 static void ImSetSfxVol() {
 	DEBUG_FUNCTION();
-	g_imuse->setGroupSfxVolume(check_int(1));
+	g_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, check_int(1));
 }
 
 static void ImGetSfxVol() {
 	DEBUG_FUNCTION();
-	lua_pushnumber(g_imuse->getGroupSfxVolume());
+	lua_pushnumber(g_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType));
 }
 
 static void ImSetParam() {
@@ -2961,7 +2963,7 @@
 	filename = luaL_check_string(1);
 	SaveGame *savedState = new SaveGame(filename, false);
 	dataSize = savedState->beginSection('SIMG');
-	data = (char *)malloc(dataSize);
+	data = new char[dataSize];
 	savedState->read(data, dataSize);
 	screenshot = new Bitmap(data, width, height, "screenshot");
 	if (screenshot) {

Modified: residual/trunk/engine/main.cpp
===================================================================
--- residual/trunk/engine/main.cpp	2008-03-10 23:04:55 UTC (rev 31100)
+++ residual/trunk/engine/main.cpp	2008-03-10 23:06:07 UTC (rev 31101)
@@ -58,6 +58,8 @@
 
 static bool g_lua_initialized = false;
 Driver *g_driver = NULL;
+DefaultTimerManager *g_timer = NULL;
+Audio::Mixer *g_mixer = NULL;
 
 static bool parseBoolStr(const char *val) {
 	if (val == NULL || val[0] == 0)
@@ -168,12 +170,18 @@
 		g_driver = new DriverTinyGL(640, 480, 16, fullscreen);
 	else

@@ Diff output truncated at 100000 characters. @@

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list