Changeset c799138 in mainline
- Timestamp:
- 2013-04-11T01:34:41Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 250828a
- Parents:
- f0a647c
- Location:
- uspace/srv/audio/hound
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/audio/hound/audio_data.c
rf0a647c rc799138 40 40 #include "log.h" 41 41 42 /** 43 * Create reference counted buffer out of ordinary data buffer. 44 * @param data audio buffer 45 * @param size Size of the @p data buffer. 46 * @param fomart audio data format. 47 * @return pointer to valid audio data structre, NULL on failure. 48 */ 42 49 audio_data_t *audio_data_create(const void *data, size_t size, 43 50 pcm_format_t format) … … 58 65 } 59 66 67 /** 68 * Get a new reference to the audio data buffer. 69 * @param adata The audio data buffer. 70 */ 60 71 void audio_data_addref(audio_data_t *adata) 61 72 { … … 65 76 } 66 77 78 /** 79 * Release a reference to the audio data buffer. 80 * @param adata The audio data buffer. 81 */ 67 82 void audio_data_unref(audio_data_t *adata) 68 83 { … … 78 93 /* Data link helpers */ 79 94 95 /** Audio data buffer list helper structure. */ 80 96 typedef struct { 81 97 link_t link; … … 84 100 } audio_data_link_t; 85 101 102 /** List instance helper function. 103 * @param l link 104 * @return valid pointer to data link structure, NULL on failure. 105 */ 86 106 static inline audio_data_link_t * audio_data_link_list_instance(link_t *l) 87 107 { … … 89 109 } 90 110 111 /** 112 * Create a new audio data link. 113 * @param adata Audio data to store. 114 * @return Valid pointer to a new audio data link structure, NULL on failure. 115 */ 91 116 static audio_data_link_t *audio_data_link_create(audio_data_t *adata) 92 117 { … … 101 126 } 102 127 128 /** 129 * Destroy audio data link. 130 * @param link The link to destroy. 131 * 132 * Releases data reference. 133 */ 103 134 static void audio_data_link_destroy(audio_data_link_t *link) 104 135 { … … 109 140 } 110 141 142 /** 143 * Data link buffer start helper function. 144 * @param alink audio data link 145 * @return pointer to the beginning of data buffer. 146 */ 111 147 static inline const void * audio_data_link_start(audio_data_link_t *alink) 112 148 { … … 116 152 } 117 153 154 /** 155 * Data link remaining size getter. 156 * @param alink audio data link 157 * @return Remaining size of valid data in the buffer. 158 */ 118 159 static inline size_t audio_data_link_remain_size(audio_data_link_t *alink) 119 160 { … … 125 166 126 167 168 /** 169 * Data link remaining frames getter. 170 * @param alink audio data link 171 * @return Number of remaining frames in the buffer. 172 */ 127 173 static inline size_t audio_data_link_available_frames(audio_data_link_t *alink) 128 174 { … … 135 181 /* Audio Pipe */ 136 182 137 183 /** 184 * Initialize audio pipe structure. 185 * @param pipe The pipe structure to initialize. 186 */ 138 187 void audio_pipe_init(audio_pipe_t *pipe) 139 188 { … … 145 194 } 146 195 147 148 196 /** 197 * Destroy all data in a pipe. 198 * @param pipe The audio pipe to clean. 199 */ 149 200 void audio_pipe_fini(audio_pipe_t *pipe) 150 201 { … … 156 207 } 157 208 209 /** 210 * Add new audio data to a pipe. 211 * @param pipe The target pipe. 212 * @param data The data. 213 * @return Error code. 214 */ 158 215 int audio_pipe_push(audio_pipe_t *pipe, audio_data_t *data) 159 216 { … … 172 229 } 173 230 231 /** 232 * Retrieve data form a audio pipe. 233 * @param pipe THe target pipe. 234 * @return Valid pointer to audio data, NULL if the pipe was empty. 235 */ 174 236 audio_data_t *audio_pipe_pop(audio_pipe_t *pipe) 175 237 { … … 191 253 } 192 254 255 256 /** 257 * Use data store in a pipe and mix it into the provided buffer. 258 * @param pipe The piep that should provide data. 259 * @param data Target buffer. 260 * @param size Target buffer size. 261 * @param format Target data format. 262 * @return Size of the target buffer used, Error code on failure. 263 */ 193 264 ssize_t audio_pipe_mix_data(audio_pipe_t *pipe, void *data, 194 265 size_t size, const pcm_format_t *f) -
uspace/srv/audio/hound/audio_data.h
rf0a647c rc799138 43 43 #include <pcm/format.h> 44 44 45 /** Reference counted audio buffer */ 45 46 typedef struct { 47 /** Audio data */ 46 48 const void *data; 49 /** Size of the buffer pointer to by data */ 47 50 size_t size; 51 /** Format of the audio data */ 48 52 pcm_format_t format; 53 /** Reference counter */ 49 54 atomic_t refcount; 50 55 } audio_data_t; 51 56 57 /** Audio data pipe structure */ 52 58 typedef struct { 59 /** List of audio data buffers */ 53 60 list_t list; 61 /** Total size of all buffers */ 54 62 size_t bytes; 63 /** Total frames stored in all buffers */ 55 64 size_t frames; 65 /** List access synchronization */ 56 66 fibril_mutex_t guard; 57 67 } audio_pipe_t; … … 71 81 const pcm_format_t *f); 72 82 83 /** 84 * Total bytes getter. 85 * @param pipe The audio pipe. 86 * @return Total size of buffer stored in the pipe. 87 */ 73 88 static inline size_t audio_pipe_bytes(audio_pipe_t *pipe) 74 89 { … … 77 92 } 78 93 94 /** 95 * Total bytes getter. 96 * @param pipe The audio pipe. 97 * @return Total number of frames stored in the pipe. 98 */ 79 99 static inline size_t audio_pipe_frames(audio_pipe_t *pipe) 80 100 { … … 83 103 } 84 104 105 /** 106 * Push data form buffer directly to pipe. 107 * @param pipe The target pipe. 108 * @param data audio buffer. 109 * @param size size of the @p data buffer 110 * @param f format of the audio data. 111 * @return Error code. 112 * 113 * Reference counted buffer is created automatically. 114 */ 85 115 static inline int audio_pipe_push_data(audio_pipe_t *pipe, 86 116 const void *data, size_t size, pcm_format_t f) -
uspace/srv/audio/hound/audio_device.c
rf0a647c rc799138 46 46 #include "log.h" 47 47 48 /* hardwired to provide ~21ms per fragment */ 48 49 #define BUFFER_PARTS 16 49 50 … … 56 57 static void fill_buffer(audio_device_t *dev, size_t size); 57 58 58 59 /** 60 * Initialize audio device structure. 61 * @param dev The structure to initialize. 62 * @param id Location service id of the device driver. 63 * @param name Name of the device. 64 * @return Error code. 65 */ 59 66 int audio_device_init(audio_device_t *dev, service_id_t id, const char *name) 60 67 { … … 85 92 return EOK; 86 93 } 94 95 /** 96 * Restore resource cplaimed during initialization. 97 * @param dev The device to release. 98 * 99 * NOT IMPLEMENTED 100 */ 87 101 void audio_device_fini(audio_device_t *dev) 88 102 { … … 90 104 } 91 105 106 /** 107 * Get device provided audio source. 108 * @param dev Th device. 109 * @return pointer to aa audio source structure, NULL if the device is not 110 * capable of capturing audio. 111 */ 112 audio_source_t * audio_device_get_source(audio_device_t *dev) 113 { 114 assert(dev); 115 if (audio_pcm_query_cap(dev->sess, AUDIO_CAP_CAPTURE)) 116 return &dev->source; 117 return NULL; 118 } 119 120 /** 121 * Get device provided audio sink. 122 * @param dev Th device. 123 * @return pointer to aa audio source structure, NULL if the device is not 124 * capable of audio playback. 125 */ 126 audio_sink_t * audio_device_get_sink(audio_device_t *dev) 127 { 128 assert(dev); 129 if (audio_pcm_query_cap(dev->sess, AUDIO_CAP_PLAYBACK)) 130 return &dev->sink; 131 return NULL; 132 } 133 134 /** 135 * Handle connection addition and removal. 136 * @param sink audio sink that is connected or disconnected. 137 * @param new True of a connection was added, false otherwise. 138 * @return Error code. 139 * 140 * Starts playback on first connection. Stops playback when there are no 141 * connections. 142 */ 92 143 static int device_sink_connection_callback(audio_sink_t* sink, bool new) 93 144 { … … 147 198 } 148 199 200 /** 201 * Handle connection addition and removal. 202 * @param source audio source that is connected or disconnected. 203 * @param new True of a connection was added, false otherwise. 204 * @return Error code. 205 * 206 * Starts capture on first connection. Stops capture when there are no 207 * connections. 208 */ 149 209 static int device_source_connection_callback(audio_source_t *source, bool new) 150 210 { … … 158 218 return ret; 159 219 } 220 221 //TODO set and test format 222 160 223 const unsigned frames = dev->buffer.fragment_size / 161 224 pcm_format_frame_size(&dev->sink.format); 162 225 ret = audio_pcm_start_capture_fragment(dev->sess, frames, 163 dev->sink.format.channels, dev->sink.format.sampling_rate, 164 dev->sink.format.sample_format); 226 dev->source.format.channels, 227 dev->source.format.sampling_rate, 228 dev->source.format.sample_format); 165 229 if (ret != EOK) { 166 230 log_error("Failed to start recording: %s", … … 191 255 } 192 256 257 /** 258 * Audio device event handler. 259 * @param iid initial call id. 260 * @param icall initial call structure. 261 * @param arg (unused) 262 */ 193 263 static void device_event_callback(ipc_callid_t iid, ipc_call_t *icall, void *arg) 194 264 { … … 226 296 } 227 297 298 /** 299 * Test format against hardware limits. 300 * @param sink audio playback device. 301 * @return Error code. 302 */ 228 303 static int device_check_format(audio_sink_t* sink) 229 304 { … … 236 311 } 237 312 313 /** 314 * Get access to device buffer. 315 * @param dev Audio device. 316 * @return Error code. 317 */ 238 318 static int get_buffer(audio_device_t *dev) 239 319 { … … 262 342 } 263 343 344 /** 345 * Surrender access to device buffer. 346 * @param dev Audio device. 347 * @return Error code. 348 */ 264 349 static int release_buffer(audio_device_t *dev) 265 350 { … … 278 363 } 279 364 365 /** 366 * Mix data from all connections and add it to the device buffer. 367 * @param dev Audio device. 368 * @param size portion of the device buffer to fill. 369 */ 280 370 static void fill_buffer(audio_device_t *dev, size_t size) 281 371 { -
uspace/srv/audio/hound/audio_device.h
rf0a647c rc799138 47 47 #include "audio_sink.h" 48 48 49 /** Audio device structure. */ 49 50 typedef struct { 51 /** Link in hound's device list */ 50 52 link_t link; 53 /** Location service id of the audio driver */ 51 54 service_id_t id; 55 /** IPC session to the device driver. */ 52 56 audio_pcm_sess_t *sess; 57 /** Device name */ 53 58 char *name; 59 /** Device buffer */ 54 60 struct { 55 61 void *base; … … 58 64 size_t fragment_size; 59 65 } buffer; 66 /** Capture device abstraction. */ 60 67 audio_source_t source; 68 /** Playback device abstraction. */ 61 69 audio_sink_t sink; 62 70 } audio_device_t; 63 71 72 /** Linked list instance helper */ 64 73 static inline audio_device_t * audio_device_list_instance(link_t *l) 65 74 { 66 return l ist_get_instance(l, audio_device_t, link);75 return l ? list_get_instance(l, audio_device_t, link) : NULL; 67 76 }; 68 77 69 78 int audio_device_init(audio_device_t *dev, service_id_t id, const char *name); 70 79 void audio_device_fini(audio_device_t *dev); 71 static inline audio_source_t * audio_device_get_source(audio_device_t *dev) 72 { 73 assert(dev); 74 return &dev->source; 75 } 76 77 static inline audio_sink_t * audio_device_get_sink(audio_device_t *dev) 78 { 79 assert(dev); 80 return &dev->sink; 81 } 82 80 audio_source_t * audio_device_get_source(audio_device_t *dev); 81 audio_sink_t * audio_device_get_sink(audio_device_t *dev); 83 82 int audio_device_recorded_data(audio_device_t *dev, void **base, size_t *size); 84 83 int audio_device_available_buffer(audio_device_t *dev, void **base, size_t *size); -
uspace/srv/audio/hound/audio_sink.c
rf0a647c rc799138 45 45 46 46 47 /** 48 * Initialize audio sink structure. 49 * @param sink The structure to initialize. 50 * @param name string identifier 51 * @param private_data backa 52 */ 47 53 int audio_sink_init(audio_sink_t *sink, const char *name, 48 54 void *private_data, int (*connection_change)(audio_sink_t *, bool), … … 50 56 { 51 57 assert(sink); 52 if (!name) { 53 log_debug("Incorrect parameters."); 58 if (!name) 54 59 return EINVAL; 55 }56 60 link_initialize(&sink->link); 57 61 list_initialize(&sink->connections); 58 62 sink->name = str_dup(name); 63 if (!sink->name) 64 return ENOMEM; 59 65 sink->private_data = private_data; 60 66 sink->format = *f; … … 65 71 } 66 72 73 /** 74 * Release resources claimed by initialization. 75 * @param sink the structure to release. 76 */ 67 77 void audio_sink_fini(audio_sink_t *sink) 68 78 { … … 74 84 } 75 85 76 #if 0 77 int audio_sink_add_source(audio_sink_t *sink, audio_source_t *source) 78 { 79 assert(sink); 80 assert(source); 81 assert_link_not_used(&source->link); 82 list_append(&source->link, &sink->sources); 83 84 const pcm_format_t old_format = sink->format; 85 86 /* The first source for me */ 87 if (list_count(&sink->sources) == 1) { 88 /* Set audio format according to the first source */ 89 if (pcm_format_is_any(&sink->format)) { 90 int ret = audio_sink_set_format(sink, &source->format); 91 if (ret != EOK) 92 return ret; 93 } 94 } 95 96 audio_source_connected(source, sink); 97 if (sink->connection_change) { 98 log_verbose("Calling connection change"); 99 const int ret = sink->connection_change(sink, true); 100 if (ret != EOK) { 101 log_debug("Connection hook failed."); 102 // audio_source_connected(source, NULL); 103 // list_remove(&source->link); 104 // sink->format = old_format; 105 return ret; 106 } 107 } 108 log_verbose("Connected source '%s' to sink '%s'", 109 source->name, sink->name); 110 111 return EOK; 112 } 113 #endif 114 86 /** 87 * Set audio sink format and check with backend, 88 * @param sink The target sink isntance. 89 * @param format Th new format. 90 * @return Error code. 91 */ 115 92 int audio_sink_set_format(audio_sink_t *sink, const pcm_format_t *format) 116 93 { … … 143 120 } 144 121 145 #if 0 146 int audio_sink_remove_source(audio_sink_t *sink, audio_source_t *source) 147 { 148 assert(sink); 149 assert(source); 150 assert(list_member(&source->link, &sink->sources)); 151 list_remove(&source->link); 152 if (sink->connection_change) { 153 const int ret = sink->connection_change(sink, false); 154 if (ret != EOK) { 155 log_debug("Connected hook failed."); 156 list_append(&source->link, &sink->sources); 157 return ret; 158 } 159 } 160 audio_source_connected(source, NULL); 161 return EOK; 162 } 163 #endif 164 165 122 /** 123 * Pull data from all connections and add the mix to the destination. 124 * @param sink The sink to mix data. 125 * @param dest Destination buffer. 126 * @param size size of the @p dest buffer. 127 * @return Error code. 128 */ 166 129 void audio_sink_mix_inputs(audio_sink_t *sink, void* dest, size_t size) 167 130 { -
uspace/srv/audio/hound/audio_sink.h
rf0a647c rc799138 47 47 typedef struct audio_sink audio_sink_t; 48 48 49 /** Audio sink abstraction structure */ 49 50 struct audio_sink { 51 /** Link in hound's sink list */ 50 52 link_t link; 53 /** List of all related connections */ 51 54 list_t connections; 55 /** Sink's name */ 52 56 const char *name; 57 /** Consumes data in this format */ 53 58 pcm_format_t format; 59 /** Backend data */ 54 60 void *private_data; 61 /** Connect/disconnect callback */ 55 62 int (*connection_change)(audio_sink_t *, bool); 63 /** Backend callback to check data */ 56 64 int (*check_format)(audio_sink_t *); 57 65 }; 58 66 67 /** 68 * List instance helper. 69 * @param l link 70 * @return pointer to a sink structure, NULL on failure. 71 */ 59 72 static inline audio_sink_t * audio_sink_list_instance(link_t *l) 60 73 { … … 65 78 void *private_data, int (*connection_change)(audio_sink_t *, bool), 66 79 int (*check_format)(audio_sink_t *), const pcm_format_t *f); 80 67 81 void audio_sink_fini(audio_sink_t *sink); 68 69 82 int audio_sink_set_format(audio_sink_t *sink, const pcm_format_t *format); 70 //int audio_sink_add_source(audio_sink_t *sink, audio_source_t *source);71 //int audio_sink_remove_source(audio_sink_t *sink, audio_source_t *source);72 83 void audio_sink_mix_inputs(audio_sink_t *sink, void* dest, size_t size); 73 84 74 75 85 #endif 76 77 86 /** 78 87 * @} 79 88 */ 80 -
uspace/srv/audio/hound/audio_source.c
rf0a647c rc799138 45 45 #include "log.h" 46 46 47 47 /** 48 * Initialize audio source strcture. 49 * @param source The structure to initialize. 50 * @param name String identifier of the audio source. 51 * @param data Backend data. 52 * @param connection_change Connect/disconnect callback. 53 * @param update_available_data Data request callback. 54 * @return Error code. 55 */ 48 56 int audio_source_init(audio_source_t *source, const char *name, void *data, 49 57 int (*connection_change)(audio_source_t *, bool new), … … 69 77 } 70 78 79 /** 80 * Release resources claimed by initialization. 81 * @param source The structure to cleanup. 82 */ 71 83 void audio_source_fini(audio_source_t *source) 72 84 { -
uspace/srv/audio/hound/audio_source.h
rf0a647c rc799138 42 42 typedef struct audio_source audio_source_t; 43 43 44 /** Audio data source abstraction structure */ 44 45 struct audio_source { 46 /** Link in hound's sources list */ 45 47 link_t link; 48 /** List of connections */ 46 49 list_t connections; 50 /** String identifier */ 47 51 const char *name; 52 /** audio data format */ 48 53 pcm_format_t format; 54 /** backend data */ 49 55 void *private_data; 56 /** Callback for connection and disconnection */ 50 57 int (*connection_change)(audio_source_t *source, bool added); 58 /** Ask backend for more data */ 51 59 int (*update_available_data)(audio_source_t *source, size_t size); 52 60 }; 53 61 62 /** 63 * List instance helper. 64 * @param l link 65 * @return pointer to a source structure, NULL on failure. 66 */ 54 67 static inline audio_source_t * audio_source_list_instance(link_t *l) 55 68 { -
uspace/srv/audio/hound/connection.c
rf0a647c rc799138 40 40 #include "connection.h" 41 41 42 /** 43 * Create connection between source and sink. 44 * @param source Valid source structure. 45 * @param sink Valid sink structure. 46 * @return pointer to a valid connection structure, NULL on failure. 47 * 48 * Reports new connection to both the source and sink. 49 */ 42 50 connection_t *connection_create(audio_source_t *source, audio_sink_t *sink) 43 51 { … … 64 72 } 65 73 74 /** 75 * Destroy existing connection 76 * @param connection The connection to destroy. 77 * 78 * Disconnects from both the source and the sink. 79 */ 66 80 void connection_destroy(connection_t *connection) 67 81 { … … 80 94 } 81 95 96 /** 97 * Update and mix data provided by the source. 98 * @param connection the connection to add. 99 * @param data Destination audio buffer. 100 * @param size size of the destination audio buffer. 101 * @param format format of the destination audio buffer. 102 */ 82 103 ssize_t connection_add_source_data(connection_t *connection, void *data, 83 104 size_t size, pcm_format_t format) -
uspace/srv/audio/hound/connection.h
rf0a647c rc799138 45 45 #include "audio_sink.h" 46 46 47 /** Source->sink connection structure */ 47 48 typedef struct { 49 /** Source's connections link */ 48 50 link_t source_link; 51 /** Sink's connections link */ 49 52 link_t sink_link; 53 /** Hound's connections link */ 50 54 link_t hound_link; 55 /** audio data pipe */ 51 56 audio_pipe_t fifo; 57 /** Target sink */ 52 58 audio_sink_t *sink; 59 /** Target source */ 53 60 audio_source_t *source; 54 61 } connection_t; 55 62 63 /** 64 * List instance helper. 65 * @param l link 66 * @return pointer to a connection structure, NULL on failure. 67 */ 56 68 static inline connection_t * connection_from_source_list(link_t *l) 57 69 { … … 59 71 } 60 72 73 /** 74 * List instance helper. 75 * @param l link 76 * @return pointer to a connection structure, NULL on failure. 77 */ 61 78 static inline connection_t * connection_from_sink_list(link_t *l) 62 79 { … … 64 81 } 65 82 83 /** 84 * List instance helper. 85 * @param l link 86 * @return pointer to a connection structure, NULL on failure. 87 */ 66 88 static inline connection_t * connection_from_hound_list(link_t *l) 67 89 { … … 75 97 size_t size, pcm_format_t format); 76 98 99 /** 100 * Add new data to the connection buffer. 101 * @param connection Target conneciton. 102 * @aparam adata Reference counted audio data buffer. 103 * @return Error code. 104 */ 77 105 static inline int connection_push_data(connection_t *connection, 78 106 audio_data_t *adata) … … 83 111 } 84 112 113 /** 114 * Source name getter. 115 * @param connection Connection to the source. 116 * @param valid string identifier, "no source" or "unnamed source" on failure. 117 */ 85 118 static inline const char *connection_source_name(connection_t *connection) 86 119 { … … 88 121 if (connection->source && connection->source->name) 89 122 return connection->source->name; 123 // TODO assert? 90 124 return connection->source ? "unnamed source" : "no source"; 91 125 } 92 126 127 /** 128 * Sink name getter. 129 * @param connection Connection to the sink. 130 * @param valid string identifier, "no source" or "unnamed source" on failure. 131 */ 93 132 static inline const char *connection_sink_name(connection_t *connection) 94 133 { … … 96 135 if (connection->sink && connection->sink->name) 97 136 return connection->sink->name; 98 return connection->source ? "unnamed source" : "no source"; 137 // TODO assert? 138 return connection->source ? "unnamed sink" : "no sink"; 99 139 } 100 140 -
uspace/srv/audio/hound/hound.c
rf0a647c rc799138 63 63 } while (0) 64 64 65 /** 66 * Search devices by name. 67 * @param name String identifier. 68 * @return Pointer to the found device, NULL on failure. 69 */ 65 70 static audio_device_t * find_device_by_name(list_t *list, const char *name) 66 71 { 67 72 FIND_BY_NAME(device); 68 73 } 74 75 /** 76 * Search sources by name. 77 * @param name String identifier. 78 * @return Pointer to the found source, NULL on failure. 79 */ 69 80 static audio_source_t * find_source_by_name(list_t *list, const char *name) 70 81 { 71 82 FIND_BY_NAME(source); 72 83 } 84 85 /** 86 * Search sinks by name. 87 * @param name String identifier. 88 * @return Pointer to the found sink, NULL on failure. 89 */ 73 90 static audio_sink_t * find_sink_by_name(list_t *list, const char *name) 74 91 { … … 78 95 static int hound_disconnect_internal(hound_t *hound, const char* source_name, const char* sink_name); 79 96 97 /** 98 * Remove provided sink. 99 * @param hound The hound structure. 100 * @param sink Target sink to remove. 101 * 102 * This function has to be called with the list_guard lock held. 103 */ 80 104 static void hound_remove_sink_internal(hound_t *hound, audio_sink_t *sink) 81 105 { 82 106 assert(hound); 83 107 assert(sink); 108 assert(fibril_mutex_is_locked(&hound->list_guard)); 84 109 log_verbose("Removing sink '%s'.", sink->name); 85 110 if (!list_empty(&sink->connections)) … … 94 119 } 95 120 121 /** 122 * Remove provided source. 123 * @param hound The hound structure. 124 * @param sink Target source to remove. 125 * 126 * This function has to be called with the guard lock held. 127 */ 96 128 static void hound_remove_source_internal(hound_t *hound, audio_source_t *source) 97 129 { … … 111 143 } 112 144 145 /** 146 * Initialize hound structure. 147 * @param hound The structure to initialize. 148 * @return Error code. 149 */ 113 150 int hound_init(hound_t *hound) 114 151 { … … 123 160 } 124 161 162 /** 163 * Add a new application context. 164 * @param hound Hound structure. 165 * @param ctx Context to add. 166 * @return Error code. 167 */ 125 168 int hound_add_ctx(hound_t *hound, hound_ctx_t *ctx) 126 169 { … … 137 180 if (ret == EOK && ctx->sink) 138 181 ret = hound_add_sink(hound, ctx->sink); 139 if (ret != EOK) 140 hound_ctx_destroy(ctx); 182 if (ret != EOK) { 183 fibril_mutex_lock(&hound->list_guard); 184 list_remove(&ctx->link); 185 fibril_mutex_unlock(&hound->list_guard); 186 } 141 187 return ret; 142 188 } 143 189 190 /** 191 * Remove existing application context. 192 * @param hound Hound structure. 193 * @param ctx Context to remove. 194 * @return Error code. 195 */ 144 196 int hound_remove_ctx(hound_t *hound, hound_ctx_t *ctx) 145 197 { … … 159 211 } 160 212 213 /** 214 * Search registered contexts for the matching id. 215 * @param hound The hound structure. 216 * @param id Requested id. 217 * @return Pointer to the found structure, NULL on failure. 218 */ 161 219 hound_ctx_t *hound_get_ctx_by_id(hound_t *hound, hound_context_id_t id) 162 220 { … … 176 234 } 177 235 236 /** 237 * Add a new device. 238 * @param hound The hound structure. 239 * @param id Locations service id representing the device driver. 240 * @param name String identifier. 241 * @return Error code. 242 */ 178 243 int hound_add_device(hound_t *hound, service_id_t id, const char *name) 179 244 { … … 247 312 } 248 313 314 /** 315 * Register a new source. 316 * @param hound The hound structure. 317 * @param source A new source to add. 318 * @return Error code. 319 */ 249 320 int hound_add_source(hound_t *hound, audio_source_t *source) 250 321 { … … 265 336 } 266 337 338 /** 339 * Register a new sink. 340 * @param hound The hound structure. 341 * @param sink A new sink to add. 342 * @return Error code. 343 */ 267 344 int hound_add_sink(hound_t *hound, audio_sink_t *sink) 268 345 { … … 283 360 } 284 361 362 /** 363 * Remove a registered source. 364 * @param hound The hound structure. 365 * @param source A registered source to remove. 366 * @return Error code. 367 */ 285 368 int hound_remove_source(hound_t *hound, audio_source_t *source) 286 369 { … … 294 377 } 295 378 296 379 /** 380 * Remove a registered sink. 381 * @param hound The hound structure. 382 * @param sink A registered sink to remove. 383 * @return Error code. 384 */ 297 385 int hound_remove_sink(hound_t *hound, audio_sink_t *sink) 298 386 { … … 306 394 } 307 395 396 /** 397 * List all registered sources. 398 * @param[in] hound The hound structure. 399 * @param[out] list List of the string identifiers. 400 * @param[out] size Number of identifiers int he @p list. 401 * @return Error code. 402 */ 308 403 int hound_list_sources(hound_t *hound, const char ***list, size_t *size) 309 404 { … … 341 436 } 342 437 438 /** 439 * List all registered sinks. 440 * @param[in] hound The hound structure. 441 * @param[out] list List of the string identifiers. 442 * @param[out] size Number of identifiers int he @p list. 443 * @return Error code. 444 */ 343 445 int hound_list_sinks(hound_t *hound, const char ***list, size_t *size) 344 446 { … … 376 478 } 377 479 480 /** 481 * List all connections 482 * @param[in] hound The hound structure. 483 * @param[out] sources List of the source string identifiers. 484 * @param[out] sinks List of the sinks string identifiers. 485 * @param[out] size Number of identifiers int he @p list. 486 * @return Error code. 487 * 488 * Lists include duplicit name entries. The order of entries is important, 489 * identifiers with the same index are connected. 490 */ 378 491 int hound_list_connections(hound_t *hound, const char ***sources, 379 492 const char ***sinks, size_t *size) … … 384 497 } 385 498 499 /** 500 * Create and register a new connection. 501 * @param hound The hound structure. 502 * @param source_name Source's string id. 503 * @param sink_name Sink's string id. 504 * @return Error code. 505 */ 386 506 int hound_connect(hound_t *hound, const char* source_name, const char* sink_name) 387 507 { … … 416 536 } 417 537 538 /** 539 * Find and destroy connection between source and sink. 540 * @param hound The hound structure. 541 * @param source_name Source's string id. 542 * @param sink_name Sink's string id. 543 * @return Error code. 544 */ 418 545 int hound_disconnect(hound_t *hound, const char* source_name, const char* sink_name) 419 546 { … … 425 552 } 426 553 554 /** 555 * Internal disconnect helper. 556 * @param hound The hound structure. 557 * @param source_name Source's string id. 558 * @param sink_name Sink's string id. 559 * @return Error code. 560 * 561 * This function has to be called with the list_guard lock held. 562 */ 427 563 static int hound_disconnect_internal(hound_t *hound, const char* source_name, 428 564 const char* sink_name) -
uspace/srv/audio/hound/hound.h
rf0a647c rc799138 49 49 #include "audio_sink.h" 50 50 51 51 /** The main Hound structure */ 52 52 typedef struct { 53 /** List access guard */ 53 54 fibril_mutex_t list_guard; 55 /** enumerated devices */ 54 56 list_t devices; 57 /** registered contexts */ 55 58 list_t contexts; 59 /** Provided sources */ 56 60 list_t sources; 61 /** Provided sinks */ 57 62 list_t sinks; 63 /** Existing connections. */ 58 64 list_t connections; 59 65 } hound_t; -
uspace/srv/audio/hound/hound_ctx.c
rf0a647c rc799138 45 45 static int update_data(audio_source_t *source, size_t size); 46 46 47 /** 48 * Allocate and initialize hound context structure. 49 * @param name String identifier. 50 * @return Pointer to a new context structure, NULL on failure 51 * 52 * Creates record context structure. 53 */ 47 54 hound_ctx_t *hound_record_ctx_get(const char *name) 48 55 { 49 return NULL; 50 } 51 56 hound_ctx_t *ctx = malloc(sizeof(hound_ctx_t)); 57 if (ctx) { 58 link_initialize(&ctx->link); 59 list_initialize(&ctx->streams); 60 fibril_mutex_initialize(&ctx->guard); 61 ctx->source = NULL; 62 ctx->sink = malloc(sizeof(audio_sink_t)); 63 if (!ctx->sink) { 64 free(ctx); 65 return NULL; 66 } 67 // TODO provide sink functions 68 const int ret = audio_sink_init(ctx->sink, name, ctx, NULL, 69 NULL, &AUDIO_FORMAT_DEFAULT); 70 if (ret != EOK) { 71 free(ctx->sink); 72 free(ctx); 73 return NULL; 74 } 75 } 76 return ctx; 77 } 78 79 /** 80 * Allocate and initialize hound context structure. 81 * @param name String identifier. 82 * @return Pointer to a new context structure, NULL on failure 83 * 84 * Creates record context structure. 85 */ 52 86 hound_ctx_t *hound_playback_ctx_get(const char *name) 53 87 { … … 74 108 } 75 109 110 /** 111 * Destroy existing context structure. 112 * @param ctx hound cotnext to destroy. 113 */ 76 114 void hound_ctx_destroy(hound_ctx_t *ctx) 77 115 { … … 88 126 } 89 127 128 /** 129 * Retrieve associated context id. 130 * @param ctx hound context. 131 * @return context id of the context. 132 */ 90 133 hound_context_id_t hound_ctx_get_id(hound_ctx_t *ctx) 91 134 { … … 94 137 } 95 138 139 /** 140 * Query playback/record status of a hound context. 141 * @param ctx Hound context. 142 * @return True if ctx is a recording context. 143 */ 96 144 bool hound_ctx_is_record(hound_ctx_t *ctx) 97 145 { … … 104 152 * STREAMS 105 153 */ 154 155 /** Hound stream structure. */ 106 156 typedef struct hound_ctx_stream { 157 /** Hound context streams link */ 107 158 link_t link; 159 /** Audio data pipe */ 108 160 audio_pipe_t fifo; 161 /** Parent context */ 109 162 hound_ctx_t *ctx; 163 /** Stream data format */ 110 164 pcm_format_t format; 165 /** Stream modifiers */ 111 166 int flags; 167 /** Maximum allowed buffer size */ 112 168 size_t allowed_size; 169 /** Fifo access synchronization */ 113 170 fibril_mutex_t guard; 171 /** buffer status change condition */ 114 172 fibril_condvar_t change; 115 173 } hound_ctx_stream_t; 116 174 175 /** 176 * List instance helper. 177 * @param l link 178 * @return pointer to a hound context structure, NULL on failure. 179 */ 117 180 static inline hound_ctx_stream_t *hound_ctx_stream_from_link(link_t *l) 118 181 { … … 120 183 } 121 184 185 /** 186 * New stream append helper. 187 * @param ctx hound context. 188 * @param stream A new stream. 189 */ 122 190 static inline void stream_append(hound_ctx_t *ctx, hound_ctx_stream_t *stream) 123 191 { … … 129 197 } 130 198 199 /** 200 * Old stream remove helper. 201 * @param ctx hound context. 202 * @param stream An old stream. 203 */ 131 204 static inline void stream_remove(hound_ctx_t *ctx, hound_ctx_stream_t *stream) 132 205 { … … 138 211 } 139 212 213 /** 214 * Create new stream. 215 * @param ctx Assocaited hound context. 216 * @param flags Stream modidfiers. 217 * @param format PCM data format. 218 * @param buffer_size Maximum allowed buffer size. 219 * @return Pointer to a new stream structure, NULL on failure. 220 */ 140 221 hound_ctx_stream_t *hound_ctx_create_stream(hound_ctx_t *ctx, int flags, 141 222 pcm_format_t format, size_t buffer_size) … … 160 241 } 161 242 243 /** 244 * Destroy existing stream structure. 245 * @param stream The stream to destroy. 246 * 247 * The function will print warning if there are data in the buffer. 248 */ 162 249 void hound_ctx_destroy_stream(hound_ctx_stream_t *stream) 163 250 { … … 177 264 } 178 265 179 266 /** 267 * Write new data to a stream. 268 * @param stream The destination stream. 269 * @param data audio data buffer. 270 * @param size size of the @p data buffer. 271 * @return Error code. 272 */ 180 273 int hound_ctx_stream_write(hound_ctx_stream_t *stream, const void *data, 181 274 size_t size) … … 199 292 } 200 293 294 /** 295 * Read data from a buffer. 296 * @param stream The source buffer. 297 * @param data Destination data buffer. 298 * @param size Size of the @p data buffer. 299 * @return Error code. 300 */ 201 301 int hound_ctx_stream_read(hound_ctx_stream_t *stream, void *data, size_t size) 202 302 { … … 205 305 } 206 306 307 /** 308 * Add (mix) stream data to the destination buffer. 309 * @param stream The source stream. 310 * @param data Destination audio buffer. 311 * @param size Size of the @p data buffer. 312 * @param format Destination data format. 313 * @return Size of the destination buffer touch with stream's data, 314 * error code on failure. 315 */ 207 316 ssize_t hound_ctx_stream_add_self(hound_ctx_stream_t *stream, void *data, 208 317 size_t size, const pcm_format_t *f) … … 216 325 } 217 326 327 /** 328 * Block until the stream's buffer is empty. 329 * @param stream Target stream. 330 */ 218 331 void hound_ctx_stream_drain(hound_ctx_stream_t *stream) 219 332 { … … 226 339 } 227 340 341 /** 342 * Update context data. 343 * @param source Source abstraction. 344 * @param size Required size in source's format. 345 * @return error code. 346 * 347 * Mixes data from all streams and pushes it to all connections. 348 */ 228 349 int update_data(audio_source_t *source, size_t size) 229 350 { -
uspace/srv/audio/hound/hound_ctx.h
rf0a647c rc799138 44 44 #include "audio_sink.h" 45 45 46 /** Application context structure */ 46 47 typedef struct { 48 /** Hound's contexts link */ 47 49 link_t link; 50 /** List of streams */ 48 51 list_t streams; 52 /** Provided audio source abstraction */ 49 53 audio_source_t *source; 54 /** Provided audio sink abstraction */ 50 55 audio_sink_t *sink; 56 /** List access synchronization */ 51 57 fibril_mutex_t guard; 52 58 } hound_ctx_t; 53 59 60 /** 61 * List instance helper. 62 * @param l link 63 * @return pointer to a hound context structure, NULL on failure. 64 */ 54 65 static inline hound_ctx_t *hound_ctx_from_link(link_t *l) 55 66 {
Note:
See TracChangeset
for help on using the changeset viewer.