--- /dev/null
+/*$T libedcast.cpp GC 1.140 10/23/05 11:32:15 */\r
+#include <fcntl.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <string.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <sys/timeb.h>\r
+#include <time.h>\r
+#include <stdarg.h>\r
+#ifdef HAVE_VORBIS\r
+#include <vorbis/vorbisenc.h>\r
+#endif\r
+\r
+#include "libedcast.h"\r
+#include "libedcast_socket.h"\r
+#ifdef WIN32\r
+#include <bass.h>\r
+#else\r
+#ifdef HAVE_LAME\r
+#include <lame/lame.h>\r
+#endif\r
+#include <errno.h>\r
+#endif\r
+#ifdef HAVE_FAAC\r
+#include <faac.h>\r
+#endif\r
+#ifndef LAME_MAXMP3BUFFER\r
+#define LAME_MAXMP3BUFFER 16384\r
+#endif\r
+#define GUINT16_TO_LE(val) ((unsigned short) (val))\r
+#define GUINT32_TO_LE(val) ((unsigned int) (val))\r
+#define GUINT16_FROM_LE(val) (GUINT16_TO_LE(val))\r
+#ifdef WIN32\r
+#pragma comment(linker, "/delayload:libfaac.dll")\r
+#define FILE_SEPARATOR "\\"\r
+#else\r
+#define FILE_SEPARATOR "/"\r
+typedef struct\r
+{\r
+ short wFormatTag;\r
+ short nChannels;\r
+ long nSamplesPerSec;\r
+ long nAvgBytesPerSec;\r
+ short nBlockAlign;\r
+ short wBitsPerSample;\r
+ short cbSize;\r
+} WAVEFORMATEX;\r
+#define WAVE_FORMAT_PCM (0x0001)\r
+#define DWORD long\r
+#endif\r
+long dwDataBlockPos = 0;\r
+long TotalWritten = 0;\r
+\r
+\r
+#ifdef WIN32\r
+#define INT32 __int32\r
+#else\r
+#define INT32 int\r
+#endif\r
+\r
+#define MAX_ENCODERS 10\r
+\r
+extern edcastGlobals *g[MAX_ENCODERS];\r
+extern edcastGlobals gMain;\r
+\r
+int buffer_blocksize = 0;\r
+\r
+#ifdef HAVE_AACP\r
+\r
+/*\r
+ =======================================================================================================================\r
+ uninteresting stuff ;\r
+ for the input plugin\r
+ =======================================================================================================================\r
+ */\r
+static void SAAdd(void *data, int timestamp, int csa) {\r
+}\r
+\r
+static void VSAAdd(void *data, int timestamp) {\r
+}\r
+\r
+static void SAVSAInit(int maxlatency_in_ms, int srate) {\r
+}\r
+\r
+static void SAVSADeInit() {\r
+}\r
+\r
+static void SAAddPCMData(void *PCMData, int nch, int bps, int timestamp) {\r
+}\r
+\r
+static int SAGetMode() {\r
+ return 0;\r
+}\r
+\r
+static int VSAGetMode(int *specNch, int *waveNch) {\r
+ return 0;\r
+}\r
+\r
+static void VSAAddPCMData(void *PCMData, int nch, int bps, int timestamp) {\r
+}\r
+\r
+static void VSASetInfo(int nch, int srate) {\r
+}\r
+\r
+static int dsp_isactive() {\r
+ return 0;\r
+}\r
+\r
+static int dsp_dosamples(short int *samples, int ns, int bps, int nch, int srate) {\r
+ return ns;\r
+}\r
+\r
+static void SetInfo(int bitrate0, int srate0, int stereo, int synched) {\r
+}\r
+#endif\r
+typedef struct tagConfigFileValue\r
+{\r
+ char_t Variable[256];\r
+ char_t Value[256];\r
+ char_t Description[1024];\r
+} configFileValue;\r
+\r
+static configFileValue configFileValues[100];\r
+static int numConfigValues = 0;\r
+\r
+static int greconnectFlag = 0;\r
+char_t defaultLogFileName[1024] = "edcast.log";\r
+\r
+void setDefaultLogFileName(char_t *filename) {\r
+ strcpy(defaultLogFileName, filename);\r
+}\r
+int getReconnectFlag(edcastGlobals *g) {\r
+ return g->gAutoReconnect;\r
+}\r
+\r
+int getReconnectSecs(edcastGlobals *g) {\r
+ return g->gReconnectSec;\r
+}\r
+\r
+void addVorbisComment(edcastGlobals *g, char_t *comment) {\r
+ int commentLen = strlen(comment) + 1;\r
+\r
+ g->vorbisComments[g->numVorbisComments] = (char_t *) calloc(1, commentLen);\r
+ if (g->vorbisComments[g->numVorbisComments]) {\r
+ memset(g->vorbisComments[g->numVorbisComments], '\000', commentLen);\r
+ strcpy(g->vorbisComments[g->numVorbisComments], comment);\r
+ g->numVorbisComments++;\r
+ }\r
+}\r
+\r
+void freeVorbisComments(edcastGlobals *g) {\r
+ for(int i = 0; i < g->numVorbisComments; i++) {\r
+ if(g->vorbisComments[i]) {\r
+ free(g->vorbisComments[i]);\r
+ g->vorbisComments[i] = NULL;\r
+ }\r
+ }\r
+\r
+ g->numVorbisComments = 0;\r
+}\r
+\r
+void addConfigVariable(edcastGlobals *g, char_t *variable) {\r
+ g->configVariables[g->numConfigVariables] = strdup(variable);\r
+ g->numConfigVariables++;\r
+}\r
+long getWritten(edcastGlobals *g) {\r
+ return g->written;\r
+}\r
+\r
+void setWritten(edcastGlobals *g, long writ) {\r
+ g->written = writ;\r
+}\r
+\r
+void setAutoConnect(edcastGlobals *g, int flag) {\r
+ g->autoconnect = flag;\r
+}\r
+\r
+FILE *getSaveFileP(edcastGlobals *g) {\r
+ return g->gSaveFile;\r
+}\r
+\r
+int getLiveRecordingSetFlag(edcastGlobals *g) {\r
+ return g->gLiveRecordingFlag;\r
+}\r
+\r
+bool getLiveRecordingFlag(edcastGlobals *g) {\r
+ return g->areLiveRecording;\r
+}\r
+\r
+void setLiveRecordingFlag(edcastGlobals *g, bool flag) {\r
+ g->areLiveRecording = flag;\r
+}\r
+\r
+int getLiveInSamplerate(edcastGlobals *g) {\r
+ return g->gLiveInSamplerate;\r
+}\r
+\r
+void setLiveInSamplerate(edcastGlobals *g, int rate) {\r
+ g->gLiveInSamplerate = rate;\r
+}\r
+\r
+int getOggFlag(edcastGlobals *g) {\r
+ return g->gOggFlag;\r
+}\r
+\r
+char_t *getServerDesc(edcastGlobals *g) {\r
+ return g->gServDesc;\r
+}\r
+\r
+char_t *getSourceURL(edcastGlobals *g) {\r
+ return g->gSourceURL;\r
+}\r
+\r
+void setSourceURL(edcastGlobals *g, char_t *url) {\r
+ strcpy(g->gSourceURL, url);\r
+}\r
+\r
+int getIsConnected(edcastGlobals *g) {\r
+ return g->weareconnected;\r
+}\r
+\r
+long getCurrentSamplerate(edcastGlobals *g) {\r
+ return g->currentSamplerate;\r
+}\r
+\r
+int getCurrentBitrate(edcastGlobals *g) {\r
+ return g->currentBitrate;\r
+}\r
+\r
+int getCurrentChannels(edcastGlobals *g) {\r
+ return g->currentChannels;\r
+}\r
+\r
+void setSourceDescription(edcastGlobals *g, char_t *desc) {\r
+ strcpy(g->sourceDescription, desc);\r
+}\r
+\r
+long getVUShow(edcastGlobals *g) {\r
+ return g->vuShow;\r
+}\r
+\r
+void setVUShow(edcastGlobals *g, long x) {\r
+ g->vuShow = x;\r
+}\r
+\r
+long getLastXWindow(edcastGlobals *g) {\r
+ return g->lastX;\r
+}\r
+\r
+long getLastYWindow(edcastGlobals *g) {\r
+ return g->lastY;\r
+}\r
+\r
+void setLastXWindow(edcastGlobals *g, long x) {\r
+ g->lastX = x;\r
+}\r
+\r
+void setLastYWindow(edcastGlobals *g, long y) {\r
+ g->lastY = y;\r
+}\r
+\r
+long getLastDummyXWindow(edcastGlobals *g) {\r
+ return g->lastDummyX;\r
+}\r
+\r
+long getLastDummyYWindow(edcastGlobals *g) {\r
+ return g->lastDummyY;\r
+}\r
+\r
+void setLastDummyXWindow(edcastGlobals *g, long x) {\r
+ g->lastDummyX = x;\r
+}\r
+\r
+void setLastDummyYWindow(edcastGlobals *g, long y) {\r
+ g->lastDummyY = y;\r
+}\r
+\r
+int getSaveAsWAV(edcastGlobals *g) {\r
+ return g->gSaveAsWAV;\r
+}\r
+\r
+void setSaveAsWAV(edcastGlobals *g, int flag) {\r
+ g->gSaveAsWAV = flag;\r
+}\r
+\r
+char_t *getCurrentRecordingName(edcastGlobals *g) {\r
+ return(g->gCurrentRecordingName);\r
+}\r
+\r
+void setCurrentRecordingName(edcastGlobals *g, char_t *name) {\r
+ strcpy(g->gCurrentRecordingName, name);\r
+}\r
+\r
+int getFrontEndType(edcastGlobals *g) {\r
+ return(g->frontEndType);\r
+}\r
+\r
+void setFrontEndType(edcastGlobals *g, int x) {\r
+ g->frontEndType = x;\r
+}\r
+\r
+int getReconnectTrigger(edcastGlobals *g) {\r
+ return(g->ReconnectTrigger);\r
+}\r
+\r
+void setReconnectTrigger(edcastGlobals *g, int x) {\r
+ g->ReconnectTrigger = x;\r
+}\r
+\r
+char_t *getLockedMetadata(edcastGlobals *g) {\r
+ return g->gManualSongTitle;\r
+}\r
+\r
+void setLockedMetadata(edcastGlobals *g, char_t *buf) {\r
+ memset(g->gManualSongTitle, '\000', sizeof(g->gManualSongTitle));\r
+ strncpy(g->gManualSongTitle, buf, sizeof(g->gManualSongTitle) - 1);\r
+}\r
+\r
+int getLockedMetadataFlag(edcastGlobals *g) {\r
+ return g->gLockSongTitle;\r
+}\r
+\r
+void setLockedMetadataFlag(edcastGlobals *g, int flag) {\r
+ g->gLockSongTitle = flag;\r
+}\r
+\r
+void setSaveDirectory(edcastGlobals *g, char_t *saveDir) {\r
+ memset(g->gSaveDirectory, '\000', sizeof(g->gSaveDirectory));\r
+ strncpy(g->gSaveDirectory, saveDir, sizeof(g->gSaveDirectory) - 1);\r
+}\r
+\r
+char_t *getSaveDirectory(edcastGlobals *g) {\r
+ return(g->gSaveDirectory);\r
+}\r
+\r
+void setSaveDirectoryFlag(edcastGlobals *g, int flag) {\r
+ g->gSaveDirectoryFlag = flag;\r
+}\r
+\r
+int getSaveDirectoryFlag(edcastGlobals *g) {\r
+ return(g->gSaveDirectoryFlag);\r
+}\r
+\r
+void setgLogFile(edcastGlobals *g, char_t *logFile) {\r
+ strcpy(g->gLogFile, logFile);\r
+}\r
+\r
+char_t *getgLogFile(edcastGlobals *g) {\r
+ return(g->gLogFile);\r
+}\r
+\r
+int resetResampler(edcastGlobals *g) {\r
+ if(g->initializedResampler) {\r
+ res_clear(&(g->resampler));\r
+ }\r
+\r
+ g->initializedResampler = 0;\r
+ return 1;\r
+}\r
+\r
+/* Gratuitously ripped from util.c */\r
+static char_t base64table[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };\r
+\r
+static signed char_t base64decode[256] = { -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -1, -2, -2, -2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, -2, -2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2 };\r
+\r
+/*\r
+ =======================================================================================================================\r
+ This isn't efficient, but it doesn't need to be\r
+ =======================================================================================================================\r
+ */\r
+char_t *util_base64_encode(char_t *data) {\r
+ int len = strlen(data);\r
+ char_t *out = (char_t *) malloc(len * 4 / 3 + 4);\r
+ char_t *result = out;\r
+ int chunk;\r
+\r
+ while(len > 0) {\r
+ chunk = (len > 3) ? 3 : len;\r
+ *out++ = base64table[(*data & 0xFC) >> 2];\r
+ *out++ = base64table[((*data & 0x03) << 4) | ((*(data + 1) & 0xF0) >> 4)];\r
+ switch(chunk) {\r
+ case 3:\r
+ *out++ = base64table[((*(data + 1) & 0x0F) << 2) | ((*(data + 2) & 0xC0) >> 6)];\r
+ *out++ = base64table[(*(data + 2)) & 0x3F];\r
+ break;\r
+\r
+ case 2:\r
+ *out++ = base64table[((*(data + 1) & 0x0F) << 2)];\r
+ *out++ = '=';\r
+ break;\r
+\r
+ case 1:\r
+ *out++ = '=';\r
+ *out++ = '=';\r
+ break;\r
+ }\r
+\r
+ data += chunk;\r
+ len -= chunk;\r
+ }\r
+\r
+ *out = 0;\r
+\r
+ return result;\r
+}\r
+\r
+char_t *util_base64_decode(unsigned char_t *input) {\r
+ int len = strlen((char_t *) input);\r
+ char_t *out = (char_t *) malloc(len * 3 / 4 + 5);\r
+ char_t *result = out;\r
+ signed char_t vals[4];\r
+\r
+ while(len > 0) {\r
+ if(len < 4) {\r
+ free(result);\r
+ return NULL; /* Invalid Base64 data */\r
+ }\r
+\r
+ vals[0] = base64decode[*input++];\r
+ vals[1] = base64decode[*input++];\r
+ vals[2] = base64decode[*input++];\r
+ vals[3] = base64decode[*input++];\r
+\r
+ if(vals[0] < 0 || vals[1] < 0 || vals[2] < -1 || vals[3] < -1) {\r
+ continue;\r
+ }\r
+\r
+ *out++ = vals[0] << 2 | vals[1] >> 4;\r
+ if(vals[2] >= 0)\r
+ *out++ = ((vals[1] & 0x0F) << 4) | (vals[2] >> 2);\r
+ else\r
+ *out++ = 0;\r
+\r
+ if(vals[3] >= 0)\r
+ *out++ = ((vals[2] & 0x03) << 6) | (vals[3]);\r
+ else\r
+ *out++ = 0;\r
+\r
+ len -= 4;\r
+ }\r
+\r
+ *out = 0;\r
+\r
+ return result;\r
+}\r
+\r
+#define HEADER_TYPE 1\r
+#define CODEC_TYPE 2\r
+\r
+void closeArchiveFile(edcastGlobals *g) {\r
+ if(g->gSaveFile) {\r
+ if(g->gSaveAsWAV) {\r
+ wav_header.length = GUINT32_TO_LE(g->written + sizeof(struct wavhead) - 8);\r
+ wav_header.data_length = GUINT32_TO_LE(g->written);\r
+ fseek(g->gSaveFile, 0, SEEK_SET);\r
+ fwrite(&wav_header, sizeof(struct wavhead), 1, g->gSaveFile);\r
+ g->written = 0;\r
+ }\r
+\r
+ fclose(g->gSaveFile);\r
+ g->gSaveFile = 0;\r
+ }\r
+}\r
+\r
+int openArchiveFile(edcastGlobals *g) {\r
+ char_t outFilename[1024] = "";\r
+ char_t outputFile[1024] = "";\r
+ struct tm *newtime;\r
+ time_t aclock;\r
+\r
+ time(&aclock);\r
+ newtime = localtime(&aclock);\r
+\r
+ sprintf(outFilename, "%s_%s", g->gServDesc, asctime(newtime));\r
+\r
+ memset(outputFile, '\000', sizeof(outputFile));\r
+\r
+ memset(outputFile, '\000', sizeof(outputFile));\r
+ ReplaceString(outFilename, outputFile, "\"", "'");\r
+ memset(outFilename, '\000', sizeof(outFilename));\r
+ ReplaceString(outputFile, outFilename, FILE_SEPARATOR, "");\r
+ memset(outputFile, '\000', sizeof(outputFile));\r
+ ReplaceString(outFilename, outputFile, "/", "");\r
+ memset(outFilename, '\000', sizeof(outFilename));\r
+ ReplaceString(outputFile, outFilename, ":", "");\r
+ memset(outputFile, '\000', sizeof(outputFile));\r
+ ReplaceString(outFilename, outputFile, "*", "");\r
+ memset(outFilename, '\000', sizeof(outFilename));\r
+ ReplaceString(outputFile, outFilename, "?", "");\r
+ memset(outputFile, '\000', sizeof(outputFile));\r
+ ReplaceString(outFilename, outputFile, "<", "");\r
+ memset(outFilename, '\000', sizeof(outFilename));\r
+ ReplaceString(outputFile, outFilename, ">", "");\r
+ memset(outputFile, '\000', sizeof(outputFile));\r
+ ReplaceString(outFilename, outputFile, "|", "");\r
+ memset(outFilename, '\000', sizeof(outFilename));\r
+ ReplaceString(outputFile, outFilename, "\n", "");\r
+\r
+ memset(outputFile, '\000', sizeof(outputFile));\r
+ strcpy(outputFile, outFilename);\r
+\r
+ if(g->gSaveAsWAV) {\r
+ strcat(outputFile, ".wav");\r
+ }\r
+ else {\r
+ if(g->gOggFlag) {\r
+ strcat(outputFile, ".ogg");\r
+ }\r
+\r
+ if(g->gLAMEFlag) {\r
+ strcat(outputFile, ".mp3");\r
+ }\r
+\r
+ if(g->gAACFlag) {\r
+ strcat(outputFile, ".aac");\r
+ }\r
+\r
+ if(g->gAACPFlag) {\r
+ strcat(outputFile, ".aac");\r
+ }\r
+ }\r
+\r
+ sprintf(outFilename, "%s%s%s", g->gSaveDirectory, FILE_SEPARATOR, outputFile);\r
+\r
+ g->gSaveFile = fopen(outFilename, "wb");\r
+ if(!g->gSaveFile) {\r
+ char_t buff[1024] = "";\r
+\r
+ sprintf(buff, "Cannot open %s", outputFile);\r
+ LogMessage(g,LOG_ERROR, buff);\r
+ return 0;\r
+ }\r
+\r
+ if(g->gSaveAsWAV) {\r
+ int nch = 2;\r
+ int rate = 44100;\r
+\r
+ memcpy(&wav_header.main_chunk, "RIFF", 4);\r
+ wav_header.length = GUINT32_TO_LE(0);\r
+ memcpy(&wav_header.chunk_type, "WAVE", 4);\r
+ memcpy(&wav_header.sub_chunk, "fmt ", 4);\r
+ wav_header.sc_len = GUINT32_TO_LE(16);\r
+ wav_header.format = GUINT16_TO_LE(1);\r
+ wav_header.modus = GUINT16_TO_LE(nch);\r
+ wav_header.sample_fq = GUINT32_TO_LE(rate);\r
+ wav_header.bit_p_spl = GUINT16_TO_LE(16);\r
+ wav_header.byte_p_sec = GUINT32_TO_LE(rate * wav_header.modus * (GUINT16_FROM_LE(wav_header.bit_p_spl) / 8));\r
+ wav_header.byte_p_spl = GUINT16_TO_LE((GUINT16_FROM_LE(wav_header.bit_p_spl) / (8 / nch)));\r
+ memcpy(&wav_header.data_chunk, "data", 4);\r
+ wav_header.data_length = GUINT32_TO_LE(0);\r
+ fwrite(&wav_header, sizeof(struct wavhead), 1, g->gSaveFile);\r
+ }\r
+\r
+ return 1;\r
+}\r
+\r
+int sendToServer(edcastGlobals *g, int sd, char_t *data, int length, int type) {\r
+ int ret = 0;\r
+ int sendflags = 0;\r
+\r
+ if(g->gSaveDirectoryFlag) {\r
+ if(!g->gSaveFile) {\r
+ openArchiveFile(g);\r
+ }\r
+ }\r
+\r
+#if !defined(WIN32) && !defined(__FreeBSD__)\r
+ sendflags = MSG_NOSIGNAL;\r
+#endif\r
+ switch(type) {\r
+ case HEADER_TYPE:\r
+ ret = send(sd, data, length, sendflags);\r
+ break;\r
+\r
+ case CODEC_TYPE:\r
+ ret = send(sd, data, length, sendflags);\r
+ if(g->gSaveDirectoryFlag) {\r
+ if(g->gSaveFile) {\r
+ if(!g->gSaveAsWAV) {\r
+ fwrite(data, length, 1, g->gSaveFile);\r
+ }\r
+ }\r
+ }\r
+ break;\r
+ }\r
+\r
+ if(ret > 0) {\r
+ if(g->writeBytesCallback) {\r
+ g->writeBytesCallback((void *) g, (void *) ret);\r
+ }\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+int readConfigFile(edcastGlobals *g, int readOnly) {\r
+ FILE *filep;\r
+ char_t buffer[1024];\r
+ char_t configFile[1024] = "";\r
+ char_t defaultConfigName[] = "edcast";\r
+\r
+\r
+ numConfigValues = 0;\r
+ memset(&configFileValues, '\000', sizeof(configFileValues));\r
+\r
+ if(readOnly) {\r
+ sprintf(configFile, "%s", g->gConfigFileName);\r
+ }\r
+ else {\r
+ if(strlen(g->gConfigFileName) == 0) {\r
+ sprintf(configFile, "%s_%d.cfg", defaultConfigName, g->encoderNumber);\r
+ }\r
+ else {\r
+ sprintf(configFile, "%s_%d.cfg", g->gConfigFileName, g->encoderNumber);\r
+ }\r
+ }\r
+\r
+ filep = fopen(configFile, "r");\r
+ if(filep == 0) {\r
+\r
+ /*\r
+ * LogMessage(g,g,LOG_ERROR, "Cannot open config file %s\n", configFile);\r
+ * strcpy(g->gConfigFileName, defaultConfigName);\r
+ */\r
+ }\r
+ else {\r
+ while(!feof(filep)) {\r
+ char_t *p2;\r
+\r
+ memset(buffer, '\000', sizeof(buffer));\r
+ fgets(buffer, sizeof(buffer) - 1, filep);\r
+ p2 = strchr(buffer, '\r');\r
+ if(p2) {\r
+ *p2 = '\000';\r
+ }\r
+\r
+ p2 = strchr(buffer, '\n');\r
+ if(p2) {\r
+ *p2 = '\000';\r
+ }\r
+\r
+ if(buffer[0] != '#') {\r
+ char_t *p1 = strchr(buffer, '=');\r
+\r
+ if(p1) {\r
+ strncpy(configFileValues[numConfigValues].Variable, buffer, p1 - buffer);\r
+ p1++; /* Get past the = */\r
+ strcpy(configFileValues[numConfigValues].Value, p1);\r
+ numConfigValues++;\r
+ }\r
+ }\r
+ }\r
+\r
+ if(filep) {\r
+ fclose(filep);\r
+ }\r
+ }\r
+\r
+ config_read(g);\r
+\r
+ if(!readOnly) {\r
+ writeConfigFile(g);\r
+ }\r
+\r
+ return 1;\r
+}\r
+\r
+int deleteConfigFile(edcastGlobals *g) {\r
+ char_t configFile[1024] = "";\r
+ char_t defaultConfigName[] = "edcast";\r
+\r
+ if(strlen(g->gConfigFileName) == 0) {\r
+ sprintf(configFile, "%s_%d.cfg", defaultConfigName, g->encoderNumber);\r
+ }\r
+ else {\r
+ sprintf(configFile, "%s_%d.cfg", g->gConfigFileName, g->encoderNumber);\r
+ }\r
+\r
+ unlink(configFile);\r
+\r
+ return 1;\r
+}\r
+\r
+void setConfigFileName(edcastGlobals *g, char_t *configFile) {\r
+ strcpy(g->gConfigFileName, configFile);\r
+}\r
+\r
+char_t *getConfigFileName(edcastGlobals *g) {\r
+ return g->gConfigFileName;\r
+}\r
+\r
+int writeConfigFile(edcastGlobals *g) {\r
+ char_t configFile[1024] = "";\r
+ char_t defaultConfigName[] = "edcast";\r
+\r
+ config_write(g);\r
+\r
+ if(strlen(g->gConfigFileName) == 0) {\r
+ sprintf(configFile, "%s_%d.cfg", defaultConfigName, g->encoderNumber);\r
+ }\r
+ else {\r
+ sprintf(configFile, "%s_%d.cfg", g->gConfigFileName, g->encoderNumber);\r
+ }\r
+\r
+ FILE *filep = fopen(configFile, "w");\r
+\r
+ if(filep == 0) {\r
+ LogMessage(g,LOG_ERROR, "Cannot open config file %s\n", configFile);\r
+ return 0;\r
+ }\r
+\r
+ for(int i = 0; i < numConfigValues; i++) {\r
+ int ok = 1;\r
+ if (g->configVariables) {\r
+ ok = 0;\r
+ for (int j=0;j<g->numConfigVariables;j++) {\r
+ if (!strcmp(g->configVariables[j], configFileValues[i].Variable)) {\r
+ ok = 1;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (ok) {\r
+ if (strlen(configFileValues[i].Description) > 0) {\r
+ fprintf(filep, "# %s\n", configFileValues[i].Description);\r
+ }\r
+ fprintf(filep, "%s=%s\n", configFileValues[i].Variable, configFileValues[i].Value);\r
+ }\r
+ }\r
+\r
+ fclose(filep);\r
+\r
+ return 1;\r
+}\r
+\r
+void printConfigFileValues() {\r
+// for(int i = 0; i < numConfigValues; i++) {\r
+// LogMessage(g,LOG_DEBUG, "(%s) = (%s)\n", configFileValues[i].Variable, configFileValues[i].Value);\r
+// }\r
+}\r
+\r
+void GetConfigVariable(edcastGlobals *g, char_t *appName, char_t *paramName, char_t *defaultvalue, char_t *destValue, int destSize, char_t *desc) {\r
+ \r
+ if (g->configVariables) {\r
+ int ok = 0;\r
+ for (int j=0;j<g->numConfigVariables;j++) {\r
+ if (!strcmp(g->configVariables[j], paramName)) {\r
+ ok = 1;\r
+ break;\r
+ }\r
+ }\r
+ if (!ok) {\r
+ strcpy(destValue, defaultvalue);\r
+ return;\r
+ }\r
+ }\r
+ for(int i = 0; i < numConfigValues; i++) {\r
+ if(!strcmp(paramName, configFileValues[i].Variable)) {\r
+ strcpy(destValue, configFileValues[i].Value);\r
+ if (desc) {\r
+ strcpy(configFileValues[i].Description, desc);\r
+ }\r
+ return;\r
+ }\r
+ }\r
+\r
+ strcpy(configFileValues[numConfigValues].Variable, paramName);\r
+ strcpy(configFileValues[numConfigValues].Value, defaultvalue);\r
+ if (desc) {\r
+ strcpy(configFileValues[numConfigValues].Description, desc);\r
+ }\r
+\r
+ strcpy(destValue, configFileValues[numConfigValues].Value);\r
+ numConfigValues++;\r
+ return;\r
+}\r
+\r
+long GetConfigVariableLong(edcastGlobals *g, char_t *appName, char_t *paramName, long defaultvalue, char_t *desc) {\r
+ char_t buf[1024] = "";\r
+ char_t defaultbuf[1024] = "";\r
+\r
+ sprintf(defaultbuf, "%d", defaultvalue);\r
+\r
+ GetConfigVariable(g, appName, paramName, defaultbuf, buf, sizeof(buf), desc);\r
+\r
+ return atol(buf);\r
+}\r
+\r
+void PutConfigVariable(edcastGlobals *g, char_t *appName, char_t *paramName, char_t *destValue) {\r
+\r
+ if (g->configVariables) {\r
+ int ok = 0;\r
+ for (int j=0;j<g->numConfigVariables;j++) {\r
+ if (!strcmp(g->configVariables[j], paramName)) {\r
+ ok = 1;\r
+ break;\r
+ }\r
+ }\r
+ if (!ok) {\r
+ return;\r
+ }\r
+ }\r
+\r
+ for(int i = 0; i < numConfigValues; i++) {\r
+ if(!strcmp(paramName, configFileValues[i].Variable)) {\r
+ strcpy(configFileValues[i].Value, destValue);\r
+ return;\r
+ }\r
+ }\r
+\r
+ strcpy(configFileValues[numConfigValues].Variable, paramName);\r
+ strcpy(configFileValues[numConfigValues].Value, destValue);\r
+ strcpy(configFileValues[numConfigValues].Description, "");\r
+ numConfigValues++;\r
+ return;\r
+}\r
+\r
+void PutConfigVariableLong(edcastGlobals *g, char_t *appName, char_t *paramName, long value) {\r
+ char_t buf[1024] = "";\r
+\r
+ sprintf(buf, "%d", value);\r
+\r
+ PutConfigVariable(g, appName, paramName, buf);\r
+\r
+ return;\r
+}\r
+\r
+void restartConnection() {\r
+ ;\r
+}\r
+\r
+int trimVariable(char_t *variable) {\r
+ char_t *p1;\r
+\r
+ /* Trim off the back */\r
+ for(p1 = variable + strlen(variable) - 1; p1 > variable; p1--) {\r
+ if((*p1 == ' ') || (*p1 == ' ')) {\r
+ *p1 = '\000';\r
+ }\r
+ else {\r
+ break;\r
+ }\r
+ }\r
+\r
+ /* Trim off the front */\r
+ char_t tempVariable[1024] = "";\r
+\r
+ memset(tempVariable, '\000', sizeof(tempVariable));\r
+ for(p1 = variable; p1 < variable + strlen(variable) - 1; p1++) {\r
+ if((*p1 == ' ') || (*p1 == ' ')) {\r
+ ;\r
+ }\r
+ else {\r
+ break;\r
+ }\r
+ }\r
+\r
+ strcpy(tempVariable, p1);\r
+ strcpy(variable, tempVariable);\r
+ return 1;\r
+}\r
+\r
+void setDestURLCallback(edcastGlobals *g, void (*pCallback) (void *, void *)) {\r
+ g->destURLCallback = pCallback;\r
+}\r
+\r
+void setSourceURLCallback(edcastGlobals *g, void (*pCallback) (void *, void *)) {\r
+ g->sourceURLCallback = pCallback;\r
+}\r
+\r
+void setServerStatusCallback(edcastGlobals *g, void (*pCallback) (void *, void *)) {\r
+ g->serverStatusCallback = pCallback;\r
+}\r
+\r
+void setGeneralStatusCallback(edcastGlobals *g, void (*pCallback) (void *, void *)) {\r
+ g->generalStatusCallback = pCallback;\r
+}\r
+\r
+void setWriteBytesCallback(edcastGlobals *g, void (*pCallback) (void *, void *)) {\r
+ g->writeBytesCallback = pCallback;\r
+}\r
+\r
+void setServerTypeCallback(edcastGlobals *g, void (*pCallback) (void *, void *)) {\r
+ g->serverTypeCallback = pCallback;\r
+}\r
+\r
+void setServerNameCallback(edcastGlobals *g, void (*pCallback) (void *, void *)) {\r
+ g->serverNameCallback = pCallback;\r
+}\r
+\r
+void setStreamTypeCallback(edcastGlobals *g, void (*pCallback) (void *, void *)) {\r
+ g->streamTypeCallback = pCallback;\r
+}\r
+\r
+void setBitrateCallback(edcastGlobals *g, void (*pCallback) (void *, void *)) {\r
+ g->bitrateCallback = pCallback;\r
+}\r
+\r
+void setOggEncoderText(edcastGlobals *g, char_t *text) {\r
+ strcpy(g->gOggEncoderText, text);\r
+}\r
+\r
+void setVUCallback(edcastGlobals *g, void (*pCallback) (int, int)) {\r
+ g->VUCallback = pCallback;\r
+}\r
+\r
+void setForceStop(edcastGlobals *g, int forceStop) {\r
+ g->gForceStop = forceStop;\r
+}\r
+\r
+void initializeGlobals(edcastGlobals *g) {\r
+\r
+ /* Global variables....gotta love em... */\r
+ g->gSCSocket = 0;\r
+ g->gSCSocket2 = 0;\r
+ g->gSCSocketControl = 0;\r
+ g->gSCFlag = 0;\r
+ g->gReconnectSec = 10;\r
+ g->gAutoCountdown = 10;\r
+ g->automaticconnect = 1;\r
+ memset(g->gServer, '\000', sizeof(g->gServer));\r
+ memset(g->gPort, '\000', sizeof(g->gPort));\r
+ memset(g->gPassword, '\000', sizeof(g->gPassword));\r
+ memset(g->gIniFile, '\000', sizeof(g->gIniFile));\r
+ memset(g->gAppName, '\000', sizeof(g->gAppName));\r
+ memset(g->gCurrentSong, '\000', sizeof(g->gCurrentSong));\r
+ g->gPubServ = 0;\r
+ memset(g->gServIRC, '\000', sizeof(g->gServIRC));\r
+ memset(g->gServAIM, '\000', sizeof(g->gServAIM));\r
+ memset(g->gServICQ, '\000', sizeof(g->gServICQ));\r
+ memset(g->gServURL, '\000', sizeof(g->gServURL));\r
+ memset(g->gServDesc, '\000', sizeof(g->gServDesc));\r
+ memset(g->gMountpoint, '\000', sizeof(g->gMountpoint));\r
+ g->gAutoReconnect = 0;\r
+ memset(g->gAutoStart, '\000', sizeof(g->gAutoStart));\r
+ memset(g->gAutoStartSec, '\000', sizeof(g->gAutoStartSec));\r
+ memset(g->gQuality, '\000', sizeof(g->gQuality));\r
+ g->gOggFlag = 0;\r
+ memset(g->gIceFlag, '\000', sizeof(g->gIceFlag));\r
+ g->gLAMEFlag = 0;\r
+ memset(g->gSaveDirectory, '\000', sizeof(g->gSaveDirectory));\r
+ memset(g->gLogFile, '\000', sizeof(g->gLogFile));\r
+ g->gLogLevel = LM_ERROR;\r
+ g->gSaveDirectoryFlag = 0;\r
+ memset(g->gSongTitle, '\000', sizeof(g->gSongTitle));\r
+ memset(g->gManualSongTitle, '\000', sizeof(g->gManualSongTitle));\r
+ g->gLockSongTitle = 0;\r
+ g->startTime = 0;\r
+ g->endTime = 0;\r
+\r
+ g->weareconnected = 0;\r
+ pthread_mutex_init(&(g->mutex), NULL);\r
+\r
+ memset(g->WindowsRecDevice, '\000', sizeof(g->WindowsRecDevice));\r
+ g->LAMEJointStereoFlag = 1;\r
+\r
+#ifndef WIN32\r
+#ifdef HAVE_LAME\r
+ g->gf = NULL;\r
+#endif\r
+#endif\r
+ g->gCurrentlyEncoding = 0;\r
+ g->gShoutcastFlag = 0;\r
+ g->gIcecastFlag = 0;\r
+ g->gSaveFile = 0;\r
+ g->destURLCallback = NULL;\r
+ g->sourceURLCallback = NULL;\r
+ g->serverStatusCallback = NULL;\r
+ g->generalStatusCallback = NULL;\r
+ g->writeBytesCallback = NULL;\r
+ g->serverTypeCallback = NULL;\r
+ g->serverNameCallback = NULL;\r
+ g->streamTypeCallback = NULL;\r
+ g->bitrateCallback = NULL;\r
+ g->VUCallback = NULL;\r
+\r
+ memset(g->sourceDescription, '\000', sizeof(g->sourceDescription));\r
+\r
+ /* OGG Stuff */\r
+ g->oggflag = 1;\r
+ g->ice2songChange = false;\r
+ g->in_header = 0;\r
+\r
+ /* Resampler stuff */\r
+ g->initializedResampler = 0;\r
+\r
+ g->gLiveRecordingFlag = 0;\r
+\r
+ g->areLiveRecording = FALSE;\r
+\r
+ memset(g->gOggEncoderText, '\000', sizeof(g->gOggEncoderText));\r
+ g->gForceStop = 0;\r
+\r
+#ifdef HAVE_VORBIS\r
+ memset(&(g->vi), '\000', sizeof(g->vi));\r
+#endif\r
+ g->vuShow = 0;\r
+\r
+ g->ReconnectTrigger = 0;\r
+\r
+}\r
+\r
+char_t *getCurrentlyPlaying(edcastGlobals *g) {\r
+ return(g->gSongTitle);\r
+}\r
+\r
+int setCurrentSongTitle(edcastGlobals *g, char_t *song) {\r
+ char_t *pCurrent;\r
+ char_t modifiedSong[1024] = "";\r
+\r
+ if(g->gLockSongTitle) {\r
+ pCurrent = g->gManualSongTitle;\r
+ }\r
+ else {\r
+ pCurrent = song;\r
+ }\r
+\r
+ if(strcmp(g->gSongTitle, pCurrent)) {\r
+ strcpy(g->gSongTitle, pCurrent);\r
+ updateSongTitle(g, 0);\r
+ return 1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int setCurrentSongTitleURL(edcastGlobals *g, char_t *song) {\r
+ char_t *pCurrent;\r
+\r
+ if(g->gLockSongTitle) {\r
+ pCurrent = g->gManualSongTitle;\r
+ }\r
+ else {\r
+ pCurrent = song;\r
+ }\r
+\r
+ if(strcmp(g->gSongTitle, pCurrent)) {\r
+ strcpy(g->gSongTitle, pCurrent);\r
+ updateSongTitle(g, 0);\r
+ return 1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+void getCurrentSongTitle(edcastGlobals *g, char_t *song, char_t *artist, char_t *full) {\r
+ char_t songTitle[1024] = "";\r
+ char_t songTitle2[1024] = "";\r
+\r
+ memset(songTitle2, '\000', sizeof(songTitle2));\r
+\r
+ char_t *pCurrent;\r
+\r
+ if(g->gLockSongTitle) {\r
+ pCurrent = g->gManualSongTitle;\r
+ }\r
+ else {\r
+ pCurrent = g->gSongTitle;\r
+ }\r
+\r
+ strcpy(songTitle, pCurrent);\r
+\r
+ strcpy(full, songTitle);\r
+\r
+ char_t *p1 = strchr(songTitle, '-');\r
+\r
+ if(p1) {\r
+ if(*(p1 - 1) == ' ') {\r
+ p1--;\r
+ }\r
+\r
+ strncpy(artist, songTitle, p1 - songTitle);\r
+ p1 = strchr(songTitle, '-');\r
+ p1++;\r
+ if(*p1 == ' ') {\r
+ p1++;\r
+ }\r
+\r
+ strcpy(song, p1);\r
+ }\r
+ else {\r
+ strcpy(artist, "");\r
+ strcpy(song, songTitle);\r
+ }\r
+}\r
+\r
+void ReplaceString(char_t *source, char_t *dest, char_t *from, char_t *to) {\r
+ int loop = 1;\r
+ char_t *p2 = (char_t *) 1;\r
+ char_t *p1 = source;\r
+\r
+ while(p2) {\r
+ p2 = strstr(p1, from);\r
+ if(p2) {\r
+ strncat(dest, p1, p2 - p1);\r
+ strcat(dest, to);\r
+ p1 = p2 + strlen(from);\r
+ }\r
+ else {\r
+ strcat(dest, p1);\r
+ }\r
+ }\r
+}\r
+\r
+/*\r
+ =======================================================================================================================\r
+ This function URLencodes strings for use in sending them thru ;\r
+ the Shoutcast admin.cgi interface to update song titles..\r
+ =======================================================================================================================\r
+ */\r
+void URLize(char_t *input, char_t *output, int inputlen, int outputlen) {\r
+ ReplaceString(input, output, "%", "%25");\r
+ memset(input, '\000', inputlen);\r
+ ReplaceString(output, input, ";", "%3B");\r
+ memset(output, '\000', outputlen);\r
+ ReplaceString(input, output, "/", "%2F");\r
+ memset(input, '\000', inputlen);\r
+ ReplaceString(output, input, "?", "%3F");\r
+ memset(output, '\000', outputlen);\r
+ ReplaceString(input, output, ":", "%3A");\r
+ memset(input, '\000', inputlen);\r
+ ReplaceString(output, input, "@", "%40");\r
+ memset(output, '\000', outputlen);\r
+ ReplaceString(input, output, "&", "%26");\r
+ memset(input, '\000', inputlen);\r
+ ReplaceString(output, input, "=", "%3D");\r
+ memset(output, '\000', outputlen);\r
+ ReplaceString(input, output, "+", "%2B");\r
+ memset(input, '\000', inputlen);\r
+ ReplaceString(output, input, " ", "%20");\r
+ memset(output, '\000', outputlen);\r
+ ReplaceString(input, output, "\"", "%22");\r
+ memset(input, '\000', inputlen);\r
+ ReplaceString(output, input, "#", "%23");\r
+ memset(output, '\000', outputlen);\r
+ ReplaceString(input, output, "<", "%3C");\r
+ memset(input, '\000', inputlen);\r
+ ReplaceString(output, input, ">", "%3E");\r
+ memset(output, '\000', outputlen);\r
+ ReplaceString(input, output, "!", "%21");\r
+ memset(input, '\000', inputlen);\r
+ ReplaceString(output, input, "*", "%2A");\r
+ memset(output, '\000', outputlen);\r
+ ReplaceString(input, output, "'", "%27");\r
+ memset(input, '\000', inputlen);\r
+ ReplaceString(output, input, "(", "%28");\r
+ memset(output, '\000', outputlen);\r
+ ReplaceString(input, output, ")", "%29");\r
+ memset(input, '\000', inputlen);\r
+ ReplaceString(output, input, ",", "%2C");\r
+\r
+ memset(output, '\000', outputlen);\r
+ strcpy(output, input);\r
+}\r
+\r
+int updateSongTitle(edcastGlobals *g, int forceURL) {\r
+ char_t contentString[2056] = "";\r
+ char_t URLPassword[255] = "";\r
+ char_t URLSong[1024] = "";\r
+ char_t Song[1024] = "";\r
+\r
+ if(getIsConnected(g)) {\r
+ if((!g->gOggFlag) || (forceURL)) {\r
+ if((g->gSCFlag) || (g->gIcecastFlag) || (g->gIcecast2Flag) || forceURL) {\r
+ URLize(g->gPassword, URLPassword, sizeof(g->gPassword), sizeof(URLPassword));\r
+\r
+ strcpy(g->gCurrentSong, g->gSongTitle);\r
+\r
+ URLize(g->gCurrentSong, URLSong, sizeof(g->gSongTitle), sizeof(URLSong));\r
+\r
+ if(g->gIcecast2Flag) {\r
+ char_t userAuth[1024] = "";\r
+\r
+ sprintf(userAuth, "source:%s", g->gPassword);\r
+\r
+ char_t *puserAuthbase64 = util_base64_encode(userAuth);\r
+\r
+ if(puserAuthbase64) {\r
+ sprintf(contentString,\r
+ "GET /admin/metadata?pass=%s&mode=updinfo&mount=%s&song=%s HTTP/1.0\r\nAuthorization: Basic %s\r\nUser-Agent: (Mozilla Compatible)\r\n\r\n",\r
+ URLPassword,\r
+ g->gMountpoint,\r
+ URLSong,\r
+ puserAuthbase64);\r
+ free(puserAuthbase64);\r
+ }\r
+ }\r
+\r
+ if(g->gIcecastFlag) {\r
+ sprintf(contentString,\r
+ "GET /admin.cgi?pass=%s&mode=updinfo&mount=%s&song=%s HTTP/1.0\r\nUser-Agent: (Mozilla Compatible)\r\n\r\n",\r
+ URLPassword,\r
+ g->gMountpoint,\r
+ URLSong);\r
+ }\r
+\r
+ if(g->gSCFlag) {\r
+ sprintf(contentString,\r
+ "GET /admin.cgi?pass=%s&mode=updinfo&song=%s HTTP/1.0\r\nUser-Agent: (Mozilla Compatible)\r\n\r\n",\r
+ URLPassword,\r
+ URLSong);\r
+ }\r
+\r
+ g->gSCSocketControl = g->controlChannel.DoSocketConnect(g->gServer, atoi(g->gPort));\r
+ if(g->gSCSocketControl != -1) {\r
+ int sent = send(g->gSCSocketControl, contentString, strlen(contentString), 0);\r
+ //int sent = sendToServer(g, g->gSCSocketControl, contentString, strlen(contentString), HEADER_TYPE);\r
+\r
+ closesocket(g->gSCSocketControl);\r
+ }\r
+ else {\r
+ LogMessage(g,LOG_ERROR, "Cannot connect to server");\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ g->ice2songChange = true;\r
+ }\r
+ return 1;\r
+ }\r
+ return 0;\r
+}\r
+\r
+/*\r
+ =======================================================================================================================\r
+ This function does some magic in order to change the metadata ;\r
+ in a vorbis stream....Vakor helped me with this, and it's pretty ;\r
+ much all his idea anyway...and probably the reason why it actually ;\r
+ does work..:)\r
+ =======================================================================================================================\r
+ */\r
+void icecast2SendMetadata(edcastGlobals *g)\r
+{\r
+#ifdef HAVE_VORBIS\r
+ pthread_mutex_lock(&(g->mutex));\r
+ vorbis_analysis_wrote(&g->vd, 0);\r
+ ogg_encode_dataout(g);\r
+ initializeencoder(g);\r
+ pthread_mutex_unlock(&(g->mutex));\r
+#endif\r
+}\r
+\r
+\r
+#ifdef HAVE_FLAC\r
+extern "C" {\r
+FLAC__StreamEncoderWriteStatus FLACWriteCallback(\r
+ const FLAC__StreamEncoder *encoder,\r
+ const FLAC__byte buffer[],\r
+ unsigned bytes,\r
+ unsigned samples,\r
+ unsigned current_frame,\r
+ void *client_data\r
+ ) {\r
+ edcastGlobals *g = (edcastGlobals *) client_data;\r
+\r
+ int sentbytes = sendToServer(g, g->gSCSocket, (char_t *) buffer, bytes, CODEC_TYPE);\r
+\r
+ if(sentbytes < 0) {\r
+ g->flacFailure = 1;\r
+ }\r
+ else {\r
+ g->flacFailure = 0;\r
+ }\r
+\r
+ return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;\r
+}\r
+}\r
+extern "C" {\r
+void FLACMetadataCallback(const FLAC__StreamEncoder *encoder,\r
+ const FLAC__StreamMetadata *metadata, \r
+ void *client_data) {\r
+ edcastGlobals *g = (edcastGlobals *) client_data;\r
+\r
+ return;\r
+}\r
+}\r
+#endif\r
+\r
+/*\r
+ =======================================================================================================================\r
+ This function will disconnect the DSP from the server (duh)\r
+ =======================================================================================================================\r
+ */\r
+int disconnectFromServer(edcastGlobals *g) {\r
+ g->weareconnected = 0;\r
+\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (char_t *) "Disconnecting");\r
+ }\r
+\r
+ if(g->gCurrentlyEncoding)\r
+ {\r
+#ifdef WIN32\r
+ Sleep(1000);\r
+#else\r
+ sleep(1);\r
+#endif\r
+ }\r
+\r
+ /* Close all open sockets */\r
+ closesocket(g->gSCSocket);\r
+ closesocket(g->gSCSocketControl);\r
+\r
+ /*\r
+ * Reset the Status to Disconnected, and reenable the config ;\r
+ * button\r
+ */\r
+ g->gSCSocket = 0;\r
+ g->gSCSocketControl = 0;\r
+\r
+#ifdef HAVE_VORBIS\r
+ ogg_stream_clear(&g->os);\r
+ vorbis_block_clear(&g->vb);\r
+ vorbis_dsp_clear(&g->vd);\r
+ vorbis_info_clear(&g->vi);\r
+ memset(&(g->vi), '\000', sizeof(g->vi));\r
+#endif\r
+#ifdef HAVE_LAME\r
+#ifndef WIN32\r
+ if(g->gf) {\r
+ lame_close(g->gf);\r
+ g->gf = NULL;\r
+ }\r
+#endif\r
+#endif\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "Disconnected");\r
+ }\r
+\r
+ closeArchiveFile(g);\r
+\r
+ return 1;\r
+}\r
+\r
+/*\r
+ =======================================================================================================================\r
+ This funciton will connect to a server (Shoutcast/Icecast/Icecast2) ;\r
+ and send the appropriate password info and check to make sure things ;\r
+ are connected....\r
+ =======================================================================================================================\r
+ */\r
+int connectToServer(edcastGlobals *g) {\r
+ int s_socket = 0;\r
+ char_t buffer[1024] = "";\r
+ char_t contentString[1024] = "";\r
+ char_t brate[25] = "";\r
+ char_t ypbrate[25] = "";\r
+\r
+ LogMessage(g,LOG_DEBUG, "Connecting encoder %d", g->encoderNumber);\r
+\r
+ sprintf(brate, "%d", g->currentBitrate);\r
+\r
+ if(g->gOggFlag) {\r
+ if(!g->gOggBitQualFlag) {\r
+ sprintf(ypbrate, "Quality %s", g->gOggQuality);\r
+ }\r
+ else {\r
+ strcpy(ypbrate, brate);\r
+ }\r
+ }\r
+ else {\r
+ strcpy(ypbrate, brate);\r
+ }\r
+\r
+ g->gSCFlag = 0;\r
+\r
+ greconnectFlag = 0;\r
+\r
+ if(g->serverStatusCallback) {\r
+ \r
+ sprintf(buffer, "Connnecting to %s:%d", g->gServer, g->gPort);\r
+ g->serverStatusCallback(g, (void *) buffer);\r
+ }\r
+\r
+#ifdef WIN32\r
+ g->dataChannel.initWinsockLib();\r
+#endif\r
+\r
+ /* If we are Icecast/Icecast2, then connect to specified port */\r
+ if(g->gIcecastFlag || g->gIcecast2Flag) {\r
+ g->gSCSocket = g->dataChannel.DoSocketConnect(g->gServer, atoi(g->gPort));\r
+ }\r
+ else {\r
+\r
+ /*\r
+ * If we are Shoutcast, then the control socket (used for password) ;\r
+ * is port+1.\r
+ */\r
+ g->gSCSocket = g->dataChannel.DoSocketConnect(g->gServer, atoi(g->gPort) + 1);\r
+ }\r
+\r
+ /* Check to see if we connected okay */\r
+ if(g->gSCSocket == -1) {\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "Unable to connect to socket");\r
+ }\r
+\r
+ return 0;\r
+ }\r
+\r
+ int pswdok = 1;\r
+\r
+ /* Yup, we did. */\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "Socket connected");\r
+ }\r
+\r
+ char_t contentType[255] = "";\r
+\r
+ if(g->gOggFlag) {\r
+ strcpy(contentType, "application/ogg");\r
+ }\r
+ else {\r
+ if(g->gAACFlag) {\r
+ strcpy(contentType, "audio/aac");\r
+ }\r
+ else {\r
+ if(g->gAACPFlag) {\r
+ strcpy(contentType, "audio/aacp");\r
+ }\r
+ else {\r
+ if(g->gFLACFlag) {\r
+ strcpy(contentType, "application/ogg");\r
+ }\r
+ else {\r
+ strcpy(contentType, "audio/mpeg");\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ /*\r
+ * Here are all the variations of sending the password to ;\r
+ * a server..This if statement really is ugly...must fix.\r
+ */\r
+ if(g->gIcecastFlag || g->gIcecast2Flag) {\r
+\r
+ /* The Icecast/Icecast2 Way */\r
+ if(g->gIcecastFlag) {\r
+ sprintf(contentString,\r
+ "SOURCE %s %s\r\ncontent-type: %s\r\nx-audiocast-name: %s\r\nx-audiocast-url: %s\r\nx-audiocast-genre: %s\r\nx-audiocast-bitrate: %s\r\nx-audiocast-public: %d\r\nx-audiocast-description: %s\r\n\r\n",\r
+ g->gPassword,\r
+ g->gMountpoint,\r
+ contentType,\r
+ g->gServDesc,\r
+ g->gServURL,\r
+ g->gServGenre,\r
+ brate,\r
+ g->gPubServ,\r
+ g->gServDesc);\r
+ }\r
+\r
+ if(g->gIcecast2Flag) {\r
+ char_t audioInfo[1024] = "";\r
+\r
+ sprintf(audioInfo,\r
+ "ice-samplerate=%d;ice-bitrate=%s;ice-channels=%d",\r
+ getCurrentSamplerate(g),\r
+ ypbrate,\r
+ getCurrentChannels(g));\r
+\r
+ char_t userAuth[1024] = "";\r
+\r
+ sprintf(userAuth, "source:%s", g->gPassword);\r
+\r
+ char_t *puserAuthbase64 = util_base64_encode(userAuth);\r
+\r
+ if(puserAuthbase64) {\r
+ sprintf(contentString,\r
+ "SOURCE %s ICE/1.0\ncontent-type: %s\nAuthorization: Basic %s\nice-name: %s\nice-url: %s\nice-genre: %s\nice-bitrate: %s\nice-private: %d\nice-public: %d\nice-description: %s\nice-audio-info: %s\n\n",\r
+ g->gMountpoint,\r
+ contentType,\r
+ puserAuthbase64,\r
+ g->gServName,\r
+ g->gServURL,\r
+ g->gServGenre,\r
+ ypbrate,\r
+ !g->gPubServ,\r
+ g->gPubServ,\r
+ g->gServDesc,\r
+ audioInfo);\r
+ free(puserAuthbase64);\r
+ }\r
+ }\r
+ }\r
+ else {\r
+\r
+ /* The Shoutcast way */\r
+ sendToServer(g, g->gSCSocket, g->gPassword, strlen(g->gPassword), HEADER_TYPE);\r
+ sendToServer(g, g->gSCSocket, "\r\n", strlen("\r\n"), HEADER_TYPE);\r
+\r
+ recv(g->gSCSocket, buffer, sizeof(buffer), (int) 0);\r
+\r
+ /*\r
+ * if we get an OK, then we are not a Shoutcast server ;\r
+ * (could be live365 or other variant)..And OK2 means it's ;\r
+ * Shoutcast and we can safely send in metadata via the ;\r
+ * admin.cgi interface.\r
+ */\r
+ if(!strncmp(buffer, "OK", strlen("OK"))) {\r
+ if(!strncmp(buffer, "OK2", strlen("OK2"))) {\r
+ g->gSCFlag = 1;\r
+ }\r
+ else {\r
+ g->gSCFlag = 0;\r
+ }\r
+\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "Password OK");\r
+ }\r
+ }\r
+ else {\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "Password Failed");\r
+ }\r
+\r
+ closesocket(g->gSCSocket);\r
+ return 0;\r
+ }\r
+\r
+ memset(contentString, '\000', sizeof(contentString));\r
+ if(strlen(g->gServICQ) == 0) {\r
+ strcpy(g->gServICQ, "N/A");\r
+ }\r
+\r
+ if(strlen(g->gServAIM) == 0) {\r
+ strcpy(g->gServAIM, "N/A");\r
+ }\r
+\r
+ if(strlen(g->gServIRC) == 0) {\r
+ strcpy(g->gServIRC, "N/A");\r
+ }\r
+\r
+ sprintf(contentString,\r
+ "content-type:%s\r\nicy-name:%s\r\nicy-genre:%s\r\nicy-url:%s\r\nicy-pub:%d\r\nicy-irc:%s\r\nicy-icq:%s\r\nicy-aim:%s\r\nicy-br:%s\r\n\r\n",\r
+ contentType,\r
+ g->gServName,\r
+ g->gServGenre,\r
+ g->gServURL,\r
+ g->gPubServ,\r
+ g->gServIRC,\r
+ g->gServICQ,\r
+ g->gServAIM,\r
+ brate);\r
+ }\r
+\r
+ sendToServer(g, g->gSCSocket, contentString, strlen(contentString), HEADER_TYPE);\r
+\r
+ if(g->gIcecastFlag) {\r
+\r
+ /*\r
+ * Here we are checking the response from Icecast/Icecast2 ;\r
+ * from when we sent in the password...OK means we are good..if the ;\r
+ * password is bad, Icecast just disconnects the socket.\r
+ */\r
+ if(g->gOggFlag) {\r
+ recv(g->gSCSocket, buffer, sizeof(buffer), 0);\r
+ if(!strncmp(buffer, "OK", strlen("OK"))) {\r
+\r
+ /* I don't think this check is needed.. */\r
+ if(!strncmp(buffer, "OK2", strlen("OK2"))) {\r
+ g->gSCFlag = 1;\r
+ }\r
+ else {\r
+ g->gSCFlag = 0;\r
+ }\r
+\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "Password OK");\r
+ }\r
+ }\r
+ else {\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "Password Failed");\r
+ }\r
+\r
+ closesocket(g->gSCSocket);\r
+ return 0;\r
+ }\r
+ }\r
+ }\r
+\r
+ /* We are connected */\r
+ char_t outFilename[1024] = "";\r
+ char_t outputFile[1024] = "";\r
+ struct tm *newtime;\r
+ time_t aclock;\r
+\r
+ time(&aclock);\r
+ newtime = localtime(&aclock);\r
+\r
+ int ret = 0;\r
+\r
+ ret = initializeencoder(g);\r
+ g->forcedDisconnect = false;\r
+ if(ret) {\r
+ g->weareconnected = 1;\r
+ g->automaticconnect = 1;\r
+\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "Success");\r
+ }\r
+\r
+ /* Start up song title check */\r
+ }\r
+ else {\r
+ disconnectFromServer(g);\r
+ if(g->serverStatusCallback)\r
+ {\r
+#ifdef WIN32\r
+ if(g->gLAMEFlag) {\r
+ g->serverStatusCallback(g, (void *) "error with lame_enc.dll");\r
+ }\r
+ else {\r
+ if(g->gAACFlag) {\r
+ g->serverStatusCallback(g, (void *) "cannot find libfaac.dll");\r
+ }\r
+ else {\r
+ g->serverStatusCallback(g, (void *) "Encoder init failed");\r
+ }\r
+ }\r
+\r
+#else\r
+ g->serverStatusCallback(g, (void *) "Encoder init failed");\r
+#endif\r
+ }\r
+\r
+ return 0;\r
+ }\r
+\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "Connected");\r
+ }\r
+\r
+ setCurrentSongTitle(g, g->gSongTitle);\r
+ updateSongTitle(g, 0);\r
+ return 1;\r
+}\r
+\r
+/*\r
+ =======================================================================================================================\r
+ These are some ogg routines that are used for Icecast2\r
+ =======================================================================================================================\r
+ */\r
+int ogg_encode_dataout(edcastGlobals *g)\r
+{\r
+#ifdef HAVE_VORBIS\r
+ ogg_packet op;\r
+ ogg_page og;\r
+ int result;\r
+ int sentbytes = 0;\r
+\r
+ if(g->in_header) {\r
+ result = ogg_stream_flush(&g->os, &og);\r
+ g->in_header = 0;\r
+ }\r
+\r
+ while(vorbis_analysis_blockout(&g->vd, &g->vb) == 1) {\r
+ vorbis_analysis(&g->vb, NULL);\r
+ vorbis_bitrate_addblock(&g->vb);\r
+\r
+ int packetsdone = 0;\r
+\r
+ while(vorbis_bitrate_flushpacket(&g->vd, &op)) {\r
+\r
+ /* Add packet to bitstream */\r
+ ogg_stream_packetin(&g->os, &op);\r
+ packetsdone++;\r
+\r
+ /*\r
+ * If we've gone over a page boundary, we can do actual output, so do so (for\r
+ * however many pages are available)\r
+ */\r
+ int eos = 0;\r
+\r
+ while(!eos) {\r
+ int result = ogg_stream_pageout(&g->os, &og);\r
+\r
+ if(!result) break;\r
+\r
+ int ret = 0;\r
+\r
+ sentbytes = sendToServer(g, g->gSCSocket, (char_t *) og.header, og.header_len, CODEC_TYPE);\r
+ if(sentbytes < 0) {\r
+ return sentbytes;\r
+ }\r
+\r
+ sentbytes += sendToServer(g, g->gSCSocket, (char_t *) og.body, og.body_len, CODEC_TYPE);\r
+ if(sentbytes < 0) {\r
+ return sentbytes;\r
+ }\r
+\r
+ if(ogg_page_eos(&og)) {\r
+ eos = 1;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return sentbytes;\r
+#else\r
+ return 0;\r
+#endif\r
+}\r
+\r
+void oddsock_error_handler_function(const char_t *format, va_list ap) {\r
+ return;\r
+}\r
+\r
+int initializeResampler(edcastGlobals *g, long inSampleRate, long inNCH) {\r
+ if(!g->initializedResampler) {\r
+ long in_samplerate = inSampleRate;\r
+ long out_samplerate = getCurrentSamplerate(g);\r
+ long in_nch = inNCH;\r
+ long out_nch = 2;\r
+\r
+ if(res_init(&(g->resampler), out_nch, out_samplerate, in_samplerate, RES_END)) {\r
+ LogMessage(g,LOG_ERROR, "Error initializing resampler");\r
+ return 0;\r
+ }\r
+\r
+ g->initializedResampler = 1;\r
+ }\r
+\r
+ return 1;\r
+}\r
+\r
+int ocConvertAudio(edcastGlobals *g, float *in_samples, float *out_samples, int num_in_samples, int num_out_samples) {\r
+ int max_num_samples = res_push_max_input(&(g->resampler), num_out_samples);\r
+ int ret_samples = res_push_interleaved(&(g->resampler),\r
+ (SAMPLE *) out_samples,\r
+ (const SAMPLE *) in_samples,\r
+ max_num_samples);\r
+\r
+ return ret_samples;\r
+}\r
+\r
+int initializeencoder(edcastGlobals *g) {\r
+ int ret = 0;\r
+ char_t outFilename[1024] = "";\r
+ char_t message[1024] = "";\r
+\r
+ resetResampler(g);\r
+\r
+ if(g->gLAMEFlag)\r
+ {\r
+#ifdef HAVE_LAME\r
+#ifdef WIN32\r
+ BE_ERR err = 0;\r
+ BE_VERSION Version = { 0, };\r
+ BE_CONFIG beConfig = { 0, };\r
+\r
+ if(g->hDLL) {\r
+ FreeLibrary(g->hDLL);\r
+ }\r
+\r
+ g->hDLL = LoadLibrary("lame_enc.dll");\r
+\r
+ if(g->hDLL == NULL) {\r
+ sprintf(message,\r
+ "Unable to load DLL (lame_enc.dll)\nYou have selected encoding with LAME, but apparently the plugin cannot find LAME installed. Due to legal issues, \\r
+edcast cannot distribute LAME directly, and so you'll have to download it \\r
+separately. You will need to put the LAME DLL (lame_enc.dll) into the same directory as the application in order to get it working-> To download the LAME DLL, check \\r
+out http://www.mp3dev.org/mp3/");\r
+ LogMessage(g,LOG_ERROR, message);\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "can't find lame_enc.dll");\r
+ }\r
+\r
+ return 0;\r
+ }\r
+\r
+ /* Get Interface functions from the DLL */\r
+ g->beInitStream = (BEINITSTREAM) GetProcAddress(g->hDLL, TEXT_BEINITSTREAM);\r
+ g->beEncodeChunk = (BEENCODECHUNK) GetProcAddress(g->hDLL, TEXT_BEENCODECHUNK);\r
+ g->beDeinitStream = (BEDEINITSTREAM) GetProcAddress(g->hDLL, TEXT_BEDEINITSTREAM);\r
+ g->beCloseStream = (BECLOSESTREAM) GetProcAddress(g->hDLL, TEXT_BECLOSESTREAM);\r
+ g->beVersion = (BEVERSION) GetProcAddress(g->hDLL, TEXT_BEVERSION);\r
+ g->beWriteVBRHeader = (BEWRITEVBRHEADER) GetProcAddress(g->hDLL, TEXT_BEWRITEVBRHEADER);\r
+\r
+ if\r
+ (\r
+ !g->beInitStream\r
+ || !g->beEncodeChunk\r
+ || !g->beDeinitStream\r
+ || !g->beCloseStream\r
+ || !g->beVersion\r
+ || !g->beWriteVBRHeader\r
+ ) {\r
+ sprintf(message, "Unable to get LAME interfaces - This DLL (lame_enc.dll) doesn't appear to be LAME?!?!?");\r
+ LogMessage(g,LOG_ERROR, message);\r
+ return 0;\r
+ }\r
+\r
+ /* Get the version number */\r
+ g->beVersion(&Version);\r
+\r
+ if(Version.byMajorVersion < 3) {\r
+ sprintf(message,\r
+ "This version of edcast expects at least version 3.91 of the LAME DLL, the DLL found is at %u.%02u, please consider upgrading",\r
+ Version.byDLLMajorVersion,\r
+ Version.byDLLMinorVersion);\r
+ LogMessage(g,LOG_ERROR, message);\r
+ }\r
+ else {\r
+ if(Version.byMinorVersion < 91) {\r
+ sprintf(message,\r
+ "This version of edcast expects at least version 3.91 of the LAME DLL, the DLL found is at %u.%02u, please consider upgrading",\r
+ Version.byDLLMajorVersion,\r
+ Version.byDLLMinorVersion);\r
+ LogMessage(g,LOG_ERROR, message);\r
+ }\r
+ }\r
+\r
+ /* Check if all interfaces are present */\r
+ memset(&beConfig, 0, sizeof(beConfig)); /* clear all fields */\r
+\r
+ /* use the LAME config structure */\r
+ beConfig.dwConfig = BE_CONFIG_LAME;\r
+\r
+ if(g->currentChannels == 1) {\r
+ beConfig.format.LHV1.nMode = BE_MP3_MODE_MONO;\r
+ }\r
+ else {\r
+ if (g->LAMEJointStereoFlag) {\r
+ beConfig.format.LHV1.nMode = BE_MP3_MODE_JSTEREO;\r
+ }\r
+ else {\r
+ beConfig.format.LHV1.nMode = BE_MP3_MODE_STEREO;\r
+ }\r
+ }\r
+\r
+ /* this are the default settings for testcase.wav */\r
+ beConfig.format.LHV1.dwStructVersion = 1;\r
+ beConfig.format.LHV1.dwStructSize = sizeof(beConfig);\r
+ beConfig.format.LHV1.dwSampleRate = g->currentSamplerate; /* INPUT FREQUENCY */\r
+ beConfig.format.LHV1.dwReSampleRate = g->currentSamplerate; /* DON"T RESAMPLE */\r
+\r
+ /*\r
+ * beConfig.format.LHV1.dwReSampleRate = 0;\r
+ */\r
+ beConfig.format.LHV1.dwBitrate = g->currentBitrate; /* MINIMUM BIT RATE */\r
+ if(g->gLAMEpreset > 0) {\r
+ beConfig.format.LHV1.nPreset = g->gLAMEpreset;\r
+ }\r
+\r
+ beConfig.format.LHV1.dwMpegVersion = MPEG1; /* MPEG VERSION (I or II) */\r
+ beConfig.format.LHV1.dwPsyModel = 0; /* USE DEFAULT PSYCHOACOUSTIC MODEL */\r
+ beConfig.format.LHV1.dwEmphasis = 0; /* NO EMPHASIS TURNED ON */\r
+ beConfig.format.LHV1.bWriteVBRHeader = TRUE; /* YES, WRITE THE XING VBR HEADER */\r
+\r
+ if(g->gLAMEOptions.cbrflag) {\r
+ beConfig.format.LHV1.bEnableVBR = FALSE;\r
+ }\r
+ else {\r
+ beConfig.format.LHV1.bEnableVBR = TRUE;\r
+ beConfig.format.LHV1.dwMaxBitrate = g->currentBitrateMax;\r
+ beConfig.format.LHV1.dwBitrate = g->currentBitrate; /* MINIMUM BIT RATE */\r
+ }\r
+\r
+ beConfig.format.LHV1.nVBRQuality = g->gLAMEOptions.quality;\r
+\r
+ beConfig.format.LHV1.nVbrMethod = VBR_METHOD_DEFAULT;\r
+ if(!strcmp(g->gLAMEOptions.VBR_mode, "vbr_rh")) {\r
+ beConfig.format.LHV1.nVbrMethod = VBR_METHOD_OLD;\r
+ }\r
+\r
+ if(!strcmp(g->gLAMEOptions.VBR_mode, "vbr_mtrh")) {\r
+ beConfig.format.LHV1.nVbrMethod = VBR_METHOD_MTRH;\r
+ }\r
+\r
+ if(!strcmp(g->gLAMEOptions.VBR_mode, "vbr_abr")) {\r
+ beConfig.format.LHV1.nVbrMethod = VBR_METHOD_ABR;\r
+ }\r
+\r
+ beConfig.format.LHV1.bNoRes = TRUE; /* No Bit resorvoir */\r
+\r
+ err = g->beInitStream(&beConfig, &(g->dwSamples), &(g->dwMP3Buffer), &(g->hbeStream));\r
+\r
+ if(err != BE_ERR_SUCCESSFUL) {\r
+ sprintf(message, "Error opening encoding stream (%lu)", err);\r
+ LogMessage(g,LOG_ERROR, message);\r
+ return 0;\r
+ }\r
+\r
+#else\r
+ g->gf = lame_init();\r
+ lame_set_errorf(g->gf, oddsock_error_handler_function);\r
+ lame_set_debugf(g->gf, oddsock_error_handler_function);\r
+ lame_set_msgf(g->gf, oddsock_error_handler_function);\r
+\r
+ lame_set_brate(g->gf, g->currentBitrate);\r
+ lame_set_quality(g->gf, g->gLAMEOptions.quality);\r
+\r
+ lame_set_num_channels(g->gf, 2);\r
+\r
+ if(g->currentChannels == 1) {\r
+ lame_set_mode(g->gf, MONO);\r
+\r
+ /*\r
+ * lame_set_num_channels(g->gf, 1);\r
+ */\r
+ }\r
+ else {\r
+ lame_set_mode(g->gf, STEREO);\r
+ }\r
+\r
+ /*\r
+ * Make the input sample rate the same as output..i.e. don't make lame do ;\r
+ * any resampling->..cause we are handling it ourselves...\r
+ */\r
+ lame_set_in_samplerate(g->gf, g->currentSamplerate);\r
+ lame_set_out_samplerate(g->gf, g->currentSamplerate);\r
+ lame_set_copyright(g->gf, g->gLAMEOptions.copywrite);\r
+ lame_set_strict_ISO(g->gf, g->gLAMEOptions.strict_ISO);\r
+ lame_set_disable_reservoir(g->gf, g->gLAMEOptions.disable_reservoir);\r
+\r
+ if(!g->gLAMEOptions.cbrflag) {\r
+ if(!strcmp(g->gLAMEOptions.VBR_mode, "vbr_rh")) {\r
+ lame_set_VBR(g->gf, vbr_rh);\r
+ }\r
+\r
+ if(!strcmp(g->gLAMEOptions.VBR_mode, "vbr_mtrh")) {\r
+ lame_set_VBR(g->gf, vbr_mtrh);\r
+ }\r
+\r
+ if(!strcmp(g->gLAMEOptions.VBR_mode, "vbr_abr")) {\r
+ lame_set_VBR(g->gf, vbr_abr);\r
+ }\r
+\r
+ lame_set_VBR_mean_bitrate_kbps(g->gf, g->currentBitrate);\r
+ lame_set_VBR_min_bitrate_kbps(g->gf, g->currentBitrateMin);\r
+ lame_set_VBR_max_bitrate_kbps(g->gf, g->currentBitrateMax);\r
+ }\r
+\r
+ if(strlen(g->gLAMEbasicpreset) > 0) {\r
+ if(!strcmp(g->gLAMEbasicpreset, "r3mix")) {\r
+\r
+ /*\r
+ * presets_set_r3mix(g->gf, g->gLAMEbasicpreset, stdout);\r
+ */\r
+ }\r
+ else {\r
+\r
+ /*\r
+ * presets_set_basic(g->gf, g->gLAMEbasicpreset, stdout);\r
+ */\r
+ }\r
+ }\r
+\r
+ if(strlen(g->gLAMEaltpreset) > 0) {\r
+ int altbitrate = atoi(g->gLAMEaltpreset);\r
+\r
+ /*\r
+ * dm_presets(g->gf, 0, altbitrate, g->gLAMEaltpreset, "edcast");\r
+ */\r
+ }\r
+\r
+ /* do internal inits... */\r
+ lame_set_lowpassfreq(g->gf, g->gLAMEOptions.lowpassfreq);\r
+ lame_set_highpassfreq(g->gf, g->gLAMEOptions.highpassfreq);\r
+\r
+ int lame_ret = lame_init_params(g->gf);\r
+\r
+ if(lame_ret != 0) {\r
+ printf("Error initializing LAME");\r
+ }\r
+#endif\r
+#else\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "Not compiled with LAME support");\r
+ }\r
+\r
+ LogMessage(g,LOG_ERROR, "Not compiled with LAME support");\r
+ return 0;\r
+#endif\r
+ }\r
+\r
+ if(g->gAACFlag)\r
+ {\r
+#ifdef HAVE_FAAC\r
+ faacEncConfigurationPtr m_pConfig;\r
+\r
+#ifdef WIN32\r
+ g->hFAACDLL = LoadLibrary("libfaac.dll");\r
+ if(g->hFAACDLL == NULL) {\r
+ sprintf(message, "Unable to load AAC DLL (libfaac.dll)");\r
+ LogMessage(g,LOG_ERROR, message);\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "can't find libfaac.dll");\r
+ }\r
+\r
+ return 0;\r
+ }\r
+\r
+ FreeLibrary(g->hFAACDLL);\r
+#endif\r
+ if(g->aacEncoder) {\r
+ faacEncClose(g->aacEncoder);\r
+ g->aacEncoder = NULL;\r
+ }\r
+\r
+ g->aacEncoder = faacEncOpen(g->currentSamplerate, g->currentChannels, &g->samplesInput, &g->maxBytesOutput);\r
+\r
+ if(g->faacFIFO) {\r
+ free(g->faacFIFO);\r
+ }\r
+\r
+ g->faacFIFO = (float *) malloc(g->samplesInput * sizeof(float) * 16);\r
+ g->faacFIFOendpos = 0;\r
+\r
+ m_pConfig = faacEncGetCurrentConfiguration(g->aacEncoder);\r
+\r
+ m_pConfig->mpegVersion = MPEG2;\r
+\r
+ m_pConfig->quantqual = atoi(g->gAACQuality);\r
+\r
+ int cutoff = atoi(g->gAACCutoff);\r
+\r
+ if(cutoff > 0) {\r
+ m_pConfig->bandWidth = cutoff;\r
+ }\r
+\r
+ /*\r
+ * m_pConfig->bitRate = (g->currentBitrate * 1000) / g->currentChannels;\r
+ */\r
+ m_pConfig->allowMidside = 1;\r
+ m_pConfig->useLfe = 0;\r
+ m_pConfig->useTns = 1;\r
+ m_pConfig->aacObjectType = LOW;\r
+ m_pConfig->outputFormat = 1;\r
+ m_pConfig->inputFormat = FAAC_INPUT_FLOAT;\r
+\r
+ /* set new config */\r
+ faacEncSetConfiguration(g->aacEncoder, m_pConfig);\r
+#else\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "Not compiled with AAC support");\r
+ }\r
+\r
+ LogMessage(g,LOG_ERROR, "Not compiled with AAC support");\r
+ return 0;\r
+#endif\r
+ }\r
+\r
+ if(g->gAACPFlag)\r
+ {\r
+#ifdef HAVE_AACP\r
+\r
+#ifdef WIN32\r
+ g->hAACPDLL = LoadLibrary("enc_aacplus.dll");\r
+ if(g->hAACPDLL == NULL) {\r
+ g->hAACPDLL = LoadLibrary("plugins\\enc_aacplus.dll");\r
+ }\r
+\r
+ if(g->hAACPDLL == NULL) {\r
+ sprintf(message, "Unable to load AAC Plus DLL (enc_aacplus.dll)");\r
+ LogMessage(g,LOG_ERROR, message);\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "can't find enc_aacplus.dll");\r
+ }\r
+\r
+ return 0;\r
+ }\r
+\r
+ g->CreateAudio3 = (CREATEAUDIO3TYPE) GetProcAddress(g->hAACPDLL, "CreateAudio3");\r
+ if(!g->CreateAudio3) {\r
+ sprintf(message, "Invalid DLL (enc_aacplus.dll)");\r
+ LogMessage(g,LOG_ERROR, message);\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "invalid enc_aacplus.dll");\r
+ }\r
+\r
+ return 0;\r
+ }\r
+\r
+ g->GetAudioTypes3 = (GETAUDIOTYPES3TYPE) GetProcAddress(g->hAACPDLL, "GetAudioTypes3");\r
+ *(void **) &(g->finishAudio3) = (void *) GetProcAddress(g->hAACPDLL, "FinishAudio3");\r
+ *(void **) &(g->PrepareToFinish) = (void *) GetProcAddress(g->hAACPDLL, "PrepareToFinish");\r
+\r
+ /*\r
+ * FreeLibrary(g->hAACPDLL);\r
+ */\r
+#endif\r
+ if(g->aacpEncoder) {\r
+ delete g->aacpEncoder;\r
+ g->aacpEncoder = NULL;\r
+ }\r
+\r
+ unsigned int outt = 1346584897;\r
+ char_t *conf_file = "edcast_aacp.ini"; /* Default ini file */\r
+\r
+ /* 1 - Mono 2 - Stereo 3 - Stereo Independent 4 - Parametric 5 - Dual Channel */\r
+ char_t sampleRate[255] = "";\r
+ char_t channelMode[255] = "";\r
+ char_t bitrateValue[255] = "";\r
+ char_t aacpV2Enable[255] = "1";\r
+ long bitrateLong = g->currentBitrate * 1000;\r
+\r
+ sprintf(bitrateValue, "%d", bitrateLong);\r
+ if(bitrateLong >= 64000) {\r
+ if(g->currentChannels == 2) {\r
+ strcpy(channelMode, "2");\r
+ }\r
+ else {\r
+ strcpy(channelMode, "1");\r
+ }\r
+ }\r
+\r
+ if((bitrateLong <= 48000) && (bitrateLong >= 16000)) {\r
+ if(g->currentChannels == 2) {\r
+ strcpy(channelMode, "4");\r
+ }\r
+ else {\r
+ strcpy(channelMode, "1");\r
+ }\r
+ }\r
+\r
+ if(bitrateLong <= 12000) {\r
+ strcpy(channelMode, "1");\r
+ }\r
+\r
+ sprintf(sampleRate, "%d", g->currentSamplerate);\r
+\r
+ WritePrivateProfileString("audio_aacplus", "samplerate", sampleRate, conf_file);\r
+ WritePrivateProfileString("audio_aacplus", "channelmode", channelMode, conf_file);\r
+ WritePrivateProfileString("audio_aacplus", "bitrate", bitrateValue, conf_file);\r
+ WritePrivateProfileString("audio_aacplus", "v2enable", aacpV2Enable, conf_file);\r
+ WritePrivateProfileString("audio_aacplus", "bitstream", "0", conf_file);\r
+ WritePrivateProfileString("audio_aacplus", "nsignallingmode", "0", conf_file);\r
+\r
+ g->aacpEncoder = g->CreateAudio3((int) g->currentChannels,\r
+ (int) g->currentSamplerate,\r
+ 16,\r
+ mmioFOURCC('P', 'C', 'M', ' '),\r
+ &outt,\r
+ conf_file);\r
+ if(!g->aacpEncoder) {\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "Invalid AAC+ settings");\r
+ }\r
+\r
+ LogMessage(g,LOG_ERROR, "Invalid AAC+ settings");\r
+ return 0;\r
+ }\r
+\r
+#else\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "Not compiled with AAC Plus support");\r
+ }\r
+\r
+ LogMessage(g,LOG_ERROR, "Not compiled with AAC Plus support");\r
+ return 0;\r
+#endif\r
+ }\r
+\r
+ if(g->gOggFlag)\r
+ {\r
+#ifdef HAVE_VORBIS\r
+ /* Ogg Vorbis Initialization */\r
+ ogg_stream_clear(&g->os);\r
+ vorbis_block_clear(&g->vb);\r
+ vorbis_dsp_clear(&g->vd);\r
+ vorbis_info_clear(&g->vi);\r
+\r
+ int bitrate = 0;\r
+\r
+ vorbis_info_init(&g->vi);\r
+\r
+ int encode_ret = 0;\r
+\r
+ if(!g->gOggBitQualFlag) {\r
+ encode_ret = vorbis_encode_setup_vbr(&g->vi,\r
+ g->currentChannels,\r
+ g->currentSamplerate,\r
+ ((float) atof(g->gOggQuality) * (float) .1));\r
+ if(encode_ret) {\r
+ vorbis_info_clear(&g->vi);\r
+ }\r
+ }\r
+ else {\r
+ int maxbit = -1;\r
+ int minbit = -1;\r
+\r
+ if(g->currentBitrateMax > 0) {\r
+ maxbit = g->currentBitrateMax;\r
+ }\r
+\r
+ if(g->currentBitrateMin > 0) {\r
+ minbit = g->currentBitrateMin;\r
+ }\r
+\r
+ encode_ret = vorbis_encode_setup_managed(&g->vi,\r
+ g->currentChannels,\r
+ g->currentSamplerate,\r
+ g->currentBitrate * 1000,\r
+ g->currentBitrate * 1000,\r
+ g->currentBitrate * 1000);\r
+\r
+ if(encode_ret) {\r
+ vorbis_info_clear(&g->vi);\r
+ }\r
+ }\r
+\r
+ if(encode_ret == OV_EIMPL) {\r
+ LogMessage(g,LOG_ERROR, "Sorry, but this vorbis mode is not supported currently...");\r
+ return 0;\r
+ }\r
+\r
+ if(encode_ret == OV_EINVAL) {\r
+ LogMessage(g,LOG_ERROR, "Sorry, but this is an illegal vorbis mode...");\r
+ return 0;\r
+ }\r
+\r
+ ret = vorbis_encode_setup_init(&g->vi);\r
+\r
+ /*\r
+ * Now, set up the analysis engine, stream encoder, and other preparation before\r
+ * the encoding begins\r
+ */\r
+ ret = vorbis_analysis_init(&g->vd, &g->vi);\r
+ ret = vorbis_block_init(&g->vd, &g->vb);\r
+\r
+ g->serialno = 0;\r
+ srand(time(0));\r
+ ret = ogg_stream_init(&g->os, rand());\r
+\r
+ /*\r
+ * Now, build the three header packets and send through to the stream output stage\r
+ * (but defer actual file output until the main encode loop)\r
+ */\r
+ ogg_packet header_main;\r
+ ogg_packet header_comments;\r
+ ogg_packet header_codebooks;\r
+ vorbis_comment vc;\r
+ char_t title[1024] = "";\r
+ char_t artist[1024] = "";\r
+ char_t FullTitle[1024] = "";\r
+ char_t SongTitle[1024] = "";\r
+ char_t Artist[1024] = "";\r
+ char_t Streamed[1024] = "";\r
+ wchar_t widestring[4096];\r
+ char tempstring[4096];\r
+\r
+ memset(Artist, '\000', sizeof(Artist));\r
+ memset(SongTitle, '\000', sizeof(SongTitle));\r
+ memset(FullTitle, '\000', sizeof(FullTitle));\r
+ memset(Streamed, '\000', sizeof(Streamed));\r
+\r
+ vorbis_comment_init(&vc);\r
+\r
+ bool bypass = false;\r
+\r
+ if(!getLockedMetadataFlag(g)) {\r
+ if(g->numVorbisComments) {\r
+ for(int i = 0; i < g->numVorbisComments; i++)\r
+ {\r
+#ifdef WIN32\r
+ MultiByteToWideChar(CP_ACP,\r
+ 0,\r
+ g->vorbisComments[i],\r
+ strlen(g->vorbisComments[i]) + 1,\r
+ widestring,\r
+ 4096);\r
+ memset(tempstring, '\000', sizeof(tempstring));\r
+ WideCharToMultiByte(CP_UTF8,\r
+ 0,\r
+ widestring,\r
+ wcslen(widestring) + 1,\r
+ tempstring,\r
+ sizeof(tempstring),\r
+ 0,\r
+ NULL);\r
+ vorbis_comment_add(&vc, tempstring);\r
+#else\r
+ vorbis_comment_add(&vc, g->vorbisComments[i]);\r
+#endif\r
+ }\r
+\r
+ bypass = true;\r
+ }\r
+ }\r
+\r
+ if(!bypass) {\r
+ getCurrentSongTitle(g, SongTitle, Artist, FullTitle);\r
+ if((strlen(SongTitle) == 0) && (strlen(Artist) == 0)) {\r
+ sprintf(title, "TITLE=%s", FullTitle);\r
+ }\r
+ else {\r
+ sprintf(title, "TITLE=%s", SongTitle);\r
+ }\r
+\r
+#ifdef WIN32\r
+ MultiByteToWideChar(CP_ACP, 0, title, strlen(title) + 1, widestring, 4096);\r
+ memset(tempstring, '\000', sizeof(tempstring));\r
+ WideCharToMultiByte(CP_UTF8,\r
+ 0,\r
+ widestring,\r
+ wcslen(widestring) + 1,\r
+ tempstring,\r
+ sizeof(tempstring),\r
+ 0,\r
+ NULL);\r
+ vorbis_comment_add(&vc, tempstring);\r
+#else\r
+ vorbis_comment_add(&vc, title);\r
+#endif\r
+ sprintf(artist, "ARTIST=%s", Artist);\r
+#ifdef WIN32\r
+ MultiByteToWideChar(CP_ACP, 0, artist, strlen(artist) + 1, widestring, 4096);\r
+ memset(tempstring, '\000', sizeof(tempstring));\r
+ WideCharToMultiByte(CP_UTF8,\r
+ 0,\r
+ widestring,\r
+ wcslen(widestring) + 1,\r
+ tempstring,\r
+ sizeof(tempstring),\r
+ 0,\r
+ NULL);\r
+ vorbis_comment_add(&vc, tempstring);\r
+#else\r
+ vorbis_comment_add(&vc, artist);\r
+#endif\r
+ }\r
+\r
+ sprintf(Streamed, "ENCODEDBY=edcast");\r
+ vorbis_comment_add(&vc, Streamed);\r
+ if(strlen(g->sourceDescription) > 0) {\r
+ sprintf(Streamed, "TRANSCODEDFROM=%s", g->sourceDescription);\r
+ vorbis_comment_add(&vc, Streamed);\r
+ }\r
+\r
+ /* Build the packets */\r
+ memset(&header_main, '\000', sizeof(header_main));\r
+ memset(&header_comments, '\000', sizeof(header_comments));\r
+ memset(&header_codebooks, '\000', sizeof(header_codebooks));\r
+\r
+ vorbis_analysis_headerout(&g->vd, &vc, &header_main, &header_comments, &header_codebooks);\r
+\r
+ ogg_stream_packetin(&g->os, &header_main);\r
+ ogg_stream_packetin(&g->os, &header_comments);\r
+ ogg_stream_packetin(&g->os, &header_codebooks);\r
+\r
+ g->in_header = 1;\r
+\r
+ ogg_page og;\r
+ int eos = 0;\r
+ int sentbytes = 0;\r
+ int ret = 0;\r
+\r
+ while(!eos) {\r
+ int result = ogg_stream_flush(&g->os, &og);\r
+\r
+ if(result == 0) break;\r
+ sentbytes += sendToServer(g, g->gSCSocket, (char *) og.header, og.header_len, CODEC_TYPE);\r
+ sentbytes += sendToServer(g, g->gSCSocket, (char *) og.body, og.body_len, CODEC_TYPE);\r
+ }\r
+\r
+ vorbis_comment_clear(&vc);\r
+ if(g->numVorbisComments) {\r
+ freeVorbisComments(g);\r
+ }\r
+\r
+#else\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "Not compiled with Ogg Vorbis support");\r
+ }\r
+\r
+ LogMessage(g,LOG_ERROR, "Not compiled with Ogg Vorbis support");\r
+ return 0;\r
+#endif\r
+ }\r
+\r
+ if(g->gFLACFlag)\r
+ {\r
+#ifdef HAVE_FLAC\r
+ char FullTitle[1024] = "";\r
+ char SongTitle[1024] = "";\r
+ char Artist[1024] = "";\r
+ char Streamed[1024] = "";\r
+\r
+ memset(Artist, '\000', sizeof(Artist));\r
+ memset(SongTitle, '\000', sizeof(SongTitle));\r
+ memset(FullTitle, '\000', sizeof(FullTitle));\r
+ memset(Streamed, '\000', sizeof(Streamed));\r
+\r
+ if(g->flacEncoder) {\r
+ FLAC__stream_encoder_finish(g->flacEncoder);\r
+ FLAC__stream_encoder_delete(g->flacEncoder);\r
+ FLAC__metadata_object_delete(g->flacMetadata);\r
+ g->flacEncoder = NULL;\r
+ g->flacMetadata = NULL;\r
+ }\r
+\r
+ g->flacEncoder = FLAC__stream_encoder_new();\r
+ g->flacMetadata = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);\r
+\r
+ FLAC__stream_encoder_set_streamable_subset(g->flacEncoder, false);\r
+// FLAC__stream_encoder_set_client_data(g->flacEncoder, (void*)g);\r
+\r
+ FLAC__stream_encoder_set_channels(g->flacEncoder, g->currentChannels);\r
+\r
+ \r
+/*\r
+ FLAC__stream_encoder_set_write_callback(g->flacEncoder,(FLAC__StreamEncoderWriteCallback) FLACWriteCallback,\r
+ (FLAC__StreamEncoderWriteCallback) FLACWriteCallback);\r
+ FLAC__stream_encoder_set_metadata_callback(g->flacEncoder,\r
+ (FLAC__StreamEncoderMetadataCallback) FLACMetadataCallback);\r
+ */\r
+ srand(time(0));\r
+\r
+\r
+ if(!getLockedMetadataFlag(g)) {\r
+ FLAC__StreamMetadata_VorbisComment_Entry entry;\r
+ FLAC__StreamMetadata_VorbisComment_Entry entry3;\r
+ FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "ENCODEDBY", "edcast");\r
+ FLAC__metadata_object_vorbiscomment_append_comment(g->flacMetadata, entry, true);\r
+ if(strlen(g->sourceDescription) > 0) {\r
+ FLAC__StreamMetadata_VorbisComment_Entry entry2;\r
+ FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry2, "TRANSCODEDFROM", g->sourceDescription);\r
+ FLAC__metadata_object_vorbiscomment_append_comment(g->flacMetadata, entry2, true);\r
+ }\r
+ getCurrentSongTitle(g, SongTitle, Artist, FullTitle);\r
+ FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry3, "TITLE", FullTitle);\r
+ FLAC__metadata_object_vorbiscomment_append_comment(g->flacMetadata, entry3, true);\r
+\r
+ }\r
+ FLAC__stream_encoder_set_ogg_serial_number(g->flacEncoder, rand());\r
+\r
+ FLAC__StreamEncoderInitStatus ret = FLAC__stream_encoder_init_ogg_stream(g->flacEncoder, NULL, (FLAC__StreamEncoderWriteCallback) FLACWriteCallback, NULL, NULL, (FLAC__StreamEncoderMetadataCallback) FLACMetadataCallback, (void*)g);\r
+ if(ret == FLAC__STREAM_ENCODER_INIT_STATUS_OK) {\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "FLAC initialized");\r
+ }\r
+ }\r
+ else {\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "Error Initializing FLAC");\r
+ }\r
+\r
+ LogMessage(g,LOG_ERROR, "Error Initializing FLAC");\r
+ return 0;\r
+ }\r
+#endif\r
+ }\r
+\r
+ return 1;\r
+}\r
+\r
+void addToFIFO(edcastGlobals *g, float *samples, int numsamples) {\r
+ int currentFIFO = g->faacFIFOendpos;\r
+\r
+ for(int i = 0; i < numsamples; i++) {\r
+ g->faacFIFO[currentFIFO] = samples[i];\r
+ currentFIFO++;\r
+ }\r
+\r
+ g->faacFIFOendpos = currentFIFO;\r
+}\r
+\r
+void FloatScale(float *destination, float *source, int numsamples, int destchannels) {\r
+ int i;\r
+\r
+ if(destchannels == 2) {\r
+ for(i = 0; i < numsamples; i++) {\r
+ *destination++ = *source++ *32767.f;\r
+ }\r
+ }\r
+ else {\r
+ for(i = 0; i < numsamples >> 1; i++) {\r
+ *destination++ = (*source++ +*source++) * 16383.f;\r
+ }\r
+ }\r
+}\r
+\r
+void ExtractFromFIFO(float *destination, float *source, int numsamples) {\r
+ for(int i = 0; i < numsamples; i++) {\r
+ *destination++ = *source++;\r
+ }\r
+}\r
+\r
+int do_encoding(edcastGlobals *g, float *samples, int numsamples, int nch) {\r
+ g->gCurrentlyEncoding = 1;\r
+\r
+ int s;\r
+ int count = 0;\r
+ unsigned char mp3buffer[LAME_MAXMP3BUFFER];\r
+ int imp3;\r
+ short int *int_samples;\r
+ int eos = 0;\r
+ int ret = 0;\r
+ int sentbytes = 0;\r
+ char buf[255] = "";\r
+\r
+ g->gCurrentlyEncoding = 1;\r
+\r
+ if(g->weareconnected) {\r
+ s = numsamples * nch;\r
+\r
+ long leftMax = 0;\r
+ long rightMax = 0;\r
+ int samplecounter = 0;\r
+\r
+ LogMessage(g,LOG_DEBUG, "determining left/right max...");\r
+ for(int i = 0; i < numsamples * 2; i = i + 2) {\r
+ leftMax += abs((int) ((float) samples[i] * 32767.f));\r
+ rightMax += abs((int) ((float) samples[i + 1] * 32767.f));\r
+ }\r
+\r
+ if(numsamples > 0) {\r
+ leftMax = leftMax / (numsamples * 2);\r
+ rightMax = rightMax / (numsamples * 2);\r
+ if(g->VUCallback) {\r
+ g->VUCallback(leftMax, rightMax);\r
+ }\r
+ }\r
+\r
+ if(g->gOggFlag)\r
+ {\r
+#ifdef HAVE_VORBIS\r
+ /*\r
+ * If a song change was detected, close the stream and resend new ;\r
+ * vorbis headers (with new comments) - all done by icecast2SendMetadata();\r
+ */\r
+ if(g->ice2songChange) {\r
+ LogMessage(g,LOG_DEBUG, "Song change processing...");\r
+ g->ice2songChange = false;\r
+ icecast2SendMetadata(g);\r
+ }\r
+\r
+ LogMessage(g,LOG_DEBUG, "vorbis_analysis_buffer...");\r
+\r
+ float **buffer = vorbis_analysis_buffer(&g->vd, numsamples);\r
+ int samplecount = 0;\r
+ int i;\r
+\r
+ samplecounter = 0;\r
+\r
+ for(i = 0; i < numsamples * 2; i = i + 2) {\r
+ buffer[0][samplecounter] = samples[i];\r
+ if(g->currentChannels == 2) {\r
+ buffer[1][samplecounter] = samples[i + 1];\r
+ }\r
+\r
+ samplecounter++;\r
+ }\r
+ LogMessage(g,LOG_DEBUG, "vorbis_analysis_wrote...");\r
+\r
+ ret = vorbis_analysis_wrote(&g->vd, numsamples);\r
+\r
+ pthread_mutex_lock(&(g->mutex));\r
+ LogMessage(g,LOG_DEBUG, "ogg_encode_dataout...");\r
+ /* Stream out what we just prepared for Vorbis... */\r
+ sentbytes = ogg_encode_dataout(g);\r
+ LogMessage(g,LOG_DEBUG, "done ogg_ecndoe_dataout...");\r
+ pthread_mutex_unlock(&(g->mutex));\r
+#endif\r
+ }\r
+\r
+ if(g->gAACFlag)\r
+ {\r
+#ifdef HAVE_FAAC\r
+ float *buffer = (float *) malloc(numsamples * 2 * sizeof(float));\r
+ FloatScale(buffer, samples, numsamples * 2, g->currentChannels);\r
+\r
+ addToFIFO(g, buffer, numsamples * g->currentChannels);\r
+\r
+ while(g->faacFIFOendpos > (int)g->samplesInput) {\r
+ float *buffer2 = (float *) malloc(g->samplesInput * 2 * sizeof(float));\r
+\r
+ ExtractFromFIFO(buffer2, g->faacFIFO, g->samplesInput);\r
+\r
+ int counter = 0;\r
+\r
+ for(int i = g->samplesInput; i < g->faacFIFOendpos; i++) {\r
+ g->faacFIFO[counter] = g->faacFIFO[i];\r
+ counter++;\r
+ }\r
+\r
+ g->faacFIFOendpos = counter;\r
+\r
+ unsigned long dwWrite = 0;\r
+ unsigned char *aacbuffer = (unsigned char *) malloc(g->maxBytesOutput);\r
+\r
+ imp3 = faacEncEncode(g->aacEncoder, (int32_t *) buffer2, g->samplesInput, aacbuffer, g->maxBytesOutput);\r
+\r
+ if(imp3) {\r
+ sentbytes = sendToServer(g, g->gSCSocket, (char *) aacbuffer, imp3, CODEC_TYPE);\r
+ }\r
+\r
+ if(buffer2) {\r
+ free(buffer2);\r
+ }\r
+\r
+ if(aacbuffer) {\r
+ free(aacbuffer);\r
+ }\r
+ }\r
+\r
+ if(buffer) {\r
+ free(buffer);\r
+ }\r
+#endif\r
+ }\r
+\r
+ if(g->gAACPFlag)\r
+ {\r
+#ifdef HAVE_AACP\r
+ static char outbuffer[32768];\r
+ static char inbuffer[32768];\r
+ static int inbufferused = 0;\r
+ int len = numsamples * g->currentChannels * sizeof(short);\r
+\r
+ int_samples = (short *) malloc(len);\r
+\r
+ int samplecount = 0;\r
+\r
+ if(g->currentChannels == 1) {\r
+ for(int i = 0; i < numsamples * 2; i = i + 2) {\r
+ int_samples[samplecount] = (short int) (samples[i] * 32767.0);\r
+ samplecount++;\r
+ }\r
+ }\r
+ else {\r
+ for(int i = 0; i < numsamples * 2; i++) {\r
+ int_samples[i] = (short int) (samples[i] * 32767.0);\r
+ samplecount++;\r
+ }\r
+ }\r
+\r
+ char *bufcounter = (char *) int_samples;\r
+\r
+ for(;;) {\r
+ int in_used = 0;\r
+\r
+ if(len <= 0) break;\r
+\r
+ int enclen = g->aacpEncoder->Encode(in_used, bufcounter, len, &in_used, outbuffer, sizeof(outbuffer));\r
+\r
+ if(enclen > 0) {\r
+ sentbytes = sendToServer(g, g->gSCSocket, (char *) outbuffer, enclen, CODEC_TYPE);\r
+ }\r
+ else {\r
+ break;\r
+ }\r
+\r
+ if(in_used > 0) {\r
+ bufcounter += in_used;\r
+ len -= in_used;\r
+ }\r
+ }\r
+\r
+ if(int_samples) {\r
+ free(int_samples);\r
+ }\r
+#endif\r
+ }\r
+\r
+ if(g->gLAMEFlag)\r
+ {\r
+#ifdef HAVE_LAME\r
+ /* Lame encoding is simple, we are passing it interleaved samples */\r
+ int_samples = (short int *) malloc(numsamples * 2 * sizeof(short int));\r
+\r
+ int samplecount = 0;\r
+\r
+ if(g->currentChannels == 1) {\r
+ for(int i = 0; i < numsamples * 2; i = i + 2) {\r
+ int_samples[samplecount] = (int) (samples[i] * 32767.0);\r
+ samplecount++;\r
+ }\r
+ }\r
+ else {\r
+ for(int i = 0; i < numsamples * 2; i++) {\r
+ int_samples[i] = (int) (samples[i] * 32767.0);\r
+ samplecount++;\r
+ }\r
+ }\r
+\r
+#ifdef WIN32\r
+ unsigned long dwWrite = 0;\r
+ int err = g->beEncodeChunk(g->hbeStream,\r
+ samplecount,\r
+ (short *) int_samples,\r
+ (PBYTE) mp3buffer,\r
+ &dwWrite);\r
+\r
+ imp3 = dwWrite;\r
+#else\r
+ float *samples_left;\r
+ float *samples_right;\r
+\r
+ samples_left = (float *) malloc(numsamples * (sizeof(float)));\r
+ samples_right = (float *) malloc(numsamples * (sizeof(float)));\r
+\r
+ for(int i = 0; i < numsamples; i++) {\r
+ samples_left[i] = samples[2 * i] * 32767.0;\r
+ samples_right[i] = samples[2 * i + 1] * 32767.0;\r
+ }\r
+\r
+ imp3 = lame_encode_buffer_float(g->gf,\r
+ (float *) samples_left,\r
+ (float *) samples_right,\r
+ numsamples,\r
+ mp3buffer,\r
+ sizeof(mp3buffer));\r
+ if(samples_left) {\r
+ free(samples_left);\r
+ }\r
+\r
+ if(samples_right) {\r
+ free(samples_right);\r
+ }\r
+#endif\r
+ if(int_samples) {\r
+ free(int_samples);\r
+ }\r
+\r
+ if(imp3 == -1) {\r
+ LogMessage(g,LOG_ERROR, "mp3 buffer is not big enough!");\r
+ return -1;\r
+ }\r
+\r
+ /* Send out the encoded buffer */\r
+ sentbytes = sendToServer(g, g->gSCSocket, (char *) mp3buffer, imp3, CODEC_TYPE);\r
+#endif\r
+ }\r
+\r
+ if(g->gFLACFlag)\r
+ {\r
+#ifdef HAVE_FLAC\r
+ INT32 *int32_samples;\r
+\r
+ int32_samples = (INT32 *) malloc(numsamples * 2 * sizeof(INT32));\r
+\r
+ int samplecount = 0;\r
+\r
+ if(g->currentChannels == 1) {\r
+ for(int i = 0; i < numsamples * 2; i = i + 2) {\r
+ int32_samples[samplecount] = (INT32) (samples[i] * 32767.0);\r
+ samplecount++;\r
+ }\r
+ }\r
+ else {\r
+ for(int i = 0; i < numsamples * 2; i++) {\r
+ int32_samples[i] = (INT32) (samples[i] * 32767.0);\r
+ samplecount++;\r
+ }\r
+ }\r
+\r
+ FLAC__stream_encoder_process_interleaved(g->flacEncoder, int32_samples, numsamples);\r
+\r
+ if(int32_samples) {\r
+ free(int32_samples);\r
+ }\r
+\r
+ if(g->flacFailure) {\r
+ sentbytes = 0;\r
+ }\r
+ else {\r
+ sentbytes = 1;\r
+ }\r
+#endif\r
+ }\r
+\r
+ /*\r
+ * Generic error checking, if there are any socket problems, the trigger ;\r
+ * a disconnection handling->..\r
+ */\r
+ if(sentbytes < 0) {\r
+ int rret = triggerDisconnect(g);\r
+ if (rret == 0) {\r
+ return 0;\r
+ }\r
+ }\r
+ }\r
+\r
+ g->gCurrentlyEncoding = 0;\r
+ return 1;\r
+}\r
+\r
+int triggerDisconnect(edcastGlobals *g) {\r
+ char buf[2046] = "";\r
+\r
+ disconnectFromServer(g);\r
+ if(g->gForceStop) {\r
+ g->gForceStop = 0;\r
+ return 0;\r
+ }\r
+\r
+\r
+ sprintf(buf, "Disconnected from server");\r
+ g->forcedDisconnect = true;\r
+ g->forcedDisconnectSecs = time(&(g->forcedDisconnectSecs));\r
+ g->serverStatusCallback(g, (void *) buf);\r
+ return 1;\r
+}\r
+void config_read(edcastGlobals *g) {\r
+ strcpy(g->gAppName, "edcast");\r
+\r
+ char buf[255] = "";\r
+ char desc[1024] = "";\r
+\r
+#ifdef XMMS_PLUGIN\r
+ sprintf(desc, "This is the named pipe used to communicate with the XMMS effect plugin. Make sure it matches the settings in that plugin");\r
+ GetConfigVariable(g, g->gAppName, "SourceURL", "/tmp/edcastFIFO", g->gSourceURL, sizeof(g->gSourceURL), desc);\r
+#else\r
+ sprintf(desc, "The source URL for the broadcast. It must be in the form http://server:port/mountpoint. For those servers without a mountpoint (Shoutcast) use http://server:port.");\r
+ GetConfigVariable(g, g->gAppName, "SourceURL", "http://localhost/", g->gSourceURL, sizeof(g->gSourceURL), desc);\r
+#endif\r
+ if(g->sourceURLCallback) {\r
+ g->sourceURLCallback(g, (char *) g->gSourceURL);\r
+ }\r
+\r
+ sprintf(desc, "Destination server details (to where you are encoding). Valid server types : Shoutcast, Icecast, Icecast2");\r
+ GetConfigVariable(g, g->gAppName, "ServerType", "Icecast2", g->gServerType, sizeof(g->gServerType), desc);\r
+// sprintf(desc, "The server to which the stream is sent. It can be a hostname or IP (example: www.stream.com, 192.168.1.100)");\r
+ GetConfigVariable(g, g->gAppName, "Server", "localhost", g->gServer, sizeof(g->gServer), NULL);\r
+// sprintf(desc, "The port to which the stream is sent. Must be a number (example: 8000)");\r
+ GetConfigVariable(g, g->gAppName, "Port", "8000", g->gPort, sizeof(g->gPort), NULL);\r
+// sprintf(desc, "This is the encoder password for the destination server (example: hackme)");\r
+ GetConfigVariable(g, g->gAppName, "ServerPassword", "changemenow", g->gPassword, sizeof(g->gPassword), NULL);\r
+// sprintf(desc,"Used for Icecast/Icecast2 servers, The mountpoint must end in .ogg for Vorbis streams and have NO extention for MP3 streams. If you are sending to a Shoutcast server, this MUST be blank. (example: /mp3, /myvorbis.ogg)");\r
+ GetConfigVariable(g, g->gAppName, "ServerMountpoint", "/stream.ogg", g->gMountpoint, sizeof(g->gMountpoint), NULL);\r
+// sprintf(desc,"This setting tells the destination server to list on any available YP listings. Not all servers support this (Shoutcast does, Icecast2 doesn't) (example: 1 for YES, 0 for NO)");\r
+ sprintf(desc,"YP (Stream Directory) Settings");\r
+ g->gPubServ = GetConfigVariableLong(g, g->gAppName, "ServerPublic", 1, desc);\r
+// sprintf(desc, "This is used in the YP listing, I think only Shoutcast supports this (example: #mystream)");\r
+ GetConfigVariable(g, g->gAppName, "ServerIRC", "", g->gServIRC, sizeof(g->gServIRC), NULL);\r
+// sprintf(desc, "This is used in the YP listing, I think only Shoutcast supports this (example: myAIMaccount)");\r
+ GetConfigVariable(g, g->gAppName, "ServerAIM", "", g->gServAIM, sizeof(g->gServAIM), NULL);\r
+// sprintf(desc, "This is used in the YP listing, I think only Shoutcast supports this (example: 332123132)");\r
+ GetConfigVariable(g, g->gAppName, "ServerICQ", "", g->gServICQ, sizeof(g->gServICQ), NULL);\r
+// sprintf(desc, "The URL that is associated with your stream. (example: http://www.mystream.com)");\r
+ GetConfigVariable(g, g->gAppName, "ServerStreamURL", "http://www.oddsock.org", g->gServURL, sizeof(g->gServURL), NULL);\r
+// sprintf(desc, "The Stream Name");\r
+ GetConfigVariable(g, g->gAppName, "ServerName", "This is my server name", g->gServName, sizeof(g->gServName), NULL);\r
+// sprintf(desc, "A short description of the stream (example: Stream House on Fire!)");\r
+ GetConfigVariable(g, g->gAppName, "ServerDescription", "This is my server description", g->gServDesc, sizeof(g->gServDesc), NULL);\r
+// sprintf(desc, "Genre of music, can be anything you want... (example: Rock)");\r
+ GetConfigVariable(g, g->gAppName, "ServerGenre", "Rock", g->gServGenre, sizeof(g->gServGenre), NULL);\r
+// sprintf(desc,"Wether or not edcast will reconnect if it is disconnected from the destination server (example: 1 for YES, 0 for NO)");\r
+ sprintf(desc,"Misc encoder properties");\r
+ g->gAutoReconnect = GetConfigVariableLong(g, g->gAppName, "AutomaticReconnect", 1, desc);\r
+\r
+// sprintf(desc, "How long it will wait (in seconds) between reconnect attempts. (example: 10)");\r
+ g->gReconnectSec = GetConfigVariableLong(g, g->gAppName, "AutomaticReconnectSecs", 10, NULL);\r
+\r
+ g->autoconnect = GetConfigVariableLong(g, g->gAppName, "AutoConnect", 0, NULL);\r
+\r
+\r
+ // sprintf(desc, "What format to encode to. Valid values are (OGG, LAME) (example: OGG, LAME)");\r
+ sprintf(desc, "Output codec selection (Valid selections : MP3, OggVorbis, Ogg FLAC, AAC, AAC Plus)");\r
+ GetConfigVariable(g, g->gAppName, "Encode", "OggVorbis", g->gEncodeType, sizeof(g->gEncodeType), desc);\r
+ if(!strncmp(g->gEncodeType, "MP3", 3)) {\r
+ /* LAME */\r
+ g->gAACPFlag = 0;\r
+ g->gOggFlag = 0;\r
+ g->gLAMEFlag = 1;\r
+ g->gAACFlag = 0;\r
+ g->gFLACFlag = 0;\r
+ }\r
+\r
+ if(!strncmp(g->gEncodeType, "AAC Plus", 8)) {\r
+\r
+ /* AAC */\r
+ g->gOggFlag = 0;\r
+ g->gLAMEFlag = 0;\r
+ g->gAACFlag = 0;\r
+ g->gAACPFlag = 1;\r
+ g->gFLACFlag = 0;\r
+ }\r
+\r
+ if(!strcmp(g->gEncodeType, "AAC")) {\r
+\r
+ /* AAC */\r
+ g->gAACPFlag = 0;\r
+ g->gOggFlag = 0;\r
+ g->gLAMEFlag = 0;\r
+ g->gAACFlag = 1;\r
+ g->gFLACFlag = 0;\r
+ }\r
+\r
+ if(!strcmp(g->gEncodeType, "OggVorbis")) {\r
+\r
+ /* OggVorbis */\r
+ g->gOggFlag = 1;\r
+ g->gAACPFlag = 0;\r
+ g->gLAMEFlag = 0;\r
+ g->gAACFlag = 0;\r
+ g->gFLACFlag = 0;\r
+ }\r
+\r
+ if(!strcmp(g->gEncodeType, "Ogg FLAC")) {\r
+\r
+ /* OggVorbis */\r
+ g->gOggFlag = 0;\r
+ g->gAACPFlag = 0;\r
+ g->gLAMEFlag = 0;\r
+ g->gAACFlag = 0;\r
+ g->gFLACFlag = 1;\r
+ }\r
+\r
+ if(g->streamTypeCallback) {\r
+ if(g->gOggFlag) {\r
+ g->streamTypeCallback(g, (void *) "OggVorbis");\r
+ }\r
+\r
+ if(g->gLAMEFlag) {\r
+ g->streamTypeCallback(g, (void *) "MP3");\r
+ }\r
+\r
+ if(g->gAACFlag) {\r
+ g->streamTypeCallback(g, (void *) "AAC");\r
+ }\r
+\r
+ if(g->gAACPFlag) {\r
+ g->streamTypeCallback(g, (void *) "AAC+");\r
+ }\r
+\r
+ if(g->gFLACFlag) {\r
+ g->streamTypeCallback(g, (void *) "OggFLAC");\r
+ }\r
+ }\r
+\r
+ if(g->destURLCallback) {\r
+ sprintf(buf, "http://%s:%s%s", g->gServer, g->gPort, g->gMountpoint);\r
+ g->destURLCallback(g, (char *) buf);\r
+ }\r
+\r
+// sprintf(desc, "Bitrate. This is the mean bitrate if using VBR.");\r
+ sprintf(desc, "General settings (non-codec related). Note : NumberChannels = 1 for MONO, 2 for STEREO");\r
+ g->currentBitrate = GetConfigVariableLong(g, g->gAppName, "BitrateNominal", 128, desc);\r
+\r
+// sprintf(desc,"Minimum Bitrate. Used only if using Bitrate Management (not recommended) or LAME VBR(example: 64, 128)");\r
+ g->currentBitrateMin = GetConfigVariableLong(g, g->gAppName, "BitrateMin", 128, NULL);\r
+\r
+// sprintf(desc,"Maximum Bitrate. Used only if using Bitrate Management (not recommended) or LAME VBR (example: 64, 128)");\r
+ g->currentBitrateMax = GetConfigVariableLong(g, g->gAppName, "BitrateMax", 128, NULL);\r
+\r
+// sprintf(desc, "Number of channels. Valid values are (1, 2). 1 means Mono, 2 means Stereo (example: 2,1)");\r
+ g->currentChannels = GetConfigVariableLong(g, g->gAppName, "NumberChannels", 2, NULL);\r
+\r
+// sprintf(desc, "Sample rate for the stream. Valid values depend on wether using lame or vorbis. Vorbis supports odd samplerates such as 32kHz and 48kHz, but lame appears to not.feel free to experiment (example: 44100, 22050, 11025)");\r
+ g->currentSamplerate = GetConfigVariableLong(g, g->gAppName, "Samplerate", 44100, NULL);\r
+\r
+// sprintf(desc, "Vorbis Quality Level. Valid values are between -1 (lowest quality) and 10 (highest). The lower the quality the lower the output bitrate. (example: -1, 3)");\r
+ sprintf(desc, "Ogg Vorbis specific settings. Note: Valid settings for BitrateQuality flag are (Quality, Bitrate Management)");\r
+ GetConfigVariable(g, g->gAppName, "OggQuality", "0", g->gOggQuality, sizeof(g->gOggQuality), desc);\r
+\r
+\r
+// sprintf(desc,"This flag specifies if you want Vorbis Quality or Bitrate Management. Quality is always recommended. Valid values are (Bitrate, Quality). (example: Quality, Bitrate Management)");\r
+ GetConfigVariable(g, g->gAppName, "OggBitrateQualityFlag", "Quality", g->gOggBitQual, sizeof(g->gOggBitQual), NULL);\r
+ g->gOggBitQualFlag = 0;\r
+ if(!strncmp(g->gOggBitQual, "Q", 1)) {\r
+\r
+ /* Quality */\r
+ g->gOggBitQualFlag = 0;\r
+ }\r
+\r
+ if(!strncmp(g->gOggBitQual, "B", 1)) {\r
+\r
+ /* Bitrate */\r
+ g->gOggBitQualFlag = 1;\r
+ }\r
+\r
+ g->gAutoCountdown = atoi(g->gAutoStartSec);\r
+ if(strlen(g->gMountpoint) > 0) {\r
+ strcpy(g->gIceFlag, "1");\r
+ }\r
+ else {\r
+ strcpy(g->gIceFlag, "0");\r
+ }\r
+\r
+ char tempString[255] = "";\r
+\r
+ memset(tempString, '\000', sizeof(tempString));\r
+ ReplaceString(g->gServer, tempString, " ", "");\r
+ strcpy(g->gServer, tempString);\r
+\r
+ memset(tempString, '\000', sizeof(tempString));\r
+ ReplaceString(g->gPort, tempString, " ", "");\r
+ strcpy(g->gPort, tempString);\r
+\r
+// sprintf(desc,"This LAME flag indicates that CBR encoding is desired. If this flag is set then LAME with use CBR, if not set then it will use VBR (and you must then specify a VBR mode). Valid values are (1 for SET, 0 for NOT SET) (example: 1)");\r
+ sprintf(desc,"LAME specific settings. Note: Setting the low/highpass freq to 0 will disable them.");\r
+ g->gLAMEOptions.cbrflag = GetConfigVariableLong(g, g->gAppName, "LameCBRFlag", 1, desc);\r
+// sprintf(desc,"A number between 1 and 10 which indicates the desired quality level of the stream. The higher the number, the higher the quality. Also, the higher the number, the higher the CPU utilization. So for slower CPUs, try a low quality number (example: 5)");\r
+ g->gLAMEOptions.quality = GetConfigVariableLong(g, g->gAppName, "LameQuality", 1, NULL);\r
+\r
+// sprintf(desc, "Copywrite flag-> Not used for much. Valid values (1 for YES, 0 for NO)");\r
+ g->gLAMEOptions.copywrite = GetConfigVariableLong(g, g->gAppName, "LameCopywrite", 0, NULL);\r
+// sprintf(desc, "Original flag-> Not used for much. Valid values (1 for YES, 0 for NO)");\r
+ g->gLAMEOptions.original = GetConfigVariableLong(g, g->gAppName, "LameOriginal", 0, NULL);\r
+// sprintf(desc, "Strict ISO flag-> Not used for much. Valid values (1 for YES, 0 for NO)");\r
+ g->gLAMEOptions.strict_ISO = GetConfigVariableLong(g, g->gAppName, "LameStrictISO", 0, NULL);\r
+// sprintf(desc, "Disable Reservior flag-> Not used for much. Valid values (1 for YES, 0 for NO)");\r
+ g->gLAMEOptions.disable_reservoir = GetConfigVariableLong(g, g->gAppName, "LameDisableReservior", 0, NULL);\r
+// sprintf(desc, "This specifies the type of VBR encoding LAME will perform if VBR encoding is set (CBRFlag is NOT SET). See the LAME documention for more on what these mean. Valid values are (vbr_rh, vbr_mt, vbr_mtrh, vbr_abr)");\r
+ GetConfigVariable(g, g->gAppName, "LameVBRMode", "vbr_abr", g->gLAMEOptions.VBR_mode, sizeof(g->gLAMEOptions.VBR_mode), NULL);\r
+\r
+// sprintf(desc, "Use LAMEs lowpass filter. If you set this to 0, then no filtering is done.");\r
+ g->gLAMEOptions.lowpassfreq = GetConfigVariableLong(g, g->gAppName, "LameLowpassfreq", 0, NULL);\r
+// sprintf(desc, "Use LAMEs highpass filter. If you set this to 0, then no filtering is done.");\r
+ g->gLAMEOptions.highpassfreq = GetConfigVariableLong(g, g->gAppName, "LameHighpassfreq", 0, NULL);\r
+\r
+ if(g->gLAMEOptions.lowpassfreq > 0) {\r
+ g->gLAMELowpassFlag = 1;\r
+ }\r
+\r
+ if(g->gLAMEOptions.highpassfreq > 0) {\r
+ g->gLAMELowpassFlag = 1;\r
+ }\r
+ sprintf(desc, "LAME Preset");\r
+ int defaultPreset = 0;\r
+#ifdef WIN32\r
+ defaultPreset = LQP_NOPRESET;\r
+#endif\r
+ g->gLAMEpreset = GetConfigVariableLong(g, g->gAppName, "LAMEPreset", defaultPreset, NULL);\r
+\r
+ sprintf(desc, "AAC (FAAC) specific settings.");\r
+// sprintf(desc, "AAC Quality Level. Valid values are between 10 (lowest quality) and 500 (highest).");\r
+ GetConfigVariable(g, g->gAppName, "AACQuality", "100", g->gAACQuality, sizeof(g->gAACQuality), desc);\r
+// sprintf(desc, "AAC Cutoff Frequency.");\r
+ GetConfigVariable(g, g->gAppName, "AACCutoff", "", g->gAACCutoff, sizeof(g->gAACCutoff), NULL);\r
+\r
+\r
+\r
+ if(!strcmp(g->gServerType, "KasterBlaster")) {\r
+ g->gShoutcastFlag = 1;\r
+ g->gIcecastFlag = 0;\r
+ g->gIcecast2Flag = 0;\r
+ }\r
+\r
+ if(!strcmp(g->gServerType, "Shoutcast")) {\r
+ g->gShoutcastFlag = 1;\r
+ g->gIcecastFlag = 0;\r
+ g->gIcecast2Flag = 0;\r
+ }\r
+\r
+ if(!strcmp(g->gServerType, "Icecast")) {\r
+ g->gShoutcastFlag = 0;\r
+ g->gIcecastFlag = 1;\r
+ g->gIcecast2Flag = 0;\r
+ }\r
+\r
+ if(!strcmp(g->gServerType, "Icecast2")) {\r
+ g->gShoutcastFlag = 0;\r
+ g->gIcecastFlag = 0;\r
+ g->gIcecast2Flag = 1;\r
+ }\r
+\r
+ if(g->serverTypeCallback) {\r
+ g->serverTypeCallback(g, (void *) g->gServerType);\r
+ }\r
+\r
+ if(g->serverNameCallback) {\r
+ char *pdata = NULL;\r
+ int pdatalen = strlen(g->gServDesc) + strlen(g->gServName) + strlen(" () ") + 1;\r
+\r
+ pdata = (char *) calloc(1, pdatalen);\r
+ sprintf(pdata, "%s (%s)", g->gServName, g->gServDesc);\r
+ g->serverNameCallback(g, (void *) pdata);\r
+ free(pdata);\r
+ }\r
+\r
+ sprintf(desc, "If recording from linein, what device to use (not needed for win32) (example: /dev/dsp)");\r
+ GetConfigVariable(g, g->gAppName, "AdvRecDevice", "/dev/dsp", buf, sizeof(buf), desc);\r
+ strcpy(g->gAdvRecDevice, buf);\r
+\r
+\r
+ sprintf(desc, "If recording from linein, what sample rate to open the device with. (example: 44100, 48000)");\r
+ GetConfigVariable(g, g->gAppName, "LiveInSamplerate", "44100", buf, sizeof(buf), desc);\r
+ g->gLiveInSamplerate = atoi(buf);\r
+\r
+ sprintf(desc, "Used for any window positions (X value)");\r
+ g->lastX = GetConfigVariableLong(g, g->gAppName, "lastX", 0, desc);\r
+ sprintf(desc, "Used for any window positions (Y value)");\r
+ g->lastY = GetConfigVariableLong(g, g->gAppName, "lastY", 0, desc);\r
+ sprintf(desc, "Used for dummy window positions (X value)");\r
+ g->lastDummyX = GetConfigVariableLong(g, g->gAppName, "lastDummyX", 0, desc);\r
+ sprintf(desc, "Used for dummy window positions (Y value)");\r
+ g->lastDummyY = GetConfigVariableLong(g, g->gAppName, "lastDummyY", 0, desc);\r
+ sprintf(desc, "Used for plugins that show the VU meter");\r
+ g->vuShow = GetConfigVariableLong(g, g->gAppName, "showVU", 0, desc);\r
+\r
+ sprintf(desc, "Flag which indicates we are recording from line in");\r
+\r
+ int lineInDefault = 0;\r
+\r
+#ifdef ODDCASTSTANDALONE\r
+ lineInDefault = 1;\r
+#endif\r
+ g->gLiveRecordingFlag = GetConfigVariableLong(g, g->gAppName, "LineInFlag", lineInDefault, desc);\r
+\r
+ sprintf(desc, "Locked Metadata");\r
+ GetConfigVariable(g, g->gAppName, "LockMetadata", "", g->gManualSongTitle, sizeof(g->gManualSongTitle), desc);\r
+ sprintf(desc, "Flag which indicates if we are using locked metadata");\r
+ g->gLockSongTitle = GetConfigVariableLong(g, g->gAppName, "LockMetadataFlag", 0, desc);\r
+\r
+ sprintf(desc, "Save directory for archive streams");\r
+ GetConfigVariable(g, g->gAppName, "SaveDirectory", "", g->gSaveDirectory, sizeof(g->gSaveDirectory), desc);\r
+ sprintf(desc, "Flag which indicates if we are saving archives");\r
+ g->gSaveDirectoryFlag = GetConfigVariableLong(g, g->gAppName, "SaveDirectoryFlag", 0, desc);\r
+ sprintf(desc, "Log Level 1 = LOG_ERROR, 2 = LOG_ERROR+LOG_INFO, 3 = LOG_ERROR+LOG_INFO+LOG_DEBUG");\r
+ g->gLogLevel = GetConfigVariableLong(g, g->gAppName, "LogLevel", 2, desc);\r
+ sprintf(desc, "Log File");\r
+ GetConfigVariable(g, g->gAppName, "LogFile", defaultLogFileName, g->gLogFile, sizeof(g->gLogFile), desc);\r
+ setgLogFile(g, g->gLogFile);\r
+\r
+ sprintf(desc, "Save Archives in WAV format");\r
+ g->gSaveAsWAV = GetConfigVariableLong(g, g->gAppName, "SaveAsWAV", 0, desc);\r
+\r
+\r
+ sprintf(desc, "Append this string to all metadata");\r
+ GetConfigVariable(g, g->gAppName, "MetadataAppend", "", g->metadataAppendString, sizeof(g->metadataAppendString), desc);\r
+ sprintf(desc,\r
+ "Remove this string (and everything after) from the window title of the window class the metadata is coming from");\r
+ GetConfigVariable(g, g->gAppName, "MetadataRemoveAfter", "", g->metadataRemoveStringAfter, sizeof(g->metadataRemoveStringAfter), desc);\r
+ sprintf(desc,"Remove this string (and everything before) from the window title of the window class the metadata is coming from");\r
+ GetConfigVariable(g, g->gAppName, "MetadataRemoveBefore", "", g->metadataRemoveStringBefore, sizeof(g->metadataRemoveStringBefore), desc);\r
+ sprintf(desc, "Window classname to grab metadata from (uses window title)");\r
+ GetConfigVariable(g, g->gAppName, "MetadataWindowClass", "", g->metadataWindowClass, sizeof(g->metadataWindowClass), desc);\r
+ sprintf(desc, "Indicator which tells edcast to grab metadata from a defined window class");\r
+ \r
+ if (GetConfigVariableLong(g, g->gAppName, "MetadataWindowClassInd", 0, desc)) {\r
+ g->metadataWindowClassInd = true;\r
+ }\r
+ else {\r
+ g->metadataWindowClassInd = false;\r
+ }\r
+\r
+\r
+\r
+ /* Set some derived values */\r
+ char localBitrate[255] = "";\r
+ char mode[50] = "";\r
+\r
+ if(g->currentChannels == 1) {\r
+ strcpy(mode, "Mono");\r
+ }\r
+\r
+ if(g->currentChannels == 2) {\r
+ strcpy(mode, "Stereo");\r
+ }\r
+\r
+ if(g->gOggFlag) {\r
+ if(g->bitrateCallback) {\r
+ if(g->gOggBitQualFlag == 0) {\r
+\r
+ /* Quality */\r
+ sprintf(localBitrate, "Vorbis: Quality %s/%s/%d", g->gOggQuality, mode, g->currentSamplerate);\r
+ }\r
+ else {\r
+ sprintf(localBitrate, "Vorbis: %dkbps/%s/%d", g->currentBitrate, mode, g->currentSamplerate);\r
+ }\r
+\r
+ g->bitrateCallback(g, (void *) localBitrate);\r
+ }\r
+ }\r
+\r
+ if(g->gLAMEFlag) {\r
+ if(g->bitrateCallback) {\r
+ if(g->gLAMEOptions.cbrflag) {\r
+ sprintf(localBitrate, "MP3: %dkbps/%dHz/%s", g->currentBitrate, g->currentSamplerate, mode);\r
+ }\r
+ else {\r
+ sprintf(localBitrate,\r
+ "MP3: (%d/%d/%d)/%s/%d",\r
+ g->currentBitrateMin,\r
+ g->currentBitrate,\r
+ g->currentBitrateMax,\r
+ mode,\r
+ g->currentSamplerate);\r
+ }\r
+\r
+ g->bitrateCallback(g, (void *) localBitrate);\r
+ }\r
+ }\r
+\r
+ if(g->gAACFlag) {\r
+ if(g->bitrateCallback) {\r
+ sprintf(localBitrate, "AAC: Quality %s/%dHz/%s", g->gAACQuality, g->currentSamplerate, mode);\r
+ g->bitrateCallback(g, (void *) localBitrate);\r
+ }\r
+ }\r
+\r
+ if(g->gAACPFlag) {\r
+ if(g->bitrateCallback) {\r
+ long bitrateLong = g->currentBitrate * 1000;\r
+\r
+ if(bitrateLong >= 64000) {\r
+ if(g->currentChannels == 2) {\r
+ strcpy(mode, "Stereo");\r
+ }\r
+ else {\r
+ strcpy(mode, "Mono");\r
+ }\r
+ }\r
+\r
+ if((bitrateLong <= 48000) && (bitrateLong >= 16000)) {\r
+ if(g->currentChannels == 2) {\r
+ strcpy(mode, "Parametric Stereo");\r
+ }\r
+ else {\r
+ strcpy(mode, "Mono");\r
+ }\r
+ }\r
+\r
+ if(bitrateLong <= 12000) {\r
+ strcpy(mode, "Mono");\r
+ }\r
+\r
+ sprintf(localBitrate, "AAC+V2: %dkbps/%dHz/%s", g->currentBitrate, g->currentSamplerate, mode);\r
+ g->bitrateCallback(g, (void *) localBitrate);\r
+ }\r
+ }\r
+\r
+ if(g->gFLACFlag) {\r
+ if(g->bitrateCallback) {\r
+ sprintf(localBitrate, "FLAC: %dHz/%s", g->currentSamplerate, mode);\r
+ g->bitrateCallback(g, (void *) localBitrate);\r
+ }\r
+ }\r
+\r
+ if(g->serverStatusCallback) {\r
+ g->serverStatusCallback(g, (void *) "Disconnected");\r
+ }\r
+\r
+ sprintf(desc, "Number of encoders to use");\r
+ g->gNumEncoders = GetConfigVariableLong(g, g->gAppName, "NumEncoders", 0, desc);\r
+\r
+ sprintf(desc, "Enable external metadata calls (DISABLED, URL, FILE)");\r
+ GetConfigVariable(g, g->gAppName, "ExternalMetadata", "DISABLED", g->externalMetadata, sizeof(g->gLogFile), desc);\r
+ sprintf(desc, "URL to retrieve for external metadata");\r
+ GetConfigVariable(g, g->gAppName, "ExternalURL", "", g->externalURL, sizeof(g->externalURL), desc);\r
+ sprintf(desc, "File to retrieve for external metadata");\r
+ GetConfigVariable(g, g->gAppName, "ExternalFile", "", g->externalFile, sizeof(g->externalFile), desc);\r
+ sprintf(desc, "Interval for retrieving external metadata");\r
+ GetConfigVariable(g, g->gAppName, "ExternalInterval", "60", g->externalInterval, sizeof(g->externalInterval), desc);\r
+ sprintf(desc, "Advanced setting");\r
+ GetConfigVariable(g, g->gAppName, "OutputControl", "", g->outputControl, sizeof(g->outputControl), desc);\r
+\r
+ sprintf(desc, "Windows Recording Device");\r
+ GetConfigVariable(g, g->gAppName, "WindowsRecDevice", "", buf, sizeof(buf), desc);\r
+ strcpy(g->WindowsRecDevice, buf);\r
+\r
+ sprintf(desc, "LAME Joint Stereo Flag");\r
+ g->LAMEJointStereoFlag = GetConfigVariableLong(g, g->gAppName, "LAMEJointStereo", 1, desc);\r
+\r
+}\r
+\r
+void config_write(edcastGlobals *g) {\r
+ strcpy(g->gAppName, "edcast");\r
+\r
+ char buf[255] = "";\r
+ char desc[1024] = "";\r
+ char tempString[1024] = "";\r
+\r
+ memset(tempString, '\000', sizeof(tempString));\r
+ ReplaceString(g->gServer, tempString, " ", "");\r
+ strcpy(g->gServer, tempString);\r
+\r
+ memset(tempString, '\000', sizeof(tempString));\r
+ ReplaceString(g->gPort, tempString, " ", "");\r
+ strcpy(g->gPort, tempString);\r
+\r
+ PutConfigVariable(g, g->gAppName, "SourceURL", g->gSourceURL);\r
+ PutConfigVariable(g, g->gAppName, "ServerType", g->gServerType);\r
+ PutConfigVariable(g, g->gAppName, "Server", g->gServer);\r
+ PutConfigVariable(g, g->gAppName, "Port", g->gPort);\r
+ PutConfigVariable(g, g->gAppName, "ServerMountpoint", g->gMountpoint);\r
+ PutConfigVariable(g, g->gAppName, "ServerPassword", g->gPassword);\r
+ PutConfigVariableLong(g, g->gAppName, "ServerPublic", g->gPubServ);\r
+ PutConfigVariable(g, g->gAppName, "ServerIRC", g->gServIRC);\r
+ PutConfigVariable(g, g->gAppName, "ServerAIM", g->gServAIM);\r
+ PutConfigVariable(g, g->gAppName, "ServerICQ", g->gServICQ);\r
+ PutConfigVariable(g, g->gAppName, "ServerStreamURL", g->gServURL);\r
+ PutConfigVariable(g, g->gAppName, "ServerDescription", g->gServDesc);\r
+ PutConfigVariable(g, g->gAppName, "ServerName", g->gServName);\r
+ PutConfigVariable(g, g->gAppName, "ServerGenre", g->gServGenre);\r
+ PutConfigVariableLong(g, g->gAppName, "AutomaticReconnect", g->gAutoReconnect);\r
+ PutConfigVariableLong(g, g->gAppName, "AutomaticReconnectSecs", g->gReconnectSec);\r
+ PutConfigVariableLong(g, g->gAppName, "AutoConnect", g->autoconnect);\r
+ PutConfigVariable(g, g->gAppName, "Encode", g->gEncodeType);\r
+\r
+ PutConfigVariableLong(g, g->gAppName, "BitrateNominal", g->currentBitrate);\r
+ PutConfigVariableLong(g, g->gAppName, "BitrateMin", g->currentBitrateMin);\r
+ PutConfigVariableLong(g, g->gAppName, "BitrateMax", g->currentBitrateMax);\r
+ PutConfigVariableLong(g, g->gAppName, "NumberChannels", g->currentChannels);\r
+ PutConfigVariableLong(g, g->gAppName, "Samplerate", g->currentSamplerate);\r
+ PutConfigVariable(g, g->gAppName, "OggQuality", g->gOggQuality);\r
+ if(g->gOggBitQualFlag) {\r
+ strcpy(g->gOggBitQual, "Bitrate");\r
+ }\r
+ else {\r
+ strcpy(g->gOggBitQual, "Quality");\r
+ }\r
+\r
+ PutConfigVariable(g, g->gAppName, "OggBitrateQualityFlag", g->gOggBitQual);\r
+ PutConfigVariableLong(g, g->gAppName, "LameCBRFlag", g->gLAMEOptions.cbrflag);\r
+ PutConfigVariableLong(g, g->gAppName, "LameQuality", g->gLAMEOptions.quality);\r
+ PutConfigVariableLong(g, g->gAppName, "LameCopywrite", g->gLAMEOptions.copywrite);\r
+ PutConfigVariableLong(g, g->gAppName, "LameOriginal", g->gLAMEOptions.original);\r
+ PutConfigVariableLong(g, g->gAppName, "LameStrictISO", g->gLAMEOptions.strict_ISO);\r
+ PutConfigVariableLong(g, g->gAppName, "LameDisableReservior", g->gLAMEOptions.disable_reservoir);\r
+ PutConfigVariable(g, g->gAppName, "LameVBRMode", g->gLAMEOptions.VBR_mode);\r
+ PutConfigVariableLong(g, g->gAppName, "LameLowpassfreq", g->gLAMEOptions.lowpassfreq);\r
+ PutConfigVariableLong(g, g->gAppName, "LameHighpassfreq", g->gLAMEOptions.highpassfreq);\r
+ PutConfigVariableLong(g, g->gAppName, "LAMEPreset", g->gLAMEpreset);\r
+ PutConfigVariable(g, g->gAppName, "AACQuality", g->gAACQuality);\r
+ PutConfigVariable(g, g->gAppName, "AACCutoff", g->gAACCutoff);\r
+\r
+ PutConfigVariable(g, g->gAppName, "AdvRecDevice", g->gAdvRecDevice);\r
+ PutConfigVariableLong(g, g->gAppName, "LiveInSamplerate", g->gLiveInSamplerate);\r
+ PutConfigVariableLong(g, g->gAppName, "LineInFlag", g->gLiveRecordingFlag);\r
+\r
+ PutConfigVariableLong(g, g->gAppName, "lastX", g->lastX);\r
+ PutConfigVariableLong(g, g->gAppName, "lastY", g->lastY);\r
+ PutConfigVariableLong(g, g->gAppName, "lastDummyX", g->lastDummyX);\r
+ PutConfigVariableLong(g, g->gAppName, "lastDummyY", g->lastDummyY);\r
+ PutConfigVariableLong(g, g->gAppName, "showVU", g->vuShow);\r
+\r
+ PutConfigVariable(g, g->gAppName, "LockMetadata", g->gManualSongTitle);\r
+ PutConfigVariableLong(g, g->gAppName, "LockMetadataFlag", g->gLockSongTitle);\r
+\r
+ PutConfigVariable(g, g->gAppName, "SaveDirectory", g->gSaveDirectory);\r
+ PutConfigVariableLong(g, g->gAppName, "SaveDirectoryFlag", g->gSaveDirectoryFlag);\r
+ PutConfigVariableLong(g, g->gAppName, "LogLevel", g->gLogLevel);\r
+ PutConfigVariableLong(g, g->gAppName, "SaveAsWAV", g->gSaveAsWAV);\r
+ PutConfigVariable(g, g->gAppName, "LogFile", g->gLogFile);\r
+\r
+ PutConfigVariableLong(g, g->gAppName, "NumEncoders", g->gNumEncoders);\r
+\r
+ PutConfigVariable(g, g->gAppName, "ExternalMetadata", g->externalMetadata);\r
+ PutConfigVariable(g, g->gAppName, "ExternalURL", g->externalURL);\r
+ PutConfigVariable(g, g->gAppName, "ExternalFile", g->externalFile);\r
+ PutConfigVariable(g, g->gAppName, "ExternalInterval", g->externalInterval);\r
+\r
+ PutConfigVariable(g, g->gAppName, "OutputControl", g->outputControl);\r
+\r
+ PutConfigVariable(g, g->gAppName, "MetadataAppend", g->metadataAppendString);\r
+ PutConfigVariable(g, g->gAppName, "MetadataRemoveBefore", g->metadataRemoveStringBefore);\r
+ PutConfigVariable(g, g->gAppName, "MetadataRemoveAfter", g->metadataRemoveStringAfter);\r
+ PutConfigVariable(g, g->gAppName, "MetadataWindowClass", g->metadataWindowClass);\r
+ PutConfigVariableLong(g, g->gAppName, "MetadataWindowClassInd", g->metadataWindowClassInd);\r
+\r
+ PutConfigVariable(g, g->gAppName, "WindowsRecDevice", g->WindowsRecDevice);\r
+ PutConfigVariableLong(g, g->gAppName, "LAMEJointStereo", g->LAMEJointStereoFlag);\r
+\r
+}\r
+\r
+/*\r
+ =======================================================================================================================\r
+ Input is in interleaved float samples\r
+ =======================================================================================================================\r
+ */\r
+int handle_output(edcastGlobals *g, float *samples, int nsamples, int nchannels, int in_samplerate) {\r
+ int ret = 1;\r
+ static int current_insamplerate = 0;\r
+ static int current_nchannels = 0;\r
+ long out_samplerate = 0;\r
+ long out_nch = 0;\r
+ int samplecount = 0;\r
+ float *samplePtr = 0;\r
+ int in_nch = nchannels;\r
+\r
+ nchannels = 2;\r
+\r
+ float *samples_resampled = NULL;\r
+ short *samples_resampled_int = NULL;\r
+ float *samples_rechannel = NULL;\r
+\r
+ if(g == NULL) {\r
+ return 1;\r
+ }\r
+\r
+ if(g->weareconnected) {\r
+ // LogMessage(g,LOG_DEBUG, "%d Calling handle output", g->encoderNumber);\r
+ out_samplerate = getCurrentSamplerate(g);\r
+ out_nch = getCurrentChannels(g);\r
+ if(g->gSaveAsWAV) {\r
+ int sizeofData = nsamples * nchannels * sizeof(short int);\r
+ short int *int_samples;\r
+\r
+ int_samples = (short int *) malloc(sizeofData);\r
+\r
+ for(int i = 0; i < nsamples * nchannels; i = i + 1) {\r
+ int_samples[i] = (short int) (samples[i] * 32767.f);\r
+ }\r
+\r
+ fwrite(int_samples, sizeofData, 1, g->gSaveFile);\r
+ g->written += sizeofData;\r
+ free(int_samples);\r
+\r
+ /*\r
+ * int sizeofData = nsamples*nchannels*sizeof(float);\r
+ * fwrite(samples, sizeofData, 1, g->gSaveFile);\r
+ * g->written += sizeofData;\r
+ * ;\r
+ * Write to WAV file\r
+ */\r
+ }\r
+\r
+ if(current_insamplerate != in_samplerate) {\r
+ resetResampler(g);\r
+ current_insamplerate = in_samplerate;\r
+ }\r
+\r
+ if(current_nchannels != nchannels) {\r
+ resetResampler(g);\r
+ current_nchannels = nchannels;\r
+ }\r
+\r
+ samples_rechannel = (float *) malloc(sizeof(float) * nsamples * nchannels);\r
+ memset(samples_rechannel, '\000', sizeof(float) * nsamples * nchannels);\r
+\r
+ samplePtr = samples;\r
+\r
+ int make_mono = 0;\r
+ int make_stereo = 0;\r
+\r
+ if((in_nch == 2) && (out_nch == 1)) {\r
+ make_mono = 1;\r
+ }\r
+\r
+ if((in_nch == 1) && (out_nch == 2)) {\r
+ make_stereo = 1;\r
+ }\r
+\r
+ if((in_nch == 1) && (out_nch == 1)) {\r
+ make_stereo = 1;\r
+ }\r
+\r
+ int samplecounter = 0;\r
+\r
+ if(make_mono) {\r
+ for(int i = 0; i < nsamples * 2; i = i + 2) {\r
+ samples_rechannel[i] = (samples[i] + samples[i + 1]) / 2;\r
+ samples_rechannel[i + 1] = (samples[i] + samples[i + 1]) / 2;\r
+ }\r
+ }\r
+\r
+ if(make_stereo) {\r
+ for(int i = 0; i < nsamples; i = i + 1) {\r
+ samples_rechannel[samplecounter] = (samples[i]);\r
+ samplecounter++;\r
+ samples_rechannel[samplecounter] = (samples[i]);\r
+ samplecounter++;\r
+ }\r
+ }\r
+\r
+ if(!(make_mono) && !(make_stereo)) {\r
+ for(int i = 0; i < nsamples * 2; i = i + 1) {\r
+ samples_rechannel[i] = (samples[i]);\r
+ }\r
+ }\r
+\r
+ LogMessage(g,LOG_DEBUG, "In samplerate = %d, Out = %d", in_samplerate, out_samplerate);\r
+ samplePtr = samples_rechannel;\r
+ if(in_samplerate != out_samplerate) {\r
+ nchannels = 2;\r
+\r
+ /* Call the resampler */\r
+ int buf_samples = ((nsamples * out_samplerate) / in_samplerate);\r
+\r
+ LogMessage(g,LOG_DEBUG, "Initializing resampler");\r
+\r
+ initializeResampler(g, in_samplerate, nchannels);\r
+\r
+ samples_resampled = (float *) malloc(sizeof(float) * buf_samples * nchannels);\r
+ memset(samples_resampled, '\000', sizeof(float) * buf_samples * nchannels);\r
+\r
+ LogMessage(g,LOG_DEBUG, "calling ocConvertAudio");\r
+ long out_samples = ocConvertAudio(g,\r
+ (float *) samplePtr,\r
+ (float *) samples_resampled,\r
+ nsamples,\r
+ buf_samples);\r
+\r
+ samples_resampled_int = (short *) malloc(sizeof(short) * out_samples * nchannels);\r
+ memset(samples_resampled_int, '\000', sizeof(short) * out_samples * nchannels);\r
+\r
+ LogMessage(g,LOG_DEBUG, "ready to do encoding");\r
+\r
+ if(out_samples > 0) {\r
+ samplecount = 0;\r
+\r
+ /* Here is the call to actually do the encoding->... */\r
+ LogMessage(g,LOG_DEBUG, "do_encoding start");\r
+ ret = do_encoding(g, (float *) (samples_resampled), out_samples, out_nch);\r
+ LogMessage(g,LOG_DEBUG, "do_encoding end (%d)", ret);\r
+ }\r
+\r
+ if(samples_resampled_int) {\r
+ free(samples_resampled_int);\r
+ samples_resampled_int = NULL;\r
+ }\r
+\r
+ if(samples_resampled) {\r
+ free(samples_resampled);\r
+ samples_resampled = NULL;\r
+ }\r
+ }\r
+ else {\r
+ LogMessage(g,LOG_DEBUG, "do_encoding start");\r
+ ret = do_encoding(g, (float *) samples_rechannel, nsamples, nchannels);\r
+ LogMessage(g,LOG_DEBUG, "do_encoding end (%d)", ret);\r
+ }\r
+\r
+ if(samples_rechannel) {\r
+ free(samples_rechannel);\r
+ samples_rechannel = NULL;\r
+ }\r
+ LogMessage(g,LOG_DEBUG, "%d Calling handle output - Ret = %d", g->encoderNumber, ret);\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+#ifdef WIN32\r
+void freeupGlobals(edcastGlobals *g) {\r
+ if(g->hDLL) {\r
+ FreeLibrary(g->hDLL);\r
+ }\r
+\r
+ if(g->faacFIFO) {\r
+ free(g->faacFIFO);\r
+ }\r
+}\r
+#endif\r
+\r
+void addUISettings(edcastGlobals *g) {\r
+\r
+\r
+ addConfigVariable(g, "AutomaticReconnect");\r
+ addConfigVariable(g, "AutomaticReconnectSecs");\r
+ addConfigVariable(g, "AutoConnect");\r
+ addConfigVariable(g, "AdvRecDevice");\r
+ addConfigVariable(g, "LiveInSamplerate");\r
+ addConfigVariable(g, "LineInFlag");\r
+ addConfigVariable(g, "lastX");\r
+ addConfigVariable(g, "lastY");\r
+ addConfigVariable(g, "lastDummyX");\r
+ addConfigVariable(g, "lastDummyY");\r
+ addConfigVariable(g, "showVU");\r
+ addConfigVariable(g, "LockMetadata");\r
+ addConfigVariable(g, "LockMetadataFlag");\r
+ addConfigVariable(g, "SaveDirectory");\r
+ addConfigVariable(g, "SaveDirectoryFlag");\r
+ addConfigVariable(g, "LogLevel");\r
+ addConfigVariable(g, "SaveAsWAV");\r
+ addConfigVariable(g, "LogFile");\r
+ addConfigVariable(g, "NumEncoders");\r
+ addConfigVariable(g, "ExternalMetadata");\r
+ addConfigVariable(g, "ExternalURL");\r
+ addConfigVariable(g, "ExternalFile");\r
+ addConfigVariable(g, "ExternalInterval");\r
+ addConfigVariable(g, "OutputControl");\r
+ addConfigVariable(g, "MetadataAppend");\r
+ addConfigVariable(g, "MetadataRemoveBefore");\r
+ addConfigVariable(g, "MetadataRemoveAfter");\r
+ addConfigVariable(g, "MetadataWindowClass");\r
+ addConfigVariable(g, "MetadataWindowClassInd");\r
+ addConfigVariable(g, "WindowsRecDevice");\r
+\r
+}\r
+\r
+void addBasicEncoderSettings(edcastGlobals *g) {\r
+ addConfigVariable(g, "ServerType");\r
+ addConfigVariable(g, "Server");\r
+ addConfigVariable(g, "Port");\r
+ addConfigVariable(g, "ServerMountpoint");\r
+ addConfigVariable(g, "ServerPassword");\r
+ addConfigVariable(g, "ServerPublic");\r
+ addConfigVariable(g, "ServerIRC");\r
+ addConfigVariable(g, "ServerAIM");\r
+ addConfigVariable(g, "ServerICQ");\r
+ addConfigVariable(g, "ServerStreamURL");\r
+ addConfigVariable(g, "ServerDescription");\r
+ addConfigVariable(g, "ServerName");\r
+ addConfigVariable(g, "ServerGenre");\r
+// addConfigVariable(g, "AutomaticReconnect");\r
+ addConfigVariable(g, "AutomaticReconnectSecs");\r
+ addConfigVariable(g, "AutoConnect");\r
+ addConfigVariable(g, "Encode");\r
+ addConfigVariable(g, "BitrateNominal");\r
+ addConfigVariable(g, "BitrateMin");\r
+ addConfigVariable(g, "BitrateMax");\r
+ addConfigVariable(g, "NumberChannels");\r
+ addConfigVariable(g, "Samplerate");\r
+ addConfigVariable(g, "OggQuality");\r
+ addConfigVariable(g, "OggBitrateQualityFlag");\r
+ addConfigVariable(g, "LameCBRFlag");\r
+ addConfigVariable(g, "LameQuality");\r
+ addConfigVariable(g, "LameCopywrite");\r
+ addConfigVariable(g, "LameOriginal");\r
+ addConfigVariable(g, "LameStrictISO");\r
+ addConfigVariable(g, "LameDisableReservior");\r
+ addConfigVariable(g, "LameVBRMode");\r
+ addConfigVariable(g, "LameLowpassfreq");\r
+ addConfigVariable(g, "LameHighpassfreq");\r
+ addConfigVariable(g, "LAMEPreset");\r
+ addConfigVariable(g, "AACQuality");\r
+ addConfigVariable(g, "AACCutoff");\r
+ addConfigVariable(g, "LogLevel");\r
+ addConfigVariable(g, "LogFile");\r
+ addConfigVariable(g, "LAMEJointStereo");\r
+ addConfigVariable(g, "SaveDirectory");\r
+ addConfigVariable(g, "SaveDirectoryFlag");\r
+ addConfigVariable(g, "SaveAsWAV");\r
+}\r
+\r
+void LogMessage(edcastGlobals *g, int type, char *source, int line, char *fmt, ...) {\r
+ va_list parms;\r
+ char errortype[25] = "";\r
+ int addNewline = 1;\r
+ struct tm *tp;\r
+ time_t t;\r
+ int parseableOutput = 0;\r
+ char timeStamp[255];\r
+\r
+ char sourceLine[1024] = "";\r
+\r
+ char *p1 = NULL;\r
+\r
+#ifdef WIN32\r
+ p1 = strrchr(source, '\\');\r
+#else\r
+ p1 = strrchr(source, '/');\r
+#endif\r
+\r
+ if (p1) {\r
+ strcpy(sourceLine, p1+1);\r
+ }\r
+ else {\r
+ strcpy(sourceLine, source);\r
+ }\r
+ memset(timeStamp, '\000', sizeof(timeStamp));\r
+\r
+ time(&t);\r
+ tp = localtime(&t);\r
+ strftime(timeStamp, sizeof(timeStamp), "%m/%d/%y %H:%M:%S", tp);\r
+\r
+ \r
+ switch (type) {\r
+ case LM_ERROR:\r
+ strcpy(errortype, "Error");\r
+ break;\r
+ case LM_INFO:\r
+ strcpy(errortype, "Info");\r
+ break;\r
+ case LM_DEBUG:\r
+ strcpy(errortype, "Debug");\r
+ break;\r
+ default:\r
+ strcpy(errortype, "Unknown");\r
+ break;\r
+ }\r
+\r
+ if (fmt[strlen(fmt)-1] == '\n') {\r
+ addNewline = 0;\r
+ }\r
+\r
+\r
+ if (type <= g->gLogLevel) {\r
+ va_start(parms, fmt);\r
+ char_t logfile[1024] = "";\r
+\r
+ if (g->logFilep == 0) {\r
+ sprintf(logfile, "%s.log", g->gLogFile);\r
+ g->logFilep = fopen(logfile, "a");\r
+ }\r
+ \r
+ if (!g->logFilep) {\r
+ fprintf(stdout, "Cannot open logfile: %s(%s:%d): ", logfile, sourceLine, line);\r
+ vfprintf(stdout, fmt, parms);\r
+ va_end(parms);\r
+ if (addNewline) {\r
+ fprintf(stdout, "\n");\r
+ }\r
+ }\r
+ else {\r
+ fprintf(g->logFilep, "%s %s(%s:%d): ", timeStamp, errortype, sourceLine, line);\r
+ vfprintf(g->logFilep, fmt, parms);\r
+ va_end(parms);\r
+ if (addNewline) {\r
+ fprintf(g->logFilep, "\n");\r
+ }\r
+ fflush(g->logFilep);\r
+ }\r
+\r
+ }\r
+\r
+}\r
+\r
+\r
+char_t *getWindowsRecordingDevice(edcastGlobals *g) {\r
+ return g->WindowsRecDevice;\r
+}\r
+void setWindowsRecordingDevice(edcastGlobals *g, char_t *device) {\r
+ strcpy(g->WindowsRecDevice, device);\r
+}\r
+int getLAMEJointStereoFlag(edcastGlobals *g) {\r
+ return g->LAMEJointStereoFlag;\r
+}\r
+void setLAMEJointStereoFlag(edcastGlobals *g, int flag) {\r
+ g->LAMEJointStereoFlag = flag;\r
+}\r
+\r