Make the player able to stream from pipes

This commit is contained in:
ejurgensen 2014-03-31 13:10:18 +02:00
parent 9efc97d702
commit 6062ca014b
5 changed files with 180 additions and 11 deletions

View File

@ -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
View 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
View 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__ */

View File

@ -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;
}

View File

@ -35,7 +35,8 @@ enum repeat_mode {
enum source_type {
SOURCE_FFMPEG = 0,
SOURCE_SPOTIFY = 1,
SOURCE_SPOTIFY,
SOURCE_PIPE,
};
struct spk_flags {