Fix folder structure
This commit is contained in:
+344
@@ -0,0 +1,344 @@
|
||||
|
||||
#define LOG_MODULE LOG_PLAYER_MODULE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/thread.h>
|
||||
#include <sys/timer.h>
|
||||
#include <sys/version.h>
|
||||
#include <dev/irqreg.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/route.h>
|
||||
#include <pro/dhcp.h>
|
||||
#include <pro/sntp.h>
|
||||
|
||||
#include <sys/confnet.h>
|
||||
|
||||
#include <dev/board.h>
|
||||
#include <pro/httpd.h>
|
||||
#include <pro/asp.h>
|
||||
#include <pro/discover.h>
|
||||
#include <dev/nicrtl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include "player.h"
|
||||
#include "vs10xx.h"
|
||||
#include "streamer.h"
|
||||
#include "settings.h"
|
||||
#include <sys/bankmem.h>
|
||||
|
||||
#define OK 1
|
||||
#define NOK 0
|
||||
|
||||
int stopped = 1;
|
||||
int stopstream = 0;
|
||||
|
||||
char* MetaData;
|
||||
|
||||
int initPlayer(void)
|
||||
{
|
||||
MetaData = (char *) calloc(128, sizeof(char));
|
||||
|
||||
SetBass(GetBass());
|
||||
SetTreble(GetTreble());
|
||||
SetVolume(GetVolume());
|
||||
return OK;
|
||||
}
|
||||
|
||||
char* GetMetaData(void)
|
||||
{
|
||||
return MetaData;
|
||||
}
|
||||
|
||||
int isStreaming()
|
||||
{
|
||||
return !stopped;
|
||||
}
|
||||
|
||||
int ProcessMetaData(FILE *stream)
|
||||
{
|
||||
u_char blks = 0;
|
||||
u_short cnt;
|
||||
int got;
|
||||
int rc = 0;
|
||||
u_char *mbuf;
|
||||
|
||||
/*
|
||||
* Wait for the lenght byte.
|
||||
*/
|
||||
got = fread(&blks, 1, 1, stream);
|
||||
if(got != 1) {
|
||||
return -1;
|
||||
}
|
||||
if (blks) {
|
||||
if (blks > 32) {
|
||||
printf("[PLAYER] Error: Metadata too large, %u blocks\n", blks);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cnt = blks * 16;
|
||||
if ((mbuf = malloc(cnt + 1)) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive the metadata block.
|
||||
*/
|
||||
for (;;) {
|
||||
if ((got = fread(mbuf + rc, 1, cnt, stream)) <= 0) {
|
||||
return -1;
|
||||
}
|
||||
if ((cnt -= got) == 0) {
|
||||
break;
|
||||
}
|
||||
rc += got;
|
||||
mbuf[rc] = 0;
|
||||
}
|
||||
|
||||
memset(&MetaData[0], 0, sizeof(MetaData));
|
||||
|
||||
int count = 0;
|
||||
int copy = 0;
|
||||
|
||||
int startval = 0;
|
||||
int stopval = 0;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
|
||||
if(mbuf[count] == '\'' && copy == 1)
|
||||
{
|
||||
copy = 0;
|
||||
stopval = count-1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(mbuf[count] == '\'' && copy == 0)
|
||||
{
|
||||
startval = count+1;
|
||||
copy = 1;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
int len = stopval - startval;
|
||||
len = len > 127 ? 127 : len;
|
||||
|
||||
strncpy(MetaData, (char*) &mbuf[startval], len);
|
||||
|
||||
free(mbuf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stop(void)
|
||||
{
|
||||
if(stopped == 1)
|
||||
return 0;
|
||||
|
||||
printf("[PLAYER] Stopping other stream\n");
|
||||
|
||||
stopstream = 1;
|
||||
|
||||
while(!stopped) { NutSleep(5); };
|
||||
printf("[PLAYER] Stream stopped\n");
|
||||
|
||||
//Give thread time to clean up
|
||||
NutSleep(100);
|
||||
|
||||
strcpy(MetaData, "");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int play(u_long ip, u_short port, u_char *path)
|
||||
{
|
||||
stop(); //Stop any old threads
|
||||
|
||||
FILE *stream;
|
||||
TCPSOCKET *sock = 0;
|
||||
u_long metaint;
|
||||
|
||||
stream = ConnectStation(sock, ip, port, path, &metaint); //Connect to a stream
|
||||
|
||||
if(!stream)
|
||||
{
|
||||
printf("[PLAYER] Not stream\n");
|
||||
return NOK;
|
||||
}
|
||||
|
||||
//Package 3 variables in a struct to pass them to the thread.
|
||||
StreamData *arguments = malloc(sizeof(StreamData));
|
||||
arguments->stream = stream;
|
||||
arguments->sock = sock;
|
||||
arguments->metaint = metaint;
|
||||
|
||||
//Start thread with packaged arguments
|
||||
NutThreadCreate("Streamer", StreamPlayer, arguments, 512);
|
||||
|
||||
//Await thread start
|
||||
NutSleep(20);
|
||||
|
||||
//Clear the packege
|
||||
free(arguments);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
THREAD(StreamPlayer, arg)
|
||||
{
|
||||
|
||||
NutThreadSetPriority(1); // high prio
|
||||
|
||||
printf("[PLAYER] Play thread created. Device is playing stream now !\n");
|
||||
|
||||
StreamData* f = (StreamData *) arg;
|
||||
|
||||
FILE* stream = f->stream;
|
||||
TCPSOCKET* sock = f->sock;
|
||||
u_long metaint = f->metaint;
|
||||
|
||||
size_t rbytes;
|
||||
u_char *mp3buf;
|
||||
u_char ief;
|
||||
int got = 0;
|
||||
u_long last;
|
||||
u_long mp3left = metaint;
|
||||
int endstream = 0;
|
||||
|
||||
/*
|
||||
* Initialize the MP3 buffer. The NutSegBuf routines provide a global
|
||||
* system buffer, which works with banked and non-banked systems.
|
||||
*/
|
||||
if (NutSegBufInit(8192) == 0) {
|
||||
printf("[PLAYER] Error: MP3 buffer init failed\n");
|
||||
NutThreadExit();
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the MP3 decoder hardware.
|
||||
*/
|
||||
if (VsPlayerReset(0)) {
|
||||
printf("[PLAYER] Error: MP3 hardware init failed\n");
|
||||
NutThreadExit();
|
||||
}
|
||||
|
||||
stopped = 0;
|
||||
|
||||
/*
|
||||
* Reset the MP3 buffer.
|
||||
*/
|
||||
ief = VsPlayerInterrupts(0);
|
||||
NutSegBufReset();
|
||||
VsPlayerInterrupts(ief);
|
||||
last = NutGetSeconds();
|
||||
|
||||
for (;;) {
|
||||
|
||||
if(stopstream)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Query number of byte available in MP3 buffer.
|
||||
*/
|
||||
ief = VsPlayerInterrupts(0);
|
||||
mp3buf = (u_char*) NutSegBufWriteRequest(&rbytes);
|
||||
VsPlayerInterrupts(ief);
|
||||
|
||||
/*
|
||||
* If the player is not running, kick it.
|
||||
*/
|
||||
if (VsGetStatus() != VS_STATUS_RUNNING) {
|
||||
printf("[PLAYER] Not running\n");
|
||||
if(rbytes < 1024 || NutGetSeconds() - last > 4UL) {
|
||||
last = NutGetSeconds();
|
||||
printf("[PLAYER] Kick player\n");
|
||||
VsPlayerKick();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Do not read pass metadata.
|
||||
*/
|
||||
if (metaint && rbytes > mp3left) {
|
||||
rbytes = mp3left;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read data directly into the MP3 buffer.
|
||||
*/
|
||||
while (rbytes) {
|
||||
|
||||
if ((got = fread(mp3buf, 1, rbytes, stream)) > 0) {
|
||||
ief = VsPlayerInterrupts(0);
|
||||
mp3buf = (u_char *) NutSegBufWriteCommit(got);
|
||||
VsPlayerInterrupts(ief);
|
||||
|
||||
if (metaint) {
|
||||
mp3left -= got;
|
||||
if (mp3left == 0) {
|
||||
ProcessMetaData(stream);
|
||||
mp3left = metaint;
|
||||
}
|
||||
}
|
||||
|
||||
if(got < rbytes && got < 512) {
|
||||
//printf("%lu buffered\n", NutSegBufUsed());
|
||||
NutSleep(250);
|
||||
}
|
||||
else {
|
||||
NutThreadYield();
|
||||
}
|
||||
} else {
|
||||
printf("[PLAYER] Failed to read from stream, closing\n");
|
||||
break;
|
||||
}
|
||||
rbytes -= got;
|
||||
}
|
||||
|
||||
if(got <= 0) {
|
||||
endstream++;
|
||||
|
||||
printf("[PLAYER] Stream ending, %d tries left\n", 3 - endstream);
|
||||
|
||||
if(endstream >= 3)
|
||||
{
|
||||
printf("[PLAYER] End of stream, closing\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
endstream = 0;
|
||||
}
|
||||
|
||||
VsPlayerStop(); //Stop the audio
|
||||
|
||||
while (VsGetStatus() == VS_STATUS_RUNNING) {
|
||||
NutSleep(50); //Wait until player has really stopped
|
||||
}
|
||||
|
||||
fclose(stream); //Close stream
|
||||
NutTcpCloseSocket(sock); //Close socket
|
||||
|
||||
strcpy(MetaData, ""); //Clear meta data
|
||||
|
||||
stopstream = 0; //Clear stop flag
|
||||
stopped = 1; //Mark thread as stopped
|
||||
|
||||
printf("[PLAYER] End of play thread\n");
|
||||
|
||||
NutThreadExit(); //Clean up thread and exit
|
||||
|
||||
for(;;)
|
||||
{
|
||||
printf("[PLAYER] PLAY THREAD NOT STOPPED\n");
|
||||
NutThreadYield();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef PLAYER_INC
|
||||
#define PLAYER_INC
|
||||
|
||||
#include <sys/nutconfig.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
//#include <stdlib.h>
|
||||
//#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <io.h>
|
||||
|
||||
//Struct to package arguments to array
|
||||
typedef struct
|
||||
{
|
||||
FILE* stream;
|
||||
TCPSOCKET* sock;
|
||||
u_long metaint;
|
||||
} StreamData;
|
||||
|
||||
THREAD(StreamPlayer, arg);
|
||||
|
||||
extern int initPlayer(void);
|
||||
extern char * GetMetaData(void);
|
||||
extern int play(u_long ip, u_short port, u_char *path);
|
||||
extern int stop(void);
|
||||
extern int isStreaming(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,98 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <io.h>
|
||||
|
||||
#include <dev/debug.h>
|
||||
#include <dev/nicrtl.h>
|
||||
#include <dev/vs1001k.h>
|
||||
|
||||
#include <sys/version.h>
|
||||
#include <sys/confnet.h>
|
||||
#include <sys/heap.h>
|
||||
#include <sys/bankmem.h>
|
||||
#include <sys/thread.h>
|
||||
#include <sys/timer.h>
|
||||
|
||||
#include <dev/board.h>
|
||||
#include <pro/httpd.h>
|
||||
#include <pro/dhcp.h>
|
||||
#include <pro/asp.h>
|
||||
#include <pro/discover.h>
|
||||
#include <dev/nicrtl.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <pro/dhcp.h>
|
||||
|
||||
#include "streamer.h"
|
||||
#include "player.h"
|
||||
#include "web.h"
|
||||
|
||||
#define OK 1
|
||||
#define NOK 0
|
||||
/*!
|
||||
* \brief Connect to a radio station.
|
||||
*
|
||||
* \param sock TCP socket for this connection.
|
||||
* \param ip IP address of the server to connect.
|
||||
* \param port Port number of the server to connect.
|
||||
*
|
||||
* \return Stream pointer of the established connection on success.
|
||||
* Otherwise 0 is returned.
|
||||
*/
|
||||
FILE *ConnectStation(TCPSOCKET *sock, u_long ip, u_short port, u_char *path, u_long *metaint){
|
||||
FILE *stream;
|
||||
u_char *line;
|
||||
u_char *cp;
|
||||
|
||||
stream = getStream(sock, ip,port);
|
||||
|
||||
/*
|
||||
* Send the HTTP request.
|
||||
*/
|
||||
printf("[STREAMER] GET %s HTTP/1.0\n\n", path);
|
||||
fprintf(stream, "GET %s HTTP/1.0\r\n", path);
|
||||
fprintf(stream, "Host: %s\r\n", inet_ntoa(ip));
|
||||
fprintf(stream, "User-Agent: Ethernut\r\n");
|
||||
fprintf(stream, "Accept: */*\r\n");
|
||||
fprintf(stream, "Icy-MetaData: 1\r\n");
|
||||
fprintf(stream, "Connection: close\r\n");
|
||||
fputs("\r\n", stream);
|
||||
fflush(stream);
|
||||
|
||||
/*
|
||||
* Receive the HTTP header.
|
||||
*/
|
||||
line = malloc(MAX_HEADERLINE);
|
||||
while(fgets((char*) line, MAX_HEADERLINE, stream)) {
|
||||
|
||||
/*
|
||||
* Chop off the carriage return at the end of the line. If none
|
||||
* was found, then this line was probably too large for our buffer.
|
||||
*/
|
||||
cp = (u_char *) strchr((char*) line, '\r');
|
||||
if(cp == 0) {
|
||||
printf("[STREAMER] Warning: Input buffer overflow\n");
|
||||
continue;
|
||||
}
|
||||
*cp = 0;
|
||||
|
||||
/*
|
||||
* The header is terminated by an empty line.
|
||||
*/
|
||||
if(*line == 0) {
|
||||
break;
|
||||
}
|
||||
if(strncmp((char*) line, "icy-metaint:", 12) == 0) {
|
||||
*metaint = atol( (char*) (line + 12));
|
||||
}
|
||||
printf("[STREAMER] line of metaint: %s\n", line);
|
||||
}
|
||||
putchar('\n');
|
||||
|
||||
free(line);
|
||||
|
||||
return stream;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef STREAMER_INC
|
||||
#define STREAMER_INC
|
||||
|
||||
#define MAX_HEADERLINE 512
|
||||
|
||||
extern FILE *ConnectStation(TCPSOCKET *sock, u_long ip, u_short port, u_char *path, u_long *metaint);
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user