Skip to content

Commit

Permalink
Improve scalability of the internal storage
Browse files Browse the repository at this point in the history
  • Loading branch information
arkq committed Feb 29, 2024
1 parent 68893c2 commit b4c9a58
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 78 deletions.
183 changes: 106 additions & 77 deletions src/storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,113 +198,112 @@ int storage_device_clear(const struct ba_device *d) {
return rv;
}

/**
* Synchronize PCM with persistent storage.
*
* @param pcm The PCM structure to synchronize.
* @return This function returns 1 or 0 respectively if the storage data was
* synchronized or not. On error -1 is returned. */
int storage_pcm_data_sync(struct ba_transport_pcm *pcm) {
static int storage_pcm_data_sync_delay(GKeyFile *db, const char *group,
struct ba_transport_pcm *pcm) {

const struct ba_transport *t = pcm->t;
const struct ba_device *d = t->d;
int rv = 0;
char **adjustments;
gsize length;

pthread_mutex_lock(&storage_mutex);
if ((adjustments = g_key_file_get_string_list(db, group,
BA_STORAGE_KEY_DELAY_ADJUSTMENT, &length, NULL)) == NULL)
return 0;

struct storage *st;
if ((st = storage_lookup(&d->addr)) == NULL)
goto final;
for (gsize index = 0; index < length; index++) {
char *codec_name = adjustments[index];
char *value = strchr(adjustments[index], ':');
if (value == NULL)
continue;
*value++ = '\0';
uint16_t codec_id = 0xFFFF;
if (t->profile & BA_TRANSPORT_PROFILE_MASK_A2DP &&
(codec_id = a2dp_codecs_codec_id_from_string(codec_name)) == 0xFFFF)
continue;
if (t->profile & BA_TRANSPORT_PROFILE_MASK_SCO &&
(codec_id = hfp_codec_id_from_string(codec_name)) == HFP_CODEC_UNDEFINED)
continue;
int16_t adjustment = atoi(value);
ba_transport_pcm_delay_adjustment_set(pcm, codec_id, adjustment);
}

GKeyFile *keyfile = st->keyfile;
const char *group = pcm->ba_dbus_path;
g_strfreev(adjustments);
return 1;
}

if (!g_key_file_has_group(keyfile, group))
goto final;
static int storage_pcm_data_sync_volume(GKeyFile *db, const char *group,
struct ba_transport_pcm *pcm) {

if (g_key_file_has_key(keyfile, group, BA_STORAGE_KEY_DELAY_ADJUSTMENT, NULL)) {
gsize length;
char **adjustments = g_key_file_get_string_list(keyfile, group,
BA_STORAGE_KEY_DELAY_ADJUSTMENT, &length, NULL);
for (gsize index = 0; index < length; index++) {
char *codec_name = adjustments[index];
char *value = strchr(adjustments[index], ':');
if (value == NULL)
continue;
*value++ = '\0';
uint16_t codec_id = 0xFFFF;
if (t->profile & BA_TRANSPORT_PROFILE_MASK_A2DP &&
(codec_id = a2dp_codecs_codec_id_from_string(codec_name)) == 0xFFFF)
continue;
if (t->profile & BA_TRANSPORT_PROFILE_MASK_SCO &&
(codec_id = hfp_codec_id_from_string(codec_name)) == HFP_CODEC_UNDEFINED)
continue;
int16_t adjustment = atoi(value);
ba_transport_pcm_delay_adjustment_set(pcm, codec_id, adjustment);
}
g_strfreev(adjustments);
rv = 1;
}
int *list_volume;
gboolean *list_mute;
gsize len;
int rv = 0;

if (g_key_file_has_key(keyfile, group, BA_STORAGE_KEY_SOFT_VOLUME, NULL)) {
pcm->soft_volume = g_key_file_get_boolean(keyfile, group,
if (g_key_file_has_key(db, group, BA_STORAGE_KEY_SOFT_VOLUME, NULL)) {
pcm->soft_volume = g_key_file_get_boolean(db, group,
BA_STORAGE_KEY_SOFT_VOLUME, NULL);
rv = 1;
}

if (g_key_file_has_key(keyfile, group, BA_STORAGE_KEY_VOLUME, NULL)) {
int *list;
gsize len = 0;
if ((list = g_key_file_get_integer_list(keyfile, group,
BA_STORAGE_KEY_VOLUME, &len, NULL)) != NULL &&
len == 2) {
ba_transport_pcm_volume_set(&pcm->volume[0], &list[0], NULL, NULL);
ba_transport_pcm_volume_set(&pcm->volume[1], &list[1], NULL, NULL);
}
g_free(list);
if ((list_volume = g_key_file_get_integer_list(db, group,
BA_STORAGE_KEY_VOLUME, &len, NULL)) != NULL &&
len == 2) {
ba_transport_pcm_volume_set(&pcm->volume[0], &list_volume[0], NULL, NULL);
ba_transport_pcm_volume_set(&pcm->volume[1], &list_volume[1], NULL, NULL);
rv = 1;
}

if (g_key_file_has_key(keyfile, group, BA_STORAGE_KEY_MUTE, NULL)) {
gboolean *list;
gsize len = 0;
if ((list = g_key_file_get_boolean_list(keyfile, group,
BA_STORAGE_KEY_MUTE, &len, NULL)) != NULL &&
len == 2) {
const bool mute[2] = { list[0], list[1] };
ba_transport_pcm_volume_set(&pcm->volume[0], NULL, &mute[0], NULL);
ba_transport_pcm_volume_set(&pcm->volume[1], NULL, &mute[1], NULL);
}
g_free(list);
if ((list_mute = g_key_file_get_boolean_list(db, group,
BA_STORAGE_KEY_MUTE, &len, NULL)) != NULL &&
len == 2) {
const bool mute[2] = { list_mute[0], list_mute[1] };
ba_transport_pcm_volume_set(&pcm->volume[0], NULL, &mute[0], NULL);
ba_transport_pcm_volume_set(&pcm->volume[1], NULL, &mute[1], NULL);
rv = 1;
}

final:
pthread_mutex_unlock(&storage_mutex);
g_free(list_volume);
g_free(list_mute);
return rv;
}

/**
* Update persistent storage with PCM data.
* Synchronize PCM with persistent storage.
*
* @param pcm The PCM structure for which to update the storage.
* @return On success this function returns 0. Otherwise -1 is returned. */
int storage_pcm_data_update(const struct ba_transport_pcm *pcm) {
* @param pcm The PCM structure to synchronize.
* @return This function returns 1 or 0 respectively if the storage data was
* synchronized or not. On error -1 is returned. */
int storage_pcm_data_sync(struct ba_transport_pcm *pcm) {

const struct ba_transport *t = pcm->t;
const struct ba_device *d = t->d;
int rv = -1;
int rv = 0;

pthread_mutex_lock(&storage_mutex);

struct storage *st;
if ((st = storage_lookup(&d->addr)) == NULL)
if ((st = storage_new(&d->addr)) == NULL)
goto final;
goto final;

GKeyFile *keyfile = st->keyfile;
const char *group = pcm->ba_dbus_path;

if (!g_key_file_has_group(keyfile, group))
goto final;

if (storage_pcm_data_sync_delay(keyfile, group, pcm))
rv = 1;
if (storage_pcm_data_sync_volume(keyfile, group, pcm))
rv = 1;

final:
pthread_mutex_unlock(&storage_mutex);
return rv;
}

static void storage_pcm_data_update_delay(GKeyFile *db, const char *group,
const struct ba_transport_pcm *pcm) {

const struct ba_transport *t = pcm->t;
const size_t num_codecs = g_hash_table_size(pcm->delay_adjustments);
char **list = calloc(num_codecs + 1, sizeof(char *));

Expand All @@ -330,21 +329,51 @@ int storage_pcm_data_update(const struct ba_transport_pcm *pcm) {

pthread_mutex_unlock(MUTABLE(&pcm->delay_adjustments_mtx));

g_key_file_set_string_list(keyfile, group, BA_STORAGE_KEY_DELAY_ADJUSTMENT,
g_key_file_set_string_list(db, group, BA_STORAGE_KEY_DELAY_ADJUSTMENT,
(const char * const *)list, num_codecs);

for (index = 0; index < num_codecs; index++)
free(list[index]);
free(list);

g_key_file_set_boolean(keyfile, group, BA_STORAGE_KEY_SOFT_VOLUME,
pcm->soft_volume);
}

static void storage_pcm_data_update_volume(GKeyFile *db, const char *group,
const struct ba_transport_pcm *pcm) {

g_key_file_set_boolean(db, group, BA_STORAGE_KEY_SOFT_VOLUME, pcm->soft_volume);

int volume[2] = { pcm->volume[0].level, pcm->volume[1].level };
g_key_file_set_integer_list(keyfile, group, BA_STORAGE_KEY_VOLUME, volume, 2);
g_key_file_set_integer_list(db, group, BA_STORAGE_KEY_VOLUME, volume, 2);

gboolean mute[2] = { pcm->volume[0].soft_mute, pcm->volume[1].soft_mute };
g_key_file_set_boolean_list(keyfile, group, BA_STORAGE_KEY_MUTE, mute, 2);
g_key_file_set_boolean_list(db, group, BA_STORAGE_KEY_MUTE, mute, 2);

}

/**
* Update persistent storage with PCM data.
*
* @param pcm The PCM structure for which to update the storage.
* @return On success this function returns 0. Otherwise -1 is returned. */
int storage_pcm_data_update(const struct ba_transport_pcm *pcm) {

const struct ba_transport *t = pcm->t;
const struct ba_device *d = t->d;
int rv = -1;

pthread_mutex_lock(&storage_mutex);

struct storage *st;
if ((st = storage_lookup(&d->addr)) == NULL)
if ((st = storage_new(&d->addr)) == NULL)
goto final;

GKeyFile *keyfile = st->keyfile;
const char *group = pcm->ba_dbus_path;

storage_pcm_data_update_delay(keyfile, group, pcm);
storage_pcm_data_update_volume(keyfile, group, pcm);

rv = 0;

Expand Down
3 changes: 2 additions & 1 deletion test/mock/mock.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* mock.c
* Copyright (c) 2016-2023 Arkadiusz Bokowy
* Copyright (c) 2016-2024 Arkadiusz Bokowy
*
* This file is a part of bluez-alsa.
*
Expand Down Expand Up @@ -179,6 +179,7 @@ int main(int argc, char *argv[]) {

assert(mkdir(TEST_BLUEALSA_STORAGE_DIR, 0755) == 0 || errno == EEXIST);
assert(storage_init(TEST_BLUEALSA_STORAGE_DIR) == 0);
atexit(storage_destroy);

GTestDBus *dbus = g_test_dbus_new(G_TEST_DBUS_NONE);
g_test_dbus_up(dbus);
Expand Down
2 changes: 2 additions & 0 deletions test/test-ba.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

Expand Down Expand Up @@ -459,6 +460,7 @@ int main(void) {

assert(mkdir(TEST_BLUEALSA_STORAGE_DIR, 0755) == 0 || errno == EEXIST);
assert(storage_init(TEST_BLUEALSA_STORAGE_DIR) == 0);
atexit(storage_destroy);

#if ENABLE_MSBC
config.hfp.codecs.msbc = false;
Expand Down

0 comments on commit b4c9a58

Please sign in to comment.