mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-27 23:55:57 -05:00
[outputs] Make a wrapper for mp3 streaming so it can be included in
the generic outputs interface and so special handling in player.c can be removed
This commit is contained in:
parent
a07c24d625
commit
36755031cb
@ -110,7 +110,7 @@ forked_daapd_SOURCES = main.c \
|
||||
outputs.h outputs.c \
|
||||
laudio_dummy.c \
|
||||
laudio.c laudio.h \
|
||||
outputs/raop.c \
|
||||
outputs/raop.c outputs/streaming.c \
|
||||
evrtsp/rtsp.c evrtp/evrtsp.h evrtsp/rtsp-internal.h evrtsp/log.h \
|
||||
$(SPOTIFY_SRC) \
|
||||
$(LASTFM_SRC) \
|
||||
|
@ -52,7 +52,7 @@ extern struct event_base *evbase_httpd;
|
||||
// Should prevent that we keep transcoding to dead connections
|
||||
#define STREAMING_CONNECTION_TIMEOUT 60
|
||||
|
||||
// Linked list of Icecast requests
|
||||
// Linked list of mp3 streaming requests
|
||||
struct streaming_session {
|
||||
struct evhttp_request *req;
|
||||
struct streaming_session *next;
|
||||
@ -108,7 +108,6 @@ streaming_fail_cb(struct evhttp_connection *evcon, void *arg)
|
||||
{
|
||||
DPRINTF(E_INFO, L_STREAMING, "No more clients, will stop streaming\n");
|
||||
event_del(streamingev);
|
||||
player_streaming_stop();
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,16 +121,16 @@ streaming_send_cb(evutil_socket_t fd, short event, void *arg)
|
||||
int len;
|
||||
int ret;
|
||||
|
||||
if (!streaming_sessions)
|
||||
return;
|
||||
|
||||
// Callback from player (EV_READ)
|
||||
// Player wrote data to the pipe (EV_READ)
|
||||
if (event & EV_READ)
|
||||
{
|
||||
ret = read(streaming_pipe[0], &streaming_rawbuf, STREAMING_RAWBUF_SIZE);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
if (!streaming_sessions)
|
||||
return;
|
||||
|
||||
decoded = transcode_raw2frame(streaming_rawbuf, STREAMING_RAWBUF_SIZE);
|
||||
if (!decoded)
|
||||
{
|
||||
@ -153,6 +152,9 @@ streaming_send_cb(evutil_socket_t fd, short event, void *arg)
|
||||
player_get_status(&streaming_player_status);
|
||||
}
|
||||
|
||||
if (!streaming_sessions)
|
||||
return;
|
||||
|
||||
if (streaming_player_status.status != PLAY_PAUSED)
|
||||
return;
|
||||
|
||||
@ -177,22 +179,6 @@ streaming_send_cb(evutil_socket_t fd, short event, void *arg)
|
||||
evbuffer_free(evbuf);
|
||||
}
|
||||
|
||||
// Thread: player
|
||||
static int
|
||||
streaming_cb(uint8_t *rawbuf, size_t size)
|
||||
{
|
||||
if (size != STREAMING_RAWBUF_SIZE)
|
||||
{
|
||||
DPRINTF(E_LOG, L_STREAMING, "Bug! Buffer size in streaming_cb does not equal input from player\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (write(streaming_pipe[1], rawbuf, size) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Thread: player (not fully thread safe, but hey...)
|
||||
static void
|
||||
player_change_cb(enum listener_event_type type)
|
||||
@ -200,6 +186,20 @@ player_change_cb(enum listener_event_type type)
|
||||
streaming_player_changed = 1;
|
||||
}
|
||||
|
||||
// Thread: player (also prone to race conditions, mostly during deinit)
|
||||
void
|
||||
streaming_write(uint8_t *buf, uint64_t rtptime)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!streaming_sessions)
|
||||
return;
|
||||
|
||||
ret = write(streaming_pipe[1], buf, STREAMING_RAWBUF_SIZE);
|
||||
if (ret < 0)
|
||||
DPRINTF(E_LOG, L_STREAMING, "Error writing to streaming pipe\n");
|
||||
}
|
||||
|
||||
int
|
||||
streaming_is_request(struct evhttp_request *req, char *uri)
|
||||
{
|
||||
@ -269,8 +269,6 @@ streaming_request(struct evhttp_request *req)
|
||||
evhttp_connection_set_timeout(evcon, STREAMING_CONNECTION_TIMEOUT);
|
||||
evhttp_connection_set_closecb(evcon, streaming_fail_cb, session);
|
||||
|
||||
player_streaming_start(streaming_cb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -403,18 +401,20 @@ streaming_deinit(void)
|
||||
if (!streaming_initialized)
|
||||
return;
|
||||
|
||||
player_streaming_stop();
|
||||
|
||||
event_free(streamingev);
|
||||
session = streaming_sessions;
|
||||
streaming_sessions = NULL; // Stops writing and sending
|
||||
|
||||
next = NULL;
|
||||
for (session = streaming_sessions; session; session = next)
|
||||
while (session)
|
||||
{
|
||||
evhttp_send_reply_end(session->req);
|
||||
next = session->next;
|
||||
free(session);
|
||||
session = next;
|
||||
}
|
||||
|
||||
event_free(streamingev);
|
||||
|
||||
listener_remove(player_change_cb);
|
||||
|
||||
close(streaming_pipe[0]);
|
||||
|
@ -10,6 +10,9 @@
|
||||
* if a suitable ffmpeg/libav encoder is not present at runtime.
|
||||
*/
|
||||
|
||||
void
|
||||
streaming_write(uint8_t *buf, uint64_t rtptime);
|
||||
|
||||
int
|
||||
streaming_is_request(struct evhttp_request *req, char *uri);
|
||||
|
||||
|
@ -35,8 +35,8 @@ extern struct output_definition output_raop;
|
||||
#ifdef CHROMECAST
|
||||
extern struct output_definition output_cast;
|
||||
#endif
|
||||
/* TODO
|
||||
extern struct output_definition output_streaming;
|
||||
/* TODO
|
||||
#ifdef ALSA
|
||||
extern struct output_definition output_alsa;
|
||||
#endif
|
||||
@ -52,8 +52,8 @@ static struct output_definition *outputs[] = {
|
||||
#ifdef CHROMECAST
|
||||
&output_cast,
|
||||
#endif
|
||||
/* TODO
|
||||
&output_streaming,
|
||||
/* TODO
|
||||
#ifdef ALSA
|
||||
&output_alsa,
|
||||
#endif
|
||||
@ -338,6 +338,9 @@ outputs_init(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!outputs[i]->init)
|
||||
continue;
|
||||
|
||||
ret = outputs[i]->init();
|
||||
if (ret < 0)
|
||||
outputs[i]->disabled = 1;
|
||||
@ -358,7 +361,10 @@ outputs_deinit(void)
|
||||
|
||||
for (i = 0; outputs[i]; i++)
|
||||
{
|
||||
if (!outputs[i]->disabled)
|
||||
if (outputs[i]->disabled)
|
||||
continue;
|
||||
|
||||
if (outputs[i]->deinit)
|
||||
outputs[i]->deinit();
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ enum output_types
|
||||
#ifdef CHROMECAST
|
||||
OUTPUT_TYPE_CAST,
|
||||
#endif
|
||||
/* TODO
|
||||
OUTPUT_TYPE_STREAMING,
|
||||
/* TODO
|
||||
OUTPUT_TYPE_ALSA,
|
||||
OUTPUT_TYPE_OSS,
|
||||
OUTPUT_TYPE_DUMMY,
|
||||
|
35
src/outputs/streaming.c
Normal file
35
src/outputs/streaming.c
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Espen Jürgensen <espenjurgensen@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "outputs.h"
|
||||
#include "httpd_streaming.h"
|
||||
|
||||
|
||||
struct output_definition output_streaming =
|
||||
{
|
||||
.name = "mp3 streaming",
|
||||
.type = OUTPUT_TYPE_STREAMING,
|
||||
.priority = 0,
|
||||
.disabled = 0,
|
||||
.write = streaming_write,
|
||||
};
|
28
src/player.c
28
src/player.c
@ -291,9 +291,6 @@ static int laudio_selected;
|
||||
static int laudio_volume;
|
||||
static int laudio_relvol;
|
||||
static int output_sessions;
|
||||
static int streaming_selected;
|
||||
|
||||
static player_streaming_cb streaming_write;
|
||||
|
||||
/* Commands */
|
||||
static struct player_command *cur_cmd;
|
||||
@ -1606,14 +1603,10 @@ playback_write(void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (streaming_selected)
|
||||
streaming_write(rawbuf, sizeof(rawbuf));
|
||||
|
||||
if (laudio_status & LAUDIO_F_STARTED)
|
||||
laudio_write(rawbuf, last_rtptime);
|
||||
|
||||
if (output_sessions > 0)
|
||||
outputs_write(rawbuf, last_rtptime);
|
||||
outputs_write(rawbuf, last_rtptime);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2170,8 +2163,7 @@ playback_abort(void)
|
||||
if (laudio_status != LAUDIO_CLOSED)
|
||||
laudio_close();
|
||||
|
||||
if (output_sessions > 0)
|
||||
outputs_playback_stop();
|
||||
outputs_playback_stop();
|
||||
|
||||
pb_timer_stop();
|
||||
|
||||
@ -2423,8 +2415,7 @@ playback_start_bh(struct player_command *cmd)
|
||||
goto out_fail;
|
||||
|
||||
/* Everything OK, start outputs */
|
||||
if (output_sessions > 0)
|
||||
outputs_playback_start(last_rtptime + AIRTUNES_V2_PACKET_SAMPLES, &pb_pos_stamp);
|
||||
outputs_playback_start(last_rtptime + AIRTUNES_V2_PACKET_SAMPLES, &pb_pos_stamp);
|
||||
|
||||
status_update(PLAY_PLAYING);
|
||||
|
||||
@ -4014,19 +4005,6 @@ player_playback_prev(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
player_streaming_start(player_streaming_cb cb)
|
||||
{
|
||||
streaming_write = cb;
|
||||
streaming_selected = 1;
|
||||
}
|
||||
|
||||
void
|
||||
player_streaming_stop(void)
|
||||
{
|
||||
streaming_selected = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
player_speaker_enumerate(spk_enum_cb cb, void *arg)
|
||||
|
@ -70,7 +70,6 @@ struct player_status {
|
||||
};
|
||||
|
||||
typedef void (*spk_enum_cb)(uint64_t id, const char *name, int relvol, struct spk_flags flags, void *arg);
|
||||
typedef int (*player_streaming_cb)(uint8_t *rawbuf, size_t size);
|
||||
|
||||
struct player_history
|
||||
{
|
||||
@ -131,12 +130,6 @@ player_playback_next(void);
|
||||
int
|
||||
player_playback_prev(void);
|
||||
|
||||
void
|
||||
player_streaming_start(player_streaming_cb cb);
|
||||
|
||||
void
|
||||
player_streaming_stop(void);
|
||||
|
||||
|
||||
int
|
||||
player_volume_set(int vol);
|
||||
|
Loading…
Reference in New Issue
Block a user