PTLib
Version 2.12.9
|
Abstract class for a generalised sound channel, and an implementation of PSoundChannel for old code that is not plugin-aware. More...
#include <sound.h>
Public Member Functions | |
Play functions | |
virtual PBoolean | Write (const void *buf, PINDEX len) |
Low level write (or play) to the channel. More... | |
virtual PINDEX | GetLastWriteCount () const |
Get number of bytes written in last Write() operation. More... | |
virtual PBoolean | PlaySound (const PSound &sound, PBoolean wait=true) |
Play a sound to the open device. More... | |
virtual PBoolean | PlayFile (const PFilePath &file, PBoolean wait=true) |
Play a sound file to the open device. More... | |
virtual PBoolean | HasPlayCompleted () |
Indicate if the sound play begun with PlayBuffer() or PlayFile() has completed. More... | |
virtual PBoolean | WaitForPlayCompletion () |
Block calling thread until the sound play begun with PlaySound() or PlayFile() has completed. More... | |
Record functions | |
virtual PBoolean | Read (void *buf, PINDEX len) |
Low level read from the channel. More... | |
PINDEX | GetLastReadCount () const |
Return number of bytes read in last Read() call. More... | |
virtual PBoolean | RecordSound (PSound &sound) |
Record into the sound object all of the buffer's of sound data. More... | |
virtual PBoolean | RecordFile (const PFilePath &file) |
Record into the platform dependent sound file all of the buffer's of sound data. More... | |
virtual PBoolean | StartRecording () |
Start filling record buffers. More... | |
virtual PBoolean | IsRecordBufferFull () |
Determine if a record buffer has been filled, so that the next Read() call will not block. More... | |
virtual PBoolean | AreAllRecordBuffersFull () |
Determine if all of the record buffer allocated has been filled. More... | |
virtual PBoolean | WaitForRecordBufferFull () |
Block the thread until a record buffer has been filled, so that the next Read() call will not block. More... | |
virtual PBoolean | WaitForAllRecordBuffersFull () |
Block the thread until all of the record buffer allocated has been filled. More... | |
![]() | |
PBoolean | SetErrorValues (Errors errorCode, int osError, ErrorGroup group=LastGeneralError) |
Set error values to those specified. More... | |
virtual Comparison | Compare (const PObject &obj) const |
Get the relative rank of the two strings. More... | |
virtual PINDEX | HashFunction () const |
Calculate a hash value for use in sets and dictionaries. More... | |
P_INT_PTR | GetHandle () const |
Get the integer operating system handle for the channel. More... | |
virtual PChannel * | GetBaseReadChannel () const |
Get the base channel of channel indirection using PIndirectChannel. More... | |
virtual PChannel * | GetBaseWriteChannel () const |
Get the base channel of channel indirection using PIndirectChannel. More... | |
void | SetReadTimeout (const PTimeInterval &time) |
Set the timeout for read operations. More... | |
PTimeInterval | GetReadTimeout () const |
Get the timeout for read operations. More... | |
virtual int | ReadChar () |
Read a single 8 bit byte from the channel. More... | |
PBoolean | ReadBlock (void *buf, PINDEX len) |
Read len bytes into the buffer from the channel. More... | |
PString | ReadString (PINDEX len) |
Read len character into a string from the channel. More... | |
void | SetWriteTimeout (const PTimeInterval &time) |
Set the timeout for write operations to complete. More... | |
PTimeInterval | GetWriteTimeout () const |
Get the timeout for write operations to complete. More... | |
virtual PBoolean | Write (const void *buf, PINDEX len, const void *) |
Low level write to the channel with marker. More... | |
PBoolean | WriteChar (int c) |
Write a single character to the channel. More... | |
PBoolean | WriteString (const PString &str) |
Write a string to the channel. More... | |
~PChannel () | |
Close down the channel. More... | |
Errors | GetErrorCode (ErrorGroup group=NumErrorGroups) const |
Get normalised error code. More... | |
int | GetErrorNumber (ErrorGroup group=NumErrorGroups) const |
Get OS errro code. More... | |
virtual PString | GetErrorText (ErrorGroup group=NumErrorGroups) const |
Get error message description. More... | |
virtual bool | ReadAsync (AsyncContext &context) |
Begin an asynchronous read from channel. More... | |
virtual void | OnReadComplete (AsyncContext &context) |
User callback function for when a ReadAsync() call has completed or timed out. More... | |
virtual bool | WriteAsync (AsyncContext &context) |
Begin an asynchronous write from channel. More... | |
virtual void | OnWriteComplete (AsyncContext &context) |
User callback function for when a WriteAsync() call has completed or timed out. More... | |
virtual PBoolean | Shutdown (ShutdownValue option) |
Close one or both of the data streams associated with a channel. More... | |
virtual bool | SetLocalEcho (bool localEcho) |
Set local echo mode. More... | |
virtual bool | FlowControl (const void *flowData) |
Flow Control information Pass data to the channel for flowControl determination. More... | |
PBoolean | SetBufferSize (PINDEX newSize) |
Set the iostream buffer size for reads and writes. More... | |
PBoolean | SendCommandString (const PString &command) |
Send a command meta-string. More... | |
void | AbortCommandString () |
Abort a command string that is in progress. More... | |
![]() | |
unsigned | GetTraceContextIdentifier () const |
Get PTRACE context identifier. More... | |
void | SetTraceContextIdentifier (unsigned id) |
void | GetTraceContextIdentifier (PObject &obj) |
void | GetTraceContextIdentifier (PObject *obj) |
void | SetTraceContextIdentifier (const PObject &obj) |
void | SetTraceContextIdentifier (const PObject *obj) |
virtual | ~PObject () |
virtual PObject * | Clone () const |
Create a copy of the class on the heap. More... | |
template<class CLS > | |
CLS * | CloneAs () const |
As for Clone() but converts to specified type. More... | |
virtual const char * | GetClass (unsigned ancestor=0) const |
Get the current dynamic type of the object instance. More... | |
PBoolean | IsClass (const char *cls) const |
virtual PBoolean | InternalIsDescendant (const char *clsName) const |
Determine if the dynamic type of the current instance is a descendent of the specified class. More... | |
__inline const PObject * | PTraceObjectInstance () const |
virtual Comparison | CompareObjectMemoryDirect (const PObject &obj) const |
Determine the byte wise comparison of two objects. More... | |
bool | operator== (const PObject &obj) const |
Compare the two objects. More... | |
bool | operator!= (const PObject &obj) const |
Compare the two objects. More... | |
bool | operator< (const PObject &obj) const |
Compare the two objects. More... | |
bool | operator> (const PObject &obj) const |
Compare the two objects. More... | |
bool | operator<= (const PObject &obj) const |
Compare the two objects. More... | |
bool | operator>= (const PObject &obj) const |
Compare the two objects. More... | |
virtual void | PrintOn (ostream &strm) const |
Output the contents of the object to the stream. More... | |
virtual void | ReadFrom (istream &strm) |
Input the contents of the object from the stream. More... | |
Protected Attributes | |
PSoundChannel * | m_baseChannel |
PReadWriteMutex | m_baseMutex |
Directions | activeDirection |
This is the direction that this sound channel is opened for use in. More... | |
![]() | |
P_INT_PTR | os_handle |
The operating system file handle return by standard open() function. More... | |
Errors | lastErrorCode [NumErrorGroups+1] |
The platform independant error code. More... | |
int | lastErrorNumber [NumErrorGroups+1] |
The operating system error number (eg as returned by errno). More... | |
PINDEX | lastReadCount |
Number of byte last read by the Read() function. More... | |
PINDEX | lastWriteCount |
Number of byte last written by the Write() function. More... | |
PTimeInterval | readTimeout |
Timeout for read operations. More... | |
PTimeInterval | writeTimeout |
Timeout for write operations. More... | |
PString | channelName |
Name of channel. More... | |
PMutex | px_threadMutex |
PXBlockType | px_lastBlockType |
PThread * | px_readThread |
PThread * | px_writeThread |
PMutex | px_writeMutex |
PThread * | px_selectThread [3] |
PMutex | px_selectMutex [3] |
![]() | |
unsigned | m_traceContextIdentifier |
Construction | |
enum | Directions { Closed = -1, Recorder, Player } |
PSoundChannel () | |
Create a sound channel. More... | |
PSoundChannel (const PString &device, Directions dir, unsigned numChannels=1, unsigned sampleRate=8000, unsigned bitsPerSample=16) | |
Create a sound channel. More... | |
virtual | ~PSoundChannel () |
Open functions | |
virtual PBoolean | Open (const PString &device, Directions dir, unsigned numChannels=1, unsigned sampleRate=8000, unsigned bitsPerSample=16) |
Open the specified device for playing or recording. More... | |
virtual PBoolean | IsOpen () const |
Test if this instance of PSoundChannel is open. More... | |
virtual PBoolean | Close () |
Close the channel, shutting down the link to the data source. More... | |
virtual P_INT_PTR | GetHandle () const |
Get the OS specific handle for the PSoundChannel. More... | |
virtual PString | GetName () const |
Get the name of the open channel. More... | |
Directions | GetDirection () const |
Get the direction of the channel. More... | |
virtual const char * | GetDirectionText () const |
virtual PBoolean | Abort () |
Abort the background playing/recording of the sound channel. More... | |
static PStringArray | GetDriverNames (PPluginManager *pluginMgr=NULL) |
Get the list of available sound drivers (plug-ins) More... | |
static PStringArray | GetDriversDeviceNames (const PString &driverName, Directions direction, PPluginManager *pluginMgr=NULL) |
Get sound devices that correspond to the specified driver name. More... | |
static PStringArray | GetDeviceNames (const PString &driverName, Directions direction, PPluginManager *pluginMgr=NULL) |
static PSoundChannel * | CreateChannel (const PString &driverName, PPluginManager *pluginMgr=NULL) |
Create the sound channel that corresponds to the specified driver name. More... | |
static PSoundChannel * | CreateChannelByName (const PString &deviceName, Directions direction, PPluginManager *pluginMgr=NULL) |
static PSoundChannel * | CreateOpenedChannel (const PString &driverName, const PString &deviceName, Directions direction, unsigned numChannels=1, unsigned sampleRate=8000, unsigned bitsPerSample=16, PPluginManager *pluginMgr=NULL) |
Create an opened sound channel that corresponds to the specified names. More... | |
static PString | GetDefaultDevice (Directions dir) |
Get the name for the default sound devices/driver that is on this platform. More... | |
static PStringArray | GetDeviceNames (Directions direction, PPluginManager *pluginMgr=NULL) |
Get the list of all devices name for the default sound devices/driver that is on this platform. More... | |
static const char * | GetDirectionText (Directions dir) |
Get text representing the direction of the channel. More... | |
Channel set up functions | |
enum | { MaxVolume = 100 } |
virtual PBoolean | SetFormat (unsigned numChannels=1, unsigned sampleRate=8000, unsigned bitsPerSample=16) |
Set the format for play/record. More... | |
virtual unsigned | GetChannels () const |
Get the number of channels (mono/stereo) in the sound. More... | |
virtual unsigned | GetSampleRate () const |
Get the sample rate in samples per second. More... | |
virtual unsigned | GetSampleSize () const |
Get the sample size in bits per sample. More... | |
virtual PBoolean | SetBuffers (PINDEX size, PINDEX count=2) |
Set the internal buffers for the sound channel I/O. More... | |
virtual PBoolean | GetBuffers (PINDEX &size, PINDEX &count) |
Get the internal buffers for the sound channel I/O. More... | |
virtual PBoolean | SetVolume (unsigned volume) |
Set the volume of the play/read process. More... | |
virtual PBoolean | GetVolume (unsigned &volume) |
Get the volume of the play/read process. More... | |
virtual bool | SetMute (bool mute) |
Set the mute state of the play/read process. More... | |
virtual bool | GetMute (bool &mute) |
Get the mute state of the play/read process. More... | |
Additional Inherited Members | |
![]() | |
enum | PXBlockType { PXReadBlock, PXWriteBlock, PXAcceptBlock, PXConnectBlock } |
enum | Errors { NoError, NotFound, FileExists, DiskFull, AccessDenied, DeviceInUse, BadParameter, NoMemory, NotOpen, Timeout, Interrupted, BufferTooSmall, Miscellaneous, ProtocolFailure, Unavailable, NumNormalisedErrors } |
Normalised error codes. More... | |
enum | ErrorGroup { LastReadError, LastWriteError, LastGeneralError, NumErrorGroups } |
Error groups. More... | |
typedef PNotifierTemplate < PChannel::AsyncContext & > | AsyncNotifier |
enum | ShutdownValue { ShutdownRead = 0, ShutdownWrite = 1, ShutdownReadAndWrite = 2 } |
![]() | |
static PString | GetErrorText (Errors lastError, int osError=0) |
Get error message description. More... | |
static PBoolean | ConvertOSError (P_INT_PTR libcReturnValue, Errors &lastError, int &osError) |
Convert an operating system error into platform independent error. More... | |
![]() | |
static const char * | Class () |
Get the name of the class as a C string. More... | |
static __inline const PObject * | PTraceObjectInstance (const char *) |
static __inline const PObject * | PTraceObjectInstance (const PObject *obj) |
static Comparison | InternalCompareObjectMemoryDirect (const PObject *obj1, const PObject *obj2, PINDEX size) |
Internal function caled from CompareObjectMemoryDirect() More... | |
![]() | |
PChannel (const PChannel &) | |
PChannel & | operator= (const PChannel &) |
virtual PBoolean | ConvertOSError (P_INT_PTR libcReturnValue, ErrorGroup group=LastGeneralError) |
Convert an operating system error into platform independent error. More... | |
int | ReadCharWithTimeout (PTimeInterval &timeout) |
Read a character with specified timeout. More... | |
PBoolean | ReceiveCommandString (int nextChar, const PString &reply, PINDEX &pos, PINDEX start) |
PBoolean | PXSetIOBlock (PXBlockType type, const PTimeInterval &timeout) |
P_INT_PTR | GetOSHandleAsInt () const |
int | PXClose () |
PChannel () | |
Create the channel. More... | |
![]() |
Abstract class for a generalised sound channel, and an implementation of PSoundChannel for old code that is not plugin-aware.
When instantiated, it selects the first plugin of the base class "PSoundChannel"
As an abstract class, this represents a sound channel. Drivers for real, platform dependent sound hardware will be ancestors of this class and can be found in the plugins section of PTLib.
A sound channel is either playing or recording. If simultaneous playing and recording is desired, two instances of PSoundChannel must be created. It is an error for the same thread to attempt to both read and write audio data to once instance of a PSoundChannel class.
PSoundChannel instances are designed to be reentrant. The actual usage model employed is left to the developer. One model could be where one thread is responsible for construction, setup, opening and read/write operations. After creating and eventually opening the channel this thread is responsible for handling read/writes fast enough to avoid gaps in the generated audio stream.
Remaining operations may beinvoked from other threads. This includes Close() and actually gathering the necessary data to be sent to the device.
Besides the basic I/O task, the Read()/Write(() functions have well defined timing characteristics. When a PSoundChannel instance is used from Opal, the read/write operations are designed to also act as timers so as to nicely space the generated network packets of audio/ sound packets to the speaker.
Read and Writes of audio data to a PSoundChannel are blocking. The length of time required to read/write a block of audio from/to a PSoundChannel instance is equal to the time required for that block of audio to record/play. So for a sound rate of 8khz, 240 samples, it is going to take 30ms to do a read/write.
Since the Read()/Write(() functions have well defined timing characteristics; they are designed to also act as timers in a loop involving data transfers to/from the codecs.
The sound is buffered and the size and number of buffers should be set before playing/recording. Each call to Write() will use one buffer, so care needs to be taken not to use a large number of small writes but tailor the buffers to the size of each write you make.
Similarly for reading, an entire buffer must be read before any of it is available to a Read() call. Note that once a buffer is filled you can read it a byte at a time if desired, but as soon as all the data in the buffer is used, the next read will wait until the entire next buffer is read from the hardware. So again, tailor the number and size of buffers to the application. To avoid being blocked until the buffer fills, you can use the StartRecording() function to initiate the buffer filling, and the IsRecordingBufferFull() function to determine when the Read() function will no longer block.
Note that this sound channel is implicitly a linear PCM channel. No data conversion is performed on data to/from the channel.
PSoundChannel::PSoundChannel | ( | ) |
Create a sound channel.
PSoundChannel::PSoundChannel | ( | const PString & | device, |
Directions | dir, | ||
unsigned | numChannels = 1 , |
||
unsigned | sampleRate = 8000 , |
||
unsigned | bitsPerSample = 16 |
||
) |
Create a sound channel.
Create a reference to the sound drivers for the platform.
device | Name of sound driver/device |
dir | Sound I/O direction |
numChannels | Number of channels eg mono/stereo |
sampleRate | Samples per second |
bitsPerSample | Number of bits per sample |
|
virtual |
|
virtual |
Abort the background playing/recording of the sound channel.
There will be a logic assertion if you attempt to Abort a sound channel operation, when the device is currently closed.
|
virtual |
Determine if all of the record buffer allocated has been filled.
There is an implicit Abort() of the recording if this occurs and recording is stopped. The channel may need to be closed and opened again to start a new recording.
|
virtual |
Close the channel, shutting down the link to the data source.
Reimplemented from PChannel.
|
static |
Create the sound channel that corresponds to the specified driver name.
driverName | Name of driver |
pluginMgr | Plug in manager, use default if NULL |
|
static |
deviceName | Name of device |
direction | Direction for device (record or play) |
pluginMgr | Plug in manager, use default if NULL |
|
static |
Create an opened sound channel that corresponds to the specified names.
If the driverName parameter is an empty string or "*" then CreateChannelByName is used with the deviceName parameter which is assumed to be a value returned from GetAllDeviceNames().
driverName | Name of driver |
deviceName | Name of device |
direction | Direction for device (record or play) |
numChannels | Number of channels 1=mon, 2=stereo |
sampleRate | Sample rate |
bitsPerSample | Bits per sample |
pluginMgr | Plug in manager, use default if NULL |
|
virtual |
Get the internal buffers for the sound channel I/O.
|
virtual |
Get the number of channels (mono/stereo) in the sound.
|
static |
Get the name for the default sound devices/driver that is on this platform.
Note that a named device may not necessarily do both playing and recording so the string returned with the dir
parameter in each value is not necessarily the same.
|
inlinestatic |
References GetDriversDeviceNames().
|
static |
Get the list of all devices name for the default sound devices/driver that is on this platform.
Note that a named device may not necessarily do both playing and recording so the arrays returned with the dir
parameter in each value is not necessarily the same.
This will return a list of unique device names across all of the available drivers. If two drivers have identical names for devices, then the string returned will be of the form driver+'\t'+device.
direction | Direction for device (record or play) |
pluginMgr | Plug in manager, use default if NULL |
|
inline |
Get the direction of the channel.
References activeDirection.
|
static |
Get text representing the direction of the channel.
|
inlinevirtual |
References activeDirection.
|
static |
Get the list of available sound drivers (plug-ins)
pluginMgr | Plug in manager, use default if NULL |
|
static |
Get sound devices that correspond to the specified driver name.
If driverName is an empty string or the value "*" then GetAllDeviceNames() is used.
driverName | Name of driver |
direction | Direction for device (record or play) |
pluginMgr | Plug in manager, use default if NULL |
Referenced by GetDeviceNames().
|
virtual |
Get the OS specific handle for the PSoundChannel.
|
virtual |
|
virtual |
|
virtual |
Get the mute state of the play/read process.
mute | Variable to receive mute state. |
|
virtual |
Get the name of the open channel.
Reimplemented from PChannel.
|
virtual |
Get the sample rate in samples per second.
|
virtual |
Get the sample size in bits per sample.
|
virtual |
Get the volume of the play/read process.
The volume range is 0 == muted, 100 == LOUDEST. The volume is a logarithmic scale mapped from the lowest gain possible on the device to the highest gain.
volume | Variable to receive volume level. |
|
virtual |
Indicate if the sound play begun with PlayBuffer() or PlayFile() has completed.
|
virtual |
Test if this instance of PSoundChannel is open.
Reimplemented from PChannel.
|
virtual |
Determine if a record buffer has been filled, so that the next Read() call will not block.
Provided that the amount of data read is less than the buffer size.
|
virtual |
Open the specified device for playing or recording.
The device name is platform specific and is as returned in the GetDevices() function.
device | Name of sound driver/device |
dir | Sound I/O direction |
numChannels | Number of channels eg mono/stereo |
sampleRate | Samples per second |
bitsPerSample | Number of bits per sample |
Play a sound file to the open device.
If the wait
parameter is true then the function does not return until the file has been played. If false then the sound play is begun asynchronously and the function returns immediately.
Note if the driver is closed of the object destroyed then the sound play is aborted.
Also note that not all possible sounds and sound files are playable by this library. No format conversions between sound object and driver are performed.
file | Sound file to play. |
wait | Flag to play sound synchronously. |
Play a sound to the open device.
If the wait
parameter is true then the function does not return until the file has been played. If false then the sound play is begun asynchronously and the function returns immediately.
Note: if the driver is closed while playing the sound, the play operation stops immediately.
Also note that not all possible sounds and sound files are playable by this library. No format conversions between sound object and driver are performed.
sound | Sound to play. |
wait | Flag to play sound synchronously. |
|
virtual |
Low level read from the channel.
This function may block until the requested number of characters were read or the read timeout was reached. The GetLastReadCount() function returns the actual number of bytes read.
It will generate a logical assertion if you attempt to read from a PSoundChannel that is setup for playing.
The GetErrorCode() function should be consulted after Read() returns false to determine what caused the failure.
len | Nr of bytes to endeaveour to read from the sound device. If len equals the buffer size set by SetBuffers() it will block for (1000*len)/(samplesize*samplerate) ms. Typically, the sample size is 2 bytes. If len == 0, this will return immediately, where the return value is equal to the value of IsOpen(). |
buf | is a pointer to the empty data area, which will contain the data collected from the sound device. It is an error for this pointer to be NULL. A logical assert will be generated when buf is NULL. |
buf | Pointer to a block of memory to receive the read bytes. |
len | Maximum number of bytes to read into the buffer. |
Reimplemented from PChannel.
Record into the platform dependent sound file all of the buffer's of sound data.
Use the SetBuffers() function to determine how long the recording will be made.
Note that this function will block until all of the data is buffered. If you wish to do this asynchronously, use StartRecording() and AreAllrecordBuffersFull() to determine when you can call RecordSound() without blocking.
file | Sound file recorded |
Record into the sound object all of the buffer's of sound data.
Use the SetBuffers() function to determine how long the recording will be made.
For the Win32 platform, the most efficient way to record a PSound is to use the SetBuffers() function to set a single buffer of the desired size and then do the recording. For Linux OSS this can cause problems as the buffers are rounded up to a power of two, so to gain more accuracy you need a number of smaller buffers.
Note that this function will block until all of the data is buffered. If you wish to do this asynchronously, use StartRecording() and AreAllrecordBuffersFull() to determine when you can call RecordSound() without blocking.
sound | Sound recorded |
|
virtual |
Set the internal buffers for the sound channel I/O.
Note that with Linux OSS, the size is always rounded up to the nearest power of two, so 20000 => 32768.
size | Size of each buffer |
count | Number of buffers |
|
virtual |
Set the format for play/record.
Note that linear PCM data is the only one supported at this time.
Note that if the PlayFile() function is used, this may be overridden by information in the file being played.
numChannels | Number of channels eg mono/stereo |
sampleRate | Samples per second |
bitsPerSample | Number of bits per sample |
|
virtual |
Set the mute state of the play/read process.
mute | New mute state |
|
virtual |
Set the volume of the play/read process.
The volume range is 0 == muted, 100 == LOUDEST. The volume is a logarithmic scale mapped from the lowest gain possible on the device to the highest gain.
volume | New volume level |
|
virtual |
Start filling record buffers.
The first call to Read() will also initiate the recording.
|
virtual |
Block the thread until all of the record buffer allocated has been filled.
There is an implicit Abort() of the recording if this occurs and recording is stopped. The channel may need to be closed and opened again to start a new recording.
|
virtual |
Block calling thread until the sound play begun with PlaySound() or PlayFile() has completed.
|
virtual |
Block the thread until a record buffer has been filled, so that the next Read() call will not block.
Provided that the amount of data read is less than the buffer size.
|
virtual |
Low level write (or play) to the channel.
It will generate a logical assertion if you attempt write to a channel set up for recording.
buf | is a pointer to the data to be written to the channel. It is an error for this pointer to be NULL. A logical assert will be generated when buf is NULL. |
len | Nr of bytes to send. If len equals the buffer size set by SetBuffers() it will block for (1000*len)/(samplesize*samplerate) ms. Typically, the sample size is 2 bytes. If len == 0, this will return immediately, where the return value is equal to the value of IsOpen(). |
Reimplemented from PChannel.
|
protected |
This is the direction that this sound channel is opened for use in.
Should the user attempt to used this opened class instance in a direction opposite to that specified in activeDirection, an assert happens.
Referenced by GetDirection(), and GetDirectionText().
|
protected |
|
protected |