void openQuicktimeMIDIPort(void) {
	ComponentResult err;
	NoteRequest nr;
	NoteChannel nc;
	int i;
	short shortpoly;
	Fixed fixedtypical;
	
	closeQuicktimeMIDIPort();
	na = OpenDefaultComponent('nota', 0);
	if (!na) return;

	for (i = 0; i < 16; i++) {
		shortpoly = CFSwapInt16HostToBig(11);
		memcpy(&nr.info.polyphony,&shortpoly,2);			/* max simultaneous tones */
		fixedtypical = CFSwapInt32HostToBig(0x00010000);
		memcpy(&nr.info.typicalPolyphony,&fixedtypical,4);

		NAStuffToneDescription(na, 1, &nr.tone);
		err = NANewNoteChannel(na, &nr, &nc);
		if (err || !nc) {
			closeQuicktimeMIDIPort();
			return;
		}
		NAResetNoteChannel(na, nc);
		NASetInstrumentNumber(na, nc, channelInstrument[i]);
		channel[i] = nc;
	}
	state = idle;
	argByte1 = 0;
	argByte2 = 0;
	lastCmdByte = nil;
	return;
}
static void qt_play_event(void *p)
{
	MidiEvent *ev = (MidiEvent *)p;
	int ch, i;

	ch = ev->channel;
	switch(ev->type)
	{
	case ME_NOTEON:
		if(play_system_mode == XG_SYSTEM_MODE && channel[ch].bank_msb == 127
			&& ev->a >= XG_DRUM_VOICE_FIRST_NOTE && ev->a <= XG_DRUM_VOICE_LAST_NOTE){
			int a = ev->a - XG_DRUM_VOICE_FIRST_NOTE;
			a = xg_drum_voice[a][1];
			NAPlayNote(gNoteAllocator, note_channel[ch], a, ev->b);
			qt_ctl_note_event(ch, ev->a, ev->b);
		}
		else if(play_system_mode == XG_SYSTEM_MODE && channel[ch].bank_msb == 126){
			NAPlayNote(gNoteAllocator, note_channel[ch], ev->a, ev->b);
			qt_ctl_note_event(ch, ev->a, ev->b);
		}
		else {
			NAPlayNote(gNoteAllocator, note_channel[ch], ev->a, ev->b);
			qt_ctl_note_event(ch, ev->a, ev->b);
		}
		break;
	case ME_NOTEOFF:
		if(play_system_mode == XG_SYSTEM_MODE && channel[ch].bank_msb == 127
			&& ev->a >= XG_DRUM_VOICE_FIRST_NOTE && ev->a <= XG_DRUM_VOICE_LAST_NOTE){
			int a = ev->a - XG_DRUM_VOICE_FIRST_NOTE;
			a = xg_drum_voice[a][1];
			NAPlayNote(gNoteAllocator, note_channel[ch], a, 0);
			qt_ctl_note_event(ch, ev->a, 0);
		}
		else if(play_system_mode == XG_SYSTEM_MODE && channel[ch].bank_msb == 126){
			NAPlayNote(gNoteAllocator, note_channel[ch], ev->a, 0);
			qt_ctl_note_event(ch, ev->a, 0);
		}
		else {
			NAPlayNote(gNoteAllocator, note_channel[ch], ev->a, 0);
			qt_ctl_note_event(ch, ev->a, 0);
		}
		break;
	case ME_PROGRAM:
		set_instrument(ev);
		break;
	/* MIDI Events */
	case ME_KEYPRESSURE:
	case ME_CHANNEL_PRESSURE:
		NASetController(gNoteAllocator, note_channel[ch], kControllerAfterTouch, ev->a<<8);
		break;
	case ME_PITCHWHEEL:
		// kControllerPitchBend 256/halfnote
		i = (ev->b<<7) + ev->a - 0x2000;
		i *= (bend_sense[ch]<<1);
		i += (i > 0 ? (1<<12) : -(1<<12));
		i >>= 13;
		NASetController(gNoteAllocator, note_channel[ch], kControllerPitchBend, i);
		break;
	/* Controls */
	case ME_TONE_BANK_LSB:
		channel[ch].bank_lsb = ev->a;
		break;
	case ME_TONE_BANK_MSB:
		channel[ch].bank_msb = ev->a;
		if(play_system_mode == XG_SYSTEM_MODE && (ev->a == 126 || ev->a == 127) && !drum_part[ch])
			drum_part[ch] = true;
		break;
	case ME_MODULATION_WHEEL:
		NASetController(gNoteAllocator, note_channel[ch], kControllerModulationWheel, ev->a);
		break;
	case ME_BREATH:
		NASetController(gNoteAllocator, note_channel[ch], kControllerBreath, ev->a<<8);
		break;
	case ME_FOOT:
		NASetController(gNoteAllocator, note_channel[ch], kControllerFoot, ev->a<<8);
		break;
	case ME_BALANCE:
		NASetController(gNoteAllocator, note_channel[ch], kControllerBalance, ev->a<<8);
		break;
	case ME_MAINVOLUME:
		NASetController(gNoteAllocator, note_channel[ch], kControllerVolume, ev->a<<8);
		break;
	case ME_PAN:
		// kControllerPan 256-512
		NASetController(gNoteAllocator, note_channel[ch], kControllerPan, (ev->a<<1) + 256);
		ctl_mode_event(CTLE_PANNING, 1, ch, ev->a);
		break;
	case ME_EXPRESSION:
		NASetController(gNoteAllocator, note_channel[ch], kControllerExpression, ev->a<<8);
		ctl_mode_event(CTLE_EXPRESSION, 1, ch, ev->a);
		break;
	case ME_SUSTAIN:
		// kControllerSustain on/off only
		NASetController(gNoteAllocator, note_channel[ch], kControllerSustain, ev->a<<8);
		ctl_mode_event(CTLE_SUSTAIN, 1, ch, ev->a);
		break;
	case ME_PORTAMENTO_TIME_MSB:
	    channel[ch].portamento_time_msb = ev->a;
		NASetController(gNoteAllocator, note_channel[ch], kControllerPortamentoTime,
			(channel[ch].portamento_time_msb + (channel[ch].portamento_time_lsb<<7))<<1);
		break;
	case ME_PORTAMENTO_TIME_LSB:
	    channel[ch].portamento_time_lsb = ev->a;
		NASetController(gNoteAllocator, note_channel[ch], kControllerPortamentoTime,
			(channel[ch].portamento_time_msb + (channel[ch].portamento_time_lsb<<7))<<1);
		break;
	case ME_PORTAMENTO:
		NASetController(gNoteAllocator, note_channel[ch], kControllerPortamento, ev->a<<8);
		break;
	case ME_DATA_ENTRY_MSB:
		if(rpn_flag){
			if(rpn_addr[ch] == 0)			// pitchbend sensitivity
				bend_sense[ch] = (ev->a<<7) + ev->b;
			else if(rpn_addr[ch] == 1){		// master tuning (fine)
				master_tune[ch] |= ev->a;
				NASetController(gNoteAllocator, note_channel[ch], kControllerMasterTune, master_tune[ch]);
			}
			else if(rpn_addr[ch] == 2){		// master tuning (coarse)
				master_tune[ch] |= (ev->a<<7);
				NASetController(gNoteAllocator, note_channel[ch], kControllerMasterTune, master_tune[ch]);
			}
		}
		else {
		}
		break;
	case ME_REVERB_EFFECT:
		NASetController(gNoteAllocator, note_channel[ch], kControllerReverb, ev->a<<8);
	    channel[ch].reverb_level = ev->a;
	    ctl_mode_event(CTLE_REVERB_EFFECT, 1, ch, ev->a);
		break;
	case ME_TREMOLO_EFFECT:
		NASetController(gNoteAllocator, note_channel[ch], kControllerTremolo, ev->a<<8);
		break;
	case ME_CHORUS_EFFECT:
		NASetController(gNoteAllocator, note_channel[ch], kControllerChorus, ev->a<<8);
	    channel[ch].chorus_level = ev->a;
	    ctl_mode_event(CTLE_CHORUS_EFFECT, 1, ch, ev->a);
		break;
	case ME_CELESTE_EFFECT:
		NASetController(gNoteAllocator, note_channel[ch], kControllerCeleste, ev->a<<8);
		break;
	case ME_PHASER_EFFECT:
		NASetController(gNoteAllocator, note_channel[ch], kControllerPhaser, ev->a<<8);
		break;
	case ME_RPN_INC:
		rpn_flag = 1;
		rpn_addr[ch]++;
		break;
	case ME_RPN_DEC:
		rpn_flag = 1;
		rpn_addr[ch]--;
		break;
	case ME_NRPN_LSB:
		rpn_flag = 0;
		nrpn_lsb[ch] = ev->a;
		break;
	case ME_NRPN_MSB:
		rpn_flag = 0;
		nrpn_msb[ch] = ev->a;
		break;
	case ME_RPN_LSB:
		rpn_flag = 1;
		rpn_addr[ch] = ev->a;
		break;
	case ME_RPN_MSB:
		break;
	case ME_ALL_SOUNDS_OFF:
		for(i = 0; i < 128; i++)
			NAPlayNote(gNoteAllocator, note_channel[ch], i, 0);
		break;
	case ME_RESET_CONTROLLERS:
		NAResetNoteChannel(gNoteAllocator, note_channel[ch]);
		ctl_mode_event(CTLE_VOLUME, 1, ch, 0);
		ctl_mode_event(CTLE_EXPRESSION, 1, ch, 127);
		ctl_mode_event(CTLE_SUSTAIN, 1, ch, 0);
		ctl_mode_event(CTLE_MOD_WHEEL, 1, ch, 0);
		ctl_mode_event(CTLE_PITCH_BEND, 1, ch, 0x2000);
		ctl_prog_event(ch, channel[ch].program);
		ctl_mode_event(CTLE_CHORUS_EFFECT, 1, ch, 0);
		ctl_mode_event(CTLE_REVERB_EFFECT, 1, ch, 0);
		break;
	case ME_ALL_NOTES_OFF:
		for(i = 0; i < 128; i++)
			NAPlayNote(gNoteAllocator, note_channel[ch], i, 0);
		break;
	case ME_MONO:
		break;
	case ME_POLY:
		break;
	case ME_SOSTENUTO:
		NASetController(gNoteAllocator, note_channel[ch], kControllerSostenuto, ev->a);
		break;
	case ME_SOFT_PEDAL:
		NASetController(gNoteAllocator, note_channel[ch], kControllerSoftPedal, ev->a);
		break;
	/* TiMidity Extensionals */
	case ME_RANDOM_PAN:
		break;
	case ME_SET_PATCH:
		break;
	case ME_TEMPO:
		break;
	case ME_CHORUS_TEXT:
	case ME_LYRIC:
	case ME_MARKER:
	case ME_INSERT_TEXT:
	case ME_TEXT:
	case ME_KARAOKE_LYRIC:
		i = ev->a | ((int)ev->b << 8);
		ctl_mode_event(CTLE_LYRIC, 1, i, 0);
		break;
	case ME_MASTER_VOLUME:
		NASetController(gNoteAllocator, NULL, kControllerMasterVolume, ev->a + (ev->b<<7));
		break;
	case ME_PATCH_OFFS:
		break;
	case ME_RESET:
		play_system_mode = ev->a;
		break;
	case ME_WRD:
		push_midi_trace2(wrd_midi_event, ch, ev->a | (ev->b<<8));
		break;
	case ME_DRUMPART:
		if(!drum_part[ch]){
			//MidiEvent *ev;

			ev->channel = ch;
			ev->a = channel[ch].program;
			set_instrument(ev);
			drum_part[ch] = true;
		}
		break;
	case ME_KEYSHIFT:
		NASetController(gNoteAllocator, NULL, kControllerMasterTune, ev->a);
		break;
	case ME_NOTE_STEP:
		break;
	case ME_EOT:
		prescan = 0;
		break;
	}
	if(ev->type != ME_EOT)
		ctl_timestamp();
}