Import upstream version 0.99.2
[fmit.git] / libs / Music / omidistream.h
1 // Copyright 2004 "Gilles Degottex"
2
3 // This file is part of "Music"
4
5 // "Music" is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published by
7 // the Free Software Foundation; either version 2.1 of the License, or
8 // (at your option) any later version.
9 // 
10 // "Music" is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 // 
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19
20 #ifndef _omidistream_h_
21 #define _omidistream_h_
22
23 #include <string>
24 #include <queue>
25 #include <map>
26 using namespace std;
27 #include <alsa/asoundlib.h>
28
29 namespace Music
30 {
31         class omidistream;
32
33 #define MIDI_TIME_DIRECT -1.0
34
35         //! a simple note (and an abstract one)
36         class note
37         {
38                 friend class omidistream;
39           public:       
40                 static queue<unsigned char> s_free_tags;
41                 static map<unsigned char, unsigned char> s_tags;
42
43           protected:
44                 static unsigned char getFreeTag();
45                 static void addNote(unsigned char tag, unsigned char note)      {s_tags.insert(make_pair(tag, note));}
46                 static unsigned char getNote(unsigned char tag)                         {return (*(s_tags.find(tag))).second;}
47
48                 snd_seq_event_t m_ev;
49
50                 note(){}
51
52           public:
53                 //! unique ctor
54                 /*! no direct send can be used ! TODO do it ...
55                  *
56                  * \param n the pitch [0,127]
57                  * \param duration duration of the note {seconds}
58                  * \param t absolute time when the note must be played {seconds}
59                  */
60                 note(unsigned char n, double duration=1.0, double t=MIDI_TIME_DIRECT);
61
62                 //! return the internal tag of the note
63                 unsigned char getTag() const {return m_ev.tag;}
64         };
65
66         //! a starting note
67         class note_on : public note
68         {
69                 friend class omidistream;
70                 friend class note_off;
71
72           public:
73                 //! build a note on event
74                 /*!
75                  * \param n the pitch [0,127]
76                  * \param t absolute time when the note must be played {seconds}
77                  * \param pTag pTage the returning unique identifier of the note
78                  */
79                 note_on(unsigned char n, double t=MIDI_TIME_DIRECT);
80
81                 //! build an empty note on event
82                 note_on();
83         };
84
85         //! a ending note
86         class note_off : public note
87         {
88                 friend class omidistream;
89
90           public:
91                 //! build a note off event from the on event
92                 /*!
93                  * \param n_on the starting event
94                  * \param t absolute time when the note must be played {seconds}
95                  */
96                 note_off(const note_on& n_on, double t=MIDI_TIME_DIRECT);
97         };
98
99         //! a midi stream for outputing notes in the midi alsa sequencer
100         /*! sample:\n\n
101          *              omidistream str("test lib", 60);\n
102          *              str << note(64, 0) << note(64, 0.5) << note(64, 1) << note(66, 1.5) << note(68, 2, 2) << note(66, 3, 2) << note(64, 4) << note(68, 4.5) << note(66, 5) << note(66, 5.5) << note(64, 6, 2) << drain;\n
103          *     sleep(10);\n
104          */
105         class omidistream
106         {
107                 friend class note;
108
109                 snd_seq_t* m_seq;
110                 int m_queue;
111                 int m_port;
112                 unsigned char m_channel;
113                 int m_A3Index;
114
115           public:
116
117                 //! unique ctor
118                 /*!
119                  * \param name a name for the stream (shown in aconnect)
120                  * \param tempo the starting tempo of the whole stream {BPM (beats per minutes)}
121                  * \param channel midi channel where the note must be thrown [1,?]
122                  */
123                 omidistream(std::string name, double tempo, unsigned char channel=1);
124
125                 //! return the unique identifier of the alsa midi client
126                 int getAlsaMidiID()                             {return snd_seq_client_id(m_seq);}
127                 
128                 //! return the index of A3 in MIDI standard (69 by default)
129                 int getA3Index()                                {return m_A3Index;}
130
131                 //! return the alsa midi port associated to the output sequencer
132                 int getPort()                                   {return m_port;}
133
134                 //! manualy flush the stream
135                 omidistream& drain();
136
137                 //! output a note in the stream
138                 omidistream& operator<<(note n);
139                 inline omidistream& operator<<(note_on n){return operator<<((note)n);}
140                 inline omidistream& operator<<(note_off n){return operator<<((note)n);}
141
142                 //! stream operator for modifiers
143                 template<class Fn> omidistream& operator<<(Fn fn){fn(*this);return *this;}
144
145                 ~omidistream();
146         };
147
148         //! stream flushing modifier
149         omidistream& drain(omidistream& str);
150 }
151
152 #endif // _omidistream_h_
153