Import Haptic Metronome
authorThomas Pietrzak <thomas.pietrzak@gmail.com>
Wed, 30 Mar 2011 14:24:34 +0000 (14:24 +0000)
committerThomas Pietrzak <thomas.pietrzak@gmail.com>
Wed, 30 Mar 2011 14:24:34 +0000 (14:24 +0000)
git-svn-id: svn+ssh://thomaspietrzak.com/var/svn/rep@2 47cf9a05-e0a8-4ed5-9e9b-101a649bc004

30 files changed:
Makefile [new file with mode: 0644]
include/Config.hpp [new file with mode: 0644]
include/List.hpp [new file with mode: 0644]
include/MIDIReader.hpp [new file with mode: 0644]
include/Mixer.hpp [new file with mode: 0644]
include/Pair.hpp [new file with mode: 0644]
include/PrefixTree.hpp [new file with mode: 0644]
include/String.hpp [new file with mode: 0644]
include/Texture.hpp [new file with mode: 0644]
include/Tools.hpp [new file with mode: 0644]
include/Track.hpp [new file with mode: 0644]
include/Triplet.hpp [new file with mode: 0644]
include/Vector2D.hpp [new file with mode: 0644]
include/Vector3D.hpp [new file with mode: 0644]
include/Wiimote.hpp [new file with mode: 0644]
src/Config.cpp [new file with mode: 0644]
src/List.cpp [new file with mode: 0644]
src/MIDIReader.cpp [new file with mode: 0644]
src/Mixer.cpp [new file with mode: 0644]
src/Pair.cpp [new file with mode: 0644]
src/PrefixTree.cpp [new file with mode: 0644]
src/String.cpp [new file with mode: 0644]
src/Texture.cpp [new file with mode: 0644]
src/Tools.cpp [new file with mode: 0644]
src/Track.cpp [new file with mode: 0644]
src/Triplet.cpp [new file with mode: 0644]
src/Vector2D.cpp [new file with mode: 0644]
src/Vector3D.cpp [new file with mode: 0644]
src/Wiimote.cpp [new file with mode: 0644]
src/main.cpp [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..aebf76f
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,54 @@
+COMP = g++
+RM = rm -f
+# VERSION = 3
+OBJS = obj/main.o obj/MIDIReader.o obj/Config.o obj/Track.o obj/Texture.o obj/Vector2D.o obj/Vector3D.o obj/String.o obj/Pair.o obj/Triplet.o obj/Tools.o obj/Mixer.o obj/List.o obj/PrefixTree.o obj/Wiimote.o
+#-lefence
+#-lSDL -lSDL_image -lGL -lGLU -lusb
+# -lefence
+# export EF_ALLOW_MALLOC_0=1
+FLAGS = -Wall -pg -DDEBUG
+LIBS = -lSDL -lSDL_image -lSDL_mixer -lGL -lGLU -lGLEW -lwiiuse
+CFLAGS = $(FLAGS) -Iinclude/
+TARGET = bin/hapticmetronome
+TAR = hapticmetronome
+REPARCHIVE = hapticmetronome
+
+all :$(TARGET)
+
+$(TARGET) : $(OBJS)
+       $(COMP) $(CFLAGS) -o $@ $^ $(LIBS)
+
+clean :
+       $(RM) $(OBJS)
+
+mrproper :
+       $(RM) $(OBJS) $(TARGET) $(TARGETDEMO)
+
+tar: 
+       mkdir $(REPARCHIVE)
+       mkdir $(REPARCHIVE)/src
+       mkdir $(REPARCHIVE)/include
+       mkdir $(REPARCHIVE)/data
+       mkdir $(REPARCHIVE)/bin
+       cp Makefile* $(REPARCHIVE)/
+       cp data/*.ttf $(REPARCHIVE)/data
+       cp data/shapes* $(REPARCHIVE)/data
+       cp data/params $(REPARCHIVE)/data
+       cp $(TARGET) $(REPARCHIVE)/bin
+       cp $(TARGET).exe $(REPARCHIVE)/bin
+       cp src/*.c $(REPARCHIVE)/src
+       cp include/*.h $(REPARCHIVE)/include
+       tar -cvzf $(TAR).tar.gz $(REPARCHIVE)
+       rm -rf $(REPARCHIVE)
+
+#obj/shapes.o : src/shapes.c
+#      $(COMP) $(CFLAGS) -o $@ -c $<
+
+obj/%.o : src/%.c include/%.h
+       $(COMP) $(CFLAGS) -o $@ -c $<
+
+obj/%.o : src/%.cpp include/%.hpp
+       $(COMP) $(CFLAGS) -o $@ -c $<
+
+obj/%.o : src/%.cpp
+       $(COMP) $(CFLAGS) -o $@ -c $<
diff --git a/include/Config.hpp b/include/Config.hpp
new file mode 100644 (file)
index 0000000..9c6cd6c
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef __CONFIG__
+#define __CONFIG__
+
+enum keys { KEY0 = 0, KEY1 = 1, KEY2 = 2, KEY3 = 3, KEY4 = 4 };
+
+#define COLOR_GREEN  0.0f,1.0f,0.0f
+#define COLOR_RED    1.0f,0.0f,0.0f
+#define COLOR_YELLOW 1.0f,1.0f,0.0f
+#define COLOR_BLUE   0.0f,0.0f,1.0f
+#define COLOR_ORANGE 1.0f,0.5f,0.0f
+// #define SECONDSIZE 3.0
+#define NOTESIZE 1.5
+#define LONGSIZE 0.5
+
+#define NECKWIDTH 12
+#define NOTEDIST 5
+
+void drawCube(double pos, double size, double colorx, double colory, double colorz);
+void drawLong(double pos, double size, double length, double colorx, double colory, double colorz);
+
+#include <GL/glew.h>
+#include <iostream>
+using namespace std;
+
+#include "String.hpp"
+#include "Tools.hpp"
+
+class Config
+{
+       public:
+               Config(double position=0, double end=0, uint32 time=0, uint32 ticks=0,bool a=false, bool b=false, bool c=false, bool d=false, bool e=false)
+               :_position(position), _end(end), _time(time), _ticks(ticks), _a(a), _b(b), _c(c), _d(d), _e(e){}
+
+               Config(const Config &cf):_position(cf._position), _end(cf._end), _time(cf._time), _ticks(cf._ticks), _a(cf._a), _b(cf._b), _c(cf._c), _d(cf._d), _e(cf._e){}
+               ~Config(){}
+
+               void addKey(keys k);
+               void remKey(keys k);
+               void setKeys(bool a, bool b, bool c, bool d, bool e);
+
+               void setPosition(double p) { _position = p; }
+               double getPosition() const { return _position; }
+
+               void setEnd(double d) { _end = d; }
+               double getEnd() const { return _end; }
+
+               void setTime(uint32 t) { _time = t; }
+               uint32 getTime() const { return _time; }
+
+               void setTicks(uint32 t) { _ticks = t; }
+               uint32 getTicks() const { return _ticks; }
+
+               void display() const;
+               void log(const String &type, FILE *file) const;
+
+               Config &operator =(const Config&cfg);
+
+               friend ostream& operator <<(ostream &os,const Config &c);
+
+               bool isNone() const { return !(_a || _b || _c || _d || _e ); }
+
+       private:
+               double _position, _end;
+               uint32 _time, _ticks;
+               bool _a, _b, _c, _d, _e;
+};
+
+#endif
diff --git a/include/List.hpp b/include/List.hpp
new file mode 100644 (file)
index 0000000..ce9557a
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef __LIST__
+#define __LIST__
+
+#include <iostream>
+using namespace std;
+
+template <class T> class List;
+
+template <class T> List<T> &operator+(const T &elt, List<T> &l);
+template <class T> ostream &operator << (ostream &os, const List<T> &l);
+
+
+template <class T>
+class List
+{
+  public:
+    struct Node
+    {
+      T key;
+      Node *next, *previous;
+      Node(const T &elt, Node *n, Node *p)
+      :key(elt), next(n), previous(p)
+      {}
+    };
+    class ListIterator
+    {
+      public:
+        ListIterator(List &l): _list(&l), _current(&(l.head)) {};
+        ListIterator(List &l, bool): _list(&l), _current(&(l.tail)) {};
+        void operator++ (int) { if (_current && *_current) _current = &((*_current)->next); }
+        void operator-- (int) { if (_current && *_current) _current = &((*_current)->previous); }
+        bool end() const { return *_current == NULL; }
+        bool beforeEnd() const { return (*_current == NULL || (*_current)->next == NULL); }
+        bool afterEnd() const { return (*_current == NULL || (*_current)->previous == NULL); }
+        T &elt() { return (*_current)->key; }
+        //TODO: test
+        void add(const T &element)
+        {
+          if (_current)
+          {
+            if (*_current)
+            {
+              *_current = new Node(element, *_current, (*_current)->previous);
+              (*_current)->next->previous = *_current;
+            }
+            else
+              *_current = new Node(element, NULL, _list->getTail());
+              _list->setTail(*_current);
+          }
+          else
+            throw "wrong iterator";
+        }
+        //TODO: test
+        void remove()
+        {
+          if (_current)
+          {
+            if (*_current)
+            {
+              Node *tbd = *_current;
+              if ((*_current)->previous)
+                (*_current)->previous->next = (*_current)->next;
+              if ((*_current)->next)
+                (*_current)->next->previous = (*_current)->previous;
+              delete tbd;
+            }
+            else
+              throw "end of list";
+          }
+          else
+            throw "wrong iterator";
+        }
+        //void displayDebug() { if (current) cout << " key=" << current->key << " next=" << current->next << " previous=" << current->previous << endl; else cout << " NULL" << endl;}
+      private:
+        ListIterator(): _list(NULL), _current(NULL) {}
+        List *_list;
+        Node **_current;
+    };
+    
+    List();
+    List(const List<T> &l);
+    ~List();
+
+    void empty();
+
+    T &operator [] (const int &i) const;
+
+    unsigned int size() const;
+    bool isEmpty() const;
+
+    Node *getHead() const;
+    void setHead(Node *);
+    Node *getTail() const;
+    void setTail(Node *);
+
+    //put the element specified on the top of the list
+    void onTop(const T&elt);
+    //put the element specified at the bottom of the list
+    void onBottom(const T&elt);
+
+    //remove the element specified
+    List<T> &operator- (const T &elt);
+    //remove the element of position pos in the list
+    List<T> &operator- (const int &pos);
+
+    //add an element at the head
+    friend List<T> &operator+ <>(const T &elt, List<T> &l);
+    //add an element at the tail
+    List<T> &operator+ (const T &elt);
+    List<T> &operator+= (const T &elt);
+    //concatenate two lists
+    List<T> &operator+ (const List<T> &l);
+    List<T> &operator+= (const List<T> &l);
+
+    List<T> &operator= (const List<T> &l);
+
+    friend ostream &operator<< <>(ostream &os, const List<T> &l);
+
+    //friend istream &operator >> (istream & is, const List &l);
+  protected:
+
+    void deleteElt(Node *elt);
+
+    Node *head, *tail;
+};
+
+#include "../src/List.cpp" 
+#endif
diff --git a/include/MIDIReader.hpp b/include/MIDIReader.hpp
new file mode 100644 (file)
index 0000000..a09c8a7
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef __MIDIREADER__
+#define __MIDIREADER__
+
+#include <stdio.h>
+
+#include "Track.hpp"
+#include "String.hpp"
+#include "Tools.hpp"
+
+
+class MIDIReader
+{
+  public:
+    MIDIReader(const String &f);
+    ~MIDIReader();
+
+    void readHeader();
+    void skipTrack();
+    void readTrack(Track &);
+    void readTracks(Track &t);
+  private:
+    MIDIReader();
+    MIDIReader(const MIDIReader &);
+
+    FILE *_file;
+    uint16 _nbtracks;
+    uint16 _timedivision;
+//     unsigned long int _position;
+    uint8 readVariableLength(uint32 &);
+    void readBytes(void *, uint32);
+               void printBytes(uint8 *data, uint32 length);
+    uint32 _position;
+};
+
+#endif
diff --git a/include/Mixer.hpp b/include/Mixer.hpp
new file mode 100644 (file)
index 0000000..7725886
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __MIXER__
+#define __MIXER__
+
+#define MAXSOUNDS 5
+
+#include "String.hpp"
+#include "PrefixTree.hpp"
+#ifdef __APPLE__
+#include <SDL_mixer/SDL_mixer.h>
+#else
+#include <SDL/SDL_mixer.h>
+#endif
+
+class Sound
+{
+  public:
+    Sound();
+    Sound(const String &);
+    ~Sound();
+
+    bool addSound(const String &filename);
+    bool addChunk(Mix_Chunk *c);
+    Mix_Chunk *mix();
+
+    Mix_Chunk *getChunk();
+    
+  private:
+    Sound(const Sound &);
+    int nbrchunks;
+    Mix_Chunk **_chunks;
+};
+
+class Mixer
+{
+  public:
+    Mixer();
+    ~Mixer();
+    static void playMusic(const String &);
+    static void stopMusic();
+    void playSound(const String &);
+    void stopSound(const int &);
+    bool addSound(const String &s, const String &filename);
+    static void channelStopped(int);
+               int getMusicVolume() const { return _musicVolume; }
+    void setMusicVolume(const int &);
+               int getSoundVolume() const { return _soundVolume; }
+    void setSoundVolume(const int &);
+  
+    static void initMixer();
+
+    static Mixer *getInstance()
+    {
+      if (!_minstance) 
+      {
+        _minstance = new Mixer();
+        initMixer();
+      }
+
+      return _minstance;
+    }
+
+  private:
+    Mixer(const Mixer &);
+    PrefixTree<Sound *> _sounds;
+    static Mix_Music *_music;
+    static int *_soundChannels;
+
+    int _musicVolume, _soundVolume;
+
+    static Mixer *_minstance;
+};
+
+#endif
diff --git a/include/Pair.hpp b/include/Pair.hpp
new file mode 100644 (file)
index 0000000..d5e5962
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef __PAIR__
+#define __PAIR__
+
+#include <iostream>
+using namespace std;
+
+template <class T, class U> class Pair;
+
+template <class T, class U> Pair<T, U> operator + (const Pair<T, U> &p1, const Pair<T, U> &p2);
+template <class T, class U> Pair<T, U> operator + (const T &a, const Pair<T, U> &p);
+template <class T, class U> Pair<T, U> operator + (const Pair<T, U> &p1, const U &a);
+template <class T, class U> Pair<T, U> operator - (const Pair<T, U> &p1, const Pair<T, U> &p2);
+template <class T, class U> Pair<T, U> operator - (const T &a, const Pair<T, U> &p);
+template <class T, class U> Pair<T, U> operator - (const Pair<T, U> &p1, const U &a);
+template <class T, class U> Pair<T, U> operator * (const Pair<T, U> &p1, const Pair<T, U> &p2);
+template <class T, class U> Pair<T, U> operator * (const T &a, const Pair<T, U> &p);
+template <class T, class U> Pair<T, U> operator * (const Pair<T, U> &p1, const U &a);
+template <class T, class U> Pair<T, U> operator / (const Pair<T, U> &p1, const Pair<T, U> &p2);
+template <class T, class U> Pair<T, U> operator / (const T &a, const Pair <T, U>&p);
+template <class T, class U> Pair<T, U> operator / (const Pair<T, U> &p1, const U &a);
+template <class T, class U> ostream &operator << (ostream &os, const Pair<T, U> &s);
+
+template <class T, class U>
+class Pair
+{
+  public:
+    inline Pair(const T &x=0, const U &y=0);
+    inline Pair(const Pair &p);
+    inline ~Pair();
+
+    const T &getX() const;
+    const U &getY() const;
+    void setX(const T &x);
+    void setY(const U &y);
+
+    inline const Pair & operator = (const Pair &s);
+    bool operator == (const Pair &s) const;
+
+    friend Pair operator + <>(const Pair &p1, const Pair &p2);
+    friend Pair operator + <>(const T &a, const Pair &p);
+    friend Pair operator + <>(const Pair &p1, const U &a);
+    friend Pair operator - <>(const Pair &p1, const Pair &p2);
+    friend Pair operator - <>(const T &a, const Pair &p);
+    friend Pair operator - <>(const Pair &p1, const U &a);
+    Pair operator - (void);
+    friend Pair operator * <>(const Pair &p1, const Pair &p2);
+    friend Pair operator * <>(const T &a, const Pair &p);
+    friend Pair operator * <>(const Pair &p1, const U &a);
+    friend Pair operator / <>(const Pair &p1, const Pair &p2);
+    friend Pair operator / <>(const T &a, const Pair &p);
+    friend Pair operator / <>(const Pair &p1, const U &a);
+    
+    friend ostream &operator << <>(ostream &os, const Pair &s);
+
+  protected:
+    T px;
+    U py;
+};
+
+#include "../src/Pair.cpp"
+
+#endif
diff --git a/include/PrefixTree.hpp b/include/PrefixTree.hpp
new file mode 100644 (file)
index 0000000..5094bc1
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef __PREFIXTREE__
+#define __PREFIXTREE__
+
+#include <iostream>
+using namespace std;
+
+#include "String.hpp"
+#include "List.hpp"
+#include "Pair.hpp"
+
+template <class T>
+class PrefixTree;
+
+template <class T>
+ostream &operator << (ostream &os, const PrefixTree<T> &t);
+
+template <class T>
+class PrefixTree
+{
+  public:
+    struct TNode
+    {
+      bool haskey;
+      T key;
+      String prefix;
+      TNode *son, *brotherleft, *brotherright, *father;
+      TNode();
+      TNode(const T &elt, const String &pref, TNode *son, TNode *brotherleft, TNode *brotherright, TNode *father);
+      TNode(const String &pref, TNode *son, TNode *brotherleft, TNode *brotherright, TNode *father);
+
+      ~TNode();
+
+      void insertInsideNode(const String &pref, const T &elt, const unsigned int &posword, const unsigned int &posnode);
+      
+      String searchInsideNode(const String &pref, const unsigned int &posword, const unsigned int &posnode) const;
+
+      bool nodeExists(const String &n, const unsigned int &posword, const unsigned int &posnode) const;
+
+      const T &getNode(const String &n, const unsigned int &posword, const unsigned int &posnode) const;
+
+      TNode *nextNode();
+
+      String wholePrefix() const;
+
+      ostream &display(ostream &os);
+    };
+    class PrefixTreeIterator
+    {
+      public:
+        PrefixTreeIterator(PrefixTree &t):pt(&t), current(t.root){}
+        void operator++(int)
+        {
+          do
+          {
+            current = current->nextNode();
+          }while (current && ! current->haskey);
+        }
+        bool end() const { return current == NULL; }
+        Pair<String, T> elt()
+        {
+          if (current->haskey)
+            return Pair<String, T>(current->wholePrefix(), current->key);
+          else
+            throw "No key";
+          //should not happen
+          return Pair<String, T>();
+        }
+      private:
+        PrefixTree *pt;
+        TNode *current;
+    };
+
+    PrefixTree();
+    PrefixTree(const PrefixTree &pt);
+    virtual ~PrefixTree();
+
+    void addNode(const String &pref, const T&elt);
+    void remNode(const T &elt);
+    bool searchNode(const String &n);
+
+    TNode * getRoot();
+
+    //currently we dont allow to modify elements like this
+    //inline T &operator[](const String &key);
+    inline const T &operator[](const String &key) const;
+
+    List<String> sonsList(const String &pref) const;
+    String completePrefix(const String &pref) const;
+
+    friend ostream &operator<< <>(ostream &os, const PrefixTree<T> &n);
+
+  protected:
+    TNode *root;
+};
+
+class ExceptionNodeDontExist
+{
+  public:
+    ExceptionNodeDontExist(const String &s="")
+    :name(s)
+    {}
+    
+    ExceptionNodeDontExist(const ExceptionNodeDontExist &e)
+    :name(e.name)
+    {}
+    
+    ~ExceptionNodeDontExist()
+    {}
+    
+    String getName() const
+    {
+      return name;
+    }
+    
+  private:
+    String name;
+};
+
+// template <class T>
+// ostream &operator << (ostream &os, const typename PrefixTree<T>::TNode &n)
+// {
+//   if (n.key)
+//     os << "[" << *(n.key) << "]";
+//   else
+//     os << "X";
+//   os << " " << n.prefix << " ";
+//   if (n.son)
+//     os << " (" << *(n.son) << ")";
+//   if (n.brother)
+//     os << " {" << *(n.brother) << "}";
+//   return os;
+// }
+
+
+// template <class T>
+// ostream &operator<< <>(ostream &os, const  typename PrefixTree<T>::TNode &n);
+
+#include "../src/PrefixTree.cpp"
+#endif
diff --git a/include/String.hpp b/include/String.hpp
new file mode 100644 (file)
index 0000000..024eb3a
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef __MYSTRING__
+#define __MYSTRING__
+
+#include <string>
+#include <iostream>
+using namespace std;
+
+class String
+{
+  public:
+    String(const String &s);
+    String(const int &a);
+    String(const double &a);
+    String(const char *s="");
+    String(const char &c);
+    ~String();
+
+    unsigned int length() const;
+    void concat(const String &s);
+    //find
+
+    const char *c_str() const;
+
+    const String & operator = (const String &s);
+    bool operator == (const String &s) const;
+    bool operator != (const String &s) const;
+
+    //returns the character i
+    char &operator [] (const int &i) const;
+    //returns the substring at pos i, and of length j
+    String operator () (const unsigned int &i, const unsigned int &j) const;
+
+    friend String operator + (const String &s1, const String &s2);
+    friend ostream &operator << (ostream &os, const String &s);
+    //friend istream &operator >> (istream & is, const String &s);
+
+  private:
+    char *string;
+};
+
+#endif
diff --git a/include/Texture.hpp b/include/Texture.hpp
new file mode 100644 (file)
index 0000000..ee7058a
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef __TEXTURE__
+#define __TEXTURE__
+
+#include <GL/glew.h>
+#include <SDL/SDL.h>
+// #include <SDL/SDL_opengl.h>
+
+#include "String.hpp"
+#include "Vector2D.hpp"
+
+class Texture
+{
+  public:
+    Texture(const String &filename, const bool &repeat=false);
+    ~Texture();
+
+    void useTexture() const;
+    bool isLoaded() const;
+    Vector2D<int> getSize() const;
+
+  private:
+    SDL_Surface *surface;
+    unsigned int gltex;
+    GLuint texture;
+    Vector2D<int> size;
+    bool repeat;
+};
+
+#endif
diff --git a/include/Tools.hpp b/include/Tools.hpp
new file mode 100644 (file)
index 0000000..b5e55bb
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef __MYTOOLS__
+#define __MYTOOLS__
+
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+
+#include "String.hpp"
+#include "Vector2D.hpp"
+#include <cmath>
+
+#define MAX(X,Y) (X)>(Y)?(X):(Y)
+#define MIN(X,Y) (X)<(Y)?(X):(Y)
+
+bool fileExists(const String &f);
+bool dirExists(const String &d);
+Vector2D<int> rotatePoint(const Vector2D<int> pos, const Vector2D<int> center, const double &angle);
+
+template<class T>T maxi(const T&a, const T&b)
+{
+  if (a>b)
+    return a;
+  else
+    return b;
+}
+
+template<class T>T mini(const T&a, const T&b)
+{
+  if (a<b)
+    return a;
+  else
+    return b;
+}
+
+double mod2pi(const double &a);
+
+#endif
diff --git a/include/Track.hpp b/include/Track.hpp
new file mode 100644 (file)
index 0000000..d9af107
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef __TRACK__
+#define __TRACK__
+
+#define NBDIFFICULTIES 4
+
+enum difficulties { EASY, NORMAL, HARD, EXPERT };
+
+#include <list>
+#include <map>
+/*#include <iostream>
+using namespace std;
+*/
+#include "Config.hpp"
+#include "Tools.hpp"
+
+class Track
+{
+  public:
+    Track();
+    Track(const Track &);
+    ~Track();
+
+    void addKey(uint32 time, uint8 note);
+    void remKey(uint32 time, uint8 note);
+
+    void addTempo(uint32 pos, uint32 t) { _tempo[pos] = t; }
+    
+//     int getTempo() const { return _currenttempo; }
+    
+//     void setTempo(uint32 t) { _currenttempo = t; }
+    
+//     uint32 beatsToTicks(uint32 time) { return (time * _currenttempo * 480) / 60000.0; }
+    uint32 beatsToTicks(uint32 time, uint32 tempo) { return (time * tempo * 480) / 60000.0; }
+    uint32 ticksToBeats(uint32 time) { return 60000000 / time; }
+
+    void displayTracks();
+               void drawFrets(double postime) const;
+               void drawNotes(double postime, uint8 diff) const;
+
+    uint32 getNbNotes(uint32 k) const { return _nbnotes[k]; }
+    uint32 getTotalLength(uint32 k) const { return _totallength[k]; }
+    uint32 getTotalNotes(uint32 k) const { return _totalnotes[k]; }
+
+               void setEndOfTrack(uint32 length) { if (length > _trackSize) _trackSize = length; }
+               uint32 getEndOfTrack() const { return _trackSize; }
+
+               Config getNote(uint32 pos, uint8 difficulty);
+               uint32 getTempo(uint32 pos);
+
+               void computeBips();
+
+    void debugTempo();
+
+   private:
+    //notes : position ; configs
+    map<uint32, Config> _notes[NBDIFFICULTIES];
+    map<uint32, uint32> _tempo;
+
+//  private:
+               list<double> _bips;
+    
+    Config _currentconfig[NBDIFFICULTIES];
+    
+    uint32 _nbnotes[NBDIFFICULTIES];
+    uint32 _totallength[NBDIFFICULTIES];
+    uint32 _totalnotes[128];
+               uint32 _trackSize;
+    bool _active;
+};
+
+#endif
diff --git a/include/Triplet.hpp b/include/Triplet.hpp
new file mode 100644 (file)
index 0000000..fbb0678
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef __TRIPLET__
+#define __TRIPLET__
+
+#include <iostream>
+using namespace std;
+
+template <class T, class U, class V> class Triplet;
+
+template <class T, class U, class V> Triplet<T, U, V> operator + (const Triplet<T, U, V> &p1, const Triplet<T, U, V> &p2);
+template <class T, class U, class V> Triplet<T, U, V> operator + (const T &a, const Triplet<T, U, V> &p);
+template <class T, class U, class V> Triplet<T, U, V> operator + (const Triplet<T, U, V> &p1, const U &a);
+template <class T, class U, class V> Triplet<T, U, V> operator - (const Triplet<T, U, V> &p1, const Triplet<T, U, V> &p2);
+template <class T, class U, class V> Triplet<T, U, V> operator - (const T &a, const Triplet<T, U, V> &p);
+template <class T, class U, class V> Triplet<T, U, V> operator - (const Triplet<T, U, V> &p1, const U &a);
+template <class T, class U, class V> Triplet<T, U, V> operator * (const Triplet<T, U, V> &p1, const Triplet<T, U, V> &p2);
+template <class T, class U, class V> Triplet<T, U, V> operator * (const T &a, const Triplet<T, U, V> &p);
+template <class T, class U, class V> Triplet<T, U, V> operator * (const Triplet<T, U, V> &p1, const U &a);
+template <class T, class U, class V> Triplet<T, U, V> operator / (const Triplet<T, U, V> &p1, const Triplet<T, U, V> &p2);
+template <class T, class U, class V> Triplet<T, U, V> operator / (const T &a, const Triplet <T, U, V>&p);
+template <class T, class U, class V> Triplet<T, U, V> operator / (const Triplet<T, U, V> &p1, const U &a);
+template <class T, class U, class V> ostream &operator << (ostream &os, const Triplet<T, U, V> &s);
+
+template <class T, class U, class V>
+class Triplet
+{
+  public:
+    inline Triplet(const T &x=0, const U &y=0, const V &z=0);
+    inline Triplet(const Triplet &p);
+    inline ~Triplet();
+
+    const T &getX() const;
+    const U &getY() const;
+    const V &getZ() const;
+    void setX(const T &x);
+    void setY(const U &y);
+    void setZ(const V &z);
+
+    inline const Triplet & operator = (const Triplet &s);
+    bool operator == (const Triplet &s) const;
+
+    friend Triplet operator + <>(const Triplet &p1, const Triplet &p2);
+    friend Triplet operator + <>(const T &a, const Triplet &p);
+    friend Triplet operator + <>(const Triplet &p1, const U &a);
+    friend Triplet operator - <>(const Triplet &p1, const Triplet &p2);
+    friend Triplet operator - <>(const T &a, const Triplet &p);
+    friend Triplet operator - <>(const Triplet &p1, const U &a);
+    Triplet operator - (void);
+    friend Triplet operator * <>(const Triplet &p1, const Triplet &p2);
+    friend Triplet operator * <>(const T &a, const Triplet &p);
+    friend Triplet operator * <>(const Triplet &p1, const U &a);
+    friend Triplet operator / <>(const Triplet &p1, const Triplet &p2);
+    friend Triplet operator / <>(const T &a, const Triplet &p);
+    friend Triplet operator / <>(const Triplet &p1, const U &a);
+    
+    friend ostream &operator << <>(ostream &os, const Triplet &s);
+
+  protected:
+    T px;
+    U py;
+    V pz;
+};
+
+#include "../src/Triplet.cpp"
+
+#endif
diff --git a/include/Vector2D.hpp b/include/Vector2D.hpp
new file mode 100644 (file)
index 0000000..8ac544c
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef __VECTOR2D__
+#define __VECTOR2D__
+
+#include "Pair.hpp"
+/*
+#include <iostream>
+using namespace std;*/
+
+template <class T> class Vector2D;
+
+template <class T> Vector2D<T> operator + (const Vector2D<T> &p1, const Vector2D<T> &p2);
+template <class T> Vector2D<T> operator + (const T &a, const Vector2D<T> &p);
+template <class T> Vector2D<T> operator + (const Vector2D<T> &p1, const T &a);
+template <class T> Vector2D<T> operator - (const Vector2D<T> &p1, const Vector2D<T> &p2);
+template <class T> Vector2D<T> operator - (const T &a, const Vector2D<T> &p);
+template <class T> Vector2D<T> operator - (const Vector2D<T> &p1, const T &a);
+template <class T> Vector2D<T> operator * (const Vector2D<T> &p1, const Vector2D<T> &p2);
+template <class T> Vector2D<T> operator * (const T &a, const Vector2D<T> &p);
+template <class T> Vector2D<T> operator * (const Vector2D<T> &p1, const T &a);
+template <class T> Vector2D<T> operator / (const Vector2D<T> &p1, const Vector2D<T> &p2);
+template <class T> Vector2D<T> operator / (const T &a, const Vector2D <T>&p);
+template <class T> Vector2D<T> operator / (const Vector2D<T> &p1, const T &a);
+// template <class T> ostream &operator << (ostream &os, const Vector2D<T> &s);
+
+enum { C_X=0, C_Y=1, C_Z=2 };
+
+template <class T>
+class Vector2D: public Pair<T, T>
+{
+  public:
+    inline Vector2D(const T &x=0, const T &y=0);
+    inline Vector2D(const Vector2D &p);
+    inline ~Vector2D();
+
+/*
+    T getX() const;
+    T getY() const;
+    void setX(const T &x);
+    void setY(const T &y);*/
+
+    inline T &operator [] (const int &i); 
+    inline const T &operator [] (const int &i) const;
+
+    
+//     const Vector2D & operator = (const Vector2D &s);
+//     bool operator == (const Vector2D &s) const;
+
+    friend Vector2D operator + <>(const Vector2D &p1, const Vector2D &p2);
+    friend Vector2D operator + <>(const T &a, const Vector2D &p);
+    friend Vector2D operator + <>(const Vector2D &p1, const T &a);
+    friend Vector2D operator - <>(const Vector2D &p1, const Vector2D &p2);
+    friend Vector2D operator - <>(const T &a, const Vector2D &p);
+    friend Vector2D operator - <>(const Vector2D &p1, const T &a);
+    Vector2D operator - (void);
+    friend Vector2D operator * <>(const Vector2D &p1, const Vector2D &p2);
+    friend Vector2D operator * <>(const T &a, const Vector2D &p);
+    friend Vector2D operator * <>(const Vector2D &p1, const T &a);
+    friend Vector2D operator / <>(const Vector2D &p1, const Vector2D &p2);
+    friend Vector2D operator / <>(const T &a, const Vector2D &p);
+    friend Vector2D operator / <>(const Vector2D &p1, const T &a);
+//     
+//     friend ostream &operator << <>(ostream &os, const Vector2D &s);
+
+  private:
+//     T px, py;
+};
+
+#include "../src/Vector2D.cpp" 
+
+#include "Vector3D.hpp"
+
+#endif
diff --git a/include/Vector3D.hpp b/include/Vector3D.hpp
new file mode 100644 (file)
index 0000000..b6db366
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef __VECTOR3D__
+#define __VECTOR3D__
+
+#include "Triplet.hpp"
+/*
+#include <iostream>
+using namespace std;*/
+
+template <class T> class Vector3D;
+
+template <class T> Vector3D<T> operator + (const Vector3D<T> &p1, const Vector3D<T> &p2);
+template <class T> Vector3D<T> operator + (const T &a, const Vector3D<T> &p);
+template <class T> Vector3D<T> operator + (const Vector3D<T> &p1, const T &a);
+template <class T> Vector3D<T> operator - (const Vector3D<T> &p1, const Vector3D<T> &p2);
+template <class T> Vector3D<T> operator - (const T &a, const Vector3D<T> &p);
+template <class T> Vector3D<T> operator - (const Vector3D<T> &p1, const T &a);
+template <class T> Vector3D<T> operator * (const Vector3D<T> &p1, const Vector3D<T> &p2);
+template <class T> Vector3D<T> operator * (const T &a, const Vector3D<T> &p);
+template <class T> Vector3D<T> operator * (const Vector3D<T> &p1, const T &a);
+template <class T> Vector3D<T> operator / (const Vector3D<T> &p1, const Vector3D<T> &p2);
+template <class T> Vector3D<T> operator / (const T &a, const Vector3D <T>&p);
+template <class T> Vector3D<T> operator / (const Vector3D<T> &p1, const T &a);
+// template <class T> ostream &operator << (ostream &os, const Vector3D<T> &s);
+
+template <class T>
+class Vector3D: public Triplet<T, T, T>
+{
+  public:
+  // passé en inline pour voir impact sur performance...
+    inline Vector3D(const T &x=0, const T &y=0, const T &z=0); 
+    inline Vector3D(const Vector3D &p);
+    inline ~Vector3D();
+    
+    inline T &operator [] (const int &i);
+    inline const T &operator [] (const int &i) const;
+
+    friend Vector3D operator + <>(const Vector3D &p1, const Vector3D &p2);
+    friend Vector3D operator + <>(const T &a, const Vector3D &p);
+    friend Vector3D operator + <>(const Vector3D &p1, const T &a);
+    friend Vector3D operator - <>(const Vector3D &p1, const Vector3D &p2);
+    friend Vector3D operator - <>(const T &a, const Vector3D &p);
+    friend Vector3D operator - <>(const Vector3D &p1, const T &a);
+    Vector3D operator - (void);
+    friend Vector3D operator * <>(const Vector3D &p1, const Vector3D &p2);
+    friend Vector3D operator * <>(const T &a, const Vector3D &p);
+    friend Vector3D operator * <>(const Vector3D &p1, const T &a);
+    friend Vector3D operator / <>(const Vector3D &p1, const Vector3D &p2);
+    friend Vector3D operator / <>(const T &a, const Vector3D &p);
+    friend Vector3D operator / <>(const Vector3D &p1, const T &a);
+
+  private:
+};
+
+#include "../src/Vector3D.cpp"
+#endif
diff --git a/include/Wiimote.hpp b/include/Wiimote.hpp
new file mode 100644 (file)
index 0000000..0fdc1cb
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef __WIIMOTE__
+#define __WIIMOTE__
+
+#ifndef WIN32
+       #include <unistd.h>
+#endif
+
+#include <wiiuse.h>
+
+
+#define MAX_WIIMOTES 4
+
+class Wiimote{
+       public:
+               Wiimote(int nb=1);
+
+               void handleEvents();
+
+               void vibration(int wiimote, int time);
+
+               virtual void handleStrumOn() = 0;
+               virtual void handleStrumOff() = 0;
+               virtual void handleButtonOn(int k) = 0;
+               virtual void handleButtonOff(int k) = 0;
+               virtual void handleButtons(bool a, bool b, bool c, bool d, bool e) = 0;
+
+       private:
+               void handleKey(guitar_hero_3_t* gh3, int key, int button);
+               wiimote **_wiimotes;
+               int _nb;
+               bool _strumstate, _keystate[5];
+};
+
+#endif
diff --git a/src/Config.cpp b/src/Config.cpp
new file mode 100644 (file)
index 0000000..95e035e
--- /dev/null
@@ -0,0 +1,134 @@
+#include "Config.hpp"
+#include <stdio.h>
+
+void Config::addKey(keys k)
+{
+       switch(k)
+       {
+               case KEY0:
+                       _a = true;
+                       break;
+               case KEY1:
+                       _b = true;
+                       break;
+               case KEY2:
+                       _c = true;
+                       break;
+               case KEY3:
+                       _d = true;
+                       break;
+               case KEY4:
+                       _e = true;
+                       break;
+       }
+}
+
+void Config::remKey(keys k)
+{
+       switch(k)
+       {
+               case KEY0:
+                       _a = false;
+                       break;
+               case KEY1:
+                       _b = false;
+                       break;
+               case KEY2:
+                       _c = false;
+                       break;
+               case KEY3:
+                       _d = false;
+                       break;
+               case KEY4:
+                       _e = false;
+                       break;
+       }
+}
+
+void Config::setKeys(bool a, bool b, bool c, bool d, bool e)
+{
+       _a = a;
+       _b = b;
+       _c = c;
+       _d = d;
+       _e = e;
+}
+
+void Config::display() const
+{
+       if (_ticks > 240)
+       {
+               if (_a)
+                       drawLong(-2*NOTEDIST, LONGSIZE, _end - _position, COLOR_GREEN);
+               if (_b)
+                       drawLong(-NOTEDIST, LONGSIZE, _end - _position, COLOR_RED);
+               if (_c)
+                       drawLong(0, LONGSIZE, _end - _position, COLOR_YELLOW);
+               if (_d)
+                       drawLong(NOTEDIST, LONGSIZE, _end - _position, COLOR_BLUE);
+               if (_e)
+                       drawLong(2*NOTEDIST, LONGSIZE, _end - _position, COLOR_ORANGE);
+       }
+
+       if (_a)
+               drawCube(-2*NOTEDIST, NOTESIZE, COLOR_GREEN);
+       if (_b)
+               drawCube(-NOTEDIST, NOTESIZE, COLOR_RED);
+       if (_c)
+               drawCube(0, NOTESIZE, COLOR_YELLOW);
+       if (_d)
+               drawCube(NOTEDIST, NOTESIZE, COLOR_BLUE);
+       if (_e)
+               drawCube(2*NOTEDIST, NOTESIZE, COLOR_ORANGE);
+}
+
+void Config::log(const String &type, FILE *file) const
+{
+       if (!file)
+               return;
+       fprintf(file, "%s;%d;%d;%d;%d;%d;%f;%f;%d;%d\n", type.c_str(), _a, _b, _c, _d, _e, _position, _end, _time, _ticks);
+}
+
+Config &Config::operator =(const Config&cfg)
+{
+       if (&cfg != this)
+       {
+               _a = cfg._a;
+               _b = cfg._b;
+               _c = cfg._c;
+               _d = cfg._d;
+               _e = cfg._e;
+               _position = cfg._position;
+               _end = cfg._end;
+               _time = cfg._time;
+               _ticks = cfg._ticks;
+       }
+       return *this;
+}
+               
+ostream& operator <<(ostream &os,const Config &c)
+{
+//                      os << c._time << " ";
+       if (c._a)
+               os << "\033[1;32mO\033[0m";
+       else
+               os << "\033[1;32m.\033[0m";
+       if (c._b)
+               os << "\033[0;31mO\033[0m";
+       else
+               os << "\033[0;31m.\033[0m";
+       if (c._c)
+               os << "\033[1;33mO\033[0m";
+       else
+               os << "\033[1;33m.\033[0m";
+       if (c._d)
+               os << "\033[1;34mO\033[0m";
+       else
+               os << "\033[1;34m.\033[0m";
+       if (c._e)
+               os << "\033[0;33mO\033[0m";
+       else
+               os << "\033[0;33m.\033[0m";
+       os << " " << c._position << " " << c._end;
+       return os;
+}
diff --git a/src/List.cpp b/src/List.cpp
new file mode 100644 (file)
index 0000000..4dbc8dc
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * 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.
+ */
+#ifdef __LIST__
+
+template <class T>
+List<T>::List()
+:head(NULL), tail(NULL)
+{
+}
+
+template <class T>
+List<T>::List(const List<T> &l)
+{
+  Node *temp = l.head;
+  head = NULL;
+  tail =  NULL;
+  while(temp)
+  {
+    Node *newnode = new Node(temp->key, NULL, tail);
+    if (!head)
+      head = newnode;
+    if (tail)
+      tail->next = newnode;
+    tail = newnode;
+    temp = temp->next;
+  }
+}
+
+template <class T>
+List<T>::~List()
+{
+  empty();
+}
+
+template <class T>
+void List<T>::empty()
+{
+  Node *temp = head;
+  while(temp)
+  {
+    Node *temp2 = temp;
+    temp = temp->next;
+    delete temp2;
+  }
+  head = NULL;
+  tail = NULL;
+}
+
+template <class T>
+T &List<T>::operator [] (const int &i) const
+{
+  int j;
+  Node *temp = head;
+  for (j = 0 ; j < i && temp ; j++)
+    temp = temp->next;
+  if (j == i)
+    return temp->key;
+  else
+    throw "Index out of range";
+}
+
+template <class T>
+unsigned int List<T>::size() const
+{
+  Node *temp = head;
+  int s=0;
+  while(temp)
+  {
+    s++;
+    temp = temp->next;
+  }
+  return s;
+}
+
+template <class T>
+bool List<T>::isEmpty() const
+{
+  return head == NULL;
+}
+
+template <class T>
+typename List<T>::Node *List<T>::getHead() const
+{
+  return head;
+}
+
+template <class T>
+void List<T>::setHead(typename List<T>::Node *n)
+{
+  head = n;
+}
+
+template <class T>
+typename List<T>::Node *List<T>::getTail()const
+{
+  return tail;
+}
+
+template <class T>
+void List<T>::setTail(typename List<T>::Node *n)
+{
+  tail = n;
+}
+
+template <class T>
+void List<T>::onTop(const T&elt)
+{
+  Node *temp = tail;
+  while(temp && temp != head)
+  {
+    if (temp->key == elt)
+    {
+      if (temp->next)
+        temp->next->previous = temp->previous;
+      if (temp->previous)
+        temp->previous->next = temp->next;
+      if (temp == tail)
+        tail = temp->previous;
+      head->previous = temp;
+      temp->next = head;
+      temp->previous = NULL;
+      head = temp;
+      break;
+    }
+    temp = temp->previous;
+  }
+}
+
+template <class T>
+void  List<T>::onBottom(const T&elt)
+{
+  *this = *this - elt + elt;
+}
+
+template <class T>
+void List<T>::deleteElt(typename List<T>::Node *elt)
+{
+  if (elt->previous)
+    elt->previous->next = elt->next;
+  else
+    head = elt->next;
+  if (elt->next)
+    elt->next->previous = elt->previous;
+  else
+    tail = elt->previous;
+  delete elt;
+}
+
+template <class T>
+List<T> &List<T>::operator- (const T &elt)
+{
+  Node *temp = head;
+  while(temp)
+  {
+    if (temp->key == elt)
+    {
+      deleteElt(temp);
+      return *this;
+    }
+    temp = temp->next;
+  }
+  return *this;
+}
+
+template <class T>
+List<T> &List<T>::operator- (const int &pos)
+{
+  int i;
+  Node *temp = head;
+  for (i = 0 ; i < pos && temp ; i++)
+    temp = temp->next;
+  if (i == pos)
+  {
+    deleteElt(temp);
+    return *this;
+  }
+  else
+    throw "Index out of range";
+}
+
+template <class T>
+List<T> &operator+ (const T &elt, List<T> &l)
+{
+  typename List<T>::Node *newnode = new typename List<T>::Node(elt, l.getHead(), NULL);
+  if (l.isEmpty())
+    l.setTail(newnode);
+  else
+    l.getHead()->previous = newnode;
+  l.setHead(newnode);
+  return l;
+}
+
+template <class T>
+List<T> &List<T>::operator+ (const T &elt)
+{
+  Node *newnode = new Node(elt, NULL, tail);
+  if (isEmpty())
+    head = newnode;
+  else
+    tail->next = newnode;
+  tail = newnode;
+  return *this;
+}
+
+template <class T>
+List<T> &List<T>::operator+= (const T &elt)
+{
+  return *this + elt;
+}
+
+//TODO: use iterators
+template <class T>
+List<T> &List<T>::operator+ (const List<T> &l)
+{
+  Node *temp = l.head;
+  while(temp)
+  {
+    *this = *this + temp->key;
+    temp = temp->next;
+  }
+  return *this;
+}
+
+//TODO: use iterators
+template <class T>
+List<T> &List<T>::operator+= (const List<T> &l)
+{
+  Node *temp = l.head;
+  while(temp)
+  {
+    *this = *this + temp->key;
+    temp = temp->next;
+  }
+  return *this;
+}
+
+template <class T>
+List<T> &List<T>::operator= (const List<T> &l)
+{
+  if (this != &l)
+  {
+    empty();
+    Node *temp = l.head;
+    head = NULL;
+    tail =  NULL;
+    while(temp)
+    {
+      Node *newnode = new Node(temp->key, tail, NULL);
+      if (!head)
+        head = newnode;
+      if (tail)
+        tail->next = newnode;
+      tail = newnode;
+      temp = temp->next;
+    }
+  }
+  return *this;
+}
+
+template <class T>
+ostream &operator<< (ostream &os, const List<T> &l)
+{
+  typename List<T>::Node *temp = l.getHead();
+  while(temp)
+  {
+    os << temp->key;
+    if (temp->next)
+      os << ", ";
+    temp = temp->next;
+  }
+  return os;
+}
+
+#endif
diff --git a/src/MIDIReader.cpp b/src/MIDIReader.cpp
new file mode 100644 (file)
index 0000000..7ccb818
--- /dev/null
@@ -0,0 +1,387 @@
+// For format explanation, see http://www.sonicspot.com/guide/midifiles.html
+
+#include <MIDIReader.hpp>
+#include <arpa/inet.h>
+#include <iostream>
+using namespace std;
+#include <string.h>
+
+#include "Tools.hpp"
+
+MIDIReader::MIDIReader()
+:_file(NULL), _nbtracks(0), _timedivision(0), _position(0)
+{
+}
+
+MIDIReader::MIDIReader(const String &filename)
+:_nbtracks(0), _timedivision(0), _position(0)
+{
+       String buffer;
+       if (fileExists(filename))
+               buffer = filename;
+       else if (fileExists("data/songs/" + filename))
+               buffer = "data/songs/" + filename;
+       else if (fileExists("../data/songs/" + filename))
+               buffer = "../data/songs/" + filename;
+       else if (fileExists("data/songs/" + filename))
+               buffer = "data/songs/" + filename;
+
+       if (buffer == "" || (_file = fopen(buffer.c_str(), "rb")) == NULL)
+       {
+               cerr << "Could not open file " << filename << " buffer=" << buffer << endl;
+               perror("error:");
+               throw 0;
+       }
+}
+
+MIDIReader::MIDIReader(const MIDIReader &m)
+: _file(m._file), _nbtracks(m._nbtracks), _timedivision(m._timedivision), _position(m._position)
+{
+}
+
+MIDIReader::~MIDIReader()
+{
+       if (_file)
+               fclose(_file);
+}
+
+void MIDIReader::readHeader()
+{
+       if (!_file)
+               return;
+       
+       uint8 temp[4];
+       
+       //read the chunk ID
+       fread((void *)(temp), 1, 4, _file);
+       if (strncmp((char *)temp, "MThd", 4) != 0)
+       {
+               cerr << "Wrong chunk '" << (char)temp[0] << (char)temp[1] << (char)(char)temp[2] << (char)temp[3] << "'" << endl;
+               return;
+       }
+
+       //read the chunk size
+       uint32 chunksize;
+       readBytes(&chunksize, 4);
+       cout << "Header size: " << chunksize << endl;
+
+       //read the format
+       uint16 format;
+       readBytes(&format, 2);
+       cout << "Format type: " << format << endl;
+       
+       //read the format
+       readBytes(&_nbtracks, 2);
+       cout << "Nb of tracks: " << _nbtracks << endl;
+       
+       //read the format
+       readBytes(&_timedivision, 2);
+       cout << "Time division: " << _timedivision << endl;
+
+       //In theory there is no more than 6 bytes in the header...
+       if (chunksize > 6)
+               cout << (chunksize - 6) << "more bytes in the header" << endl;
+}
+
+void MIDIReader::skipTrack()
+{
+       uint8 temp[4];
+       //read the chunk ID
+       fread((void *)(temp), 4, 1, _file);
+//      cerr << temp << endl;
+       if (strncmp((char *)temp, "MTrk", 4) != 0)
+       {
+               cerr << "Wrong track chunk '" << (char)temp[0] << (char)temp[1] << (char)temp[2] << (char)temp[3] << "'" << endl;
+               return;
+       }
+
+       //read the chunk size
+       uint32 chunksize;
+       readBytes(&chunksize, 4);
+       cout << "Chunk size: " << chunksize << endl;
+               fseek(_file, chunksize, SEEK_CUR);
+       cout << "Track Skipped" << endl;
+}
+
+void MIDIReader::readTrack(Track &tr)
+{
+       uint8 temp[4];
+       //read the chunk ID
+       fread((void *)(temp), 4, 1, _file);
+//      cerr << temp << endl;
+       if (strncmp((char *)temp, "MTrk", 4) != 0)
+       {
+               cerr << "Wrong track chunk '" << (char)temp[0] << (char)temp[1] << (char)temp[2] << (char)temp[3] << "'" << endl;
+               return;
+       }
+
+       //read the chunk size
+       uint32 chunksize;
+       readBytes(&chunksize, 4);
+       cout << "Chunk size: " << chunksize << endl;
+
+//      unsigned long
+       _position = 0;
+
+//              char temp2[4];
+//              readBytes(&te)
+//              fread(&temp2, 4, 1, _file);
+//              readBytes((char *)(&temp2),4);
+//              printf("TEMP : %0x %0x %0x %0x\n", temp2[0], temp2[1], temp2[2], temp2[3]);
+       bool end = false;
+       uint8 oldeventandchannel = 0;
+       uint32 timestamp = 0;
+
+//      Track example;
+       
+       //Read the events
+       while (_position < chunksize)
+       {
+               uint32 delta;
+               //The delta is a variable-length stuff
+               /*uint8 nblus = */readVariableLength(delta);
+
+               timestamp += delta;
+       
+               uint8 eventandchannel, tempevt;
+               // 4 bits for event type, and 4 others for the channel
+               readBytes(&tempevt, 1);
+               fseek(_file, -1, SEEK_CUR);
+               _position--;
+
+               if (tempevt & 0x80)
+               {
+                       readBytes(&eventandchannel, 1);
+                       if ((tempevt & 0xf0) != 0xf0)
+                               oldeventandchannel = eventandchannel;
+               }
+               else
+//              {
+                       eventandchannel = oldeventandchannel;
+//              }
+
+               //Meta events
+               if ((eventandchannel & 0xff) == 0xff)
+               {
+                       if (end)
+                               cerr << "EXTRA EVT ";
+                       uint8 type;
+                       readBytes(&type, 1);
+
+                       uint32 length;
+                       /*uint8 nblus = */readVariableLength(length);
+       
+                       uint8 *data = new uint8[length];
+                       readBytes(data, length);
+                       uint32 tempo = 0;
+       
+                       switch(type)
+                       {
+                               case 0x00:
+                                       cout << "Sequence number: " << data[0] << " ; " << data[1] << endl;
+                                       break;
+                               case 0x01:
+                                       cout << "Text: ";
+                                       printBytes(data, length);
+                                       break;
+                               case 0x02:
+                                       cout << "Copyright: ";
+                                       printBytes(data, length);
+                                       break;
+                               case 0x03:
+                                       cout << "Track name: ";
+                                       printBytes(data, length);
+                                       break;
+                               case 0x04:
+                                       cout << "Instrument name: ";
+                                       printBytes(data, length);
+                                       break;
+                               case 0x05:
+                                       cout << "Lyrics: ";
+                                       printBytes(data, length);
+                                       break;
+                               case 0x06:
+                                       cout << "Maker: ";
+                                       printBytes(data, length);
+                                       break;
+                               case 0x07:
+                                       cout << "Cue point: ";
+                                       printBytes(data, length);
+                                       break;
+                               case 0x20:
+                                       cout << "MIDI Channel prefix: " << data << endl;
+                                       break;
+                               case 0x2F:
+                                       cout << "End of track at " << timestamp << endl;
+                                       tr.setEndOfTrack(timestamp);
+                                       end = true;
+                                       break;
+                               case 0x51:
+                                       tempo = ((int(data[2]) << 16) + (int(data[1]) << 8) + int(data[0]));
+                                       cout << "Tempo at " << timestamp << " : x=" << tempo << "=" << 60000000 / tempo << "bpm" << endl;
+                                       tr.addTempo(timestamp, tempo);
+                                       break;
+                               case 0x58:
+                                       cout << "Time signature: " << int(data[3]) << "|" << int(data[2]) << " " << int(data[1]) << " ticks " << int(data[0]) << "x" << endl;
+                                       break;
+                               case 0x59:
+                                       cout << "Key signature: " << int(data[1]) << " " << int(data[0]) << endl;
+                                       break;
+                               case 0x7F:
+                                       cout << "Sequencer stuff!" << endl;
+                                       break;
+                               default:
+                                       printf("Unknown chunk: %0x, size=%d\n", type, length);
+                                       break;
+                       }
+                       delete []data;
+               }
+               //System Data
+               else if ((eventandchannel & 0xf0) == 0xf0)// || (eventandchannel & 0xff) == 0xf7)
+               {
+                       //May be something else
+                       uint32 length;
+                       readVariableLength(length);
+                       uint8 *data = new uint8[length];
+                       readBytes(data, length);
+                       printf("System data\n");
+                       delete []data;
+               }
+               //Other events
+               else
+               {
+//                      printf("Evt : %x %x %x\n", eventandchannel & 0xf0, eventandchannel & 0x0f, eventandchannel);
+                       uint8 par1, par2;
+//                      position += 2;
+//                      char *notenames[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
+                       switch(eventandchannel & 0xf0)
+                       {
+                               ///Note ON
+                               case 0x80:
+                                       readBytes(&par1, 1);
+                                       readBytes(&par2, 1);
+//                                      printf("- Delta : %4d ; Note %s%d (%02x) off, velocity=%d, channel=%d\n", delta, notenames[par1 % 12], par1 / 12, par1+0, par2+0, eventandchannel & 0x0f);
+                                       tr.remKey(timestamp, par1);
+//                                     tr.addKey(delta, par1);
+//                                      cout << "Note " << notenames[int(par1) % 12] << (int(par1) / 12) << " (" << << ") off, velocity=" << int(par2) << " channel " << (eventandchannel & 0x0f) << endl;
+                                       break;
+                               ///Note OFF
+                               case 0x90:
+                                       readBytes(&par1, 1);
+                                       readBytes(&par2, 1);
+//                                      printf("+ Delta : %4d ; Note %s%d (%02x) on, velocity=%d, channel=%d\n", delta, notenames[par1 % 12], par1 / 12, par1+0, par2+0, eventandchannel & 0x0f);
+                                       if (par2 > 0)
+                                               tr.addKey(timestamp, par1);
+                                       else
+                                       tr.remKey(timestamp, par1);
+//                                      printf("Delta : %4ld ; ", delta);
+//                                      cout << "Note " << notenames[int(par1) % 12] << (int(par1) / 12 )<< " on,      velocity=" << int(par2) << " channel " << (eventandchannel & 0x0f) << endl;
+                                       break;
+                               case 0xA0:
+                                       readBytes(&par1, 1);
+                                       readBytes(&par2, 1);
+                                       printf("Delta : %4d ; Note Aftertouch\n", delta);
+                                       break;
+                               case 0xB0:
+                                       readBytes(&par1, 1);
+                                       readBytes(&par2, 1);
+                                       printf("Delta : %4d ; Controller\n", delta);
+                                       break;
+                               case 0xC0:
+                                       readBytes(&par1, 1);
+                                       printf("Delta : %4d ; Program Change\n", delta);
+                                       break;
+                               case 0xD0:
+                                       readBytes(&par1, 1);
+                                       printf("Delta : %4d ; Channel Aftertouch\n", delta);
+                                       break;
+                               case 0xE0:
+                                       readBytes(&par1, 1);
+                                       readBytes(&par2, 1);
+                                       printf("Delta : %4d ; Pitch Bend\n", delta);
+                                       break;
+                               default:
+                                       readBytes(&par1, 1);
+                                       printf("Delta : %4d ; Other event : %x, channel %x\n", delta, (eventandchannel & 0xf0) >> 4, eventandchannel & 0x0f);
+//                                      cout << endl;
+                                       break;
+                       }
+               }
+//              printf("Delta : %d, Event %4x on channel %d, par1 = %d, par2 = %d\n", delta, eventandchannel >> 4, eventandchannel & 0x0f, par1, par2);
+       }
+//      tr.displayTracks();
+}
+
+void MIDIReader::readTracks(Track &t)//, int &nb)
+{
+/*     Track tracks[_nbtracks];
+       for (int i=0 ; i < _nbtracks ; i++)
+       {
+               cout << "Reading Track " << i << endl;
+               readTrack(tracks[i]);
+       }*/
+
+//      Track t;
+       //read tempos
+       readTrack(t);
+       //read notes
+       readTrack(t);
+       //skip other tracks
+       for (int i = 2 ; i < _nbtracks ; i++)
+       {
+               cout << "Skipping Track " << i << endl;
+               skipTrack();
+       }
+
+
+       cout << "Stats Track " << endl;
+       for (int j = 0 ; j < NBDIFFICULTIES ; j++)
+       {
+               cout << "       Difficulty " << j << " ";
+               cout << t.getNbNotes(j) << " notes ";
+               cout << " l=" << t.getTotalLength(j) << endl;
+       }
+
+//      t.debugTempo();
+
+       int total = 0;
+       cout << "Notes : ";
+       for (int j = 0 ; j < 128 ; j++)
+       {
+               cout << j << ":" << t.getTotalNotes(j) << " ";
+               total += t.getTotalNotes(j);
+       }
+       cout << endl << "Total : " << total << endl;
+}
+
+uint8 MIDIReader::readVariableLength(uint32 &nb)
+{
+       uint8 nblus = 0;
+       nb = 0;
+       uint8 temp;
+       do
+       {
+               fread((void *)(&temp), 1, 1, _file);
+               nb = (nb << 7) | (temp & 0x7f);
+               nblus++;
+       }
+       while (temp & 0x80 && nblus < 4);
+       _position += nblus;
+       return nblus;
+}
+
+void MIDIReader::readBytes(void *data, uint32 nb)
+{
+       uint8 temp[nb];
+       fread((void *)(&temp), nb, 1, _file);
+               for (uint32 i=0 ; i<nb ; i++)
+                       ((uint8 *)data)[i] = temp[nb - i - 1];
+       _position += nb;
+}
+
+void MIDIReader::printBytes(uint8 *data, uint32 length)
+{
+       for (uint32 i=0 ; i < length ; i++)
+               cout << data[length - i - 1];
+       cout << endl;
+}
diff --git a/src/Mixer.cpp b/src/Mixer.cpp
new file mode 100644 (file)
index 0000000..4d9d9ae
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "Mixer.hpp"
+#include "Tools.hpp"
+//#include "log.hpp"
+
+Sound::Sound()
+:nbrchunks(0), _chunks(NULL)
+{
+}
+
+Sound::Sound(const Sound &s)
+:nbrchunks(s.nbrchunks), _chunks(s._chunks)
+{
+}
+
+Sound::Sound(const String &filename)
+:nbrchunks(0), _chunks(NULL)
+{
+       addSound(filename);
+}
+
+bool Sound::addSound(const String &filename)
+{
+       String buffer;
+       if (fileExists(filename))
+               buffer = filename;
+       else if (fileExists("data/sounds/" + filename))
+               buffer = "data/sounds/" + filename;
+       else if (fileExists("../data/sounds/" + filename))
+               buffer = "../data/sounds/" + filename;
+       else if (fileExists("data/songs/" + filename))
+               buffer = "data/songs/" + filename;
+       else if (fileExists("../data/songs/" + filename))
+               buffer = "../data/songs/" + filename;
+
+       //_debug_(stderr, "Sound(%s)\n",buffer.c_str());
+       
+       if (buffer != "")
+       {
+               Mix_Chunk *c = Mix_LoadWAV(buffer.c_str());
+               if(c)
+                       return addChunk(c);
+               else
+                       fprintf(stderr, "cannot load sound %s ; %s\n",buffer.c_str(), SDL_GetError());
+       }
+       else
+               fprintf(stderr, "sound file %s not found\n",filename.c_str());
+
+       return false;
+}
+
+bool Sound::addChunk(Mix_Chunk *c)
+{
+       if(c == NULL)
+               return false;
+
+       if(_chunks == NULL)
+       {
+               _chunks=new Mix_Chunk*[1];
+               nbrchunks=1;
+               _chunks[0]=c;
+       }
+       else
+       {
+               nbrchunks++;
+               Mix_Chunk **t=new Mix_Chunk*[nbrchunks];
+               for (int i = 0 ; i < nbrchunks - 1 ; i++)
+                       t[i] = _chunks[i];
+               t[nbrchunks-1] = c;
+               delete [] _chunks;
+               _chunks=t;
+       }
+
+       return true;
+}
+
+Sound::~Sound()
+{
+       if (_chunks)
+       {
+               // TODO FIX: if we copy the sound (with the copy constructor)
+               //      the destructor doesn't have to destroy the chunk !
+               for(int i = 0 ; i < nbrchunks ; i++)
+                       Mix_FreeChunk(_chunks[i]);
+               delete [] _chunks;
+       }
+}
+
+Mix_Chunk *Sound::getChunk()
+{
+       if(!_chunks)
+               return NULL;
+       int i = rand() % nbrchunks;
+       return _chunks[i];
+}
+
+Mix_Chunk *Sound::mix()
+{
+       if (nbrchunks <= 0)
+               return NULL;
+       Mix_Chunk *m = new(Mix_Chunk);
+       m->allocated = _chunks[0]->allocated;
+       m->alen = _chunks[0]->alen;
+       m->abuf = new Uint8[m->alen];
+       m->volume = _chunks[0]->volume;
+       for (Uint32 i = 0 ; i < m->alen ; i++)
+       {
+               printf("%d/%d\r",i, m->alen);
+               m->abuf[i] = 0;
+               for (int j = 0 ; j < nbrchunks ; j++)
+                       m->abuf[i] += _chunks[j]->abuf[i] / nbrchunks;
+       }
+       return m;
+}
+
+Mix_Music *Mixer::_music = NULL;
+Mixer *Mixer::_minstance = NULL;
+int *Mixer::_soundChannels = NULL;
+
+Mixer::Mixer()
+:/*_music(NULL), *//*_soundChannels(new int[MAXSOUNDS]),*/ _musicVolume(-1), _soundVolume(-1)
+{
+       if (!_soundChannels)
+               _soundChannels = new int[MAXSOUNDS];
+       for (int i = 0 ; i < MAXSOUNDS ; i++)
+               _soundChannels[i] = -1;
+       Mix_ChannelFinished(channelStopped);
+}
+
+Mixer::Mixer(const Mixer &m)
+:_sounds(m._sounds)/*, _music(m._music)*//*, _soundChannels(new int[MAXSOUNDS])*/
+{
+       if (!_soundChannels)
+               _soundChannels = new int[MAXSOUNDS];
+       for (int i = 0 ; i < MAXSOUNDS ; i++)
+               _soundChannels[i] = m._soundChannels[i];
+}
+
+Mixer::~Mixer()
+{
+       for (int i = 0 ; i < MAXSOUNDS ; i++)
+               if (_soundChannels[i] >=0)
+                       stopSound(i);
+       delete _soundChannels;
+       //TODO: destroy the Sounds...
+        //for the moment we never unload Sounds...
+       if (_music)
+               stopMusic();
+}
+
+
+void Mixer::initMixer()
+{
+/*     list<msg_t>::iterator it;
+       for(it=cc.l.begin();it!=cc.l.end();++it) {
+               if(it->match("SOUND")) {
+                       string n,f;
+                       it->tail() >> n >> f;
+                       _minstance->addSound(n.c_str(),f.c_str());
+               }
+       }*/
+}
+
+void Mixer::playMusic(const String &filename)
+{
+       //_debug_(stderr, "playMusic(%s)\n",filename.c_str());
+       if (_music)
+       {
+               Mix_HaltMusic();
+               Mix_FreeMusic(_music);
+       }
+       String buffer;
+       if (fileExists(filename))
+               buffer = filename;
+       else if (fileExists("data/sounds/" + filename))
+               buffer = "data/sounds/" + filename;
+       else if (fileExists("../data/sounds/" + filename))
+               buffer = "../data/sounds/" + filename;
+       else if (fileExists("data/songs/" + filename))
+               buffer = "data/songs/" + filename;
+       else if (fileExists("../data/songs/" + filename))
+               buffer = "../data/songs/" + filename;
+
+       if (buffer != "")
+       {
+               _music = Mix_LoadMUS(buffer.c_str());
+               if(_music==NULL)
+                       fprintf(stderr, "cannot load music %s\n",buffer.c_str());
+               else
+               {
+                       Mix_PlayMusic(_music, -1);
+                       Mix_HookMusicFinished(stopMusic);
+               }
+       }
+       else
+               fprintf(stderr, "music file %s not found\n",filename.c_str());
+
+       //else
+       //      cout << "music file " << filename << " not found" << endl;
+}
+
+void Mixer::stopMusic()
+{
+       Mix_HaltMusic();
+       Mix_FreeMusic(_music);
+       _music = NULL;
+}
+
+bool Mixer::addSound(const String &s, const String &filename)
+{
+       Sound *snd;
+       try
+       {
+               snd = _sounds[s];
+       }
+       catch(ExceptionNodeDontExist &e)
+       {
+               _sounds.addNode(s, new Sound);
+               snd = _sounds[s];
+       }
+
+       return snd->addSound(filename);
+}
+
+void Mixer::playSound(const String &s)
+{
+       //_debug_(stderr, "playSound(%s)\n",s.c_str());
+       Sound *snd;
+       try
+       {
+               snd = _sounds[s];
+       }
+       catch(ExceptionNodeDontExist &e)
+       {
+               _sounds.addNode(s, new Sound(s));
+               snd = _sounds[s];
+       }
+       
+       Mix_Chunk *c=snd->getChunk();
+       if(c)
+       {
+               for (int i = 0 ; i < MAXSOUNDS ; i++)
+               {
+                       if (_soundChannels[i] < 0 || !Mix_Playing(_soundChannels[i]))
+                       {
+                               _soundChannels[i] = Mix_PlayChannel(-1, c, 0);
+       // else { 
+       //      fprintf(stderr, "snd->getChunk()==NULL\n");
+       //}
+                               break;
+                       }
+               }
+       }
+}
+
+void Mixer::stopSound(const int &i)
+{
+       Mix_HaltChannel(_soundChannels[i]);
+}
+
+void Mixer::channelStopped(int channel)
+{
+       for (int i = 0 ; i < MAXSOUNDS ; i++)
+       {
+               if (_soundChannels[i] == channel)
+               {
+                       _soundChannels[i] = -1;
+                       break;
+               }
+       }
+}
+
+void Mixer::setMusicVolume(const int &v)
+{
+       _musicVolume = v;
+       Mix_VolumeMusic(_musicVolume);
+}
+
+void Mixer::setSoundVolume(const int &v)
+{
+       _soundVolume = v;
+       for (int i = 0 ; i < MAXSOUNDS ; i++)
+               //if (Mix_Playing(_soundChannels[i]))
+                       Mix_Volume(_soundChannels[i], v);
+//                     Mix_VolumeChunk(_sounds[i]->getChunk(), _soundVolume);
+}
+
diff --git a/src/Pair.cpp b/src/Pair.cpp
new file mode 100644 (file)
index 0000000..69b99b1
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * 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.
+ */
+#ifdef __PAIR__
+
+#include <iostream>
+using namespace std;
+
+template <class T, class U>
+Pair<T, U>::Pair(const T &x, const U &y)
+:px(x), py(y)
+{
+}
+
+template <class T, class U>
+Pair<T, U>::Pair(const Pair<T, U> &p)
+:px(p.px), py(p.py)
+{
+}
+
+template <class T, class U>
+Pair<T, U>::~Pair()
+{
+}
+
+template <class T, class U>
+const T &Pair<T, U>::getX() const
+{
+  return px;
+}
+
+template <class T, class U>
+const U &Pair<T, U>::getY() const
+{
+  return py;
+}
+
+template <class T, class U>
+void Pair<T, U>::setX(const T &x)
+{
+  px = x;
+}
+
+template <class T, class U>
+void Pair<T, U>::setY(const U &y)
+{
+  py = y;
+}
+
+///Use an exception ?
+// template <class T, class U>
+// T &Pair<T, U>::operator [] (const int &i)
+// {
+//   if (i == 0)
+//     return px;
+//   else
+//     return py;
+// }
+// 
+// template <class T, class U>
+// T Pair<T, U>::operator [] (const int &i) const
+// {
+//   if (i == 0)
+//     return px;
+//   else
+//     return py;
+// }
+
+
+template <class T, class U>
+const Pair<T, U> & Pair<T, U>::operator = (const Pair<T, U> &p)
+{
+  px = p.px;
+  py = p.py;
+  return *this;
+}
+
+template <class T, class U>
+bool Pair<T, U>::operator == (const Pair<T, U> &p) const
+{
+  return (px == p.px) && (py == p.py);
+}
+
+template <class T, class U>
+Pair<T, U> operator + (const Pair<T, U> &p1, const Pair<T, U> &p2)
+{
+  Pair<T, U> result;
+  result.px = p1.px + p2.px;
+  result.py = p1.py + p2.py;
+  return result;
+}
+
+template <class T, class U>
+Pair<T, U> operator + (const T &a, const Pair<T, U> &p)
+{
+  return p + Pair<T, U>(a, a);
+}
+
+template <class T, class U>
+Pair<T, U> operator + (const Pair<T, U> &p, const U &a)
+{
+  return p + Pair<T, U>(a, a);
+}
+
+template <class T, class U>
+Pair<T, U> operator - (const Pair<T, U> &p1, const Pair<T, U> &p2)
+{
+  Pair<T, U> result;
+  result.px = p1.px - p2.px;
+  result.py = p1.py - p2.py;
+  return result;
+}
+
+template <class T, class U>
+Pair<T, U> operator - (const T &a, const Pair<T, U> &p)
+{
+  return Pair<T, U>(a, a) - p ;
+}
+
+template <class T, class U>
+Pair<T, U> operator - (const Pair<T, U> &p, const U &a)
+{
+  return p - Pair<T, U>(a, a);
+}
+
+template <class T, class U>
+Pair<T, U> Pair<T, U>::operator - (void)
+{
+  return Pair<T, U>(-px, -py);
+}
+
+template <class T, class U>
+Pair<T, U> operator * (const Pair<T, U> &p1, const Pair<T, U> &p2)
+{
+  Pair<T, U> result;
+  result.px = p1.px * p2.px;
+  result.py = p1.py * p2.py;
+  return result;
+}
+
+template <class T, class U>
+Pair<T, U> operator * (const T &a, const Pair<T, U> &p)
+{
+  return p * Pair<T, U>(a, a);
+}
+
+template <class T, class U>
+Pair<T, U> operator * (const Pair<T, U> &p, const U &a)
+{
+  return p * Pair<T, U>(a, a);
+}
+
+template <class T, class U>
+Pair<T, U> operator / (const Pair<T, U> &p1, const Pair<T, U> &p2)
+{
+  Pair<T, U> result;
+  result.px = p1.px / p2.px;
+  result.py = p1.py / p2.py;
+  return result;
+}
+
+template <class T, class U>
+Pair<T, U> operator / (const T &a, const Pair<T, U> &p)
+{
+  return Pair<T, U>(a, a) / p;
+}
+
+template <class T, class U>
+Pair<T, U> operator / (const Pair<T, U> &p, const U &a)
+{
+  return p / Pair<T, U>(a, a);
+}
+
+template <class T, class U>
+ostream &operator << (ostream &os, const Pair<T, U> &p)
+{
+  os << "(" << p.px << "," << p.py << ")";
+  return os;
+}
+
+#endif
diff --git a/src/PrefixTree.cpp b/src/PrefixTree.cpp
new file mode 100644 (file)
index 0000000..d8f3311
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * 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.
+ */
+#ifdef __PREFIXTREE__
+
+template <class T>
+PrefixTree<T>::PrefixTree()
+:root(new TNode())
+{
+}
+
+template <class T>
+PrefixTree<T>::PrefixTree(const PrefixTree<T> &pt)
+:root(pt.root)
+{
+}
+
+template <class T>
+PrefixTree<T>::~PrefixTree()
+{
+  delete root;
+}
+
+template <class T>
+void PrefixTree<T>::addNode(const String &pref, const T&elt)
+{
+  root->insertInsideNode(pref, elt, 0, 0);
+}
+
+template <class T>
+void PrefixTree<T>::remNode(const T &elt)
+{
+  //TODO
+}
+
+template <class T>
+List<String> PrefixTree<T>::sonsList(const String &pref) const
+{
+  //TODO
+  return List<String>();
+}
+
+template <class T>
+String PrefixTree<T>::completePrefix(const String &pref) const
+{
+  return root->searchInsideNode(pref, 0, 0);
+}
+
+template <class T>
+PrefixTree<T>::TNode::TNode()
+:haskey(false), key(), prefix(""), son(NULL), brotherleft(NULL), brotherright(NULL), father(NULL)
+{
+}
+
+template <class T>
+PrefixTree<T>::TNode::TNode(const T &elt, const String &pref, TNode *s, TNode *bl, TNode *br, TNode *f)
+:haskey(true), key(elt), prefix(pref), son(s), brotherleft(bl), brotherright(br), father(f)
+{
+}
+
+template <class T>
+PrefixTree<T>::TNode::TNode(const String &pref, TNode *s, TNode *bl, TNode *br, TNode *f)
+:haskey(false), key(), prefix(pref), son(s), brotherleft(bl), brotherright(br), father(f)
+{
+}
+
+template <class T>
+PrefixTree<T>::TNode::~TNode()
+{
+  delete son;
+  delete brotherright;
+}
+
+template <class T>
+void PrefixTree<T>::TNode::insertInsideNode(const String &pref, const T &elt, const unsigned int &posword, const unsigned int &posnode)
+{
+  if (posnode >= prefix.length())
+  {
+    if (posword >= pref.length())
+      key = elt;
+    else if (son == NULL)
+      son = new TNode(elt, pref(posword, pref.length() - posword), NULL, NULL, NULL, this);
+    else
+      son->insertInsideNode(pref, elt, posword, 0);
+  }
+  else
+  {
+    if (posword >= pref.length())
+    {
+      TNode *temp = new TNode(key, prefix(posnode, prefix.length() - posnode), son, NULL, NULL, this);
+      key = elt;
+      prefix = prefix(0, posnode);
+      son = temp;
+    }
+    else
+    {
+      if (pref[posword] == prefix[posnode])
+        insertInsideNode(pref, elt, posword + 1, posnode + 1);
+      else
+      {
+        if (posnode == 0)
+        {
+          if (brotherright)
+            brotherright->insertInsideNode(pref, elt, posword, 0);
+          else
+            brotherright = new TNode(elt, pref(posword, pref.length() - posword), NULL, this, NULL, father);
+        }
+        else
+        {
+          TNode *temp = new TNode(prefix(0, posnode), this, brotherleft, brotherright, father);
+          if (father->son == this)
+            father->son = temp;
+          if (brotherleft)
+            brotherleft->brotherright = temp;
+          if (brotherright)
+            brotherright->brotherleft = temp;
+          TNode *temp2 = new TNode(elt, pref(posword, pref.length() - posword), NULL, this, NULL, temp);
+          father = temp;
+          brotherleft = NULL;
+          brotherright = temp2;
+          prefix = prefix(posnode, prefix.length() - posnode);
+        }
+      }
+    }
+  }
+}
+
+template <class T>
+String PrefixTree<T>::TNode::searchInsideNode(const String &pref, const unsigned int &posword, const unsigned int &posnode) const
+{
+  if (posnode >= prefix.length())
+  {
+    if (posword >= pref.length() || son == NULL)
+      return pref(0, posword);
+    return son->searchInsideNode(pref, posword, 0);
+  }
+  if (posword >= pref.length())
+    return pref + prefix(posnode, prefix.length() - posnode);
+  if (pref[posword] == prefix[posnode])
+    return searchInsideNode(pref, posword + 1, posnode + 1);
+  if (posnode == 0 && brotherright)
+    return brotherright->searchInsideNode(pref, posword, 0);
+  return pref(0, posword);
+}
+
+template <class T>
+bool PrefixTree<T>::searchNode(const String &n)
+{
+  return root->nodeExists(n, 0, 0);
+}
+
+template <class T>
+bool PrefixTree<T>::TNode::nodeExists(const String &n, const unsigned int &posword, const unsigned int &posnode) const
+{
+  if (posnode >= prefix.length())
+  {
+    if (posword >= n.length())
+      return haskey;
+    if (son == NULL)
+      return false;
+    return son->nodeExists(n, posword, 0);
+  }
+  if (posword >= n.length())
+    return false;
+  if (n[posword] != prefix[posnode])
+  {
+    if (posnode == 0 && brotherright)
+      return brotherright->nodeExists(n, posword, 0);
+    else
+      return false;
+  }
+  return nodeExists(n, posword + 1, posnode + 1);
+}
+
+template <class T>
+const T &PrefixTree<T>::TNode::getNode(const String &n, const unsigned int &posword, const unsigned int &posnode) const
+{
+  if (posnode >= prefix.length())
+  {
+    if (posword >= n.length())
+      return key;
+    if (son == NULL)
+      throw ExceptionNodeDontExist(n);
+    return son->getNode(n, posword, 0);
+  }
+  if (posword >= n.length())
+    throw ExceptionNodeDontExist(n);
+  if (n[posword] != prefix[posnode])
+  {
+    if (posnode == 0 && brotherright)
+      return brotherright->getNode(n, posword, 0);
+    else
+      throw ExceptionNodeDontExist(n);
+  }
+  return getNode(n, posword + 1, posnode + 1);
+}
+
+template <class T>
+typename PrefixTree<T>::TNode * PrefixTree<T>::getRoot()
+{
+  return root;
+}
+/*
+template <class T>
+inline T &PrefixTree<T>::operator[](const String &key)
+{
+  return root->getNode(n, 0, 0);
+}*/
+
+template <class T>
+inline const T &PrefixTree<T>::operator[](const String &key) const
+{
+  return root->getNode(key, 0, 0);
+}
+
+template <class T>
+ostream &PrefixTree<T>::TNode::display(ostream &os)
+{
+// cout << "display key" << endl;
+  if (haskey)
+    os << "[" << key << "]";
+  else
+    os << "X";
+// cout << "display prefix" << endl;
+  os << " " << prefix << " ";
+// cout << "display son" << endl;
+  if (son)
+  {
+    os << " (";
+    son->display(os);
+    os << ")";
+  }
+// cout << "display brother" << endl;
+  if (brotherright)
+  {
+    os << " {";
+    brotherright->display(os);
+    os << "}";
+  }
+  return os;
+}
+
+/*template <class T>
+ostream &operator<< (ostream &os, const typename PrefixTree<T>::TNode &n)
+{
+  if (n.key)
+    os << "[" << *(n.key) << "]";
+  else
+    os << "X";
+  os << " " << n.prefix << " ";
+  if (n.son)
+    os << " (" << *(n.son) << ")";
+  if (n.brother)
+    os << " {" << *(n.brother) << "}";
+  return os;
+}*/
+
+template <class T>
+ostream &operator<< (ostream &os, const PrefixTree<T> &n)
+{
+  if (n.root)
+    n.root->display(os);
+  return os;
+}
+
+template <class T>
+typename PrefixTree<T>::TNode *PrefixTree<T>::TNode::nextNode()
+{
+  if (son)
+    return son;
+  TNode *temp = this;
+  while (temp && !temp->brotherright)
+    temp = temp->father;
+  if (temp)
+    return temp->brotherright;
+  else
+    return NULL;
+}
+
+template <class T>
+String PrefixTree<T>::TNode::wholePrefix() const
+{
+  if (father)
+    return father->wholePrefix() + prefix;
+  else
+    return prefix;
+}
+
+#endif
diff --git a/src/String.cpp b/src/String.cpp
new file mode 100644 (file)
index 0000000..1d105ae
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include "String.hpp"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <cmath>
+#include <cfloat>
+#include <cstring>
+#include <iostream>
+using namespace std;
+
+String::String(const String &s)
+:string(strdup(s.string))
+{
+}
+
+String::String(const int &a)
+{
+  if (a == 0)
+    string = (char *)malloc(2 * sizeof(char));
+  else if (a < 0)
+    string = (char *)malloc(int(log10(-a) + 3) * sizeof(char));
+  else
+    string = (char *)malloc(int(log10(a) + 2) * sizeof(char));
+  sprintf(string, "%d", a);
+}
+
+String::String(const double &a)
+{
+  //compute the number of chars
+  //too many if |n| < 0
+  //fix this in the future
+  int i;
+  long long pi=1;
+  for (i=0 ; a * pi - ceil(a * pi) > DBL_EPSILON ; i++,pi*=10);
+
+  int size;
+  if (i == 0)
+  {
+    if (a == 0)
+      size=2;
+    else if (a < 0)
+      size=int(log10(-a) + 3);
+    else
+      size=int(log10(a) + 2);
+  } else {
+    if (a < 0)
+      size=int(log10(-a * pow(10.0, i)) + 4);
+    else
+      size=int(log10(a * pow(10.0, i)) + 3);
+  }
+  
+  string = (char *)malloc(size * sizeof(char));
+  snprintf(string,size, "%.20f", a);
+}
+
+
+String::String(const char *s)
+:string(strdup(s))
+{
+}
+
+String::String(const char &c)
+{
+  string = (char *)malloc(2 * sizeof(char));
+  string[0] = c;
+  string[1] = '\0';
+}
+
+String::~String()
+{
+  free(string);
+}
+
+unsigned int String::length() const
+{
+  return strlen(string);
+}
+
+void String::concat(const String &s)
+{
+  string = (char *)realloc(string, (length() + s.length() + 1) * sizeof(char));
+  strcat(string, s.string);
+}
+
+const char *String::c_str() const
+{
+  return string;
+}
+
+const String & String::operator = (const String &s)
+{
+  if (&s != this)
+  {
+    free(string);
+    string = strdup(s.string);
+  }
+  return *this;
+}
+
+bool String::operator == (const String &s) const
+{
+  if (s.length() != length())
+    return false;
+  for (unsigned int i = 0 ; i < length() ; i++)
+    if (string[i] != s.string[i])
+      return false;
+  return true;
+}
+
+bool String::operator != (const String &s) const
+{
+  return !(*this == s);
+}
+
+char &String::operator [] (const int &i) const
+{
+  return string[i];
+}
+
+String String::operator () (const unsigned int &i, const unsigned int &j) const
+{
+  String result;
+  free (result.string);
+  result.string = (char *)malloc((j + 1) * sizeof(char));
+  for (unsigned int k = 0 ; k < j ; k++)
+    result.string[k] = string[k + i];
+  result.string[j] = '\0';
+  return result;
+}
+
+String operator + (const String &s1, const String &s2)
+{
+  String temp(s1);
+  temp.concat(s2);
+  return temp;
+}
+
+ostream &operator << (ostream & os, const String &s)
+{
+  os << s.string;
+  return os;
+}
+
+// istream &operator >> (istream & is, const String &s);
+// {
+// 
+// }
diff --git a/src/Texture.cpp b/src/Texture.cpp
new file mode 100644 (file)
index 0000000..e3f9913
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include "Texture.hpp"
+
+// #include <Ogl.h>
+// #include <SDL/SDL.h>
+#ifdef __APPLE__
+#include <SDL_image/SDL_image.h>
+#else
+#include <SDL/SDL_image.h>
+#endif
+// #include <SDL/SDL_opengl.h>
+#include <stdarg.h>
+
+#include "Tools.hpp"
+
+#define BUFFERSIZE 256
+
+Texture::Texture(const String &filename, const bool &rep)
+:surface(NULL), repeat(rep)
+{
+  glGenTextures (1, &texture);
+  glBindTexture (GL_TEXTURE_2D, texture);
+
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+  String buffer;
+  if (fileExists(filename))
+    buffer = filename;
+  else if (fileExists("data/textures/" + filename))
+    buffer = "data/textures/" + filename;
+  else if (fileExists("../data/textures/" + filename))
+    buffer = "../data/textures/" + filename;
+  else if (fileExists("data/textures2D/" + filename))
+    buffer = "data/textures2D/" + filename;
+  else if (fileExists("../data/textures2D/" + filename))
+    buffer = "../data/textures2D/" + filename;
+  else if (fileExists("data/textures3D/" + filename))
+    buffer = "data/textures3D/" + filename;
+  else if (fileExists("../data/textures3D/" + filename))
+    buffer = "../data/textures3D/" + filename;
+  else if (fileExists("data/fonts/" + filename))
+    buffer = "data/fonts/" + filename;
+  else if (fileExists("../data/fonts/" + filename))
+    buffer = "../data/fonts/" + filename;
+
+  if (buffer != "")
+    surface = IMG_Load(buffer.c_str());
+       else
+               cerr << "Could not open texture " << filename << endl;
+
+  if (surface)
+  {
+    size[C_X] = surface->w;
+    size[C_Y] = surface->h;
+    SDL_Surface *temp = NULL;
+    SDL_PixelFormat format = {NULL, 32, 4, 0, 0, 0, 0, 0, 8, 16, 24, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000, 0, 255};
+    switch(surface->format->BitsPerPixel)
+    {
+      case 24:
+        //convert to 32bits
+        temp = SDL_ConvertSurface(surface, &format, SDL_SWSURFACE);
+        SDL_FreeSurface(surface);
+        surface = temp;
+        gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, surface->w, surface->h, GL_RGB, GL_UNSIGNED_BYTE, surface->pixels);
+        break;
+      case 32:
+        //convert if it's ABGR
+        if (surface->format->Rshift > surface->format->Bshift)
+        {
+          temp = SDL_ConvertSurface(surface, &format, SDL_SWSURFACE);
+          SDL_FreeSurface(surface);
+          surface = temp;
+        }
+        break;
+    }
+    gluBuild2DMipmaps(GL_TEXTURE_2D, 4, surface->w, surface->h, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels);
+  }
+}
+
+
+Texture::~Texture()
+{
+  if (surface)
+  {
+    SDL_FreeSurface(surface);
+    glDeleteTextures(1, &texture);
+  }
+  else
+    cerr << "no texture..." << endl;
+}
+
+void Texture::useTexture() const
+{
+  if (surface)
+    glBindTexture(GL_TEXTURE_2D, texture);
+  else
+    cerr << "problem with texture" << endl;
+}
+
+bool Texture::isLoaded() const
+{
+  return (surface != NULL);
+}
+
+Vector2D<int> Texture::getSize() const
+{
+  return size;
+}
diff --git a/src/Tools.cpp b/src/Tools.cpp
new file mode 100644 (file)
index 0000000..79ce059
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include "Tools.hpp"
+
+#include <cmath>
+#include <cstdio>
+#include <sys/types.h>
+#include <dirent.h>
+using namespace std;
+
+bool fileExists(const String &f)
+{
+  FILE *file;
+  if ((file = fopen(f.c_str(),"r")) != NULL)
+  {
+    fclose(file);
+    return true;
+  }
+  return false;
+}
+
+bool dirExists(const String &d)
+{
+  DIR *dir;
+  if ((dir = opendir(d.c_str())) != NULL)
+  {
+    closedir(dir);
+    return true;
+  }
+  return false;
+}
+
+Vector2D<int> rotatePoint(const Vector2D<int> pos, const Vector2D<int> center, const double &angle)
+{
+  return Vector2D<int>(
+    int((pos[C_X] - center[C_X]) * cos(angle) - (pos[C_Y] - center[C_Y]) * sin(angle) + center[C_X]),
+    int((pos[C_Y] - center[C_Y]) * cos(angle) + (pos[C_X] - center[C_X]) * sin(angle) + center[C_Y])
+  );
+}
+
+//recursive, but supposed to be called once...
+//see if we have to do something here...
+double mod2pi(const double &a)
+{
+  if (a > 2 * M_PI)
+    return mod2pi(a - 2 * M_PI);
+  else if (a < 0)
+    return mod2pi(a + 2 * M_PI);
+  return a;
+}
diff --git a/src/Track.cpp b/src/Track.cpp
new file mode 100644 (file)
index 0000000..e9173c5
--- /dev/null
@@ -0,0 +1,452 @@
+#include "Track.hpp"
+
+#include "Mixer.hpp"
+
+#include <map>
+
+double SECONDSIZE = 0.050;
+
+extern FILE *logfile;
+
+void drawCube(double pos, double size, double colorx, double colory, double colorz)
+{
+       glBegin(GL_QUADS);
+               glColor3f(colorx, colory, colorz);                      // Set The Color To Green
+/*
+               glNormal3f(0, -1, 0);
+               glVertex3f( size+pos,0, size);                  // Top Right Of The Quad (Bottom)
+               glVertex3f(-size+pos,0, size);                  // Top Left Of The Quad (Bottom)
+               glVertex3f(-size+pos,0,-size);                  // Bottom Left Of The Quad (Bottom)
+               glVertex3f( size+pos,0,-size);                  // Bottom Right Of The Quad (Bottom)
+*/
+               glNormal3f(0, 0.5, 0.5);
+               glVertex3f( size/2+pos, size/3, size/2);                        // Top Right Of The Quad (Front)
+               glVertex3f(-size/2+pos, size/3, size/2);                        // Top Left Of The Quad (Front)
+               glVertex3f(-size+pos,0, size);                  // Bottom Left Of The Quad (Front)
+               glVertex3f( size+pos,0, size);                  // Bottom Right Of The Quad (Front)
+
+               glNormal3f(0, 0.5, -0.5);
+               glVertex3f( size+pos,0,-size);                  // Bottom Left Of The Quad (Back)
+               glVertex3f(-size+pos,0,-size);                  // Bottom Right Of The Quad (Back)
+               glVertex3f(-size/2+pos, size/3,-size/2);                        // Top Right Of The Quad (Back)
+               glVertex3f( size/2+pos, size/3,-size/2);                        // Top Left Of The Quad (Back)
+
+               glNormal3f(-0.5, 0.5, 0);
+               glVertex3f(-size/2+pos, size/3, size/2);                        // Top Right Of The Quad (Left)
+               glVertex3f(-size/2+pos, size/3,-size/2);                        // Top Left Of The Quad (Left)
+               glVertex3f(-size+pos,0,-size);                  // Bottom Left Of The Quad (Left)
+               glVertex3f(-size+pos,0, size);                  // Bottom Right Of The Quad (Left)
+
+               glNormal3f(0.5, 0.5, 0);
+               glVertex3f( size/2+pos, size/3,-size/2l);                       // Top Right Of The Quad (Right)
+               glVertex3f( size/2+pos, size/3, size/2);                        // Top Left Of The Quad (Right)
+               glVertex3f( size+pos,0, size);                  // Bottom Left Of The Quad (Right)
+               glVertex3f( size+pos,0,-size);                  // Bottom Right Of The Quad (Right)
+
+               glColor3f(1.0, 1.0, 1.0);                       // Set The Color To White
+               glNormal3f(0, 1, 0);
+               glVertex3f( size/2+pos, size/3,-size/2);                        // Top Right Of The Quad (Top)
+               glVertex3f( size/2+pos, size/3, size/2);                        // Bottom Right Of The Quad (Top)
+               glVertex3f(-size/2+pos, size/3, size/2);                        // Bottom Left Of The Quad (Top)
+               glVertex3f(-size/2+pos, size/3,-size/2);                        // Top Left Of The Quad (Top)
+/*
+*/
+       glEnd();                                                // Done Drawing The Quad
+}
+
+void drawLong(double pos, double size, double length, double colorx, double colory, double colorz)
+{
+       double l = length*SECONDSIZE;
+       glBegin(GL_QUADS);
+               glColor3f(colorx, colory, colorz);                      // Set The Color
+/*
+               glNormal3f(0, -1, 0);
+               glVertex3f( size+pos,0, size);                  // Top Right Of The Quad (Bottom)
+               glVertex3f(-size+pos,0, size);                  // Top Left Of The Quad (Bottom)
+               glVertex3f(-size+pos,0,-size-l);                        // Bottom Left Of The Quad (Bottom)
+               glVertex3f( size+pos,0,-size-l);                        // Bottom Right Of The Quad (Bottom)
+*/
+               glNormal3f(0, 0.5, 0.5);
+               glVertex3f( size/2+pos, size/3, size/2);                        // Top Right Of The Quad (Front)
+               glVertex3f(-size/2+pos, size/3, size/2);                        // Top Left Of The Quad (Front)
+               glVertex3f(-size+pos,0, size);                  // Bottom Left Of The Quad (Front)
+               glVertex3f( size+pos,0, size);                  // Bottom Right Of The Quad (Front)
+
+               glNormal3f(0, 0.5, -0.5);
+               glVertex3f( size+pos,0,-size);                  // Bottom Left Of The Quad (Back)
+               glVertex3f(-size+pos,0,-size);                  // Bottom Right Of The Quad (Back)
+               glVertex3f(-size/2+pos, size/3,-size/2-l);                      // Top Right Of The Quad (Back)
+               glVertex3f( size/2+pos, size/3,-size/2-l);                      // Top Left Of The Quad (Back)
+
+               glNormal3f(-0.5, 0.5, 0);
+               glVertex3f(-size/2+pos, size/3, size/2);                        // Top Right Of The Quad (Left)
+               glVertex3f(-size/2+pos, size/3,-size/2-l);                      // Top Left Of The Quad (Left)
+               glVertex3f(-size+pos,0,-size-l);                        // Bottom Left Of The Quad (Left)
+               glVertex3f(-size+pos,0, size);                  // Bottom Right Of The Quad (Left)
+
+               glNormal3f(0.5, 0.5, 0);
+               glVertex3f( size/2+pos, size/3,-size/2-l);                      // Top Right Of The Quad (Right)
+               glVertex3f( size/2+pos, size/3, size/2);                        // Top Left Of The Quad (Right)
+               glVertex3f( size+pos,0, size);                  // Bottom Left Of The Quad (Right)
+               glVertex3f( size+pos,0,-size-l);                        // Bottom Right Of The Quad (Right)
+
+               glNormal3f(0, 1, 0);
+               glVertex3f( size/2+pos, size/3,-size/2-l);                      // Top Right Of The Quad (Top)
+               glVertex3f(-size/2+pos, size/3,-size/2-l);                      // Top Left Of The Quad (Top)
+               glVertex3f(-size/2+pos, size/3, size/2);                        // Bottom Left Of The Quad (Top)
+               glVertex3f( size/2+pos, size/3, size/2);                        // Bottom Right Of The Quad (Top)
+       glEnd();                                                // Done Drawing The Quad
+}
+
+Track::Track()
+:/*_currenttempo(120)*,_currentpos(0),*/ _trackSize(0), _active(true)
+{
+  for (uint8 i = 0 ; i < NBDIFFICULTIES ; i++)
+  {
+    _currentconfig[i] = 0;
+    _nbnotes[i] = 0;
+    _totallength[i] = 0;
+  }
+  for (uint8 i = 0 ; i < 128 ; i++)
+    _totalnotes[i] = 0;
+}
+
+Track::Track(const Track &tr)
+{
+       cerr << "WARNING: COPYING THE TRACK!" << endl;
+  for (uint8 i = 0 ; i < NBDIFFICULTIES ; i++)
+  {
+    _notes[i] = tr._notes[i];
+    _currentconfig[i] = tr._currentconfig[i];
+    _nbnotes[i] = 0;
+    _totallength[i] = 0;
+  }
+}
+
+Track::~Track()
+{
+}
+/*
+  http://www.scorehero.com/forum/viewtopic.php?t=1179
+  Lead guitar track (GH1)
+  =======================
+
+  Track 1 contains only events that affect gameplay. The exception to this rule is that Track 1 also contains events guiding the animation of the singer's mouth. Note-on and Note-off events are the only MIDI event types that are valid in this track other than the first event which is always a Track Name event with a track name of "T1 GEMS". Each gameplay event is allocated a MIDI note number where the note letter specifies the type of event and the note octave specifies the difficulty level to which the note applies. Each note event applies to a single difficulty level except for the vocal track events which apply to all difficulty levels. The note number mapping is as follows:
+
+  60: guitar note GREEN, easy (C)
+  61: guitar note RED, easy (C#)
+  62: guitar note YELLOW, easy (D)
+  63: guitar note BLUE, easy (D#)
+  64: guitar note ORANGE, easy (E)
+  67: star power group, easy (G)
+  69: player 1 section, easy (A)
+  70: player 2 section, easy (A#)
+  72: guitar note GREEN, medium (C)
+  73: guitar note RED, medium (C#)
+  74: guitar note YELLOW, medium (D)
+  75: guitar note BLUE, medium (D#)
+  76: guitar note ORANGE, medium (E)
+  79: star power group, medium (G)
+  81: player 1 section, medium (A)
+  82: player 2 section, medium (A#)
+  84: guitar note GREEN, hard (C)
+  85: guitar note RED, hard (C#)
+  86: guitar note YELLOW, hard (D)
+  87: guitar note BLUE, hard (D#)
+  88: guitar note ORANGE, hard (E)
+  91: star power group, hard (G)
+  93: player 1 section, hard (A)
+  94: player 2 section, hard (A#)
+  96: guitar note GREEN, expert (C)
+  97: guitar note RED, expert (C#)
+  98: guitar note YELLOW, expert (D)
+  99: guitar note BLUE, expert (D#)
+  100: guitar note ORANGE, expert (E)
+  103: star power group, expert (G)
+  105: player 1 section, expert (A)
+  106: player 2 section, expert (A#)
+  108: vocal track (C)
+*/
+
+void Track::addKey(uint32 time, uint8 note)
+{
+//   _totalnotes[note]++;
+
+//   cout << "addkey begin" << endl;
+  uint8 difficulty = note / 12 - 5;
+  uint8 key = note % 12;
+//   cout << "+ diff=" << difficulty+0 << " key=" << key+0 << " note=" << note+0 << endl;  //could be note 108 for singer
+  if (difficulty >= NBDIFFICULTIES || difficulty < 0)
+  {
+    //cout << "Wrong difficulty!" << difficulty << endl;
+    return;
+  }
+  //Notes could be other stuff
+  if (key >= 5)
+  {
+//     cout << "+ Key : " << key+0 << " difficulty : " << difficulty+0 << endl;
+    return;
+  }
+/*
+       //if delta is 0, this is a new note
+       if (delta > 0)
+       {
+               _notes[difficulty][_currentconfig[difficulty].getTime()] = _currentconfig[difficulty];
+               //set the new position
+               _currentconfig[difficulty].setTime(_currentconfig[difficulty].getTime() + _currentconfig[difficulty].getDuration());
+               //set the new duration
+               _currentconfig[difficulty].setDuration(delta);
+       }
+       _currentconfig[difficulty].addKey(keys(key));*/
+
+       _currentconfig[difficulty].addKey(keys(key));
+       _currentconfig[difficulty].setTime(time);
+       
+//   if (delta > 
+//   _currentconfig[difficulty].addKey(keys(key));
+  
+/*  if (_notes[difficulty].empty())
+  {
+    _currentconfig[difficulty].remKey(keys(key));
+    _currentconfig[difficulty] = delta;
+    _currentconfig[difficulty].addKey(keys(key));
+    _notes[difficulty].push_back(_currentconfig[difficulty]);
+    _nbnotes[difficulty]++;
+    _totallength[difficulty] += delta;
+    return;
+  }
+
+  if (delta > 0)
+  {
+    _currentconfig[difficulty].remKey(keys(key));
+    _notes[difficulty].push_back(_currentconfig[difficulty]);
+    _currentconfig[difficulty].setTime(delta);
+    _nbnotes[difficulty]++;
+    _totallength[difficulty] += delta;
+  }
+  _currentconfig[difficulty].addKey(keys(key));*/
+//   cout << "addkey end" << endl;
+}
+
+void Track::remKey(uint32 time, uint8 note)
+{
+       _totalnotes[note]++;
+//   cout << "remkey begin" << endl;
+  uint8 difficulty = note / 12 - 5;
+  uint8 key = note % 12;
+//   cout << "- diff=" << difficulty+0 << " key=" << key+0 << " note=" << note+0 << endl;
+  if (difficulty >= NBDIFFICULTIES || difficulty+0 < 0)
+  {
+//     cout << "Wrong difficulty!" << difficulty << endl;
+    return;
+  }
+  //Notes could be other stuff
+  if (key >= 5)
+  {
+//     cout << "- Key : " << key+0 << " difficulty : " << difficulty+0 << endl;
+    return;
+  }
+       if (_notes[difficulty].count(_currentconfig[difficulty].getTime()) == 0)
+       {
+               _currentconfig[difficulty].setTicks(time - _currentconfig[difficulty].getTime());
+               //compute the note duration and position
+               uint32 currenttempo = 0, lasttick = 0;
+               map<uint32, uint32>::iterator ti = _tempo.begin();
+               uint32 tickpos = _currentconfig[difficulty].getTime();
+               while (ti != _tempo.end() && (*ti).first <= tickpos)
+               {
+                       _currentconfig[difficulty].setPosition(_currentconfig[difficulty].getPosition() + ((*ti).first - lasttick) * (currenttempo / 480000.0));
+                       lasttick = (*ti).first;
+                       currenttempo = (*ti).second;
+                       ti++;
+               }
+               if (tickpos > lasttick)
+                       _currentconfig[difficulty].setPosition(_currentconfig[difficulty].getPosition() + (tickpos - lasttick) * (currenttempo / 480000.0));
+                                       
+               while (tickpos < time)
+               {
+                       if (ti != _tempo.end() && (*ti).first < time)
+                       {
+                               _currentconfig[difficulty].setEnd(_currentconfig[difficulty].getPosition() + ((*ti).first - tickpos) * (currenttempo / 480000.0));
+                               tickpos = (*ti).first;
+                               currenttempo = (*ti).second;
+                               ti++;
+                       }
+                       else
+                       {
+                               _currentconfig[difficulty].setEnd(_currentconfig[difficulty].getPosition() + (time - tickpos) * (currenttempo / 480000.0));
+                               tickpos = time;
+                       }
+               }
+
+               
+               _notes[difficulty][_currentconfig[difficulty].getTime()] = _currentconfig[difficulty];
+
+//             cout << "add note pos=" << _notes[difficulty][_currentconfig[difficulty].getTime()].getPosition() << " duration=" << _notes[difficulty][_currentconfig[difficulty].getTime()].getDuration() << endl;
+
+
+               _currentconfig[difficulty].setPosition(0);
+               _currentconfig[difficulty].setEnd(0);
+               _currentconfig[difficulty].setTicks(0);
+               _nbnotes[difficulty]++;
+       }
+       _currentconfig[difficulty].remKey(keys(key));
+/*
+       //if delta is 0, this is a new note
+       if (delta > 0)
+       {
+               _notes[difficulty][_currentconfig[difficulty].getTime()] = _currentconfig[difficulty];
+               //set the new position
+               _currentconfig[difficulty].setTime(_currentconfig[difficulty].getTime() + _currentconfig[difficulty].getDuration());
+               //set the new duration
+               _currentconfig[difficulty].setDuration(delta);
+       }
+       _currentconfig[difficulty].remKey(keys(key));
+  */
+/*  if (_notes[difficulty].empty())
+  {
+    _currentconfig[difficulty] = delta;
+    _currentconfig[difficulty].remKey(keys(key));
+    _notes[difficulty].push_back(_currentconfig[difficulty]);
+    _nbnotes[difficulty]++;
+    _totallength[difficulty] += delta;
+    return;
+  }
+
+  if (delta > 0)
+  {
+    _currentconfig[difficulty].remKey(keys(key));
+    _notes[difficulty].push_back(_currentconfig[difficulty]);
+    _currentconfig[difficulty].setTime(delta);
+    _nbnotes[difficulty]++;
+    _totallength[difficulty] += delta;
+  }
+  _currentconfig[difficulty].remKey(keys(key));*/
+//   cout << "remkey end" << endl;
+}
+
+Config Track::getNote(uint32 pos, uint8 difficulty)
+{
+       if (_notes[difficulty].count(pos) == 0)
+               throw 0;
+       return _notes[difficulty][pos];
+}
+
+uint32 Track::getTempo(uint32 pos)
+{
+       if (_tempo.count(pos) == 0)
+               throw 0;
+       return _tempo[pos];
+}
+
+void Track::computeBips()
+{
+       double pos = 0;
+       uint32 currenttempo = 120;
+       map<uint32,uint32>::iterator p = _tempo.begin();
+       for (uint32 i = 0 ; i < getEndOfTrack() ; i += 480)
+       {
+               //cout << "Bip @ " << pos << endl;
+               _bips.push_back(pos);
+               if (p != _tempo.end() && (*p).first <  i + 480)
+               {
+                       pos += ((*p).first - i) * (currenttempo / 480000.0);
+                       currenttempo = (*p).second;
+                       pos += (i + 480 - (*p).first) * (currenttempo / 480000.0);
+                       ++p;
+               }
+               else
+                       pos += currenttempo / 1000.0;
+       }
+}
+
+void Track::displayTracks()
+{
+  cout << "TRACK:" << endl;
+  for (uint8 k=0 ; k < NBDIFFICULTIES ; k++)
+  {
+    cout << "Difficulty " << (k+0) << ":" << endl;
+    for(map<uint32,Config>::iterator i = _notes[k].begin(); i != _notes[k].end(); ++i)
+      cout << (*i).first << ": " << (*i).second << endl;
+  }
+}
+
+void Track::debugTempo()
+{
+   cout << "Tempo changes: " << endl;
+   for( map<uint32,uint32>::iterator ii=_tempo.begin(); ii!=_tempo.end(); ++ii)
+       cout << (*ii).first << ": " << (*ii).second << " (" << ticksToBeats((*ii).second) << ")" << endl;
+}
+
+void Track::drawFrets(double postime) const
+{
+       static list<double>::const_iterator startingbips = _bips.begin();
+       
+// on avance tant que les bips sont dépassées
+       while (startingbips != _bips.end() && *startingbips < postime)
+       {
+               Mixer::getInstance()->playSound("bip");
+               if (logfile)
+                       fprintf(logfile, "Bip;%f;%f;%f\n", *startingbips, postime, postime - *startingbips);
+               startingbips++;
+       }
+
+       list<double>::const_iterator b = startingbips;
+
+       glMatrixMode(GL_MODELVIEW);
+       //on dessine les frettes jusqu'à 10s
+       while (b != _bips.end() && *b < postime + 10000)
+       {
+               glPushMatrix();
+               glTranslatef(0, 0, - SECONDSIZE * *b);
+                       glBegin(GL_QUADS);
+                               glColor3f(0.8, 0.8, 0.0);                       // Set The Color To Green
+                               glNormal3f(0, 0.5, 0.5);
+                               glVertex3f( NECKWIDTH,0, 0.1);
+                               glVertex3f( NECKWIDTH,0.1, 0);
+                               glVertex3f(-NECKWIDTH,0.1, 0);
+                               glVertex3f(-NECKWIDTH,0, 0.1);
+                               glNormal3f(0, 0.5, -0.5);
+                               glVertex3f( NECKWIDTH,0.1, 0);
+                               glVertex3f( NECKWIDTH,0, -0.1);
+                               glVertex3f(-NECKWIDTH,0, -0.1);
+                               glVertex3f(-NECKWIDTH,0.1, 0);
+                       glEnd();
+               glPopMatrix();
+               b++;
+       }
+}
+
+void Track::drawNotes(double postime, uint8 diff) const
+{
+       static map<uint32,Config>::const_iterator startingn = _notes[diff].begin();
+       static double startingpos = 0.0;
+
+//     cout << "startingpos=" << startingpos << " postime=" << postime << " first note at " << (*startingn).first << ":" << (*startingn).second.getPosition() << endl;
+
+       // on avance tant que les notes sont dépassées
+       while (startingn != _notes[diff].end())
+       {
+               double endpos = (*startingn).second.getPosition();
+               if ((*startingn).second.getTicks() > 240)
+                       endpos = (*startingn).second.getEnd();
+               if (endpos >= postime)
+                       break;
+               startingpos = (*startingn).second.getPosition();
+               (*startingn).second.log("Note", logfile);
+               startingn++;
+       }
+
+       map<uint32,Config>::const_iterator n = startingn;
+       
+       glMatrixMode(GL_MODELVIEW);
+       //on dessine les notes jusqu'à 10s
+       while (n != _notes[diff].end() && (*n).second.getEnd() < postime + 10000)
+       {
+               glPushMatrix();
+               glTranslatef(0, 0, - SECONDSIZE * (*n).second.getPosition());
+               (*n).second.display();
+               glPopMatrix();
+               n++;
+       }
+}
diff --git a/src/Triplet.cpp b/src/Triplet.cpp
new file mode 100644 (file)
index 0000000..0b5363d
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * 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.
+ */
+#ifdef __TRIPLET__
+
+#include <iostream>
+using namespace std;
+
+template <class T, class U, class V>
+Triplet<T, U, V>::Triplet(const T &x, const U &y, const V &z)
+:px(x), py(y), pz(z)
+{
+}
+
+template <class T, class U, class V>
+Triplet<T, U, V>::Triplet(const Triplet<T, U, V> &p)
+:px(p.px), py(p.py), pz(p.pz)
+{
+}
+
+template <class T, class U, class V>
+Triplet<T, U, V>::~Triplet()
+{
+}
+
+template <class T, class U, class V>
+const T &Triplet<T, U, V>::getX() const
+{
+  return px;
+}
+
+template <class T, class U, class V>
+const U &Triplet<T, U, V>::getY() const
+{
+  return py;
+}
+
+template <class T, class U, class V>
+const V &Triplet<T, U, V>::getZ() const
+{
+  return pz;
+}
+
+template <class T, class U, class V>
+void Triplet<T, U, V>::setX(const T &x)
+{
+  px = x;
+}
+
+template <class T, class U, class V>
+void Triplet<T, U, V>::setY(const U &y)
+{
+  py = y;
+}
+
+template <class T, class U, class V>
+void Triplet<T, U, V>::setZ(const V &z)
+{
+  pz = z;
+}
+
+///Use an exception ?
+// template <class T, class U, class V>
+// T &Triplet<T, U, V>::operator [] (const int &i)
+// {
+//   if (i == 0)
+//     return px;
+//   else
+//     return py;
+// }
+// 
+// template <class T, class U, class V>
+// T Triplet<T, U, V>::operator [] (const int &i) const
+// {
+//   if (i == 0)
+//     return px;
+//   else
+//     return py;
+// }
+
+
+template <class T, class U, class V>
+const Triplet<T, U, V> & Triplet<T, U, V>::operator = (const Triplet<T, U, V> &p)
+{
+  px = p.px;
+  py = p.py;
+  pz = p.pz;
+  return *this;
+}
+
+template <class T, class U, class V>
+bool Triplet<T, U, V>::operator == (const Triplet<T, U, V> &p) const
+{
+  return (px == p.px) && (py == p.py) && (pz == p.pz);
+}
+
+template <class T, class U, class V>
+Triplet<T, U, V> operator + (const Triplet<T, U, V> &p1, const Triplet<T, U, V> &p2)
+{
+  Triplet<T, U, V> result;
+  result.px = p1.px + p2.px;
+  result.py = p1.py + p2.py;
+  result.pz = p1.pz + p2.pz;
+  return result;
+}
+
+template <class T, class U, class V>
+Triplet<T, U, V> operator + (const T &a, const Triplet<T, U, V> &p)
+{
+  return p + Triplet<T, U, V>(a, a, a);
+}
+
+template <class T, class U, class V>
+Triplet<T, U, V> operator + (const Triplet<T, U, V> &p, const U &a)
+{
+  return p + Triplet<T, U, V>(a, a, a);
+}
+
+template <class T, class U, class V>
+Triplet<T, U, V> operator - (const Triplet<T, U, V> &p1, const Triplet<T, U, V> &p2)
+{
+  Triplet<T, U, V> result;
+  result.px = p1.px - p2.px;
+  result.py = p1.py - p2.py;
+  result.py = p1.pz - p2.pz;
+  return result;
+}
+
+template <class T, class U, class V>
+Triplet<T, U, V> operator - (const T &a, const Triplet<T, U, V> &p)
+{
+  return Triplet<T, U, V>(a, a, a) - p ;
+}
+
+template <class T, class U, class V>
+Triplet<T, U, V> operator - (const Triplet<T, U, V> &p, const U &a)
+{
+  return p - Triplet<T, U, V>(a, a, a);
+}
+
+template <class T, class U, class V>
+Triplet<T, U, V> Triplet<T, U, V>::operator - (void)
+{
+  return Triplet<T, U, V>(-px, -py, -pz);
+}
+
+template <class T, class U, class V>
+Triplet<T, U, V> operator * (const Triplet<T, U, V> &p1, const Triplet<T, U, V> &p2)
+{
+  Triplet<T, U, V> result;
+  result.px = p1.px * p2.px;
+  result.py = p1.py * p2.py;
+  result.pz = p1.pz * p2.pz;
+  return result;
+}
+
+template <class T, class U, class V>
+Triplet<T, U, V> operator * (const T &a, const Triplet<T, U, V> &p)
+{
+  return p * Triplet<T, U, V>(a, a, a);
+}
+
+template <class T, class U, class V>
+Triplet<T, U, V> operator * (const Triplet<T, U, V> &p, const U &a)
+{
+  return p * Triplet<T, U, V>(a, a, a);
+}
+
+template <class T, class U, class V>
+Triplet<T, U, V> operator / (const Triplet<T, U, V> &p1, const Triplet<T, U, V> &p2)
+{
+  Triplet<T, U, V> result;
+  result.px = p1.px / p2.px;
+  result.py = p1.py / p2.py;
+  result.pz = p1.pz / p2.pz;
+  return result;
+}
+
+template <class T, class U, class V>
+Triplet<T, U, V> operator / (const T &a, const Triplet<T, U, V> &p)
+{
+  return Triplet<T, U, V>(a, a, a) / p;
+}
+
+template <class T, class U, class V>
+Triplet<T, U, V> operator / (const Triplet<T, U, V> &p, const U &a)
+{
+  return p / Triplet<T, U, V>(a, a, a);
+}
+
+template <class T, class U, class V>
+ostream &operator << (ostream &os, const Triplet<T, U, V> &p)
+{
+  os << "(" << p.px << "," << p.py << "," << p.pz << ")";
+  return os;
+}
+
+#endif
diff --git a/src/Vector2D.cpp b/src/Vector2D.cpp
new file mode 100644 (file)
index 0000000..12abaf6
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * 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.
+ */
+#ifdef __VECTOR2D__
+
+#include <iostream>
+using namespace std;
+
+template <class T>
+Vector2D<T>::Vector2D(const T &x, const T &y)
+:Pair<T, T>(x, y)
+{
+}
+
+template <class T>
+Vector2D<T>::Vector2D(const Vector2D<T> &p)
+:Pair<T, T>(p)
+{
+}
+
+template <class T>
+Vector2D<T>::~Vector2D()
+{
+}
+
+/*
+template <class T>
+T Vector2D<T>::getX() const
+{
+  return px;
+}
+
+template <class T>
+T Vector2D<T>::getY() const
+{
+  return py;
+}
+
+template <class T>
+void Vector2D<T>::setX(const T &x)
+{
+  px = x;
+}
+
+template <class T>
+void Vector2D<T>::setY(const T &y)
+{
+  py = y;
+}*/
+
+///Use an exception ?
+template <class T>
+T &Vector2D<T>::operator [] (const int &i)
+{
+  if (i == 0)
+    return this->px;
+  else
+    return this->py;
+}
+
+template <class T>
+const T &Vector2D<T>::operator [] (const int &i) const
+{
+  if (i == 0)
+    return this->px;
+  else
+    return this->py;
+}
+
+/*
+template <class T>
+const Vector2D<T> & Vector2D<T>::operator = (const Vector2D<T> &p)
+{
+  px = p.px;
+  py = p.py;
+  return *this;
+}
+
+template <class T>
+bool Vector2D<T>::operator == (const Vector2D<T> &p) const
+{
+  return (px == p.px) && (py == p.py);
+}*/
+
+template <class T>
+Vector2D<T> operator + (const Vector2D<T> &p1, const Vector2D<T> &p2)
+{
+  Vector2D<T> result;
+  result.px = p1.px + p2.px;
+  result.py = p1.py + p2.py;
+  return result;
+}
+
+template <class T>
+Vector2D<T> operator + (const T &a, const Vector2D<T> &p)
+{
+  return p + Vector2D<T>(a, a);
+}
+
+template <class T>
+Vector2D<T> operator + (const Vector2D<T> &p, const T &a)
+{
+  return p + Vector2D<T>(a, a);
+}
+
+template <class T>
+Vector2D<T> operator - (const Vector2D<T> &p1, const Vector2D<T> &p2)
+{
+  Vector2D<T> result;
+  result.px = p1.px - p2.px;
+  result.py = p1.py - p2.py;
+  return result;
+}
+
+template <class T>
+Vector2D<T> operator - (const T &a, const Vector2D<T> &p)
+{
+  return Vector2D<T>(a, a) - p ;
+}
+
+template <class T>
+Vector2D<T> operator - (const Vector2D<T> &p, const T &a)
+{
+  return p - Vector2D<T>(a, a);
+}
+
+template <class T>
+Vector2D<T> Vector2D<T>::operator - (void)
+{
+  return Vector2D<T>(-this->px, -this->py);
+}
+
+template <class T>
+Vector2D<T> operator * (const Vector2D<T> &p1, const Vector2D<T> &p2)
+{
+  Vector2D<T> result;
+  result.px = p1.px * p2.px;
+  result.py = p1.py * p2.py;
+  return result;
+}
+
+template <class T>
+Vector2D<T> operator * (const T &a, const Vector2D<T> &p)
+{
+  return p * Vector2D<T>(a, a);
+}
+
+template <class T>
+Vector2D<T> operator * (const Vector2D<T> &p, const T &a)
+{
+  return p * Vector2D<T>(a, a);
+}
+
+template <class T>
+Vector2D<T> operator / (const Vector2D<T> &p1, const Vector2D<T> &p2)
+{
+  Vector2D<T> result;
+  result.px = p1.px / p2.px;
+  result.py = p1.py / p2.py;
+  return result;
+}
+
+template <class T>
+Vector2D<T> operator / (const T &a, const Vector2D<T> &p)
+{
+  return Vector2D<T>(a, a) / p;
+}
+
+template <class T>
+Vector2D<T> operator / (const Vector2D<T> &p, const T &a)
+{
+  return p / Vector2D<T>(a, a);
+}
+
+/*template <class T>
+ostream &operator << (ostream &os, const Vector2D<T> &p)
+{
+  os << "(" << p.px << "," << p.py << ")";
+  return os;
+}*/
+
+#endif
diff --git a/src/Vector3D.cpp b/src/Vector3D.cpp
new file mode 100644 (file)
index 0000000..a2fa6e9
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * This source file is part of Dungeon Digger
+ * Website: http://sourceforge.net/projects/dungeondigger/
+ *
+ * Copyright (C) 2006 Dungeon Digger Team
+ *
+ * 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.
+ */
+#ifdef __VECTOR3D__
+
+#include <iostream>
+using namespace std;
+
+template <class T>
+Vector3D<T>::Vector3D(const T &x, const T &y, const T &z)
+:Triplet<T, T, T>(x, y, z)
+{
+}
+
+template <class T>
+Vector3D<T>::Vector3D(const Vector3D<T> &p)
+:Triplet<T, T, T>(p)
+{
+}
+
+template <class T>
+Vector3D<T>::~Vector3D()
+{
+}
+
+///Use an exception ?
+template <class T>
+T &Vector3D<T>::operator [] (const int &i)
+{
+  if (i == 0)
+    return this->px;
+  else if (i == 1)
+    return this->py;
+  else
+    return this->pz;
+}
+
+template <class T>
+const T &Vector3D<T>::operator [] (const int &i) const
+{
+  if (i == 0)
+    return this->px;
+  else if (i == 1)
+    return this->py;
+  else
+    return this->pz;
+}
+
+template <class T>
+Vector3D<T> operator + (const Vector3D<T> &p1, const Vector3D<T> &p2)
+{
+  Vector3D<T> result;
+  result.px = p1.px + p2.px;
+  result.py = p1.py + p2.py;
+  result.pz = p1.pz + p2.pz;
+  return result;
+}
+
+template <class T>
+Vector3D<T> operator + (const T &a, const Vector3D<T> &p)
+{
+  return p + Vector3D<T>(a, a, a);
+}
+
+template <class T>
+Vector3D<T> operator + (const Vector3D<T> &p, const T &a)
+{
+  return p + Vector3D<T>(a, a, a);
+}
+
+template <class T>
+Vector3D<T> operator - (const Vector3D<T> &p1, const Vector3D<T> &p2)
+{
+  Vector3D<T> result;
+  result.px = p1.px - p2.px;
+  result.py = p1.py - p2.py;
+  result.pz = p1.pz - p2.pz;
+  return result;
+}
+
+template <class T>
+Vector3D<T> operator - (const T &a, const Vector3D<T> &p)
+{
+  return Vector3D<T>(a, a, a) - p ;
+}
+
+template <class T>
+Vector3D<T> operator - (const Vector3D<T> &p, const T &a)
+{
+  return p - Vector3D<T>(a, a, a);
+}
+
+template <class T>
+Vector3D<T> Vector3D<T>::operator - (void)
+{
+  return Vector3D<T>(-this->px, -this->py, -this->pz);
+}
+
+template <class T>
+Vector3D<T> operator * (const Vector3D<T> &p1, const Vector3D<T> &p2)
+{
+  Vector3D<T> result;
+  result.px = p1.px * p2.px;
+  result.py = p1.py * p2.py;
+  result.pz = p1.pz * p2.pz;
+  return result;
+}
+
+template <class T>
+Vector3D<T> operator * (const T &a, const Vector3D<T> &p)
+{
+  return p * Vector3D<T>(a, a, a);
+}
+
+template <class T>
+Vector3D<T> operator * (const Vector3D<T> &p, const T &a)
+{
+  return p * Vector3D<T>(a, a, a);
+}
+
+template <class T>
+Vector3D<T> operator / (const Vector3D<T> &p1, const Vector3D<T> &p2)
+{
+  Vector3D<T> result;
+  result.px = p1.px / p2.px;
+  result.py = p1.py / p2.py;
+  result.pz = p1.pz / p2.pz;
+  return result;
+}
+
+template <class T>
+Vector3D<T> operator / (const T &a, const Vector3D<T> &p)
+{
+  return Vector3D<T>(a, a, a) / p;
+}
+
+template <class T>
+Vector3D<T> operator / (const Vector3D<T> &p, const T &a)
+{
+  return p / Vector3D<T>(a, a, a);
+}
+
+#endif
diff --git a/src/Wiimote.cpp b/src/Wiimote.cpp
new file mode 100644 (file)
index 0000000..9698669
--- /dev/null
@@ -0,0 +1,119 @@
+#include "Wiimote.hpp"
+
+#include <iostream>
+using namespace std;
+
+#define MAX(X,Y) (((X)>(Y))?(X):(Y))
+#define MIN(X,Y) (((X)<(Y))?(X):(Y))
+
+Wiimote::Wiimote(int nb)
+:_wiimotes(wiiuse_init(nb)), _nb(nb), _strumstate(false)
+{
+       for (int i = 0 ; i < 5 ; i++)
+               _keystate[i] = false;
+
+       printf("wiimote structure : %p\n", _wiimotes);
+
+       int found = wiiuse_find(_wiimotes, nb, 5);
+       if (!found)
+       {
+               printf ("No wiimotes found.\n");
+               throw 0;
+       }
+
+       int connected = wiiuse_connect(_wiimotes, nb);
+       if (connected)
+               printf("Connected to %d wiimotes (of %d found).\n", connected, found);
+       else
+       {
+               printf("Failed to connect to any wiimote.\n");
+               throw 1;
+       }
+
+       for (int i = 0 ; i < MIN(nb,4) ; i++)
+       {
+//             cout << "+ leds of " << i << endl;
+               wiiuse_set_leds(_wiimotes[i], WIIMOTE_LED_1 * i);
+//             cout << "- leds of " << i << endl;
+       }
+
+}
+void Wiimote::handleKey(guitar_hero_3_t* gh3, int key, int button)
+{
+       if (_keystate[key])
+       {
+               if (!IS_PRESSED(gh3, button))
+                       handleButtonOff(key);
+               _keystate[key] = false;
+       }
+       else
+       {
+               if (IS_PRESSED(gh3, button))
+                       handleButtonOn(key);
+               _keystate[key] = true;
+       }
+}
+
+void Wiimote::handleEvents()
+{
+       if (!wiiuse_poll(_wiimotes, _nb))
+               return;
+       for (int i = 0 ; i < _nb ; i++)
+       {
+               switch(_wiimotes[i]->event)
+               {
+                       //normal event
+                       case WIIUSE_EVENT:
+                               if (_wiimotes[i]->exp.type == EXP_GUITAR_HERO_3)
+                               {
+                                       struct guitar_hero_3_t* gh3 = (guitar_hero_3_t *)&_wiimotes[i]->exp.gh3;
+
+                                       if (_strumstate)
+                                       {
+                                               if (!IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_STRUM_UP) && !IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_STRUM_DOWN))
+                                               {
+                                                       handleStrumOff();
+                                                       _strumstate = false;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               if (IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_STRUM_UP) || IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_STRUM_DOWN))
+                                               {
+                                                       handleStrumOn();
+                                                       _strumstate = true;
+                                               }
+                                       }
+
+                                       handleButtons(IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_GREEN),
+                                               IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_RED),
+                                               IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_YELLOW),
+                                               IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_BLUE),
+                                               IS_PRESSED(gh3, GUITAR_HERO_3_BUTTON_ORANGE));
+/*                                     handleKey(gh3, 0, GUITAR_HERO_3_BUTTON_GREEN);
+                                       handleKey(gh3, 1, GUITAR_HERO_3_BUTTON_RED);
+                                       handleKey(gh3, 2, GUITAR_HERO_3_BUTTON_YELLOW);
+                                       handleKey(gh3, 3, GUITAR_HERO_3_BUTTON_BLUE);
+                                       handleKey(gh3, 4, GUITAR_HERO_3_BUTTON_ORANGE);*/
+                               }
+
+                               break;
+
+                       case WIIUSE_GUITAR_HERO_3_CTRL_INSERTED:
+                               cout << "Ready to rock!" << endl;
+                               break;
+
+                       case WIIUSE_GUITAR_HERO_3_CTRL_REMOVED:
+                               cout << "This is the end..." << endl;
+                               break;
+
+                       default:
+                               break;
+               }
+       }
+       
+}
+
+void Wiimote::vibration(int wiimote, int time)
+{
+}
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644 (file)
index 0000000..f353f6b
--- /dev/null
@@ -0,0 +1,561 @@
+#include <iostream>
+
+#include "MIDIReader.hpp"
+#include "Track.hpp"
+#include "Texture.hpp"
+#include "Mixer.hpp"
+
+#include <sys/time.h>
+#include <list>
+/*#ifdef __APPLE__
+#include <SDL_mixer/SDL_mixer.h>
+#else
+#include <SDL/SDL_mixer.h>
+#endif*/
+
+#include <GL/glew.h>
+#include <SDL/SDL.h>
+#include <SDL/SDL_mixer.h>
+#include <SDL/SDL_image.h>
+extern double SECONDSIZE;
+
+#include "Wiimote.hpp"
+
+double posx, posy, posz;
+struct timeval start;
+Texture *texturebois, *texturefond;
+int resolution_x, resolution_y;
+Config fromKeyboard;
+
+int bandVolume, guitarVolume, bipVolume;
+
+FILE *logfile = NULL;
+//list<double> bips;
+//list<double>::iterator cb;
+
+void init()
+{
+  //initializes SDL
+  cout << "init SDL" << endl;
+  const SDL_VideoInfo* info = NULL;
+
+  atexit(SDL_Quit);
+
+  if( SDL_Init(SDL_INIT_EVERYTHING) <0 )
+    throw "Error while loading SDL";
+
+  //Initialize SDL_mixer
+  if (Mix_OpenAudio( 22050, MIX_DEFAULT_FORMAT, 2, 1024 ) == -1 );
+//    throw String("Can't initialize sound");
+
+  cout << "get video info" << endl;
+  info = SDL_GetVideoInfo();
+  if(!info)
+    throw "Impossible to get information from SDL";
+
+  SDL_EnableUNICODE(1);
+
+//   int width, height;
+  // we search for the available screen sizes
+  int searchflags = SDL_HWSURFACE;// | SDL_FULLSCREEN;
+  SDL_Rect **modes = SDL_ListModes(NULL, searchflags);
+  if (modes == NULL)
+    throw "Impossible to get the screen resolution !";
+  else if (modes == (SDL_Rect **)-1)
+  {
+    resolution_x = 1280;
+    resolution_y = 1024;
+  }
+  else
+  {
+    int i;
+    for (i=0 ; modes[i] ; i++)
+    {
+      cout << "Resolution available: " << modes[i]->w << "x" << modes[i]->h << endl;
+      if (modes[i]->w == 1280 && modes[i]->h == 1024)
+      {
+        resolution_x = modes[i]->w;
+        resolution_y = modes[i]->h;
+        break;
+      }
+    }
+    if (!modes[i])
+    {
+      cout << "Resolution wanted not available" << endl;
+      resolution_x = 1024;
+      resolution_y = 768;
+    }
+  }
+
+  //initializes Opengl
+  if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
+    throw "Couldn't initialise Video SubSystem: %s\n";
+
+  SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+  SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+  SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
+  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+  SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 8);
+  SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 8);
+  SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 8);
+  SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 8);
+
+  int flags = SDL_OPENGL | SDL_OPENGLBLIT | SDL_HWSURFACE;// | SDL_FULLSCREEN;
+
+//   int flags = SDL_OPENGL | SDL_OPENGLBLIT | SDL_SWSURFACE | SDL_FULLSCREEN;
+  SDL_Surface * screen;
+  if (!(screen = SDL_SetVideoMode(resolution_x, resolution_y, 0, flags)))
+    throw "Impossible to change the video mode";
+
+  // Utilisation de l'anti-aliasing possible ?
+  if (SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1) == -1)
+    throw "Impossible  to initialize SDL_GL_MULTISAMPLEBUFFERS";
+
+  // Nombre de tampons utilisés pour l'anti-aliasing (la valeur utilisée dépend de la carte graphique)
+  if (SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 6) == -1)
+    throw "Impossible to initialize SDL_GL_MULTISAMPLESAMPLES";
+
+  GLdouble ratio = (GLdouble) screen->w / screen->h;
+
+  printf("infos : %d %d %d %d\n", screen->flags, screen->w, screen->h, screen->pitch);
+  printf("Video resolution: %dx%dx%d (ratio = %3.2f)\n", screen->w, screen->h, screen->format->BitsPerPixel, ratio);
+  printf("OpenGL infos\n");
+  printf("------------\n");
+  printf("Vendor    : %s\n", glGetString(GL_VENDOR));
+  printf("Renderer  : %s\n", glGetString(GL_RENDERER));
+  printf("Version   : %s\n", glGetString(GL_VERSION));
+  printf("Extensions: %s\n", glGetString(GL_EXTENSIONS));
+
+  glClearColor(1.0, 1.0, 1.0, 0.0);
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  glViewport(0, 0, resolution_x, resolution_y);
+
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glEnable(GL_BLEND);
+  glShadeModel(GL_SMOOTH);
+  glEnable(GL_NORMALIZE);
+       
+  GLfloat light_ambient[] = { 0.8, 0.7, 0.9, 1.0 };
+  GLfloat light_diffuse[] = { 1.0, 0.9, 0.8, 1.0 };
+  GLfloat light_specular[] = { 1.0, 0.9, 0.7, 1.0};
+  glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
+  glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
+  glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
+//   glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 0.5);
+  glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.01);
+  glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.01);
+  glEnable(GL_LIGHTING);
+  glEnable(GL_LIGHT0);
+//  SDL_EnableKeyRepeat(10, 100);
+
+       texturebois = new Texture("wood.jpg", true);
+       texturefond = new Texture("back.jpg");
+
+       posx=0.0;
+       posy=25.0;
+       posz=0.0;
+
+       fromKeyboard.setPosition(-1);
+       fromKeyboard.setEnd(-1);
+}
+
+#define POSITION_EYE    45
+#define POSITION_CENTER (-80)
+#define VIEWLENGTH 250
+
+
+void draw(Track &t, uint8 diff)
+{
+       struct timeval now;
+       gettimeofday(&now, NULL);
+       double postime = (now.tv_sec - start.tv_sec) * 1000. + (now.tv_usec - start.tv_usec) / 1000.0;
+       posz = -SECONDSIZE * postime;
+
+//   cout << "draw screen" << endl;
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+//     glColor(1.0, 1.0, 1.0, 0.0);
+
+       //Draw the back
+  glDisable(GL_LIGHTING);
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluOrtho2D(0, resolution_x, resolution_y, 0);
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+
+  glEnable(GL_TEXTURE_2D);
+       texturefond->useTexture();
+       glBegin(GL_QUADS);
+               glColor3f(1.0, 1.0, 1.0);
+               glTexCoord2d(0.0, 0.0); glVertex2f(0.0, 0.0);
+               glTexCoord2d(0.0, 1.0); glVertex2f(0.0, resolution_y);
+               glTexCoord2d(1.0, 1.0); glVertex2f(resolution_x, resolution_y);
+               glTexCoord2d(1.0, 0.0); glVertex2f(resolution_x, 0.0);
+       glEnd();
+  glDisable(GL_TEXTURE_2D);
+               
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+       gluPerspective( 45.0f, double(resolution_x) / double(resolution_y), POSITION_EYE+3, VIEWLENGTH );
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+       //cout << "posz=" << posz << endl;
+       gluLookAt(posx, posy, posz + POSITION_EYE, 0, 0, posz + POSITION_CENTER, 0.0,1.0,0.0);
+//     gluLookAt(posx-50, posy, posz-POSITION, 0, 0,posz-POSITION, 0.0,1.0,0.0);
+       GLfloat light_position[] = { 0.0, 10.0 , posz, 1.0 };
+  glLightfv(GL_LIGHT1, GL_POSITION, light_position);
+       
+//     cout << "End: " << t.getEndOfTrack() << endl;
+
+//glEnable(GL_LIGHTING);
+
+       // Draw the guitar neck
+  glEnable(GL_TEXTURE_2D);
+       texturebois->useTexture();
+       glBegin(GL_QUADS);
+               glColor3f(1.0, 1.0, 1.0);                       // Set The Color To Green
+               glTexCoord2d(0.0, 0.0); glVertex3f( NECKWIDTH,0, 0);
+               glTexCoord2d(0.0, 20000); glVertex3f( NECKWIDTH,0,-1500000);
+               glTexCoord2d(1.0, 20000); glVertex3f(-NECKWIDTH,0,-1500000);
+               glTexCoord2d(1.0, 0.0); glVertex3f(-NECKWIDTH,0, 0);
+       glEnd();
+  glDisable(GL_TEXTURE_2D);
+       
+       //Draw the position bar
+  glMatrixMode(GL_MODELVIEW);
+       glPushMatrix();
+       glTranslatef(0,0,posz);
+       glBegin(GL_QUADS);
+               glColor3f(0.8, 0.8, 0.8);
+               glNormal3f(0, 1, 0);
+               glVertex3f( NECKWIDTH,0, 1);
+               glVertex3f( NECKWIDTH,0.2, 0);
+               glVertex3f(-NECKWIDTH,0.2, 0);
+               glVertex3f(-NECKWIDTH,0, 1);
+               glVertex3f( NECKWIDTH,0.2, 0);
+               glVertex3f( NECKWIDTH,0, -1);
+               glVertex3f(-NECKWIDTH,0, -1);
+               glVertex3f(-NECKWIDTH,0.2, 0);
+       glEnd();
+       glBegin(GL_QUADS);
+               glColor3f(0.8, 0.8, 0.8);
+               glNormal3f(0, 1, 0);
+               glVertex3f(NECKWIDTH, 0, 1);
+               glVertex3f(NECKWIDTH+.1,0.2, 1);
+               glVertex3f(NECKWIDTH+.1,0.2,-VIEWLENGTH);
+               glVertex3f(NECKWIDTH,0, -VIEWLENGTH);
+               glVertex3f(NECKWIDTH+.1, 0.2, 1);
+               glVertex3f(NECKWIDTH+.2,0, 1);
+               glVertex3f(NECKWIDTH+.2,0,-VIEWLENGTH);
+               glVertex3f(NECKWIDTH+.1,0.2, -VIEWLENGTH);
+       glEnd();
+       glBegin(GL_QUADS);
+               glColor3f(0.8, 0.8, 0.8);
+               glNormal3f(0, 1, 0);
+               glVertex3f(-NECKWIDTH, 0, 1);
+               glVertex3f(-NECKWIDTH-.1,0.2, 1);
+               glVertex3f(-NECKWIDTH-.1,0.2,-VIEWLENGTH);
+               glVertex3f(-NECKWIDTH,0, -VIEWLENGTH);
+               glVertex3f(-NECKWIDTH-.1, 0.2, 1);
+               glVertex3f(-NECKWIDTH-.2,0, 1);
+               glVertex3f(-NECKWIDTH-.2,0,-VIEWLENGTH);
+               glVertex3f(-NECKWIDTH-.1,0.2, -VIEWLENGTH);
+       glEnd();
+       fromKeyboard.display();
+       glPopMatrix();
+
+       //draw the frets
+       t.drawFrets(postime);
+
+       // Draw the notes
+       t.drawNotes(postime, diff);
+
+       SDL_GL_SwapBuffers();
+}
+
+void handleKeyOn(keys k)
+{
+       fromKeyboard.addKey(k);
+/*     switch(k)
+       {
+               case KEY0:
+                       cout << "\033[1;32mGREEN\033[0m" << endl;
+                       break;
+               case KEY1:
+                       cout << "\033[0;31mRED\033[0m" << endl;
+                       break;
+               case KEY2:
+                       cout << "\033[1;33mYELLOW\033[0m" << endl;
+                       break;
+               case KEY3:
+                       cout << "\033[1;34mBLUE\033[0m" << endl;
+                       break;
+               case KEY4:
+                       cout << "\033[0;33mORANGE\033[0m" << endl;
+                       break;
+       }*/
+}
+
+void handleKeyOff(keys k)
+{
+//     fromKeyboard.remKey(k);
+       if (fromKeyboard.getPosition() == -1)
+               return;
+               
+       struct timeval now;
+       gettimeofday(&now, NULL);
+       double postime = (now.tv_sec - start.tv_sec) * 1000 + (now.tv_usec - start.tv_usec) / 1000.0;
+       fromKeyboard.setEnd(postime);
+       cout << fromKeyboard << endl;
+       fromKeyboard.log("Play", logfile);
+
+       fromKeyboard.setPosition(postime);
+       fromKeyboard.setEnd(-1);
+}
+
+void handleKeys(bool a, bool b, bool c, bool d, bool e)
+{
+       if (fromKeyboard.isNone())
+               fromKeyboard.setPosition(-1);
+       fromKeyboard.setKeys(a, b, c, d, e);
+}
+
+void handleStrokeOn()
+{
+       struct timeval now;
+       gettimeofday(&now, NULL);
+       double postime = (now.tv_sec - start.tv_sec) * 1000 + (now.tv_usec - start.tv_usec) / 1000.0;
+       //cout << postime << endl;
+
+       if (fromKeyboard.getPosition() != -1)
+       {
+               fromKeyboard.setEnd(postime);
+               cout << fromKeyboard << endl;
+               fromKeyboard.log("Play", logfile);
+       }
+       fromKeyboard.setPosition(postime);
+       fromKeyboard.setEnd(-1);
+}
+
+void handleStrokeOff()
+{
+}
+
+class MyWiimote: public Wiimote
+{
+       public:
+               MyWiimote():Wiimote(1){}
+
+               void handleStrumOn() { handleStrokeOn(); }
+               void handleStrumOff() { handleStrokeOff(); }
+               void handleButtonOn(int k) { handleKeyOn(keys(k)); }
+               void handleButtonOff(int k) { handleKeyOff(keys(k)); }
+               void handleButtons(bool a, bool b, bool c, bool d, bool e) { handleKeys(a, b, c, d, e); }
+};
+
+bool processEvents()
+{
+  SDL_Event event;
+//   bool quitProgram = false;
+
+  while (SDL_PollEvent (&event))
+       {
+               Uint8 *keystate;
+               switch (event.type)
+               {
+                       case SDL_QUIT:
+                               return true;
+                               break;
+
+                       case SDL_KEYDOWN:
+                               keystate = SDL_GetKeyState(NULL);
+                               handleKeys(keystate[SDLK_a], keystate[SDLK_z], keystate[SDLK_e], keystate[SDLK_r], keystate[SDLK_t]);
+                               switch(((SDL_KeyboardEvent *)(&event))->keysym.sym)
+                               {
+                                       case SDLK_ESCAPE:
+                                               return true;
+                                       case SDLK_UP:
+                                               SECONDSIZE +=10;
+                                               break;
+                                       case SDLK_DOWN:
+                                               SECONDSIZE -=1;
+                                               break;
+                                       case SDLK_LEFT:
+                                               posy +=1;
+                                               break;
+                                       case SDLK_RIGHT:
+                                               posy -=1;
+                                               break;
+                                       case SDLK_KP_PLUS:
+                                               Mixer::getInstance()->setMusicVolume(Mixer::getInstance()->getMusicVolume() + 10);
+                                               Mixer::getInstance()->setSoundVolume(Mixer::getInstance()->getSoundVolume() + 10);
+                                               break;
+                                       case SDLK_KP_MINUS:
+                                               Mixer::getInstance()->setMusicVolume(Mixer::getInstance()->getMusicVolume() - 10);
+                                               Mixer::getInstance()->setSoundVolume(Mixer::getInstance()->getSoundVolume() - 10);
+                                               break;
+/*                                     case SDLK_a:
+                                               handleKeyOn(KEY0);
+                                               break;
+                                       case SDLK_z:
+                                               handleKeyOn(KEY1);
+                                               break;
+                                       case SDLK_e:
+                                               handleKeyOn(KEY2);
+                                               break;
+                                       case SDLK_r:
+                                               handleKeyOn(KEY3);
+                                               break;
+                                       case SDLK_t:
+                                               handleKeyOn(KEY4);
+                                               break;*/
+                                       case SDLK_SPACE:
+                                               handleStrokeOn();
+                                               break;
+                                       default:
+                                               break;
+                               }
+                               break;
+
+                       case SDL_KEYUP:
+                               switch(((SDL_KeyboardEvent *)(&event))->keysym.sym)
+                               {
+                                       case SDLK_a:
+                                               handleKeyOff(KEY0);
+                                               break;
+                                       case SDLK_z:
+                                               handleKeyOff(KEY1);
+                                               break;
+                                       case SDLK_e:
+                                               handleKeyOff(KEY2);
+                                               break;
+                                       case SDLK_r:
+                                               handleKeyOff(KEY3);
+                                               break;
+                                       case SDLK_t:
+                                               handleKeyOff(KEY4);
+                                               break;
+                                       case SDLK_SPACE:
+                                               handleStrokeOff();
+                                               break;
+                                       default:
+                                               break;
+                               }
+                               keystate = SDL_GetKeyState(NULL);
+                               handleKeys(keystate[SDLK_a], keystate[SDLK_z], keystate[SDLK_e], keystate[SDLK_r], keystate[SDLK_t]);
+                               break;
+                       default:
+       //       lasteventtype = OTHER;
+                               break;
+               }
+       }
+  return false;
+}
+
+int main(int argc, char *argv[])
+{
+       bool iswiimoteconnected = false;
+       Wiimote *mw;
+       try
+       {
+               mw = new MyWiimote();
+               iswiimoteconnected = true;
+       }
+       catch(...){}
+
+       if (argc < 2)
+       {
+               cout << "Usage : " << argv[0] << "songname" << endl;
+               exit(0);
+       }
+       String songname(argv[1]);
+
+       if (argc >= 3)
+       {
+               time_t tim = time(NULL);
+               struct tm *t  = gmtime(&tim);
+    String logfilename = String(argv[2]) + "-" + String(1900 + t->tm_year) + "-" + String(t->tm_mon) + "-" + String(t->tm_mday) + "-" + String(t->tm_hour) + "-" + String(t->tm_min) + "-" + String(t->tm_sec) + "-" + String(argv[1]);
+    logfile = fopen(logfilename.c_str(), "w");
+       }
+
+       init();
+
+       cout << "Loading song" << endl;
+       MIDIReader *test;
+       try
+       {
+               test = new MIDIReader(songname + "/notes.mid");
+       }
+       catch(...)
+       {
+               cerr << "Unable to load the song file" << endl;
+               exit(0);
+       }
+
+       cout << "Loading notes" << endl;
+
+  test->readHeader();
+       Track tr;
+  test->readTracks(tr);
+
+       cout << "Computing metronome bips" << endl;
+
+       //compute the ticks positions
+       tr.computeBips();
+
+       bool quitProgram = false;
+
+       cout << "Loading sounds" << endl;
+
+       Mixer::getInstance()->addSound("guitar", songname + "/guitar.ogg");
+       bool rhythm = Mixer::getInstance()->addSound("rhythm", songname + "/rhythm.ogg");
+
+       Mixer::getInstance()->addSound("bip","bip.ogg");
+       Mixer::getInstance()->setMusicVolume(30);
+       Mixer::getInstance()->setSoundVolume(30);
+
+       cout << "LET'S ROCK!" << endl;
+
+       Mixer::getInstance()->playMusic(songname + "/song.ogg");
+       Mixer::getInstance()->playSound("guitar");
+       if (rhythm)
+               Mixer::getInstance()->playSound("rhythm");
+       gettimeofday(&start, NULL);
+/*
+       Sound music;
+       cout << "Load sounds" << endl;
+       music.addSound(songname + "/song.ogg");
+       music.addSound(songname + "/guitar.ogg");
+       music.addSound(songname + "/rhythm.ogg");
+       cout << "Mixing sounds" << endl;
+       Mix_Chunk *m_chunk = music.mix();
+       cout << "Play music" << endl;
+       Mix_PlayChannel(-1, m_chunk, 1);
+*/
+/*
+       Mix_Chunk *Mix_LoadWAV(char *file) x2/3
+       for(...)
+               a/3+b/3+c/3;
+       int Mix_SetPanning(int channel, Uint8 left, Uint8 right) left + right
+       int Mix_PlayChannel(int channel, Mix_Chunk *chunk, int loops)
+*/
+
+  while(!quitProgram)
+  {
+//             cout << "events" << endl;
+    quitProgram = processEvents();
+               if (iswiimoteconnected)
+                       mw->handleEvents();
+//             cout << "draw" << endl;
+    draw(tr, NORMAL);
+//             cout << "pause" << endl;
+//    SDL_Delay(10);
+  }
+
+       if (logfile)
+               fclose(logfile);
+
+  return 1;
+}