예제 #1
0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	AUMixer3DView::SetRenderingFlagsCheckboxes
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void	AUMixer3DView::SetRenderingFlagsCheckboxes()
{
	// set the check boxes according to the current rendering flags
	UInt32 flags;
	UInt32 size = sizeof(flags);
	
	AudioUnitGetProperty(
		GetEditAudioUnit(),
		kAudioUnitProperty_3DMixerRenderingFlags,
		kAudioUnitScope_Input,
		0,
		&flags,
		&size );

	UInt32 usesReverb = 0;
	AudioUnitGetProperty(
		GetEditAudioUnit(),
		kAudioUnitProperty_UsesInternalReverb,
		kAudioUnitScope_Input,
		0,
		&usesReverb,
		&size );

	SetCheckbox('atr0', 1, flags & k3DMixerRenderingFlags_InterAuralDelay );
	SetCheckbox('atr1', 2, flags & k3DMixerRenderingFlags_DopplerShift );
	SetCheckbox('atr2', 3, flags & k3DMixerRenderingFlags_DistanceAttenuation );
	SetCheckbox('atr3', 4, flags & k3DMixerRenderingFlags_DistanceFilter );
	SetCheckbox('atr4', 5, flags & k3DMixerRenderingFlags_DistanceDiffusion );
	SetCheckbox('rvrb', 6, usesReverb );
	::UpdateControls(GetCarbonWindow(), NULL );
}
예제 #2
0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	AUMixer3DView::SetCheckbox
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void	AUMixer3DView::SetCheckbox(OSType inSig, SInt32 inID, SInt16 inValue )
{
	WindowRef window = GetCarbonWindow();
	
	ControlID controlID;
	controlID.signature = inSig;
	controlID.id = inID;
	
	ControlRef control;
	OSStatus result = ::GetControlByID(window, &controlID, &control );

	if(result == noErr)
	{
		SetControlValue(control, int(inValue != 0 ) );
		ShowControl(control);
	}
}
예제 #3
0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	AUMixer3DView::SetRenderingAlgorithmControl
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void	AUMixer3DView::SetRenderingAlgorithmControl(int inAlgorithm )
{
	WindowRef window = GetCarbonWindow();
	
	ControlID controlID;
	controlID.signature = 'algo';
	controlID.id = 0;
	
	ControlRef control;
	OSStatus result = ::GetControlByID(window, &controlID, &control );

	if(result == noErr)
	{
		SetControlValue(control, inAlgorithm+1 );
		ShowControl(control);
	}
	
}
예제 #4
0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	AUDiskStreamingCheckbox::AUDiskStreamingCheckbox
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
AUDiskStreamingCheckbox::AUDiskStreamingCheckbox (AUCarbonViewBase *inBase, 
				Point 					inLocation,  
				ControlFontStyleRec & 	inFontStyle)
	: AUPropertyControl (inBase)
{
	Rect r;
	r.top = inLocation.v;		r.bottom = r.top;
	r.left = inLocation.h;		r.right = r.left;
	
    // localize as necessary
    if (!sLocalized) {
		sLocalized = true;
        CFBundleRef mainBundle = CFBundleGetBundleWithIdentifier(kLocalizedStringBundle_AUView);
        if (mainBundle) {
            kStringStreamFromDisk =	CFCopyLocalizedStringFromTableInBundle(
                                        kAUViewLocalizedStringKey_StreamFromDisk, kLocalizedStringTable_AUView,
                                        mainBundle, CFSTR("'Stream From Disk' checkbox title string"));
        }
    }
    
	verify_noerr(CreateCheckBoxControl(	GetCarbonWindow(), 
										&r, 
										kStringStreamFromDisk, 
										0, 
										true, 
										&mControl));
	verify_noerr (SetControlFontStyle (mControl, &inFontStyle));
	ControlSize smallSize = kControlSizeSmall;
	verify_noerr (SetControlData (mControl, kControlEntireControl, kControlSizeTag, sizeof (ControlSize), &smallSize));

	AUCarbonViewControl::SizeControlToFit(mControl, NULL, &mHeight);
	if (mHeight < 0) mHeight = 0;
	
	EmbedControl(mControl);
	
	UInt32 value = 0;
	UInt32 size = sizeof(value);
	verify_noerr (AudioUnitGetProperty (mView->GetEditAudioUnit(), kMusicDeviceProperty_StreamFromDisk, kAudioUnitScope_Global, 0, &value, &size));
	
	HandlePropertyChange (value);
	
	RegisterEvents();
}
예제 #5
0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	AUMixer3DView::CreateUI
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OSStatus	AUMixer3DView::CreateUI(Float32	inXOffset, Float32 	inYOffset)
{
	EventHandlerUPP  handlerUPP = NewEventHandlerUPP(MyEventHandlerDispatch);

	EventTypeSpec    eventTypes[] =
	{
		{kEventClassKeyboard, kEventRawKeyDown},
		{kEventClassKeyboard, kEventRawKeyRepeat},
		{kEventClassMouse, kEventMouseDown},
		{kEventClassMouse, kEventMouseUp},
		{kEventClassMouse, kEventMouseDragged},
		{kEventClassCommand, kEventCommandProcess},
		
		{kEventClassWindow, kEventWindowDrawContent},
		
		{kEventClassWindow, kEventWindowUpdate},
		
	};


	SizeControl(mCarbonPane, 400, 400);

	InstallWindowEventHandler( GetCarbonWindow(), handlerUPP, sizeof(eventTypes) / sizeof(EventTypeSpec), eventTypes, this, NULL);

	RGBColor color1;
	color1.red = 65535;
	color1.green = 0;
	color1.blue = 0;
	gTrackers[0] = new TrackingLine(color1, (int)inXOffset, (int)inYOffset, 400, 400);

	RGBColor color2;
	color2.red = 0;
	color2.green = 65535;
	color2.blue = 0;
	gTrackers[1]  = new TrackingLine(color2, (int)inXOffset, (int)inYOffset, 400, 400);
        
	RGBColor color3;
	color3.red = 0;
	color3.green = 0;
	color3.blue = 65535;
	gTrackers[2]  = new TrackingLine(color3, (int)inXOffset, (int)inYOffset, 400, 400);
        
	RGBColor color4;
	color4.red = 20000;
	color4.green = 20000;
	color4.blue = 20000;
	gListener  = new TrackingLine(color4, (int)inXOffset, (int)inYOffset, 400, 400);
	gListener->ScaleDistance(0.0);
	
	
	mOffsetX = (int)inXOffset;
	mOffsetY = (int)inYOffset;

	SetRenderingFlagsCheckboxes();


	UInt32 algo;
	UInt32 size = sizeof(algo);
	AudioUnitGetProperty(
		GetEditAudioUnit(),
		kAudioUnitProperty_SpatializationAlgorithm,
		kAudioUnitScope_Input,
		0,
		&algo,
		&size );

	SetRenderingAlgorithmControl(algo);

	mBackgroundColor.red = 50000;
	mBackgroundColor.green = 50000;
	mBackgroundColor.blue = 50000;
	
	TrackingLine::SetBackgroundColor(mBackgroundColor );
	
	mIsTrackingMouse = false;

	
	EventLoopTimerUPP timerUPP = ::NewEventLoopTimerUPP(MixerTimerProc);

//printf("timerUPP = %x\n", timerUPP );
	
	EventLoopTimerRef timerRef;
	EventLoopRef mainEventLoop = GetMainEventLoop();

//printf("mainEventLoop = %x\n", mainEventLoop);
//printf("this = %x\n", (int)this );

gAUMixer3DView = this;
	
	OSStatus timerResult =  ::InstallEventLoopTimer(
									mainEventLoop,
									0.005 /* delay */,
									0.020 /* interval */,
									timerUPP,
									this,
									&timerRef );                       

//printf("timerResult = %d\n", timerResult );
//printf("timerRef = %x\n", timerRef );
  
	return timerResult;
}
예제 #6
0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	MyEventHandler
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
OSStatus AUMixer3DView::MyEventHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent)
{
	OSStatus result = noErr;
	
	UInt32 eventClass = GetEventClass(inEvent);
	UInt32 eventKind = GetEventKind(inEvent);

	// draw event
	if(eventClass == kEventClassWindow)
	{
		if(eventKind == kEventWindowDrawContent ) 
		{
			Rect r = {mOffsetY, mOffsetX, mOffsetY + 400, mOffsetX + 400};
			RGBForeColor(&mBackgroundColor );
			PaintRect(&r);
	
			for(int i = 0; i < kNTrackers; i++)
			{
				gTrackers[i]->Draw();
			}
			
			gListener->Draw();
	
			
			return noErr;
		}
	}



	CGrafPtr gp = GetWindowPort(GetCarbonWindow());
	
	CGrafPtr save;
	GetPort(&save);
	SetPort(gp );



	const float kDistanceScale = 0.1 /*0.3*/;


/*
	k3DMixerRenderingFlags_InterAuralDelay			= (1L << 0),
	k3DMixerRenderingFlags_DopplerShift				= (1L << 1),
	k3DMixerRenderingFlags_DistanceAttenuation		= (1L << 2),
	k3DMixerRenderingFlags_DistanceFilter			= (1L << 3),
	k3DMixerRenderingFlags_DistanceDiffusion		= (1L << 4)
*/	
	if(eventClass == kEventClassCommand )
	{
		HICommand	command;
		GetEventParameter (inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &command);

		SInt16 value = ::GetControlValue((ControlRef)command.menu.menuRef );
	
		//char *p = ((char*)&command.commandID );
		//printf("%x command.commandID = %d : %d : %c%c%c%c\n", command.menu.menuRef, command.commandID, int(value), p[0],p[1],p[2],p[3] );

		
		if(command.commandID == 'algo' )
		{
			// set rendering algorithm
			
			UInt32 algo = value - 1;
			
			for(int i = 0; i < kNTrackers; i++)
			{
				AudioUnitSetProperty(
					GetEditAudioUnit(),
					kAudioUnitProperty_SpatializationAlgorithm,
					kAudioUnitScope_Input,
					i,
					&algo,
					sizeof(algo) );
			}
			
			// rendering flags have changed with setting of rendering algorithm
			SetRenderingFlagsCheckboxes();
		}
		else if(command.commandID == 'volm' )
		{
			Float32 s = float(value) / 100.0;
			s = s*s;
			
			if(s == 0.0)
			{
				s = -96.0;
			}
			else
			{
				s = 20.0 * log10(s);
			}
			//printf("volume = %f dB\n", s);

			// set master gain in dB
			AudioUnitSetParameter(GetEditAudioUnit(),
				k3DMixerParam_Gain,
				kAudioUnitScope_Output,
				0,
				s,
				0 );
			
		}
		else if(command.commandID == 'attn' )
		{
			// volume attenuation curve
			
			Float64 s = float(value) / 100.0;
			
			//printf("volume atten curve= %f\n", s);

			// volume attenuation curve follows the law:   1.0 / (1.0 + s *(distance - 1.0) )
			//
			// where distance is in meters, and s is generally between 0.1 and 1.0 (0.3 is good default)
			//
			// there is no attenuation if distance <= 1.0 meter

			for(int i = 0; i < kNTrackers; i++)
			{
				result = AudioUnitSetProperty(	GetEditAudioUnit(),
												kAudioUnitProperty_3DMixerDistanceAtten,
												kAudioUnitScope_Input,
												i,
												&s,
												sizeof(s) );
			}
		}
		else
		{
			UInt32 mask = 0;
			switch(command.commandID )
			{
				case 'atr0':
					mask = k3DMixerRenderingFlags_InterAuralDelay;
					break;
				case 'atr1':
					mask = k3DMixerRenderingFlags_DopplerShift;
					break;
				case 'atr2':
					mask = k3DMixerRenderingFlags_DistanceAttenuation;
					break;
				case 'atr3':
					mask = k3DMixerRenderingFlags_DistanceFilter;
					break;
				case 'atr4':
					mask = k3DMixerRenderingFlags_DistanceDiffusion;
					break;
				case 'rvrb':
				{
					UInt32 usesReverb = value;
					AudioUnitSetProperty(
						GetEditAudioUnit(),
						kAudioUnitProperty_UsesInternalReverb,
						kAudioUnitScope_Input,
						0,
						&usesReverb,
						sizeof(usesReverb) );
						
					break;
				}
			}
			
			if(mask != 0)
			{		
				for(int i = 0; i < kNTrackers; i++)
				{
					UInt32 flags;
					UInt32 size = sizeof(flags);
					
					AudioUnitGetProperty(
						GetEditAudioUnit(),
						kAudioUnitProperty_3DMixerRenderingFlags,
						kAudioUnitScope_Input,
						i,
						&flags,
						&size );
					
					if(value > 0)
					{
						flags |= mask;
					}
					else
					{
						flags &= ~mask;
					}
					
					AudioUnitSetProperty(
						GetEditAudioUnit(),
						kAudioUnitProperty_3DMixerRenderingFlags,
						kAudioUnitScope_Input,
						i,
						&flags,
						size );
				}
				
				return noErr;
			}
		}
		
		return eventNotHandledErr;
	}
	else		
	if(eventClass == kEventClassMouse )
	{

		HIPoint			mousePos;
		result =  GetEventParameter(  	inEvent,
										kEventParamMouseLocation,
										typeHIPoint,
										NULL,       /* can be NULL */
										sizeof(HIPoint),
										NULL,       /* can be NULL */
										&mousePos);

		UInt32	modifiers;
		result =  GetEventParameter(  	inEvent,
										kEventParamKeyModifiers,
										typeUInt32,
										NULL,       /* can be NULL */
										sizeof(UInt32),
										NULL,       /* can be NULL */
										&modifiers);
	
	
		Point pt;
		pt.h = short(mousePos.x);
		pt.v = short(mousePos.y);
		
		
		Rect r2 = GetPortBitMapForCopyBits(gp)->bounds;
		
		GlobalToLocal(&pt);
		pt.h -= mOffsetX;
		pt.v -= mOffsetY;	
		if(!mIsTrackingMouse && (pt.h < 0 || pt.v < 0) ) return eventNotHandledErr;

		// check for title bar
		if(pt.v < 0 && pt.v > -30 )
		{
			return eventNotHandledErr;
		}


		Rect r1;
		GetPortBounds(gp, &r1 );
		//int width = r1.right-r1.left;
		//int height = r1.bottom-r1.top;
		
		//!!@ hardcoded
		int width = 400;
		int height = 400;

		int centerx = int(0.5*width);
		int centery = int(0.5*height);
		
		static int currentLine = 0;
		
		float x = pt.h - centerx;
		float y = -(pt.v - centery);
		
		float rangle = atan2(x,y);
		float angle = 180.0 * rangle / 3.14159;
		
		static int hitx = 0;
		static int hity = 0;
		static float hitAngle = 0.0;


		switch(eventKind)
		{
			case kEventMouseDown:
			{
				mIsTrackingMouse = true;
				
				// determine the closest source

				float bestDistance = 100000.0;
				int bestIndex = 0;
				
				for(int i = 0; i < kNTrackers; i++)
				{
					if(gTrackers[i]->Distance(pt.h, pt.v) < bestDistance )
					{
						bestIndex = i;
						bestDistance = gTrackers[i]->Distance(pt.h, pt.v);
					}
				}
				
				if(modifiers & (1L << shiftKeyBit)) {
					
					Float32 gain;
					
					AudioUnitGetParameter(GetEditAudioUnit(),
							k3DMixerParam_Gain,
							kAudioUnitScope_Input,
							bestIndex,
							&gain);
					
					if (gain > -120)
						gain = -120;
					else
						gain = 0;
						
					AudioUnitSetParameter(GetEditAudioUnit(),
							k3DMixerParam_Gain,
							kAudioUnitScope_Input,
							bestIndex,
							gain,
							0);
				}

				currentLine = bestIndex;
				SetInput(currentLine);
				
				for(int i = 0; i < kNTrackers; i++)
				{
					if(i != currentLine) gTrackers[i]->Draw();
					gTrackers[i]->Anchor();
				}
				
				hitx = (int)x;
				hity = (int)y;
				hitAngle = angle;
			}
				
			case kEventMouseDragged:
			{
				if(modifiers & (1L << optionKeyBit) )
				{
					for(int i = 0; i < kNTrackers; i++)
					{
						float newAngle = gTrackers[i]->Rotate(angle - hitAngle );
						
						AudioUnitSetParameter(GetEditAudioUnit(),
							0 /* azimuth */,
							kAudioUnitScope_Input,
							i,
							newAngle,
							0 );
					}
					
					gListener->Draw();
				}
				else if(modifiers & (1L << cmdKeyBit) )
				{

					for(int i = 0; i < kNTrackers; i++)
					{
						float angle;
						float pixelDistance;
						
						gTrackers[i]->Offset(x-hitx, -(y-hity), angle, pixelDistance );

						
						float distance = kDistanceScale *  pixelDistance;
		
						AudioUnitSetParameter(GetEditAudioUnit(),
							0 /* azimuth */,
							kAudioUnitScope_Input,
							i,
							angle,
							0 );

						AudioUnitSetParameter(GetEditAudioUnit(),
							2 /* distance */,
							kAudioUnitScope_Input,
							i,
							distance,
							0 );
					}
					
					gListener->Draw();
				}
				else
				{
					TrackingLine *trackingLine = gTrackers[currentLine];
					
					if(trackingLine)
					{
						trackingLine->Track(pt.h, pt.v);
											
						for(int i = 0; i < kNTrackers; i++)
						{
							if(i != currentLine) gTrackers[i]->Draw();
							gTrackers[i]->Anchor();
						}
						
						gListener->Draw();
					}
					
					AudioUnitSetParameter(GetEditAudioUnit(),
						0 /* azimuth */,
						kAudioUnitScope_Input,
						currentLine,
						angle,
						0 );
					
					float distance = kDistanceScale *   sqrt( x*x + y*y);
	
					AudioUnitSetParameter(GetEditAudioUnit(),
						2 /* distance */,
						kAudioUnitScope_Input,
						currentLine,
						distance,
						0 );
				}
				
				break;
			}
		
			case kEventMouseUp:
				mIsTrackingMouse = false;
				break;
		
		}




		SetPort(save);

		return noErr;
	}
	else
	{
		UInt8			keyCode;
		result =  GetEventParameter(  	inEvent,
												kEventParamKeyMacCharCodes,
												typeChar,
												NULL,       /* can be NULL */
												sizeof(UInt8),
												NULL,       /* can be NULL */
												&keyCode);


#if 1
		switch(keyCode)
		{
			case 'q':
				SetFileInput(0);
				break;

			case 'w':
				SetFileInput(1);
				break;

			case 'e':
				SetFileInput(2);
				break;

			case 'r':
				SetFileInput(3);
				break;

			case 't':
				SetFileInput(4);
				break;

			case 'y':
				SetFileInput(5);
				break;

			case 'u':
				SetFileInput(6);
				break;
				
			case 'i':
				SetFileInput(7);
				break;
				
			case 'o':
				SetFileInput(8);
				break;
				
			case 'p':
				SetFileInput(9);
				break;
				
			case 'a':
				SetFileInput(10);
				break;
				
			case 's':
				SetFileInput(11);
				break;
				
			case 'd':
				SetFileInput(12);
				break;
								
			default:
				break;
		
		}
#endif

		SetPort(save);
		return noErr;
	}
	
	return eventNotHandledErr;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	AURenderQualityPopup::AURenderQualityPopup
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
AURenderQualityPopup::AURenderQualityPopup (AUCarbonViewBase *inBase, 
				Point 					inLocation, 
				int 					inRightEdge, 
				ControlFontStyleRec & 	inFontStyle)
	: AUPropertyControl (inBase)
{
	Rect r;
	r.top = inLocation.v;		r.bottom = r.top + 17;
	r.left = inLocation.h;		r.right = r.left + inRightEdge;
	
	ControlFontStyleRec fontStyle = inFontStyle;
	inFontStyle.just = teFlushRight;

	ControlRef			ref;
		
	CFBundleRef mainBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.audio.units.Components"));
	if (mainBundle != NULL) {
		CFMutableStringRef renderTitle = CFStringCreateMutable(NULL, 0);
		CFStringAppend(renderTitle, CFCopyLocalizedStringFromTableInBundle(
			CFSTR("Render Quality"), CFSTR("CustomUI"), mainBundle,
			CFSTR("The Render Quality Popup menu title")));
		CFStringAppend(renderTitle, CFSTR(":"));
	
		OSErr theErr =  CreateStaticTextControl (GetCarbonWindow(), &r, renderTitle, &inFontStyle, &ref);
		if (theErr == noErr)
			EmbedControl(ref);
		
		r.left = r.right + 8;
		r.right = r.left + 100;

		short bundleRef = CFBundleOpenBundleResourceMap (mainBundle);
		
		theErr = CreatePopupButtonControl (mView->GetCarbonWindow(), &r, NULL,
			/*kQualityMenuID*/ -12345, false, -1, 0, 0, &mControl);	
			
		MenuRef menuRef;
		verify_noerr(CreateNewMenu(kQualityMenuID, 0, &menuRef));
		
		verify_noerr(AppendMenuItemTextWithCFString (menuRef, CFCopyLocalizedStringFromTableInBundle(CFSTR("Maximum"), CFSTR("CustomUI"), mainBundle, CFSTR("")), 0, kChangeRenderQualityCmd, 0));
		verify_noerr(AppendMenuItemTextWithCFString (menuRef, CFCopyLocalizedStringFromTableInBundle(CFSTR("High"), CFSTR("CustomUI"), mainBundle, CFSTR("")), 0, kChangeRenderQualityCmd, 0));
		verify_noerr(AppendMenuItemTextWithCFString (menuRef, CFCopyLocalizedStringFromTableInBundle(CFSTR("Medium"), CFSTR("CustomUI"), mainBundle, CFSTR("")), 0, kChangeRenderQualityCmd, 0));
		verify_noerr(AppendMenuItemTextWithCFString (menuRef, CFCopyLocalizedStringFromTableInBundle(CFSTR("Low"), CFSTR("CustomUI"), mainBundle, CFSTR("")), 0, kChangeRenderQualityCmd, 0));
		verify_noerr(AppendMenuItemTextWithCFString (menuRef, CFCopyLocalizedStringFromTableInBundle(CFSTR("Minimum"), CFSTR("CustomUI"), mainBundle, CFSTR("")), 0, kChangeRenderQualityCmd, 0));
																
		verify_noerr(SetControlData(mControl, 0, kControlPopupButtonMenuRefTag, sizeof(menuRef), &menuRef));
					
		verify_noerr(SetControlFontStyle (mControl, &inFontStyle));
			
		SetControl32BitMaximum(mControl, 5);
		UInt32 renderQuality;
		UInt32 size = sizeof(UInt32);
		AudioUnitGetProperty (mView->GetEditAudioUnit(), 
							kAudioUnitProperty_RenderQuality,
							kAudioUnitScope_Global, 
							0, 
							&renderQuality, 
							&size);
							
		HandlePropertyChange(renderQuality);

		EmbedControl(mControl);
		theErr = AudioUnitAddPropertyListener(mView->GetEditAudioUnit(), kAudioUnitProperty_RenderQuality, RenderQualityListener, this);
		CFBundleCloseBundleResourceMap (mainBundle, bundleRef);
		CFRelease(renderTitle);
	}
	RegisterEvents();
}