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_WASAPI_DEVOUT_H__ 21 #define __AGS_WASAPI_DEVOUT_H__ 22 23 #include <glib.h> 24 #include <glib-object.h> 25 26 #include <ags/ags_api_config.h> 27 28 #ifdef AGS_WITH_WASAPI 29 #include <windows.h> 30 #include <tchar.h> 31 #include <math.h> 32 #include <float.h> 33 #include <mmdeviceapi.h> 34 #include <audioclient.h> 35 #include <avrt.h> 36 #include <functiondiscoverykeys_devpkey.h> 37 #include <winerror.h> 38 #endif 39 40 #include <ags/libags.h> 41 42 G_BEGIN_DECLS 43 44 #define AGS_TYPE_WASAPI_DEVOUT (ags_wasapi_devout_get_type()) 45 #define AGS_WASAPI_DEVOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), AGS_TYPE_WASAPI_DEVOUT, AgsWasapiDevout)) 46 #define AGS_WASAPI_DEVOUT_CLASS(class) (G_TYPE_CHECK_CLASS_CAST(class, AGS_TYPE_WASAPI_DEVOUT, AgsWasapiDevout)) 47 #define AGS_IS_WASAPI_DEVOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), AGS_TYPE_WASAPI_DEVOUT)) 48 #define AGS_IS_WASAPI_DEVOUT_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), AGS_TYPE_WASAPI_DEVOUT)) 49 #define AGS_WASAPI_DEVOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS(obj, AGS_TYPE_WASAPI_DEVOUT, AgsWasapiDevoutClass)) 50 51 #define AGS_WASAPI_DEVOUT_GET_OBJ_MUTEX(obj) (&(((AgsWasapiDevout *) obj)->obj_mutex)) 52 53 #define AGS_WASAPI_DEVOUT_DEFAULT_WASAPI_BUFFER_SIZE (8192) 54 55 typedef struct _AgsWasapiDevout AgsWasapiDevout; 56 typedef struct _AgsWasapiDevoutClass AgsWasapiDevoutClass; 57 58 /** 59 * AgsWasapiDevoutFlags: 60 * @AGS_WASAPI_DEVOUT_ADDED_TO_REGISTRY: the core-audio devout was added to registry, see #AgsConnectable::add_to_registry() 61 * @AGS_WASAPI_DEVOUT_CONNECTED: indicates the core-audio devout was connected by calling #AgsConnectable::connect() 62 * @AGS_WASAPI_DEVOUT_BUFFER0: ring-buffer 0 63 * @AGS_WASAPI_DEVOUT_BUFFER1: ring-buffer 1 64 * @AGS_WASAPI_DEVOUT_BUFFER2: ring-buffer 2 65 * @AGS_WASAPI_DEVOUT_BUFFER3: ring-buffer 3 66 * @AGS_WASAPI_DEVOUT_BUFFER4: ring-buffer 4 67 * @AGS_WASAPI_DEVOUT_BUFFER5: ring-buffer 5 68 * @AGS_WASAPI_DEVOUT_BUFFER6: ring-buffer 6 69 * @AGS_WASAPI_DEVOUT_BUFFER7: ring-buffer 7 70 * @AGS_WASAPI_DEVOUT_ATTACK_FIRST: use first attack, instead of second one 71 * @AGS_WASAPI_DEVOUT_PLAY: do playback 72 * @AGS_WASAPI_DEVOUT_SHUTDOWN: stop playback 73 * @AGS_WASAPI_DEVOUT_START_PLAY: playback starting 74 * @AGS_WASAPI_DEVOUT_NONBLOCKING: do non-blocking calls 75 * @AGS_WASAPI_DEVOUT_INITIALIZED: the soundcard was initialized 76 * @AGS_WASAPI_DEVOUT_SHARE_MODE_EXCLUSIVE: share mode exclusive 77 * 78 * Enum values to control the behavior or indicate internal state of #AgsWasapiDevout by 79 * enable/disable as flags. 80 */ 81 typedef enum{ 82 AGS_WASAPI_DEVOUT_ADDED_TO_REGISTRY = 1, 83 AGS_WASAPI_DEVOUT_CONNECTED = 1 << 1, 84 85 AGS_WASAPI_DEVOUT_BUFFER0 = 1 << 2, 86 AGS_WASAPI_DEVOUT_BUFFER1 = 1 << 3, 87 AGS_WASAPI_DEVOUT_BUFFER2 = 1 << 4, 88 AGS_WASAPI_DEVOUT_BUFFER3 = 1 << 5, 89 AGS_WASAPI_DEVOUT_BUFFER4 = 1 << 6, 90 AGS_WASAPI_DEVOUT_BUFFER5 = 1 << 7, 91 AGS_WASAPI_DEVOUT_BUFFER6 = 1 << 8, 92 AGS_WASAPI_DEVOUT_BUFFER7 = 1 << 9, 93 94 AGS_WASAPI_DEVOUT_ATTACK_FIRST = 1 << 10, 95 96 AGS_WASAPI_DEVOUT_PLAY = 1 << 11, 97 AGS_WASAPI_DEVOUT_SHUTDOWN = 1 << 12, 98 AGS_WASAPI_DEVOUT_START_PLAY = 1 << 13, 99 100 AGS_WASAPI_DEVOUT_NONBLOCKING = 1 << 14, 101 AGS_WASAPI_DEVOUT_INITIALIZED = 1 << 15, 102 103 AGS_WASAPI_DEVOUT_SHARE_MODE_EXCLUSIVE = 1 << 16, 104 }AgsWasapiDevoutFlags; 105 106 #define AGS_WASAPI_DEVOUT_ERROR (ags_wasapi_devout_error_quark()) 107 108 typedef enum{ 109 AGS_WASAPI_DEVOUT_ERROR_LOCKED_SOUNDCARD, 110 AGS_WASAPI_DEVOUT_ERROR_BROKEN_CONFIGURATION, 111 }AgsWasapiDevoutError; 112 113 struct _AgsWasapiDevout 114 { 115 GObject gobject; 116 117 guint flags; 118 119 GRecMutex obj_mutex; 120 121 AgsUUID *uuid; 122 123 guint dsp_channels; 124 guint pcm_channels; 125 guint format; 126 guint buffer_size; 127 guint samplerate; 128 129 GRecMutex **buffer_mutex; 130 131 guint sub_block_count; 132 GRecMutex **sub_block_mutex; 133 134 void** buffer; 135 136 gboolean use_cache; 137 guint cache_buffer_size; 138 139 guint current_cache; 140 guint completed_cache; 141 guint cache_offset; 142 void **cache; 143 144 guint wasapi_buffer_size; 145 146 double bpm; // beats per minute 147 gdouble delay_factor; 148 149 gdouble *delay; // count of tics within buffer size 150 guint *attack; // where currently tic resides in the stream's offset, measured in 1/64 of bpm 151 152 gdouble tact_counter; 153 gdouble delay_counter; // next time attack changeing when delay_counter == delay 154 guint tic_counter; // in the range of default period 155 156 guint start_note_offset; 157 guint note_offset; 158 guint note_offset_absolute; 159 160 guint loop_left; 161 guint loop_right; 162 gboolean do_loop; 163 164 guint loop_offset; 165 166 gchar *device; 167 168 #ifdef AGS_WITH_WASAPI 169 IMMDevice *mm_device; 170 IAudioClient *audio_client; 171 #else 172 gpointer mm_device; 173 gpointer audio_client; 174 #endif 175 176 GMutex callback_mutex; 177 GCond callback_cond; 178 179 GMutex callback_finish_mutex; 180 GCond callback_finish_cond; 181 }; 182 183 struct _AgsWasapiDevoutClass 184 { 185 GObjectClass gobject; 186 }; 187 188 GType ags_wasapi_devout_get_type(); 189 190 GQuark ags_wasapi_devout_error_quark(); 191 192 gboolean ags_wasapi_devout_test_flags(AgsWasapiDevout *wasapi_devout, guint flags); 193 void ags_wasapi_devout_set_flags(AgsWasapiDevout *wasapi_devout, guint flags); 194 void ags_wasapi_devout_unset_flags(AgsWasapiDevout *wasapi_devout, guint flags); 195 196 void ags_wasapi_devout_switch_buffer_flag(AgsWasapiDevout *wasapi_devout); 197 198 void ags_wasapi_devout_adjust_delay_and_attack(AgsWasapiDevout *wasapi_devout); 199 void ags_wasapi_devout_realloc_buffer(AgsWasapiDevout *wasapi_devout); 200 201 AgsWasapiDevout* ags_wasapi_devout_new(); 202 203 G_END_DECLS 204 205 #endif /*__AGS_WASAPI_DEVOUT_H__*/ 206