1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2019 Joël Krähemann
3  *
4  * This file is part of GSequencer.
5  *
6  * GSequencer is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GSequencer is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with GSequencer.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef __AGS_CORE_AUDIO_MIDIIN_H__
21 #define __AGS_CORE_AUDIO_MIDIIN_H__
22 
23 #include <glib.h>
24 #include <glib-object.h>
25 
26 #include <ags/libags.h>
27 
28 G_BEGIN_DECLS
29 
30 #define AGS_TYPE_CORE_AUDIO_MIDIIN                (ags_core_audio_midiin_get_type())
31 #define AGS_CORE_AUDIO_MIDIIN(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_CORE_AUDIO_MIDIIN, AgsCoreAudioMidiin))
32 #define AGS_CORE_AUDIO_MIDIIN_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST(class, AGS_TYPE_CORE_AUDIO_MIDIIN, AgsCoreAudioMidiin))
33 #define AGS_IS_CORE_AUDIO_MIDIIN(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AGS_TYPE_CORE_AUDIO_MIDIIN))
34 #define AGS_IS_CORE_AUDIO_MIDIIN_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_CORE_AUDIO_MIDIIN))
35 #define AGS_CORE_AUDIO_MIDIIN_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS(obj, AGS_TYPE_CORE_AUDIO_MIDIIN, AgsCoreAudioMidiinClass))
36 
37 #define AGS_CORE_AUDIO_MIDIIN_GET_OBJ_MUTEX(obj) (&(((AgsCoreAudioMidiin *) obj)->obj_mutex))
38 
39 #define AGS_CORE_AUDIO_MIDIIN_DEFAULT_BUFFER_SIZE (256)
40 
41 typedef struct _AgsCoreAudioMidiin AgsCoreAudioMidiin;
42 typedef struct _AgsCoreAudioMidiinClass AgsCoreAudioMidiinClass;
43 
44 /**
45  * AgsCoreAudioMidiinFlags:
46  * @AGS_CORE_AUDIO_MIDIIN_ADDED_TO_REGISTRY: the CoreAudio midiin was added to registry, see #AgsConnectable::add_to_registry()
47  * @AGS_CORE_AUDIO_MIDIIN_CONNECTED: indicates the CoreAudio midiin was connected by calling #AgsConnectable::connect()
48  * @AGS_CORE_AUDIO_MIDIIN_BUFFER0: ring-buffer 0
49  * @AGS_CORE_AUDIO_MIDIIN_BUFFER1: ring-buffer 1
50  * @AGS_CORE_AUDIO_MIDIIN_BUFFER2: ring-buffer 2
51  * @AGS_CORE_AUDIO_MIDIIN_BUFFER3: ring-buffer 3
52  * @AGS_CORE_AUDIO_MIDIIN_ATTACK_FIRST: use first attack, instead of second one
53  * @AGS_CORE_AUDIO_MIDIIN_RECORD: is recording
54  * @AGS_CORE_AUDIO_MIDIIN_SHUTDOWN: stop recording
55  * @AGS_CORE_AUDIO_MIDIIN_START_RECORD: just started recording
56  * @AGS_CORE_AUDIO_MIDIIN_NONBLOCKING: do non-blocking calls
57  * @AGS_CORE_AUDIO_MIDIIN_INITIALIZED: recording is initialized
58  *
59  * Enum values to control the behavior or indicate internal state of #AgsCoreAudioMidiin by
60  * enable/disable as flags.
61  */
62 typedef enum
63 {
64   AGS_CORE_AUDIO_MIDIIN_ADDED_TO_REGISTRY  = 1,
65   AGS_CORE_AUDIO_MIDIIN_CONNECTED          = 1 <<  1,
66 
67   AGS_CORE_AUDIO_MIDIIN_BUFFER0            = 1 <<  2,
68   AGS_CORE_AUDIO_MIDIIN_BUFFER1            = 1 <<  3,
69   AGS_CORE_AUDIO_MIDIIN_BUFFER2            = 1 <<  4,
70   AGS_CORE_AUDIO_MIDIIN_BUFFER3            = 1 <<  5,
71 
72   AGS_CORE_AUDIO_MIDIIN_ATTACK_FIRST       = 1 <<  6,
73 
74   AGS_CORE_AUDIO_MIDIIN_RECORD             = 1 <<  7,
75 
76   AGS_CORE_AUDIO_MIDIIN_SHUTDOWN           = 1 <<  8,
77   AGS_CORE_AUDIO_MIDIIN_START_RECORD       = 1 <<  9,
78 
79   AGS_CORE_AUDIO_MIDIIN_NONBLOCKING        = 1 << 10,
80   AGS_CORE_AUDIO_MIDIIN_INITIALIZED        = 1 << 11,
81 }AgsCoreAudioMidiinFlags;
82 
83 /**
84  * AgsCoreAudioMidiinSyncFlags:
85  * @AGS_CORE_AUDIO_MIDIIN_PASS_THROUGH: do not sync
86  * @AGS_CORE_AUDIO_MIDIIN_INITIAL_CALLBACK: initial callback
87  * @AGS_CORE_AUDIO_MIDIIN_CALLBACK_WAIT: sync wait, soundcard conditional lock
88  * @AGS_CORE_AUDIO_MIDIIN_CALLBACK_DONE: sync done, soundcard conditional lock
89  * @AGS_CORE_AUDIO_MIDIIN_CALLBACK_FINISH_WAIT: sync wait, client conditional lock
90  * @AGS_CORE_AUDIO_MIDIIN_CALLBACK_FINISH_DONE: sync done, client conditional lock
91  * @AGS_CORE_AUDIO_MIDIIN_DO_SYNC: do synchronize
92  *
93  * Enum values to control the synchronization between soundcard and client.
94  */
95 typedef enum{
96   AGS_CORE_AUDIO_MIDIIN_PASS_THROUGH                   = 1,
97   AGS_CORE_AUDIO_MIDIIN_INITIAL_CALLBACK               = 1 <<  1,
98   AGS_CORE_AUDIO_MIDIIN_CALLBACK_WAIT                  = 1 <<  2,
99   AGS_CORE_AUDIO_MIDIIN_CALLBACK_DONE                  = 1 <<  3,
100   AGS_CORE_AUDIO_MIDIIN_CALLBACK_FINISH_WAIT           = 1 <<  4,
101   AGS_CORE_AUDIO_MIDIIN_CALLBACK_FINISH_DONE           = 1 <<  5,
102   AGS_CORE_AUDIO_MIDIIN_DO_SYNC                        = 1 <<  6,
103 }AgsCoreAudioMidiinSyncFlags;
104 
105 #define AGS_CORE_AUDIO_MIDIIN_ERROR (ags_core_audio_midiin_error_quark())
106 
107 typedef enum{
108   AGS_CORE_AUDIO_MIDIIN_ERROR_LOCKED_SOUNDCARD,
109 }AgsCoreAudioMidiinError;
110 
111 struct _AgsCoreAudioMidiin
112 {
113   GObject gobject;
114 
115   guint flags;
116   volatile guint sync_flags;
117 
118   GRecMutex obj_mutex;
119 
120   AgsUUID *uuid;
121 
122   GRecMutex **buffer_mutex;
123   char **buffer;
124   guint buffer_size[4];
125 
126   double bpm; // beats per minute
127 
128   gdouble delay;
129   gdouble delay_factor;
130   guint latency;
131 
132   gdouble tact_counter;
133   gdouble delay_counter; // next time attack changeing when delay_counter == delay
134   guint tic_counter; // in the range of default period
135 
136   guint start_note_offset;
137   guint note_offset;
138   guint note_offset_absolute;
139 
140   gchar *card_uri;
141   GObject *core_audio_client;
142 
143   gchar **port_name;
144   GList *core_audio_port;
145 
146   GMutex callback_mutex;
147   GCond callback_cond;
148 
149   GMutex callback_finish_mutex;
150   GCond callback_finish_cond;
151 };
152 
153 struct _AgsCoreAudioMidiinClass
154 {
155   GObjectClass gobject;
156 };
157 
158 GType ags_core_audio_midiin_get_type();
159 
160 GQuark ags_core_audio_midiin_error_quark();
161 
162 gboolean ags_core_audio_midiin_test_flags(AgsCoreAudioMidiin *core_audio_midiin, guint flags);
163 void ags_core_audio_midiin_set_flags(AgsCoreAudioMidiin *core_audio_midiin, guint flags);
164 void ags_core_audio_midiin_unset_flags(AgsCoreAudioMidiin *core_audio_midiin, guint flags);
165 
166 void ags_core_audio_midiin_switch_buffer_flag(AgsCoreAudioMidiin *core_audio_midiin);
167 
168 AgsCoreAudioMidiin* ags_core_audio_midiin_new();
169 
170 G_END_DECLS
171 
172 #endif /*__AGS_CORE_AUDIO_MIDIIN_H__*/
173