Changed audio system to use external driver modules.
This commit is contained in:
parent
d6e0f5e675
commit
85954c5498
4
Makefile
4
Makefile
@ -17,8 +17,8 @@ SRC += cwSerialPort.cpp cwSerialPortSrv.cpp
|
|||||||
HDR += cwMidi.h cwMidiPort.h
|
HDR += cwMidi.h cwMidiPort.h
|
||||||
SRC += cwMidi.cpp cwMidiPort.cpp cwMidiAlsa.cpp
|
SRC += cwMidi.cpp cwMidiPort.cpp cwMidiAlsa.cpp
|
||||||
|
|
||||||
HDR += cwAudioBuf.h cwAudioPort.h cwAudioPortAlsa.h
|
HDR += cwAudioBuf.h cwAudioDevice.h cwAudioDeviceAlsa.h
|
||||||
SRC += cwAudioBuf.cpp cwAudioPort.cpp cwAudioPortAlsa.cpp
|
SRC += cwAudioBuf.cpp cwAudioDevice.cpp cwAudioDeviceAlsa.cpp cwAudioDeviceTest.cpp
|
||||||
|
|
||||||
|
|
||||||
LIBS = -lpthread -lwebsockets -lasound
|
LIBS = -lpthread -lwebsockets -lasound
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "cwMem.h"
|
#include "cwMem.h"
|
||||||
#include "cwTime.h"
|
#include "cwTime.h"
|
||||||
#include "cwTextBuf.h"
|
#include "cwTextBuf.h"
|
||||||
#include "cwAudioPort.h"
|
#include "cwAudioDevice.h"
|
||||||
#include "cwAudioBuf.h"
|
#include "cwAudioBuf.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -853,13 +853,11 @@ void cw::audio::buf::inputToOutput( unsigned iDevIdx, unsigned oDevIdx )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cw::audio::buf::report( textBuf::handle_t tbH )
|
void cw::audio::buf::report()
|
||||||
{
|
{
|
||||||
unsigned i,j,k;
|
unsigned i,j,k;
|
||||||
for(i=0; i<_theBuf.devCnt; ++i)
|
for(i=0; i<_theBuf.devCnt; ++i)
|
||||||
{
|
{
|
||||||
textBuf::print(tbH,"%i ",i);
|
|
||||||
|
|
||||||
for(j=0; j<kIoApCnt; ++j)
|
for(j=0; j<kIoApCnt; ++j)
|
||||||
{
|
{
|
||||||
cmApIO* ip = _theBuf.devArray[i].ioArray + j;
|
cmApIO* ip = _theBuf.devArray[i].ioArray + j;
|
||||||
@ -875,13 +873,11 @@ void cw::audio::buf::report( textBuf::handle_t tbH )
|
|||||||
fn += cp->fn;
|
fn += cp->fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
textBuf::print(tbH,"%s - i:%7i o:%7i f:%7i n:%7i err %s:%7i ",
|
cwLogInfo("%i : %s - i:%7i o:%7i f:%7i n:%7i err %s:%7i ",
|
||||||
j==0?"IN":"OUT",
|
i,j==0?"IN ":"OUT",
|
||||||
ii,oi,fn,ip->n, (j==0?"over":"under"), ip->faultCnt);
|
ii,oi,fn,ip->n, (j==0?"over":"under"), ip->faultCnt);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
textBuf::print(tbH,"\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ namespace cw
|
|||||||
void inputToOutput( unsigned inDevIdx, unsigned outDevIdx );
|
void inputToOutput( unsigned inDevIdx, unsigned outDevIdx );
|
||||||
|
|
||||||
// Print the current buffer state.
|
// Print the current buffer state.
|
||||||
void report( textBuf::handle_t tbH );
|
void report();
|
||||||
|
|
||||||
// Run a buffer usage simulation to test the class. cmAudioPortTest.c calls this function.
|
// Run a buffer usage simulation to test the class. cmAudioPortTest.c calls this function.
|
||||||
void test();
|
void test();
|
||||||
|
217
cwAudioDevice.cpp
Normal file
217
cwAudioDevice.cpp
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
#include "cwCommon.h"
|
||||||
|
#include "cwLog.h"
|
||||||
|
#include "cwCommonImpl.h"
|
||||||
|
#include "cwMem.h"
|
||||||
|
#include "cwTime.h"
|
||||||
|
#include "cwAudioDevice.h"
|
||||||
|
#include "cwText.h"
|
||||||
|
|
||||||
|
namespace cw
|
||||||
|
{
|
||||||
|
namespace audio
|
||||||
|
{
|
||||||
|
namespace device
|
||||||
|
{
|
||||||
|
typedef struct drv_str
|
||||||
|
{
|
||||||
|
unsigned begIdx;
|
||||||
|
unsigned endIdx;
|
||||||
|
driver_t* drv;
|
||||||
|
struct drv_str* link;
|
||||||
|
} drv_t;
|
||||||
|
|
||||||
|
typedef struct device_str
|
||||||
|
{
|
||||||
|
drv_t* drvList = nullptr;
|
||||||
|
unsigned nextDrvIdx = 0;
|
||||||
|
} device_t;
|
||||||
|
|
||||||
|
inline device_t* _handleToPtr( handle_t h ){ return handleToPtr<handle_t,device_t>(h); }
|
||||||
|
|
||||||
|
cw::rc_t _destroy( device_t* p )
|
||||||
|
{
|
||||||
|
drv_t* d = p->drvList;
|
||||||
|
while( d != nullptr )
|
||||||
|
{
|
||||||
|
drv_t* d0 = d->link;
|
||||||
|
memRelease(d);
|
||||||
|
d = d0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memRelease(p);
|
||||||
|
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
drv_t* _indexToDriver( device_t* p, unsigned idx )
|
||||||
|
{
|
||||||
|
drv_t* l = p->drvList;
|
||||||
|
for(; l != nullptr; l=l->link )
|
||||||
|
if( l->begIdx <= idx && idx <= l->endIdx )
|
||||||
|
return l;
|
||||||
|
|
||||||
|
cwLogError(kInvalidArgRC,"An invalid audio device index (%) was requested.",idx);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
drv_t* _indexToDriver( handle_t h, unsigned idx )
|
||||||
|
{
|
||||||
|
device_t* p = _handleToPtr(h);
|
||||||
|
return _indexToDriver(p,idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::audio::device::create( handle_t& hRef )
|
||||||
|
{
|
||||||
|
rc_t rc;
|
||||||
|
if((rc = destroy(hRef)) != kOkRC)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
device_t* p = memAllocZ<device_t>();
|
||||||
|
hRef.set(p);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::audio::device::destroy( handle_t& hRef )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
if( !hRef.isValid() )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
device_t* p = _handleToPtr(hRef);
|
||||||
|
|
||||||
|
if((rc = _destroy(p)) != kOkRC )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
hRef.clear();
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::audio::device::registerDriver( handle_t h, driver_t* drv )
|
||||||
|
{
|
||||||
|
device_t* p = _handleToPtr(h);
|
||||||
|
|
||||||
|
unsigned n = drv->deviceCount( drv );
|
||||||
|
if( n > 0 )
|
||||||
|
{
|
||||||
|
drv_t* d = memAllocZ<drv_t>();
|
||||||
|
|
||||||
|
d->begIdx = p->nextDrvIdx;
|
||||||
|
p->nextDrvIdx += n;
|
||||||
|
d->endIdx = p->nextDrvIdx-1;
|
||||||
|
d->drv = drv;
|
||||||
|
d->link = p->drvList;
|
||||||
|
p->drvList = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned cw::audio::device::deviceCount( handle_t h )
|
||||||
|
{
|
||||||
|
device_t* p = _handleToPtr(h);
|
||||||
|
return p->nextDrvIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned cw::audio::device::deviceLabelToIndex( handle_t h, const char* label )
|
||||||
|
{
|
||||||
|
unsigned n = deviceCount(h);
|
||||||
|
unsigned i;
|
||||||
|
for(i=0; i<n; ++i)
|
||||||
|
{
|
||||||
|
const char* s = deviceLabel(h,i);
|
||||||
|
if( textCompare(s,label)==0)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return kInvalidIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* cw::audio::device::deviceLabel( handle_t h, unsigned devIdx )
|
||||||
|
{
|
||||||
|
drv_t* d;
|
||||||
|
if((d = _indexToDriver(h,devIdx)) != nullptr )
|
||||||
|
return d->drv->deviceLabel( d->drv, devIdx - d->begIdx );
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned cw::audio::device::deviceChannelCount( handle_t h, unsigned devIdx, bool inputFl )
|
||||||
|
{
|
||||||
|
drv_t* d;
|
||||||
|
if((d = _indexToDriver(h,devIdx)) != nullptr )
|
||||||
|
return d->drv->deviceChannelCount( d->drv, devIdx - d->begIdx, inputFl );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double cw::audio::device::deviceSampleRate( handle_t h, unsigned devIdx )
|
||||||
|
{
|
||||||
|
drv_t* d;
|
||||||
|
if((d = _indexToDriver(h,devIdx)) != nullptr )
|
||||||
|
return d->drv->deviceSampleRate( d->drv, devIdx - d->begIdx );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned cw::audio::device::deviceFramesPerCycle( handle_t h, unsigned devIdx, bool inputFl )
|
||||||
|
{
|
||||||
|
drv_t* d;
|
||||||
|
if((d = _indexToDriver(h,devIdx)) != nullptr )
|
||||||
|
return d->drv->deviceFramesPerCycle( d->drv, devIdx - d->begIdx, inputFl );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::audio::device::deviceSetup( handle_t h, unsigned devIdx, double sr, unsigned frmPerCycle, cbFunc_t cb, void* cbData )
|
||||||
|
{
|
||||||
|
drv_t* d;
|
||||||
|
if((d = _indexToDriver(h,devIdx)) != nullptr )
|
||||||
|
return d->drv->deviceSetup( d->drv, devIdx - d->begIdx, sr, frmPerCycle, cb, cbData );
|
||||||
|
return kInvalidArgRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::audio::device::deviceStart( handle_t h, unsigned devIdx )
|
||||||
|
{
|
||||||
|
drv_t* d;
|
||||||
|
if((d = _indexToDriver(h,devIdx)) != nullptr )
|
||||||
|
return d->drv->deviceStart( d->drv, devIdx - d->begIdx );
|
||||||
|
return kInvalidArgRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::audio::device::deviceStop( handle_t h, unsigned devIdx )
|
||||||
|
{
|
||||||
|
drv_t* d;
|
||||||
|
if((d = _indexToDriver(h,devIdx)) != nullptr )
|
||||||
|
return d->drv->deviceStop( d->drv, devIdx - d->begIdx );
|
||||||
|
return kInvalidArgRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cw::audio::device::deviceIsStarted(handle_t h, unsigned devIdx )
|
||||||
|
{
|
||||||
|
drv_t* d;
|
||||||
|
if((d = _indexToDriver(h,devIdx)) != nullptr )
|
||||||
|
return d->drv->deviceIsStarted( d->drv, devIdx - d->begIdx );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cw::audio::device::deviceRealTimeReport( handle_t h, unsigned devIdx )
|
||||||
|
{
|
||||||
|
drv_t* d;
|
||||||
|
if((d = _indexToDriver(h,devIdx)) != nullptr )
|
||||||
|
d->drv->deviceRealTimeReport( d->drv, devIdx - d->begIdx );
|
||||||
|
}
|
||||||
|
|
||||||
|
void cw::audio::device::report( handle_t h )
|
||||||
|
{
|
||||||
|
for(unsigned i=0; i<deviceCount(h); ++i)
|
||||||
|
{
|
||||||
|
cwLogInfo( "%8.1f in:%i (%i) out:%i (%i) %s",
|
||||||
|
deviceSampleRate(h,i),
|
||||||
|
deviceChannelCount(h,i,true), deviceFramesPerCycle(h,i,true),
|
||||||
|
deviceChannelCount(h,i,false), deviceFramesPerCycle(h,i,false),
|
||||||
|
deviceLabel(h,i));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
95
cwAudioDevice.h
Normal file
95
cwAudioDevice.h
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#ifndef cwAudioDevice_H
|
||||||
|
#define cwAudioDevice_H
|
||||||
|
|
||||||
|
namespace cw
|
||||||
|
{
|
||||||
|
namespace audio
|
||||||
|
{
|
||||||
|
namespace device
|
||||||
|
{
|
||||||
|
typedef float sample_t;
|
||||||
|
|
||||||
|
// audioPacket_t flags
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
kInterleavedApFl = 0x01, // The audio samples are interleaved.
|
||||||
|
kFloatApFl = 0x02 // The audio samples are single precision floating point values.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Audio packet record used by the audioPacket_t callback.
|
||||||
|
// Audio ports send and receive audio using this data structure.
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned devIdx; // device associated with packet
|
||||||
|
unsigned begChIdx; // first device channel
|
||||||
|
unsigned chCnt; // count of channels
|
||||||
|
unsigned audioFramesCnt; // samples per channel (see note below)
|
||||||
|
unsigned bitsPerSample; // bits per sample word
|
||||||
|
unsigned flags; // kInterleavedApFl | kFloatApFl
|
||||||
|
void* audioBytesPtr; // pointer to sample data
|
||||||
|
void* cbArg; // user defined argument passed in via deviceSetup()
|
||||||
|
time::spec_t timeStamp; // Packet time stamp.
|
||||||
|
} audioPacket_t;
|
||||||
|
|
||||||
|
|
||||||
|
// Audio port callback signature.
|
||||||
|
// inPktArray[inPktCnt] are full packets of audio coming from the ADC to the application.
|
||||||
|
// outPktArray[outPktCnt] are empty packets of audio which will be filled by the application
|
||||||
|
// and then sent to the DAC.
|
||||||
|
//
|
||||||
|
// The value of audioFrameCnt gives the number of samples per channel which are available
|
||||||
|
// in the packet data buffer 'audioBytesPtr'. The callback function may decrease this number in
|
||||||
|
// output packets if the number of samples available is less than the size of the buffer.
|
||||||
|
// It is the responsibility of the calling audio port to notice this change and pass the new,
|
||||||
|
// decreased number of samples to the hardware.
|
||||||
|
//
|
||||||
|
// In general it should be assmed that this call is made from a system thread which is not
|
||||||
|
// the same as the application thread.
|
||||||
|
// The usual thread safety precautions should therefore be taken if this function implementation
|
||||||
|
// interacts with data structures also handled by the application. The audio buffer class (\see cmApBuf.h)
|
||||||
|
// is designed to provide a safe and efficient way to communicate between
|
||||||
|
// the audio thread and the application.
|
||||||
|
typedef void (*cbFunc_t)( audioPacket_t* inPktArray, unsigned inPktCnt, audioPacket_t* outPktArray, unsigned outPktCnt );
|
||||||
|
|
||||||
|
typedef struct driver_str
|
||||||
|
{
|
||||||
|
void* drvArg;
|
||||||
|
rc_t (*deviceCount)( struct driver_str* drvArg);
|
||||||
|
const char* (*deviceLabel)( struct driver_str* drvArg, unsigned devIdx );
|
||||||
|
unsigned (*deviceChannelCount)( struct driver_str* drvArg, unsigned devIdx, bool inputFl );
|
||||||
|
double (*deviceSampleRate)( struct driver_str* drvArg, unsigned devIdx );
|
||||||
|
unsigned (*deviceFramesPerCycle)( struct driver_str* drvArg, unsigned devIdx, bool inputFl );
|
||||||
|
rc_t (*deviceSetup)( struct driver_str* drvArg, unsigned devIdx, double sr, unsigned frmPerCycle, cbFunc_t cb, void* cbData );
|
||||||
|
rc_t (*deviceStart)( struct driver_str* drvArg, unsigned devIdx );
|
||||||
|
rc_t (*deviceStop)( struct driver_str* drvArg, unsigned devIdx );
|
||||||
|
bool (*deviceIsStarted)( struct driver_str* drvArg, unsigned devIdx );
|
||||||
|
void (*deviceRealTimeReport)( struct driver_str* drvArg, unsigned devIdx );
|
||||||
|
} driver_t;
|
||||||
|
|
||||||
|
typedef handle<struct device_str> handle_t;
|
||||||
|
|
||||||
|
rc_t create( handle_t& hRef );
|
||||||
|
rc_t destroy( handle_t& hRef );
|
||||||
|
|
||||||
|
rc_t registerDriver( handle_t h, driver_t* drv );
|
||||||
|
|
||||||
|
unsigned deviceCount( handle_t h );
|
||||||
|
unsigned deviceLabelToIndex( handle_t h, const char* label );
|
||||||
|
const char* deviceLabel( handle_t h, unsigned devIdx );
|
||||||
|
unsigned deviceChannelCount( handle_t h, unsigned devIdx, bool inputFl );
|
||||||
|
double deviceSampleRate( handle_t h, unsigned devIdx );
|
||||||
|
unsigned deviceFramesPerCycle( handle_t h, unsigned devIdx, bool inputFl );
|
||||||
|
rc_t deviceSetup( handle_t h, unsigned devIdx, double sr, unsigned frmPerCycle, cbFunc_t cb, void* cbData );
|
||||||
|
rc_t deviceStart( handle_t h, unsigned devIdx );
|
||||||
|
rc_t deviceStop( handle_t h, unsigned devIdx );
|
||||||
|
bool deviceIsStarted( handle_t h, unsigned devIdx );
|
||||||
|
void deviceRealTimeReport( handle_t h, unsigned devIdx );
|
||||||
|
|
||||||
|
void report( handle_t h );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
37
cwAudioDeviceAlsa.h
Normal file
37
cwAudioDeviceAlsa.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef cwAudioDeviceAlsa_H
|
||||||
|
#define cwAudioDeviceAlsa_H
|
||||||
|
|
||||||
|
|
||||||
|
namespace cw
|
||||||
|
{
|
||||||
|
namespace audio
|
||||||
|
{
|
||||||
|
namespace device
|
||||||
|
{
|
||||||
|
namespace alsa
|
||||||
|
{
|
||||||
|
typedef handle<struct alsa_str> handle_t;
|
||||||
|
|
||||||
|
rc_t create( handle_t& hRef, struct driver_str*& drvRef );
|
||||||
|
rc_t destroy( handle_t& hRef );
|
||||||
|
|
||||||
|
unsigned deviceCount( struct driver_str* drv);
|
||||||
|
const char* deviceLabel( struct driver_str* drv, unsigned devIdx );
|
||||||
|
unsigned deviceChannelCount( struct driver_str* drv, unsigned devIdx, bool inputFl );
|
||||||
|
double deviceSampleRate( struct driver_str* drv, unsigned devIdx );
|
||||||
|
unsigned deviceFramesPerCycle( struct driver_str* drv, unsigned devIdx, bool inputFl );
|
||||||
|
rc_t deviceSetup( struct driver_str* drv, unsigned devIdx, double sr, unsigned frmPerCycle, cbFunc_t cbFunc, void* cbArg );
|
||||||
|
rc_t deviceStart( struct driver_str* drv, unsigned devIdx );
|
||||||
|
rc_t deviceStop( struct driver_str* drv, unsigned devIdx );
|
||||||
|
bool deviceIsStarted( struct driver_str* drv, unsigned devIdx );
|
||||||
|
void deviceRealTimeReport( struct driver_str* drv, unsigned devIdx );
|
||||||
|
|
||||||
|
void report(handle_t h );
|
||||||
|
void report();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -2,375 +2,12 @@
|
|||||||
#include "cwLog.h"
|
#include "cwLog.h"
|
||||||
#include "cwCommonImpl.h"
|
#include "cwCommonImpl.h"
|
||||||
#include "cwMem.h"
|
#include "cwMem.h"
|
||||||
#include "cwTextBuf.h"
|
|
||||||
#include "cwTime.h"
|
#include "cwTime.h"
|
||||||
#include "cwAudioPort.h"
|
#include "cwTextBuf.h"
|
||||||
|
#include "cwAudioDevice.h"
|
||||||
#include "cwAudioBuf.h"
|
#include "cwAudioBuf.h"
|
||||||
|
#include "cwAudioDeviceAlsa.h"
|
||||||
|
#include "cwAudioDeviceTest.h"
|
||||||
#ifdef cwLINUX
|
|
||||||
#include "cwAudioPortAlsa.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef cwOSX
|
|
||||||
#include "cmAudioPortOsx.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace cw
|
|
||||||
{
|
|
||||||
namespace audio
|
|
||||||
{
|
|
||||||
namespace device
|
|
||||||
{
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned begDevIdx;
|
|
||||||
unsigned endDevIdx;
|
|
||||||
|
|
||||||
rc_t (*initialize)( unsigned baseApDevIdx );
|
|
||||||
rc_t (*finalize)();
|
|
||||||
rc_t (*deviceCount)();
|
|
||||||
const char* (*deviceLabel)( unsigned devIdx );
|
|
||||||
unsigned (*deviceChannelCount)( unsigned devIdx, bool inputFl );
|
|
||||||
double (*deviceSampleRate)( unsigned devIdx );
|
|
||||||
unsigned (*deviceFramesPerCycle)( unsigned devIdx, bool inputFl );
|
|
||||||
rc_t (*deviceSetup)( unsigned devIdx, double sr, unsigned frmPerCycle, cbFunc_t cb, void* cbData );
|
|
||||||
rc_t (*deviceStart)( unsigned devIdx );
|
|
||||||
rc_t (*deviceStop)( unsigned devIdx );
|
|
||||||
bool (*deviceIsStarted)( unsigned devIdx );
|
|
||||||
|
|
||||||
} cmApDriver_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
cmApDriver_t* drvArray;
|
|
||||||
unsigned drvCnt;
|
|
||||||
unsigned devCnt;
|
|
||||||
} cmAp_t;
|
|
||||||
|
|
||||||
cmAp_t* _ap = NULL;
|
|
||||||
|
|
||||||
rc_t _cmApIndexToDev( unsigned devIdx, cmApDriver_t** drvPtrPtr, unsigned* devIdxPtr )
|
|
||||||
{
|
|
||||||
assert( drvPtrPtr != NULL && devIdxPtr != NULL );
|
|
||||||
*drvPtrPtr = NULL;
|
|
||||||
*devIdxPtr = kInvalidIdx;
|
|
||||||
|
|
||||||
unsigned i;
|
|
||||||
for(i=0; i<_ap->drvCnt; ++i)
|
|
||||||
if( _ap->drvArray[i].begDevIdx != kInvalidIdx )
|
|
||||||
if( (_ap->drvArray[i].begDevIdx <= devIdx) && (devIdx <= _ap->drvArray[i].endDevIdx) )
|
|
||||||
{
|
|
||||||
*drvPtrPtr = _ap->drvArray + i;
|
|
||||||
*devIdxPtr = devIdx - _ap->drvArray[i].begDevIdx;
|
|
||||||
return kOkRC;
|
|
||||||
}
|
|
||||||
|
|
||||||
return cwLogError(kInvalidIdRC,"The audio port device index %i is not valid.",devIdx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cw::rc_t cw::audio::device::initialize()
|
|
||||||
{
|
|
||||||
rc_t rc = kOkRC;
|
|
||||||
if((rc = finalize()) != kOkRC )
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
_ap = memAllocZ<cmAp_t>(1);
|
|
||||||
|
|
||||||
_ap->drvCnt = 1;
|
|
||||||
_ap->drvArray = memAllocZ<cmApDriver_t>(_ap->drvCnt);
|
|
||||||
cmApDriver_t* dp = _ap->drvArray;
|
|
||||||
|
|
||||||
#ifdef cwOSX
|
|
||||||
dp->initialize = cmApOsxInitialize;
|
|
||||||
dp->finalize = cmApOsxFinalize;
|
|
||||||
dp->deviceCount = cmApOsxDeviceCount;
|
|
||||||
dp->deviceLabel = cmApOsxDeviceLabel;
|
|
||||||
dp->deviceChannelCount = cmApOsxDeviceChannelCount;
|
|
||||||
dp->deviceSampleRate = cmApOsxDeviceSampleRate;
|
|
||||||
dp->deviceFramesPerCycle = cmApOsxDeviceFramesPerCycle;
|
|
||||||
dp->deviceSetup = cmApOsxDeviceSetup;
|
|
||||||
dp->deviceStart = cmApOsxDeviceStart;
|
|
||||||
dp->deviceStop = cmApOsxDeviceStop;
|
|
||||||
dp->deviceIsStarted = cmApOsxDeviceIsStarted;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef cwLINUX
|
|
||||||
dp->initialize = alsa::initialize;
|
|
||||||
dp->finalize = alsa::finalize;
|
|
||||||
dp->deviceCount = alsa::deviceCount;
|
|
||||||
dp->deviceLabel = alsa::deviceLabel;
|
|
||||||
dp->deviceChannelCount = alsa::deviceChannelCount;
|
|
||||||
dp->deviceSampleRate = alsa::deviceSampleRate;
|
|
||||||
dp->deviceFramesPerCycle = alsa::deviceFramesPerCycle;
|
|
||||||
dp->deviceSetup = alsa::deviceSetup;
|
|
||||||
dp->deviceStart = alsa::deviceStart;
|
|
||||||
dp->deviceStop = alsa::deviceStop;
|
|
||||||
dp->deviceIsStarted = alsa::deviceIsStarted;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
dp = _ap->drvArray + 1;
|
|
||||||
|
|
||||||
dp->initialize = cmApFileInitialize;
|
|
||||||
dp->finalize = cmApFileFinalize;
|
|
||||||
dp->deviceCount = cmApFileDeviceCount;
|
|
||||||
dp->deviceLabel = cmApFileDeviceLabel;
|
|
||||||
dp->deviceChannelCount = cmApFileDeviceChannelCount;
|
|
||||||
dp->deviceSampleRate = cmApFileDeviceSampleRate;
|
|
||||||
dp->deviceFramesPerCycle = cmApFileDeviceFramesPerCycle;
|
|
||||||
dp->deviceSetup = cmApFileDeviceSetup;
|
|
||||||
dp->deviceStart = cmApFileDeviceStart;
|
|
||||||
dp->deviceStop = cmApFileDeviceStop;
|
|
||||||
dp->deviceIsStarted = cmApFileDeviceIsStarted;
|
|
||||||
|
|
||||||
dp = _ap->drvArray + 2;
|
|
||||||
|
|
||||||
dp->initialize = cmApAggInitialize;
|
|
||||||
dp->finalize = cmApAggFinalize;
|
|
||||||
dp->deviceCount = cmApAggDeviceCount;
|
|
||||||
dp->deviceLabel = cmApAggDeviceLabel;
|
|
||||||
dp->deviceChannelCount = cmApAggDeviceChannelCount;
|
|
||||||
dp->deviceSampleRate = cmApAggDeviceSampleRate;
|
|
||||||
dp->deviceFramesPerCycle = cmApAggDeviceFramesPerCycle;
|
|
||||||
dp->deviceSetup = cmApAggDeviceSetup;
|
|
||||||
dp->deviceStart = cmApAggDeviceStart;
|
|
||||||
dp->deviceStop = cmApAggDeviceStop;
|
|
||||||
dp->deviceIsStarted = cmApAggDeviceIsStarted;
|
|
||||||
|
|
||||||
dp = _ap->drvArray + 3;
|
|
||||||
|
|
||||||
dp->initialize = cmApNrtInitialize;
|
|
||||||
dp->finalize = cmApNrtFinalize;
|
|
||||||
dp->deviceCount = cmApNrtDeviceCount;
|
|
||||||
dp->deviceLabel = cmApNrtDeviceLabel;
|
|
||||||
dp->deviceChannelCount = cmApNrtDeviceChannelCount;
|
|
||||||
dp->deviceSampleRate = cmApNrtDeviceSampleRate;
|
|
||||||
dp->deviceFramesPerCycle = cmApNrtDeviceFramesPerCycle;
|
|
||||||
dp->deviceSetup = cmApNrtDeviceSetup;
|
|
||||||
dp->deviceStart = cmApNrtDeviceStart;
|
|
||||||
dp->deviceStop = cmApNrtDeviceStop;
|
|
||||||
dp->deviceIsStarted = cmApNrtDeviceIsStarted;
|
|
||||||
*/
|
|
||||||
|
|
||||||
_ap->devCnt = 0;
|
|
||||||
|
|
||||||
unsigned i;
|
|
||||||
for(i=0; i<_ap->drvCnt; ++i)
|
|
||||||
{
|
|
||||||
unsigned dn;
|
|
||||||
rc_t rc0;
|
|
||||||
|
|
||||||
_ap->drvArray[i].begDevIdx = kInvalidIdx;
|
|
||||||
_ap->drvArray[i].endDevIdx = kInvalidIdx;
|
|
||||||
|
|
||||||
if((rc0 = _ap->drvArray[i].initialize(_ap->devCnt)) != kOkRC )
|
|
||||||
{
|
|
||||||
rc = rc0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((dn = _ap->drvArray[i].deviceCount()) > 0)
|
|
||||||
{
|
|
||||||
_ap->drvArray[i].begDevIdx = _ap->devCnt;
|
|
||||||
_ap->drvArray[i].endDevIdx = _ap->devCnt + dn - 1;
|
|
||||||
_ap->devCnt += dn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( rc != kOkRC )
|
|
||||||
finalize();
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
cw::rc_t cw::audio::device::finalize()
|
|
||||||
{
|
|
||||||
rc_t rc=kOkRC;
|
|
||||||
rc_t rc0 = kOkRC;
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
if( _ap == NULL )
|
|
||||||
return kOkRC;
|
|
||||||
|
|
||||||
for(i=0; i<_ap->drvCnt; ++i)
|
|
||||||
{
|
|
||||||
if((rc0 = _ap->drvArray[i].finalize()) != kOkRC )
|
|
||||||
rc = rc0;
|
|
||||||
}
|
|
||||||
|
|
||||||
memRelease(_ap->drvArray);
|
|
||||||
memRelease(_ap);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsigned cw::audio::device::deviceCount()
|
|
||||||
{ return _ap->devCnt; }
|
|
||||||
|
|
||||||
const char* cw::audio::device::deviceLabel( unsigned devIdx )
|
|
||||||
{
|
|
||||||
cmApDriver_t* dp = NULL;
|
|
||||||
unsigned di = kInvalidIdx;
|
|
||||||
rc_t rc;
|
|
||||||
|
|
||||||
if( devIdx == kInvalidIdx )
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if((rc = _cmApIndexToDev(devIdx,&dp,&di)) != kOkRC )
|
|
||||||
return cwStringNullGuard(NULL);
|
|
||||||
|
|
||||||
return dp->deviceLabel(di);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned cw::audio::device::deviceLabelToIndex( const char* label )
|
|
||||||
{
|
|
||||||
unsigned n = deviceCount();
|
|
||||||
unsigned i;
|
|
||||||
for(i=0; i<n; ++i)
|
|
||||||
{
|
|
||||||
const char* s = deviceLabel(i);
|
|
||||||
if( s!=NULL && strcmp(s,label)==0)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return kInvalidIdx;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsigned cw::audio::device::deviceChannelCount( unsigned devIdx, bool inputFl )
|
|
||||||
{
|
|
||||||
cmApDriver_t* dp = NULL;
|
|
||||||
unsigned di = kInvalidIdx;
|
|
||||||
rc_t rc;
|
|
||||||
|
|
||||||
if( devIdx == kInvalidIdx )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if((rc = _cmApIndexToDev(devIdx,&dp,&di)) != kOkRC )
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
return dp->deviceChannelCount(di,inputFl);
|
|
||||||
}
|
|
||||||
|
|
||||||
double cw::audio::device::deviceSampleRate( unsigned devIdx )
|
|
||||||
{
|
|
||||||
cmApDriver_t* dp = NULL;
|
|
||||||
unsigned di = kInvalidIdx;
|
|
||||||
rc_t rc;
|
|
||||||
|
|
||||||
if((rc = _cmApIndexToDev(devIdx,&dp,&di)) != kOkRC )
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
return dp->deviceSampleRate(di);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned cw::audio::device::deviceFramesPerCycle( unsigned devIdx, bool inputFl )
|
|
||||||
{
|
|
||||||
cmApDriver_t* dp = NULL;
|
|
||||||
unsigned di = kInvalidIdx;
|
|
||||||
rc_t rc;
|
|
||||||
|
|
||||||
if( devIdx == kInvalidIdx )
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if((rc = _cmApIndexToDev(devIdx,&dp,&di)) != kOkRC )
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
return dp->deviceFramesPerCycle(di,inputFl);
|
|
||||||
}
|
|
||||||
|
|
||||||
cw::rc_t cw::audio::device::deviceSetup(
|
|
||||||
unsigned devIdx,
|
|
||||||
double srate,
|
|
||||||
unsigned framesPerCycle,
|
|
||||||
cbFunc_t cbFunc,
|
|
||||||
void* cbArg )
|
|
||||||
{
|
|
||||||
cmApDriver_t* dp;
|
|
||||||
unsigned di;
|
|
||||||
rc_t rc;
|
|
||||||
|
|
||||||
if( devIdx == kInvalidIdx )
|
|
||||||
return kOkRC;
|
|
||||||
|
|
||||||
if((rc = _cmApIndexToDev(devIdx,&dp,&di)) != kOkRC )
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
return dp->deviceSetup(di,srate,framesPerCycle,cbFunc,cbArg);
|
|
||||||
}
|
|
||||||
|
|
||||||
cw::rc_t cw::audio::device::deviceStart( unsigned devIdx )
|
|
||||||
{
|
|
||||||
cmApDriver_t* dp;
|
|
||||||
unsigned di;
|
|
||||||
rc_t rc;
|
|
||||||
|
|
||||||
if( devIdx == kInvalidIdx )
|
|
||||||
return kOkRC;
|
|
||||||
|
|
||||||
if((rc = _cmApIndexToDev(devIdx,&dp,&di)) != kOkRC )
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
return dp->deviceStart(di);
|
|
||||||
}
|
|
||||||
|
|
||||||
cw::rc_t cw::audio::device::deviceStop( unsigned devIdx )
|
|
||||||
{
|
|
||||||
cmApDriver_t* dp;
|
|
||||||
unsigned di;
|
|
||||||
rc_t rc;
|
|
||||||
|
|
||||||
if( devIdx == kInvalidIdx )
|
|
||||||
return kOkRC;
|
|
||||||
|
|
||||||
if((rc = _cmApIndexToDev(devIdx,&dp,&di)) != kOkRC )
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
return dp->deviceStop(di);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cw::audio::device::deviceIsStarted( unsigned devIdx )
|
|
||||||
{
|
|
||||||
cmApDriver_t* dp;
|
|
||||||
unsigned di;
|
|
||||||
rc_t rc;
|
|
||||||
|
|
||||||
if( devIdx == kInvalidIdx )
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if((rc = _cmApIndexToDev(devIdx,&dp,&di)) != kOkRC )
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
return dp->deviceIsStarted(di);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cw::audio::device::report()
|
|
||||||
{
|
|
||||||
unsigned i,j,k;
|
|
||||||
for(j=0,k=0; j<_ap->drvCnt; ++j)
|
|
||||||
{
|
|
||||||
cmApDriver_t* drvPtr = _ap->drvArray + j;
|
|
||||||
unsigned n = drvPtr->deviceCount();
|
|
||||||
|
|
||||||
for(i=0; i<n; ++i,++k)
|
|
||||||
{
|
|
||||||
cwLogInfo( "%i %f in:%i (%i) out:%i (%i) %s",
|
|
||||||
k, drvPtr->deviceSampleRate(i),
|
|
||||||
drvPtr->deviceChannelCount(i,true), drvPtr->deviceFramesPerCycle(i,true),
|
|
||||||
drvPtr->deviceChannelCount(i,false), drvPtr->deviceFramesPerCycle(i,false),
|
|
||||||
drvPtr->deviceLabel(i));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//cmApAlsaDeviceReport(rpt);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace cw
|
namespace cw
|
||||||
{
|
{
|
||||||
@ -380,7 +17,7 @@ namespace cw
|
|||||||
{
|
{
|
||||||
/// [cmAudioPortExample]
|
/// [cmAudioPortExample]
|
||||||
|
|
||||||
// See cmApPortTest() below for the main point of entry.
|
// See test() below for the main point of entry.
|
||||||
|
|
||||||
// Data structure used to hold the parameters for cpApPortTest()
|
// Data structure used to hold the parameters for cpApPortTest()
|
||||||
// and the user defined data record passed to the host from the
|
// and the user defined data record passed to the host from the
|
||||||
@ -640,8 +277,10 @@ namespace cw
|
|||||||
cwLogInfo(msg);
|
cwLogInfo(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a command line option.
|
// Get a command line option. Note that if 'boolFl' is set to 'true' then the function simply
|
||||||
int _cmApGetOpt( int argc, const char* argv[], const char* label, int defaultVal, bool boolFl )
|
// returns '1'. This is used to handle arguments whose presense indicates a positive boolean
|
||||||
|
// flag. For example -h (help) indicates that the usage data should be printed - it needs no other argument.
|
||||||
|
int _cmApGetOpt( int argc, const char* argv[], const char* label, int defaultVal, bool boolFl=false )
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(; i<argc; ++i)
|
for(; i<argc; ++i)
|
||||||
@ -664,6 +303,12 @@ namespace cw
|
|||||||
|
|
||||||
void _cmApPortCb2( audioPacket_t* inPktArray, unsigned inPktCnt, audioPacket_t* outPktArray, unsigned outPktCnt )
|
void _cmApPortCb2( audioPacket_t* inPktArray, unsigned inPktCnt, audioPacket_t* outPktArray, unsigned outPktCnt )
|
||||||
{
|
{
|
||||||
|
for(unsigned i=0; i<inPktCnt; ++i)
|
||||||
|
static_cast<cmApPortTestRecd*>(inPktArray[i].cbArg)->cbCnt++;
|
||||||
|
|
||||||
|
for(unsigned i=0; i<outPktCnt; ++i)
|
||||||
|
static_cast<cmApPortTestRecd*>(outPktArray[i].cbArg)->cbCnt++;
|
||||||
|
|
||||||
buf::inputToOutput( _cmGlobalInDevIdx, _cmGlobalOutDevIdx );
|
buf::inputToOutput( _cmGlobalInDevIdx, _cmGlobalOutDevIdx );
|
||||||
|
|
||||||
buf::update( inPktArray, inPktCnt, outPktArray, outPktCnt );
|
buf::update( inPktArray, inPktCnt, outPktArray, outPktCnt );
|
||||||
@ -673,23 +318,26 @@ namespace cw
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Audio Port testing function
|
// Audio Port testing function
|
||||||
cw::rc_t cw::audio::device::test( bool runFl, int argc, const char** argv )
|
cw::rc_t cw::audio::device::test( int argc, const char** argv )
|
||||||
{
|
{
|
||||||
cmApPortTestRecd r;
|
cmApPortTestRecd r;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
int result = 0;
|
rc_t rc;
|
||||||
textBuf::handle_t tbH = textBuf::create();
|
driver_t* drv = nullptr;
|
||||||
|
handle_t h;
|
||||||
|
alsa::handle_t alsaH;
|
||||||
|
bool runFl = true;
|
||||||
|
|
||||||
if( _cmApGetOpt(argc,argv,"-h",0,true) )
|
if( _cmApGetOpt(argc,argv,"-h",0,true) )
|
||||||
_cmApPrintUsage();
|
_cmApPrintUsage();
|
||||||
|
|
||||||
|
|
||||||
runFl = _cmApGetOpt(argc,argv,"-p",!runFl,true)?false:true;
|
runFl = _cmApGetOpt(argc,argv,"-p",0,true)?false:true;
|
||||||
r.srate = _cmApGetOpt(argc,argv,"-r",44100,false);
|
r.srate = _cmApGetOpt(argc,argv,"-r",44100);
|
||||||
r.chIdx = _cmApGetOpt(argc,argv,"-a",0,false);
|
r.chIdx = _cmApGetOpt(argc,argv,"-a",0);
|
||||||
r.chCnt = _cmApGetOpt(argc,argv,"-c",2,false);
|
r.chCnt = _cmApGetOpt(argc,argv,"-c",2);
|
||||||
r.bufCnt = _cmApGetOpt(argc,argv,"-b",3,false);
|
r.bufCnt = _cmApGetOpt(argc,argv,"-b",3);
|
||||||
r.framesPerCycle = _cmApGetOpt(argc,argv,"-f",512,false);
|
r.framesPerCycle = _cmApGetOpt(argc,argv,"-f",512);
|
||||||
r.bufFrmCnt = (r.bufCnt*r.framesPerCycle);
|
r.bufFrmCnt = (r.bufCnt*r.framesPerCycle);
|
||||||
r.bufSmpCnt = (r.chCnt * r.bufFrmCnt);
|
r.bufSmpCnt = (r.chCnt * r.bufFrmCnt);
|
||||||
r.logCnt = 100;
|
r.logCnt = 100;
|
||||||
@ -699,8 +347,8 @@ cw::rc_t cw::audio::device::test( bool runFl, int argc, const char** argv )
|
|||||||
char log[r.logCnt];
|
char log[r.logCnt];
|
||||||
unsigned ilog[r.logCnt];
|
unsigned ilog[r.logCnt];
|
||||||
|
|
||||||
r.inDevIdx = _cmGlobalInDevIdx = _cmApGetOpt(argc,argv,"-i",0,false);
|
r.inDevIdx = _cmGlobalInDevIdx = _cmApGetOpt(argc,argv,"-i",0);
|
||||||
r.outDevIdx = _cmGlobalOutDevIdx = _cmApGetOpt(argc,argv,"-o",2,false);
|
r.outDevIdx = _cmGlobalOutDevIdx = _cmApGetOpt(argc,argv,"-o",2);
|
||||||
r.phase = 0;
|
r.phase = 0;
|
||||||
r.frqHz = 2000;
|
r.frqHz = 2000;
|
||||||
r.bufInIdx = 0;
|
r.bufInIdx = 0;
|
||||||
@ -713,75 +361,75 @@ cw::rc_t cw::audio::device::test( bool runFl, int argc, const char** argv )
|
|||||||
r.ilog = ilog;
|
r.ilog = ilog;
|
||||||
r.cbCnt = 0;
|
r.cbCnt = 0;
|
||||||
|
|
||||||
cwLogInfo("%s in:%i out:%i chidx:%i chs:%i bufs=%i frm=%i rate=%f",runFl?"exec":"rpt",r.inDevIdx,r.outDevIdx,r.chIdx,r.chCnt,r.bufCnt,r.framesPerCycle,r.srate);
|
cwLogInfo("Program cfg: %s in:%i out:%i chidx:%i chs:%i bufs=%i frm=%i rate=%f",runFl?"exec":"rpt",r.inDevIdx,r.outDevIdx,r.chIdx,r.chCnt,r.bufCnt,r.framesPerCycle,r.srate);
|
||||||
|
|
||||||
/*
|
|
||||||
if( cmApFileAllocate(rpt) != kOkRC )
|
|
||||||
{
|
|
||||||
cwLogInfo("Audio port file allocation failed.");
|
|
||||||
result = -1;
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate the non-real-time port
|
|
||||||
if( cmApNrtAllocate(rpt) != kOkRC )
|
|
||||||
{
|
|
||||||
cwLogInfo("Non-real-time system allocation failed.");
|
|
||||||
result = 1;
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// initialize the audio device interface
|
// initialize the audio device interface
|
||||||
if( initialize() != kOkRC )
|
if((rc = create(h)) != kOkRC )
|
||||||
{
|
{
|
||||||
cwLogInfo("Initialize failed.");
|
cwLogInfo("Initialize failed.");
|
||||||
result = 1;
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize the ALSA device driver interface
|
||||||
|
if((rc = alsa::create(alsaH, drv )) != kOkRC )
|
||||||
|
{
|
||||||
|
cwLogInfo("ALSA initialize failed.");
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// register the ALSA device driver with the audio interface
|
||||||
|
if((rc = registerDriver( h, drv )) != kOkRC )
|
||||||
|
{
|
||||||
|
cwLogInfo("ALSA driver registration failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// report the current audio device configuration
|
// report the current audio device configuration
|
||||||
for(i=0; i<deviceCount(); ++i)
|
for(i=0; i<deviceCount(h); ++i)
|
||||||
{
|
{
|
||||||
cwLogInfo("%i [in: chs=%i frames=%i] [out: chs=%i frames=%i] srate:%f %s",i,deviceChannelCount(i,true),deviceFramesPerCycle(i,true),deviceChannelCount(i,false),deviceFramesPerCycle(i,false),deviceSampleRate(i),deviceLabel(i));
|
cwLogInfo("%i [in: chs=%i frames=%i] [out: chs=%i frames=%i] srate:%f %s",i,deviceChannelCount(h,i,true),deviceFramesPerCycle(h,i,true),deviceChannelCount(h,i,false),deviceFramesPerCycle(h,i,false),deviceSampleRate(h,i),deviceLabel(h,i));
|
||||||
}
|
}
|
||||||
|
|
||||||
// report the current audio devices using the audio port interface function
|
// report the current audio devices using the audio port interface function
|
||||||
report();
|
report(h);
|
||||||
|
|
||||||
if( runFl )
|
if( runFl )
|
||||||
{
|
{
|
||||||
// initialize the audio bufer
|
// initialize the audio bufer
|
||||||
buf::initialize( deviceCount(), r.meterMs );
|
buf::initialize( deviceCount(h), r.meterMs );
|
||||||
|
|
||||||
// setup the buffer for the output device
|
// setup the buffer for the output device
|
||||||
buf::setup( r.outDevIdx, r.srate, r.framesPerCycle, r.bufCnt, deviceChannelCount(r.outDevIdx,true), r.framesPerCycle, deviceChannelCount(r.outDevIdx,false), r.framesPerCycle );
|
buf::setup( r.outDevIdx, r.srate, r.framesPerCycle, r.bufCnt, deviceChannelCount(h,r.outDevIdx,true), r.framesPerCycle, deviceChannelCount(h,r.outDevIdx,false), r.framesPerCycle );
|
||||||
|
|
||||||
// setup the buffer for the input device
|
// setup the buffer for the input device
|
||||||
if( r.inDevIdx != r.outDevIdx )
|
if( r.inDevIdx != r.outDevIdx )
|
||||||
buf::setup( r.inDevIdx, r.srate, r.framesPerCycle, r.bufCnt, deviceChannelCount(r.inDevIdx,true), r.framesPerCycle, deviceChannelCount(r.inDevIdx,false), r.framesPerCycle );
|
buf::setup( r.inDevIdx, r.srate, r.framesPerCycle, r.bufCnt, deviceChannelCount(h,r.inDevIdx,true), r.framesPerCycle, deviceChannelCount(h,r.inDevIdx,false), r.framesPerCycle );
|
||||||
|
|
||||||
// setup an output device
|
// setup an output device
|
||||||
if(deviceSetup(r.outDevIdx,r.srate,r.framesPerCycle,_cmApPortCb2,&r) != kOkRC )
|
if(deviceSetup(h, r.outDevIdx,r.srate,r.framesPerCycle,_cmApPortCb2,&r) != kOkRC )
|
||||||
cwLogInfo("Out device setup failed.");
|
cwLogInfo("Out device setup failed.");
|
||||||
else
|
else
|
||||||
// setup an input device
|
// setup an input device
|
||||||
if( deviceSetup(r.inDevIdx,r.srate,r.framesPerCycle,_cmApPortCb2,&r) != kOkRC )
|
if( deviceSetup(h, r.inDevIdx,r.srate,r.framesPerCycle,_cmApPortCb2,&r) != kOkRC )
|
||||||
cwLogInfo("In device setup failed.");
|
cwLogInfo("In device setup failed.");
|
||||||
else
|
else
|
||||||
// start the input device
|
// start the input device
|
||||||
if( deviceStart(r.inDevIdx) != kOkRC )
|
if( deviceStart(h, r.inDevIdx) != kOkRC )
|
||||||
cwLogInfo("In device start failed.");
|
cwLogInfo("In device start failed.");
|
||||||
else
|
else
|
||||||
// start the output device
|
// start the output device
|
||||||
if( deviceStart(r.outDevIdx) != kOkRC )
|
if( deviceStart(h, r.outDevIdx) != kOkRC )
|
||||||
cwLogInfo("Out Device start failed.");
|
cwLogInfo("Out Device start failed.");
|
||||||
|
else
|
||||||
|
cwLogInfo("Setup complete!");
|
||||||
|
|
||||||
cwLogInfo("q=quit O/o output tone, I/i input tone P/p pass");
|
|
||||||
|
cwLogInfo("q=quit O/o output tone, I/i input tone P/p pass s=buf report");
|
||||||
char c;
|
char c;
|
||||||
while((c=getchar()) != 'q')
|
while((c=getchar()) != 'q')
|
||||||
{
|
{
|
||||||
//cmApAlsaDeviceRtReport(rpt,r.outDevIdx);
|
deviceRealTimeReport(h, r.outDevIdx );
|
||||||
|
|
||||||
switch(c)
|
switch(c)
|
||||||
{
|
{
|
||||||
@ -801,48 +449,42 @@ cw::rc_t cw::audio::device::test( bool runFl, int argc, const char** argv )
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
buf::report(tbH);
|
buf::report();
|
||||||
cwLogInfo("%s",textBuf::text(tbH));
|
|
||||||
textBuf::clear(tbH);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// stop the input device
|
// stop the input device
|
||||||
if( deviceIsStarted(r.inDevIdx) )
|
if( deviceIsStarted(h,r.inDevIdx) )
|
||||||
if( deviceStop(r.inDevIdx) != kOkRC )
|
if( deviceStop(h,r.inDevIdx) != kOkRC )
|
||||||
cwLogInfo("In device stop failed.");
|
cwLogInfo("In device stop failed.");
|
||||||
|
|
||||||
// stop the output device
|
// stop the output device
|
||||||
if( deviceIsStarted(r.outDevIdx) )
|
if( deviceIsStarted(h,r.outDevIdx) )
|
||||||
if( deviceStop(r.outDevIdx) != kOkRC )
|
if( deviceStop(h,r.outDevIdx) != kOkRC )
|
||||||
cwLogInfo("Out device stop failed.");
|
cwLogInfo("Out device stop failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
|
|
||||||
|
// release the ALSA driver
|
||||||
|
rc_t rc0 = alsa::destroy(alsaH);
|
||||||
|
|
||||||
// release any resources held by the audio port interface
|
// release any resources held by the audio port interface
|
||||||
if( finalize() != kOkRC )
|
rc_t rc1 = destroy(h);
|
||||||
cwLogInfo("Finalize failed.");
|
|
||||||
|
rc_t rc2 = buf::finalize();
|
||||||
buf::finalize();
|
|
||||||
|
|
||||||
//cmApNrtFree();
|
//cmApNrtFree();
|
||||||
//cmApFileFree();
|
//cmApFileFree();
|
||||||
|
|
||||||
// report the count of audio buffer callbacks
|
// report the count of audio buffer callbacks
|
||||||
cwLogInfo("cb count:%i", r.cbCnt );
|
cwLogInfo("cb count:%i", r.cbCnt );
|
||||||
//for(i=0; i<_logCnt; ++i)
|
|
||||||
// cwLogInfo("%c(%i)",_log[i],_ilog[i]);
|
|
||||||
//cwLogInfo("\n");
|
|
||||||
|
|
||||||
textBuf::destroy(tbH);
|
return rcSelect(rc,rc0,rc1,rc2);
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [cmAudioPortExample]
|
/// [cmAudioPortExample]
|
||||||
|
|
||||||
|
|
||||||
|
|
15
cwAudioDeviceTest.h
Normal file
15
cwAudioDeviceTest.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef cwAudioDeviceTest_H
|
||||||
|
#define cwAudioDeviceTest_H
|
||||||
|
|
||||||
|
namespace cw
|
||||||
|
{
|
||||||
|
namespace audio
|
||||||
|
{
|
||||||
|
namespace device
|
||||||
|
{
|
||||||
|
rc_t test( int argc, const char** argv );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
119
cwAudioPort.h
119
cwAudioPort.h
@ -1,119 +0,0 @@
|
|||||||
//( { file_desc: "Cross platform audio device interface." kw:[audio rt] }
|
|
||||||
//
|
|
||||||
// This interface provides data declarations for platform dependent
|
|
||||||
// audio I/O functions. The implementation for the functions are
|
|
||||||
// in platform specific modules. See cmAudioPortOsx.c and cmAudioPortAlsa.c.
|
|
||||||
//
|
|
||||||
// ALSA Notes:
|
|
||||||
// Assign capture device to line or mic input:
|
|
||||||
// amixer -c 0 cset iface=MIXER,name='Input Source',index=0 Mic
|
|
||||||
// amixer -c 0 cset iface=MIXER,name='Input Source',index=0 Line
|
|
||||||
//
|
|
||||||
// -c 0 select the first card
|
|
||||||
// -iface=MIXER the cset is targetting the MIXER component
|
|
||||||
// -name='Input Source',index=0 the control to set is the first 'Input Source'
|
|
||||||
// Note that the 'Capture' control sets the input gain.
|
|
||||||
//
|
|
||||||
// See alsamixer for a GUI to accomplish the same thing.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//)
|
|
||||||
|
|
||||||
#ifndef cwAudioPort_H
|
|
||||||
#define cwAudioPort_H
|
|
||||||
|
|
||||||
namespace cw
|
|
||||||
{
|
|
||||||
namespace audio
|
|
||||||
{
|
|
||||||
namespace device
|
|
||||||
{
|
|
||||||
typedef float sample_t;
|
|
||||||
|
|
||||||
// audioPacket_t flags
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
kInterleavedApFl = 0x01, // The audio samples are interleaved.
|
|
||||||
kFloatApFl = 0x02 // The audio samples are single precision floating point values.
|
|
||||||
};
|
|
||||||
|
|
||||||
// Audio packet record used by the audioPacket_t callback.
|
|
||||||
// Audio ports send and receive audio using this data structure.
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned devIdx; // device associated with packet
|
|
||||||
unsigned begChIdx; // first device channel
|
|
||||||
unsigned chCnt; // count of channels
|
|
||||||
unsigned audioFramesCnt; // samples per channel (see note below)
|
|
||||||
unsigned bitsPerSample; // bits per sample word
|
|
||||||
unsigned flags; // kInterleavedApFl | kFloatApFl
|
|
||||||
void* audioBytesPtr; // pointer to sample data
|
|
||||||
void* userCbPtr; // user defined argument passed in via deviceSetup()
|
|
||||||
time::spec_t timeStamp; // Packet time stamp.
|
|
||||||
} audioPacket_t;
|
|
||||||
|
|
||||||
|
|
||||||
// Audio port callback signature.
|
|
||||||
// inPktArray[inPktCnt] are full packets of audio coming from the ADC to the application.
|
|
||||||
// outPktArray[outPktCnt] are empty packets of audio which will be filled by the application
|
|
||||||
// and then sent to the DAC.
|
|
||||||
//
|
|
||||||
// The value of audioFrameCnt gives the number of samples per channel which are available
|
|
||||||
// in the packet data buffer 'audioBytesPtr'. The callback function may decrease this number in
|
|
||||||
// output packets if the number of samples available is less than the size of the buffer.
|
|
||||||
// It is the responsibility of the calling audio port to notice this change and pass the new,
|
|
||||||
// decreased number of samples to the hardware.
|
|
||||||
//
|
|
||||||
// In general it should be assmed that this call is made from a system thread which is not
|
|
||||||
// the same as the application thread.
|
|
||||||
// The usual thread safety precautions should therefore be taken if this function implementation
|
|
||||||
// interacts with data structures also handled by the application. The audio buffer class (\see cmApBuf.h)
|
|
||||||
// is designed to provide a safe and efficient way to communicate between
|
|
||||||
// the audio thread and the application.
|
|
||||||
typedef void (*cbFunc_t)( audioPacket_t* inPktArray, unsigned inPktCnt, audioPacket_t* outPktArray, unsigned outPktCnt );
|
|
||||||
|
|
||||||
rc_t initialize();
|
|
||||||
rc_t finalize();
|
|
||||||
unsigned deviceCount();
|
|
||||||
const char* deviceLabel( unsigned devIdx );
|
|
||||||
unsigned deviceLabelToIndex( const char* label );
|
|
||||||
unsigned deviceChannelCount( unsigned devIdx, bool inputFl );
|
|
||||||
|
|
||||||
// Get the current sample rate of a device. Note that if the device has both
|
|
||||||
// input and output capability then the sample rate is the same for both.
|
|
||||||
double deviceSampleRate( unsigned devIdx );
|
|
||||||
unsigned deviceFramesPerCycle( unsigned devIdx, bool inputFl );
|
|
||||||
|
|
||||||
// Configure a device.
|
|
||||||
// All devices must be setup before they are started.
|
|
||||||
// framesPerCycle is the requested number of samples per audio callback. The
|
|
||||||
// actual number of samples made from a callback may be smaller. See the note
|
|
||||||
// regarding this in audioPacket_t.
|
|
||||||
// If the device cannot support the requested configuration then the function
|
|
||||||
// will return an error code.
|
|
||||||
// If the device is started when this function is called then it will be
|
|
||||||
// automatically stopped and then restarted following the reconfiguration.
|
|
||||||
// If the reconfiguration fails then the device may not be restared.
|
|
||||||
rc_t deviceSetup( unsigned devIdx, double srate, unsigned framesPerCallback, cbFunc_t cbFunc, void* cbArg );
|
|
||||||
|
|
||||||
// Start a device. Note that the callback may be made prior to this function returning.
|
|
||||||
rc_t deviceStart( unsigned devIdx );
|
|
||||||
rc_t deviceStop( unsigned devIdx );
|
|
||||||
bool deviceIsStarted( unsigned devIdx );
|
|
||||||
|
|
||||||
// Print a report of all the current audio device configurations.
|
|
||||||
void report();
|
|
||||||
|
|
||||||
// Test the audio port by synthesizing a sine signal or passing audio through
|
|
||||||
// from the input to the output. This is also a good example of how to
|
|
||||||
// use all of the functions in the interface.
|
|
||||||
// Set runFl to false to print a report without starting any audio devices.
|
|
||||||
// See cmAudiotPortTest.c for usage example for this function.
|
|
||||||
rc_t test( bool runFl, int argc, const char** argv );
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,53 +0,0 @@
|
|||||||
#ifndef cwAudioPortAlsa_H
|
|
||||||
#define cwAudioPortAlsa_H
|
|
||||||
|
|
||||||
namespace cw
|
|
||||||
{
|
|
||||||
namespace audio
|
|
||||||
{
|
|
||||||
namespace device
|
|
||||||
{
|
|
||||||
namespace alsa
|
|
||||||
{
|
|
||||||
//{ { label: cmApAlsa kw:[ audio, device, rt ] }
|
|
||||||
//
|
|
||||||
//(
|
|
||||||
// ALSA audio device API
|
|
||||||
//
|
|
||||||
// This API is used by the cmAudioPort interface when
|
|
||||||
// the library is compiled for a Linux platform.
|
|
||||||
//
|
|
||||||
//)
|
|
||||||
|
|
||||||
//[
|
|
||||||
|
|
||||||
rc_t initialize( unsigned baseApDevIdx );
|
|
||||||
rc_t finalize();
|
|
||||||
|
|
||||||
rc_t deviceCount();
|
|
||||||
const char* deviceLabel( unsigned devIdx );
|
|
||||||
unsigned deviceChannelCount( unsigned devIdx, bool inputFl );
|
|
||||||
double deviceSampleRate( unsigned devIdx );
|
|
||||||
unsigned deviceFramesPerCycle( unsigned devIdx, bool inputFl );
|
|
||||||
|
|
||||||
rc_t deviceSetup(
|
|
||||||
unsigned devIdx,
|
|
||||||
double srate,
|
|
||||||
unsigned framesPerCycle,
|
|
||||||
device::cbFunc_t callbackPtr,
|
|
||||||
void* userCbPtr );
|
|
||||||
|
|
||||||
rc_t deviceStart( unsigned devIdx );
|
|
||||||
rc_t deviceStop( unsigned devIdx );
|
|
||||||
bool deviceIsStarted( unsigned devIdx );
|
|
||||||
|
|
||||||
void deviceReport( );
|
|
||||||
|
|
||||||
//]
|
|
||||||
//}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -64,6 +64,19 @@ namespace cw
|
|||||||
const char* idToLabel( const idLabelPair_t* array, unsigned id, unsigned eolId );
|
const char* idToLabel( const idLabelPair_t* array, unsigned id, unsigned eolId );
|
||||||
unsigned labelToId( const idLabelPair_t* array, const char* label, unsigned eolId );
|
unsigned labelToId( const idLabelPair_t* array, const char* label, unsigned eolId );
|
||||||
|
|
||||||
|
|
||||||
|
inline rc_t rcSelect() { return kOkRC; }
|
||||||
|
|
||||||
|
template<typename T, typename... ARGS>
|
||||||
|
rc_t rcSelect(T rc, ARGS... args)
|
||||||
|
{
|
||||||
|
if( rc != kOkRC )
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
return rcSelect(args...);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void sleepSec( unsigned secs ); // sleep seconds
|
void sleepSec( unsigned secs ); // sleep seconds
|
||||||
void sleepMs( unsigned ms ); // sleep milliseconds
|
void sleepMs( unsigned ms ); // sleep milliseconds
|
||||||
void sleepUs( unsigned us ); // sleep seconds
|
void sleepUs( unsigned us ); // sleep seconds
|
||||||
|
396
cwFile.cpp
396
cwFile.cpp
@ -14,132 +14,138 @@
|
|||||||
namespace cw
|
namespace cw
|
||||||
{
|
{
|
||||||
|
|
||||||
typedef struct file_str
|
namespace file
|
||||||
{
|
{
|
||||||
FILE* fp;
|
typedef struct file_str
|
||||||
char* fnStr;
|
{
|
||||||
} file_t;
|
FILE* fp;
|
||||||
|
char* fnStr;
|
||||||
|
} this_t;
|
||||||
|
|
||||||
|
|
||||||
#define _fileHandleToPtr(h) handleToPtr<fileH_t,file_t>(h)
|
this_t* _handleToPtr(handle_t h)
|
||||||
|
{
|
||||||
|
return handleToPtr<handle_t,this_t>(h);
|
||||||
|
}
|
||||||
|
|
||||||
char* _fileToBuf( fileH_t h, unsigned nn, unsigned* bufByteCntPtr )
|
char* _fileToBuf( handle_t h, unsigned nn, unsigned* bufByteCntPtr )
|
||||||
{
|
{
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
unsigned n = fileByteCount(h);
|
unsigned n = byteCount(h);
|
||||||
char* buf = nullptr;
|
char* buf = nullptr;
|
||||||
|
|
||||||
// if the file size calculation is ok
|
// if the file size calculation is ok
|
||||||
if( errno != 0 )
|
if( errno != 0 )
|
||||||
{
|
{
|
||||||
cwLogSysError(kOpFailRC,errno,"Invalid file buffer length on '%s'.", cwStringNullGuard(fileName(h)));
|
cwLogSysError(kOpFailRC,errno,"Invalid file buffer length on '%s'.", cwStringNullGuard(name(h)));
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate the read target buffer
|
// allocate the read target buffer
|
||||||
if((buf = memAlloc<char>(n+nn)) == nullptr)
|
if((buf = memAlloc<char>(n+nn)) == nullptr)
|
||||||
{
|
{
|
||||||
cwLogError(kMemAllocFailRC,"Read buffer allocation failed.");
|
cwLogError(kMemAllocFailRC,"Read buffer allocation failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// read the file
|
// read the file
|
||||||
if( fileRead(h,buf,n) != kOkRC )
|
if( read(h,buf,n) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
// zero memory after the file data
|
// zero memory after the file data
|
||||||
memset(buf+n,0,nn);
|
memset(buf+n,0,nn);
|
||||||
|
|
||||||
if( bufByteCntPtr != nullptr )
|
if( bufByteCntPtr != nullptr )
|
||||||
*bufByteCntPtr = n;
|
*bufByteCntPtr = n;
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
if( bufByteCntPtr != nullptr )
|
if( bufByteCntPtr != nullptr )
|
||||||
*bufByteCntPtr = 0;
|
*bufByteCntPtr = 0;
|
||||||
|
|
||||||
memRelease(buf);
|
memRelease(buf);
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char* _fileFnToBuf( const char* fn, unsigned nn, unsigned* bufByteCntPtr )
|
char* _fileFnToBuf( const char* fn, unsigned nn, unsigned* bufByteCntPtr )
|
||||||
{
|
{
|
||||||
fileH_t h;
|
handle_t h;
|
||||||
char* buf = nullptr;
|
char* buf = nullptr;
|
||||||
|
|
||||||
if( fileOpen(h,fn,kReadFileFl | kBinaryFileFl) != kOkRC )
|
if( open(h,fn,kReadFl | kBinaryFl) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
buf = _fileToBuf(h,nn,bufByteCntPtr);
|
buf = _fileToBuf(h,nn,bufByteCntPtr);
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
fileClose(h);
|
close(h);
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_t _fileGetLine( file_t* p, char* buf, unsigned* bufByteCntPtr )
|
rc_t _fileGetLine( this_t* p, char* buf, unsigned* bufByteCntPtr )
|
||||||
{
|
{
|
||||||
// fgets() reads up to n-1 bytes into buf[]
|
// fgets() reads up to n-1 bytes into buf[]
|
||||||
if( fgets(buf,*bufByteCntPtr,p->fp) == nullptr )
|
if( fgets(buf,*bufByteCntPtr,p->fp) == nullptr )
|
||||||
{
|
{
|
||||||
// an read error or EOF condition occurred
|
// an read error or EOF condition occurred
|
||||||
*bufByteCntPtr = 0;
|
*bufByteCntPtr = 0;
|
||||||
|
|
||||||
if( !feof(p->fp ) )
|
if( !feof(p->fp ) )
|
||||||
return cwLogSysError(kReadFailRC,errno,"File read line failed");
|
return cwLogSysError(kReadFailRC,errno,"File read line failed");
|
||||||
|
|
||||||
return kReadFailRC;
|
return kReadFailRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return kOkRC;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
cw::rc_t cw::file::open( handle_t& hRef, const char* fn, unsigned flags )
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::fileOpen( fileH_t& hRef, const char* fn, unsigned flags )
|
|
||||||
{
|
{
|
||||||
char mode[] = "/0/0/0";
|
char mode[] = "/0/0/0";
|
||||||
file_t* p = nullptr;
|
this_t* p = nullptr;
|
||||||
rc_t rc;
|
rc_t rc;
|
||||||
|
|
||||||
if((rc = fileClose(hRef)) != kOkRC )
|
if((rc = close(hRef)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if( cwIsFlag(flags,kReadFileFl) )
|
if( cwIsFlag(flags,kReadFl) )
|
||||||
mode[0] = 'r';
|
mode[0] = 'r';
|
||||||
else
|
else
|
||||||
if( cwIsFlag(flags,kWriteFileFl) )
|
if( cwIsFlag(flags,kWriteFl) )
|
||||||
mode[0] = 'w';
|
mode[0] = 'w';
|
||||||
else
|
else
|
||||||
if( cwIsFlag(flags,kAppendFileFl) )
|
if( cwIsFlag(flags,kAppendFl) )
|
||||||
mode[0] = 'a';
|
mode[0] = 'a';
|
||||||
else
|
else
|
||||||
cwLogError(kInvalidArgRC,"File open flags must contain 'kReadFileFl','kWriteFileFl', or 'kAppendFileFl'.");
|
cwLogError(kInvalidArgRC,"File open flags must contain 'kReadFl','kWriteFl', or 'kAppendFl'.");
|
||||||
|
|
||||||
if( cwIsFlag(flags,kUpdateFileFl) )
|
if( cwIsFlag(flags,kUpdateFl) )
|
||||||
mode[1] = '+';
|
mode[1] = '+';
|
||||||
|
|
||||||
// handle requests to use stdin,stdout,stderr
|
// handle requests to use stdin,stdout,stderr
|
||||||
FILE* sfp = nullptr;
|
FILE* sfp = nullptr;
|
||||||
if( cwIsFlag(flags,kStdoutFileFl) )
|
if( cwIsFlag(flags,kStdoutFl) )
|
||||||
{
|
{
|
||||||
sfp = stdout;
|
sfp = stdout;
|
||||||
fn = "stdout";
|
fn = "stdout";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if( cwIsFlag(flags,kStderrFileFl) )
|
if( cwIsFlag(flags,kStderrFl) )
|
||||||
{
|
{
|
||||||
sfp = stderr;
|
sfp = stderr;
|
||||||
fn = "stderr";
|
fn = "stderr";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if( cwIsFlag(flags,kStdinFileFl) )
|
if( cwIsFlag(flags,kStdinFl) )
|
||||||
{
|
{
|
||||||
sfp = stdin;
|
sfp = stdin;
|
||||||
fn = "stdin";
|
fn = "stdin";
|
||||||
@ -149,9 +155,9 @@ cw::rc_t cw::fileOpen( fileH_t& hRef, const char* fn, unsigned flags )
|
|||||||
if( fn == nullptr )
|
if( fn == nullptr )
|
||||||
return cwLogError(kInvalidArgRC,"File object allocation failed due to empty file name.");
|
return cwLogError(kInvalidArgRC,"File object allocation failed due to empty file name.");
|
||||||
|
|
||||||
unsigned byteCnt = sizeof(file_t) + strlen(fn) + 1;
|
unsigned byteCnt = sizeof(this_t) + strlen(fn) + 1;
|
||||||
|
|
||||||
if((p = memAllocZ<file_t>(byteCnt)) == nullptr )
|
if((p = memAllocZ<this_t>(byteCnt)) == nullptr )
|
||||||
return cwLogError(kOpFailRC,"File object allocation failed for file '%s'.",cwStringNullGuard(fn));
|
return cwLogError(kOpFailRC,"File object allocation failed for file '%s'.",cwStringNullGuard(fn));
|
||||||
|
|
||||||
p->fnStr = (char*)(p+1);
|
p->fnStr = (char*)(p+1);
|
||||||
@ -175,12 +181,12 @@ cw::rc_t cw::fileOpen( fileH_t& hRef, const char* fn, unsigned flags )
|
|||||||
return kOkRC;
|
return kOkRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::fileClose( fileH_t& hRef )
|
cw::rc_t cw::file::close( handle_t& hRef )
|
||||||
{
|
{
|
||||||
if( fileIsValid(hRef) == false )
|
if( isValid(hRef) == false )
|
||||||
return kOkRC;
|
return kOkRC;
|
||||||
|
|
||||||
file_t* p = _fileHandleToPtr(hRef);
|
this_t* p = _handleToPtr(hRef);
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if( p->fp != nullptr )
|
if( p->fp != nullptr )
|
||||||
@ -188,17 +194,17 @@ cw::rc_t cw::fileClose( fileH_t& hRef )
|
|||||||
return cwLogSysError(kCloseFailRC,errno,"File close failed on '%s'.", cwStringNullGuard(p->fnStr));
|
return cwLogSysError(kCloseFailRC,errno,"File close failed on '%s'.", cwStringNullGuard(p->fnStr));
|
||||||
|
|
||||||
memRelease(p);
|
memRelease(p);
|
||||||
hRef.set(nullptr);
|
hRef.clear();
|
||||||
|
|
||||||
return kOkRC;
|
return kOkRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cw::fileIsValid( fileH_t h )
|
bool cw::file::isValid( handle_t h )
|
||||||
{ return h.isValid(); }
|
{ return h.isValid(); }
|
||||||
|
|
||||||
cw::rc_t cw::fileRead( fileH_t h, void* buf, unsigned bufByteCnt )
|
cw::rc_t cw::file::read( handle_t h, void* buf, unsigned bufByteCnt )
|
||||||
{
|
{
|
||||||
file_t* p = _fileHandleToPtr(h);
|
this_t* p = _handleToPtr(h);
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if( fread(buf,bufByteCnt,1,p->fp) != 1 )
|
if( fread(buf,bufByteCnt,1,p->fp) != 1 )
|
||||||
@ -207,9 +213,9 @@ cw::rc_t cw::fileRead( fileH_t h, void* buf, unsigned bufByteCnt )
|
|||||||
return kOkRC;
|
return kOkRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::fileWrite( fileH_t h, const void* buf, unsigned bufByteCnt )
|
cw::rc_t cw::file::write( handle_t h, const void* buf, unsigned bufByteCnt )
|
||||||
{
|
{
|
||||||
file_t* p = _fileHandleToPtr(h);
|
this_t* p = _handleToPtr(h);
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if( fwrite(buf,bufByteCnt,1,p->fp) != 1 )
|
if( fwrite(buf,bufByteCnt,1,p->fp) != 1 )
|
||||||
@ -218,18 +224,18 @@ cw::rc_t cw::fileWrite( fileH_t h, const void* buf, unsigned bufByteCnt )
|
|||||||
return kOkRC;
|
return kOkRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::fileSeek( fileH_t h, enum fileSeekFlags_t flags, int offsByteCnt )
|
cw::rc_t cw::file::seek( handle_t h, enum seekFlags_t flags, int offsByteCnt )
|
||||||
{
|
{
|
||||||
file_t* p = _fileHandleToPtr(h);
|
this_t* p = _handleToPtr(h);
|
||||||
unsigned fileflags = 0;
|
unsigned fileflags = 0;
|
||||||
|
|
||||||
if( cwIsFlag(flags,kBeginFileFl) )
|
if( cwIsFlag(flags,kBeginFl) )
|
||||||
fileflags = SEEK_SET;
|
fileflags = SEEK_SET;
|
||||||
else
|
else
|
||||||
if( cwIsFlag(flags,kCurFileFl) )
|
if( cwIsFlag(flags,kCurFl) )
|
||||||
fileflags = SEEK_CUR;
|
fileflags = SEEK_CUR;
|
||||||
else
|
else
|
||||||
if( cwIsFlag(flags,kEndFileFl) )
|
if( cwIsFlag(flags,kEndFl) )
|
||||||
fileflags = SEEK_END;
|
fileflags = SEEK_END;
|
||||||
else
|
else
|
||||||
return cwLogError(kInvalidArgRC,"Invalid file seek flag on '%s'.",cwStringNullGuard(p->fnStr));
|
return cwLogError(kInvalidArgRC,"Invalid file seek flag on '%s'.",cwStringNullGuard(p->fnStr));
|
||||||
@ -241,11 +247,11 @@ cw::rc_t cw::fileSeek( fileH_t h, enum fileSeekFlags_t flags, int offsByteCnt
|
|||||||
return kOkRC;
|
return kOkRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::fileTell( fileH_t h, long* offsPtr )
|
cw::rc_t cw::file::tell( handle_t h, long* offsPtr )
|
||||||
{
|
{
|
||||||
cwAssert( offsPtr != nullptr );
|
cwAssert( offsPtr != nullptr );
|
||||||
*offsPtr = -1;
|
*offsPtr = -1;
|
||||||
file_t* p = _fileHandleToPtr(h);
|
this_t* p = _handleToPtr(h);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
if((*offsPtr = ftell(p->fp)) == -1)
|
if((*offsPtr = ftell(p->fp)) == -1)
|
||||||
@ -254,15 +260,15 @@ cw::rc_t cw::fileTell( fileH_t h, long* offsPtr )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool cw::fileEof( fileH_t h )
|
bool cw::file::eof( handle_t h )
|
||||||
{ return feof( _fileHandleToPtr(h)->fp ) != 0; }
|
{ return feof( _handleToPtr(h)->fp ) != 0; }
|
||||||
|
|
||||||
|
|
||||||
unsigned cw::fileByteCount( fileH_t h )
|
unsigned cw::file::byteCount( handle_t h )
|
||||||
{
|
{
|
||||||
struct stat sr;
|
struct stat sr;
|
||||||
int f;
|
int f;
|
||||||
file_t* p = _fileHandleToPtr(h);
|
this_t* p = _handleToPtr(h);
|
||||||
const char errMsg[] = "File byte count request failed.";
|
const char errMsg[] = "File byte count request failed.";
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
@ -282,44 +288,44 @@ unsigned cw::fileByteCount( fileH_t h )
|
|||||||
return sr.st_size;
|
return sr.st_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::fileByteCountFn( const char* fn, unsigned* fileByteCntPtr )
|
cw::rc_t cw::file::byteCountFn( const char* fn, unsigned* fileByteCntPtr )
|
||||||
{
|
{
|
||||||
cwAssert( fileByteCntPtr != nullptr );
|
cwAssert( fileByteCntPtr != nullptr );
|
||||||
rc_t rc;
|
rc_t rc;
|
||||||
fileH_t h;
|
handle_t h;
|
||||||
|
|
||||||
if((rc = fileOpen(h,fn,kReadFileFl)) != kOkRC )
|
if((rc = open(h,fn,kReadFl)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if( fileByteCntPtr != nullptr)
|
if( fileByteCntPtr != nullptr)
|
||||||
*fileByteCntPtr = fileByteCount(h);
|
*fileByteCntPtr = byteCount(h);
|
||||||
|
|
||||||
fileClose(h);
|
close(h);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::fileCompare( const char* fn0, const char* fn1, bool& isEqualRef )
|
cw::rc_t cw::file::compare( const char* fn0, const char* fn1, bool& isEqualRef )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
unsigned bufByteCnt = 2048;
|
unsigned bufByteCnt = 2048;
|
||||||
fileH_t h0;
|
handle_t h0;
|
||||||
fileH_t h1;
|
handle_t h1;
|
||||||
file_t* p0 = nullptr;
|
this_t* p0 = nullptr;
|
||||||
file_t* p1 = nullptr;
|
this_t* p1 = nullptr;
|
||||||
char b0[ bufByteCnt ];
|
char b0[ bufByteCnt ];
|
||||||
char b1[ bufByteCnt ];
|
char b1[ bufByteCnt ];
|
||||||
|
|
||||||
isEqualRef = true;
|
isEqualRef = true;
|
||||||
|
|
||||||
if((rc = fileOpen(h0,fn0,kReadFileFl)) != kOkRC )
|
if((rc = open(h0,fn0,kReadFl)) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
if((rc = fileOpen(h1,fn1,kReadFileFl)) != kOkRC )
|
if((rc = open(h1,fn1,kReadFl)) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
p0 = _fileHandleToPtr(h0);
|
p0 = _handleToPtr(h0);
|
||||||
p1 = _fileHandleToPtr(h1);
|
p1 = _handleToPtr(h1);
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
@ -336,36 +342,36 @@ cw::rc_t cw::fileCompare( const char* fn0, const char* fn1, bool& isEqualRef )
|
|||||||
}
|
}
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
fileClose(h0);
|
close(h0);
|
||||||
fileClose(h1);
|
close(h1);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* cw::fileName( fileH_t h )
|
const char* cw::file::name( handle_t h )
|
||||||
{
|
{
|
||||||
file_t* p = _fileHandleToPtr(h);
|
this_t* p = _handleToPtr(h);
|
||||||
return p->fnStr;
|
return p->fnStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::fileFnWrite( const char* fn, const void* buf, unsigned bufByteCnt )
|
cw::rc_t cw::file::fnWrite( const char* fn, const void* buf, unsigned bufByteCnt )
|
||||||
{
|
{
|
||||||
fileH_t h;
|
handle_t h;
|
||||||
rc_t rc;
|
rc_t rc;
|
||||||
|
|
||||||
if((rc = fileOpen(h,fn,kWriteFileFl)) != kOkRC )
|
if((rc = open(h,fn,kWriteFl)) != kOkRC )
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
|
|
||||||
rc = fileWrite(h,buf,bufByteCnt);
|
rc = write(h,buf,bufByteCnt);
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
fileClose(h);
|
close(h);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::fileCopy(
|
cw::rc_t cw::file::copy(
|
||||||
const char* srcDir,
|
const char* srcDir,
|
||||||
const char* srcFn,
|
const char* srcFn,
|
||||||
const char* srcExt,
|
const char* srcExt,
|
||||||
@ -401,12 +407,12 @@ cw::rc_t cw::fileCopy(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// read the source file into a buffer
|
// read the source file into a buffer
|
||||||
if((buf = fileFnToBuf(srcPathFn,&byteCnt)) == nullptr )
|
if((buf = fnToBuf(srcPathFn,&byteCnt)) == nullptr )
|
||||||
rc = cwLogError(kReadFailRC,"Attempt to fill a buffer from '%s' failed.",cwStringNullGuard(srcPathFn));
|
rc = cwLogError(kReadFailRC,"Attempt to fill a buffer from '%s' failed.",cwStringNullGuard(srcPathFn));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// write the file to the output file
|
// write the file to the output file
|
||||||
if( fileFnWrite(dstPathFn,buf,byteCnt) != kOkRC )
|
if( fnWrite(dstPathFn,buf,byteCnt) != kOkRC )
|
||||||
rc = cwLogError(kWriteFailRC,"An attempt to write a buffer to '%s' failed.",cwStringNullGuard(dstPathFn));
|
rc = cwLogError(kWriteFailRC,"An attempt to write a buffer to '%s' failed.",cwStringNullGuard(dstPathFn));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,7 +425,7 @@ cw::rc_t cw::fileCopy(
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::fileBackup( const char* dir, const char* name, const char* ext )
|
cw::rc_t cw::file::backup( const char* dir, const char* name, const char* ext )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
char* newName = nullptr;
|
char* newName = nullptr;
|
||||||
@ -465,7 +471,7 @@ cw::rc_t cw::fileBackup( const char* dir, const char* name, const char* ext )
|
|||||||
if( fileSysIsFile(newFn) == false )
|
if( fileSysIsFile(newFn) == false )
|
||||||
{
|
{
|
||||||
// .. then duplicate the file
|
// .. then duplicate the file
|
||||||
if((rc = fileCopy(srcFn,nullptr,nullptr,newFn,nullptr,nullptr)) != kOkRC )
|
if((rc = copy(srcFn,nullptr,nullptr,newFn,nullptr,nullptr)) != kOkRC )
|
||||||
rc = cwLogError(rc,"The file '%s' could not be duplicated as '%s'.",cwStringNullGuard(srcFn),cwStringNullGuard(newFn));
|
rc = cwLogError(rc,"The file '%s' could not be duplicated as '%s'.",cwStringNullGuard(srcFn),cwStringNullGuard(newFn));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -486,22 +492,22 @@ cw::rc_t cw::fileBackup( const char* dir, const char* name, const char* ext )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char* cw::fileToBuf( fileH_t h, unsigned* bufByteCntPtr )
|
char* cw::file::toBuf( handle_t h, unsigned* bufByteCntPtr )
|
||||||
{ return _fileToBuf(h,0,bufByteCntPtr); }
|
{ return _fileToBuf(h,0,bufByteCntPtr); }
|
||||||
|
|
||||||
char* cw::fileFnToBuf( const char* fn, unsigned* bufByteCntPtr )
|
char* cw::file::fnToBuf( const char* fn, unsigned* bufByteCntPtr )
|
||||||
{ return _fileFnToBuf(fn,0,bufByteCntPtr); }
|
{ return _fileFnToBuf(fn,0,bufByteCntPtr); }
|
||||||
|
|
||||||
char* cw::fileToStr( fileH_t h, unsigned* bufByteCntPtr )
|
char* cw::file::toStr( handle_t h, unsigned* bufByteCntPtr )
|
||||||
{ return _fileToBuf(h,1,bufByteCntPtr); }
|
{ return _fileToBuf(h,1,bufByteCntPtr); }
|
||||||
|
|
||||||
char* cw::fileFnToStr( const char* fn, unsigned* bufByteCntPtr )
|
char* cw::file::fnToStr( const char* fn, unsigned* bufByteCntPtr )
|
||||||
{ return _fileFnToBuf(fn,1,bufByteCntPtr); }
|
{ return _fileFnToBuf(fn,1,bufByteCntPtr); }
|
||||||
|
|
||||||
cw::rc_t cw::fileLineCount( fileH_t h, unsigned* lineCntPtr )
|
cw::rc_t cw::file::lineCount( handle_t h, unsigned* lineCntPtr )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
file_t* p = _fileHandleToPtr(h);
|
this_t* p = _handleToPtr(h);
|
||||||
unsigned lineCnt = 0;
|
unsigned lineCnt = 0;
|
||||||
long offs;
|
long offs;
|
||||||
int c;
|
int c;
|
||||||
@ -510,7 +516,7 @@ cw::rc_t cw::fileLineCount( fileH_t h, unsigned* lineCntPtr )
|
|||||||
cwAssert( lineCntPtr != nullptr );
|
cwAssert( lineCntPtr != nullptr );
|
||||||
*lineCntPtr = 0;
|
*lineCntPtr = 0;
|
||||||
|
|
||||||
if((rc = fileTell(h,&offs)) != kOkRC )
|
if((rc = tell(h,&offs)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
@ -522,7 +528,7 @@ cw::rc_t cw::fileLineCount( fileH_t h, unsigned* lineCntPtr )
|
|||||||
if( c == EOF )
|
if( c == EOF )
|
||||||
{
|
{
|
||||||
if( errno )
|
if( errno )
|
||||||
rc = cwLogSysError(kReadFailRC,errno,"File read char failed on 's'.", cwStringNullGuard(fileName(h)));
|
rc = cwLogSysError(kReadFailRC,errno,"File read char failed on 's'.", cwStringNullGuard(name(h)));
|
||||||
else
|
else
|
||||||
++lineCnt; // add one in case the last line isn't terminated with a '\n'.
|
++lineCnt; // add one in case the last line isn't terminated with a '\n'.
|
||||||
|
|
||||||
@ -535,7 +541,7 @@ cw::rc_t cw::fileLineCount( fileH_t h, unsigned* lineCntPtr )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if((rc = fileSeek(h,kBeginFileFl,offs)) != kOkRC )
|
if((rc = seek(h,kBeginFl,offs)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
*lineCntPtr = lineCnt;
|
*lineCntPtr = lineCnt;
|
||||||
@ -544,10 +550,10 @@ cw::rc_t cw::fileLineCount( fileH_t h, unsigned* lineCntPtr )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::fileGetLine( fileH_t h, char* buf, unsigned* bufByteCntPtr )
|
cw::rc_t cw::file::getLine( handle_t h, char* buf, unsigned* bufByteCntPtr )
|
||||||
{
|
{
|
||||||
cwAssert( bufByteCntPtr != nullptr );
|
cwAssert( bufByteCntPtr != nullptr );
|
||||||
file_t* p = _fileHandleToPtr(h);
|
this_t* p = _handleToPtr(h);
|
||||||
unsigned tn = 128;
|
unsigned tn = 128;
|
||||||
char t[ tn ];
|
char t[ tn ];
|
||||||
unsigned on = *bufByteCntPtr;
|
unsigned on = *bufByteCntPtr;
|
||||||
@ -555,7 +561,7 @@ cw::rc_t cw::fileGetLine( fileH_t h, char* buf, unsigned* bufByteCntPtr )
|
|||||||
rc_t rc;
|
rc_t rc;
|
||||||
|
|
||||||
// store the current file offset
|
// store the current file offset
|
||||||
if((rc = fileTell(h,&offs)) != kOkRC )
|
if((rc = tell(h,&offs)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
// if no buffer was given then use t[]
|
// if no buffer was given then use t[]
|
||||||
@ -598,7 +604,7 @@ cw::rc_t cw::fileGetLine( fileH_t h, char* buf, unsigned* bufByteCntPtr )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// restore the original file offset
|
// restore the original file offset
|
||||||
if((rc = fileSeek(h,kBeginFileFl,offs)) != kOkRC )
|
if((rc = seek(h,kBeginFl,offs)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
// add 1 for /0, 1 for /n and 1 to detect buf-too-short
|
// add 1 for /0, 1 for /n and 1 to detect buf-too-short
|
||||||
@ -608,7 +614,7 @@ cw::rc_t cw::fileGetLine( fileH_t h, char* buf, unsigned* bufByteCntPtr )
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::fileGetLineAuto( fileH_t h, char** bufPtrPtr, unsigned* bufByteCntPtr )
|
cw::rc_t cw::file::getLineAuto( handle_t h, char** bufPtrPtr, unsigned* bufByteCntPtr )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
bool fl = true;
|
bool fl = true;
|
||||||
@ -620,7 +626,7 @@ cw::rc_t cw::fileGetLineAuto( fileH_t h, char** bufPtrPtr, unsigned* bufByteCntP
|
|||||||
{
|
{
|
||||||
fl = false;
|
fl = false;
|
||||||
|
|
||||||
switch( rc = fileGetLine(h,buf,bufByteCntPtr) )
|
switch( rc = getLine(h,buf,bufByteCntPtr) )
|
||||||
{
|
{
|
||||||
case kOkRC:
|
case kOkRC:
|
||||||
{
|
{
|
||||||
@ -644,91 +650,91 @@ cw::rc_t cw::fileGetLineAuto( fileH_t h, char** bufPtrPtr, unsigned* bufByteCntP
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::fileReadChar( fileH_t h, char* buf, unsigned cnt )
|
cw::rc_t cw::file::readChar( handle_t h, char* buf, unsigned cnt )
|
||||||
{ return fileRead(h,buf,sizeof(buf[0])*cnt); }
|
{ return read(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileReadUChar( fileH_t h, unsigned char* buf, unsigned cnt )
|
cw::rc_t cw::file::readUChar( handle_t h, unsigned char* buf, unsigned cnt )
|
||||||
{ return fileRead(h,buf,sizeof(buf[0])*cnt); }
|
{ return read(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileReadShort( fileH_t h, short* buf, unsigned cnt )
|
cw::rc_t cw::file::readShort( handle_t h, short* buf, unsigned cnt )
|
||||||
{ return fileRead(h,buf,sizeof(buf[0])*cnt); }
|
{ return read(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileReadUShort( fileH_t h, unsigned short* buf, unsigned cnt )
|
cw::rc_t cw::file::readUShort( handle_t h, unsigned short* buf, unsigned cnt )
|
||||||
{ return fileRead(h,buf,sizeof(buf[0])*cnt); }
|
{ return read(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileReadLong( fileH_t h, long* buf, unsigned cnt )
|
cw::rc_t cw::file::readLong( handle_t h, long* buf, unsigned cnt )
|
||||||
{ return fileRead(h,buf,sizeof(buf[0])*cnt); }
|
{ return read(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileReadULong( fileH_t h, unsigned long* buf, unsigned cnt )
|
cw::rc_t cw::file::readULong( handle_t h, unsigned long* buf, unsigned cnt )
|
||||||
{ return fileRead(h,buf,sizeof(buf[0])*cnt); }
|
{ return read(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileReadInt( fileH_t h, int* buf, unsigned cnt )
|
cw::rc_t cw::file::readInt( handle_t h, int* buf, unsigned cnt )
|
||||||
{ return fileRead(h,buf,sizeof(buf[0])*cnt); }
|
{ return read(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileReadUInt( fileH_t h, unsigned int* buf, unsigned cnt )
|
cw::rc_t cw::file::readUInt( handle_t h, unsigned int* buf, unsigned cnt )
|
||||||
{ return fileRead(h,buf,sizeof(buf[0])*cnt); }
|
{ return read(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileReadFloat( fileH_t h, float* buf, unsigned cnt )
|
cw::rc_t cw::file::readFloat( handle_t h, float* buf, unsigned cnt )
|
||||||
{ return fileRead(h,buf,sizeof(buf[0])*cnt); }
|
{ return read(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileReadDouble( fileH_t h, double* buf, unsigned cnt )
|
cw::rc_t cw::file::readDouble( handle_t h, double* buf, unsigned cnt )
|
||||||
{ return fileRead(h,buf,sizeof(buf[0])*cnt); }
|
{ return read(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileReadBool( fileH_t h, bool* buf, unsigned cnt )
|
cw::rc_t cw::file::readBool( handle_t h, bool* buf, unsigned cnt )
|
||||||
{ return fileRead(h,buf,sizeof(buf[0])*cnt); }
|
{ return read(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::fileWriteChar( fileH_t h, const char* buf, unsigned cnt )
|
cw::rc_t cw::file::writeChar( handle_t h, const char* buf, unsigned cnt )
|
||||||
{ return fileWrite(h,buf,sizeof(buf[0])*cnt); }
|
{ return write(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileWriteUChar( fileH_t h, const unsigned char* buf, unsigned cnt )
|
cw::rc_t cw::file::writeUChar( handle_t h, const unsigned char* buf, unsigned cnt )
|
||||||
{ return fileWrite(h,buf,sizeof(buf[0])*cnt); }
|
{ return write(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileWriteShort( fileH_t h, const short* buf, unsigned cnt )
|
cw::rc_t cw::file::writeShort( handle_t h, const short* buf, unsigned cnt )
|
||||||
{ return fileWrite(h,buf,sizeof(buf[0])*cnt); }
|
{ return write(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileWriteUShort( fileH_t h, const unsigned short* buf, unsigned cnt )
|
cw::rc_t cw::file::writeUShort( handle_t h, const unsigned short* buf, unsigned cnt )
|
||||||
{ return fileWrite(h,buf,sizeof(buf[0])*cnt); }
|
{ return write(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileWriteLong( fileH_t h, const long* buf, unsigned cnt )
|
cw::rc_t cw::file::writeLong( handle_t h, const long* buf, unsigned cnt )
|
||||||
{ return fileWrite(h,buf,sizeof(buf[0])*cnt); }
|
{ return write(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileWriteULong( fileH_t h, const unsigned long* buf, unsigned cnt )
|
cw::rc_t cw::file::writeULong( handle_t h, const unsigned long* buf, unsigned cnt )
|
||||||
{ return fileWrite(h,buf,sizeof(buf[0])*cnt); }
|
{ return write(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileWriteInt( fileH_t h, const int* buf, unsigned cnt )
|
cw::rc_t cw::file::writeInt( handle_t h, const int* buf, unsigned cnt )
|
||||||
{ return fileWrite(h,buf,sizeof(buf[0])*cnt); }
|
{ return write(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileWriteUInt( fileH_t h, const unsigned int* buf, unsigned cnt )
|
cw::rc_t cw::file::writeUInt( handle_t h, const unsigned int* buf, unsigned cnt )
|
||||||
{ return fileWrite(h,buf,sizeof(buf[0])*cnt); }
|
{ return write(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileWriteFloat( fileH_t h, const float* buf, unsigned cnt )
|
cw::rc_t cw::file::writeFloat( handle_t h, const float* buf, unsigned cnt )
|
||||||
{ return fileWrite(h,buf,sizeof(buf[0])*cnt); }
|
{ return write(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileWriteDouble( fileH_t h, const double* buf, unsigned cnt )
|
cw::rc_t cw::file::writeDouble( handle_t h, const double* buf, unsigned cnt )
|
||||||
{ return fileWrite(h,buf,sizeof(buf[0])*cnt); }
|
{ return write(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
cw::rc_t cw::fileWriteBool( fileH_t h, const bool* buf, unsigned cnt )
|
cw::rc_t cw::file::writeBool( handle_t h, const bool* buf, unsigned cnt )
|
||||||
{ return fileWrite(h,buf,sizeof(buf[0])*cnt); }
|
{ return write(h,buf,sizeof(buf[0])*cnt); }
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::fileWriteStr( fileH_t h, const char* s )
|
cw::rc_t cw::file::writeStr( handle_t h, const char* s )
|
||||||
{
|
{
|
||||||
rc_t rc;
|
rc_t rc;
|
||||||
|
|
||||||
unsigned n = textLength(s);
|
unsigned n = textLength(s);
|
||||||
|
|
||||||
if((rc = fileWriteUInt(h,&n,1)) != kOkRC )
|
if((rc = writeUInt(h,&n,1)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if( n > 0 )
|
if( n > 0 )
|
||||||
rc = fileWriteChar(h,s,n);
|
rc = writeChar(h,s,n);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::fileReadStr( fileH_t h, char** sRef, unsigned maxCharN )
|
cw::rc_t cw::file::readStr( handle_t h, char** sRef, unsigned maxCharN )
|
||||||
{
|
{
|
||||||
unsigned n;
|
unsigned n;
|
||||||
rc_t rc;
|
rc_t rc;
|
||||||
@ -741,7 +747,7 @@ cw::rc_t cw::fileReadStr( fileH_t h, char** sRef, unsigned maxCharN )
|
|||||||
maxCharN = 16384;
|
maxCharN = 16384;
|
||||||
|
|
||||||
// read the string length
|
// read the string length
|
||||||
if((rc = fileReadUInt(h,&n,1)) != kOkRC )
|
if((rc = readUInt(h,&n,1)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
// verify that string isn't too long
|
// verify that string isn't too long
|
||||||
@ -754,7 +760,7 @@ cw::rc_t cw::fileReadStr( fileH_t h, char** sRef, unsigned maxCharN )
|
|||||||
char* s = memAllocZ<char>(n+1);
|
char* s = memAllocZ<char>(n+1);
|
||||||
|
|
||||||
// fill the buffer from the file
|
// fill the buffer from the file
|
||||||
if((rc = fileReadChar(h,s,n)) != kOkRC )
|
if((rc = readChar(h,s,n)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
s[n] = 0; // terminate the string
|
s[n] = 0; // terminate the string
|
||||||
@ -765,33 +771,33 @@ cw::rc_t cw::fileReadStr( fileH_t h, char** sRef, unsigned maxCharN )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::filePrint( fileH_t h, const char* text )
|
cw::rc_t cw::file::print( handle_t h, const char* text )
|
||||||
{
|
{
|
||||||
file_t* p = _fileHandleToPtr(h);
|
this_t* p = _handleToPtr(h);
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
if( fputs(text,p->fp) < 0 )
|
if( fputs(text,p->fp) < 0 )
|
||||||
return cwLogSysError(kOpFailRC,errno,"File print failed on '%s'.", cwStringNullGuard(fileName(h)));
|
return cwLogSysError(kOpFailRC,errno,"File print failed on '%s'.", cwStringNullGuard(name(h)));
|
||||||
|
|
||||||
return kOkRC;
|
return kOkRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::fileVPrintf( fileH_t h, const char* fmt, va_list vl )
|
cw::rc_t cw::file::vPrintf( handle_t h, const char* fmt, va_list vl )
|
||||||
{
|
{
|
||||||
file_t* p = _fileHandleToPtr(h);
|
this_t* p = _handleToPtr(h);
|
||||||
|
|
||||||
if( vfprintf(p->fp,fmt,vl) < 0 )
|
if( vfprintf(p->fp,fmt,vl) < 0 )
|
||||||
return cwLogSysError(kOpFailRC,errno,"File print failed on '%s'.", cwStringNullGuard(fileName(h)));
|
return cwLogSysError(kOpFailRC,errno,"File print failed on '%s'.", cwStringNullGuard(name(h)));
|
||||||
|
|
||||||
return kOkRC;
|
return kOkRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::filePrintf( fileH_t h, const char* fmt, ... )
|
cw::rc_t cw::file::printf( handle_t h, const char* fmt, ... )
|
||||||
{
|
{
|
||||||
va_list vl;
|
va_list vl;
|
||||||
va_start(vl,fmt);
|
va_start(vl,fmt);
|
||||||
rc_t rc = fileVPrintf(h,fmt,vl);
|
rc_t rc = vPrintf(h,fmt,vl);
|
||||||
va_end(vl);
|
va_end(vl);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
341
cwFile.h
341
cwFile.h
@ -3,206 +3,209 @@
|
|||||||
|
|
||||||
namespace cw
|
namespace cw
|
||||||
{
|
{
|
||||||
typedef handle<struct file_str> fileH_t;
|
namespace file
|
||||||
|
|
||||||
// Flags for use with fileOpen().
|
|
||||||
enum fileOpenFlags_t
|
|
||||||
{
|
{
|
||||||
kReadFileFl = 0x01, //< Open a file for reading
|
|
||||||
kWriteFileFl = 0x02, //< Create an empty file for writing
|
typedef handle<struct file_str> handle_t;
|
||||||
kAppendFileFl = 0x04, //< Open a file for writing at the end of the file.
|
|
||||||
kUpdateFileFl = 0x08, //< Open a file for reading and writing.
|
|
||||||
kBinaryFileFl = 0x10, //< Open a file for binary (not text) input/output.
|
|
||||||
kStdoutFileFl = 0x20, //< Ignore fn use 'stdout'
|
|
||||||
kStderrFileFl = 0x40, //< Ignore fn use 'stderr'
|
|
||||||
kStdinFileFl = 0x80, //< Ignore fn use 'stdin'
|
|
||||||
};
|
|
||||||
|
|
||||||
// Open or create a file.
|
// Flags for use with fileOpen().
|
||||||
// Equivalent to fopen().
|
enum openFlags_t
|
||||||
// If *hp was not initalized by an earlier call to fileOpen() then it should
|
{
|
||||||
// be set to fileNullHandle prior to calling this function. If *hp is a valid handle
|
kReadFl = 0x01, //< Open a file for reading
|
||||||
// then it is automatically finalized by an internal call to fileClose() prior to
|
kWriteFl = 0x02, //< Create an empty file for writing
|
||||||
// being re-iniitalized.
|
kAppendFl = 0x04, //< Open a file for writing at the end of the file.
|
||||||
//
|
kUpdateFl = 0x08, //< Open a file for reading and writing.
|
||||||
// If kStdoutFileFl, kStderrFileFl or kStdinFileFl are set then
|
kBinaryFl = 0x10, //< Open a file for binary (not text) input/output.
|
||||||
// file name argument 'fn' is ignored.
|
kStdoutFl = 0x20, //< Ignore fn use 'stdout'
|
||||||
rc_t fileOpen(
|
kStderrFl = 0x40, //< Ignore fn use 'stderr'
|
||||||
fileH_t& hRef, // Pointer to a client supplied fileHandle_t to recieve the handle for the new object.
|
kStdinFl = 0x80, //< Ignore fn use 'stdin'
|
||||||
const char* fn, // The name of the file to open or create.
|
};
|
||||||
unsigned flags ); // See fileOpenFlags_t
|
|
||||||
|
|
||||||
// Close a file opened with Equivalent to fclose().
|
// Open or create a file.
|
||||||
rc_t fileClose( fileH_t& hRef );
|
// Equivalent to fopen().
|
||||||
|
// If *hp was not initalized by an earlier call to fileOpen() then it should
|
||||||
|
// be set to fileNullHandle prior to calling this function. If *hp is a valid handle
|
||||||
|
// then it is automatically finalized by an internal call to fileClose() prior to
|
||||||
|
// being re-iniitalized.
|
||||||
|
//
|
||||||
|
// If kStdoutFl, kStderrFl or kStdinFl are set then
|
||||||
|
// file name argument 'fn' is ignored.
|
||||||
|
rc_t open(
|
||||||
|
handle_t& hRef, // Pointer to a client supplied fileHandle_t to recieve the handle for the new object.
|
||||||
|
const char* fn, // The name of the file to open or create.
|
||||||
|
unsigned flags ); // See fileOpenFlags_t
|
||||||
|
|
||||||
// Return true if the file handle is associated with an open file.
|
// Close a file opened with Equivalent to fclose().
|
||||||
bool fileIsValid( fileH_t h );
|
rc_t close( handle_t& hRef );
|
||||||
|
|
||||||
// Read a block bytes from a file. Equivalent to fread().
|
// Return true if the file handle is associated with an open file.
|
||||||
rc_t fileRead( fileH_t h, void* buf, unsigned bufByteCnt );
|
bool isValid( handle_t h );
|
||||||
|
|
||||||
// Write a block of bytes to a file. Equivalent to fwrite().
|
// Read a block bytes from a file. Equivalent to fread().
|
||||||
rc_t fileWrite( fileH_t h, const void* buf, unsigned bufByteCnt );
|
rc_t read( handle_t h, void* buf, unsigned bufByteCnt );
|
||||||
|
|
||||||
|
// Write a block of bytes to a file. Equivalent to fwrite().
|
||||||
|
rc_t write( handle_t h, const void* buf, unsigned bufByteCnt );
|
||||||
|
|
||||||
enum fileSeekFlags_t
|
enum seekFlags_t
|
||||||
{
|
{
|
||||||
kBeginFileFl = 0x01,
|
kBeginFl = 0x01,
|
||||||
kCurFileFl = 0x02,
|
kCurFl = 0x02,
|
||||||
kEndFileFl = 0x04
|
kEndFl = 0x04
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set the file position indicator. Equivalent to fseek().
|
// Set the file position indicator. Equivalent to fseek().
|
||||||
rc_t fileSeek( fileH_t h, enum fileSeekFlags_t flags, int offsByteCnt );
|
rc_t seek( handle_t h, enum seekFlags_t flags, int offsByteCnt );
|
||||||
|
|
||||||
// Return the file position indicator. Equivalent to ftell().
|
// Return the file position indicator. Equivalent to ftell().
|
||||||
rc_t fileTell( fileH_t h, long* offsPtr );
|
rc_t tell( handle_t h, long* offsPtr );
|
||||||
|
|
||||||
// Return true if the file position indicator is at the end of the file.
|
// Return true if the file position indicator is at the end of the file.
|
||||||
// Equivalent to feof().
|
// Equivalent to feof().
|
||||||
bool fileEof( fileH_t h );
|
bool eof( handle_t h );
|
||||||
|
|
||||||
// Return the length of the file in bytes
|
// Return the length of the file in bytes
|
||||||
unsigned fileByteCount( fileH_t h );
|
unsigned byteCount( handle_t h );
|
||||||
rc_t fileByteCountFn( const char* fn, unsigned* fileByteCntPtr );
|
rc_t byteCountFn( const char* fn, unsigned* fileByteCntPtr );
|
||||||
|
|
||||||
// Set *isEqualPtr=true if the two files are identical.
|
// Set *isEqualPtr=true if the two files are identical.
|
||||||
rc_t fileCompare( const char* fn0, const char* fn1, bool& isEqualFlRef );
|
rc_t compare( const char* fn0, const char* fn1, bool& isEqualFlRef );
|
||||||
|
|
||||||
// Return the file name associated with a file handle.
|
// Return the file name associated with a file handle.
|
||||||
const char* fileName( fileH_t h );
|
const char* name( handle_t h );
|
||||||
|
|
||||||
// Write a buffer to a file.
|
// Write a buffer to a file.
|
||||||
rc_t fileFnWrite( const char* fn, const void* buf, unsigned bufByteCnt );
|
rc_t fnWrite( const char* fn, const void* buf, unsigned bufByteCnt );
|
||||||
|
|
||||||
// Allocate and fill a buffer from the file.
|
// Allocate and fill a buffer from the file.
|
||||||
// Set *bufByteCntPtr to count of bytes read into the buffer.
|
// Set *bufByteCntPtr to count of bytes read into the buffer.
|
||||||
// 'bufByteCntPtr' is optional - set it to nullptr if it is not required by the caller.
|
// 'bufByteCntPtr' is optional - set it to nullptr if it is not required by the caller.
|
||||||
// It is the callers responsibility to delete the returned buffer with a
|
// It is the callers responsibility to delete the returned buffer with a
|
||||||
// call to cmMemFree()
|
// call to cmMemFree()
|
||||||
char* fileToBuf( fileH_t h, unsigned* bufByteCntPtr );
|
char* toBuf( handle_t h, unsigned* bufByteCntPtr );
|
||||||
|
|
||||||
// Same as fileToBuf() but accepts a file name argument.
|
// Same as fileToBuf() but accepts a file name argument.
|
||||||
char* fileFnToBuf( const char* fn, unsigned* bufByteCntPtr );
|
char* fnToBuf( const char* fn, unsigned* bufByteCntPtr );
|
||||||
|
|
||||||
|
|
||||||
// Copy the file named in srcDir/srcFn/srcExt to a file named dstDir/dstFn/dstExt.
|
// Copy the file named in srcDir/srcFn/srcExt to a file named dstDir/dstFn/dstExt.
|
||||||
// Note that srcExt/dstExt may be set to nullptr if the file extension is included
|
// Note that srcExt/dstExt may be set to nullptr if the file extension is included
|
||||||
// in srcFn/dstFn. Likewise srcFn/dstFn may be set to nullptr if the file name
|
// in srcFn/dstFn. Likewise srcFn/dstFn may be set to nullptr if the file name
|
||||||
// is included in srcDir/dstDir.
|
// is included in srcDir/dstDir.
|
||||||
rc_t fileCopy(
|
rc_t copy(
|
||||||
const char* srcDir,
|
const char* srcDir,
|
||||||
const char* srcFn,
|
const char* srcFn,
|
||||||
const char* srcExt,
|
const char* srcExt,
|
||||||
const char* dstDir,
|
const char* dstDir,
|
||||||
const char* dstFn,
|
const char* dstFn,
|
||||||
const char* dstExt);
|
const char* dstExt);
|
||||||
|
|
||||||
|
|
||||||
// This function creates a backup copy of the file 'fn' by duplicating it into
|
// This function creates a backup copy of the file 'fn' by duplicating it into
|
||||||
// a file named fn_#.ext where # is an integer which makes the file name unique.
|
// a file named fn_#.ext where # is an integer which makes the file name unique.
|
||||||
// The integers chosen with zero and are incremented until an
|
// The integers chosen with zero and are incremented until an
|
||||||
// unused file name is found in the same directory as 'fn'.
|
// unused file name is found in the same directory as 'fn'.
|
||||||
// If the file identified by 'fn' is not found then the function returns quietly.
|
// If the file identified by 'fn' is not found then the function returns quietly.
|
||||||
rc_t fileBackup( const char* dir, const char* name, const char* ext );
|
rc_t backup( const char* dir, const char* name, const char* ext );
|
||||||
|
|
||||||
// Allocate and fill a zero terminated string from a file.
|
// Allocate and fill a zero terminated string from a file.
|
||||||
// Set *bufByteCntPtr to count of bytes read into the buffer.=
|
// Set *bufByteCntPtr to count of bytes read into the buffer.=
|
||||||
// (the buffer memory size is one byte larger to account for the terminating zero)
|
// (the buffer memory size is one byte larger to account for the terminating zero)
|
||||||
// 'bufByteCntPtr' is optional - set it to nullptr if it is not required by the caller.
|
// 'bufByteCntPtr' is optional - set it to nullptr if it is not required by the caller.
|
||||||
// It is the callers responsibility to delete the returned buffer with a
|
// It is the callers responsibility to delete the returned buffer with a
|
||||||
// call to cmMemFree()
|
// call to cmMemFree()
|
||||||
char* fileToStr( fileH_t h, unsigned* bufByteCntPtr );
|
char* toStr( handle_t h, unsigned* bufByteCntPtr );
|
||||||
|
|
||||||
// Same as fileToBuf() but accepts a file name argument.
|
// Same as fileToBuf() but accepts a file name argument.
|
||||||
char* fileFnToStr( const char* fn, unsigned* bufByteCntPtr );
|
char* fnToStr( const char* fn, unsigned* bufByteCntPtr );
|
||||||
|
|
||||||
// Return the count of lines in a file.
|
// Return the count of lines in a file.
|
||||||
rc_t fileLineCount( fileH_t h, unsigned* lineCntPtr );
|
rc_t lineCount( handle_t h, unsigned* lineCntPtr );
|
||||||
|
|
||||||
// Read the next line into buf[bufByteCnt].
|
// Read the next line into buf[bufByteCnt].
|
||||||
// Consider using fileGetLineAuto() as an alternative to this function
|
// Consider using fileGetLineAuto() as an alternative to this function
|
||||||
// to avoid having to use a buffer with an explicit size.
|
// to avoid having to use a buffer with an explicit size.
|
||||||
//
|
//
|
||||||
// If buf is not long enough to hold the entire string then
|
// If buf is not long enough to hold the entire string then
|
||||||
//
|
//
|
||||||
// 1. The function returns kFileBufTooSmallRC
|
// 1. The function returns kFileBufTooSmallRC
|
||||||
// 2. *bufByteCntPtr is set to the size of the required buffer.
|
// 2. *bufByteCntPtr is set to the size of the required buffer.
|
||||||
// 3. The internal file position is left unchanged.
|
// 3. The internal file position is left unchanged.
|
||||||
//
|
//
|
||||||
// If the buffer is long enough to hold the entire line then
|
// If the buffer is long enough to hold the entire line then
|
||||||
// *bufByteCntPtr is left unchanged.
|
// *bufByteCntPtr is left unchanged.
|
||||||
// See fileGetLineTest() in cmProcTest.c or fileGetLineAuto()
|
// See fileGetLineTest() in cmProcTest.c or fileGetLineAuto()
|
||||||
// in file.c for examples of how to use this function to a
|
// in file.c for examples of how to use this function to a
|
||||||
// achieve proper buffer sizing.
|
// achieve proper buffer sizing.
|
||||||
rc_t fileGetLine( fileH_t h, char* buf, unsigned* bufByteCntPtr );
|
rc_t getLine( handle_t h, char* buf, unsigned* bufByteCntPtr );
|
||||||
|
|
||||||
// A version of fileGetLine() which eliminates the need to handle buffer
|
// A version of fileGetLine() which eliminates the need to handle buffer
|
||||||
// sizing.
|
// sizing.
|
||||||
//
|
//
|
||||||
// Example usage:
|
// Example usage:
|
||||||
//
|
//
|
||||||
// char* buf = nullptr;
|
// char* buf = nullptr;
|
||||||
// unsigned bufByteCnt = 0;
|
// unsigned bufByteCnt = 0;
|
||||||
// while(fileGetLineAuto(h,&buf,&bufByteCnt)==kOkFileRC)
|
// while(fileGetLineAuto(h,&buf,&bufByteCnt)==kOkFileRC)
|
||||||
// proc(buf);
|
// proc(buf);
|
||||||
// cmMemPtrFree(buf);
|
// cmMemPtrFree(buf);
|
||||||
//
|
//
|
||||||
// On the first call to this function *bufPtrPtr must be set to nullptr and
|
// On the first call to this function *bufPtrPtr must be set to nullptr and
|
||||||
// *bufByteCntPtr must be set to 0.
|
// *bufByteCntPtr must be set to 0.
|
||||||
// Following the last call to this function call cmMemPtrFree(bufPtrptr)
|
// Following the last call to this function call cmMemPtrFree(bufPtrptr)
|
||||||
// to be sure the line buffer is fully released. Note this step is not
|
// to be sure the line buffer is fully released. Note this step is not
|
||||||
// neccessary if the last call does not return kOkFileRC.
|
// neccessary if the last call does not return kOkFileRC.
|
||||||
rc_t fileGetLineAuto( fileH_t h, char** bufPtrPtr, unsigned* bufByteCntPtr );
|
rc_t getLineAuto( handle_t h, char** bufPtrPtr, unsigned* bufByteCntPtr );
|
||||||
|
|
||||||
// Binary Array Reading Functions
|
// Binary Array Reading Functions
|
||||||
// Each of these functions reads a block of binary data from a file.
|
// Each of these functions reads a block of binary data from a file.
|
||||||
// The advantage to using these functions over fileRead() is only that they are type specific.
|
// The advantage to using these functions over fileRead() is only that they are type specific.
|
||||||
rc_t fileReadChar( fileH_t h, char* buf, unsigned cnt );
|
rc_t readChar( handle_t h, char* buf, unsigned cnt );
|
||||||
rc_t fileReadUChar( fileH_t h, unsigned char* buf, unsigned cnt );
|
rc_t readUChar( handle_t h, unsigned char* buf, unsigned cnt );
|
||||||
rc_t fileReadShort( fileH_t h, short* buf, unsigned cnt );
|
rc_t readShort( handle_t h, short* buf, unsigned cnt );
|
||||||
rc_t fileReadUShort( fileH_t h, unsigned short* buf, unsigned cnt );
|
rc_t readUShort( handle_t h, unsigned short* buf, unsigned cnt );
|
||||||
rc_t fileReadLong( fileH_t h, long* buf, unsigned cnt );
|
rc_t readLong( handle_t h, long* buf, unsigned cnt );
|
||||||
rc_t fileReadULong( fileH_t h, unsigned long* buf, unsigned cnt );
|
rc_t readULong( handle_t h, unsigned long* buf, unsigned cnt );
|
||||||
rc_t fileReadInt( fileH_t h, int* buf, unsigned cnt );
|
rc_t readInt( handle_t h, int* buf, unsigned cnt );
|
||||||
rc_t fileReadUInt( fileH_t h, unsigned int* buf, unsigned cnt );
|
rc_t readUInt( handle_t h, unsigned int* buf, unsigned cnt );
|
||||||
rc_t fileReadFloat( fileH_t h, float* buf, unsigned cnt );
|
rc_t readFloat( handle_t h, float* buf, unsigned cnt );
|
||||||
rc_t fileReadDouble( fileH_t h, double* buf, unsigned cnt );
|
rc_t readDouble( handle_t h, double* buf, unsigned cnt );
|
||||||
rc_t fileReadBool( fileH_t h, bool* buf, unsigned cnt );
|
rc_t readBool( handle_t h, bool* buf, unsigned cnt );
|
||||||
|
|
||||||
// Binary Array Writing Functions
|
// Binary Array Writing Functions
|
||||||
// Each of these functions writes an array to a binary file.
|
// Each of these functions writes an array to a binary file.
|
||||||
// The advantage to using functions rather than fileWrite() is only that they are type specific.
|
// The advantage to using functions rather than fileWrite() is only that they are type specific.
|
||||||
rc_t fileWriteChar( fileH_t h, const char* buf, unsigned cnt );
|
rc_t writeChar( handle_t h, const char* buf, unsigned cnt );
|
||||||
rc_t fileWriteUChar( fileH_t h, const unsigned char* buf, unsigned cnt );
|
rc_t writeUChar( handle_t h, const unsigned char* buf, unsigned cnt );
|
||||||
rc_t fileWriteShort( fileH_t h, const short* buf, unsigned cnt );
|
rc_t writeShort( handle_t h, const short* buf, unsigned cnt );
|
||||||
rc_t fileWriteUShort( fileH_t h, const unsigned short* buf, unsigned cnt );
|
rc_t writeUShort( handle_t h, const unsigned short* buf, unsigned cnt );
|
||||||
rc_t fileWriteLong( fileH_t h, const long* buf, unsigned cnt );
|
rc_t writeLong( handle_t h, const long* buf, unsigned cnt );
|
||||||
rc_t fileWriteULong( fileH_t h, const unsigned long* buf, unsigned cnt );
|
rc_t writeULong( handle_t h, const unsigned long* buf, unsigned cnt );
|
||||||
rc_t fileWriteInt( fileH_t h, const int* buf, unsigned cnt );
|
rc_t writeInt( handle_t h, const int* buf, unsigned cnt );
|
||||||
rc_t fileWriteUInt( fileH_t h, const unsigned int* buf, unsigned cnt );
|
rc_t writeUInt( handle_t h, const unsigned int* buf, unsigned cnt );
|
||||||
rc_t fileWriteFloat( fileH_t h, const float* buf, unsigned cnt );
|
rc_t writeFloat( handle_t h, const float* buf, unsigned cnt );
|
||||||
rc_t fileWriteDouble( fileH_t h, const double* buf, unsigned cnt );
|
rc_t writeDouble( handle_t h, const double* buf, unsigned cnt );
|
||||||
rc_t fileWriteBool( fileH_t h, const bool* buf, unsigned cnt );
|
rc_t writeBool( handle_t h, const bool* buf, unsigned cnt );
|
||||||
|
|
||||||
// Write a string to a file as <N> <char0> <char1> ... <char(N-1)>
|
// Write a string to a file as <N> <char0> <char1> ... <char(N-1)>
|
||||||
// where N is the count of characters in the string.
|
// where N is the count of characters in the string.
|
||||||
rc_t fileWriteStr( fileH_t h, const char* s );
|
rc_t writeStr( handle_t h, const char* s );
|
||||||
|
|
||||||
// Read a string back from a file as written by fileWriteStr().
|
// Read a string back from a file as written by fileWriteStr().
|
||||||
// Note that the string will by string will be dynamically allocated
|
// Note that the string will by string will be dynamically allocated
|
||||||
// and threfore must eventually be released via cmMemFree().
|
// and threfore must eventually be released via cmMemFree().
|
||||||
// If maxCharN is set to zero then the default maximum string
|
// If maxCharN is set to zero then the default maximum string
|
||||||
// length is 16384. Note that this limit is used to prevent
|
// length is 16384. Note that this limit is used to prevent
|
||||||
// corrupt files from generating excessively long strings.
|
// corrupt files from generating excessively long strings.
|
||||||
rc_t fileReadStr( fileH_t h, char** sRef, unsigned maxCharN );
|
rc_t readStr( handle_t h, char** sRef, unsigned maxCharN );
|
||||||
|
|
||||||
// Formatted Text Output Functions:
|
// Formatted Text Output Functions:
|
||||||
// Print formatted text to a file.
|
// Print formatted text to a file.
|
||||||
rc_t filePrint( fileH_t h, const char* text );
|
rc_t print( handle_t h, const char* text );
|
||||||
rc_t filePrintf( fileH_t h, const char* fmt, ... );
|
rc_t printf( handle_t h, const char* fmt, ... );
|
||||||
rc_t fileVPrintf( fileH_t h, const char* fmt, va_list vl );
|
rc_t vPrintf( handle_t h, const char* fmt, va_list vl );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
cwLex.cpp
20
cwLex.cpp
@ -532,27 +532,27 @@ cw::rc_t cw::lexSetTextBuffer( lexH_t h, const char* cp, unsigned cn
|
|||||||
|
|
||||||
cw::rc_t cw::lexSetFile( lexH_t h, const char* fn )
|
cw::rc_t cw::lexSetFile( lexH_t h, const char* fn )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
fileH_t fh;
|
file::handle_t fh;
|
||||||
lex_t* p = _lexHandleToPtr(h);
|
lex_t* p = _lexHandleToPtr(h);
|
||||||
long n = 0;
|
long n = 0;
|
||||||
|
|
||||||
assert( fn != nullptr && p != nullptr );
|
assert( fn != nullptr && p != nullptr );
|
||||||
|
|
||||||
// open the file
|
// open the file
|
||||||
if((rc = fileOpen(fh,fn,kReadFileFl)) != kOkRC )
|
if((rc = file::open(fh,fn,file::kReadFl)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
// seek to the end of the file
|
// seek to the end of the file
|
||||||
if((rc = fileSeek(fh,kEndFileFl,0)) != kOkRC )
|
if((rc = file::seek(fh,file::kEndFl,0)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
// get the length of the file
|
// get the length of the file
|
||||||
if((rc = fileTell(fh,&n)) != kOkRC )
|
if((rc = file::tell(fh,&n)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
// rewind to the beginning of the file
|
// rewind to the beginning of the file
|
||||||
if((rc = fileSeek(fh,kBeginFileFl,0)) != kOkRC )
|
if((rc = file::seek(fh,file::kBeginFl,0)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
// allocate the text buffer
|
// allocate the text buffer
|
||||||
@ -563,7 +563,7 @@ cw::rc_t cw::lexSetFile( lexH_t h, const char* fn )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// read the file into the buffer
|
// read the file into the buffer
|
||||||
if((rc = fileRead(fh,p->textBuf,n)) != kOkRC )
|
if((rc = file::read(fh,p->textBuf,n)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if((rc = _lexSetTextBuffer( p, p->textBuf, n )) != kOkRC )
|
if((rc = _lexSetTextBuffer( p, p->textBuf, n )) != kOkRC )
|
||||||
@ -571,7 +571,7 @@ cw::rc_t cw::lexSetFile( lexH_t h, const char* fn )
|
|||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
// close the file
|
// close the file
|
||||||
rc_t rc0 = fileClose(fh);
|
rc_t rc0 = file::close(fh);
|
||||||
|
|
||||||
if(rc != kOkRC )
|
if(rc != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
5
cwMem.h
5
cwMem.h
@ -93,11 +93,12 @@ namespace cw
|
|||||||
return memDuplStr(s1);
|
return memDuplStr(s1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// s1n is <= s0n
|
||||||
// copy s1[] into s0[]
|
// copy s1[] into s0[]
|
||||||
size_t i=0;
|
size_t i=0;
|
||||||
for(; s1[i]; ++i)
|
for(; s1[i]; ++i)
|
||||||
s0[i] = s1[i];
|
s0[i] = s1[i];
|
||||||
s0[i+1] = 0;
|
s0[i] = 0;
|
||||||
|
|
||||||
return s0;
|
return s0;
|
||||||
}
|
}
|
||||||
@ -118,7 +119,7 @@ namespace cw
|
|||||||
|
|
||||||
|
|
||||||
C buf[ bufN + 1 ];
|
C buf[ bufN + 1 ];
|
||||||
size_t n = vsnprintf(buf,bufN,fmt,vl1);
|
size_t n = vsnprintf(buf,bufN+1,fmt,vl1);
|
||||||
|
|
||||||
cwAssert(n <= bufN);
|
cwAssert(n <= bufN);
|
||||||
|
|
||||||
|
@ -521,7 +521,7 @@ cw::rc_t cw::objectFromFile( const char* fn, object_t*& objRef )
|
|||||||
unsigned bufByteCnt = 0;
|
unsigned bufByteCnt = 0;
|
||||||
char* buf = NULL;
|
char* buf = NULL;
|
||||||
|
|
||||||
if(( buf = fileFnToStr(fn, &bufByteCnt)) != NULL )
|
if(( buf = file::fnToStr(fn, &bufByteCnt)) != NULL )
|
||||||
{
|
{
|
||||||
rc = objectFromString( buf, objRef );
|
rc = objectFromString( buf, objRef );
|
||||||
memRelease(buf);
|
memRelease(buf);
|
||||||
|
13
main.cpp
13
main.cpp
@ -16,7 +16,9 @@
|
|||||||
#include "cwMidi.h"
|
#include "cwMidi.h"
|
||||||
#include "cwTime.h"
|
#include "cwTime.h"
|
||||||
#include "cwMidiPort.h"
|
#include "cwMidiPort.h"
|
||||||
#include "cwAudioPort.h"
|
#include "cwAudioDevice.h"
|
||||||
|
#include "cwAudioDeviceTest.h"
|
||||||
|
#include "cwAudioDeviceAlsa.h"
|
||||||
#include "cwAudioBuf.h"
|
#include "cwAudioBuf.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -126,10 +128,8 @@ void serialPortSrvTest( cw::object_t* cfg, int argc, const char* argv[] ) { cw::
|
|||||||
void midiDeviceTest( cw::object_t* cfg, int argc, const char* argv[] ) { cw::midi::device::test();}
|
void midiDeviceTest( cw::object_t* cfg, int argc, const char* argv[] ) { cw::midi::device::test();}
|
||||||
void textBufTest( cw::object_t* cfg, int argc, const char* argv[] ) { cw::textBuf::test(); }
|
void textBufTest( cw::object_t* cfg, int argc, const char* argv[] ) { cw::textBuf::test(); }
|
||||||
void audioBufTest( cw::object_t* cfg, int argc, const char* argv[] ) { cw::audio::buf::test(); }
|
void audioBufTest( cw::object_t* cfg, int argc, const char* argv[] ) { cw::audio::buf::test(); }
|
||||||
void audioPortTest( cw::object_t* cfg, int argc, const char* argv[] )
|
void audioDevTest( cw::object_t* cfg, int argc, const char* argv[] ) { cw::audio::device::test( argc, argv ); }
|
||||||
{
|
void audioDevAlsaTest( cw::object_t* cfg, int argc, const char* argv[] ) { cw::audio::device::alsa::report(); }
|
||||||
cw::audio::device::test( false, argc, argv );
|
|
||||||
}
|
|
||||||
|
|
||||||
void stubTest( cw::object_t* cfg, int argc, const char* argv[] )
|
void stubTest( cw::object_t* cfg, int argc, const char* argv[] )
|
||||||
{
|
{
|
||||||
@ -168,7 +168,8 @@ int main( int argc, const char* argv[] )
|
|||||||
{ "midiDevice", midiDeviceTest },
|
{ "midiDevice", midiDeviceTest },
|
||||||
{ "textBuf", textBufTest },
|
{ "textBuf", textBufTest },
|
||||||
{ "audioBuf", audioBufTest },
|
{ "audioBuf", audioBufTest },
|
||||||
{ "audioPort",audioPortTest },
|
{ "audioDev",audioDevTest },
|
||||||
|
{ "audioDevAlsa", audioDevAlsaTest },
|
||||||
{ "stub", stubTest },
|
{ "stub", stubTest },
|
||||||
{ nullptr, nullptr }
|
{ nullptr, nullptr }
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user