Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 992ef56 in mainline


Ignore:
Timestamp:
2012-07-12T17:24:51Z (10 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial
Children:
1240bb9
Parents:
ec49085
Message:

hound: Implement device playback backend

Location:
uspace/srv/audio/hound
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/audio/hound/Makefile

    rec49085 r992ef56  
    2828
    2929USPACE_PREFIX = ../../..
    30 EXTRA_CFLAGS = -DNAME="\"hound\""
    3130BINARY = hound
     31
     32EXTRA_CFLAGS = \
     33        -DNAME="\"hound\"" \
     34        -I$(LIBDRV_PREFIX)/include
     35
     36LIBS = \
     37        $(LIBDRV_PREFIX)/libdrv.a
    3238
    3339SOURCES = \
  • uspace/srv/audio/hound/audio_device.c

    rec49085 r992ef56  
    4242#include <str_error.h>
    4343
     44#include <audio_pcm_iface.h>
     45
    4446#include "audio_device.h"
    4547#include "log.h"
    4648
     49#define BUFFER_BLOCKS 2
     50
    4751static int device_sink_connection_callback(void* arg);
    4852static int device_source_connection_callback(void* arg, const audio_format_t *f);
    49 static int audio_device_get_buffer(audio_device_t *dev)
    50 {
    51         // TODO implement
    52         return ENOTSUP;
    53 }
    54 static int audio_device_release_buffer(audio_device_t *dev)
    55 {
    56         // TODO implement
    57         return ENOTSUP;
    58 }
    59 static int audio_device_start_playback(audio_device_t *dev)
    60 {
    61         // TODO implement
    62         return ENOTSUP;
    63 }
    64 static int audio_device_stop_playback(audio_device_t *dev)
    65 {
    66         // TODO implement
    67         return ENOTSUP;
    68 }
    69 static int audio_device_start_recording(audio_device_t *dev)
    70 {
    71         // TODO implement
    72         return ENOTSUP;
    73 }
    74 static int audio_device_stop_recording(audio_device_t *dev)
    75 {
    76         // TODO implement
    77         return ENOTSUP;
    78 }
     53static void device_event_callback(ipc_callid_t iid, ipc_call_t *icall, void *arg);
     54static int get_buffer(audio_device_t *dev);
     55static int release_buffer(audio_device_t *dev);
     56static int start_playback(audio_device_t *dev);
     57static int stop_playback(audio_device_t *dev);
     58static int start_recording(audio_device_t *dev);
     59static int stop_recording(audio_device_t *dev);
    7960
    8061
     
    9980            device_source_connection_callback, dev);
    10081
     82        /* Init buffer members */
     83        fibril_mutex_initialize(&dev->buffer.guard);
     84        fibril_condvar_initialize(&dev->buffer.wc);
     85        dev->buffer.id = 0;
     86        dev->buffer.base = NULL;
     87        dev->buffer.position = NULL;
     88        dev->buffer.size = 0;
     89
    10190        log_verbose("Initialized device (%p) '%s' with id %u.",
    10291            dev, dev->name, dev->id);
     
    10998        audio_device_t *dev = arg;
    11099        if (list_count(&dev->sink.sources) == 1) {
    111                 int ret = audio_device_get_buffer(dev);
     100                int ret = get_buffer(dev);
    112101                if (ret != EOK) {
    113102                        log_error("Failed to get device buffer: %s",
     
    115104                        return ret;
    116105                }
    117                 ret = audio_device_start_playback(dev);
     106                ret = start_playback(dev);
    118107                if (ret != EOK) {
    119108                        log_error("Failed to start playback: %s",
    120109                            str_error(ret));
    121                         audio_device_release_buffer(dev);
     110                        release_buffer(dev);
    122111                        return ret;
    123112                }
    124113        }
    125114        if (list_count(&dev->sink.sources) == 0) {
    126                 int ret = audio_device_stop_playback(dev);
     115                int ret = stop_playback(dev);
    127116                if (ret != EOK) {
    128117                        log_error("Failed to start playback: %s",
     
    131120                }
    132121                dev->sink.format = AUDIO_FORMAT_ANY;
    133                 ret = audio_device_release_buffer(dev);
     122                ret = release_buffer(dev);
    134123                if (ret != EOK) {
    135124                        log_error("Failed to release buffer: %s",
     
    145134        audio_device_t *dev = arg;
    146135        if (f) { /* Connected, f points to sink format */
    147                 int ret = audio_device_get_buffer(dev);
     136                int ret = get_buffer(dev);
    148137                if (ret != EOK) {
    149138                        log_error("Failed to get device buffer: %s",
     
    151140                        return ret;
    152141                }
    153                 ret = audio_device_start_recording(dev);
     142                ret = start_recording(dev);
    154143                if (ret != EOK) {
    155144                        log_error("Failed to start recording: %s",
    156145                            str_error(ret));
    157                         audio_device_release_buffer(dev);
     146                        release_buffer(dev);
    158147                        return ret;
    159148                }
    160149                dev->source.format = *f;
    161150        } else { /* Disconnected, f is NULL */
    162                 int ret = audio_device_stop_recording(dev);
     151                int ret = stop_recording(dev);
    163152                if (ret != EOK) {
    164153                        log_error("Failed to start recording: %s",
     
    167156                }
    168157                dev->sink.format = AUDIO_FORMAT_ANY;
    169                 ret = audio_device_release_buffer(dev);
     158                ret = release_buffer(dev);
    170159                if (ret != EOK) {
    171160                        log_error("Failed to release buffer: %s",
     
    178167}
    179168
     169static void device_event_callback(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     170{
     171        /* Answer initial request */
     172        async_answer_0(iid, EOK);
     173        audio_device_t *dev = arg;
     174        assert(dev);
     175        while (1) {
     176                ipc_call_t call;
     177                ipc_callid_t callid = async_get_call(&call);
     178                async_answer_0(callid, EOK);
     179                if (IPC_GET_IMETHOD(call) != IPC_FIRST_USER_METHOD) {
     180                        log_debug("Unknown event.\n");
     181                        continue;
     182                }
     183                // Assume playback for now
     184                if (dev->buffer.position) {
     185                        dev->buffer.position += dev->buffer.size / BUFFER_BLOCKS;
     186                }
     187                if (!dev->buffer.position ||
     188                    dev->buffer.position >= dev->buffer.base + dev->buffer.size)
     189                {
     190                        dev->buffer.position = dev->buffer.base;
     191                }
     192                audio_sink_mix_inputs(
     193                    &dev->sink, dev->buffer.base,
     194                    dev->buffer.size / BUFFER_BLOCKS);
     195
     196        }
     197        //TODO implement
     198}
     199
     200static int get_buffer(audio_device_t *dev)
     201{
     202        assert(dev);
     203        if (!dev->sess) {
     204                log_debug("No connection to device");
     205                return EIO;
     206        }
     207        if (dev->buffer.base) {
     208                log_debug("We already have a buffer");
     209                return EBUSY;
     210        }
     211
     212        dev->buffer.size = 0;
     213
     214        async_exch_t *exch = async_exchange_begin(dev->sess);
     215        const int ret = audio_pcm_get_buffer(exch, &dev->buffer.base,
     216            &dev->buffer.size, &dev->buffer.id, device_event_callback, dev);
     217        async_exchange_end(exch);
     218        return ret;
     219}
     220
     221#define CHECK_BUFFER_AND_CONNECTION() \
     222do { \
     223        assert(dev); \
     224        if (!dev->sess) { \
     225                log_debug("No connection to device"); \
     226                return EIO; \
     227        } \
     228        if (!dev->buffer.base) { \
     229                log_debug("We don't have a buffer"); \
     230                return ENOENT; \
     231        } \
     232} while (0)
     233
     234
     235static int release_buffer(audio_device_t *dev)
     236{
     237        CHECK_BUFFER_AND_CONNECTION();
     238
     239        async_exch_t *exch = async_exchange_begin(dev->sess);
     240        const int ret = audio_pcm_release_buffer(exch, dev->buffer.id);
     241        async_exchange_end(exch);
     242        if (ret == EOK) {
     243                dev->buffer.base = NULL;
     244                dev->buffer.size = 0;
     245                dev->buffer.position = NULL;
     246        }
     247        return ret;
     248}
     249
     250static int start_playback(audio_device_t *dev)
     251{
     252        CHECK_BUFFER_AND_CONNECTION();
     253
     254        /* Fill the buffer first */
     255        audio_sink_mix_inputs(&dev->sink, dev->buffer.base, dev->buffer.size);
     256
     257        async_exch_t *exch = async_exchange_begin(dev->sess);
     258        const int ret = audio_pcm_start_playback(exch, dev->buffer.id,
     259            BUFFER_BLOCKS, dev->sink.format.channels,
     260            dev->sink.format.sampling_rate, dev->sink.format.sample_format);
     261        async_exchange_end(exch);
     262        return ret;
     263}
     264
     265static int stop_playback(audio_device_t *dev)
     266{
     267        CHECK_BUFFER_AND_CONNECTION();
     268
     269        async_exch_t *exch = async_exchange_begin(dev->sess);
     270        const int ret = audio_pcm_stop_playback(exch, dev->buffer.id);
     271        async_exchange_end(exch);
     272        return ret;
     273}
     274
     275static int start_recording(audio_device_t *dev)
     276{
     277        CHECK_BUFFER_AND_CONNECTION();
     278
     279        async_exch_t *exch = async_exchange_begin(dev->sess);
     280        const int ret = audio_pcm_start_record(exch, dev->buffer.id,
     281            BUFFER_BLOCKS, dev->sink.format.channels,
     282            dev->sink.format.sampling_rate, dev->sink.format.sample_format);
     283        async_exchange_end(exch);
     284        return ret;
     285}
     286
     287static int stop_recording(audio_device_t *dev)
     288{
     289        CHECK_BUFFER_AND_CONNECTION();
     290
     291        async_exch_t *exch = async_exchange_begin(dev->sess);
     292        const int ret = audio_pcm_stop_record(exch, dev->buffer.id);
     293        async_exchange_end(exch);
     294        return ret;
     295}
    180296
    181297/**
  • uspace/srv/audio/hound/audio_device.h

    rec49085 r992ef56  
    5656                fibril_mutex_t guard;
    5757                fibril_condvar_t wc;
     58                unsigned id;
    5859                void *base;
    5960                size_t size;
    60                 audio_format_t format;
    61                 void *available_base;
    62                 size_t available_size;
     61                void *position;
    6362        } buffer;
    6463        audio_source_t source;
Note: See TracChangeset for help on using the changeset viewer.