1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2020 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_FIFOOUT_H__
21 #define __AGS_FIFOOUT_H__
22 
23 #include <glib.h>
24 #include <glib-object.h>
25 
26 #include <sys/types.h>
27 
28 #include <ags/libags.h>
29 
30 G_BEGIN_DECLS
31 
32 #define AGS_TYPE_FIFOOUT                (ags_fifoout_get_type())
33 #define AGS_FIFOOUT(obj)                (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_FIFOOUT, AgsFifoout))
34 #define AGS_FIFOOUT_CLASS(class)        (G_TYPE_CHECK_CLASS_CAST(class, AGS_TYPE_FIFOOUT, AgsFifoout))
35 #define AGS_IS_FIFOOUT(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AGS_TYPE_FIFOOUT))
36 #define AGS_IS_FIFOOUT_CLASS(class)     (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_FIFOOUT))
37 #define AGS_FIFOOUT_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS(obj, AGS_TYPE_FIFOOUT, AgsFifooutClass))
38 
39 #define AGS_FIFOOUT_GET_OBJ_MUTEX(obj) (&(((AgsFifoout *) obj)->obj_mutex))
40 
41 #define AGS_FIFOOUT_DEFAULT_DEVICE "/dev/null"
42 
43 #define AGS_FIFOOUT_DEFAULT_RING_BUFFER_SIZE (8)
44 
45 typedef struct _AgsFifoout AgsFifoout;
46 typedef struct _AgsFifooutClass AgsFifooutClass;
47 
48 /**
49  * AgsFifooutFlags:
50  * @AGS_FIFOOUT_ADDED_TO_REGISTRY: the fifoout was added to registry, see #AgsConnectable::add_to_registry()
51  * @AGS_FIFOOUT_CONNECTED: indicates the fifoout was connected by calling #AgsConnectable::connect()
52  * @AGS_FIFOOUT_BUFFER0: ring-buffer 0
53  * @AGS_FIFOOUT_BUFFER1: ring-buffer 1
54  * @AGS_FIFOOUT_BUFFER2: ring-buffer 2
55  * @AGS_FIFOOUT_BUFFER3: ring-buffer 3
56  * @AGS_FIFOOUT_ATTACK_FIRST: use first attack, instead of second one
57  * @AGS_FIFOOUT_PLAY: use first attack, instead of second one
58  * @AGS_FIFOOUT_SHUTDOWN: stop playback
59  * @AGS_FIFOOUT_START_PLAY: playback starting
60  * @AGS_FIFOOUT_NONBLOCKING: do non-blocking calls
61  * @AGS_FIFOOUT_INITIALIZED: the soundcard was initialized
62  *
63  * Enum values to control the behavior or indicate internal state of #AgsFifoout by
64  * enable/disable as flags.
65  */
66 typedef enum
67 {
68   AGS_FIFOOUT_ADDED_TO_REGISTRY  = 1,
69   AGS_FIFOOUT_CONNECTED          = 1 <<  1,
70 
71   AGS_FIFOOUT_BUFFER0            = 1 <<  2,
72   AGS_FIFOOUT_BUFFER1            = 1 <<  3,
73   AGS_FIFOOUT_BUFFER2            = 1 <<  4,
74   AGS_FIFOOUT_BUFFER3            = 1 <<  5,
75 
76   AGS_FIFOOUT_ATTACK_FIRST       = 1 <<  6,
77 
78   AGS_FIFOOUT_PLAY               = 1 <<  7,
79 
80   AGS_FIFOOUT_SHUTDOWN           = 1 <<  8,
81   AGS_FIFOOUT_START_PLAY         = 1 <<  9,
82 
83   AGS_FIFOOUT_NONBLOCKING        = 1 << 10,
84   AGS_FIFOOUT_INITIALIZED        = 1 << 11,
85 }AgsFifooutFlags;
86 
87 #define AGS_FIFOOUT_ERROR (ags_fifoout_error_quark())
88 
89 typedef enum{
90   AGS_FIFOOUT_ERROR_LOCKED_SOUNDCARD,
91 }AgsFifooutError;
92 
93 struct _AgsFifoout
94 {
95   GObject gobject;
96 
97   guint flags;
98 
99   GRecMutex obj_mutex;
100 
101   AgsUUID *uuid;
102 
103   guint dsp_channels;
104   guint pcm_channels;
105   guint format;
106   guint buffer_size;
107   guint samplerate; // sample_rate
108 
109   GRecMutex **buffer_mutex;
110 
111   guint sub_block_count;
112   GRecMutex **sub_block_mutex;
113 
114   void** buffer;
115 
116   volatile gboolean available;
117 
118   guint ring_buffer_size;
119   guint nth_ring_buffer;
120 
121   unsigned char **ring_buffer;
122 
123   double bpm; // beats per minute
124   gdouble delay_factor;
125 
126   gdouble *delay; // count of tics within buffer size
127   guint *attack; // where currently tic resides in the stream's offset, measured in 1/64 of bpm
128 
129   gdouble tact_counter;
130   gdouble delay_counter; // next time attack changeing when delay_counter == delay
131   guint tic_counter; // in the range of default period
132 
133   guint note_offset;
134   guint note_offset_absolute;
135 
136   guint loop_left;
137   guint loop_right;
138   gboolean do_loop;
139 
140   guint loop_offset;
141 
142   gchar *device;
143   int fifo_fd;
144 };
145 
146 struct _AgsFifooutClass
147 {
148   GObjectClass gobject;
149 };
150 
151 GType ags_fifoout_get_type();
152 GType ags_fifoout_flags_get_type();
153 
154 GQuark ags_fifoout_error_quark();
155 
156 gboolean ags_fifoout_test_flags(AgsFifoout *fifoout, guint flags);
157 void ags_fifoout_set_flags(AgsFifoout *fifoout, guint flags);
158 void ags_fifoout_unset_flags(AgsFifoout *fifoout, guint flags);
159 
160 void ags_fifoout_switch_buffer_flag(AgsFifoout *fifoout);
161 
162 void ags_fifoout_adjust_delay_and_attack(AgsFifoout *fifoout);
163 void ags_fifoout_realloc_buffer(AgsFifoout *fifoout);
164 
165 AgsFifoout* ags_fifoout_new();
166 
167 G_END_DECLS
168 
169 #endif /*__AGS_FIFOOUT_H__*/
170