mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-25 14:45:55 -05:00
Make the player able to stream from pipes
This commit is contained in:
parent
9efc97d702
commit
6062ca014b
@ -94,6 +94,7 @@ forked_daapd_SOURCES = main.c \
|
||||
httpd_dacp.c httpd_dacp.h \
|
||||
dmap_common.c dmap_common.h \
|
||||
transcode.c transcode.h \
|
||||
pipe.c pipe.h \
|
||||
artwork.c artwork.h \
|
||||
misc.c misc.h \
|
||||
rng.c rng.h \
|
||||
|
126
src/pipe.c
Normal file
126
src/pipe.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "pipe.h"
|
||||
#include "logger.h"
|
||||
|
||||
#define PIPE_BUFFER_SIZE 8192
|
||||
|
||||
static int g_fd = -1;
|
||||
static void *g_buf = NULL;
|
||||
|
||||
int
|
||||
pipe_setup(struct media_file_info *mfi)
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
if (!mfi->path)
|
||||
{
|
||||
DPRINTF(E_LOG, L_PLAYER, "Path to pipe is NULL\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
DPRINTF(E_DBG, L_PLAYER, "Setting up pipe: %s\n", mfi->path);
|
||||
|
||||
if (lstat(mfi->path, &sb) < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_PLAYER, "Could not lstat() '%s': %s\n", mfi->path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!S_ISFIFO(sb.st_mode))
|
||||
{
|
||||
DPRINTF(E_LOG, L_PLAYER, "Source type is pipe, but path is not a fifo: %s\n", mfi->path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_fd = open(mfi->path, O_RDONLY);
|
||||
if (g_fd < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_PLAYER, "Could not open pipe for reading '%s': %s\n", mfi->path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_buf = (void *)malloc(PIPE_BUFFER_SIZE);
|
||||
if (!g_buf)
|
||||
{
|
||||
DPRINTF(E_LOG, L_PLAYER, "Out of memory for buffer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
pipe_cleanup(void)
|
||||
{
|
||||
if (g_fd >= 0)
|
||||
close(g_fd);
|
||||
g_fd = -1;
|
||||
|
||||
if (g_buf)
|
||||
free(g_buf);
|
||||
g_buf = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
pipe_audio_get(struct evbuffer *evbuf, int wanted)
|
||||
{
|
||||
int got;
|
||||
|
||||
if (wanted > PIPE_BUFFER_SIZE)
|
||||
wanted = PIPE_BUFFER_SIZE;
|
||||
|
||||
got = read(g_fd, g_buf, wanted);
|
||||
|
||||
if (got < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_PLAYER, "Could not read from pipe: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If the other end of the pipe is not writing we just return silence
|
||||
if (got == 0)
|
||||
{
|
||||
memset(g_buf, 0, wanted);
|
||||
got = wanted;
|
||||
}
|
||||
|
||||
evbuffer_add(evbuf, g_buf, got);
|
||||
|
||||
return got;
|
||||
}
|
||||
|
17
src/pipe.h
Normal file
17
src/pipe.h
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
#ifndef __PIPE_H__
|
||||
#define __PIPE_H__
|
||||
|
||||
#include "db.h"
|
||||
#include <event.h>
|
||||
|
||||
int
|
||||
pipe_setup(struct media_file_info *mfi);
|
||||
|
||||
void
|
||||
pipe_cleanup(void);
|
||||
|
||||
int
|
||||
pipe_audio_get(struct evbuffer *evbuf, int wanted);
|
||||
|
||||
#endif /* !__PIPE_H__ */
|
44
src/player.c
44
src/player.c
@ -54,11 +54,13 @@
|
||||
#include "conffile.h"
|
||||
#include "misc.h"
|
||||
#include "rng.h"
|
||||
#include "transcode.h"
|
||||
#include "player.h"
|
||||
#include "raop.h"
|
||||
#include "laudio.h"
|
||||
|
||||
/* These handle getting the media data */
|
||||
#include "transcode.h"
|
||||
#include "pipe.h"
|
||||
#ifdef HAVE_SPOTIFY_H
|
||||
# include "spotify.h"
|
||||
#endif
|
||||
@ -921,6 +923,10 @@ source_free(struct player_source *ps)
|
||||
spotify_playback_stop();
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SOURCE_PIPE:
|
||||
pipe_cleanup();
|
||||
break;
|
||||
}
|
||||
|
||||
free(ps);
|
||||
@ -948,6 +954,10 @@ source_stop(struct player_source *ps)
|
||||
spotify_playback_stop();
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SOURCE_PIPE:
|
||||
pipe_cleanup();
|
||||
break;
|
||||
}
|
||||
|
||||
tmp = ps;
|
||||
@ -1064,19 +1074,26 @@ source_open(struct player_source *ps, int no_md)
|
||||
|
||||
DPRINTF(E_INFO, L_PLAYER, "Opening '%s' (%s)\n", mfi->title, mfi->path);
|
||||
|
||||
if (strncmp(mfi->path, "spotify:", strlen("spotify:")) == 0)
|
||||
// Setup the source type responsible for getting the audio
|
||||
switch (mfi->data_kind)
|
||||
{
|
||||
ps->type = SOURCE_SPOTIFY;
|
||||
case 2:
|
||||
ps->type = SOURCE_SPOTIFY;
|
||||
#ifdef HAVE_SPOTIFY_H
|
||||
ret = spotify_playback_play(mfi);
|
||||
ret = spotify_playback_play(mfi);
|
||||
#else
|
||||
ret = -1;
|
||||
ret = -1;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
ps->type = SOURCE_FFMPEG;
|
||||
ret = transcode_setup(&ps->ctx, mfi, NULL, 0);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
ps->type = SOURCE_PIPE;
|
||||
ret = pipe_setup(mfi);
|
||||
break;
|
||||
|
||||
default:
|
||||
ps->type = SOURCE_FFMPEG;
|
||||
ret = transcode_setup(&ps->ctx, mfi, NULL, 0);
|
||||
}
|
||||
|
||||
free_mfi(mfi, 0);
|
||||
@ -1455,6 +1472,10 @@ source_read(uint8_t *buf, int len, uint64_t rtptime)
|
||||
break;
|
||||
#endif
|
||||
|
||||
case SOURCE_PIPE:
|
||||
ret = pipe_audio_get(audio_buf, len - nbytes);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
@ -2652,6 +2673,9 @@ playback_seek_bh(struct player_command *cmd)
|
||||
ret = spotify_playback_seek(ms);
|
||||
break;
|
||||
#endif
|
||||
case SOURCE_PIPE:
|
||||
ret = 1;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
|
@ -35,7 +35,8 @@ enum repeat_mode {
|
||||
|
||||
enum source_type {
|
||||
SOURCE_FFMPEG = 0,
|
||||
SOURCE_SPOTIFY = 1,
|
||||
SOURCE_SPOTIFY,
|
||||
SOURCE_PIPE,
|
||||
};
|
||||
|
||||
struct spk_flags {
|
||||
|
Loading…
Reference in New Issue
Block a user