JNIEXPORT jboolean JNICALL Java_com_sun_media_sound_MixerSynth_nRemapInstrument(JNIEnv* e, jobject thisObj, jlong id, jint from, jint to) { OPErr opErr; TRACE0("Java_com_sun_media_sound_MixerSynth_nRemapInstrument\n"); opErr = GM_RemapInstrument((GM_Song *) (INT_PTR) id, (XLongResourceID)from, (XLongResourceID)to); TRACE0("Java_com_sun_media_sound_MixerSynth_nRemapInstrument completed\n"); return ( (opErr == NO_ERR) ? TRUE : FALSE ); }
JNIEXPORT jboolean JNICALL Java_com_sun_media_sound_AbstractPlayer_nRemapInstrument(JNIEnv* e, jobject thisObj, jlong id, jint from, jint to) { GM_Song *pSong = (GM_Song *) (INT_PTR) id; OPErr opErr = NOT_SETUP; TRACE0("Java_com_sun_media_sound_AbstractPlayer_nRemapInstrument\n"); if (pSong) { opErr = GM_RemapInstrument(pSong, (XLongResourceID)from, (XLongResourceID)to); if (opErr != NO_ERR) { ERROR1("Java_com_sun_media_sound_AbstractPlayer_nRemapInstrument: GM_RemapInstrument returned an error: %d\n", opErr); } } else { ERROR0("Java_com_sun_media_sound_AbstractPlayer_nRemapInstrument: pSong is NULL\n"); } TRACE0("Java_com_sun_media_sound_AbstractPlayer_nRemapInstrument completed\n"); return ( (opErr == NO_ERR) ? TRUE : FALSE ); }
// Scan the midi file and determine which instrument that need to be loaded and load them. OPErr GM_LoadSongInstruments(GM_Song *theSong, XShortResourceID *pArray, XBOOL loadInstruments) { register INT32 count, loadCount, instCount, newCount; XBOOL loopSongSave; OPErr theErr; SBYTE remapUsedSaved[MAX_INSTRUMENTS]; SBYTE remapUsed[MAX_INSTRUMENTS]; #if DISPLAY_INSTRUMENTS { char text[256]; drawDebug = DNew((char *)"\pInstruments to load"); sprintf(text, "SONG %ld debug file", (INT32)theSong->songID); #if DISPLAY_INSTRUMENTS_FILE DAttachFile(drawDebug, ctop(text)); DPrint(drawDebug, "Writing output to file: Ô%pÕ\r", text); #endif } #endif // Set the sequencer to mark instruments only theErr = NO_ERR; theSong->pUsedPatchList = (SBYTE *)XNewPtr((MAX_INSTRUMENTS*MAX_BANKS*128L) / 8); if (theSong->pUsedPatchList) { for (count = 0; count < MAX_INSTRUMENTS*MAX_BANKS; count++) { theSong->remapArray[count] = count; if (pArray) { pArray[count] = (XShortResourceID)-1; } } for (count = 0; count < MAX_CHANNELS; count++) { theSong->firstChannelBank[count] = 0; theSong->firstChannelProgram[count] = -1; } theErr = PV_ConfigureMusic(theSong); if (theErr == NO_ERR) { if (theSong->defaultPercusionProgram == -1) { theSong->channelBank[PERCUSSION_CHANNEL] = 0; theSong->firstChannelBank[PERCUSSION_CHANNEL] = 0; } else { if (theSong->defaultPercusionProgram) { theSong->firstChannelProgram[PERCUSSION_CHANNEL] = theSong->defaultPercusionProgram; GM_SetUsedInstrument(theSong, (XLongResourceID)theSong->defaultPercusionProgram, 60, TRUE); } } theSong->AnalyzeMode = SCAN_SAVE_PATCHES; theSong->SomeTrackIsAlive = TRUE; loopSongSave = theSong->loopSong; theSong->loopSong = FALSE; while (theSong->SomeTrackIsAlive) { theErr = PV_ProcessMidiSequencerSlice(NULL, theSong); if (theErr) { break; } } theSong->AnalyzeMode = SCAN_NORMAL; theSong->loopSong = loopSongSave; if (theErr == NO_ERR) { // are we trying to load any instruments? This is for the case were there are no program changes. We must do something newCount = FALSE; for (count = 0; count < MAX_CHANNELS; count++) { if (count != PERCUSSION_CHANNEL) // only look at non percussion channels { if (theSong->firstChannelProgram[count] != -1) { newCount = TRUE; break; } } } if (newCount == FALSE) { // there have been no program changes. So set up just the piano in all channels for (count = 0; count < MAX_CHANNELS; count++) { theSong->firstChannelProgram[count] = 0; theSong->channelProgram[count] = 0; } GM_SetUsedInstrument(theSong, 0, -1, TRUE); // load the entire piano } #if DISPLAY_INSTRUMENTS DPrint(drawDebug, "Loading instruments:\r"); #endif instCount = 0; for (count = 0; count < MAX_INSTRUMENTS*MAX_BANKS; count++) { // instrument needs to be loaded if (GM_IsInstrumentUsed(theSong, count, -1)) { #if DISPLAY_INSTRUMENTS DPrint(drawDebug, "Instrument %ld: ", (INT32)count); #endif loadCount = theSong->instrumentRemap[count]; if (loadCount == -1) { loadCount = count; } #if DISPLAY_INSTRUMENTS else { DPrint(drawDebug, "remapped to %ld ", (INT32)loadCount); } #endif #if DISPLAY_INSTRUMENTS DPrint(drawDebug, "loading instrument %ld\r", loadCount); #endif if (pArray) { pArray[instCount++] = (short)loadCount; } if (loadInstruments) { if (loadCount != count) { GM_GetInstrumentUsedRange(theSong, loadCount, remapUsedSaved); // save GM_GetInstrumentUsedRange(theSong, count, remapUsed); GM_SetInstrumentUsedRange(theSong, loadCount, remapUsed); } theErr = GM_LoadInstrument(theSong, loadCount); if (theErr != NO_ERR) { // if the instrument is some other bank, then go back to the standard GM bank before failing if (loadCount > MAX_INSTRUMENTS) { #if DISPLAY_INSTRUMENTS DPrint(drawDebug, "Failed loading extra bank instrument %ld, falling back to GM.\r", loadCount); #endif newCount = (loadCount % MAX_INSTRUMENTS); newCount += ((loadCount / MAX_INSTRUMENTS) & 1) * MAX_INSTRUMENTS; loadCount = newCount; #if DISPLAY_INSTRUMENTS DPrint(drawDebug, "Loading instrument %ld\r", loadCount); #endif theErr = GM_LoadInstrument(theSong, loadCount); if (theSong->ignoreBadInstruments) { theErr = NO_ERR; } } else { // we are in GM, so check our ignore flag if (theSong->ignoreBadInstruments) { theErr = NO_ERR; } } } if (loadCount != count) { GM_SetInstrumentUsedRange(theSong, loadCount, remapUsedSaved); // save } if (theErr) { #if DISPLAY_INSTRUMENTS DPrint(drawDebug, "Failed to load instrument %ld (%ld)\r", (INT32)loadCount, (INT32)theErr); #endif break; } theErr = GM_RemapInstrument(theSong, loadCount, count); // remap from: to // we are in GM, so check our ignore flag if (theSong->ignoreBadInstruments) { theErr = NO_ERR; } } } } } } if (theErr != NO_ERR) { GM_UnloadSongInstruments(theSong); // ignore error } XDisposePtr(theSong->pUsedPatchList); theSong->pUsedPatchList = NULL; } else { theErr = MEMORY_ERR; } #if DISPLAY_INSTRUMENTS DPrint(drawDebug, "\rClick to exit"); while (Button() == FALSE) {}; while (Button()) {}; FlushEvents(mDownMask, 0); DCopy(drawDebug); DDispose(drawDebug); #endif return theErr; }