static size_t osx_output_play(struct audio_output *ao, const void *chunk, size_t size, G_GNUC_UNUSED GError **error) { struct osx_output *od = (struct osx_output *)ao; g_mutex_lock(od->mutex); void *dest; size_t max_length; while (true) { dest = fifo_buffer_write(od->buffer, &max_length); if (dest != NULL) break; /* wait for some free space in the buffer */ g_cond_wait(od->condition, od->mutex); } if (size > max_length) size = max_length; memcpy(dest, chunk, size); fifo_buffer_append(od->buffer, size); g_mutex_unlock(od->mutex); return size; }
void growing_fifo_append(struct fifo_buffer **buffer_p, const void *data, size_t length) { void *p = growing_fifo_write(buffer_p, length); memcpy(p, data, length); fifo_buffer_append(*buffer_p, length); }
static bool httpd_client_read(struct httpd_client *client) { char *p; size_t max_length; GError *error = NULL; GIOStatus status; gsize bytes_read; if (client->state == RESPONSE) { /* the client has already sent the request, and he must not send more */ char buffer[1]; status = g_io_channel_read_chars(client->channel, buffer, sizeof(buffer), &bytes_read, NULL); if (status == G_IO_STATUS_NORMAL) g_warning("unexpected input from client"); return false; } p = fifo_buffer_write(client->input, &max_length); if (p == NULL) { g_warning("buffer overflow"); return false; } status = g_io_channel_read_chars(client->channel, p, max_length, &bytes_read, &error); switch (status) { case G_IO_STATUS_NORMAL: fifo_buffer_append(client->input, bytes_read); return httpd_client_received(client); case G_IO_STATUS_AGAIN: /* try again later, after select() */ return true; case G_IO_STATUS_EOF: /* peer disconnected */ return false; case G_IO_STATUS_ERROR: /* I/O error */ g_warning("failed to read from client: %s", error->message); g_error_free(error); return false; } /* unreachable */ return false; }
static bool wave_encoder_open(struct encoder *_encoder, G_GNUC_UNUSED struct audio_format *audio_format, G_GNUC_UNUSED GError **error) { struct wave_encoder *encoder = (struct wave_encoder *)_encoder; assert(audio_format_valid(audio_format)); switch (audio_format->format) { case SAMPLE_FORMAT_S8: encoder->bits = 8; break; case SAMPLE_FORMAT_S16: encoder->bits = 16; break; case SAMPLE_FORMAT_S24: audio_format->format = SAMPLE_FORMAT_S24_P32; encoder->bits = 24; break; case SAMPLE_FORMAT_S24_P32: encoder->bits = 24; break; case SAMPLE_FORMAT_S32: encoder->bits = 32; break; default: audio_format->format = SAMPLE_FORMAT_S16; encoder->bits = 16; break; } encoder->buffer = growing_fifo_new(); struct wave_header *header = growing_fifo_write(&encoder->buffer, sizeof(*header)); /* create PCM wave header in initial buffer */ fill_wave_header(header, audio_format->channels, encoder->bits, audio_format->sample_rate, (encoder->bits / 8) * audio_format->channels ); fifo_buffer_append(encoder->buffer, sizeof(*header)); return true; }
static gboolean mpd_inotify_in_event(G_GNUC_UNUSED GIOChannel *_source, G_GNUC_UNUSED GIOCondition condition, gpointer data) { struct mpd_inotify_source *source = data; void *dest; size_t length; ssize_t nbytes; const struct inotify_event *event; dest = fifo_buffer_write(source->buffer, &length); if (dest == NULL) MPD_ERROR("buffer full"); nbytes = read(source->fd, dest, length); if (nbytes < 0) MPD_ERROR("failed to read from inotify: %s", g_strerror(errno)); if (nbytes == 0) MPD_ERROR("end of file from inotify"); fifo_buffer_append(source->buffer, nbytes); while (true) { const char *name; event = fifo_buffer_read(source->buffer, &length); if (event == NULL || length < sizeof(*event) || length < sizeof(*event) + event->len) break; if (event->len > 0 && event->name[event->len - 1] == 0) name = event->name; else name = NULL; source->callback(event->wd, event->mask, name, source->callback_ctx); fifo_buffer_consume(source->buffer, sizeof(*event) + event->len); } return true; }
static int client_input_received(struct client *client, size_t bytesRead) { char *line; int ret; fifo_buffer_append(client->input, bytesRead); /* process all lines */ while ((line = client_read_line(client)) != NULL) { ret = client_process_line(client, line); g_free(line); if (ret == COMMAND_RETURN_KILL || ret == COMMAND_RETURN_CLOSE) return ret; if (client_is_expired(client)) return COMMAND_RETURN_CLOSE; } return 0; }