Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
254
Src/Plugins/DSP/dsp_sc/sc2srclib/Include/c_jobmanager.h
Normal file
254
Src/Plugins/DSP/dsp_sc/sc2srclib/Include/c_jobmanager.h
Normal file
|
@ -0,0 +1,254 @@
|
|||
#ifndef __C_JOBMANAGER_H__
|
||||
#define __C_JOBMANAGER_H__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <wtypes.h>
|
||||
#include <winbase.h> // for mutex support
|
||||
#define T_MUTEX HANDLE
|
||||
#else // _WIN32
|
||||
#error "This won't compile under anything other than windows since I haven't implemented mutexing on anything else"
|
||||
#endif // _WIN32
|
||||
|
||||
template<class T> class C_JOBMANAGER {
|
||||
public:
|
||||
typedef int (*T_JOBHANDLER)(int state, int last_state, T *userData);
|
||||
private:
|
||||
struct T_JOB {
|
||||
int state;
|
||||
int last_state;
|
||||
int suspended;
|
||||
T *userData;
|
||||
};
|
||||
struct T_HANDLER {
|
||||
int state;
|
||||
int last_state;
|
||||
T_JOBHANDLER jobHandler;
|
||||
};
|
||||
std::vector<T_JOB*> JobList;
|
||||
std::vector<T_HANDLER*> HandlerList;
|
||||
T_MUTEX mutex;
|
||||
|
||||
protected:
|
||||
int waitForMutex() {
|
||||
#ifdef _WIN32
|
||||
if(WaitForSingleObject(mutex,INFINITE) == WAIT_OBJECT_0) return 1;
|
||||
#else // _WIN32
|
||||
// insert mutex magic here
|
||||
#endif // _WIN32
|
||||
return 0;
|
||||
}
|
||||
|
||||
void releaseMutex() {
|
||||
#ifdef _WIN32
|
||||
ReleaseMutex(mutex);
|
||||
#else // _WIN32
|
||||
// insert mutex magic here
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
public:
|
||||
C_JOBMANAGER() {
|
||||
#ifdef _WIN32
|
||||
mutex = CreateMutex(NULL,TRUE,NULL);
|
||||
ReleaseMutex(mutex);
|
||||
#else // _WIN32
|
||||
// insert mutex magic here
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
virtual ~C_JOBMANAGER() {
|
||||
waitForMutex();
|
||||
#ifdef _WIN32
|
||||
CloseHandle(mutex);
|
||||
mutex = NULL;
|
||||
#else // _WIN32
|
||||
// insert mutex magic here
|
||||
#endif // _WIN32
|
||||
|
||||
//JobList.deleteAll();
|
||||
for (auto job : JobList)
|
||||
{
|
||||
delete job;
|
||||
}
|
||||
JobList.clear();
|
||||
|
||||
//HandlerList.deleteAll();
|
||||
for (auto handler : HandlerList)
|
||||
{
|
||||
delete handler;
|
||||
}
|
||||
HandlerList.clear();
|
||||
}
|
||||
|
||||
T *operator[](int job) {
|
||||
if(!waitForMutex()) return NULL;
|
||||
T_JOB *j = JobList[job];
|
||||
T *val = NULL;
|
||||
if(j) val = j->userData;
|
||||
releaseMutex();
|
||||
return val;
|
||||
}
|
||||
|
||||
virtual int AddJob(int state, T *userData, int suspended = 0, int isUserUnique = 1) {
|
||||
if(!waitForMutex()) return -1;
|
||||
int n = JobList.size();
|
||||
if(isUserUnique && n) {
|
||||
for(int i = n-1; i >= 0; i--) {
|
||||
T_JOB *item = JobList[i];
|
||||
if(item) {
|
||||
if(item->userData == userData) {
|
||||
releaseMutex();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
T_JOB *job = new T_JOB;
|
||||
job->last_state = OUT_DISCONNECTED;
|
||||
job->state = state;
|
||||
job->suspended = suspended;
|
||||
job->userData = userData;
|
||||
JobList.push_back(job);
|
||||
releaseMutex();
|
||||
return n;
|
||||
}
|
||||
|
||||
virtual int GetJobState(int job) {
|
||||
int retval = -1;
|
||||
if(waitForMutex()) {
|
||||
int n = JobList.size();
|
||||
if(job < n && job >= 0) retval = JobList[job]->state;
|
||||
releaseMutex();
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
virtual void SetJobState(int job, int state) {
|
||||
if(!waitForMutex()) return;
|
||||
int n = JobList.size();
|
||||
if(job < n && job >= 0) JobList[job]->state = state;
|
||||
releaseMutex();
|
||||
}
|
||||
|
||||
virtual void SuspendJob(int job, int suspended) {
|
||||
if(!waitForMutex()) return;
|
||||
int n = JobList.size();
|
||||
if(job < n && job >= 0) JobList[job]->suspended = suspended;
|
||||
releaseMutex();
|
||||
}
|
||||
|
||||
virtual void DelJob(int job) {
|
||||
if(!waitForMutex()) return;
|
||||
int n = JobList.size();
|
||||
if(job < n && job >= 0) {
|
||||
delete JobList[job];
|
||||
JobList.erase(JobList.begin() + job);
|
||||
}
|
||||
releaseMutex();
|
||||
}
|
||||
|
||||
virtual void ClearJobs() {
|
||||
if(!waitForMutex())
|
||||
return;
|
||||
|
||||
//JobList.deleteAll();
|
||||
for (auto job : JobList)
|
||||
{
|
||||
delete job;
|
||||
}
|
||||
JobList.clear();
|
||||
|
||||
releaseMutex();
|
||||
}
|
||||
|
||||
virtual void AddHandler(int state, T_JOBHANDLER jobHandler) {
|
||||
if(!waitForMutex()) return;
|
||||
int n = HandlerList.size();
|
||||
for(int i = n-1; i >= 0; i--) {
|
||||
T_HANDLER *item = HandlerList[i];
|
||||
if(item) {
|
||||
if(item->state == state) {
|
||||
releaseMutex();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
T_HANDLER *handler = new T_HANDLER;
|
||||
handler->state = state;
|
||||
handler->jobHandler = jobHandler;
|
||||
HandlerList.push_back(handler);
|
||||
releaseMutex();
|
||||
}
|
||||
|
||||
virtual void DelHandler(int state) {
|
||||
if(!waitForMutex()) return;
|
||||
int n = HandlerList.size();
|
||||
for(int i = n-1; i >= 0; i--) {
|
||||
T_HANDLER *item = HandlerList[i];
|
||||
if(item) {
|
||||
if(item->state == state) {
|
||||
delete HandlerList[i];
|
||||
HandlerList.erase(HandlerList.begin() + i);
|
||||
releaseMutex();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
releaseMutex();
|
||||
}
|
||||
|
||||
virtual void ClearHandlers() {
|
||||
if(!waitForMutex())
|
||||
return;
|
||||
|
||||
//HandlerList.deleteAll();
|
||||
for (auto handler : HandlerList)
|
||||
{
|
||||
delete handler;
|
||||
}
|
||||
HandlerList.clear();
|
||||
|
||||
releaseMutex();
|
||||
}
|
||||
|
||||
virtual int GetNumJobs() {
|
||||
if(!waitForMutex()) return -1;
|
||||
int n = JobList.size();
|
||||
releaseMutex();
|
||||
return n;
|
||||
}
|
||||
|
||||
virtual int GetNumHandlers() {
|
||||
if(!waitForMutex()) return -1;
|
||||
int n = HandlerList.size();
|
||||
releaseMutex();
|
||||
return n;
|
||||
}
|
||||
|
||||
virtual void Run(int job) {
|
||||
if(!waitForMutex()) return;
|
||||
int nJ = JobList.size();
|
||||
int nH = HandlerList.size();
|
||||
if(job < nJ && job >= 0) {
|
||||
T_JOB *job_item = JobList[job];
|
||||
for(int i = nH-1; i >= 0; i--) {
|
||||
T_HANDLER *handler = HandlerList[i];
|
||||
if(handler) {
|
||||
if(handler->state == job_item->state) {
|
||||
if(!job_item->suspended) {
|
||||
int cur_state = job_item->state;
|
||||
job_item->state = handler->jobHandler(job_item->state,job_item->last_state,job_item->userData);
|
||||
job_item->last_state = cur_state;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
releaseMutex();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // !__C_JOBMANAGER_H__
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef __C_SERIAL_JOBMANAGER_H__
|
||||
#define __C_SERIAL_JOBMANAGER_H__
|
||||
|
||||
#include "c_jobmanager.h"
|
||||
|
||||
template<class T> class C_SERIAL_JOBMANAGER : public C_JOBMANAGER<T> {
|
||||
private:
|
||||
int currentJob;
|
||||
public:
|
||||
C_SERIAL_JOBMANAGER() {
|
||||
currentJob = 0;
|
||||
}
|
||||
~C_SERIAL_JOBMANAGER() { }
|
||||
int GetCurrentJob() { return currentJob; }
|
||||
virtual void Run(int passes = 1) {
|
||||
int numPasses = passes;
|
||||
while(numPasses-- > 0) {
|
||||
C_JOBMANAGER<T>::Run(currentJob++);
|
||||
if(currentJob > GetNumJobs()) currentJob = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // !__C_SERIAL_JOBMANAGER_H__
|
194
Src/Plugins/DSP/dsp_sc/sc2srclib/Include/c_shoutcast_2_output.h
Normal file
194
Src/Plugins/DSP/dsp_sc/sc2srclib/Include/c_shoutcast_2_output.h
Normal file
|
@ -0,0 +1,194 @@
|
|||
#ifndef __C_SHOUTCAST_2_OUTPUT_H__
|
||||
#define __C_SHOUTCAST_2_OUTPUT_H__
|
||||
|
||||
#include <time.h>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "c_serial_jobmanager.h"
|
||||
#include "../jnetlib/jnetlib.h"
|
||||
#include "../Encoders/c_encoder.h"
|
||||
#include "../Encoders/c_encoder_mp3dll.h"
|
||||
|
||||
#include "../lame/include/lame.h"
|
||||
#include "../lame/libmp3lame/lame_global_flags.h"
|
||||
#include "../uvAuth21/uvAuth21.h"
|
||||
|
||||
#ifdef USEAACP
|
||||
#include "../Encoders/c_encoder_aacp.h"
|
||||
#endif
|
||||
struct T_OUTPUT_CONFIG {
|
||||
char Name[32];
|
||||
char UserID[256];
|
||||
char Address[1024];
|
||||
u_short Port;
|
||||
char StationID[8];
|
||||
char Password[256]; // 4 - 8 for 1.8.2
|
||||
char cipherkey[32];// sc2 cipherkey
|
||||
int AutoRecon;
|
||||
int ReconTime;
|
||||
char Description[1024];
|
||||
char ServerURL[2048];
|
||||
int Genre1;
|
||||
int Genre2;
|
||||
char Genre3[1024];
|
||||
char ICQ[128];
|
||||
char AIM[512];
|
||||
char IRC[512];
|
||||
char content_type[11];
|
||||
int Public;
|
||||
int doTitleUpdate;
|
||||
int protocol;
|
||||
int DoUpload;
|
||||
char introfilepath[4096];
|
||||
char backupfile[4096];
|
||||
};
|
||||
|
||||
#define DEFAULT_ENCODER (C_ENCODER *)(-1)
|
||||
|
||||
#define OM_ENCODE 1
|
||||
#define OM_OUTPUT 2
|
||||
#define OM_OTHER 4
|
||||
#define OM_ALL (OM_ENCODE | OM_OUTPUT | OM_OTHER)
|
||||
|
||||
enum OUTPUTTYPE {
|
||||
OUTTYPE_SOURCE,
|
||||
OUTTYPE_TITLE,
|
||||
};
|
||||
|
||||
struct T_OUTPUT_INFO {
|
||||
unsigned int BytesSent; // how many bytes of content we've sent
|
||||
clock_t ConnectionTime; // time a socket connection occurred
|
||||
int Version; // server version
|
||||
int Caps; // server capabilities
|
||||
int Reconnect; // flag for the reconnection algorithm
|
||||
int ReconnectTime; // value used in conjunction with the reconnection algorithm
|
||||
int Succeeded; // had at least one successful connection (for reconnection alg.) -1 = password failure
|
||||
int sc2Suceeded;//sc2 version
|
||||
char ErrorMsg[1024];
|
||||
time_t ConnectedAt;
|
||||
wchar_t Title[1024];
|
||||
wchar_t Next[1024];
|
||||
char URL[1024];
|
||||
int introuploaded;
|
||||
int backupuploaded;
|
||||
};
|
||||
|
||||
struct T_OUTPUT {
|
||||
JNL_Connection Output;
|
||||
enum OUTPUTTYPE Type;
|
||||
int Bitrate; // this shouldn't be here, but it's the only way we can tell the shoutcast server the bitrate
|
||||
char * ContentType; //neither should this
|
||||
int SlowClose; // set to 1 to wait until all data is sent before closing the connection
|
||||
T_OUTPUT_CONFIG *Config;
|
||||
T_OUTPUT_INFO Info;
|
||||
int m_sendmetadata;
|
||||
int m_initdone;
|
||||
};
|
||||
|
||||
enum OUTPUTSTATE {
|
||||
OUT_ERROR, // not a true state, but is returned when GetState() is called with an invalid connection handle
|
||||
OUT_IDLE,
|
||||
OUT_CONNECT,
|
||||
OUT_REQUEST_CIPHER,
|
||||
OUT_RECV_CIPHER,
|
||||
OUT_SENDAUTH,
|
||||
OUT_RECVAUTHRESPONSE,
|
||||
OUT_SEND_MIME,
|
||||
OUT_RECV_MIME,
|
||||
OUT_SEND_BITRATE,
|
||||
OUT_RECV_BITRATE,
|
||||
OUT_SEND_BUFSIZE,
|
||||
OUT_RECV_BUFSIZE,
|
||||
OUT_SEND_MAX,
|
||||
OUT_RECV_MAX,
|
||||
OUT_SENDYP,
|
||||
OUT_RECVYP,
|
||||
OUT_SEND_INITFLUSH,
|
||||
OUT_RECV_INITFLUSH,
|
||||
OUT_SEND_INITSTANDBY,
|
||||
OUT_RECV_INITSTANDBY,
|
||||
OUT_SEND_INTRO,
|
||||
OUT_RECV_INTRO,
|
||||
OUT_SEND_BACKUP,
|
||||
OUT_RECV_BACKUP,
|
||||
OUT_SENDCONTENT,
|
||||
OUT_DISCONNECT,
|
||||
OUT_RECONNECT,
|
||||
OUT_TITLESENDUPDATE,
|
||||
};
|
||||
#define OUT_DISCONNECTED OUT_IDLE
|
||||
|
||||
class C_SHOUTCAST_2_OUTPUT {
|
||||
private:
|
||||
C_ENCODER *Encoder;
|
||||
int IOwnEncoder;
|
||||
C_SERIAL_JOBMANAGER<T_OUTPUT> OutputManager;
|
||||
HANDLE mutex;
|
||||
|
||||
protected:
|
||||
static int Output_Idle(int state, T_OUTPUT *userData);
|
||||
static int Output_Connect(int state, T_OUTPUT *userData);
|
||||
static int Output_Request_Cipher(int state, T_OUTPUT *userData);
|
||||
static int Output_Receive_Cipher(int state, T_OUTPUT *userData);
|
||||
static int Output_SendAuth(int state, T_OUTPUT *userData);
|
||||
static int Output_RecvAuthResponse(int state, T_OUTPUT *userData);
|
||||
static int Output_Send_Mime(int state, T_OUTPUT *userData);
|
||||
static int Output_Recv_Mime(int state, T_OUTPUT *userData);
|
||||
static int Output_Send_Bitrate(int state, T_OUTPUT *userData);
|
||||
static int Output_Recv_Bitrate(int state, T_OUTPUT *userData);
|
||||
static int Output_Send_Buf_Size(int state, T_OUTPUT *userData);
|
||||
static int Output_Recv_Buf_Size(int state, T_OUTPUT *userData);
|
||||
static int Output_Send_Max_Size(int state, T_OUTPUT *userData);
|
||||
static int Output_Recv_Max_Size(int state, T_OUTPUT *userData);
|
||||
static int Output_DUMMY(int state, T_OUTPUT *userData);
|
||||
static int Output_SendYP(int state, T_OUTPUT *userData);
|
||||
static int Output_RecvYP(int state, T_OUTPUT *userData);
|
||||
static int Output_Send_InitFlush(int state, T_OUTPUT *userData);
|
||||
static int Output_Recv_InitFlush(int state, T_OUTPUT *userData);
|
||||
static int Output_Send_InitStandby(int state, T_OUTPUT *userData);
|
||||
static int Output_Recv_InitStandby(int state, T_OUTPUT *userData);
|
||||
static int Output_Send_InitMeta(int state, T_OUTPUT *userData);
|
||||
static int Output_Recv_InitMeta(int state, T_OUTPUT *userData);
|
||||
static int Output_Send_Intro(int state, T_OUTPUT *userData);
|
||||
static int Output_Recv_Intro(int state, T_OUTPUT *userData);
|
||||
static int Output_Send_Backup(int state, T_OUTPUT *userData);
|
||||
static int Output_Recv_Backup(int state, T_OUTPUT *userData);
|
||||
|
||||
static int Output_SendContent(int state, T_OUTPUT *userData);
|
||||
static int Output_Disconnect(int state, T_OUTPUT *userData);
|
||||
static int Output_Reconnect(int state, T_OUTPUT *userData);
|
||||
static int Output_Title_SendUpdate(int state, T_OUTPUT *userData);
|
||||
static int Output_Title_SendUpdatev2(int state, T_OUTPUT *userData);
|
||||
// uvox21
|
||||
static char * createUvoxFrameClasstype(std::string typeString);
|
||||
static int createUvoxFrame(int length, char * payload_in,char * payload_out, char * classtype);
|
||||
static int parseUvoxFrame(char * payload_in,char * payload_out);
|
||||
static int checkUvoxFrameForError(char * pload_out,int state, T_OUTPUT *userData);
|
||||
|
||||
void (*lame_init)(void);
|
||||
void (*lame_init_params)(lame_global_flags *);
|
||||
int (*lame_encode_buffer_interleaved)(lame_global_flags *,short int pcm[],int num_samples, char *mp3buffer,int mp3buffer_size);
|
||||
int (*lame_encode_flush)(lame_global_flags *,char *mp3buffer, int size);
|
||||
|
||||
public:
|
||||
C_SHOUTCAST_2_OUTPUT();
|
||||
void SetLame(void *init, void *params, void *encode, void *finish);
|
||||
~C_SHOUTCAST_2_OUTPUT();
|
||||
int Run(int mode = 0, void *Input = NULL, int InputSize = 0);
|
||||
int AddOutput(T_OUTPUT_CONFIG *Config);
|
||||
void UpdateOutput(int Connection);
|
||||
void RemoveOutput(int Connection);
|
||||
void ConnectOutput(int Connection);
|
||||
void DisconnectOutput(int Connection, int withReconnect = 0, int reconnectTime = -1); // withReconnect of -1 will use the output config's setting
|
||||
void SetEncoder(C_ENCODER *encoder, int takeOwnership = 0);
|
||||
void UpdateTitle(wchar_t*Title,wchar_t*Next, int Connection,int titleseq);
|
||||
enum OUTPUTSTATE GetState(int Connection);
|
||||
T_OUTPUT_CONFIG *operator[](int Connection);
|
||||
T_OUTPUT_CONFIG *GetOutput(int Connection);
|
||||
C_ENCODER *GetEncoder();
|
||||
T_OUTPUT_INFO *GetOutputInfo(int Connection);
|
||||
int m_titleseq;
|
||||
};
|
||||
|
||||
#endif // !__C_SHOUTCAST_2_OUTPUT_H__
|
817
Src/Plugins/DSP/dsp_sc/sc2srclib/Include/shoutcast_output.h
Normal file
817
Src/Plugins/DSP/dsp_sc/sc2srclib/Include/shoutcast_output.h
Normal file
|
@ -0,0 +1,817 @@
|
|||
#ifndef __SHOUTCAST_OUTPUT_H__
|
||||
#define __SHOUTCAST_OUTPUT_H__
|
||||
|
||||
#include <time.h>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <list>
|
||||
#include <fstream>
|
||||
#include "c_serial_jobmanager.h"
|
||||
#include "../Components/wac_network/wac_network_connection_api.h"
|
||||
#include <WinSock2.h>
|
||||
|
||||
#include "../Encoders/c_encoder.h"
|
||||
#include "../Encoders/c_encoder_mp3dll.h"
|
||||
|
||||
#include "../lame/include/lame.h"
|
||||
#include "../lame/libmp3lame/lame_global_flags.h"
|
||||
#include "../uvAuth21/uvAuth21.h"
|
||||
|
||||
#define UV_SYNC_BYTE 0x5A
|
||||
#define UV_RESERVED 0x00
|
||||
#define UV_END 0x00
|
||||
#define UV_END_LEN 1
|
||||
#define UV_HEADER_LEN 6
|
||||
#define UV_META_LEN 6
|
||||
#define UV_FRAME_LEN 16384
|
||||
#define UV_MAX_DATA_LEN (UV_FRAME_LEN - UV_HEADER_LEN - UV_END_LEN)
|
||||
#define UV_MAX_META_LEN (UV_FRAME_LEN - UV_HEADER_LEN - UV_META_LEN - UV_END_LEN)
|
||||
#define UV_MAX_META_FRAGMENTS 32
|
||||
#define UV_MAX_TOTAL_META_LEN (UV_MAX_META_LEN * UV_MAX_META_FRAGMENTS)
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
bool parent;
|
||||
bool children;
|
||||
} SCgenres;
|
||||
static SCgenres genres[] = {{"Alternative", true, true},
|
||||
{"Adult Alternative", false},
|
||||
{"Britpop", false},
|
||||
{"Classic Alternative", false},
|
||||
{"College", false},
|
||||
{"Dancepunk", false},
|
||||
{"Dream Pop", false},
|
||||
{"Emo", false},
|
||||
{"Goth", false},
|
||||
{"Grunge", false},
|
||||
{"Hardcore", false},
|
||||
{"Indie Pop", false},
|
||||
{"Indie Rock", false},
|
||||
{"Industrial", false},
|
||||
{"LoFi", false},
|
||||
{"Modern Rock", false},
|
||||
{"New Wave", false},
|
||||
{"Noise Pop", false},
|
||||
{"Post Punk", false},
|
||||
{"Power Pop", false},
|
||||
{"Punk", false},
|
||||
{"Ska", false},
|
||||
{"Xtreme", false},
|
||||
|
||||
{"Blues", true, true},
|
||||
{"Acoustic Blues", false},
|
||||
{"Cajun and Zydeco", false},
|
||||
{"Chicago Blues", false},
|
||||
{"Contemporary Blues", false},
|
||||
{"Country Blues", false},
|
||||
{"Delta Blues", false},
|
||||
{"Electric Blues", false},
|
||||
|
||||
{"Classical", true, true},
|
||||
{"Baroque", false},
|
||||
{"Chamber", false},
|
||||
{"Choral", false},
|
||||
{"Classical Period", false},
|
||||
{"Early Classical", false},
|
||||
{"Impressionist", false},
|
||||
{"Modern", false},
|
||||
{"Opera", false},
|
||||
{"Piano", false},
|
||||
{"Romantic", false},
|
||||
{"Symphony", false},
|
||||
|
||||
{"Country", true, true},
|
||||
{"Alt Country", false},
|
||||
{"Americana", false},
|
||||
{"Bluegrass", false},
|
||||
{"Classic Country", false},
|
||||
{"Contemporary Bluegrass", false},
|
||||
{"Contemporary Country", false},
|
||||
{"Honky Tonk", false},
|
||||
{"Hot Country Hits", false},
|
||||
{"Western", false},
|
||||
|
||||
{"Decades", true, true},
|
||||
{"30s", false},
|
||||
{"40s", false},
|
||||
{"50s", false},
|
||||
{"60s", false},
|
||||
{"70s", false},
|
||||
{"80s", false},
|
||||
{"90s", false},
|
||||
{"00s", false},
|
||||
|
||||
{"Easy Listening", true, true},
|
||||
{"Exotica", false},
|
||||
{"Light Rock", false},
|
||||
{"Lounge", false},
|
||||
{"Orchestral Pop", false},
|
||||
{"Polka", false},
|
||||
{"Space Age Pop", false},
|
||||
|
||||
{"Electronic", true, true},
|
||||
{"Acid House", false},
|
||||
{"Ambient", false},
|
||||
{"Big Beat", false},
|
||||
{"Breakbeat", false},
|
||||
{"Dance", false},
|
||||
{"Demo", false},
|
||||
{"Disco", false},
|
||||
{"Downtempo", false},
|
||||
{"Drum and Bass", false},
|
||||
{"Dubstep", false},
|
||||
{"Electro", false},
|
||||
{"Garage", false},
|
||||
{"Hard House", false},
|
||||
{"House", false},
|
||||
{"IDM", false},
|
||||
{"Jungle", false},
|
||||
{"Progressive", false},
|
||||
{"Techno", false},
|
||||
{"Trance", false},
|
||||
{"Tribal", false},
|
||||
{"Trip Hop", false},
|
||||
|
||||
{"Folk", true, true},
|
||||
{"Alternative Folk", false},
|
||||
{"Contemporary Folk", false},
|
||||
{"Folk Rock", false},
|
||||
{"New Acoustic", false},
|
||||
{"Old Time", false},
|
||||
{"Traditional Folk", false},
|
||||
{"World Folk", false},
|
||||
|
||||
{"Inspirational", true, true},
|
||||
{"Christian", false},
|
||||
{"Christian Metal", false},
|
||||
{"Christian Rap", false},
|
||||
{"Christian Rock", false},
|
||||
{"Classic Christian", false},
|
||||
{"Contemporary Gospel", false},
|
||||
{"Gospel", false},
|
||||
{"Praise and Worship", false},
|
||||
{"Sermons and Services", false},
|
||||
{"Southern Gospel", false},
|
||||
{"Traditional Gospel", false},
|
||||
|
||||
{"International", true, true},
|
||||
{"African", false},
|
||||
{"Afrikaans", false},
|
||||
{"Arabic", false},
|
||||
{"Asian", false},
|
||||
{"Bollywood", false},
|
||||
{"Brazilian", false},
|
||||
{"Caribbean", false},
|
||||
{"Celtic", false},
|
||||
{"Creole", false},
|
||||
{"European", false},
|
||||
{"Filipino", false},
|
||||
{"French", false},
|
||||
{"German", false},
|
||||
{"Greek", false},
|
||||
{"Hawaiian and Pacific", false},
|
||||
{"Hebrew", false},
|
||||
{"Hindi", false},
|
||||
{"Indian", false},
|
||||
{"Islamic", false},
|
||||
{"Japanese", false},
|
||||
{"Klezmer", false},
|
||||
{"Korean", false},
|
||||
{"Mediterranean", false},
|
||||
{"Middle Eastern", false},
|
||||
{"North American", false},
|
||||
{"Russian", false},
|
||||
{"Soca", false},
|
||||
{"South American", false},
|
||||
{"Tamil", false},
|
||||
{"Turkish", false},
|
||||
{"Worldbeat", false},
|
||||
{"Zouk", false},
|
||||
|
||||
{"Jazz", true, true},
|
||||
{"Acid Jazz", false},
|
||||
{"Avant Garde", false},
|
||||
{"Big Band", false},
|
||||
{"Bop", false},
|
||||
{"Classic Jazz", false},
|
||||
{"Cool Jazz", false},
|
||||
{"Fusion", false},
|
||||
{"Hard Bop", false},
|
||||
{"Latin Jazz", false},
|
||||
{"Smooth Jazz", false},
|
||||
{"Swing", false},
|
||||
{"Vocal Jazz", false},
|
||||
{"World Fusion", false},
|
||||
|
||||
{"Latin", true, true},
|
||||
{"Bachata", false},
|
||||
{"Banda", false},
|
||||
{"Bossa Nova", false},
|
||||
{"Cumbia", false},
|
||||
{"Flamenco", false},
|
||||
{"Latin Dance", false},
|
||||
{"Latin Pop", false},
|
||||
{"Latin Rap and Hip Hop", false},
|
||||
{"Latin Rock", false},
|
||||
{"Mariachi", false},
|
||||
{"Merengue", false},
|
||||
{"Ranchera", false},
|
||||
{"Reggaeton", false},
|
||||
{"Regional Mexican", false},
|
||||
{"Salsa", false},
|
||||
{"Samba", false},
|
||||
{"Tango", false},
|
||||
{"Tejano", false},
|
||||
{"Tropicalia", false},
|
||||
|
||||
{"Metal", true, true},
|
||||
{"Black Metal", false},
|
||||
{"Classic Metal", false},
|
||||
{"Death Metal", false},
|
||||
{"Extreme Metal", false},
|
||||
{"Grindcore", false},
|
||||
{"Hair Metal", false},
|
||||
{"Heavy Metal", false},
|
||||
{"Metalcore", false},
|
||||
{"Power Metal", false},
|
||||
{"Progressive Metal", false},
|
||||
{"Rap Metal", false},
|
||||
{"Thrash Metal", false},
|
||||
|
||||
{"Misc", true, false},
|
||||
|
||||
{"New Age", true, true},
|
||||
{"Environmental", false},
|
||||
{"Ethnic Fusion", false},
|
||||
{"Healing", false},
|
||||
{"Meditation", false},
|
||||
{"Spiritual", false},
|
||||
|
||||
{"Pop", true, true},
|
||||
{"Adult Contemporary", false},
|
||||
{"Barbershop", false},
|
||||
{"Bubblegum Pop", false},
|
||||
{"Dance Pop", false},
|
||||
{"Idols", false},
|
||||
{"JPOP", false},
|
||||
{"KPOP", false},
|
||||
{"Oldies", false},
|
||||
{"Soft Rock", false},
|
||||
{"Teen Pop", false},
|
||||
{"Top 40", false},
|
||||
{"World Pop", false},
|
||||
|
||||
{"Public Radio", true, true},
|
||||
{"College", false},
|
||||
{"News", false},
|
||||
{"Sports", false},
|
||||
{"Talk", false},
|
||||
{"Weather", false},
|
||||
|
||||
{"R&B and Urban", true, false},
|
||||
{"Classic R&B", false},
|
||||
{"Contemporary R&B", false},
|
||||
{"Doo Wop", false},
|
||||
{"Funk", false},
|
||||
{"Motown", false},
|
||||
{"Neo Soul", false},
|
||||
{"Quiet Storm", false},
|
||||
{"Soul", false},
|
||||
{"Urban Contemporary", false},
|
||||
|
||||
{"Rap", true, true},
|
||||
{"Alternative Rap", false},
|
||||
{"Dirty South", false},
|
||||
{"East Coast Rap", false},
|
||||
{"Freestyle", false},
|
||||
{"Gangsta Rap", false},
|
||||
{"Hip Hop", false},
|
||||
{"Mixtapes", false},
|
||||
{"Old School", false},
|
||||
{"Turntablism", false},
|
||||
{"Underground Hip Hop", false},
|
||||
{"West Coast Rap", false},
|
||||
|
||||
{"Reggae", true, true},
|
||||
{"Contemporary Reggae", false},
|
||||
{"Dancehall", false},
|
||||
{"Dub", false},
|
||||
{"Pop Reggae", false},
|
||||
{"Ragga", false},
|
||||
{"Reggae Roots", false},
|
||||
{"Rock Steady", false},
|
||||
|
||||
{"Rock", true, true},
|
||||
{"Adult Album Alternative", false},
|
||||
{"British Invasion", false},
|
||||
{"Celtic Rock", false},
|
||||
{"Classic Rock", false},
|
||||
{"Garage Rock", false},
|
||||
{"Glam", false},
|
||||
{"Hard Rock", false},
|
||||
{"Jam Bands", false},
|
||||
{"JROCK", false},
|
||||
{"Piano Rock", false},
|
||||
{"Prog Rock", false},
|
||||
{"Psychedelic", false},
|
||||
{"Rock & Roll", false},
|
||||
{"Rockabilly", false},
|
||||
{"Singer and Songwriter", false},
|
||||
{"Surf", false},
|
||||
|
||||
{"Seasonal and Holiday", true, true},
|
||||
{"Anniversary", false},
|
||||
{"Birthday", false},
|
||||
{"Christmas", false},
|
||||
{"Halloween", false},
|
||||
{"Hanukkah", false},
|
||||
{"Honeymoon", false},
|
||||
{"Kwanzaa", false},
|
||||
{"Valentine", false},
|
||||
{"Wedding", false},
|
||||
{"Winter", false},
|
||||
|
||||
{"Soundtracks", true, true},
|
||||
{"Anime", false},
|
||||
{"Kids", false},
|
||||
{"Original Score", false},
|
||||
{"Showtunes", false},
|
||||
{"Video Game Music", false},
|
||||
|
||||
{"Talk", true, true},
|
||||
{"BlogTalk", false},
|
||||
{"Comedy", false},
|
||||
{"Community", false},
|
||||
{"Educational", false},
|
||||
{"Government", false},
|
||||
{"News", false},
|
||||
{"Old Time Radio", false},
|
||||
{"Other Talk", false},
|
||||
{"Political", false},
|
||||
{"Scanner", false},
|
||||
{"Spoken Word", false},
|
||||
{"Sports", false},
|
||||
{"Technology", false},
|
||||
|
||||
{"Themes", true, true},
|
||||
{"Adult", false},
|
||||
{"Best Of", false},
|
||||
{"Chill", false},
|
||||
{"Eclectic", false},
|
||||
{"Experimental", false},
|
||||
{"Female", false},
|
||||
{"Heartache", false},
|
||||
{"Instrumental", false},
|
||||
{"LGBT", false},
|
||||
{"Love and Romance", false},
|
||||
{"Party Mix", false},
|
||||
{"Patriotic", false},
|
||||
{"Rainy Day Mix", false},
|
||||
{"Reality", false},
|
||||
{"Sexy", false},
|
||||
{"Shuffle", false},
|
||||
{"Travel Mix", false},
|
||||
{"Tribute", false},
|
||||
{"Trippy", false},
|
||||
{"Work Mix", false}
|
||||
};
|
||||
|
||||
// pulled from nmrCommon\intTypes.h
|
||||
typedef unsigned char __uint8;
|
||||
typedef unsigned short __uint16;
|
||||
typedef unsigned int __uint32;
|
||||
typedef unsigned long long __uint64;
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
||||
// this structure should be 16384 bytes in total size
|
||||
// and is defined in full size so that we know its ok
|
||||
struct uv2xHdr
|
||||
{ // uvox2 message
|
||||
__uint8 sync;
|
||||
__uint8 qos;
|
||||
__uint16 msgType;
|
||||
__uint16 msgLen;
|
||||
__uint8 m_data[UV_MAX_DATA_LEN];
|
||||
__uint8 end;
|
||||
};
|
||||
|
||||
struct uv2xMetadataHdr
|
||||
{ /* uvox 2 metadata header */
|
||||
__uint8 sync;
|
||||
__uint8 qos;
|
||||
__uint16 msgType;
|
||||
__uint16 msgLen;
|
||||
|
||||
__uint16 id; /* ID (cookie) identifying a metadata package */
|
||||
__uint16 span; /* Span of messages in the metadata package being assembled */
|
||||
__uint16 index; /* Index of the message in the metadata package being assembled */
|
||||
|
||||
__uint8 m_data[UV_MAX_META_LEN];
|
||||
__uint8 end;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#define MSG_AUTH 0x1001
|
||||
#define MSG_BROADCAST_SETUP 0x1002
|
||||
#define MSG_NEGOTIATE_BUFFER_SIZE 0x1003
|
||||
#define MSG_STANDBY 0x1004
|
||||
#define MSG_TERMINATE 0x1005
|
||||
#define MSG_FLUSH_CACHED_METADATA 0x1006
|
||||
#define MSG_LISTENER_AUTHENTICATION 0x1007
|
||||
#define MSG_MAX_PAYLOAD_SIZE 0x1008
|
||||
#define MSG_CIPHER 0x1009
|
||||
#define MSG_MIME_TYPE 0x1040
|
||||
#define MSG_FILE_TRANSFER_BEGIN 0x1050
|
||||
#define MSG_FILE_TRANSFER_DATA 0x1051
|
||||
|
||||
#define MSG_BROADCAST_INTERRUPTION 0x2001
|
||||
#define MSG_BROADCAST_TERMINATE 0x2002
|
||||
|
||||
#define MSG_ICYNAME 0x1100
|
||||
#define MSG_ICYGENRE 0x1101
|
||||
#define MSG_ICYURL 0x1102
|
||||
#define MSG_ICYPUB 0x1103
|
||||
|
||||
#define MSG_METADATA_CONTENTINFO 0x3000
|
||||
#define MSG_METADATA_URL 0x3001
|
||||
#define MSG_METADATA_XML 0x3901
|
||||
#define MSG_METADATA_XML_NEW 0x3902
|
||||
|
||||
// only id the start of the album art type as it's variable
|
||||
#define MSG_METADATA_ALBUMART 0x4000
|
||||
#define MSG_METADATA_STATION_ART 0x0000
|
||||
#define MSG_METADATA_PLAYING_ART 0x0100
|
||||
/*
|
||||
0x4 0x0xx Station logo
|
||||
0x4 0x1xx Album art
|
||||
|
||||
00 = image/jpeg
|
||||
01 = image/png
|
||||
02 = image/bmp
|
||||
03 = image/gif
|
||||
*/
|
||||
|
||||
#define MSG_METADATA_TIMEREMAINING 0x5001
|
||||
|
||||
#define MP3_DATA 0x7000
|
||||
#define VLB_DATA 0x8000
|
||||
#define AAC_LC_DATA 0x8001
|
||||
#define AACP_DATA 0x8003
|
||||
#define OGG_DATA 0x8004
|
||||
|
||||
struct T_OUTPUT_CONFIG {
|
||||
char Name[32];
|
||||
wchar_t DisplayName[32];
|
||||
char UserID[256];
|
||||
char Address[1024];
|
||||
u_short Port;
|
||||
char StationID[12];
|
||||
char Password[256]; // 4 - 8 for 1.8.2
|
||||
char cipherkey[64]; // sc2 cipherkey
|
||||
int AutoRecon;
|
||||
int ReconTime;
|
||||
char Description[1024];
|
||||
char ServerURL[2048];
|
||||
char Genre[256];
|
||||
char ICQ[128];
|
||||
char AIM[1024];
|
||||
char IRC[1024];
|
||||
int Public;
|
||||
int doTitleUpdate;
|
||||
int protocol;
|
||||
int protocol_retry;
|
||||
char Now[1024];
|
||||
char Next[1024];
|
||||
};
|
||||
|
||||
#define DEFAULT_ENCODER (C_ENCODER *)(-1)
|
||||
|
||||
#define OM_ENCODE 1
|
||||
#define OM_OUTPUT 2
|
||||
#define OM_OTHER 4
|
||||
#define OM_ALL (OM_ENCODE | OM_OUTPUT | OM_OTHER)
|
||||
|
||||
enum OUTPUTTYPE {
|
||||
OUTTYPE_SOURCE,
|
||||
OUTTYPE_TITLE,
|
||||
};
|
||||
|
||||
typedef unsigned long ARGB32;
|
||||
|
||||
struct T_OUTPUT_TITLE {
|
||||
wchar_t *Title;
|
||||
wchar_t *Song;
|
||||
wchar_t *Album;
|
||||
wchar_t *Artist;
|
||||
wchar_t *Genre;
|
||||
wchar_t *Comment;
|
||||
wchar_t *Year;
|
||||
std::vector<std::wstring> NextList;
|
||||
void *APIC[2];
|
||||
int APICLength[2];
|
||||
int APICType[2];
|
||||
|
||||
T_OUTPUT_TITLE() : Title(0), Song(0), Album(0), Artist(0), Genre(0), Comment(0), Year(0)
|
||||
{
|
||||
memset(APIC, 0, sizeof(void *) * 2);
|
||||
memset(APICLength, 0, sizeof(int) * 2);
|
||||
memset(APICType, 0, sizeof(int) * 2);
|
||||
}
|
||||
|
||||
|
||||
~T_OUTPUT_TITLE()
|
||||
{
|
||||
if (Title)
|
||||
{
|
||||
free(Title);
|
||||
Title = 0;
|
||||
}
|
||||
|
||||
if (Song)
|
||||
{
|
||||
free(Song);
|
||||
Song = 0;
|
||||
}
|
||||
|
||||
if (Album)
|
||||
{
|
||||
free(Album);
|
||||
Album = 0;
|
||||
}
|
||||
|
||||
if (Artist)
|
||||
{
|
||||
free(Artist);
|
||||
Artist = 0;
|
||||
}
|
||||
|
||||
if (Genre)
|
||||
{
|
||||
free(Genre);
|
||||
Genre = 0;
|
||||
}
|
||||
|
||||
if (Comment)
|
||||
{
|
||||
free(Comment);
|
||||
Comment = 0;
|
||||
}
|
||||
|
||||
if (Year)
|
||||
{
|
||||
free(Year);
|
||||
Year = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct T_OUTPUT_INFO {
|
||||
unsigned int BytesSent; // how many bytes of content we've sent
|
||||
clock_t ConnectionTime; // time a socket connection occurred
|
||||
int Version; // server version
|
||||
int Caps; // server capabilities
|
||||
int Reconnect; // flag for the reconnection algorithm
|
||||
int ReconnectTime; // value used in conjunction with the reconnection algorithm
|
||||
int Succeeded; // had at least one successful connection (for reconnection alg.) -1 = password failure
|
||||
int last_state; // using this as a means to allow for closing on errors but able to show a better message
|
||||
int Switching; // if we're doing an automatic protocol version change (from v2 to v1)
|
||||
char *ErrorMsg;
|
||||
time_t ConnectedAt;
|
||||
int meta_cached;
|
||||
int art_cached[2];
|
||||
unsigned short art_index[2];
|
||||
unsigned short art_cached_span[2];
|
||||
int art_cached_length[2];
|
||||
|
||||
// metadata information about the stream, etc
|
||||
wchar_t *Title;
|
||||
std::vector<std::wstring> NextList;
|
||||
wchar_t *Song;
|
||||
wchar_t *Album;
|
||||
wchar_t *Artist;
|
||||
wchar_t *Genre;
|
||||
wchar_t *Comment;
|
||||
wchar_t *Year;
|
||||
void *APIC[2];
|
||||
int APICLength[2];
|
||||
int APICType[2];
|
||||
|
||||
T_OUTPUT_INFO() : BytesSent(0), ConnectionTime(0), Version(0),
|
||||
Caps(0), Reconnect(0), ReconnectTime(0),
|
||||
Succeeded(0), last_state(0), Switching(0),
|
||||
ErrorMsg(0), ConnectedAt(0), meta_cached(0),
|
||||
Title(0), Song(0), Album(0), Artist(0),
|
||||
Genre(0), Comment(0), Year(0)
|
||||
{
|
||||
memset(art_cached, 0, sizeof(int) * 2);
|
||||
memset(art_index, 0, sizeof(unsigned short) * 2);
|
||||
memset(art_cached_span, 0, sizeof(unsigned short) * 2);
|
||||
memset(art_cached_length, 0, sizeof(int) * 2);
|
||||
|
||||
memset(APIC, 0, sizeof(void *) * 2);
|
||||
memset(APICLength, 0, sizeof(int) * 2);
|
||||
memset(APICType, 0, sizeof(int) * 2);
|
||||
}
|
||||
|
||||
~T_OUTPUT_INFO()
|
||||
{
|
||||
if (Title)
|
||||
{
|
||||
free(Title);
|
||||
Title = 0;
|
||||
}
|
||||
|
||||
if (Song)
|
||||
{
|
||||
free(Song);
|
||||
Song = 0;
|
||||
}
|
||||
|
||||
if (Album)
|
||||
{
|
||||
free(Album);
|
||||
Album = 0;
|
||||
}
|
||||
|
||||
if (Artist)
|
||||
{
|
||||
free(Artist);
|
||||
Artist = 0;
|
||||
}
|
||||
|
||||
if (Genre)
|
||||
{
|
||||
free(Genre);
|
||||
Genre = 0;
|
||||
}
|
||||
|
||||
if (Comment)
|
||||
{
|
||||
free(Comment);
|
||||
Comment = 0;
|
||||
}
|
||||
|
||||
if (Year)
|
||||
{
|
||||
free(Year);
|
||||
Year = 0;
|
||||
}
|
||||
|
||||
if (Succeeded == -2 && ErrorMsg) {
|
||||
free(ErrorMsg);
|
||||
ErrorMsg = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct T_OUTPUT {
|
||||
int Connection; // using this for the title update callback so the correct instance is updated
|
||||
void (*TitleCallback)(const int Connection, const int Mode);
|
||||
api_connection *Output;
|
||||
enum OUTPUTTYPE Type;
|
||||
int Bitrate; // this shouldn't be here, but it's the only way we can tell the shoutcast server the bitrate
|
||||
char *ContentType; // neither should this
|
||||
int SlowClose; // set to 1 to wait until all data is sent before closing the connection
|
||||
T_OUTPUT_CONFIG *Config;
|
||||
T_OUTPUT_INFO Info;
|
||||
|
||||
T_OUTPUT() : Connection(0), TitleCallback(0), Output(0), Type(OUTTYPE_SOURCE), Bitrate(0), ContentType(0), SlowClose(0), Config(0) {}
|
||||
};
|
||||
|
||||
enum OUTPUTSTATE {
|
||||
OUT_ERROR, // not a true state, but is returned when GetState() is called with an invalid connection handle
|
||||
OUT_DISCONNECTED,
|
||||
OUT_CONNECT,
|
||||
OUT_REQUEST_CIPHER,
|
||||
OUT_RECV_CIPHER,
|
||||
OUT_SENDAUTH,
|
||||
OUT_RECVAUTHRESPONSE,
|
||||
OUT_SEND_MIME,
|
||||
OUT_RECV_MIME,
|
||||
OUT_SEND_BITRATE,
|
||||
OUT_RECV_BITRATE,
|
||||
OUT_SEND_BUFSIZE,
|
||||
OUT_RECV_BUFSIZE,
|
||||
OUT_SEND_MAX,
|
||||
OUT_RECV_MAX,
|
||||
OUT_SENDYP,
|
||||
OUT_SEND_INITFLUSH,
|
||||
OUT_RECV_INITFLUSH,
|
||||
OUT_SEND_INITSTANDBY,
|
||||
OUT_RECV_INITSTANDBY,
|
||||
/*OUT_SEND_INTRO,
|
||||
OUT_RECV_INTRO,
|
||||
OUT_SEND_BACKUP,
|
||||
OUT_RECV_BACKUP,*/
|
||||
OUT_SENDCONTENT,
|
||||
OUT_DISCONNECT,
|
||||
OUT_RECONNECT,
|
||||
OUT_TITLESENDUPDATE,
|
||||
OUT_FAIL_CIPHER,
|
||||
OUT_SEND_METADATA,
|
||||
OUT_SEND_ARTWORK,
|
||||
};
|
||||
static void *mutex;
|
||||
|
||||
class SHOUTCAST_OUTPUT {
|
||||
private:
|
||||
C_ENCODER *Encoder;
|
||||
int IOwnEncoder;
|
||||
C_SERIAL_JOBMANAGER<T_OUTPUT> OutputManager;
|
||||
T_OUTPUT_TITLE metadata;
|
||||
|
||||
protected:
|
||||
static int Output_Disconnected(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Connect(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Request_Cipher(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Receive_Cipher(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_SendAuth(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_RecvAuthResponse(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Send_Mime(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Recv_Mime(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Send_Bitrate(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Recv_Bitrate(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Send_Buf_Size(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Recv_Buf_Size(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Send_Max_Size(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Recv_Max_Size(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_DUMMY(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_SendYP(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Send_InitFlush(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Recv_InitFlush(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Send_InitStandby(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Recv_InitStandby(int state, int last_state, T_OUTPUT *userData);
|
||||
/*static int Output_Send_Intro(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Recv_Intro(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Send_Backup(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Recv_Backup(int state, int last_state, T_OUTPUT *userData);*/
|
||||
static int Output_SendContent(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Disconnect(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Reconnect(int state, int last_state, T_OUTPUT *userData);
|
||||
|
||||
static int Output_Title_SendUpdate(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Send_Metadata(int state, int last_state, T_OUTPUT *userData);
|
||||
static int Output_Send_Artwork(int state, int last_state, T_OUTPUT *userData);
|
||||
|
||||
// uvox21
|
||||
static void createUvoxFrame(int length, char *payload_in, int type, T_OUTPUT *userData);
|
||||
static int createUvoxMetaFrame(int length, char *payload_in, int type,
|
||||
T_OUTPUT *userData, unsigned short id, unsigned short span = 1);
|
||||
static int parseUvoxFrame(char *payload_in, char *payload_out);
|
||||
static int checkUvoxFrameForError(char *pload_out, int state, T_OUTPUT *userData);
|
||||
|
||||
void (*lame_init)(void);
|
||||
void (*lame_init_params)(lame_global_flags *);
|
||||
int (*lame_encode_buffer_interleaved)(lame_global_flags *, short int pcm[], int num_samples, char *mp3buffer, int mp3buffer_size);
|
||||
int (*lame_encode_flush)(lame_global_flags *, char *mp3buffer, int size);
|
||||
|
||||
HINSTANCE libinst;
|
||||
|
||||
public:
|
||||
SHOUTCAST_OUTPUT();
|
||||
void SetLame(void *init, void *params, void *encode, void *finish);
|
||||
~SHOUTCAST_OUTPUT();
|
||||
int Run(int mode = 0, void *Input = NULL, int InputSize = 0, int SaveEncoder = -1);
|
||||
int AddOutput(int Connection, T_OUTPUT_CONFIG *Config, void (*TitleCallback)(const int Connection, const int Mode)=0);
|
||||
void UpdateOutput(int Connection);
|
||||
void RemoveOutput(int Connection);
|
||||
int ConnectOutput(int Connection);
|
||||
int DisconnectOutput(int Connection, int withReconnect = 0, int reconnectTime = -1); // withReconnect of -1 will use the output config's setting
|
||||
void SetEncoder(C_ENCODER *encoder, int takeOwnership = 0);
|
||||
|
||||
// we will attempt to cache the title information to save on duplication and
|
||||
// also to make it easier for the title to be re-sent on server disconnect
|
||||
void UpdateTitleCache(wchar_t *Title, std::vector<std::wstring> NextList, wchar_t *Song,
|
||||
wchar_t *Album, wchar_t *Artist, wchar_t *Genre, wchar_t *Comment,
|
||||
wchar_t* Year, int Connection, bool sendNext);
|
||||
void UpdateTitle(wchar_t *Title, std::vector<std::wstring> NextList,
|
||||
int Connection, bool sendNext, bool UseCache = true);
|
||||
|
||||
void UpdateArtwork(int Connection);
|
||||
void UpdateAlbumArtCache(void* APIC, int APIClength, int APICType, int Connection);
|
||||
int UpdateAlbumArt(int Connection);
|
||||
|
||||
enum OUTPUTSTATE GetState(int Connection);
|
||||
T_OUTPUT_CONFIG *operator[](int Connection);
|
||||
T_OUTPUT_CONFIG *GetOutput(int Connection);
|
||||
C_ENCODER *GetEncoder();
|
||||
T_OUTPUT_INFO *GetOutputInfo(int Connection);
|
||||
};
|
||||
static unsigned short mid = 1;
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define DEBUG_STATE OutputDebugString(__FUNCTION__); OutputDebugString("\r\n");
|
||||
#else
|
||||
#define DEBUG_STATE
|
||||
#endif
|
||||
|
||||
#define STATE userData->Info.last_state = last_state
|
||||
#define LOCK if(WaitForSingleObject(mutex,INFINITE) == WAIT_OBJECT_0)
|
||||
#define UNLOCK ReleaseMutex(mutex);
|
||||
|
||||
extern char sourceVersion[64];
|
||||
extern HWND hMainDLG;
|
||||
#endif // !__SHOUTCAST_OUTPUT_H__
|
Loading…
Add table
Add a link
Reference in a new issue