mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-26 07:05:57 -05:00
[outputs] Changes to interface of outputs module
* Drop output_sessions, was just a pointer to the actual session anyway * Drop the old write, flush and stop prototypes * Some minor changes/renaming Purpose of this is also to fix a race condition in player.c where it could try to start two sessions on the same speaker. This could happen because outputs_device_start() in line 2093 is conditional on device->session which however is false while a device is starting up.
This commit is contained in:
parent
cee740ae51
commit
14a6d318f0
117
src/outputs.c
117
src/outputs.c
@ -148,7 +148,7 @@ buffer_fill(struct output_buffer *obuf, void *buf, size_t bufsize, struct media_
|
||||
int n;
|
||||
|
||||
obuf->write_counter++;
|
||||
obuf->pts = pts;
|
||||
obuf->pts = *pts;
|
||||
|
||||
// The resampling/encoding (transcode) contexts work for a given input quality,
|
||||
// so if the quality changes we need to reset the contexts. We also do that if
|
||||
@ -207,49 +207,48 @@ buffer_drain(struct output_buffer *obuf)
|
||||
/* ----------------------------------- API ---------------------------------- */
|
||||
|
||||
int
|
||||
outputs_device_start(struct output_device *device, output_status_cb cb, uint64_t rtptime)
|
||||
outputs_device_start(struct output_device *device, output_status_cb cb)
|
||||
{
|
||||
if (outputs[device->type]->disabled)
|
||||
if (outputs[device->type]->disabled || !outputs[device->type]->device_start)
|
||||
return -1;
|
||||
|
||||
if (outputs[device->type]->device_start)
|
||||
return outputs[device->type]->device_start(device, cb, rtptime);
|
||||
else
|
||||
return -1;
|
||||
if (device->session)
|
||||
{
|
||||
DPRINTF(E_LOG, L_PLAYER, "Bug! outputs_device_start() called for a device that already has a session\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return outputs[device->type]->device_start(device, cb);
|
||||
}
|
||||
|
||||
int
|
||||
outputs_device_start2(struct output_device *device, output_status_cb cb)
|
||||
outputs_device_stop(struct output_device *device, output_status_cb cb)
|
||||
{
|
||||
if (outputs[device->type]->disabled)
|
||||
if (outputs[device->type]->disabled || !outputs[device->type]->device_stop)
|
||||
return -1;
|
||||
|
||||
if (outputs[device->type]->device_start2)
|
||||
return outputs[device->type]->device_start2(device, cb);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
if (!device->session)
|
||||
{
|
||||
DPRINTF(E_LOG, L_PLAYER, "Bug! outputs_device_stop() called for a device that has no session\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
outputs_device_stop(struct output_session *session)
|
||||
{
|
||||
if (outputs[session->type]->disabled)
|
||||
return;
|
||||
|
||||
if (outputs[session->type]->device_stop)
|
||||
outputs[session->type]->device_stop(session);
|
||||
return outputs[device->type]->device_stop(device, cb);
|
||||
}
|
||||
|
||||
int
|
||||
outputs_device_probe(struct output_device *device, output_status_cb cb)
|
||||
{
|
||||
if (outputs[device->type]->disabled)
|
||||
if (outputs[device->type]->disabled || !outputs[device->type]->device_probe)
|
||||
return -1;
|
||||
|
||||
if (outputs[device->type]->device_probe)
|
||||
return outputs[device->type]->device_probe(device, cb);
|
||||
else
|
||||
return -1;
|
||||
if (device->session)
|
||||
{
|
||||
DPRINTF(E_LOG, L_PLAYER, "Bug! outputs_device_probe() called for a device that already has a session\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return outputs[device->type]->device_probe(device, cb);
|
||||
}
|
||||
|
||||
void
|
||||
@ -311,6 +310,16 @@ outputs_device_quality_set(struct output_device *device, struct media_quality *q
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
outputs_device_set_cb(struct output_device *device, output_status_cb cb)
|
||||
{
|
||||
if (outputs[device->type]->disabled)
|
||||
return;
|
||||
|
||||
if (outputs[device->type]->device_set_cb)
|
||||
outputs[device->type]->device_set_cb(device, cb);
|
||||
}
|
||||
|
||||
void
|
||||
outputs_playback_stop(void)
|
||||
{
|
||||
@ -327,22 +336,7 @@ outputs_playback_stop(void)
|
||||
}
|
||||
|
||||
void
|
||||
outputs_write(uint8_t *buf, uint64_t rtptime)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; outputs[i]; i++)
|
||||
{
|
||||
if (outputs[i]->disabled)
|
||||
continue;
|
||||
|
||||
if (outputs[i]->write)
|
||||
outputs[i]->write(buf, rtptime);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
outputs_write2(void *buf, size_t bufsize, struct media_quality *quality, int nsamples, struct timespec *pts)
|
||||
outputs_write(void *buf, size_t bufsize, struct media_quality *quality, int nsamples, struct timespec *pts)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -353,15 +347,15 @@ outputs_write2(void *buf, size_t bufsize, struct media_quality *quality, int nsa
|
||||
if (outputs[i]->disabled)
|
||||
continue;
|
||||
|
||||
if (outputs[i]->write2)
|
||||
outputs[i]->write2(&output_buffer);
|
||||
if (outputs[i]->write)
|
||||
outputs[i]->write(&output_buffer);
|
||||
}
|
||||
|
||||
buffer_drain(&output_buffer);
|
||||
}
|
||||
|
||||
int
|
||||
outputs_flush(output_status_cb cb, uint64_t rtptime)
|
||||
outputs_flush(output_status_cb cb)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
@ -373,41 +367,12 @@ outputs_flush(output_status_cb cb, uint64_t rtptime)
|
||||
continue;
|
||||
|
||||
if (outputs[i]->flush)
|
||||
ret += outputs[i]->flush(cb, rtptime);
|
||||
ret += outputs[i]->flush(cb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
outputs_flush2(output_status_cb cb)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = 0;
|
||||
for (i = 0; outputs[i]; i++)
|
||||
{
|
||||
if (outputs[i]->disabled)
|
||||
continue;
|
||||
|
||||
if (outputs[i]->flush2)
|
||||
ret += outputs[i]->flush2(cb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
outputs_status_cb(struct output_session *session, output_status_cb cb)
|
||||
{
|
||||
if (outputs[session->type]->disabled)
|
||||
return;
|
||||
|
||||
if (outputs[session->type]->status_cb)
|
||||
outputs[session->type]->status_cb(session, cb);
|
||||
}
|
||||
|
||||
struct output_metadata *
|
||||
outputs_metadata_prepare(int id)
|
||||
{
|
||||
|
@ -140,18 +140,11 @@ struct output_device
|
||||
|
||||
// Opaque pointers to device and session data
|
||||
void *extra_device_info;
|
||||
struct output_session *session;
|
||||
void *session;
|
||||
|
||||
struct output_device *next;
|
||||
};
|
||||
|
||||
// Except for the type, sessions are opaque outside of the output backend
|
||||
struct output_session
|
||||
{
|
||||
enum output_types type;
|
||||
void *session;
|
||||
};
|
||||
|
||||
// Linked list of metadata prepared by each output backend
|
||||
struct output_metadata
|
||||
{
|
||||
@ -172,12 +165,12 @@ struct output_frame
|
||||
struct output_buffer
|
||||
{
|
||||
uint32_t write_counter; // REMOVE ME? not used for anything
|
||||
struct timespec *pts;
|
||||
struct timespec pts;
|
||||
struct output_frame frames[OUTPUTS_MAX_QUALITY_SUBSCRIPTIONS + 1];
|
||||
} output_buffer;
|
||||
|
||||
|
||||
typedef void (*output_status_cb)(struct output_device *device, struct output_session *session, enum output_device_state status);
|
||||
typedef void (*output_status_cb)(struct output_device *device, enum output_device_state status);
|
||||
|
||||
struct output_definition
|
||||
{
|
||||
@ -202,11 +195,10 @@ struct output_definition
|
||||
void (*deinit)(void);
|
||||
|
||||
// Prepare a playback session on device and call back
|
||||
int (*device_start)(struct output_device *device, output_status_cb cb, uint64_t rtptime);
|
||||
int (*device_start2)(struct output_device *device, output_status_cb cb);
|
||||
int (*device_start)(struct output_device *device, output_status_cb cb);
|
||||
|
||||
// Close a session prepared by device_start
|
||||
void (*device_stop)(struct output_session *session);
|
||||
// Close a session prepared by device_start and call back
|
||||
int (*device_stop)(struct output_device *device, output_status_cb cb);
|
||||
|
||||
// Test the connection to a device and call back
|
||||
int (*device_probe)(struct output_device *device, output_status_cb cb);
|
||||
@ -223,24 +215,22 @@ struct output_definition
|
||||
// Request a change of quality from the device
|
||||
int (*quality_set)(struct output_device *device, struct media_quality *quality);
|
||||
|
||||
// Change the call back associated with a device
|
||||
void (*device_set_cb)(struct output_device *device, output_status_cb cb);
|
||||
|
||||
// Start/stop playback on devices that were started
|
||||
void (*playback_start)(uint64_t next_pkt, struct timespec *ts);
|
||||
void (*playback_stop)(void);
|
||||
|
||||
// Write stream data to the output devices
|
||||
void (*write)(uint8_t *buf, uint64_t rtptime);
|
||||
void (*write2)(struct output_buffer *buffer);
|
||||
void (*write)(struct output_buffer *buffer);
|
||||
|
||||
// Flush all sessions, the return must be number of sessions pending the flush
|
||||
int (*flush)(output_status_cb cb, uint64_t rtptime);
|
||||
int (*flush2)(output_status_cb cb);
|
||||
int (*flush)(output_status_cb cb);
|
||||
|
||||
// Authorize an output with a pin-code (probably coming from the filescanner)
|
||||
void (*authorize)(const char *pin);
|
||||
|
||||
// Change the call back associated with a session
|
||||
void (*status_cb)(struct output_session *session, output_status_cb cb);
|
||||
|
||||
// Metadata
|
||||
void *(*metadata_prepare)(int id);
|
||||
void (*metadata_send)(void *metadata, uint64_t rtptime, uint64_t offset, int startup);
|
||||
@ -249,13 +239,10 @@ struct output_definition
|
||||
};
|
||||
|
||||
int
|
||||
outputs_device_start(struct output_device *device, output_status_cb cb, uint64_t rtptime);
|
||||
outputs_device_start(struct output_device *device, output_status_cb cb);
|
||||
|
||||
int
|
||||
outputs_device_start2(struct output_device *device, output_status_cb cb);
|
||||
|
||||
void
|
||||
outputs_device_stop(struct output_session *session);
|
||||
outputs_device_stop(struct output_device *device, output_status_cb cb);
|
||||
|
||||
int
|
||||
outputs_device_probe(struct output_device *device, output_status_cb cb);
|
||||
@ -273,23 +260,17 @@ outputs_device_volume_to_pct(struct output_device *device, const char *value);
|
||||
int
|
||||
outputs_device_quality_set(struct output_device *device, struct media_quality *quality);
|
||||
|
||||
void
|
||||
outputs_device_set_cb(struct output_device *device, output_status_cb cb);
|
||||
|
||||
void
|
||||
outputs_playback_stop(void);
|
||||
|
||||
void
|
||||
outputs_write(uint8_t *buf, uint64_t rtptime);
|
||||
|
||||
void
|
||||
outputs_write2(void *buf, size_t bufsize, struct media_quality *quality, int nsamples, struct timespec *pts);
|
||||
outputs_write(void *buf, size_t bufsize, struct media_quality *quality, int nsamples, struct timespec *pts);
|
||||
|
||||
int
|
||||
outputs_flush(output_status_cb cb, uint64_t rtptime);
|
||||
|
||||
int
|
||||
outputs_flush2(output_status_cb cb);
|
||||
|
||||
void
|
||||
outputs_status_cb(struct output_session *session, output_status_cb cb);
|
||||
outputs_flush(output_status_cb cb);
|
||||
|
||||
struct output_metadata *
|
||||
outputs_metadata_prepare(int id);
|
||||
|
Loading…
Reference in New Issue
Block a user