Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

ComediSrv.cc

Go to the documentation of this file.
00001 /*
00002 
00003     ComediServer
00004     Copyright (C) 2002 Jussi Laako
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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);  // non-default
00200         FLAC__stream_encoder_set_do_exhaustive_model_search(spFLACEnc,
00201             1);  // non-default
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

Generated on Sun Oct 26 19:11:19 2003 for HASAS by doxygen 1.3.3