PageRenderTime 135ms CodeModel.GetById 25ms app.highlight 103ms RepoModel.GetById 1ms app.codeStats 0ms

/libs/ObjectAL/OpenAL/ALWrapper.m

http://github.com/kstenerud/ObjectAL-for-iPhone
Objective C | 1397 lines | 1167 code | 169 blank | 61 comment | 37 complexity | 05f1ece03adfe2f6f2e70e2022ca598a MD5 | raw file
   1//
   2//  OpenAL.m
   3//  ObjectAL
   4//
   5//  Created by Karl Stenerud on 15/12/09.
   6//
   7// Copyright 2009 Karl Stenerud
   8//
   9// Licensed under the Apache License, Version 2.0 (the "License");
  10// you may not use this file except in compliance with the License.
  11// You may obtain a copy of the License at
  12//
  13// http://www.apache.org/licenses/LICENSE-2.0
  14//
  15// Unless required by applicable law or agreed to in writing, software
  16// distributed under the License is distributed on an "AS IS" BASIS,
  17// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18// See the License for the specific language governing permissions and
  19// limitations under the License.
  20//
  21// Note: You are NOT required to make the license available from within your
  22// iOS application. Including it in your project is sufficient.
  23//
  24// Attribution is not required, but appreciated :)
  25//
  26
  27#import "ALWrapper.h"
  28#import "ObjectALMacros.h"
  29#import "OALNotifications.h"
  30
  31/** Check the result of an AL call, logging an error if necessary.
  32 *
  33 * @return TRUE if the call was successful.
  34 */
  35#define CHECK_AL_CALL() checkIfSuccessful(__PRETTY_FUNCTION__)
  36
  37/** Check the result of an ALC call, logging an error if necessary.
  38 *
  39 * @param DEVICE The device involved in the ALC call.
  40 * @return TRUE if the call was successful.
  41 */
  42#define CHECK_ALC_CALL(DEVICE) checkIfSuccessfulWithDevice(__PRETTY_FUNCTION__, (DEVICE))
  43
  44
  45/**
  46 * Private interface to ALWrapper.
  47 */
  48@interface ALWrapper (Private)
  49
  50/** Decode an OpenAL supplied NULL-separated string list into an NSArray.
  51 *
  52 * @param source the string list as supplied by OpenAL.
  53 * @return the string list in an NSArray of NSString.
  54 */
  55+ (NSArray*) decodeNullSeparatedStringList:(const ALCchar*) source;
  56
  57/** Decode an OpenAL supplied space-separated string list into an NSArray.
  58 *
  59 * @param source the string list as supplied by OpenAL.
  60 * @return the string list in an NSArray of NSString.
  61 */
  62+ (NSArray*) decodeSpaceSeparatedStringList:(const ALCchar*) source;
  63
  64/** Check the OpenAL error status and log an error message if necessary.
  65 *
  66 * @param contextInfo Contextual information to add when logging an error.
  67 * @return TRUE if the operation was successful (no error).
  68 */
  69BOOL checkIfSuccessful(const char* contextInfo);
  70
  71/** Check the OpenAL error status and log an error message if necessary.
  72 *
  73 * @param contextInfo Contextual information to add when logging an error.
  74 * @param device The device to check for errors on.
  75 * @return TRUE if the operation was successful (no error).
  76 */
  77BOOL checkIfSuccessfulWithDevice(const char* contextInfo, ALCdevice* device);
  78
  79@end
  80
  81#pragma mark -
  82
  83@implementation ALWrapper
  84
  85typedef ALdouble AL_APIENTRY (*alcMacOSXGetMixerOutputRateProcPtr)();
  86typedef ALvoid AL_APIENTRY (*alcMacOSXMixerOutputRateProcPtr) (const ALdouble value);
  87typedef ALvoid AL_APIENTRY (*alBufferDataStaticProcPtr) (const ALint bid,
  88														 ALenum format,
  89														 const ALvoid* data,
  90														 ALsizei size,
  91														 ALsizei freq);
  92
  93static alcMacOSXGetMixerOutputRateProcPtr alcGetMacOSXMixerOutputRate = NULL;
  94static alcMacOSXMixerOutputRateProcPtr alcMacOSXMixerOutputRate = NULL;
  95static alBufferDataStaticProcPtr alBufferDataStatic = NULL;
  96
  97
  98#pragma mark -
  99#pragma mark Error Handling
 100
 101BOOL checkIfSuccessful(const char* contextInfo)
 102{
 103	ALenum error = alGetError();
 104	if(AL_NO_ERROR != error)
 105	{
 106		OAL_LOG_ERROR_CONTEXT(contextInfo, @"%s (error code 0x%08x)", alGetString(error), error);
 107		[[NSNotificationCenter defaultCenter] postNotificationName:OALAudioErrorNotification object:[ALWrapper class]];
 108		return NO;
 109	}
 110	return YES;
 111}
 112
 113BOOL checkIfSuccessfulWithDevice(const char* contextInfo, ALCdevice* device)
 114{
 115	ALenum error = alcGetError(device);
 116	if(ALC_NO_ERROR != error)
 117	{
 118		OAL_LOG_ERROR_CONTEXT(contextInfo, @"%s (error code 0x%08x)", alcGetString(device, error), error);
 119		[[NSNotificationCenter defaultCenter] postNotificationName:OALAudioErrorNotification object:[ALWrapper class]];
 120		return NO;
 121	}
 122	return YES;
 123}
 124
 125
 126#pragma mark Internal Utility
 127
 128+ (NSArray*) decodeNullSeparatedStringList:(const ALCchar*) source
 129{
 130	NSMutableArray* array = [NSMutableArray arrayWithCapacity:10];
 131	NSString* lastString = nil;
 132	
 133	for(const ALCchar* nextString = source; 0 != *nextString; nextString += [lastString length] + 1)
 134	{
 135		lastString = [NSString stringWithFormat:@"%s", nextString];
 136	}
 137	
 138	return array;
 139}
 140
 141+ (NSArray*) decodeSpaceSeparatedStringList:(const ALCchar*) source
 142{
 143	NSMutableArray* array = [NSMutableArray arrayWithCapacity:10];
 144	ALCchar buffer[200];
 145	ALCchar* bufferPtr = buffer;
 146	const ALCchar* sourcePtr = source;
 147
 148	for(;;)
 149	{
 150		*bufferPtr = *sourcePtr;
 151		if(' ' == *bufferPtr || bufferPtr >= buffer + 199)
 152		{
 153			*bufferPtr = 0;
 154		}
 155		if(0 == *bufferPtr)
 156		{
 157			[array addObject:[NSString stringWithFormat:@"%s", buffer]];
 158			bufferPtr = buffer;
 159		}
 160		else
 161		{
 162			bufferPtr++;
 163		}
 164
 165		if(0 == *sourcePtr)
 166		{
 167			break;
 168		}
 169
 170		sourcePtr++;
 171	}
 172	
 173	return array;
 174}
 175
 176
 177#pragma mark -
 178#pragma mark OpenAL Management
 179
 180+ (bool) enable:(ALenum) capability
 181{
 182	bool result;
 183	@synchronized(self)
 184	{
 185		alEnable(capability);
 186		result = CHECK_AL_CALL();
 187	}
 188	return result;
 189}
 190
 191+ (bool) disable:(ALenum) capability
 192{
 193	bool result;
 194	@synchronized(self)
 195	{
 196		alDisable(capability);
 197		result = CHECK_AL_CALL();
 198	}
 199	return result;
 200}
 201
 202+ (bool) isEnabled:(ALenum) capability
 203{
 204	ALboolean result;
 205	@synchronized(self)
 206	{
 207		result = alIsEnabled(capability);
 208		CHECK_AL_CALL();
 209	}
 210	return result;
 211}
 212
 213
 214#pragma mark OpenAL Extensions
 215
 216+ (bool) isExtensionPresent:(NSString*) extensionName
 217{
 218	ALboolean result;
 219	@synchronized(self)
 220	{
 221		result = alIsExtensionPresent([extensionName UTF8String]);
 222		CHECK_AL_CALL();
 223	}
 224	return result;
 225}
 226
 227+ (void*) getProcAddress:(NSString*) functionName
 228{
 229	void* result;
 230	@synchronized(self)
 231	{
 232		result = alGetProcAddress([functionName UTF8String]);
 233		CHECK_AL_CALL();
 234	}
 235	return result;
 236}
 237
 238+ (ALenum) getEnumValue:(NSString*) enumName
 239{
 240	ALenum result;
 241	@synchronized(self)
 242	{
 243		result = alGetEnumValue([enumName UTF8String]);
 244		CHECK_AL_CALL();
 245	}
 246	return result;
 247}
 248
 249
 250#pragma mark -
 251#pragma mark Device Management
 252
 253+ (ALCdevice*) openDevice:(NSString*) deviceName
 254{
 255	ALCdevice* device;
 256	@synchronized(self)
 257	{
 258		device = alcOpenDevice([deviceName UTF8String]);
 259		if(NULL == device)
 260		{
 261			OAL_LOG_ERROR(@"Could not open device %@", deviceName);
 262		}
 263	}
 264	return device;
 265}
 266
 267+ (bool) closeDevice:(ALCdevice*) device
 268{
 269	bool result;
 270	@synchronized(self)
 271	{
 272		alcCloseDevice(device);
 273		result = CHECK_ALC_CALL(device);
 274	}
 275	return result;
 276}
 277
 278
 279#pragma mark Device Extensions
 280
 281+ (bool) isExtensionPresent:(ALCdevice*) device name:(NSString*) extensionName
 282{
 283	bool result;
 284	@synchronized(self)
 285	{
 286		result = alcIsExtensionPresent(device, [extensionName UTF8String]);
 287		CHECK_ALC_CALL(device);
 288	}
 289	return result;
 290}
 291
 292+ (void*) getProcAddress:(ALCdevice*) device name:(NSString*) functionName
 293{
 294	void* result;
 295	@synchronized(self)
 296	{
 297		result = alcGetProcAddress(device, [functionName UTF8String]);
 298		CHECK_ALC_CALL(device);
 299	}
 300	return result;
 301}
 302
 303+ (ALenum) getEnumValue:(ALCdevice*) device name:(NSString*) enumName
 304{
 305	ALenum result;
 306	@synchronized(self)
 307	{
 308		result = alcGetEnumValue(device, [enumName UTF8String]);
 309		CHECK_ALC_CALL(device);
 310	}
 311	return result;
 312}
 313
 314
 315#pragma mark Device Properties
 316
 317+ (NSString*) getString:(ALCdevice*) device attribute:(ALenum) attribute
 318{
 319	const ALCchar* result;
 320	@synchronized(self)
 321	{
 322		result = alcGetString(device, attribute);
 323		CHECK_ALC_CALL(device);
 324	}
 325	return [NSString stringWithFormat:@"%s", result];
 326}
 327
 328+ (NSArray*) getNullSeparatedStringList:(ALCdevice*) device attribute:(ALenum) attribute
 329{
 330	const ALCchar* result;
 331	@synchronized(self)
 332	{
 333		result = alcGetString(device, attribute);
 334		CHECK_ALC_CALL(device);
 335	}
 336	return [self decodeNullSeparatedStringList:result];
 337}
 338
 339+ (NSArray*) getSpaceSeparatedStringList:(ALCdevice*) device attribute:(ALenum) attribute
 340{
 341	const ALCchar* result;
 342	@synchronized(self)
 343	{
 344		result = alcGetString(device, attribute);
 345		CHECK_ALC_CALL(device);
 346	}
 347	return [self decodeSpaceSeparatedStringList:result];
 348}
 349
 350+ (ALint) getInteger:(ALCdevice*) device attribute:(ALenum) attribute
 351{
 352	ALint result = 0;
 353	[self getIntegerv:device attribute:attribute size:1 data:&result];
 354	return result;
 355}
 356
 357+ (bool) getIntegerv:(ALCdevice*) device attribute:(ALenum) attribute size:(ALsizei) size data:(ALCint*) data
 358{
 359	bool result;
 360	@synchronized(self)
 361	{
 362		alcGetIntegerv(device, attribute, size, data);
 363		result = CHECK_ALC_CALL(device);
 364	}
 365	return result;
 366}
 367
 368
 369#pragma mark Capture
 370
 371+ (ALCdevice*) openCaptureDevice:(NSString*) deviceName frequency:(ALCuint) frequency format:(ALCenum) format bufferSize:(ALCsizei) bufferSize
 372{
 373	ALCdevice* result;
 374	@synchronized(self)
 375	{
 376		result = alcCaptureOpenDevice([deviceName UTF8String], frequency, format, bufferSize);
 377		if(nil == result)
 378		{
 379			OAL_LOG_ERROR(@"Could not open capture device %@", deviceName);
 380		}
 381	}
 382	return result;
 383}
 384
 385+ (bool) closeCaptureDevice:(ALCdevice*) device
 386{
 387	bool result;
 388	@synchronized(self)
 389	{
 390		alcCaptureCloseDevice(device);
 391		result = CHECK_ALC_CALL(device);
 392	}
 393	return result;
 394}
 395
 396+ (bool) startCapture:(ALCdevice*) device
 397{
 398	bool result;
 399	@synchronized(self)
 400	{
 401		alcCaptureStop(device);
 402		result = CHECK_ALC_CALL(device);
 403	}
 404	return result;
 405}
 406
 407+ (bool) stopCapture:(ALCdevice*) device
 408{
 409	bool result;
 410	@synchronized(self)
 411	{
 412		alcCaptureStop(device);
 413		result = CHECK_ALC_CALL(device);
 414	}
 415	return result;
 416}
 417
 418+ (bool) captureSamples:(ALCdevice*) device buffer:(ALCvoid*) buffer numSamples:(ALCsizei) numSamples
 419{
 420	bool result;
 421	@synchronized(self)
 422	{
 423		alcCaptureSamples(device, buffer, numSamples);
 424		result = CHECK_ALC_CALL(device);
 425	}
 426	return result;
 427}
 428
 429
 430#pragma mark -
 431#pragma mark Context Management
 432
 433+ (ALCcontext*) createContext:(ALCdevice*) device attributes:(ALCint*) attributes
 434{
 435	ALCcontext* result;
 436	@synchronized(self)
 437	{
 438		result = alcCreateContext(device, attributes);
 439		CHECK_ALC_CALL(device);
 440	}
 441	return result;
 442}
 443
 444+ (bool) makeContextCurrent:(ALCcontext*) context
 445{
 446	return [self makeContextCurrent:context deviceReference:nil];
 447}
 448
 449+ (bool) makeContextCurrent:(ALCcontext*) context deviceReference:(ALCdevice*) deviceReference
 450{
 451	@synchronized(self)
 452	{
 453		if(!alcMakeContextCurrent(context))
 454		{
 455			if(nil != deviceReference)
 456			{
 457				CHECK_ALC_CALL(deviceReference);
 458			}
 459			else
 460			{
 461				OAL_LOG_ERROR(@"Could not make context %d current.  Pass in a device reference for better diagnostic info.", context);
 462			}
 463			return NO;
 464		}
 465	}
 466	return YES;
 467}
 468
 469+ (void) processContext:(ALCcontext*) context
 470{
 471	@synchronized(self)
 472	{
 473		alcProcessContext(context);
 474		// No way to check for error from here
 475	}
 476}
 477
 478+ (void) suspendContext:(ALCcontext*) context
 479{
 480	@synchronized(self)
 481	{
 482		alcSuspendContext(context);
 483		// No way to check for error from here
 484	}
 485}
 486
 487+ (void) destroyContext:(ALCcontext*) context
 488{
 489	@synchronized(self)
 490	{
 491		alcDestroyContext(context);
 492		// No way to check for error from here
 493	}
 494}
 495
 496+ (ALCcontext*) getCurrentContext
 497{
 498	ALCcontext* result;
 499	@synchronized(self)
 500	{
 501		result = alcGetCurrentContext();
 502	}
 503	return result;
 504}
 505
 506+ (ALCdevice*) getContextsDevice:(ALCcontext*) context
 507{
 508	return [self getContextsDevice:context deviceReference:nil];
 509}
 510
 511+ (ALCdevice*) getContextsDevice:(ALCcontext*) context deviceReference:(ALCdevice*) deviceReference
 512{
 513	ALCdevice* result;
 514	@synchronized(self)
 515	{
 516		if(nil == (result = alcGetContextsDevice(context)))
 517		{
 518			if(nil != deviceReference)
 519			{
 520				CHECK_ALC_CALL(deviceReference);
 521			}
 522			else
 523			{
 524				OAL_LOG_ERROR(@"Could not get device for context %d.  Pass in a device reference for better diagnostic info.", context);
 525			}
 526		}
 527	}
 528	return result;
 529}
 530
 531
 532#pragma mark Context Properties
 533
 534+ (bool) getBoolean:(ALenum) parameter
 535{
 536	ALboolean result;
 537	@synchronized(self)
 538	{
 539		result = alGetBoolean(parameter);
 540		CHECK_AL_CALL();
 541	}
 542	return result;
 543}
 544
 545+ (ALdouble) getDouble:(ALenum) parameter
 546{
 547	ALdouble result;
 548	@synchronized(self)
 549	{
 550		result = alGetDouble(parameter);
 551		CHECK_AL_CALL();
 552	}
 553	return result;
 554}
 555
 556+ (ALfloat) getFloat:(ALenum) parameter
 557{
 558	ALfloat result;
 559	@synchronized(self)
 560	{
 561		result = alGetFloat(parameter);
 562		CHECK_AL_CALL();
 563	}
 564	return result;
 565}
 566
 567+ (ALint) getInteger:(ALenum) parameter
 568{
 569	ALint result;
 570	@synchronized(self)
 571	{
 572		result = alGetInteger(parameter);
 573		CHECK_AL_CALL();
 574	}
 575	return result;
 576}
 577
 578+ (NSString*) getString:(ALenum) parameter
 579{
 580	const ALchar* result;
 581	@synchronized(self)
 582	{
 583		result = alGetString(parameter);
 584		CHECK_AL_CALL();
 585	}
 586	return [NSString stringWithFormat:@"%s", result];
 587}
 588
 589+ (NSArray*) getNullSeparatedStringList:(ALenum) parameter
 590{
 591	const ALchar* result;
 592	@synchronized(self)
 593	{
 594		result = alGetString(parameter);
 595		CHECK_AL_CALL();
 596	}
 597	return [self decodeNullSeparatedStringList:result];
 598}
 599
 600+ (NSArray*) getSpaceSeparatedStringList:(ALenum) parameter
 601{
 602	const ALchar* result;
 603	@synchronized(self)
 604	{
 605		result = alGetString(parameter);
 606		CHECK_AL_CALL();
 607	}
 608	return [self decodeSpaceSeparatedStringList:result];
 609}
 610
 611+ (bool) getBooleanv:(ALenum) parameter values:(ALboolean*) values
 612{
 613	bool result;
 614	@synchronized(self)
 615	{
 616		alGetBooleanv(parameter, values);
 617		result = CHECK_AL_CALL();
 618	}
 619	return result;
 620}
 621
 622+ (bool) getDoublev:(ALenum) parameter values:(ALdouble*) values
 623{
 624	bool result;
 625	@synchronized(self)
 626	{
 627		alGetDoublev(parameter, values);
 628		result = CHECK_AL_CALL();
 629	}
 630	return result;
 631}
 632
 633+ (bool) getFloatv:(ALenum) parameter values:(ALfloat*) values
 634{
 635	bool result;
 636	@synchronized(self)
 637	{
 638		alGetFloatv(parameter, values);
 639		result = CHECK_AL_CALL();
 640	}
 641	return result;
 642}
 643
 644+ (bool) getIntegerv:(ALenum) parameter values:(ALint*) values
 645{
 646	bool result;
 647	@synchronized(self)
 648	{
 649		alGetIntegerv(parameter, values);
 650		result = CHECK_AL_CALL();
 651	}
 652	return result;
 653}
 654
 655+ (bool) distanceModel:(ALenum) value
 656{
 657	bool result;
 658	@synchronized(self)
 659	{
 660		alDistanceModel(value);
 661		result = CHECK_AL_CALL();
 662	}
 663	return result;
 664}
 665
 666+ (bool) dopplerFactor:(ALfloat) value
 667{
 668	bool result;
 669	@synchronized(self)
 670	{
 671		alDopplerFactor(value);
 672		result = CHECK_AL_CALL();
 673	}
 674	return result;
 675}
 676
 677+ (bool) speedOfSound:(ALfloat) value
 678{
 679	bool result;
 680	@synchronized(self)
 681	{
 682		alSpeedOfSound(value);
 683		result = CHECK_AL_CALL();
 684	}
 685	return result;
 686}
 687
 688
 689#pragma mark -
 690#pragma mark Listener Properties
 691
 692+ (bool) listenerf:(ALenum) parameter value:(ALfloat) value
 693{
 694	bool result;
 695	@synchronized(self)
 696	{
 697		alListenerf(parameter, value);
 698		result = CHECK_AL_CALL();
 699	}
 700	return result;
 701}
 702
 703+ (bool) listener3f:(ALenum) parameter v1:(ALfloat) v1 v2:(ALfloat) v2 v3:(ALfloat) v3
 704{
 705	bool result;
 706	@synchronized(self)
 707	{
 708		alListener3f(parameter, v1, v2, v3);
 709		result = CHECK_AL_CALL();
 710	}
 711	return result;
 712}
 713
 714+ (bool) listenerfv:(ALenum) parameter values:(ALfloat*) values
 715{
 716	bool result;
 717	@synchronized(self)
 718	{
 719		alListenerfv(parameter, values);
 720		result = CHECK_AL_CALL();
 721	}
 722	return result;
 723}
 724
 725+ (bool) listeneri:(ALenum) parameter value:(ALint) value
 726{
 727	bool result;
 728	@synchronized(self)
 729	{
 730		alListeneri(parameter, value);
 731		result = CHECK_AL_CALL();
 732	}
 733	return result;
 734}
 735
 736+ (bool) listener3i:(ALenum) parameter v1:(ALint) v1 v2:(ALint) v2 v3:(ALint) v3
 737{
 738	bool result;
 739	@synchronized(self)
 740	{
 741		alListener3i(parameter, v1, v2, v3);
 742		result = CHECK_AL_CALL();
 743	}
 744	return result;
 745}
 746
 747+ (bool) listeneriv:(ALenum) parameter values:(ALint*) values
 748{
 749	bool result;
 750	@synchronized(self)
 751	{
 752		alListeneriv(parameter, values);
 753		result = CHECK_AL_CALL();
 754	}
 755	return result;
 756}
 757
 758
 759+ (ALfloat) getListenerf:(ALenum) parameter
 760{
 761	ALfloat value;
 762	@synchronized(self)
 763	{
 764		alGetListenerf(parameter, &value);
 765		CHECK_AL_CALL();
 766	}
 767	return value;
 768}
 769
 770+ (bool) getListener3f:(ALenum) parameter v1:(ALfloat*) v1 v2:(ALfloat*) v2 v3:(ALfloat*) v3
 771{
 772	bool result;
 773	@synchronized(self)
 774	{
 775		alGetListener3f(parameter, v1, v2, v3);
 776		result = CHECK_AL_CALL();
 777	}
 778	return result;
 779}
 780
 781+ (bool) getListenerfv:(ALenum) parameter values:(ALfloat*) values
 782{
 783	bool result;
 784	@synchronized(self)
 785	{
 786		alGetListenerfv(parameter, values);
 787		result = CHECK_AL_CALL();
 788	}
 789	return result;
 790}
 791
 792+ (ALint) getListeneri:(ALenum) parameter
 793{
 794	ALint value;
 795	@synchronized(self)
 796	{
 797		alGetListeneri(parameter, &value);
 798		CHECK_AL_CALL();
 799	}
 800	return value;
 801}
 802
 803+ (bool) getListener3i:(ALenum) parameter v1:(ALint*) v1 v2:(ALint*) v2 v3:(ALint*) v3
 804{
 805	bool result;
 806	@synchronized(self)
 807	{
 808		alGetListener3i(parameter, v1, v2, v3);
 809		result = CHECK_AL_CALL();
 810	}
 811	return result;
 812}
 813
 814+ (bool) getListeneriv:(ALenum) parameter values:(ALint*) values
 815{
 816	bool result;
 817	@synchronized(self)
 818	{
 819		alGetListeneriv(parameter, values);
 820		result = CHECK_AL_CALL();
 821	}
 822	return result;
 823}
 824
 825
 826#pragma mark -
 827#pragma mark Source Management
 828
 829+ (bool) genSources:(ALuint*) sourceIds numSources:(ALsizei) numSources
 830{
 831	bool result;
 832	@synchronized(self)
 833	{
 834		alGenSources(numSources, sourceIds);
 835		result = CHECK_AL_CALL();
 836	}
 837	return result;
 838}
 839
 840+ (ALuint) genSource
 841{
 842	ALuint sourceId;
 843	@synchronized(self)
 844	{
 845		[self genSources:&sourceId numSources:1];
 846		sourceId = CHECK_AL_CALL() ? sourceId : (ALuint)AL_INVALID;
 847	}
 848	return sourceId;
 849}
 850
 851+ (bool) deleteSources:(ALuint*) sourceIds numSources:(ALsizei) numSources
 852{
 853	bool result;
 854	@synchronized(self)
 855	{
 856		alDeleteSources(numSources, sourceIds);
 857		result = CHECK_AL_CALL();
 858	}
 859	return result;
 860}
 861
 862+ (bool) deleteSource:(ALuint) sourceId
 863{
 864	bool result;
 865	@synchronized(self)
 866	{
 867		[self deleteSources:&sourceId numSources:1];
 868		result = CHECK_AL_CALL();
 869	}
 870	return result;
 871}
 872
 873+ (bool) isSource:(ALuint) sourceId
 874{
 875	bool result;
 876	@synchronized(self)
 877	{
 878		result = alIsSource(sourceId);
 879		CHECK_AL_CALL();
 880	}
 881	return result;
 882}
 883
 884
 885#pragma mark Source Properties
 886
 887+ (bool) sourcef:(ALuint) sourceId parameter:(ALenum) parameter value:(ALfloat) value
 888{
 889	bool result;
 890	@synchronized(self)
 891	{
 892		alSourcef(sourceId, parameter, value);
 893		result = CHECK_AL_CALL();
 894	}
 895	return result;
 896}
 897
 898+ (bool) source3f:(ALuint) sourceId parameter:(ALenum) parameter v1:(ALfloat) v1 v2:(ALfloat) v2 v3:(ALfloat) v3
 899{
 900	bool result;
 901	@synchronized(self)
 902	{
 903		alSource3f(sourceId, parameter, v1, v2, v3);
 904		result = CHECK_AL_CALL();
 905	}
 906	return result;
 907}
 908
 909+ (bool) sourcefv:(ALuint) sourceId parameter:(ALenum) parameter values:(ALfloat*) values
 910{
 911	bool result;
 912	@synchronized(self)
 913	{
 914		alSourcefv(sourceId, parameter, values);
 915		result = CHECK_AL_CALL();
 916	}
 917	return result;
 918}
 919
 920+ (bool) sourcei:(ALuint) sourceId parameter:(ALenum) parameter value:(ALint) value
 921{
 922	bool result;
 923	@synchronized(self)
 924	{
 925		alSourcei(sourceId, parameter, value);
 926		result = CHECK_AL_CALL();
 927	}
 928	return result;
 929}
 930
 931+ (bool) source3i:(ALuint) sourceId parameter:(ALenum) parameter v1:(ALint) v1 v2:(ALint) v2 v3:(ALint) v3
 932{
 933	bool result;
 934	@synchronized(self)
 935	{
 936		alSource3i(sourceId, parameter, v1, v2, v3);
 937		result = CHECK_AL_CALL();
 938	}
 939	return result;
 940}
 941
 942+ (bool) sourceiv:(ALuint) sourceId parameter:(ALenum) parameter values:(ALint*) values
 943{
 944	bool result;
 945	@synchronized(self)
 946	{
 947		alSourceiv(sourceId, parameter, values);
 948		result = CHECK_AL_CALL();
 949	}
 950	return result;
 951}
 952
 953
 954+ (ALfloat) getSourcef:(ALuint) sourceId parameter:(ALenum) parameter
 955{
 956	ALfloat value;
 957	@synchronized(self)
 958	{
 959		alGetSourcef(sourceId, parameter, &value);
 960		CHECK_AL_CALL();
 961	}
 962	return value;
 963}
 964
 965+ (bool) getSource3f:(ALuint) sourceId parameter:(ALenum) parameter v1:(ALfloat*) v1 v2:(ALfloat*) v2 v3:(ALfloat*) v3
 966{
 967	bool result;
 968	@synchronized(self)
 969	{
 970		alGetSource3f(sourceId, parameter, v1, v2, v3);
 971		result = CHECK_AL_CALL();
 972	}
 973	return result;
 974}
 975
 976+ (bool) getSourcefv:(ALuint) sourceId parameter:(ALenum) parameter values:(ALfloat*) values
 977{
 978	bool result;
 979	@synchronized(self)
 980	{
 981		alGetSourcefv(sourceId, parameter, values);
 982		result = CHECK_AL_CALL();
 983	}
 984	return result;
 985}
 986
 987+ (ALint) getSourcei:(ALuint) sourceId parameter:(ALenum) parameter
 988{
 989	ALint value;
 990	@synchronized(self)
 991	{
 992		alGetSourcei(sourceId, parameter, &value);
 993		CHECK_AL_CALL();
 994	}
 995	return value;
 996}
 997
 998+ (bool) getSource3i:(ALuint) sourceId parameter:(ALenum) parameter v1:(ALint*) v1 v2:(ALint*) v2 v3:(ALint*) v3
 999{
1000	bool result;
1001	@synchronized(self)
1002	{
1003		alGetSource3i(sourceId, parameter, v1, v2, v3);
1004		result = CHECK_AL_CALL();
1005	}
1006	return result;
1007}
1008
1009+ (bool) getSourceiv:(ALuint) sourceId parameter:(ALenum) parameter values:(ALint*) values
1010{
1011	bool result;
1012	@synchronized(self)
1013	{
1014		alGetSourceiv(sourceId, parameter, values);
1015		result = CHECK_AL_CALL();
1016	}
1017	return result;
1018}
1019
1020
1021#pragma mark Source Playback
1022
1023+ (bool) sourcePlay:(ALuint) sourceId
1024{
1025	bool result;
1026	@synchronized(self)
1027	{
1028		alSourcePlay(sourceId);
1029		result = CHECK_AL_CALL();
1030	}
1031	return result;
1032}
1033
1034+ (bool) sourcePlayv:(ALuint*) sourceIds numSources:(ALsizei) numSources
1035{
1036	bool result;
1037	@synchronized(self)
1038	{
1039		alSourcePlayv(numSources, sourceIds);
1040		result = CHECK_AL_CALL();
1041	}
1042	return result;
1043}
1044
1045+ (bool) sourcePause:(ALuint) sourceId
1046{
1047	bool result;
1048	@synchronized(self)
1049	{
1050		alSourcePause(sourceId);
1051		result = CHECK_AL_CALL();
1052	}
1053	return result;
1054}
1055
1056+ (bool) sourcePausev:(ALuint*) sourceIds numSources:(ALsizei) numSources
1057{
1058	bool result;
1059	@synchronized(self)
1060	{
1061		alSourcePausev(numSources, sourceIds);
1062		result = CHECK_AL_CALL();
1063	}
1064	return result;
1065}
1066
1067+ (bool) sourceStop:(ALuint) sourceId
1068{
1069	bool result;
1070	@synchronized(self)
1071	{
1072		alSourceStop(sourceId);
1073		result = CHECK_AL_CALL();
1074	}
1075	return result;
1076}
1077
1078+ (bool) sourceStopv:(ALuint*) sourceIds numSources:(ALsizei) numSources
1079{
1080	bool result;
1081	@synchronized(self)
1082	{
1083		alSourceStopv(numSources, sourceIds);
1084		result = CHECK_AL_CALL();
1085	}
1086	return result;
1087}
1088
1089+ (bool) sourceRewind:(ALuint) sourceId
1090{
1091	bool result;
1092	@synchronized(self)
1093	{
1094		alSourceRewind(sourceId);
1095		result = CHECK_AL_CALL();
1096	}
1097	return result;
1098}
1099
1100+ (bool) sourceRewindv:(ALuint*) sourceIds numSources:(ALsizei) numSources
1101{
1102	bool result;
1103	@synchronized(self)
1104	{
1105		alSourceRewindv(numSources, sourceIds);
1106		result = CHECK_AL_CALL();
1107	}
1108	return result;
1109}
1110
1111+ (bool) sourceQueueBuffers:(ALuint) sourceId numBuffers:(ALsizei) numBuffers bufferIds:(ALuint*) bufferIds
1112{
1113	bool result;
1114	@synchronized(self)
1115	{
1116		alSourceQueueBuffers(sourceId, numBuffers, bufferIds);
1117		result = CHECK_AL_CALL();
1118	}
1119	return result;
1120}
1121
1122+ (bool) sourceUnqueueBuffers:(ALuint) sourceId numBuffers:(ALsizei) numBuffers bufferIds:(ALuint*) bufferIds
1123{
1124	bool result;
1125	@synchronized(self)
1126	{
1127		alSourceUnqueueBuffers(sourceId, numBuffers, bufferIds);
1128		result = CHECK_AL_CALL();
1129	}
1130	return result;
1131}
1132
1133
1134#pragma mark -
1135#pragma mark Buffer Management
1136
1137+ (bool) genBuffers:(ALuint*) bufferIds numBuffers:(ALsizei) numBuffers
1138{
1139	bool result;
1140	@synchronized(self)
1141	{
1142		alGenBuffers(numBuffers, bufferIds);
1143		result = CHECK_AL_CALL();
1144	}
1145	return result;
1146}
1147
1148+ (ALuint) genBuffer
1149{
1150	ALuint bufferId;
1151	@synchronized(self)
1152	{
1153		[self genBuffers:&bufferId numBuffers:1];
1154		bufferId = CHECK_AL_CALL() ? bufferId : (ALuint)AL_INVALID;
1155	}
1156	return bufferId;
1157}
1158
1159+ (bool) deleteBuffers:(ALuint*) bufferIds numBuffers:(ALsizei) numBuffers
1160{
1161	bool result;
1162	@synchronized(self)
1163	{
1164		alDeleteBuffers(numBuffers, bufferIds);
1165		result = CHECK_AL_CALL();
1166	}
1167	return result;
1168}
1169
1170+ (bool) deleteBuffer:(ALuint) bufferId
1171{
1172	bool result;
1173	@synchronized(self)
1174	{
1175		[self deleteBuffers:&bufferId numBuffers:1];
1176		result = CHECK_AL_CALL();
1177	}
1178	return result;
1179}
1180
1181+ (bool) isBuffer:(ALuint) bufferId
1182{
1183	bool result;
1184	@synchronized(self)
1185	{
1186		result = alIsBuffer(bufferId);
1187		CHECK_AL_CALL();
1188	}
1189	return result;
1190}
1191
1192+ (bool) bufferData:(ALuint) bufferId format:(ALenum) format data:(const ALvoid*) data size:(ALsizei) size frequency:(ALsizei) frequency
1193{
1194	bool result;
1195	@synchronized(self)
1196	{
1197		alBufferData(bufferId, format, data, size, frequency);
1198		result = CHECK_AL_CALL();
1199	}
1200	return result;
1201}
1202
1203
1204#pragma mark Buffer Properties
1205
1206+ (bool) bufferf:(ALuint) bufferId parameter:(ALenum) parameter value:(ALfloat) value
1207{
1208	bool result;
1209	@synchronized(self)
1210	{
1211		alBufferf(bufferId, parameter, value);
1212		result = CHECK_AL_CALL();
1213	}
1214	return result;
1215}
1216
1217+ (bool) buffer3f:(ALuint) bufferId parameter:(ALenum) parameter v1:(ALfloat) v1 v2:(ALfloat) v2 v3:(ALfloat) v3
1218{
1219	bool result;
1220	@synchronized(self)
1221	{
1222		alBuffer3f(bufferId, parameter, v1, v2, v3);
1223		result = CHECK_AL_CALL();
1224	}
1225	return result;
1226}
1227
1228+ (bool) bufferfv:(ALuint) bufferId parameter:(ALenum) parameter values:(ALfloat*) values
1229{
1230	bool result;
1231	@synchronized(self)
1232	{
1233		alBufferfv(bufferId, parameter, values);
1234		result = CHECK_AL_CALL();
1235	}
1236	return result;
1237}
1238
1239+ (bool) bufferi:(ALuint) bufferId parameter:(ALenum) parameter value:(ALint) value
1240{
1241	bool result;
1242	@synchronized(self)
1243	{
1244		alBufferi(bufferId, parameter, value);
1245		result = CHECK_AL_CALL();
1246	}
1247	return result;
1248}
1249
1250+ (bool) buffer3i:(ALuint) bufferId parameter:(ALenum) parameter v1:(ALint) v1 v2:(ALint) v2 v3:(ALint) v3
1251{
1252	bool result;
1253	@synchronized(self)
1254	{
1255		alBuffer3i(bufferId, parameter, v1, v2, v3);
1256		result = CHECK_AL_CALL();
1257	}
1258	return result;
1259}
1260
1261+ (bool) bufferiv:(ALuint) bufferId parameter:(ALenum) parameter values:(ALint*) values
1262{
1263	bool result;
1264	@synchronized(self)
1265	{
1266		alBufferiv(bufferId, parameter, values);
1267		result = CHECK_AL_CALL();
1268	}
1269	return result;
1270}
1271
1272
1273+ (ALfloat) getBufferf:(ALuint) bufferId parameter:(ALenum) parameter
1274{
1275	ALfloat value;
1276	@synchronized(self)
1277	{
1278		alGetBufferf(bufferId, parameter, &value);
1279		CHECK_AL_CALL();
1280	}
1281	return value;
1282}
1283
1284+ (bool) getBuffer3f:(ALuint) bufferId parameter:(ALenum) parameter v1:(ALfloat*) v1 v2:(ALfloat*) v2 v3:(ALfloat*) v3
1285{
1286	bool result;
1287	@synchronized(self)
1288	{
1289		alGetBuffer3f(bufferId, parameter, v1, v2, v3);
1290		result = CHECK_AL_CALL();
1291	}
1292	return result;
1293}
1294
1295+ (bool) getBufferfv:(ALuint) bufferId parameter:(ALenum) parameter values:(ALfloat*) values
1296{
1297	bool result;
1298	@synchronized(self)
1299	{
1300		alGetBufferfv(bufferId, parameter, values);
1301		result = CHECK_AL_CALL();
1302	}
1303	return result;
1304}
1305
1306+ (ALint) getBufferi:(ALuint) bufferId parameter:(ALenum) parameter
1307{
1308	ALint value;
1309	@synchronized(self)
1310	{
1311		alGetBufferi(bufferId, parameter, &value);
1312		CHECK_AL_CALL();
1313	}
1314	return value;
1315}
1316
1317+ (bool) getBuffer3i:(ALuint) bufferId parameter:(ALenum) parameter v1:(ALint*) v1 v2:(ALint*) v2 v3:(ALint*) v3
1318{
1319	bool result;
1320	@synchronized(self)
1321	{
1322		alGetBuffer3i(bufferId, parameter, v1, v2, v3);
1323		result = CHECK_AL_CALL();
1324	}
1325	return result;
1326}
1327
1328+ (bool) getBufferiv:(ALuint) bufferId parameter:(ALenum) parameter values:(ALint*) values
1329{
1330	bool result;
1331	@synchronized(self)
1332	{
1333		alGetBufferiv(bufferId, parameter, values);
1334		result = CHECK_AL_CALL();
1335	}
1336	return result;
1337}
1338
1339
1340#pragma mark -
1341#pragma mark Apple Extensions
1342
1343+ (ALdouble) getMixerOutputDataRate
1344{
1345	if(NULL == alcGetMacOSXMixerOutputRate)
1346	{
1347		alcGetMacOSXMixerOutputRate = (alcMacOSXGetMixerOutputRateProcPtr) alcGetProcAddress(NULL, (const ALCchar*) "alcMacOSXGetMixerOutputRate");
1348		if(NULL == alcGetMacOSXMixerOutputRate)
1349		{
1350			OAL_LOG_ERROR(@"Could not get proc pointer for \"alcMacOSXMixerOutputRate\".");
1351		}
1352	}
1353	
1354	ALdouble result;
1355	@synchronized(self)
1356	{
1357		result = alcGetMacOSXMixerOutputRate();
1358		CHECK_AL_CALL();
1359	}
1360	return result;
1361}
1362
1363+ (void) setMixerOutputDataRate:(ALdouble) frequency
1364{
1365	if(NULL == alcMacOSXMixerOutputRate)
1366	{
1367		alcMacOSXMixerOutputRate = (alcMacOSXMixerOutputRateProcPtr) alcGetProcAddress(NULL, (const ALCchar*) "alcMacOSXMixerOutputRate");
1368		if(NULL == alcMacOSXMixerOutputRate)
1369		{
1370			OAL_LOG_ERROR(@"Could not get proc pointer for \"alcMacOSXMixerOutputRate\".");
1371		}
1372	}
1373	
1374	alcMacOSXMixerOutputRate(frequency);
1375}
1376
1377+ (bool) bufferDataStatic:(ALuint) bufferId format:(ALenum) format data:(const ALvoid*) data size:(ALsizei) size frequency:(ALsizei) frequency
1378{
1379	if(NULL == alBufferDataStatic)
1380	{
1381		alBufferDataStatic = (alBufferDataStaticProcPtr) alcGetProcAddress(NULL, (const ALCchar*) "alBufferDataStatic");
1382		if(NULL == alBufferDataStatic)
1383		{
1384			OAL_LOG_ERROR(@"Could not get proc pointer for \"alBufferDataStatic\".");
1385		}
1386	}
1387	
1388	bool result;
1389	@synchronized(self)
1390	{
1391		alBufferDataStatic(bufferId, format, data, size, frequency);
1392		result = CHECK_AL_CALL();
1393	}
1394	return result;
1395}
1396
1397@end