00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <signal.h>
00026 #include <limits.h>
00027 #include <errno.h>
00028 #include <time.h>
00029 #include <string.h>
00030 #include <unistd.h>
00031 #include <fcntl.h>
00032 #include <sched.h>
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035
00036 #include "SockClie.hh"
00037
00038 #include "SaveSrv.hh"
00039
00040
00041 static bool bDaemon = false;
00042 static const char *cpFileExt[] = { "wav", "aiff", "flac" };
00043 static const char cpFLACMarker[] = "fLaC";
00044 clSaveSrv SaveSrv;
00045
00046 void SigHandler (int iSigNum)
00047 {
00048 switch (iSigNum)
00049 {
00050 case SIGINT:
00051 SaveSrv.Log.Add('#', "Received SIGINT, terminating...");
00052 SaveSrv.Stop();
00053 break;
00054 case SIGTERM:
00055 SaveSrv.Log.Add('#', "Received SIGTERM, terminating...");
00056 SaveSrv.Stop();
00057 break;
00058 case SIGSEGV:
00059 SaveSrv.Log.Add('!', "Oops, received SIGSEGV, terminating...");
00060 abort();
00061 break;
00062 }
00063 }
00064
00065
00066 int main (int argc, char *argv[])
00067 {
00068 bool bRealTime = false;
00069 int iArgCntr;
00070 uid_t uidCurrent;
00071 struct sched_param sSchedParam;
00072
00073 signal(SIGPIPE, SIG_IGN);
00074 signal(SIGFPE, SIG_IGN);
00075 signal(SIGINT, SigHandler);
00076 signal(SIGTERM, SigHandler);
00077 signal(SIGSEGV, SigHandler);
00078
00079 for (iArgCntr = 1; iArgCntr < argc; iArgCntr++)
00080 {
00081 if (strcmp(argv[iArgCntr], "--rt") == 0)
00082 bRealTime = true;
00083 }
00084
00085 if (bRealTime)
00086 {
00087 uidCurrent = getuid();
00088 setuid(0);
00089 memset(&sSchedParam, 0x00, sizeof(sSchedParam));
00090 sSchedParam.sched_priority = sched_get_priority_min(SCHED_FIFO);
00091 sched_setscheduler(getpid(), SCHED_FIFO, &sSchedParam);
00092 setuid(uidCurrent);
00093 }
00094
00095 return SaveSrv.Main(argc, argv);
00096 }
00097
00098
00099 #ifdef USE_FLAC
00100
00101 FLAC__StreamEncoderWriteStatus WrapFLACWrite (
00102 const FLAC__StreamEncoder *spFLACEnc, const FLAC__byte cpBuffer[],
00103 unsigned uiBytes, unsigned uiSamples, unsigned uiCurrFrame,
00104 void *vpDataPtr)
00105 {
00106 clSaveSrv *SaveSrvInst = (clSaveSrv *) vpDataPtr;
00107
00108 return SaveSrvInst->FLACWrite(spFLACEnc, cpBuffer, uiBytes, uiSamples,
00109 uiCurrFrame);
00110 }
00111
00112
00113 void WrapFLACMetaData (
00114 const FLAC__StreamEncoder *spFLACEnc,
00115 const FLAC__StreamMetadata *spFLACMetaData,
00116 void *vpDataPtr)
00117 {
00118 clSaveSrv *SaveSrvInst = (clSaveSrv *) vpDataPtr;
00119
00120 SaveSrvInst->FLACMetaData(spFLACEnc, spFLACMetaData);
00121 }
00122
00123 #endif
00124
00125
00126 bool clSaveSrv::Initialize ()
00127 {
00128 char cpSndFileVer[SAVS_SNDFILE_MSGLEN + 1];
00129
00130 Cfg.SetFileName(SD_CFGFILE);
00131 if (!Cfg.GetStr("LocalSocket", cpSockName))
00132 {
00133 Log.Add('!', "\"LocalSocket\" not found from configuration file");
00134 return false;
00135 }
00136 Cfg.SetFileName(SAVS_CFGFILE);
00137 if (!Cfg.GetStr("SavePath", cpSavePath))
00138 {
00139 Log.Add('!', "\"SavePath\" not found from configuration file");
00140 return false;
00141 }
00142 if (!Cfg.GetInt("Format", &iFormat))
00143 {
00144 Log.Add('!', "\"Format\" not found from configuration file");
00145 return false;
00146 }
00147 if (!Cfg.GetInt("Type", &iType))
00148 {
00149 Log.Add('!', "\"Type\" not found from configuration file");
00150 return false;
00151 }
00152 if (!Cfg.GetInt("Bits", &iBits))
00153 {
00154 Log.Add('!', "\"Bits\" not found from configuration file");
00155 return false;
00156 }
00157 if (!Cfg.GetInt("Dither", &iDither))
00158 iDither = 0;
00159 if (iBits != 8 && iBits != 16 && iBits != 24)
00160 {
00161 iDither = 0;
00162 Log.Add(' ', "Unsupported word length for dithering, dither disabled");
00163 }
00164 if (!Cfg.GetInt("FrameLength", &lFrameLen))
00165 lFrameLen = SAVS_DEF_FRAMELEN;
00166 if (!Cfg.GetInt("FileTime", &iFileTime))
00167 iFileTime = SAVS_DEF_FILETIME;
00168
00169 lFrameSize = lFrameLen * sizeof(GDT);
00170 InFrame.Size(lFrameSize);
00171 if (iDither == 1)
00172 {
00173 OutFrame.Size(lFrameLen * (iBits / 8));
00174 Log.Add(' ', "Dither enabled");
00175 }
00176 else
00177 {
00178 OutFrame.Size(lFrameLen * sizeof(double));
00179 Log.Add(' ', "Dither disabled");
00180 }
00181 NoiseFrame.Size(lFrameLen * sizeof(int));
00182 #ifdef USE_FLAC
00183 FLACFrame.Size(lFrameLen * sizeof(FLAC__int32));
00184 #endif
00185
00186 #ifdef linux
00187 int iRndH = open("/dev/urandom", O_RDONLY);
00188 if (iRndH < 0)
00189 {
00190 Log.Add('!', "Unable to access /dev/urandom", errno);
00191 return false;
00192 }
00193 if (read(iRndH, &uiRndSeed, sizeof(unsigned int)) == sizeof(unsigned int))
00194 {
00195 Log.Add(' ', "Random number generator seeded using /dev/urandom");
00196 }
00197 else
00198 {
00199 uiRndSeed = time(NULL);
00200 Log.Add('#', "Unable to read /dev/urandom, seeding with time");
00201 }
00202 close(iRndH);
00203 #else
00204 uiRndSeed = time(NULL);
00205 #endif
00206
00207 int iRandVal;
00208 int *ipRndPtr = NoiseFrame;
00209 #if (defined(linux) || defined(BSDSYS))
00210 srandom(uiRndSeed);
00211 #else
00212 srand(uiRndSeed);
00213 #endif
00214 for (long lRndCntr = 0; lRndCntr < lFrameLen; lRndCntr++)
00215 {
00216 #if (defined(linux) || defined(BSDSYS))
00217 iRandVal = random();
00218 #else
00219 iRandVal = rand();
00220 #endif
00221 ipRndPtr[lRndCntr] = (iRandVal & 0x7fffffff);
00222 }
00223 #ifdef USE_MERSENNE_TWISTER
00224 MTR = new MTRand(uiRndSeed);
00225 Log.Add(' ', "Using Mersenne Twister as PRNG");
00226 #endif
00227
00228 iFileTime *= 60;
00229
00230 sf_command(NULL, SFC_GET_LIB_VERSION, cpSndFileVer, SAVS_SNDFILE_MSGLEN);
00231 Log.Add(' ', cpSndFileVer);
00232 return true;
00233 }
00234
00235
00236 bool clSaveSrv::ConnectStream ()
00237 {
00238 int iSockH;
00239 char cpLogEntry[SAVS_LOGENTRY_SIZE + 1];
00240 stRawDataReq sDataReq;
00241 clSockClie SClient;
00242
00243 iSockH = SClient.Connect(cpSockName);
00244 if (iSockH < 0)
00245 {
00246 Log.Add('!', "clSockClie::Connect() failed", SClient.GetErrno());
00247 return false;
00248 }
00249 SOp.SetHandle(iSockH);
00250 if (SOp.ReadN(&sDataHdr, sizeof(sDataHdr)) != sizeof(sDataHdr))
00251 {
00252 Log.Add('!', "clSockOp::ReadN() failed", SOp.GetErrno());
00253 return false;
00254 }
00255 sDataReq.iChannel = -1;
00256 if (SOp.WriteN(&sDataReq, sizeof(sDataReq)) != sizeof(sDataReq))
00257 {
00258 Log.Add('!', "clSockOp::WriteN() failed", SOp.GetErrno());
00259 return false;
00260 }
00261 sprintf(cpLogEntry, "Stream ch %i fs %g", sDataHdr.iChannels,
00262 sDataHdr.dSampleRate);
00263 Log.Add(' ', cpLogEntry);
00264 return true;
00265 }
00266
00267
00268 bool clSaveSrv::CreateFile ()
00269 {
00270 char cpFileName[_POSIX_PATH_MAX + 1];
00271 SF_INFO sSndInfo;
00272
00273 if (spSndFile != NULL) sf_close(spSndFile);
00274
00275 CreateFileName(cpFileName);
00276
00277 memset(&sSndInfo, 0x00, sizeof(sSndInfo));
00278 sSndInfo.samplerate = (int) (sDataHdr.dSampleRate + 0.5);
00279 sSndInfo.channels = sDataHdr.iChannels;
00280 switch (iFormat)
00281 {
00282 case SAVS_FORMAT_WAV:
00283 sSndInfo.format = SF_FORMAT_WAV;
00284 break;
00285 case SAVS_FORMAT_AIFF:
00286 sSndInfo.format = SF_FORMAT_AIFF;
00287 break;
00288 default:
00289 iFormat = SAVS_FORMAT_WAV;
00290 sSndInfo.format = (SF_FORMAT_WAV|SF_FORMAT_PCM_16);
00291 }
00292 switch (iType)
00293 {
00294 case SAVS_TYPE_PCM:
00295 switch (iBits)
00296 {
00297 case 8:
00298 sSndInfo.format |= SF_FORMAT_PCM_U8;
00299 break;
00300 case 16:
00301 sSndInfo.format |= SF_FORMAT_PCM_16;
00302 break;
00303 case 24:
00304 sSndInfo.format |= SF_FORMAT_PCM_24;
00305 break;
00306 case 32:
00307 sSndInfo.format |= SF_FORMAT_PCM_32;
00308 break;
00309 }
00310 break;
00311 case SAVS_TYPE_FLOAT:
00312 sSndInfo.format |= SF_FORMAT_FLOAT;
00313 break;
00314 case SAVS_TYPE_ADPCM:
00315 sSndInfo.format |= SF_FORMAT_IMA_ADPCM;
00316 break;
00317 case SAVS_TYPE_MSADPCM:
00318 sSndInfo.format |= SF_FORMAT_MS_ADPCM;
00319 break;
00320 default:
00321 sSndInfo.format |= SF_FORMAT_FLOAT;
00322 }
00323 sSndInfo.format |= SF_ENDIAN_FILE;
00324 if (!sf_format_check(&sSndInfo))
00325 {
00326 Log.Add('!', "Invalid file format");
00327 return false;
00328 }
00329 spSndFile = sf_open(cpFileName, SFM_WRITE, &sSndInfo);
00330 if (spSndFile == NULL)
00331 {
00332 Log.Add('!', "File open failed");
00333 return false;
00334 }
00335 if (!sf_command(spSndFile, SFC_SET_NORM_DOUBLE, NULL, SF_TRUE))
00336 {
00337
00338
00339
00340 }
00341 if (iDither > 1)
00342 {
00343 if (!sf_command(spSndFile, SFC_SET_ADD_DITHER_ON_WRITE, NULL, SF_TRUE))
00344 {
00345 Log.Add('#', "Warning, failed to enable dithering");
00346 }
00347 }
00348 Log.Add('+', cpFileName);
00349 return true;
00350 }
00351
00352
00353 bool clSaveSrv::CreateFile2 ()
00354 {
00355 #ifdef USE_FLAC
00356 int iMaxLPCOrder;
00357 int iMinRiceOrder;
00358 int iMaxRiceOrder;
00359 char cpFileName[_POSIX_PATH_MAX + 1];
00360 FLAC__StreamEncoderState iEncState;
00361
00362 if (spFLACEnc != NULL && iFileH >= 0)
00363 {
00364 FLAC__stream_encoder_finish(spFLACEnc);
00365 close(iFileH);
00366 }
00367
00368 if (!Cfg.GetInt("FLACMaxLPCOrder", &iMaxLPCOrder))
00369 iMaxLPCOrder = 0;
00370 if (iMaxLPCOrder > (int) FLAC__MAX_LPC_ORDER)
00371 iMaxLPCOrder = FLAC__MAX_LPC_ORDER;
00372 if (!Cfg.GetInt("FLACMinRiceOrder", &iMinRiceOrder))
00373 iMinRiceOrder = 0;
00374 if (!Cfg.GetInt("FLACMaxRiceOrder", &iMaxRiceOrder))
00375 iMaxRiceOrder = 0;
00376 if (iMaxRiceOrder > (int) FLAC__MAX_RICE_PARTITION_ORDER)
00377 iMaxRiceOrder = FLAC__MAX_RICE_PARTITION_ORDER;
00378
00379 CreateFileName(cpFileName);
00380
00381 iFileH = open(cpFileName, O_WRONLY|O_CREAT,
00382 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
00383 if (iFileH < 0)
00384 {
00385 Log.Add('!', "File open failed");
00386 return false;
00387 }
00388
00389 if (spFLACEnc == NULL)
00390 {
00391 spFLACEnc = FLAC__stream_encoder_new();
00392 if (spFLACEnc == NULL)
00393 {
00394 Log.Add('!', "FLAC constructor failed");
00395 return false;
00396 }
00397 }
00398 FLAC__stream_encoder_set_streamable_subset(spFLACEnc,
00399 1);
00400 FLAC__stream_encoder_set_do_mid_side_stereo(spFLACEnc,
00401 0);
00402 FLAC__stream_encoder_set_loose_mid_side_stereo(spFLACEnc,
00403 0);
00404 FLAC__stream_encoder_set_channels(spFLACEnc,
00405 sDataHdr.iChannels);
00406 FLAC__stream_encoder_set_bits_per_sample(spFLACEnc,
00407 iBits);
00408 FLAC__stream_encoder_set_sample_rate(spFLACEnc,
00409 (int) (sDataHdr.dSampleRate + 0.5));
00410 FLAC__stream_encoder_set_blocksize(spFLACEnc,
00411 lFrameLen);
00412 FLAC__stream_encoder_set_max_lpc_order(spFLACEnc,
00413 iMaxLPCOrder);
00414 FLAC__stream_encoder_set_qlp_coeff_precision(spFLACEnc,
00415 0);
00416 FLAC__stream_encoder_set_do_qlp_coeff_prec_search(spFLACEnc,
00417 0);
00418 FLAC__stream_encoder_set_do_escape_coding(spFLACEnc,
00419 1);
00420 FLAC__stream_encoder_set_do_exhaustive_model_search(spFLACEnc,
00421 1);
00422 FLAC__stream_encoder_set_min_residual_partition_order(spFLACEnc,
00423 iMinRiceOrder);
00424 FLAC__stream_encoder_set_max_residual_partition_order(spFLACEnc,
00425 iMaxRiceOrder);
00426 FLAC__stream_encoder_set_rice_parameter_search_dist(spFLACEnc,
00427 0);
00428
00429
00430 FLAC__stream_encoder_set_total_samples_estimate(spFLACEnc,
00431 0);
00432 FLAC__stream_encoder_set_metadata(spFLACEnc,
00433 NULL, 0);
00434 FLAC__stream_encoder_set_write_callback(spFLACEnc,
00435 WrapFLACWrite);
00436 FLAC__stream_encoder_set_metadata_callback(spFLACEnc,
00437 WrapFLACMetaData);
00438 FLAC__stream_encoder_set_client_data(spFLACEnc,
00439 (void *) this);
00440
00441 iEncState = FLAC__stream_encoder_init(spFLACEnc);
00442 if (iEncState != FLAC__STREAM_ENCODER_OK)
00443 {
00444 Log.Add('!', FLAC__StreamEncoderStateString[iEncState]);
00445 return false;
00446 }
00447
00448 Log.Add('+', cpFileName);
00449 return true;
00450 #else
00451 return false;
00452 #endif
00453 }
00454
00455
00456 void clSaveSrv::CreateFileName (char *cpFileName)
00457 {
00458 int iFileNumber;
00459 char cpTime[SAVS_TIMELEN + 1];
00460 time_t ttTime;
00461
00462 ttTime = time(NULL);
00463 ttFileStarted = ttTime - ttTime % iFileTime;
00464 strftime(cpTime, SAVS_TIMELEN + 1, "%d%m%Y%H%M", localtime(&ttFileStarted));
00465 iFileNumber = 0;
00466 do
00467 {
00468 sprintf(cpFileName, "%s%s-%i.%s",
00469 cpSavePath, cpTime, iFileNumber, cpFileExt[iFormat]);
00470 iFileNumber++;
00471 } while(access(cpFileName, F_OK) == 0);
00472 }
00473
00474
00475 void clSaveSrv::ProcessLoop ()
00476 {
00477 time_t ttTime;
00478
00479 Log.Add(' ', "Entering process loop");
00480 if (iFormat == SAVS_FORMAT_WAV ||
00481 iFormat == SAVS_FORMAT_AIFF)
00482 {
00483 if (!CreateFile()) Stop();
00484 }
00485 else if (iFormat == SAVS_FORMAT_FLAC)
00486 {
00487 if (!CreateFile2()) Stop();
00488 }
00489 while (bRun)
00490 {
00491 if (access(SAVS_SHUTDOWNFILE, F_OK) == 0)
00492 {
00493 unlink(SAVS_SHUTDOWNFILE);
00494 Stop();
00495 break;
00496 }
00497 if (SOp.ReadN(InFrame, lFrameSize) != lFrameSize)
00498 {
00499 Log.Add('!', "clSockOp::ReadN() error", SOp.GetErrno());
00500 break;
00501 }
00502 if (iFormat == SAVS_FORMAT_WAV ||
00503 iFormat == SAVS_FORMAT_AIFF)
00504 {
00505 if (!WriteData()) break;
00506 }
00507 else if (iFormat == SAVS_FORMAT_FLAC)
00508 {
00509 if (!WriteData2()) break;
00510 }
00511 ttTime = time(NULL);
00512 if ((ttTime - ttTime % iFileTime) > ttFileStarted)
00513 {
00514 if (iFormat == SAVS_FORMAT_WAV ||
00515 iFormat == SAVS_FORMAT_AIFF)
00516 {
00517 if (!CreateFile()) break;
00518 }
00519 else if (iFormat == SAVS_FORMAT_FLAC)
00520 {
00521 if (!CreateFile2()) break;
00522 }
00523 }
00524 }
00525 Log.Add(' ', "Leaving process loop");
00526 }
00527
00528
00529 void clSaveSrv::Dither ()
00530 {
00531 int iSignMask;
00532 int iNoiseMask;
00533 long lSampleCntr;
00534 long lTempSample;
00535 GDT fDithScale;
00536 #ifndef USE_MERSENNE_TWISTER
00537 int *ipNoiseFrame = NoiseFrame;
00538 #endif
00539 GDT *fpInFrame = InFrame;
00540
00541 if (iBits == 8)
00542 {
00543 fDithScale = 0x7f000000;
00544 iSignMask = 0x00800000;
00545 iNoiseMask = 0x007fffff;
00546 unsigned char *ipOutFrame8 = OutFrame;
00547 for (lSampleCntr = 0; lSampleCntr < lFrameLen; lSampleCntr++)
00548 {
00549 #ifndef USE_MERSENNE_TWISTER
00550 int iRndVal = ipNoiseFrame[lSampleCntr];
00551 #else
00552 int iRndVal = (int) (MTR->randInt() & 0x7fffffff);
00553 #endif
00554 int iDithVal = (iRndVal & iSignMask) ?
00555 -(iRndVal & iNoiseMask) : (iRndVal & iNoiseMask);
00556 lTempSample =
00557 (long) (fpInFrame[lSampleCntr] * fDithScale) + iDithVal;
00558 ipOutFrame8[lSampleCntr] = (unsigned char)
00559 ((lTempSample >> 24) + 0x7f);
00560 }
00561 }
00562 else if (iBits == 16)
00563 {
00564 fDithScale = 0x7fff0000;
00565 iSignMask = 0x00008000;
00566 iNoiseMask = 0x00007fff;
00567 signed short *ipOutFrame16 = OutFrame;
00568 for (lSampleCntr = 0; lSampleCntr < lFrameLen; lSampleCntr++)
00569 {
00570 #ifndef USE_MERSENNE_TWISTER
00571 int iRndVal = ipNoiseFrame[lSampleCntr];
00572 #else
00573 int iRndVal = (int) (MTR->randInt() & 0x7fffffff);
00574 #endif
00575 int iDithVal = (iRndVal & iSignMask) ?
00576 -(iRndVal & iNoiseMask) : (iRndVal & iNoiseMask);
00577 lTempSample =
00578 (long) (fpInFrame[lSampleCntr] * fDithScale) + iDithVal;
00579 ipOutFrame16[lSampleCntr] = (signed short)
00580 (lTempSample >> 16);
00581 }
00582 }
00583 else if (iBits == 24)
00584 {
00585 fDithScale = 0x7fffff00;
00586 iSignMask = 0x00000080;
00587 iNoiseMask = 0x0000007f;
00588 signed int *ipOutFrame24 = OutFrame;
00589 for (lSampleCntr = 0; lSampleCntr < lFrameLen; lSampleCntr++)
00590 {
00591 #ifndef USE_MERSENNE_TWISTER
00592 int iRndVal = ipNoiseFrame[lSampleCntr];
00593 #else
00594 int iRndVal = (int) (MTR->randInt() & 0x7fffffff);
00595 #endif
00596 int iDithVal = (iRndVal & iSignMask) ?
00597 -(iRndVal & iNoiseMask) : (iRndVal & iNoiseMask);
00598 lTempSample =
00599 (long) (fpInFrame[lSampleCntr] * fDithScale) + iDithVal;
00600 ipOutFrame24[lSampleCntr] = (signed int)
00601 (lTempSample >> 8);
00602 }
00603 }
00604 }
00605
00606
00607 bool clSaveSrv::WriteData ()
00608 {
00609 char cpSndFileError[SAVS_SNDFILE_MSGLEN + 1];
00610
00611 if (iDither == 1)
00612 {
00613 Dither();
00614 if (iBits == 8)
00615 {
00616 if (sf_write_raw(spSndFile, OutFrame, (sf_count_t) lFrameLen) !=
00617 (sf_count_t) lFrameLen)
00618 {
00619 sf_error_str(spSndFile, cpSndFileError, SAVS_SNDFILE_MSGLEN);
00620 Log.Add('!', cpSndFileError);
00621 return false;
00622 }
00623 }
00624 else if (iBits == 16)
00625 {
00626 if (sf_write_short(spSndFile, OutFrame, (sf_count_t) lFrameLen) !=
00627 (sf_count_t) lFrameLen)
00628 {
00629 sf_error_str(spSndFile, cpSndFileError, SAVS_SNDFILE_MSGLEN);
00630 Log.Add('!', cpSndFileError);
00631 return false;
00632 }
00633 }
00634 else if (iBits == 24)
00635 {
00636 if (sf_write_int(spSndFile, OutFrame, (sf_count_t) lFrameLen) !=
00637 (sf_count_t) lFrameLen)
00638 {
00639 sf_error_str(spSndFile, cpSndFileError, SAVS_SNDFILE_MSGLEN);
00640 Log.Add('!', cpSndFileError);
00641 return false;
00642 }
00643 }
00644 }
00645 else
00646 {
00647 GDT *fpInFrame = InFrame;
00648 double *dpOutFrame = OutFrame;
00649 for (long lSampleCntr = 0; lSampleCntr < lFrameLen; lSampleCntr++)
00650 {
00651 dpOutFrame[lSampleCntr] = fpInFrame[lSampleCntr];
00652 }
00653 if (sf_write_double(spSndFile, dpOutFrame, (sf_count_t) lFrameLen) !=
00654 (sf_count_t) lFrameLen)
00655 {
00656 sf_error_str(spSndFile, cpSndFileError, SAVS_SNDFILE_MSGLEN);
00657 Log.Add('!', cpSndFileError);
00658 return false;
00659 }
00660 }
00661 return true;
00662 }
00663
00664
00665 bool clSaveSrv::WriteData2 ()
00666 {
00667 #ifdef USE_FLAC
00668 long lSampleCntr;
00669 FLAC__int32 *ipDest = FLACFrame;
00670
00671 if (iDither == 1)
00672 {
00673 Dither();
00674 }
00675 else
00676 {
00677 float *fpInFrame = InFrame;
00678 if (iBits == 8)
00679 DSP.Convert((unsigned char *) OutFrame, fpInFrame, lFrameLen);
00680 if (iBits == 16)
00681 DSP.Convert((signed short *) OutFrame, fpInFrame, lFrameLen, false);
00682 if (iBits == 24)
00683 DSP.Convert((signed int *) OutFrame, fpInFrame, lFrameLen, true);
00684 }
00685 if (iBits == 8)
00686 {
00687 unsigned char *ipSrc = OutFrame;
00688
00689 for (lSampleCntr = 0; lSampleCntr < lFrameLen; lSampleCntr++)
00690 ipDest[lSampleCntr] = (FLAC__int32) ipSrc[lSampleCntr] - 0x80;
00691 }
00692 else if (iBits == 16)
00693 {
00694 signed short *ipSrc = OutFrame;
00695
00696 for (lSampleCntr = 0; lSampleCntr < lFrameLen; lSampleCntr++)
00697 ipDest[lSampleCntr] = (FLAC__int32) ipSrc[lSampleCntr];
00698 }
00699 else if (iBits == 24)
00700 {
00701 signed int *ipSrc = OutFrame;
00702
00703 for (lSampleCntr = 0; lSampleCntr < lFrameLen; lSampleCntr++)
00704 ipDest[lSampleCntr] =
00705 ((FLAC__int32) ipSrc[lSampleCntr] >> 8);
00706 }
00707 if (!FLAC__stream_encoder_process_interleaved(spFLACEnc,
00708 ipDest, lFrameLen / sDataHdr.iChannels))
00709 return false;
00710 return true;
00711 #else
00712 return false;
00713 #endif
00714 }
00715
00716
00717
00718 clSaveSrv::clSaveSrv ()
00719 {
00720 bRun = true;
00721 iFileH = -1;
00722 spSndFile = NULL;
00723 #ifdef USE_FLAC
00724 spFLACEnc = NULL;
00725 #endif
00726 #ifdef USE_MERSENNE_TWISTER
00727 MTR = NULL;
00728 #endif
00729 Log.Open(SAVS_LOGFILE);
00730 Log.Add('*', "Starting");
00731 }
00732
00733
00734 clSaveSrv::~clSaveSrv ()
00735 {
00736 #ifdef USE_MERSENNE_TWISTER
00737 if (MTR != NULL) delete MTR;
00738 #endif
00739 #ifdef USE_FLAC
00740 if (spFLACEnc != NULL)
00741 {
00742 if (iFileH >= 0)
00743 {
00744 FLAC__stream_encoder_finish(spFLACEnc);
00745 close(iFileH);
00746 }
00747 FLAC__stream_encoder_delete(spFLACEnc);
00748 }
00749 #endif
00750 if (spSndFile != NULL) sf_close(spSndFile);
00751 Log.Add('*', "Ending");
00752 }
00753
00754
00755 int clSaveSrv::Main (int iArgC, char **cpArgV)
00756 {
00757 if (iArgC >= 2)
00758 {
00759 if (strcmp(cpArgV[1], "-D"))
00760 {
00761 bDaemon = true;
00762 }
00763 else if (strcmp(cpArgV[1], "--version"))
00764 {
00765 printf("%s v%i.%i.%i\n", cpArgV[0], SAVS_VERSMAJ,
00766 SAVS_VERSMIN, SAVS_VERSPL);
00767 printf("Copyright (C) 2001-2002 Jussi Laako\n");
00768 return 0;
00769 }
00770 else if (strcmp(cpArgV[1], "--help"))
00771 {
00772 printf("%s [-D|--version|--help]\n\n", cpArgV[0]);
00773 printf("-D start as daemon\n");
00774 printf("--version display version information\n");
00775 printf("--help display this help\n");
00776 return 0;
00777 }
00778 }
00779 if (bDaemon)
00780 {
00781 if (fork() != 0)
00782 {
00783 exit(0);
00784 }
00785 setsid();
00786 freopen("/dev/null", "r+", stderr);
00787 freopen("/dev/null", "r+", stdin);
00788 freopen("/dev/null", "r+", stdout);
00789 }
00790 if (!Initialize()) return 1;
00791 if (!ConnectStream()) return 2;
00792 ProcessLoop();
00793 return 0;
00794 }
00795
00796
00797 #ifdef USE_FLAC
00798
00799 FLAC__StreamEncoderWriteStatus clSaveSrv::FLACWrite (
00800 const FLAC__StreamEncoder *spFLACEnc, const FLAC__byte *cpBuffer,
00801 unsigned uiBytes, unsigned uiSamples, unsigned uiCurrFrame)
00802 {
00803 if (write(iFileH, cpBuffer, uiBytes) != (int) uiBytes)
00804 return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
00805 return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
00806 }
00807
00808
00809 void clSaveSrv::FLACMetaData (
00810 const FLAC__StreamEncoder *spFLACEnc,
00811 const FLAC__StreamMetadata *spFLACMetaData)
00812 {
00813
00814
00815 }
00816
00817 #endif