00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <pthread.h>
00024 #include <stdio.h>
00025 #include <string.h>
00026 #include <signal.h>
00027 #include <unistd.h>
00028 #include <limits.h>
00029 #include <math.h>
00030 #include <float.h>
00031 #include <sys/types.h>
00032 #include <sys/stat.h>
00033 #include <sys/socket.h>
00034 #include <netinet/in.h>
00035 #include <arpa/inet.h>
00036
00037 #include "ComediSrv.hh"
00038
00039
00040 static bool bDaemon = false;
00041 clComediSrv ComediSrv;
00042
00043
00044 int main (int argc, char *argv[])
00045 {
00046 return ComediSrv.Main(argc, argv);
00047 }
00048
00049
00050 void SigHandler (int iSigNum)
00051 {
00052 switch (iSigNum)
00053 {
00054 case SIGINT:
00055 ComediSrv.Log.Add('#', "Received SIGINT, terminating...");
00056 ComediSrv.Stop();
00057 break;
00058 case SIGHUP:
00059 ComediSrv.Log.Add('#', "Received SIGHUP, terminating...");
00060 ComediSrv.Stop();
00061 break;
00062 case SIGTERM:
00063 ComediSrv.Log.Add('#', "Received SIGTERM, terminating...");
00064 ComediSrv.Stop();
00065 break;
00066 default:
00067 ComediSrv.Log.Add('!', "Received unknown signal, terminating...");
00068 ComediSrv.Stop();
00069 }
00070 }
00071
00072
00073 void *WrapAudioInThread (void *vpParam)
00074 {
00075 return ComediSrv.AudioInThread(vpParam);
00076 }
00077
00078
00079 void *WrapServeClientThread (void *vpParam)
00080 {
00081 return ComediSrv.ServeClientThread(vpParam);
00082 }
00083
00084
00085 #ifdef USE_FLAC
00086
00087 FLAC__StreamEncoderWriteStatus WrapFLACWrite (
00088 const FLAC__StreamEncoder *spFLACEnc, const FLAC__byte cpBuffer[],
00089 unsigned uiBytes, unsigned uiSamples, unsigned uiCurrFrame,
00090 void *vpDataPtr)
00091 {
00092 clComediSrv *ComediSrvInst = (clComediSrv *) vpDataPtr;
00093
00094 return ComediSrvInst->FLACWrite(spFLACEnc, cpBuffer, uiBytes, uiSamples,
00095 uiCurrFrame);
00096 }
00097
00098
00099 void WrapFLACMetaData (
00100 const FLAC__StreamEncoder *spFLACEnc,
00101 const FLAC__StreamMetadata *spFLACMetaData,
00102 void *vpDataPtr)
00103 {
00104 clComediSrv *ComediSrvInst = (clComediSrv *) vpDataPtr;
00105
00106 ComediSrvInst->FLACMetaData(spFLACEnc, spFLACMetaData);
00107 }
00108
00109 #endif
00110
00111
00112 bool clComediSrv::GetAudioCfg (char *cpDevice, int *ipChannels,
00113 double *dpSampleRate, int *ipBits, double *dpRange, int *ipFragSize)
00114 {
00115 if (!Cfg.GetStr("Device", cpDevice))
00116 {
00117 Log.Add('!', "\"Device\" not found from configuration file");
00118 return false;
00119 }
00120 if (!Cfg.GetInt("Channels", ipChannels))
00121 {
00122 Log.Add('!', "\"Channels\" not found from configuration file");
00123 return false;
00124 }
00125 if (!Cfg.GetFlt("SampleRate", dpSampleRate))
00126 {
00127 Log.Add('!', "\"SampleRate\" not found from configuration file");
00128 return false;
00129 }
00130 if (!Cfg.GetInt("Bits", ipBits))
00131 {
00132 Log.Add('!', "\"Bits\" not found from configuration file");
00133 return false;
00134 }
00135 if (!Cfg.GetFlt("Range", dpRange))
00136 {
00137 Log.Add('!', "\"Range\" not found from configuration file");
00138 return false;
00139 }
00140 if (!Cfg.GetInt("FragSize", ipFragSize))
00141 {
00142 Log.Add('!', "\"FragSize\" not found from configuration file");
00143 return false;
00144 }
00145 return true;
00146 }
00147
00148
00149 bool clComediSrv::InitCompress (int iChannels, int iSampleRate, int iBits,
00150 int iFragSize, int iCompress)
00151 {
00152 if (iCompress == MSG_SOUND_COMPRESS_FLAC)
00153 {
00154 #ifdef USE_FLAC
00155 int iMaxLPCOrder;
00156 int iMinRiceOrder;
00157 int iMaxRiceOrder;
00158 FLAC__StreamEncoderState iEncState;
00159
00160 if (!Cfg.GetInt("FLACMaxLPCOrder", &iMaxLPCOrder))
00161 iMaxLPCOrder = 0;
00162 if (iMaxLPCOrder > (int) FLAC__MAX_LPC_ORDER)
00163 iMaxLPCOrder = FLAC__MAX_LPC_ORDER;
00164 if (!Cfg.GetInt("FLACMinRiceOrder", &iMinRiceOrder))
00165 iMinRiceOrder = 0;
00166 if (!Cfg.GetInt("FLACMaxRiceOrder", &iMaxRiceOrder))
00167 iMaxRiceOrder = 0;
00168 if (iMaxRiceOrder > (int) FLAC__MAX_RICE_PARTITION_ORDER)
00169 iMaxRiceOrder = FLAC__MAX_RICE_PARTITION_ORDER;
00170 FLACFrame.Size(iFragSize * sizeof(FLAC__int32));
00171
00172 spFLACEnc = FLAC__stream_encoder_new();
00173 if (spFLACEnc == NULL)
00174 {
00175 Log.Add('!', "FLAC constructor failed");
00176 return false;
00177 }
00178 FLAC__stream_encoder_set_streamable_subset(spFLACEnc,
00179 1);
00180 FLAC__stream_encoder_set_do_mid_side_stereo(spFLACEnc,
00181 0);
00182 FLAC__stream_encoder_set_loose_mid_side_stereo(spFLACEnc,
00183 0);
00184 FLAC__stream_encoder_set_channels(spFLACEnc,
00185 iChannels);
00186 FLAC__stream_encoder_set_bits_per_sample(spFLACEnc,
00187 iBits);
00188 FLAC__stream_encoder_set_sample_rate(spFLACEnc,
00189 iSampleRate);
00190 FLAC__stream_encoder_set_blocksize(spFLACEnc,
00191 iFragSize);
00192 FLAC__stream_encoder_set_max_lpc_order(spFLACEnc,
00193 iMaxLPCOrder);
00194 FLAC__stream_encoder_set_qlp_coeff_precision(spFLACEnc,
00195 0);
00196 FLAC__stream_encoder_set_do_qlp_coeff_prec_search(spFLACEnc,
00197 0);
00198 FLAC__stream_encoder_set_do_escape_coding(spFLACEnc,
00199 1);
00200 FLAC__stream_encoder_set_do_exhaustive_model_search(spFLACEnc,
00201 1);
00202 FLAC__stream_encoder_set_min_residual_partition_order(spFLACEnc,
00203 iMinRiceOrder);
00204 FLAC__stream_encoder_set_max_residual_partition_order(spFLACEnc,
00205 iMaxRiceOrder);
00206 FLAC__stream_encoder_set_rice_parameter_search_dist(spFLACEnc,
00207 0);
00208 FLAC__stream_encoder_set_total_samples_estimate(spFLACEnc,
00209 0);
00210 FLAC__stream_encoder_set_metadata(spFLACEnc,
00211 NULL, 0);
00212 FLAC__stream_encoder_set_write_callback(spFLACEnc,
00213 WrapFLACWrite);
00214 FLAC__stream_encoder_set_metadata_callback(spFLACEnc,
00215 WrapFLACMetaData);
00216 FLAC__stream_encoder_set_client_data(spFLACEnc,
00217 (void *) this);
00218
00219 iEncState = FLAC__stream_encoder_init(spFLACEnc);
00220 if (iEncState != FLAC__STREAM_ENCODER_OK)
00221 {
00222 Log.Add('!', FLAC__StreamEncoderStateString[iEncState]);
00223 return false;
00224 }
00225 #else
00226 return false;
00227 #endif
00228 }
00229 else return false;
00230
00231 return true;
00232 }
00233
00234
00235 #ifdef USE_FLAC
00236 void clComediSrv::Convert (FLAC__int32 *ipDest, const void *vpSrc,
00237 long lSamples, int iBits)
00238 {
00239 long lSampleCntr;
00240 GDT fScale;
00241 GDT *fpSrc = (GDT *) vpSrc;
00242
00243 fScale = (GDT) (pow(2.0, iBits - 1) - 1.0);
00244 for (lSampleCntr = 0; lSampleCntr < lSamples; lSampleCntr++)
00245 {
00246 ipDest[lSampleCntr] = (FLAC__int32)
00247 (fpSrc[lSampleCntr] * fScale + (GDT) 0.5);
00248 }
00249 }
00250 #endif
00251
00252
00253 clComediSrv::clComediSrv ()
00254 {
00255 bRun = true;
00256 iAudioBufSize = 0;
00257 iBlockCntr = 0;
00258 #ifdef USE_FLAC
00259 spFLACEnc = NULL;
00260 #endif
00261 Log.Open(COM_LOGFILE);
00262 Log.Add('*', "Starting");
00263 Cfg.SetFileName(COM_CFGFILE);
00264 }
00265
00266
00267 clComediSrv::~clComediSrv ()
00268 {
00269 #ifdef USE_FLAC
00270 if (spFLACEnc != NULL)
00271 {
00272 FLAC__stream_encoder_finish(spFLACEnc);
00273 FLAC__stream_encoder_delete(spFLACEnc);
00274 }
00275 #endif
00276 Log.Add('*', "Ending");
00277 }
00278
00279
00280 int clComediSrv::Main (int iArgC, char **cpArgV)
00281 {
00282 int iPort;
00283 int iSockH;
00284 void *vpAudioInRes;
00285 pthread_t ptidAudioIn;
00286 pthread_t ptidServeClient;
00287 clSockServ SServ;
00288
00289 signal(SIGINT, SigHandler);
00290 signal(SIGHUP, SigHandler);
00291 signal(SIGTERM, SigHandler);
00292 signal(SIGPIPE, SIG_IGN);
00293 signal(SIGFPE, SIG_IGN);
00294 if (iArgC >= 2)
00295 {
00296 if (strcmp(cpArgV[1], "-D"))
00297 {
00298 bDaemon = true;
00299 }
00300 else if (strcmp(cpArgV[1], "--version"))
00301 {
00302 printf("%s v%i.%i.%i\n", cpArgV[0], GLOBAL_VERSMAJ,
00303 GLOBAL_VERSMIN, GLOBAL_VERSPL);
00304 printf("Copyright (C) 2002 Jussi Laako\n");
00305 return 0;
00306 }
00307 else if (strcmp(cpArgV[1], "--help"))
00308 {
00309 printf("%s [-D|--version|--help]\n\n", cpArgV[0]);
00310 printf("-D start as daemon\n");
00311 printf("--version display version information\n");
00312 printf("--help display this help\n");
00313 return 0;
00314 }
00315 }
00316 if (bDaemon)
00317 {
00318 if (fork() != 0)
00319 {
00320 exit(0);
00321 }
00322 setsid();
00323 freopen("/dev/null", "r+", stderr);
00324 freopen("/dev/null", "r+", stdin);
00325 freopen("/dev/null", "r+", stdout);
00326 }
00327 if (!Cfg.GetInt("Port", &iPort))
00328 {
00329 Log.Add('!', "\"Port\" not found from configuration file");
00330 return 1;
00331 }
00332 SServ.Bind(iPort);
00333 pthread_create(&ptidAudioIn, NULL, WrapAudioInThread, NULL);
00334 while (bRun)
00335 {
00336 if (access(COM_SHUTDOWNFILE, F_OK) == 0)
00337 {
00338 unlink(COM_SHUTDOWNFILE);
00339 Stop();
00340 break;
00341 }
00342 iSockH = SServ.WaitForConnect(COM_CONNECT_TIMEOUT);
00343 if (iSockH >= 0)
00344 {
00345 pthread_create(&ptidServeClient, NULL, WrapServeClientThread,
00346 (void *) iSockH);
00347 pthread_detach(ptidServeClient);
00348 }
00349 }
00350 pthread_join(ptidAudioIn, &vpAudioInRes);
00351 if ((int) vpAudioInRes != 0) return ((int) vpAudioInRes);
00352 return 0;
00353 }
00354
00355
00356 void *clComediSrv::AudioInThread (void *vpParam)
00357 {
00358 int iChannels;
00359 int iBits;
00360 int iFragSize;
00361 int iSampleCount;
00362 int iCompress;
00363 int iComediVersion;
00364 int iDoubleClock;
00365 double dSampleRate;
00366 double dRange;
00367 char cpDevice[_POSIX_PATH_MAX + 1];
00368 char cpLogEntry[COM_LOGENTRY_SIZE];
00369 sigset_t sigsetThis;
00370 #ifndef BSDSYS
00371 uid_t uidCurrent;
00372 struct sched_param sSchedParam;
00373 #endif
00374 clAlloc RawBuf;
00375 clComediIO ComediIO;
00376 clDSPOp DSP;
00377 clSoundMsg Msg;
00378
00379 sigemptyset(&sigsetThis);
00380 sigaddset(&sigsetThis, SIGPIPE);
00381 sigaddset(&sigsetThis, SIGINT);
00382 sigaddset(&sigsetThis, SIGHUP);
00383 sigaddset(&sigsetThis, SIGFPE);
00384 pthread_sigmask(SIG_BLOCK, &sigsetThis, NULL);
00385
00386 GetAudioCfg(cpDevice, &iChannels, &dSampleRate, &iBits, &dRange,
00387 &iFragSize);
00388 if (!Cfg.GetInt("Compress", &iCompress))
00389 iCompress = MSG_SOUND_COMPRESS_NONE;
00390 if (!Cfg.GetInt("DoubleClock", &iDoubleClock))
00391 iDoubleClock = 0;
00392 sprintf(cpLogEntry, "Request %s: ch %i fs %g wl %i r %g", cpDevice,
00393 iChannels, dSampleRate, iBits, dRange);
00394 Log.Add(' ', cpLogEntry);
00395 if (!ComediIO.Open(cpDevice))
00396 {
00397 sprintf(cpLogEntry, "Unable to open device: %s",
00398 ComediIO.GetErrorMsg());
00399 Log.Add('!', cpLogEntry);
00400 Stop();
00401 return ((void *) 2);
00402 }
00403 if (iFragSize > 0)
00404 {
00405 if (!ComediIO.PcmBufferSizeSet(iFragSize * 2))
00406 {
00407 sprintf(cpLogEntry, "Unable to set buffer size: %s",
00408 ComediIO.GetErrorMsg());
00409 Log.Add('#', cpLogEntry);
00410 }
00411 }
00412 else
00413 {
00414 iFragSize = ComediIO.PcmBufferSizeGet() / 2;
00415 if (iFragSize <= 0)
00416 {
00417 sprintf(cpLogEntry,
00418 "Unable to get fragment size, making guess: %s",
00419 ComediIO.GetErrorMsg());
00420 Log.Add('!', cpLogEntry);
00421 iFragSize = COM_FRAG_SIZE_DEFAULT;
00422 }
00423 }
00424 sprintf(cpLogEntry, "Open %s: frag %i (%i) bytes",
00425 cpDevice, ComediIO.PcmBufferSizeGet() / 2, iFragSize);
00426 Log.Add(' ', cpLogEntry);
00427 iComediVersion = ComediIO.GetVersionCode();
00428 sprintf(cpLogEntry, "Comedi version %i.%i.%i",
00429 ((clComediIO::VERS_MASK_MAJ & iComediVersion) >> clComediIO::VERS_SHIFT_MAJ),
00430 ((clComediIO::VERS_MASK_MIN & iComediVersion) >> clComediIO::VERS_SHIFT_MIN),
00431 ((clComediIO::VERS_MASK_PL & iComediVersion) >> clComediIO::VERS_SHIFT_PL));
00432 Log.Add(' ', cpLogEntry);
00433 sprintf(cpLogEntry, "Driver %s, board %s",
00434 ComediIO.GetDriverName(),
00435 ComediIO.GetBoardName());
00436 Log.Add(' ', cpLogEntry);
00437
00438 iSampleCount = iFragSize / ComediIO.PcmGetIntSampleSize();
00439 if (iCompress == MSG_SOUND_COMPRESS_FLAC)
00440 {
00441 #ifdef USE_FLAC
00442 iAudioBufSize = iSampleCount * sizeof(FLAC__int32);
00443 #else
00444 iAudioBufSize = 0;
00445 #endif
00446 }
00447 else
00448 {
00449 iAudioBufSize = iSampleCount * sizeof(GDT);
00450 }
00451
00452 RawBuf.Size(iSampleCount * sizeof(GDT));
00453 RawBuf.Lock();
00454 AudioBuf.Size(iAudioBufSize);
00455 AudioBuf.Lock();
00456
00457 if (iCompress)
00458 {
00459 if (!InitCompress(iChannels, (int) (dSampleRate + 0.5), iBits,
00460 iSampleCount, iCompress))
00461 Stop();
00462 }
00463
00464 #ifndef BSDSYS
00465 uidCurrent = getuid();
00466 setuid(0);
00467 sSchedParam.sched_priority = sched_get_priority_min(SCHED_FIFO) +
00468 COM_INTHREAD_PRIORITY;
00469 if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &sSchedParam) != 0)
00470 Log.Add('#', "Warning: Unable to set scheduling parameters");
00471 setuid(uidCurrent);
00472 #endif
00473
00474 if (!ComediIO.PcmInStart(&dSampleRate, iChannels, dRange, COM_USE_DITHER,
00475 (iDoubleClock) ? true : false))
00476 {
00477 sprintf(cpLogEntry, "Unable to start PCM subdevice: %s",
00478 ComediIO.GetErrorMsg());
00479 Log.Add('!', cpLogEntry);
00480 Stop();
00481 }
00482 sprintf(cpLogEntry, "Actual fs %g", dSampleRate);
00483 Log.Add(' ', cpLogEntry);
00484 sHdr.iChannels = iChannels;
00485 sHdr.dSampleRate = dSampleRate;
00486 sHdr.iFragmentSize = iSampleCount;
00487 sHdr.iCompress = iCompress;
00488
00489 Log.Add(' ', "AudioIn thread running");
00490 while (bRun)
00491 {
00492 if (ComediIO.PcmInRead((GDT *) RawBuf, iSampleCount) < iSampleCount)
00493 {
00494 sprintf(cpLogEntry, "Error reading device: %s",
00495 ComediIO.GetErrorMsg());
00496 Log.Add('!', cpLogEntry);
00497 Stop();
00498 return ((void *) 2);
00499 }
00500 if (iCompress == MSG_SOUND_COMPRESS_FLAC)
00501 {
00502 #ifdef USE_FLAC
00503 Convert(FLACFrame, RawBuf, iSampleCount, iBits);
00504 if (!FLAC__stream_encoder_process_interleaved(spFLACEnc,
00505 FLACFrame, iSampleCount / iChannels))
00506 {
00507 Log.Add('!', "Compression error");
00508 Stop();
00509 return ((void *) 2);
00510 }
00511 #endif
00512 }
00513 else
00514 {
00515 #ifndef USE_RWLOCK
00516 MtxAudio.Wait();
00517 #else
00518 RWLAudio.WaitWrite();
00519 #endif
00520 Msg.SetData(AudioBuf, (GDT *) RawBuf, iSampleCount);
00521 iBlockCntr++;
00522 CndAudio.NotifyAll();
00523 #ifndef USE_RWLOCK
00524 MtxAudio.Release();
00525 #else
00526 RWLAudio.Release();
00527 #endif
00528 }
00529 }
00530 ComediIO.PcmInStop();
00531 ComediIO.PcmInClose();
00532 ComediIO.Close();
00533 Log.Add(' ', "AudioIn thread ending");
00534 return ((void *) 0);
00535 }
00536
00537
00538 void *clComediSrv::ServeClientThread (void *vpParam)
00539 {
00540 bool bConnected = true;
00541 int iFragBufCount;
00542 int iLocalBlockCntr;
00543 char cpLogEntry[COM_LOGENTRY_SIZE];
00544 char cpHdrMsg[GLOBAL_HEADER_LEN];
00545 socklen_t iAddrLen;
00546 struct sockaddr_in sPeerAddr;
00547 sigset_t sigsetThis;
00548 #ifndef BSDSYS
00549 uid_t uidCurrent;
00550 struct sched_param sSchedParam;
00551 #endif
00552 clAlloc OutBuf(iAudioBufSize);
00553 clSoundMsg Msg;
00554 clSockOp SOp((int) vpParam);
00555
00556 sigemptyset(&sigsetThis);
00557 sigaddset(&sigsetThis, SIGPIPE);
00558 sigaddset(&sigsetThis, SIGINT);
00559 sigaddset(&sigsetThis, SIGHUP);
00560 pthread_sigmask(SIG_BLOCK, &sigsetThis, NULL);
00561
00562 if (!Cfg.GetInt("BufferFrags", &iFragBufCount))
00563 iFragBufCount = COM_SOCKET_BUF_FRAGS;
00564 SOp.SetSendBufSize(iFragBufCount * iAudioBufSize);
00565 SOp.DisableNagle();
00566 SOp.SetTypeOfService(IPTOS_LOWDELAY);
00567 iAddrLen = sizeof(sPeerAddr);
00568 SOp.GetPeerName((struct sockaddr *) &sPeerAddr, &iAddrLen);
00569 sprintf(cpLogEntry, "Client connected from %s:%i",
00570 inet_ntoa(sPeerAddr.sin_addr), ntohs(sPeerAddr.sin_port));
00571 Log.Add('+', cpLogEntry);
00572 Msg.SetStart(cpHdrMsg, &sHdr);
00573 if (SOp.WriteN(cpHdrMsg, GLOBAL_HEADER_LEN) < GLOBAL_HEADER_LEN)
00574 bConnected = false;
00575 OutBuf.Lock();
00576 if (sHdr.iCompress)
00577 {
00578 if (SOp.WriteN(CompHead, CompHead.GetSize()) < CompHead.GetSize())
00579 bConnected = false;
00580 }
00581
00582 #ifndef BSDSYS
00583 uidCurrent = getuid();
00584 setuid(0);
00585 sSchedParam.sched_priority = sched_get_priority_min(SCHED_FIFO) +
00586 COM_OUTTHREAD_PRIORITY;
00587 if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &sSchedParam) != 0)
00588 Log.Add('#', "Warning: Unable to set scheduling parameters");
00589 setuid(uidCurrent);
00590 #endif
00591
00592 iLocalBlockCntr = iBlockCntr;
00593 while (bRun && bConnected)
00594 {
00595 MtxAudio.Wait();
00596 CndAudio.Wait(MtxAudio.GetPtr());
00597 #ifdef USE_RWLOCK
00598 MtxAudio.Release();
00599 RWLAudio.WaitRead();
00600 #endif
00601 if (iAudioBufSize > OutBuf.GetSize())
00602 {
00603 OutBuf.UnLock();
00604 OutBuf.Size(iAudioBufSize);
00605 OutBuf.Lock();
00606 }
00607 memcpy(OutBuf, AudioBuf, iAudioBufSize);
00608 iLocalBlockCntr++;
00609 if (iLocalBlockCntr != iBlockCntr)
00610 {
00611 printf("comedisrv: %i blocks lost\n",
00612 iBlockCntr - iLocalBlockCntr);
00613 iLocalBlockCntr = iBlockCntr;
00614 }
00615 #ifndef USE_RWLOCK
00616 MtxAudio.Release();
00617 #else
00618 RWLAudio.Release();
00619 #endif
00620 if (SOp.WriteN(OutBuf, iAudioBufSize) < iAudioBufSize)
00621 bConnected = false;
00622 }
00623 sprintf(cpLogEntry, "Client from %s:%i disconnected",
00624 inet_ntoa(sPeerAddr.sin_addr), ntohs(sPeerAddr.sin_port));
00625 Log.Add('-', cpLogEntry);
00626 return NULL;
00627 }
00628
00629
00630 #ifdef USE_FLAC
00631
00632 FLAC__StreamEncoderWriteStatus clComediSrv::FLACWrite (
00633 const FLAC__StreamEncoder *spFLACEnc, const FLAC__byte *cpBuffer,
00634 unsigned uiBytes, unsigned uiSamples, unsigned uiCurrFrame)
00635 {
00636 static bool bFirst = true;
00637 FLAC__StreamEncoderWriteStatus iEncStatus =
00638 FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
00639
00640 #ifndef USE_RWLOCK
00641 MtxAudio.Wait();
00642 #else
00643 RWLAudio.WaitWrite();
00644 #endif
00645 if (bFirst)
00646 {
00647 CompHead.Size(uiBytes);
00648 memcpy(CompHead, cpBuffer, uiBytes);
00649 bFirst = false;
00650 }
00651 else
00652 {
00653 iAudioBufSize = uiBytes;
00654 if (iAudioBufSize > AudioBuf.GetSize())
00655 {
00656 AudioBuf.UnLock();
00657 AudioBuf.Size(iAudioBufSize);
00658 AudioBuf.Lock();
00659 }
00660 memcpy(AudioBuf, cpBuffer, iAudioBufSize);
00661 iBlockCntr++;
00662 CndAudio.NotifyAll();
00663 }
00664 #ifndef USE_RWLOCK
00665 MtxAudio.Release();
00666 #else
00667 RWLAudio.Release();
00668 #endif
00669 return iEncStatus;
00670 }
00671
00672
00673 void clComediSrv::FLACMetaData (
00674 const FLAC__StreamEncoder *spFLACEnc,
00675 const FLAC__StreamMetadata *spFLACMetaData)
00676 {
00677 }
00678
00679 #endif