mirror of
https://github.com/Tha14/toxic.git
synced 2025-12-07 15:56:35 +01:00
Fix more threading issues
This commit is contained in:
162
src/device.c
162
src/device.c
@@ -58,14 +58,14 @@ typedef struct Device {
|
||||
DataHandleCallback cb; /* Use this to handle data from input device usually */
|
||||
void* cb_data; /* Data to be passed to callback */
|
||||
int32_t call_idx; /* ToxAv call index */
|
||||
|
||||
|
||||
uint32_t source, buffers[OPENAL_BUFS]; /* Playback source/buffers */
|
||||
uint32_t ref_count;
|
||||
int32_t selection;
|
||||
bool enable_VAD;
|
||||
bool muted;
|
||||
pthread_mutex_t mutex[1];
|
||||
uint32_t sample_rate;
|
||||
uint32_t sample_rate;
|
||||
uint32_t frame_duration;
|
||||
int32_t sound_mode;
|
||||
#ifdef AUDIO
|
||||
@@ -89,7 +89,7 @@ static ToxAv* av = NULL;
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
|
||||
bool thread_running = true,
|
||||
bool thread_running = true,
|
||||
thread_paused = true; /* Thread control */
|
||||
|
||||
void* thread_poll(void*);
|
||||
@@ -105,19 +105,19 @@ DeviceError init_devices()
|
||||
size[input] = 0;
|
||||
if ( (stringed_device_list = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER)) ) {
|
||||
ddevice_names[input] = alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
|
||||
|
||||
|
||||
for ( ; *stringed_device_list && size[input] < MAX_DEVICES; ++size[input] ) {
|
||||
devices_names[input][size[input]] = stringed_device_list;
|
||||
devices_names[input][size[input]] = stringed_device_list;
|
||||
stringed_device_list += strlen( stringed_device_list ) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size[output] = 0;
|
||||
if ( (stringed_device_list = alcGetString(NULL, ALC_DEVICE_SPECIFIER)) ) {
|
||||
ddevice_names[output] = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
|
||||
|
||||
|
||||
for ( ; *stringed_device_list && size[output] < MAX_DEVICES; ++size[output] ) {
|
||||
devices_names[output][size[output]] = stringed_device_list;
|
||||
devices_names[output][size[output]] = stringed_device_list;
|
||||
stringed_device_list += strlen( stringed_device_list ) + 1;
|
||||
}
|
||||
}
|
||||
@@ -125,27 +125,30 @@ DeviceError init_devices()
|
||||
// Start poll thread
|
||||
if (pthread_mutex_init(&mutex, NULL) != 0)
|
||||
return de_InternalError;
|
||||
|
||||
|
||||
pthread_t thread_id;
|
||||
if ( pthread_create(&thread_id, NULL, thread_poll, NULL) != 0 || pthread_detach(thread_id) != 0)
|
||||
return de_InternalError;
|
||||
|
||||
if ( pthread_create(&thread_id, NULL, thread_poll, NULL) != 0 || pthread_detach(thread_id) != 0)
|
||||
return de_InternalError;
|
||||
|
||||
#ifdef AUDIO
|
||||
av = av_;
|
||||
#endif /* AUDIO */
|
||||
|
||||
|
||||
return (DeviceError) de_None;
|
||||
}
|
||||
|
||||
DeviceError terminate_devices()
|
||||
{
|
||||
/* Cleanup if needed */
|
||||
lock;
|
||||
thread_running = false;
|
||||
unlock;
|
||||
|
||||
usleep(20000);
|
||||
|
||||
|
||||
if (pthread_mutex_destroy(&mutex) != 0)
|
||||
return (DeviceError) de_InternalError;
|
||||
|
||||
|
||||
return (DeviceError) de_None;
|
||||
}
|
||||
|
||||
@@ -153,16 +156,16 @@ DeviceError device_mute(DeviceType type, uint32_t device_idx)
|
||||
{
|
||||
if (device_idx >= MAX_DEVICES) return de_InvalidSelection;
|
||||
lock;
|
||||
|
||||
|
||||
Device* device = running[type][device_idx];
|
||||
|
||||
if (!device) {
|
||||
|
||||
if (!device) {
|
||||
unlock;
|
||||
return de_DeviceNotActive;
|
||||
}
|
||||
|
||||
|
||||
device->muted = !device->muted;
|
||||
|
||||
|
||||
unlock;
|
||||
return de_None;
|
||||
}
|
||||
@@ -175,7 +178,7 @@ DeviceError device_set_VAD_treshold(uint32_t device_idx, float value)
|
||||
|
||||
Device* device = running[input][device_idx];
|
||||
|
||||
if (!device) {
|
||||
if (!device) {
|
||||
unlock;
|
||||
return de_DeviceNotActive;
|
||||
}
|
||||
@@ -192,7 +195,7 @@ DeviceError set_primary_device(DeviceType type, int32_t selection)
|
||||
{
|
||||
if (size[type] <= selection || selection < 0) return de_InvalidSelection;
|
||||
primary_device[type] = selection;
|
||||
|
||||
|
||||
return de_None;
|
||||
}
|
||||
|
||||
@@ -212,88 +215,88 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx
|
||||
if (size[type] <= selection || selection < 0) return de_InvalidSelection;
|
||||
|
||||
if (channels != 1 && channels != 2) return de_UnsupportedMode;
|
||||
|
||||
|
||||
lock;
|
||||
|
||||
const uint32_t frame_size = (sample_rate * frame_duration / 1000);
|
||||
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < MAX_DEVICES && running[type][i] != NULL; ++i);
|
||||
|
||||
|
||||
if (i == MAX_DEVICES) { unlock; return de_AllDevicesBusy; }
|
||||
else *device_idx = i;
|
||||
|
||||
|
||||
for (i = 0; i < MAX_DEVICES; i ++) { /* Check if any device has the same selection */
|
||||
if ( running[type][i] && running[type][i]->selection == selection ) {
|
||||
// printf("a%d-%d:%p ", selection, i, running[type][i]->dhndl);
|
||||
|
||||
running[type][*device_idx] = running[type][i];
|
||||
|
||||
running[type][*device_idx] = running[type][i];
|
||||
running[type][i]->ref_count ++;
|
||||
|
||||
|
||||
unlock;
|
||||
return de_None;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Device* device = running[type][*device_idx] = calloc(1, sizeof(Device));
|
||||
device->selection = selection;
|
||||
|
||||
|
||||
device->sample_rate = sample_rate;
|
||||
device->frame_duration = frame_duration;
|
||||
device->sound_mode = channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
|
||||
|
||||
|
||||
if (pthread_mutex_init(device->mutex, NULL) != 0) {
|
||||
free(device);
|
||||
unlock;
|
||||
return de_InternalError;
|
||||
}
|
||||
|
||||
|
||||
if (type == input) {
|
||||
device->dhndl = alcCaptureOpenDevice(devices_names[type][selection],
|
||||
device->dhndl = alcCaptureOpenDevice(devices_names[type][selection],
|
||||
sample_rate, device->sound_mode, frame_size * 2);
|
||||
#ifdef AUDIO
|
||||
device->VAD_treshold = user_settings->VAD_treshold;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
else {
|
||||
device->dhndl = alcOpenDevice(devices_names[type][selection]);
|
||||
if ( !device->dhndl ) {
|
||||
if ( !device->dhndl ) {
|
||||
free(device);
|
||||
running[type][*device_idx] = NULL;
|
||||
unlock;
|
||||
return de_FailedStart;
|
||||
}
|
||||
|
||||
|
||||
device->ctx = alcCreateContext(device->dhndl, NULL);
|
||||
alcMakeContextCurrent(device->ctx);
|
||||
|
||||
|
||||
alGenBuffers(OPENAL_BUFS, device->buffers);
|
||||
alGenSources((uint32_t)1, &device->source);
|
||||
alSourcei(device->source, AL_LOOPING, AL_FALSE);
|
||||
|
||||
|
||||
uint16_t zeros[frame_size];
|
||||
memset(zeros, 0, frame_size*2);
|
||||
|
||||
|
||||
for ( i = 0; i < OPENAL_BUFS; ++i ) {
|
||||
alBufferData(device->buffers[i], device->sound_mode, zeros, frame_size*2, sample_rate);
|
||||
}
|
||||
|
||||
|
||||
alSourceQueueBuffers(device->source, OPENAL_BUFS, device->buffers);
|
||||
alSourcePlay(device->source);
|
||||
}
|
||||
|
||||
|
||||
if (alcGetError(device->dhndl) != AL_NO_ERROR) {
|
||||
free(device);
|
||||
running[type][*device_idx] = NULL;
|
||||
unlock;
|
||||
return de_FailedStart;
|
||||
}
|
||||
|
||||
|
||||
if (type == input) {
|
||||
alcCaptureStart(device->dhndl);
|
||||
thread_paused = false;
|
||||
}
|
||||
|
||||
|
||||
unlock;
|
||||
return de_None;
|
||||
}
|
||||
@@ -301,47 +304,47 @@ DeviceError open_device(DeviceType type, int32_t selection, uint32_t* device_idx
|
||||
DeviceError close_device(DeviceType type, uint32_t device_idx)
|
||||
{
|
||||
if (device_idx >= MAX_DEVICES) return de_InvalidSelection;
|
||||
|
||||
|
||||
lock;
|
||||
Device* device = running[type][device_idx];
|
||||
DeviceError rc = de_None;
|
||||
|
||||
if (!device) {
|
||||
|
||||
if (!device) {
|
||||
unlock;
|
||||
return de_DeviceNotActive;
|
||||
}
|
||||
|
||||
|
||||
running[type][device_idx] = NULL;
|
||||
|
||||
|
||||
if ( !device->ref_count ) {
|
||||
|
||||
|
||||
// printf("Closed device ");
|
||||
|
||||
|
||||
if (type == input) {
|
||||
if ( !alcCaptureCloseDevice(device->dhndl) ) rc = de_AlError;
|
||||
}
|
||||
else {
|
||||
else {
|
||||
if (alcGetCurrentContext() != device->ctx) alcMakeContextCurrent(device->ctx);
|
||||
|
||||
|
||||
alDeleteSources(1, &device->source);
|
||||
alDeleteBuffers(OPENAL_BUFS, device->buffers);
|
||||
|
||||
|
||||
alcMakeContextCurrent(NULL);
|
||||
if ( device->ctx ) alcDestroyContext(device->ctx);
|
||||
if ( !alcCloseDevice(device->dhndl) ) rc = de_AlError;
|
||||
}
|
||||
|
||||
|
||||
free(device);
|
||||
}
|
||||
else device->ref_count--;
|
||||
|
||||
|
||||
unlock;
|
||||
return rc;
|
||||
}
|
||||
|
||||
DeviceError register_device_callback( int32_t call_idx, uint32_t device_idx, DataHandleCallback callback, void* data, bool enable_VAD)
|
||||
{
|
||||
if (size[input] <= device_idx || !running[input][device_idx] || running[input][device_idx]->dhndl == NULL)
|
||||
{
|
||||
if (size[input] <= device_idx || !running[input][device_idx] || running[input][device_idx]->dhndl == NULL)
|
||||
return de_InvalidSelection;
|
||||
|
||||
lock;
|
||||
@@ -375,9 +378,9 @@ inline__ DeviceError write_out(uint32_t device_idx, const int16_t* data, uint32_
|
||||
alSourceUnqueueBuffers(device->source, processed, bufids);
|
||||
alDeleteBuffers(processed - 1, bufids + 1);
|
||||
bufid = bufids[0];
|
||||
}
|
||||
}
|
||||
else if(queued < 16) alGenBuffers(1, &bufid);
|
||||
else {
|
||||
else {
|
||||
pthread_mutex_unlock(device->mutex);
|
||||
return de_Busy;
|
||||
}
|
||||
@@ -404,44 +407,51 @@ void* thread_poll (void* arg) // TODO: maybe use thread for every input source
|
||||
(void)arg;
|
||||
uint32_t i;
|
||||
int32_t sample = 0;
|
||||
|
||||
|
||||
while (thread_running)
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
lock;
|
||||
if (!thread_running) {
|
||||
unlock;
|
||||
break;
|
||||
}
|
||||
unlock;
|
||||
|
||||
if (thread_paused) usleep(10000); /* Wait for unpause. */
|
||||
else
|
||||
{
|
||||
for (i = 0; i < size[input]; ++i)
|
||||
for (i = 0; i < size[input]; ++i)
|
||||
{
|
||||
lock;
|
||||
if (running[input][i] != NULL)
|
||||
if (running[input][i] != NULL)
|
||||
{
|
||||
alcGetIntegerv(running[input][i]->dhndl, ALC_CAPTURE_SAMPLES, sizeof(int32_t), &sample);
|
||||
|
||||
|
||||
int f_size = (running[input][i]->sample_rate * running[input][i]->frame_duration / 1000);
|
||||
|
||||
if (sample < f_size) {
|
||||
|
||||
if (sample < f_size) {
|
||||
unlock;
|
||||
continue;
|
||||
}
|
||||
Device* device = running[input][i];
|
||||
|
||||
|
||||
int16_t frame[16000];
|
||||
alcCaptureSamples(device->dhndl, frame, f_size);
|
||||
|
||||
if (device->muted) {
|
||||
|
||||
if (device->muted) {
|
||||
unlock;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if ( device->cb ) device->cb(frame, f_size, device->cb_data);
|
||||
}
|
||||
}
|
||||
unlock;
|
||||
}
|
||||
usleep(5000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
@@ -462,8 +472,8 @@ DeviceError selection_valid(DeviceType type, int32_t selection)
|
||||
|
||||
void* get_device_callback_data(uint32_t device_idx)
|
||||
{
|
||||
if (size[input] <= device_idx || !running[input][device_idx] || running[input][device_idx]->dhndl == NULL)
|
||||
if (size[input] <= device_idx || !running[input][device_idx] || running[input][device_idx]->dhndl == NULL)
|
||||
return NULL;
|
||||
|
||||
|
||||
return running[input][device_idx]->cb_data;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user