Ejemplo n.º 1
0
 EngineChannel::~EngineChannel() {
     DisconnectAudioOutputDevice();
     // In case the channel was removed before the instrument was
     // fully loaded, try to give back instrument again (see bug #113)
     InstrumentChangeCmd< ::gig::DimensionRegion, ::gig::Instrument>& cmd = ChangeInstrument(NULL);
     if (cmd.pInstrument) {
         Engine::instruments.HandBack(cmd.pInstrument, this);
     }
     ///////
 }
Ejemplo n.º 2
0
    /**
     * Load an instrument from a .gig file. PrepareLoadInstrument() has to
     * be called first to provide the information which instrument to load.
     * This method will then actually start to load the instrument and block
     * the calling thread until loading was completed.
     *
     * @see PrepareLoadInstrument()
     */
    void EngineChannel::LoadInstrument() {
        InstrumentResourceManager* pInstrumentManager = dynamic_cast<InstrumentResourceManager*>(pEngine->GetInstrumentManager());

        // make sure we don't trigger any new notes with an old
        // instrument
        InstrumentChangeCmd< ::gig::DimensionRegion, ::gig::Instrument>& cmd = ChangeInstrument(0);
        if (cmd.pInstrument) {
            // give old instrument back to instrument manager, but
            // keep the dimension regions and samples that are in use
            pInstrumentManager->HandBackInstrument(cmd.pInstrument, this, cmd.pRegionsInUse);
        }
        if (cmd.pScript) {
            // give old instrument script back to instrument resource manager
            cmd.pScript->resetAll();
        }
        cmd.pRegionsInUse->clear();

        // delete all key groups
        DeleteGroupEventLists();

        // request gig instrument from instrument manager
        ::gig::Instrument* newInstrument;
        try {
            InstrumentManager::instrument_id_t instrid;
            instrid.FileName  = InstrumentFile;
            instrid.Index     = InstrumentIdx;

            newInstrument = pInstrumentManager->Borrow(instrid, this);
            if (!newInstrument) {
                throw InstrumentManagerException("resource was not created");
            }

            if (newInstrument->ScriptSlotCount() > 1) {
                std::cerr << "WARNING: Executing more than one real-time instrument script slot is not implemented yet!\n";
            }
            ::gig::Script* script = newInstrument->GetScriptOfSlot(0);
            if (script) {
                String sourceCode = script->GetScriptAsText();
                LoadInstrumentScript(sourceCode);
            }
        }
        catch (RIFF::Exception e) {
            InstrumentStat = -2;
            StatusChanged(true);
            String msg = "gig::Engine error: Failed to load instrument, cause: " + e.Message;
            throw Exception(msg);
        }
        catch (InstrumentManagerException e) {
            InstrumentStat = -3;
            StatusChanged(true);
            String msg = "gig::Engine error: Failed to load instrument, cause: " + e.Message();
            throw Exception(msg);
        }
        catch (...) {
            InstrumentStat = -4;
            StatusChanged(true);
            throw Exception("gig::Engine error: Failed to load instrument, cause: Unknown exception while trying to parse gig file.");
        }

        RoundRobinIndex = 0;
        for (int i = 0 ; i < 128 ; i++) pMIDIKeyInfo[i].pRoundRobinIndex = NULL;

        // rebuild ActiveKeyGroups map with key groups of current
        // instrument and set the round robin pointers to use one
        // counter for each region
        int region = 0;
        for (::gig::Region* pRegion = newInstrument->GetFirstRegion(); pRegion; pRegion = newInstrument->GetNextRegion()) {
            AddGroup(pRegion->KeyGroup);

            RoundRobinIndexes[region] = 0;
            for (int iKey = pRegion->KeyRange.low; iKey <= pRegion->KeyRange.high; iKey++) {
                pMIDIKeyInfo[iKey].pRoundRobinIndex = &RoundRobinIndexes[region];
            }
            region++;
        }

        InstrumentIdxName = newInstrument->pInfo->Name;
        InstrumentStat = 100;

        {
            InstrumentChangeCmd< ::gig::DimensionRegion, ::gig::Instrument>& cmd =
                ChangeInstrument(newInstrument);
            if (cmd.pScript) {
                // give old instrument script back to instrument resource manager
                cmd.pScript->resetAll();
            }
        }

        StatusChanged(true);
    }
Ejemplo n.º 3
0
OSStatus ComboBoxHandler(EventHandlerCallRef next,
                         EventRef event, void *data)
{
    WindowRef window;
    HIViewRef combo;
    CFIndex index;
    UInt32 id;

    // Get the window
    
    window = ActiveNonFloatingWindow();

    // Get the control

    GetEventParameter(event, kEventParamDirectObject,
                      typeControlRef, NULL, sizeof(combo),
                      NULL, &combo);

    // Get the index

    GetEventParameter(event, kEventParamComboBoxListSelectedItemIndex,
                      typeCFIndex, NULL, sizeof(index),
                      NULL, &index);

    // Get the command id

    HIViewGetCommandID(combo, &id);

    // Switch on the command id
        
    switch (id)
    {
        // Instrument

    case kCommandInst:
        instrument = index;
        ChangeInstrument(instrument);
        break;

        // Key

    case kCommandKey:
        key = index;
	type = types[key];
	ChangeDisplay();
        break;

        // Something else

    default:
        return eventNotHandledErr;
    }

    // Clear the keyboard focus, otherwise the focus stays on the
    // combo box and makes it drop down when the user presses a key

    ClearKeyboardFocus(window);

    // Report success

    return noErr;
}
Ejemplo n.º 4
0
int main(int argc, char *argv[])
{
    WindowRef window;
    HIViewRef content;
    HIViewRef combo;
    HIViewRef group;
    HIViewRef check;
    HIViewRef text;
    HIViewRef slider;
    HIViewRef quit;

    MenuRef menu;
    HIRect rect;

    // Window bounds

    Rect bounds = {0, 0, 436, 590};

    // Create window

    CreateNewWindow(kDocumentWindowClass,
                    kWindowStandardFloatingAttributes |
                    kWindowStandardHandlerAttribute |
		    kWindowInWindowMenuAttribute |
                    kWindowCompositingAttribute,
                    &bounds, &window);

    // Set the title

    SetWindowTitleWithCFString(window, CFSTR("Accordion"));

    // Create an application menu

    CreateNewMenu(0, 0, &menu);

    // Set menu title

    SetMenuTitleWithCFString(menu,
	CFStringCreateWithPascalString(kCFAllocatorDefault,
                                       "\p\024",
                                       kCFStringEncodingMacRoman));
    // Create an about item

    InsertMenuItemTextWithCFString(menu, CFSTR("About Accordion"),
                                   0, 0, kHICommandAbout);

    // Insert the menu

    InsertMenu(menu, 0);

    // Create a standard window menu

    CreateStandardWindowMenu(0, &menu);

    // Insert the menu

    InsertMenu(menu, 0);

    // Show and position the window

    ShowWindow(window);
    RepositionWindow(window, NULL, kWindowCascadeOnMainScreen);

    // Find the window content

    HIViewFindByID(HIViewGetRoot(window),
                   kHIViewWindowContentID,
                   &content);

    // Set bounds for group box

    bounds.bottom = 92;
    bounds.right  = 550;

    // Create group box

    CreateGroupBoxControl(window, &bounds, NULL, true, &group);

    // Place in the window

    HIViewAddSubview(content, group);
    HIViewPlaceInSuperviewAt(group, 20, 20);

    // Bounds of text

    bounds.bottom = 16;
    bounds.right = 74;

    // Create static text

    CreateStaticTextControl(window, &bounds, CFSTR("Instrument:"),
			    NULL, &text);

    // Place in the group box

    HIViewAddSubview(group, text);
    HIViewPlaceInSuperviewAt(text, 16, 18);

    // Bounds of combo box

    rect.size.height = 20;
    rect.size.width = 168;    

    // Create combo box

    HIComboBoxCreate(&rect, CFSTR(" Accordion"), NULL, NULL,
                     kHIComboBoxStandardAttributes,
                     &combo);

    // Set visible and set command ID

    HIViewSetVisible(combo, true);
    HIViewSetCommandID(combo, kCommandInst); 

    // Add the instruments

    for (int i = 0; i < Length(instruments); i++)
    {
        HIComboBoxAppendTextItem(combo,
            CFStringCreateWithCString(kCFAllocatorDefault,
                                      instruments[i],
                                      kCFStringEncodingMacRoman), NULL);

        // Set the current instrument

        if (strcmp(instruments[i], " Accordion") == 0)
            instrument = i;
    }

    // Place in the group box

    HIViewAddSubview(group, combo);
    HIViewPlaceInSuperviewAt(combo, 102, 16);

    // Bounds of check box

    bounds.bottom = 18;
    bounds.right = 121;

    // Create check box

    CreateCheckBoxControl(window, &bounds, CFSTR("Reverse"),
                          false, true, &check);

    // Set the control ID and the command ID

    HIViewSetID(check, kHIViewIDReverse);
    HIViewSetCommandID(check, kCommandReverse); 

    // Place in the group box

    HIViewAddSubview(group, check);
    HIViewPlaceInSuperviewAt(check, 286, 17);

    // Bounds of text

    bounds.bottom = 16;
    bounds.right  = 32;

    // Create static text

    CreateStaticTextControl(window, &bounds, CFSTR("Key:"), NULL, &text);

    // Place in the group box

    HIViewAddSubview(group, text);
    HIViewPlaceInSuperviewAt(text, 400, 18);

    // Bounds of combo box

    rect.size.width = 90;

    // Create combo box

    HIComboBoxCreate(&rect, CFSTR(" A/D/G"), NULL, NULL,
                     kHIComboBoxStandardAttributes,
                     &combo);

    // Set visible and set command ID

    HIViewSetVisible(combo, true);
    HIViewSetID(combo, kHIViewIDKey);
    HIViewSetCommandID(combo, kCommandKey); 

    // Add keys

    for (int i = 0; i < Length(keys); i++)
    {
        HIComboBoxAppendTextItem(combo,
            CFStringCreateWithCString(kCFAllocatorDefault,
                                      keys[i],
                                      kCFStringEncodingMacRoman), NULL);

        // Set current key

        if (strcmp(keys[i], " A/D/G") == 0)
            key = i;
    }

    // Place in the group box

    HIViewAddSubview(group, combo);
    HIViewPlaceInSuperviewAt(combo, 440, 16);

    // Bounds of text

    bounds.bottom = 16;
    bounds.right  = 54;

    // Create static text

    CreateStaticTextControl(window, &bounds, CFSTR("Volume:"), NULL, &text);

    // Place in the group box

    HIViewAddSubview(group, text);
    HIViewPlaceInSuperviewAt(text, 16, 56);
    
    // Bounds of slider

    bounds.bottom = 16;
    bounds.right  = 168;

    // Create slider

    CreateSliderControl(window, &bounds, MAXVOL, 0, MAXVOL,
                        kControlSliderDoesNotPoint, 0, false, NULL, &slider);

    // Set command ID

    HIViewSetCommandID(slider, kCommandVolume); 

    // Place in the group box

    HIViewAddSubview(group, slider);
    HIViewPlaceInSuperviewAt(slider, 100, 58);

    // Bounds of check box

    bounds.bottom = 18;
    bounds.right = 121;

    // Create check box

    CreateCheckBoxControl(window, &bounds, CFSTR("Notes"),
                          false, true, &check);

    // Set the control ID and the command ID

    HIViewSetID(check, kHIViewIDNote);
    HIViewSetCommandID(check, kCommandNote); 

    // Place in the group box

    HIViewAddSubview(group, check);
    HIViewPlaceInSuperviewAt(check, 286, 56);

    // Bounds of push button

    bounds.bottom = 20;
    bounds.right  = 90;

    // Create push button

    CreatePushButtonControl(window, &bounds, CFSTR("Quit"), &quit);

    // Set command ID

    HIViewSetCommandID(quit, kHICommandQuit); 

    // Place in the group box

    HIViewAddSubview(group, quit);
    HIViewPlaceInSuperviewAt(quit, 440, 54);

    // Group box bounds

    bounds.bottom = 48;
    bounds.right  = 550;

    // Create group box

    CreateGroupBoxControl(window, &bounds, NULL, true, &group);

    // Place in the window

    HIViewAddSubview(content, group);
    HIViewPlaceInSuperviewAt(group, 20, 132);

    // Font style

    ControlFontStyleRec style;
    style.flags = kControlUseFontMask|kControlUseJustMask;
    style.font = kControlFontBigSystemFont;
    style.just = teCenter;

    // Bounds of text
    
    bounds.bottom = 16;
    bounds.right  = 550;

    // Create static text

    CreateStaticTextControl(window, &bounds, CFSTR("Accordion"),
                            &style, &text);

    // Place in the group box

    HIViewAddSubview(group, text);
    HIViewPlaceInSuperviewAt(text, 0, 8);

    // Bounds of text

    bounds.bottom = 16;
    bounds.right  = 550;

    // Create static text

    CreateStaticTextControl(window, &bounds,
                            CFSTR("Play accordion on your keyboard"),
                            &style, &text);

    // Place in the group box

    HIViewAddSubview(group, text);
    HIViewPlaceInSuperviewAt(text, 0, 24);

    // Group box bounds

    bounds.bottom = 196;
    bounds.right  = 550;

    // Create group box

    CreateGroupBoxControl(window, &bounds, NULL, true, &group);

    // Place in the window

    HIViewAddSubview(content, group);
    HIViewPlaceInSuperviewAt(group, 20, 200);

    // Button bounds

    bounds.bottom = SIZE;
    bounds.right  = SIZE;

    // Create row of bass buttons

    for (int i = 0; i < Length(bassdisplay); i++)
    {
	int x = 15 + 44 * i;
	int y = 15;

	// Create button

	CreateBevelButtonControl(window, &bounds, NULL,
				 kControlBevelButtonNormalBevel,
				 kControlBehaviorPushbutton,
				 NULL, 0, 0, 0, &bassdisplay[i]);

	// Place in the group box

	HIViewAddSubview(group, bassdisplay[i]);
	HIViewPlaceInSuperviewAt(bassdisplay[i], x, y);
    }

    // Create three rows of buttons

    for (int i = 0; i < Length(display); i++)
    {
	for (int j = 0; j < ((i == 1)? Length(display[i]):
			 Length(display[i]) - 1); j++)
	{
	    int x = (i == 1)? 37 + 44 * j: 59 + 44 * j;
	    int y = 59 + 44 * i;

	    // Create button

	    CreateBevelButtonControl(window, &bounds, NULL,
				     kControlBevelButtonNormalBevel,
				     kControlBehaviorPushbutton,
				     NULL, 0, 0, 0, &display[i][j]);

	    // Place in the group box

	    HIViewAddSubview(group, display[i][j]);
	    HIViewPlaceInSuperviewAt(display[i][j], x, y);
        }
    }

    // Create spacebar button

    CreateBevelButtonControl(window, &bounds, NULL,
			     kControlBevelButtonNormalBevel,
			     kControlBehaviorPushbutton,
			     NULL, 0, 0, 0, &spacebar);

    // Place in the group box

    HIViewAddSubview(group, spacebar);
    HIViewPlaceInSuperviewAt(spacebar, 16, 147);

    // Group box bounds, wider than the window to hide rounded corners

    bounds.bottom = 20;
    bounds.right = 598;

    // Create group box for fake status bar

    CreateGroupBoxControl(window, &bounds, NULL, false, &group);

    // Place in window at negative offset to hide rounded corners

    HIViewAddSubview(content, group);
    HIViewPlaceInSuperviewAt(group, -4, 416);

    // Text bounds

    bounds.bottom = 16;
    bounds.right  = 590;

    // Font style

    style.flags = kControlUseFontMask|kControlUseJustMask;
    style.font = kControlFontSmallSystemFont;
    style.just = teCenter;

    // Create static text

    CreateStaticTextControl(window, &bounds,
        CFSTR("Press the keyboard keys as accordion buttons "
              "and the space bar as the bellows. 3rd button start."),
                            &style, &text);

    // Place in group box

    HIViewAddSubview(group, text);
    HIViewPlaceInSuperviewAt(text, 0, 2);

    // Application events type spec

    EventTypeSpec applicationEvents[] =
        {{kEventClassApplication, kEventAppFrontSwitched}};

    // Install event handler

    InstallApplicationEventHandler(NewEventHandlerUPP(ApplicationHandler),
                                   Length(applicationEvents), applicationEvents,
                                   NULL, NULL);

    // Mouse events type spec

    EventTypeSpec mouseEvents[] =
	{{kEventClassMouse, kEventMouseDown}};

    // Install event handler on the event dispatcher, so that we can
    // see mouse events before the default handler gets them

    InstallEventHandler(GetEventDispatcherTarget(),
                        NewEventHandlerUPP(MouseHandler),
                        Length(mouseEvents), mouseEvents,
                        NULL, NULL);

    // Window events type spec

    EventTypeSpec windowEvents[] =
        {{kEventClassWindow, kEventWindowClose}};

    // Install event handler

    InstallWindowEventHandler(window, NewEventHandlerUPP(WindowHandler),
                              Length(windowEvents), windowEvents,
                              NULL, NULL);

    // Combo box events type spec

    EventTypeSpec comboBoxEvents[] =
        {{kEventClassHIComboBox, kEventComboBoxListItemSelected}};

    // Install event handler

    InstallApplicationEventHandler(NewEventHandlerUPP(ComboBoxHandler),
                                   Length(comboBoxEvents), comboBoxEvents,
                                   NULL, NULL);

    // Command events type spec

    EventTypeSpec commandEvents[] =
        {{kEventClassCommand, kEventCommandProcess}};

    // Install event handler

    InstallApplicationEventHandler(NewEventHandlerUPP(CommandHandler),
                                   Length(commandEvents), commandEvents,
                                   NULL, NULL);

    // Keyboard events type spec

    EventTypeSpec keyboardEvents[] =
        {{kEventClassKeyboard, kEventRawKeyDown},
         {kEventClassKeyboard, kEventRawKeyUp},
         {kEventClassKeyboard, kEventRawKeyModifiersChanged}};

    // Install event handler on the event dispatcher

    InstallEventHandler(GetEventDispatcherTarget(),
			NewEventHandlerUPP(KeyboardHandler),
			Length(keyboardEvents), keyboardEvents,
			NULL, NULL);

    // Audio Unit graph

    AUGraph graph;

    // Audio Unit synthesizer and output node

    AUNode synthNode;
    AUNode outNode;

    // Component description

    ComponentDescription cd;
    cd.componentManufacturer = kAudioUnitManufacturer_Apple;
    cd.componentFlags = 0;
    cd.componentFlagsMask = 0;

    do
    {
	// New AU graph

	OSStatus status = NewAUGraph(&graph);

	if (status != noErr)
	{
	    DisplayAlert(CFSTR("NewAUGraph"), 
			 CFSTR("Can't create a new AUGraph"),
			 status);
	    break;
	}

	// Synthesizer

	cd.componentType = kAudioUnitType_MusicDevice;
	cd.componentSubType = kAudioUnitSubType_DLSSynth;

	// New synthesizer node

	status = AUGraphNewNode(graph, &cd, 0, NULL, &synthNode);

	if (status != noErr)
	{
	    DisplayAlert(CFSTR("AUGraphNewNode"), 
			 CFSTR("Can't create a new  AUGraph node"),
			 status);
	    break;
	}

	// Output

	cd.componentType = kAudioUnitType_Output;
	cd.componentSubType = kAudioUnitSubType_DefaultOutput;
 
	// New output node

	status = AUGraphNewNode(graph, &cd, 0, NULL, &outNode);

	if (status != noErr)
	{
	    DisplayAlert(CFSTR("AUGraphNewNode"), 
			 CFSTR("Can't create a new  AUGraph node"),
			 status);
	    break;
	}

	// Open graph

	status = AUGraphOpen(graph);

	if (status != noErr)
	{
	    DisplayAlert(CFSTR("AUGraphOpen"), 
			 CFSTR("Can't open AUGraph"),
			 status);
	    break;
	}

	// Connect synthesizer node to output node

	status = AUGraphConnectNodeInput(graph, synthNode, 0, outNode, 0);

	if (status != noErr)
	{
	    DisplayAlert(CFSTR("AUGraphConnectNodeInput"), 
			 CFSTR("Can't connect AUGraph input node"),
			 status);
	    break;
	}

	// Get a synthesizer unit

	status =
	    AUGraphGetNodeInfo(graph, synthNode, NULL, 0, NULL, &synthUnit);

	if (status != noErr)
	{
	    DisplayAlert(CFSTR("AUGraphGetNodeInfo"), 
			 CFSTR("Can't get AUGraph node info"),
			 status);
	    break;
	}

	// Initialise

	status = AUGraphInitialize(graph);

	if (status != noErr)
	{
	    DisplayAlert(CFSTR("AUGraphInitialize"), 
			 CFSTR("Can't initialize AUGraph"),
			 status);
	    break;
	}

	// Start

	status = AUGraphStart(graph);

	if (status != noErr)
	{
	    DisplayAlert(CFSTR("AUGraphStart"), 
			 CFSTR("Can't start AUGraph"),
			 status);
	    break;
	}

	// Show the graph

	//     CAShow(graph);

    } while (false);

    // Change instrument

    ChangeInstrument(instrument);

    // Run the application event loop

    RunApplicationEventLoop();

    // Stop the graph

    AUGraphStop(graph);

    // Dispose of the graph

    DisposeAUGraph(graph);

    // Exit

    return 0;
}
Ejemplo n.º 5
0
    /**
     * Load an instrument from a .sf2 file. PrepareLoadInstrument() has to
     * be called first to provide the information which instrument to load.
     * This method will then actually start to load the instrument and block
     * the calling thread until loading was completed.
     *
     * @see PrepareLoadInstrument()
     */
    void EngineChannel::LoadInstrument() {
        InstrumentResourceManager* pInstrumentManager = dynamic_cast<InstrumentResourceManager*>(pEngine->GetInstrumentManager());

        // make sure we don't trigger any new notes with an old
        // instrument
        InstrumentChangeCmd< ::sf2::Region, ::sf2::Preset>& cmd = ChangeInstrument(0);
        if (cmd.pInstrument) {
            // give old instrument back to instrument manager, but
            // keep the dimension regions and samples that are in use
            pInstrumentManager->HandBackInstrument(cmd.pInstrument, this, cmd.pRegionsInUse);
        }
        cmd.pRegionsInUse->clear();

        // delete all key groups
        DeleteGroupEventLists();

        // request sf2 instrument from instrument manager
        ::sf2::Preset* newInstrument;
        try {
            InstrumentManager::instrument_id_t instrid;
            instrid.FileName  = InstrumentFile;
            instrid.Index     = InstrumentIdx;

            newInstrument = pInstrumentManager->Borrow(instrid, this);
            if (!newInstrument) {
                throw InstrumentManagerException("resource was not created");
            }
        }
        catch (InstrumentManagerException e) {
            InstrumentStat = -3;
            StatusChanged(true);
            String msg = "sf2::Engine error: Failed to load instrument, cause: " + e.Message();
            throw Exception(msg);
        }
        catch (::sf2::Exception e) {
            InstrumentStat = -3;
            StatusChanged(true);
            String msg = "sf2::Engine error: Failed to load instrument, cause: " + e.Message;
            throw Exception(msg);
        }
        catch (::std::runtime_error e) {
            InstrumentStat = -3;
            StatusChanged(true);
            String msg = "sf2::Engine error: Failed to load instrument, cause: ";
            msg += e.what();
            throw Exception(msg);
        }
        catch (...) {
            InstrumentStat = -4;
            StatusChanged(true);
            throw Exception("sf2::Engine error: Failed to load instrument, cause: Unknown exception while trying to parse sf2 file.");
        }

        // rebuild ActiveKeyGroups map with key groups of current instrument
        for (int i = 0 ; i < newInstrument->GetRegionCount() ; i++) {
            ::sf2::Region* pRegion = newInstrument->GetRegion(i);
            for (int j = 0 ; j < pRegion->pInstrument->GetRegionCount() ; j++) {
                ::sf2::Region* pSubRegion = pRegion->pInstrument->GetRegion(j);
                AddGroup(pSubRegion->exclusiveClass);
            }
        }

        InstrumentIdxName = newInstrument->GetName();
        InstrumentStat = 100;

        ChangeInstrument(newInstrument);

        StatusChanged(true);
    }