#include #include #include "alsa-softmixer.h" #include "alsa-transaction.h" #include "wrap-json.h" static void AlsaMixerTransactionFree(AlsaMixerTransaction * transaction) { free((char*)transaction->uid); free(transaction); } AlsaMixerTransaction * AlsaMixerTransactionNew(struct SoftMixerT_ * mixer, const char * uid) { AlsaMixerTransaction * transaction = (AlsaMixerTransaction *) malloc(sizeof(AlsaMixerTransaction)); if (transaction == NULL) goto fail; AFB_API_INFO(mixer->api, "-------- NEW TRANSACTION %s --------", uid); CDS_INIT_LIST_HEAD(&transaction->item_list); transaction->uid = strdup(uid); if (transaction->uid == NULL) { goto fail_list; } transaction->mixer = mixer; cds_list_add(&transaction->transaction_node, &mixer->transactionList); return transaction; fail_list: free(transaction); fail: return NULL; } void AlsaMixerTransactionObjectDelete(AlsaMixerTransaction* transaction, void * object, bool destructor) { AlsaMixerTransactionDataItem *item, *tmp; cds_list_for_each_entry_safe(item, tmp, &transaction->item_list, list_entry) if (item->object == object) { if (destructor && item->destructor) item->destructor(transaction->mixer, item->object); cds_list_del(&item->list_entry); free(item); } } bool AlsaMixerTransactionObjectAdd(AlsaMixerTransaction* list, void* object, AlsaTransactionDestructor destructor) { bool ret = false; AlsaMixerTransactionDataItem * newItem = NULL; if (!list) goto fail; newItem = (AlsaMixerTransactionDataItem *) malloc(sizeof(AlsaMixerTransactionDataItem)); if (newItem == NULL) goto fail; CDS_INIT_LIST_HEAD(&newItem->list_entry); newItem->object = object; newItem->destructor = destructor; cds_list_add(&newItem->list_entry, &list->item_list); ret = true; fail: return ret; } bool AlsaMixerTransactionObjectAddTail(AlsaMixerTransaction* list, void* object, AlsaTransactionDestructor destructor) { bool ret = false; AlsaMixerTransactionDataItem * newItem = NULL; if (!list) goto fail; newItem = (AlsaMixerTransactionDataItem *) malloc(sizeof(AlsaMixerTransactionDataItem)); if (newItem == NULL) goto fail; CDS_INIT_LIST_HEAD(&newItem->list_entry); newItem->object = object; newItem->destructor = destructor; cds_list_add_tail(&newItem->list_entry, &list->item_list); ret = true; fail: return ret; } static void AlsaMixerTransactionDoCleanup(AlsaMixerTransaction* transaction) { AlsaMixerTransactionDataItem * item, *sav; AFB_ApiInfo(transaction->mixer->api, "%s for transaction %s", __func__, transaction->uid); cds_list_for_each_entry_safe(item, sav, &transaction->item_list, list_entry) { if (item->destructor) item->destructor(transaction->mixer, item->object); cds_list_del(&item->list_entry); free(item); } AFB_ApiInfo(transaction->mixer->api, "%s for transaction %s .. DONE !", __func__, transaction->uid); } void AlsaMixerTransactionVerbCB(AFB_ReqT request) { json_object *responseJ = NULL; AlsaMixerTransaction *transaction = (AlsaMixerTransaction*) afb_req_get_vcbdata(request); json_object *argsJ = afb_req_json(request); int error; char * action = NULL; const char * uid = NULL; error = wrap_json_unpack(argsJ, "{ss!}", "action", &action); if (error) { AFB_ReqFailF(request, "missing action", "%s: missing 'action' field: %s", transaction->uid, json_object_get_string(argsJ)); goto fail; } uid = strdup(transaction->uid); if (!uid) { SOFTMIXER_NOMEM(transaction->mixer->api); goto fail; } if (strcmp(action, "remove") == 0) { error = afb_api_del_verb(transaction->mixer->api, transaction->uid, (void**)NULL); if (error) { AFB_ReqFail(request, "verb deletion" , "verb was not removed"); goto fail; } AlsaMixerTransactionDelete(transaction); } else { AFB_ReqFailF(request, "unsupported action", "%s: unsupported action %s (supported ones are ['remove']", transaction->uid, action); goto fail; } responseJ=json_object_new_object(); json_object_object_add(responseJ, "result", json_object_new_string("OK")); AFB_ReqSuccess(request, responseJ, uid); fail: free((char*)uid); return; } void AlsaMixerTransactionDelete(AlsaMixerTransaction * transaction) { AlsaMixerTransactionDoCleanup(transaction); // remove this transaction for the list of mixer cds_list_del(&transaction->transaction_node); AlsaMixerTransactionFree(transaction); }