mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-14 08:15:02 -05:00
commit
633d297936
@ -40,6 +40,45 @@
|
||||
|
||||
#define FIFO_BUFFER_SIZE 65536 /* pipe capacity on Linux >= 2.6.11 */
|
||||
|
||||
|
||||
struct fifo_packet
|
||||
{
|
||||
/* pcm data */
|
||||
uint8_t samples[1408]; // STOB(AIRTUNES_V2_PACKET_SAMPLES)
|
||||
|
||||
/* RTP-time of the first sample*/
|
||||
uint64_t rtptime;
|
||||
|
||||
struct fifo_packet *next;
|
||||
struct fifo_packet *prev;
|
||||
};
|
||||
|
||||
struct fifo_buffer
|
||||
{
|
||||
struct fifo_packet *head;
|
||||
struct fifo_packet *tail;
|
||||
};
|
||||
static struct fifo_buffer buffer;
|
||||
|
||||
|
||||
static void
|
||||
free_buffer()
|
||||
{
|
||||
struct fifo_packet *packet;
|
||||
struct fifo_packet *tmp;
|
||||
|
||||
packet = buffer.tail;
|
||||
while (packet)
|
||||
{
|
||||
tmp = packet;
|
||||
packet = packet->next;
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
buffer.tail = NULL;
|
||||
buffer.head = NULL;
|
||||
}
|
||||
|
||||
struct fifo_session
|
||||
{
|
||||
enum output_device_state state;
|
||||
@ -201,7 +240,7 @@ fifo_session_free(struct fifo_session *fifo_session)
|
||||
|
||||
free(fifo_session->output_session);
|
||||
free(fifo_session);
|
||||
|
||||
free_buffer();
|
||||
fifo_session = NULL;
|
||||
}
|
||||
|
||||
@ -315,6 +354,7 @@ fifo_device_stop(struct output_session *output_session)
|
||||
struct fifo_session *fifo_session = output_session->session;
|
||||
|
||||
fifo_close(fifo_session);
|
||||
free_buffer();
|
||||
|
||||
fifo_session->state = OUTPUT_STATE_STOPPED;
|
||||
fifo_status(fifo_session);
|
||||
@ -383,6 +423,8 @@ fifo_playback_stop(void)
|
||||
if (!fifo_session)
|
||||
return;
|
||||
|
||||
free_buffer();
|
||||
|
||||
fifo_session->state = OUTPUT_STATE_CONNECTED;
|
||||
fifo_status(fifo_session);
|
||||
}
|
||||
@ -396,11 +438,12 @@ fifo_flush(output_status_cb cb, uint64_t rtptime)
|
||||
return 0;
|
||||
|
||||
fifo_empty(fifo_session);
|
||||
free_buffer();
|
||||
|
||||
fifo_session->status_cb = cb;
|
||||
fifo_session->state = OUTPUT_STATE_CONNECTED;
|
||||
fifo_status(fifo_session);
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -409,15 +452,43 @@ fifo_write(uint8_t *buf, uint64_t rtptime)
|
||||
struct fifo_session *fifo_session = sessions;
|
||||
size_t length = STOB(AIRTUNES_V2_PACKET_SAMPLES);
|
||||
ssize_t bytes;
|
||||
struct fifo_packet *packet;
|
||||
uint64_t cur_pos;
|
||||
struct timespec now;
|
||||
int ret;
|
||||
|
||||
if (!fifo_session || !fifo_session->device->selected)
|
||||
return;
|
||||
|
||||
while (1)
|
||||
packet = (struct fifo_packet *) calloc(1, sizeof(struct fifo_packet));
|
||||
memcpy(packet->samples, buf, sizeof(packet->samples));
|
||||
packet->rtptime = rtptime;
|
||||
if (buffer.head)
|
||||
{
|
||||
bytes = write(fifo_session->output_fd, buf, length);
|
||||
buffer.head->next = packet;
|
||||
packet->prev = buffer.head;
|
||||
}
|
||||
buffer.head = packet;
|
||||
if (!buffer.tail)
|
||||
buffer.tail = packet;
|
||||
|
||||
ret = player_get_current_pos(&cur_pos, &now, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_FIFO, "Could not get playback position\n");
|
||||
return;
|
||||
}
|
||||
|
||||
while (buffer.tail && buffer.tail->rtptime <= cur_pos)
|
||||
{
|
||||
bytes = write(fifo_session->output_fd, buffer.tail->samples, length);
|
||||
if (bytes > 0)
|
||||
return;
|
||||
{
|
||||
packet = buffer.tail;
|
||||
buffer.tail = buffer.tail->next;
|
||||
free(packet);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bytes < 0)
|
||||
{
|
||||
@ -463,6 +534,8 @@ fifo_init(void)
|
||||
|
||||
nickname = cfg_getstr(cfg_fifo, "nickname");
|
||||
|
||||
memset(&buffer, 0, sizeof(struct fifo_buffer));
|
||||
|
||||
device = calloc(1, sizeof(struct output_device));
|
||||
if (!device)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user