~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/third_party/portaudio/src/hostapi/asio/iasiothiscallresolver.cpp

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
        IASIOThiscallResolver.cpp see the comments in iasiothiscallresolver.h for
3
 
    the top level description - this comment describes the technical details of
4
 
    the implementation.
5
 
 
6
 
    The latest version of this file is available from:
7
 
    http://www.audiomulch.com/~rossb/code/calliasio
8
 
 
9
 
    please email comments to Ross Bencina <rossb@audiomulch.com>
10
 
 
11
 
    BACKGROUND
12
 
 
13
 
    The IASIO interface declared in the Steinberg ASIO 2 SDK declares
14
 
    functions with no explicit calling convention. This causes MSVC++ to default
15
 
    to using the thiscall convention, which is a proprietary convention not
16
 
    implemented by some non-microsoft compilers - notably borland BCC,
17
 
    C++Builder, and gcc. MSVC++ is the defacto standard compiler used by
18
 
    Steinberg. As a result of this situation, the ASIO sdk will compile with
19
 
    any compiler, however attempting to execute the compiled code will cause a
20
 
    crash due to different default calling conventions on non-Microsoft
21
 
    compilers.
22
 
 
23
 
    IASIOThiscallResolver solves the problem by providing an adapter class that
24
 
    delegates to the IASIO interface using the correct calling convention
25
 
    (thiscall). Due to the lack of support for thiscall in the Borland and GCC
26
 
    compilers, the calls have been implemented in assembly language.
27
 
 
28
 
    A number of macros are defined for thiscall function calls with different
29
 
    numbers of parameters, with and without return values - it may be possible
30
 
    to modify the format of these macros to make them work with other inline
31
 
    assemblers.
32
 
 
33
 
 
34
 
    THISCALL DEFINITION
35
 
 
36
 
    A number of definitions of the thiscall calling convention are floating
37
 
    around the internet. The following definition has been validated against
38
 
    output from the MSVC++ compiler:
39
 
 
40
 
    For non-vararg functions, thiscall works as follows: the object (this)
41
 
    pointer is passed in ECX. All arguments are passed on the stack in
42
 
    right to left order. The return value is placed in EAX. The callee
43
 
    clears the passed arguments from the stack.
44
 
 
45
 
 
46
 
    FINDING FUNCTION POINTERS FROM AN IASIO POINTER
47
 
 
48
 
    The first field of a COM object is a pointer to its vtble. Thus a pointer
49
 
    to an object implementing the IASIO interface also points to a pointer to
50
 
    that object's vtbl. The vtble is a table of function pointers for all of
51
 
    the virtual functions exposed by the implemented interfaces.
52
 
 
53
 
    If we consider a variable declared as a pointer to IASO:
54
 
 
55
 
    IASIO *theAsioDriver
56
 
 
57
 
    theAsioDriver points to:
58
 
 
59
 
    object implementing IASIO
60
 
    {
61
 
        IASIOvtbl *vtbl
62
 
        other data
63
 
    }
64
 
 
65
 
    in other words, theAsioDriver points to a pointer to an IASIOvtbl
66
 
 
67
 
    vtbl points to a table of function pointers:
68
 
 
69
 
    IASIOvtbl ( interface IASIO : public IUnknown )
70
 
    {
71
 
    (IUnknown functions)
72
 
    0   virtual HRESULT STDMETHODCALLTYPE (*QueryInterface)(REFIID riid, void **ppv) = 0;
73
 
    4   virtual ULONG STDMETHODCALLTYPE (*AddRef)() = 0;
74
 
    8   virtual ULONG STDMETHODCALLTYPE (*Release)() = 0;
75
 
 
76
 
    (IASIO functions)
77
 
    12  virtual ASIOBool (*init)(void *sysHandle) = 0;
78
 
    16  virtual void (*getDriverName)(char *name) = 0;
79
 
    20  virtual long (*getDriverVersion)() = 0;
80
 
    24  virtual void (*getErrorMessage)(char *string) = 0;
81
 
    28  virtual ASIOError (*start)() = 0;
82
 
    32  virtual ASIOError (*stop)() = 0;
83
 
    36  virtual ASIOError (*getChannels)(long *numInputChannels, long *numOutputChannels) = 0;
84
 
    40  virtual ASIOError (*getLatencies)(long *inputLatency, long *outputLatency) = 0;
85
 
    44  virtual ASIOError (*getBufferSize)(long *minSize, long *maxSize,
86
 
            long *preferredSize, long *granularity) = 0;
87
 
    48  virtual ASIOError (*canSampleRate)(ASIOSampleRate sampleRate) = 0;
88
 
    52  virtual ASIOError (*getSampleRate)(ASIOSampleRate *sampleRate) = 0;
89
 
    56  virtual ASIOError (*setSampleRate)(ASIOSampleRate sampleRate) = 0;
90
 
    60  virtual ASIOError (*getClockSources)(ASIOClockSource *clocks, long *numSources) = 0;
91
 
    64  virtual ASIOError (*setClockSource)(long reference) = 0;
92
 
    68  virtual ASIOError (*getSamplePosition)(ASIOSamples *sPos, ASIOTimeStamp *tStamp) = 0;
93
 
    72  virtual ASIOError (*getChannelInfo)(ASIOChannelInfo *info) = 0;
94
 
    76  virtual ASIOError (*createBuffers)(ASIOBufferInfo *bufferInfos, long numChannels,
95
 
            long bufferSize, ASIOCallbacks *callbacks) = 0;
96
 
    80  virtual ASIOError (*disposeBuffers)() = 0;
97
 
    84  virtual ASIOError (*controlPanel)() = 0;
98
 
    88  virtual ASIOError (*future)(long selector,void *opt) = 0;
99
 
    92  virtual ASIOError (*outputReady)() = 0;
100
 
    };
101
 
 
102
 
    The numbers in the left column show the byte offset of each function ptr
103
 
    from the beginning of the vtbl. These numbers are used in the code below
104
 
    to select different functions.
105
 
 
106
 
    In order to find the address of a particular function, theAsioDriver
107
 
    must first be dereferenced to find the value of the vtbl pointer:
108
 
 
109
 
    mov     eax, theAsioDriver
110
 
    mov     edx, [theAsioDriver]  // edx now points to vtbl[0]
111
 
 
112
 
    Then an offset must be added to the vtbl pointer to select a
113
 
    particular function, for example vtbl+44 points to the slot containing
114
 
    a pointer to the getBufferSize function.
115
 
 
116
 
    Finally vtbl+x must be dereferenced to obtain the value of the function
117
 
    pointer stored in that address:
118
 
 
119
 
    call    [edx+44]    // call the function pointed to by
120
 
                        // the value in the getBufferSize field of the vtbl
121
 
 
122
 
 
123
 
    SEE ALSO
124
 
 
125
 
    Martin Fay's OpenASIO DLL at http://www.martinfay.com solves the same
126
 
    problem by providing a new COM interface which wraps IASIO with an
127
 
    interface that uses portable calling conventions. OpenASIO must be compiled
128
 
    with MSVC, and requires that you ship the OpenASIO DLL with your
129
 
    application.
130
 
 
131
 
 
132
 
    ACKNOWLEDGEMENTS
133
 
 
134
 
    Ross Bencina: worked out the thiscall details above, wrote the original
135
 
    Borland asm macros, and a patch for asio.cpp (which is no longer needed).
136
 
    Thanks to Martin Fay for introducing me to the issues discussed here,
137
 
    and to Rene G. Ceballos for assisting with asm dumps from MSVC++.
138
 
 
139
 
    Antti Silvast: converted the original calliasio to work with gcc and NASM
140
 
    by implementing the asm code in a separate file.
141
 
 
142
 
        Fraser Adams: modified the original calliasio containing the Borland inline
143
 
    asm to add inline asm for gcc i.e. Intel syntax for Borland and AT&T syntax
144
 
    for gcc. This seems a neater approach for gcc than to have a separate .asm
145
 
    file and it means that we only need one version of the thiscall patch.
146
 
 
147
 
    Fraser Adams: rewrote the original calliasio patch in the form of the
148
 
    IASIOThiscallResolver class in order to avoid modifications to files from
149
 
    the Steinberg SDK, which may have had potential licence issues.
150
 
 
151
 
    Andrew Baldwin: contributed fixes for compatibility problems with more
152
 
    recent versions of the gcc assembler.
153
 
*/
154
 
 
155
 
 
156
 
// We only need IASIOThiscallResolver at all if we are on Win32. For other
157
 
// platforms we simply bypass the IASIOThiscallResolver definition to allow us
158
 
// to be safely #include'd whatever the platform to keep client code portable
159
 
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
160
 
 
161
 
 
162
 
// If microsoft compiler we can call IASIO directly so IASIOThiscallResolver
163
 
// is not used.
164
 
#if !defined(_MSC_VER)
165
 
 
166
 
 
167
 
#include <new>
168
 
#include <assert.h>
169
 
 
170
 
// We have a mechanism in iasiothiscallresolver.h to ensure that asio.h is
171
 
// #include'd before it in client code, we do NOT want to do this test here.
172
 
#define iasiothiscallresolver_sourcefile 1
173
 
#include "iasiothiscallresolver.h"
174
 
#undef iasiothiscallresolver_sourcefile
175
 
 
176
 
// iasiothiscallresolver.h redefines ASIOInit for clients, but we don't want
177
 
// this macro defined in this translation unit.
178
 
#undef ASIOInit
179
 
 
180
 
 
181
 
// theAsioDriver is a global pointer to the current IASIO instance which the
182
 
// ASIO SDK uses to perform all actions on the IASIO interface. We substitute
183
 
// our own forwarding interface into this pointer.
184
 
extern IASIO* theAsioDriver;
185
 
 
186
 
 
187
 
// The following macros define the inline assembler for BORLAND first then gcc
188
 
 
189
 
#if defined(__BCPLUSPLUS__) || defined(__BORLANDC__)
190
 
 
191
 
 
192
 
#define CALL_THISCALL_0( resultName, thisPtr, funcOffset )\
193
 
    void *this_ = (thisPtr);                                                \
194
 
    __asm {                                                                 \
195
 
        mov     ecx, this_            ;                                     \
196
 
        mov     eax, [ecx]            ;                                     \
197
 
        call    [eax+funcOffset]      ;                                     \
198
 
        mov     resultName, eax       ;                                     \
199
 
    }
200
 
 
201
 
 
202
 
#define CALL_VOID_THISCALL_1( thisPtr, funcOffset, param1 )\
203
 
    void *this_ = (thisPtr);                                                \
204
 
    __asm {                                                                 \
205
 
        mov     eax, param1           ;                                     \
206
 
        push    eax                   ;                                     \
207
 
        mov     ecx, this_            ;                                     \
208
 
        mov     eax, [ecx]            ;                                     \
209
 
        call    [eax+funcOffset]      ;                                     \
210
 
    }
211
 
 
212
 
 
213
 
#define CALL_THISCALL_1( resultName, thisPtr, funcOffset, param1 )\
214
 
    void *this_ = (thisPtr);                                                \
215
 
    __asm {                                                                 \
216
 
        mov     eax, param1           ;                                     \
217
 
        push    eax                   ;                                     \
218
 
        mov     ecx, this_            ;                                     \
219
 
        mov     eax, [ecx]            ;                                     \
220
 
        call    [eax+funcOffset]      ;                                     \
221
 
        mov     resultName, eax       ;                                     \
222
 
    }
223
 
 
224
 
 
225
 
#define CALL_THISCALL_1_DOUBLE( resultName, thisPtr, funcOffset, param1 )\
226
 
    void *this_ = (thisPtr);                                                \
227
 
    void *doubleParamPtr_ (&param1);                                        \
228
 
    __asm {                                                                 \
229
 
        mov     eax, doubleParamPtr_  ;                                     \
230
 
        push    [eax+4]               ;                                     \
231
 
        push    [eax]                 ;                                     \
232
 
        mov     ecx, this_            ;                                     \
233
 
        mov     eax, [ecx]            ;                                     \
234
 
        call    [eax+funcOffset]      ;                                     \
235
 
        mov     resultName, eax       ;                                     \
236
 
    }
237
 
 
238
 
 
239
 
#define CALL_THISCALL_2( resultName, thisPtr, funcOffset, param1, param2 )\
240
 
    void *this_ = (thisPtr);                                                \
241
 
    __asm {                                                                 \
242
 
        mov     eax, param2           ;                                     \
243
 
        push    eax                   ;                                     \
244
 
        mov     eax, param1           ;                                     \
245
 
        push    eax                   ;                                     \
246
 
        mov     ecx, this_            ;                                     \
247
 
        mov     eax, [ecx]            ;                                     \
248
 
        call    [eax+funcOffset]      ;                                     \
249
 
        mov     resultName, eax       ;                                     \
250
 
    }
251
 
 
252
 
 
253
 
#define CALL_THISCALL_4( resultName, thisPtr, funcOffset, param1, param2, param3, param4 )\
254
 
    void *this_ = (thisPtr);                                                \
255
 
    __asm {                                                                 \
256
 
        mov     eax, param4           ;                                     \
257
 
        push    eax                   ;                                     \
258
 
        mov     eax, param3           ;                                     \
259
 
        push    eax                   ;                                     \
260
 
        mov     eax, param2           ;                                     \
261
 
        push    eax                   ;                                     \
262
 
        mov     eax, param1           ;                                     \
263
 
        push    eax                   ;                                     \
264
 
        mov     ecx, this_            ;                                     \
265
 
        mov     eax, [ecx]            ;                                     \
266
 
        call    [eax+funcOffset]      ;                                     \
267
 
        mov     resultName, eax       ;                                     \
268
 
    }
269
 
 
270
 
 
271
 
#elif defined(__GNUC__)
272
 
 
273
 
 
274
 
#define CALL_THISCALL_0( resultName, thisPtr, funcOffset )                  \
275
 
    __asm__ __volatile__ ("movl (%1), %%edx\n\t"                            \
276
 
                          "call *"#funcOffset"(%%edx)\n\t"                  \
277
 
                          :"=a"(resultName) /* Output Operands */           \
278
 
                          :"c"(thisPtr)     /* Input Operands */            \
279
 
                         );                                                 \
280
 
 
281
 
 
282
 
#define CALL_VOID_THISCALL_1( thisPtr, funcOffset, param1 )                 \
283
 
    __asm__ __volatile__ ("pushl %0\n\t"                                    \
284
 
                          "movl (%1), %%edx\n\t"                            \
285
 
                          "call *"#funcOffset"(%%edx)\n\t"                  \
286
 
                          :                 /* Output Operands */           \
287
 
                          :"r"(param1),     /* Input Operands */            \
288
 
                           "c"(thisPtr)                                     \
289
 
                         );                                                 \
290
 
 
291
 
 
292
 
#define CALL_THISCALL_1( resultName, thisPtr, funcOffset, param1 )          \
293
 
    __asm__ __volatile__ ("pushl %1\n\t"                                    \
294
 
                          "movl (%2), %%edx\n\t"                            \
295
 
                          "call *"#funcOffset"(%%edx)\n\t"                  \
296
 
                          :"=a"(resultName) /* Output Operands */           \
297
 
                          :"r"(param1),     /* Input Operands */            \
298
 
                           "c"(thisPtr)                                     \
299
 
                          );                                                \
300
 
 
301
 
 
302
 
#define CALL_THISCALL_1_DOUBLE( resultName, thisPtr, funcOffset, param1 )   \
303
 
    __asm__ __volatile__ ("pushl 4(%1)\n\t"                                 \
304
 
                          "pushl (%1)\n\t"                                  \
305
 
                          "movl (%2), %%edx\n\t"                            \
306
 
                          "call *"#funcOffset"(%%edx);\n\t"                 \
307
 
                          :"=a"(resultName) /* Output Operands */           \
308
 
                          :"a"(&param1),    /* Input Operands */            \
309
 
                           /* Note: Using "r" above instead of "a" fails */ \
310
 
                           /* when using GCC 3.3.3, and maybe later versions*/\
311
 
                           "c"(thisPtr)                                     \
312
 
                          );                                                \
313
 
 
314
 
 
315
 
#define CALL_THISCALL_2( resultName, thisPtr, funcOffset, param1, param2 )  \
316
 
    __asm__ __volatile__ ("pushl %1\n\t"                                    \
317
 
                          "pushl %2\n\t"                                    \
318
 
                          "movl (%3), %%edx\n\t"                            \
319
 
                          "call *"#funcOffset"(%%edx)\n\t"                  \
320
 
                          :"=a"(resultName) /* Output Operands */           \
321
 
                          :"r"(param2),     /* Input Operands */            \
322
 
                           "r"(param1),                                     \
323
 
                           "c"(thisPtr)                                     \
324
 
                          );                                                \
325
 
 
326
 
 
327
 
#define CALL_THISCALL_4( resultName, thisPtr, funcOffset, param1, param2, param3, param4 )\
328
 
    __asm__ __volatile__ ("pushl %1\n\t"                                    \
329
 
                          "pushl %2\n\t"                                    \
330
 
                          "pushl %3\n\t"                                    \
331
 
                          "pushl %4\n\t"                                    \
332
 
                          "movl (%5), %%edx\n\t"                            \
333
 
                          "call *"#funcOffset"(%%edx)\n\t"                  \
334
 
                          :"=a"(resultName) /* Output Operands */           \
335
 
                          :"r"(param4),     /* Input Operands  */           \
336
 
                           "r"(param3),                                     \
337
 
                           "r"(param2),                                     \
338
 
                           "r"(param1),                                     \
339
 
                           "c"(thisPtr)                                     \
340
 
                          );                                                \
341
 
 
342
 
#endif
343
 
 
344
 
 
345
 
 
346
 
// Our static singleton instance.
347
 
IASIOThiscallResolver IASIOThiscallResolver::instance;
348
 
 
349
 
// Constructor called to initialize static Singleton instance above. Note that
350
 
// it is important not to clear that_ incase it has already been set by the call
351
 
// to placement new in ASIOInit().
352
 
IASIOThiscallResolver::IASIOThiscallResolver()
353
 
{
354
 
}
355
 
 
356
 
// Constructor called from ASIOInit() below
357
 
IASIOThiscallResolver::IASIOThiscallResolver(IASIO* that)
358
 
: that_( that )
359
 
{
360
 
}
361
 
 
362
 
// Implement IUnknown methods as assert(false). IASIOThiscallResolver is not
363
 
// really a COM object, just a wrapper which will work with the ASIO SDK.
364
 
// If you wanted to use ASIO without the SDK you might want to implement COM
365
 
// aggregation in these methods.
366
 
HRESULT STDMETHODCALLTYPE IASIOThiscallResolver::QueryInterface(REFIID riid, void **ppv)
367
 
{
368
 
    (void)riid;     // suppress unused variable warning
369
 
 
370
 
    assert( false ); // this function should never be called by the ASIO SDK.
371
 
 
372
 
    *ppv = NULL;
373
 
    return E_NOINTERFACE;
374
 
}
375
 
 
376
 
ULONG STDMETHODCALLTYPE IASIOThiscallResolver::AddRef()
377
 
{
378
 
    assert( false ); // this function should never be called by the ASIO SDK.
379
 
 
380
 
    return 1;
381
 
}
382
 
 
383
 
ULONG STDMETHODCALLTYPE IASIOThiscallResolver::Release()
384
 
{
385
 
    assert( false ); // this function should never be called by the ASIO SDK.
386
 
 
387
 
    return 1;
388
 
}
389
 
 
390
 
 
391
 
// Implement the IASIO interface methods by performing the vptr manipulation
392
 
// described above then delegating to the real implementation.
393
 
ASIOBool IASIOThiscallResolver::init(void *sysHandle)
394
 
{
395
 
    ASIOBool result;
396
 
    CALL_THISCALL_1( result, that_, 12, sysHandle );
397
 
    return result;
398
 
}
399
 
 
400
 
void IASIOThiscallResolver::getDriverName(char *name)
401
 
{
402
 
    CALL_VOID_THISCALL_1( that_, 16, name );
403
 
}
404
 
 
405
 
long IASIOThiscallResolver::getDriverVersion()
406
 
{
407
 
    ASIOBool result;
408
 
    CALL_THISCALL_0( result, that_, 20 );
409
 
    return result;
410
 
}
411
 
 
412
 
void IASIOThiscallResolver::getErrorMessage(char *string)
413
 
{
414
 
     CALL_VOID_THISCALL_1( that_, 24, string );
415
 
}
416
 
 
417
 
ASIOError IASIOThiscallResolver::start()
418
 
{
419
 
    ASIOBool result;
420
 
    CALL_THISCALL_0( result, that_, 28 );
421
 
    return result;
422
 
}
423
 
 
424
 
ASIOError IASIOThiscallResolver::stop()
425
 
{
426
 
    ASIOBool result;
427
 
    CALL_THISCALL_0( result, that_, 32 );
428
 
    return result;
429
 
}
430
 
 
431
 
ASIOError IASIOThiscallResolver::getChannels(long *numInputChannels, long *numOutputChannels)
432
 
{
433
 
    ASIOBool result;
434
 
    CALL_THISCALL_2( result, that_, 36, numInputChannels, numOutputChannels );
435
 
    return result;
436
 
}
437
 
 
438
 
ASIOError IASIOThiscallResolver::getLatencies(long *inputLatency, long *outputLatency)
439
 
{
440
 
    ASIOBool result;
441
 
    CALL_THISCALL_2( result, that_, 40, inputLatency, outputLatency );
442
 
    return result;
443
 
}
444
 
 
445
 
ASIOError IASIOThiscallResolver::getBufferSize(long *minSize, long *maxSize,
446
 
        long *preferredSize, long *granularity)
447
 
{
448
 
    ASIOBool result;
449
 
    CALL_THISCALL_4( result, that_, 44, minSize, maxSize, preferredSize, granularity );
450
 
    return result;
451
 
}
452
 
 
453
 
ASIOError IASIOThiscallResolver::canSampleRate(ASIOSampleRate sampleRate)
454
 
{
455
 
    ASIOBool result;
456
 
    CALL_THISCALL_1_DOUBLE( result, that_, 48, sampleRate );
457
 
    return result;
458
 
}
459
 
 
460
 
ASIOError IASIOThiscallResolver::getSampleRate(ASIOSampleRate *sampleRate)
461
 
{
462
 
    ASIOBool result;
463
 
    CALL_THISCALL_1( result, that_, 52, sampleRate );
464
 
    return result;
465
 
}
466
 
 
467
 
ASIOError IASIOThiscallResolver::setSampleRate(ASIOSampleRate sampleRate)
468
 
{
469
 
    ASIOBool result;
470
 
    CALL_THISCALL_1_DOUBLE( result, that_, 56, sampleRate );
471
 
    return result;
472
 
}
473
 
 
474
 
ASIOError IASIOThiscallResolver::getClockSources(ASIOClockSource *clocks, long *numSources)
475
 
{
476
 
    ASIOBool result;
477
 
    CALL_THISCALL_2( result, that_, 60, clocks, numSources );
478
 
    return result;
479
 
}
480
 
 
481
 
ASIOError IASIOThiscallResolver::setClockSource(long reference)
482
 
{
483
 
    ASIOBool result;
484
 
    CALL_THISCALL_1( result, that_, 64, reference );
485
 
    return result;
486
 
}
487
 
 
488
 
ASIOError IASIOThiscallResolver::getSamplePosition(ASIOSamples *sPos, ASIOTimeStamp *tStamp)
489
 
{
490
 
    ASIOBool result;
491
 
    CALL_THISCALL_2( result, that_, 68, sPos, tStamp );
492
 
    return result;
493
 
}
494
 
 
495
 
ASIOError IASIOThiscallResolver::getChannelInfo(ASIOChannelInfo *info)
496
 
{
497
 
    ASIOBool result;
498
 
    CALL_THISCALL_1( result, that_, 72, info );
499
 
    return result;
500
 
}
501
 
 
502
 
ASIOError IASIOThiscallResolver::createBuffers(ASIOBufferInfo *bufferInfos,
503
 
        long numChannels, long bufferSize, ASIOCallbacks *callbacks)
504
 
{
505
 
    ASIOBool result;
506
 
    CALL_THISCALL_4( result, that_, 76, bufferInfos, numChannels, bufferSize, callbacks );
507
 
    return result;
508
 
}
509
 
 
510
 
ASIOError IASIOThiscallResolver::disposeBuffers()
511
 
{
512
 
    ASIOBool result;
513
 
    CALL_THISCALL_0( result, that_, 80 );
514
 
    return result;
515
 
}
516
 
 
517
 
ASIOError IASIOThiscallResolver::controlPanel()
518
 
{
519
 
    ASIOBool result;
520
 
    CALL_THISCALL_0( result, that_, 84 );
521
 
    return result;
522
 
}
523
 
 
524
 
ASIOError IASIOThiscallResolver::future(long selector,void *opt)
525
 
{
526
 
    ASIOBool result;
527
 
    CALL_THISCALL_2( result, that_, 88, selector, opt );
528
 
    return result;
529
 
}
530
 
 
531
 
ASIOError IASIOThiscallResolver::outputReady()
532
 
{
533
 
    ASIOBool result;
534
 
    CALL_THISCALL_0( result, that_, 92 );
535
 
    return result;
536
 
}
537
 
 
538
 
 
539
 
// Implement our substitute ASIOInit() method
540
 
ASIOError IASIOThiscallResolver::ASIOInit(ASIODriverInfo *info)
541
 
{
542
 
    // To ensure that our instance's vptr is correctly constructed, even if
543
 
    // ASIOInit is called prior to main(), we explicitly call its constructor
544
 
    // (potentially over the top of an existing instance). Note that this is
545
 
    // pretty ugly, and is only safe because IASIOThiscallResolver has no
546
 
    // destructor and contains no objects with destructors.
547
 
    new((void*)&instance) IASIOThiscallResolver( theAsioDriver );
548
 
 
549
 
    // Interpose between ASIO client code and the real driver.
550
 
    theAsioDriver = &instance;
551
 
 
552
 
    // Note that we never need to switch theAsioDriver back to point to the
553
 
    // real driver because theAsioDriver is reset to zero in ASIOExit().
554
 
 
555
 
    // Delegate to the real ASIOInit
556
 
        return ::ASIOInit(info);
557
 
}
558
 
 
559
 
 
560
 
#endif /* !defined(_MSC_VER) */
561
 
 
562
 
#endif /* Win32 */