JNIEXPORT void JNICALL
    Java_com_sun_media_sound_MixerMidiChannel_nProgramChange__JIIJ(JNIEnv* e, jobject thisObj, jlong id, jint channelNumber, jint program, jlong tick) {

    TRACE0("Java_com_sun_media_sound_MixerMidiChannel_nProgramChange.\n");
    VTRACE1("-> id: %lu\n", id);
    VTRACE3("-> channelNumber: %d, program: %d, tick: %lu\n", channelNumber, program, tick);

    if (tick < 0)
	{
	    /* talk directly to the synthesizer */
	    GM_ProgramChange((void *)e, (GM_Song *) (INT_PTR) id, (INT16)channelNumber, (INT16)program);
	}
    else 
	{
	    /* schedule with the sequencer */
	    QGM_ProgramChange((void *)e, (GM_Song *) (INT_PTR) id, (UINT32)tick, (INT16)channelNumber, (INT16)program);
	}

    TRACE0("Java_com_sun_media_sound_MixerMidiChannel_nProgramChange completed.\n");
}
Пример #2
0
static OPErr MixerSourceLineCallbackProc(void* context, GM_StreamMessage message, GM_StreamData* pAS)
{
    JNIEnv* e = (JNIEnv*)context;														    
    VTRACE2("MixerSourceLineCallbackProc, context: %lx, message: %d\n", context, message);

    // for STREAM_CREATE, we just need to allocate the buffer.
    // we need to convert from gmData->dataLength (number of frames) to number of bytes.
    // $$kk: 03.15.98: this is the same calculation done by PV_GetSampleSizeInBytes.  however, this
    // method is not available outside GenAudioStreams.c right now.

    if (message == STREAM_CREATE)
	{
	    jint    const byteCount = pAS->dataLength * pAS->channelSize * (pAS->dataBitSize / 8);

	    VTRACE1("STREAM_CREATE: %lx\n", pAS->userReference);
	    VTRACE3("STREAM_CREATE: byteCount = %d, dataLength = %lu, frameSize = %d.\n", byteCount, pAS->dataLength, (pAS->channelSize * (pAS->dataBitSize / 8)) );

	    pAS->pData = XNewPtr(byteCount);
	    if (!pAS->pData)
		{
		    ERROR1("MixerSourceLineCallbackProc: STREAM_CREATE: Failed to allocate %d bytes\n", byteCount);
		    return MEMORY_ERR;
		}

	    VTRACE1("STREAM_CREATE: %lx completed\n", pAS->userReference);
	}
    else if (message == STREAM_DESTROY)
	{
	    VTRACE1("STREAM_DESTROY: %lx\n", pAS->userReference);

	    CallToJavaStreamDestroy(e, (jobject)pAS->userReference);

	    // $$kk: 12.21.98: for some reason, this causes the vm to crash some
	    // random time later.  so we have a memory leak here.  i don't know
	    // why we can't release the memory here....
		
	    // $$kk: 03.22.00: i am putting this code back in.  the memory leak is
	    // causing problems, and so far i have not been able to reproduce the
	    // crash.  the memory leak is reported in bug #4319431: "Memory leaks
	    // on opening and closing source DataLines."

	    if (pAS->pData)
		{
		    XDisposePtr(pAS->pData);
		}

	    VTRACE1("STREAM_DESTROY: %lx completed\n", pAS->userReference);
	}
    else if (message == STREAM_GET_DATA)
	{		
	    int length;
	    int frameLengthInBytes = pAS->channelSize * (pAS->dataBitSize / 8);
	    jbyteArray array = (jbyteArray)(*e)->GetObjectField(e, (jobject)pAS->userReference, g_dataArrayFieldID);

	    if (array == NULL) 
		{
		    ERROR0("STREAM_GET_DATA: failed to get array\n");
		    return GENERAL_BAD;
		}

	    // make the callback.
	    // pAS->dataLength is the length in FRAMES.
	    // length returned is length in FRAMES.
	    length = (int)CallToJavaStreamGetData(e, (jobject)pAS->userReference, array, (jint)pAS->dataLength);

	    // length will be -1 when the stream finishes
		
	    if (length < 0)
		{
		    VTRACE0("STREAM_GET_DATA: got negative length; stopping stream\n");
		    return STREAM_STOP_PLAY;
		}
													   
	    // get the relevant array elements

	    // $$kk: 03.15.98: can we avoid this copy??
	    (*e)->GetByteArrayRegion(e, array, (jint)0, (jint)(length * frameLengthInBytes), (jbyte*)(pAS->pData));
		
	    // $$kk: 04.21.00: fix for bug #4332327: "JNI leaks local references on 
	    // keeping a SourceLine open for long."
	    (*e)->DeleteLocalRef(e, array);		
		
	    // set dataLength to the number of frames read
	    pAS->dataLength = length;

	    VTRACE2("STREAM_GET_DATA: length: %d, pAS->dataLength: %lu\n", length, pAS->dataLength);
	    VTRACE1("STREAM_GET_DATA: %lx completed\n", pAS->userReference);
	}
    else if (message == STREAM_START)
	{
	    TRACE2("STREAM_START: stream: %lx,  framePosition: %lu\n", pAS->userReference, pAS->startSample);
	    CallToJavaStreamStart(e, (jobject)pAS->userReference);
	    TRACE1("STREAM_START: %lx completed\n", pAS->userReference);
	}
    else if (message == STREAM_STOP)
	{
	    TRACE2("STREAM_STOP: %lx,  framePosition: %lu\n", pAS->userReference, pAS->startSample);
	    CallToJavaStreamStop(e, (jobject)pAS->userReference);
	    TRACE1("STREAM_STOP: %lx completed\n", pAS->userReference);
	}
    else if (message == STREAM_EOM)
	{
	    TRACE2("STREAM_EOM: %lx,  framePosition: %lu\n", pAS->userReference, pAS->startSample);
	    CallToJavaStreamEOM(e, (jobject)pAS->userReference);
	    TRACE1("STREAM_EOM: %lx completed\n", pAS->userReference);
	}
    else if (message == STREAM_ACTIVE)
	{
	    TRACE2("STREAM_ACTIVE: %lx,  framePosition: %lu\n", pAS->userReference, pAS->startSample);
	    CallToJavaStreamActive(e, (jobject)pAS->userReference);
	    TRACE1("STREAM_ACTIVE: %lx completed\n", pAS->userReference);
	}
    else if (message == STREAM_INACTIVE)
	{
	    TRACE2("STREAM_INACTIVE: %lx,  framePosition: %lu\n", pAS->userReference, pAS->startSample);
	    CallToJavaStreamInactive(e, (jobject)pAS->userReference);
	    TRACE1("STREAM_INACTIVE: %lx completed\n", pAS->userReference);
	}

    else
	{
	    ERROR1("Bad message code in MixerSourceLineCallbackProc() : %d\n", message);
	    return GENERAL_BAD;
	}

    return NO_ERR;
}