Uncommented beaudio code
[pwlib.git] / src / ptlib / unix / macosaudio / MacMain.h
blobaf3fb67794d88f293320034bbd0de95eaa0c5845
1 // This embarassing hack exists purely because EMACS' electric-c indentation
2 // mode is too clever by half...
3 #ifdef __cplusplus
4 #define BEGIN_EXTERN_C extern "C" {
5 #define END_EXTERN_C };
6 #else
7 #define BEGIN_EXTERN_C
8 #define END_EXTERN_C
9 #endif
11 #include <CoreServices/CoreServices.h>
13 BEGIN_EXTERN_C
15 // In order to get along with the threading restrictions of Carbon
17 // "Carbon is not thread-safe for preemptive threads. You really need
18 // to use Carbon only from your main thread, and not from other
19 // pthreads. ..."
21 // this file implements a special main() function for the Mac OS, as well as
22 // implementing a command queue so that other threads may make Carbon toolbox
23 // calls safely (i.e. by asking the Mac main thread to do so).
25 // The job of the main thread is to handle events. The main thread also
26 // drives the sequence grabber (by calling SGIdle when appropriate) and the
27 // Sound Manager.
28 // The need to fiddle with these features is communicated via custom Carbon
29 // Events; the Carbon Event Manager is MPThread-safe (but not pthread
30 // safe), so I have made sure that PWLIB uses MPThreads so they can talk
31 // directly to the main thread.
33 // Oh yeah, and it calls the PProcess::Main() function, too. Wouldn't want
34 // to forget about that. That gets called on yet another MPThread, whose
35 // termination drives the shutdown of the main thread. I hope.
37 // Some of the ideas here come from the OTMP library. Some of them don't.
38 // Guess which set turns out to be more reliable...
40 // In detail:
41 // A thread wishing to have a Carbon action performed creates one of these
42 // structures on its stack and calls CarbonQueue; when CarbonQueue returns,
43 // the action has been performed.
45 // CarbonQueue initializes a semaphore in the carbonRequest object, places
46 // the object on an OTLIFO queue, and wakes up the main thread with
47 // a custom Carbon Event. Then it sleeps on the semaphore.
49 // The main thread's handler checks the queue for Carbon commands needing
50 // to be made in the context of the process main thread. When it has
51 // performed each call, it signals the semaphore and goes to the next
52 // request. A few commands cannot be completed synchronously by the main
53 // thread; they pass responsibility for the semaphore to a callback function.
55 enum carbonCommand_t
57 // audio recorder commands
58 kOpenRecorder = 'opre',
59 // arguments: const char *name, struct soundParams *
60 // returns: reference to new audio recorder OR error
61 kSetFormatRecorder = 'sfre',
62 // arguments: int reference, int soundParams *
63 // returns: error
64 kCloseRecorder = 'clre',
65 // arguments: int reference
66 // returns: error
67 kStartRecorder = 'stre',
68 // arguments: int reference, struct ringbuffer *
69 // returns: error
70 kStopRecorder = 'spre',
71 // arguments: int reference
72 // returns: error
73 // audio player commands
74 kOpenPlayer = 'oppl',
75 // arguments: name, soundParams *
76 // returns: reference to new audio player OR error
77 kSetFormatPlayer = 'sfpl',
78 // arguments: int reference, soundParams *
79 // returns: error
80 kClosePlayer = 'cppl',
81 // arguments: int reference
82 // returns: error
83 kPlaySample = 'smpl',
84 // arguments: int reference, char *buffer, int buflen
85 // returns: error
86 // note: returns when sound is enqueued, not finished.
87 kStopPlayer = 'stpl', // ssshhh!!!
88 // arguments: int reference
89 // returns: error
90 kIsPlaying = 'ispl',
91 // arguments: int reference
92 // returns: 0/1 if playing
93 kWaitForPlayCompletion = 'wapl',
94 // arguments: int reference
95 // returns: error
96 // blah blah blah
97 kNotACommand = 0
100 typedef
101 struct soundParams
103 unsigned short sp_channels;
104 unsigned short sp_samplesize;
105 unsigned long sp_samplerate;
106 #ifdef __cplusplus
107 soundParams(int c, int s, long r)
108 : sp_channels(c), sp_samplesize(s), sp_samplerate(r)
110 #endif
111 } soundParams;
113 typedef struct commandRequest commandRequest;
114 OSStatus CarbonQueue(commandRequest *request);
116 struct commandRequest
118 OTLink m_next; // it's a pointer
120 carbonCommand_t m_command;
121 unsigned long m_arg1, m_arg2, m_arg3, m_arg4;
122 unsigned long m_result; // if useful data is returned
123 OSStatus m_status; // error return
124 MPSemaphoreID m_done;
125 #ifdef __cplusplus
126 commandRequest(carbonCommand_t cmd,
127 unsigned long a1 = 0,
128 unsigned long a2 = 0,
129 unsigned long a3 = 0,
130 unsigned long a4 = 0)
131 : m_command(cmd), m_arg1(a1), m_arg2(a2), m_arg3(a3), m_arg4(a4),
132 m_result(0), m_status(0), m_done(0)
134 commandRequest()
135 : m_command(kNotACommand), m_arg1(0), m_arg2(0), m_arg3(0), m_arg4(0),
136 m_result(0), m_status(0), m_done(0)
138 // convenience constructors
139 commandRequest(carbonCommand_t cmd,
140 const unsigned char *a1,
141 const soundParams *a2)
142 : m_command(cmd),
143 m_arg1((unsigned long)a1), m_arg2((unsigned long)a2),
144 m_arg3(0), m_arg4(0),
145 m_result(0), m_status(0), m_done(0)
147 commandRequest(carbonCommand_t cmd,
148 int a1,
149 const soundParams *a2)
150 : m_command(cmd),
151 m_arg1(a1), m_arg2((unsigned long)a2), m_arg3(0), m_arg4(0),
152 m_result(0), m_status(0), m_done(0)
154 commandRequest(carbonCommand_t cmd,
155 int a1,
156 const void *a2)
157 : m_command(cmd),
158 m_arg1(a1), m_arg2((unsigned long)a2), m_arg3(0), m_arg4(0),
159 m_result(0), m_status(0), m_done(0)
161 commandRequest(carbonCommand_t cmd,
162 int a1,
163 const void *a2,
164 unsigned long a3)
165 : m_command(cmd),
166 m_arg1(a1), m_arg2((unsigned long)a2), m_arg3(a3), m_arg4(0),
167 m_result(0), m_status(0), m_done(0)
169 // and a convenience inline
170 OSStatus CarbonQueue()
172 return ::CarbonQueue(this);
174 #endif
177 END_EXTERN_C