/***************************************************************************
*   NAME:  LOADPTCH.C $Revision: 1.15 $
**  COPYRIGHT:
**  "Copyright (c) 1994,1995 by e-Tek Labs"
**
**       "This software is furnished under a license and may be used,
**       copied, or disclosed only in accordance with the terms of such
**       license and with the inclusion of the above copyright notice.
**       This software or any other copies thereof may not be provided or
**       otherwise made available to any other person. No title to and
**       ownership of the software is hereby transfered."
****************************************************************************
* $Log: loadptch.c $
* Revision 1.15  1995/10/13 17:32:44  mleibow
* Changed patch loader to use iwllist.c and iwllist.h instead of list.c and list.h
* Revision 1.14  1995/07/11 10:38:01  teckert
* Revision 1.13  1995/07/11 10:26:39  teckert
* Added function to clear user flags when synth client closes
* Revision 1.12  1995/06/28 11:37:38  teckert
* Rewrote patch caching strategy to handle low memory conditions.
* Revision 1.11  1995/04/28 16:01:40  teckert
* Bug fixed (Defered notes and MCI pause-unpause anomaly)
* Revision 1.10  1995/04/24 18:16:48  teckert
* Added full memory condition handling
* Revision 1.9  1995/04/19 18:36:22  teckert
* Updated with new patch.c helper routines
* Revision 1.8  1995/04/19 17:18:46  mleibow
* Rewrote patch loading code
* Revision 1.7  1995/04/10 13:47:25  teckert
* added allocation bug fixes
* Revision 1.6  1995/04/04 15:34:10  teckert
* Added changes to fix MCI pause-unpause bug
* Revision 1.5  1995/03/30 16:37:47  teckert
* Updated according to Mike's new patch.c (ignores unknown chunks)
* Revision 1.4  1995/03/03 11:14:43  sdsmith
* Replaced dma_buf_one with dma_buf_two and call to iw_dram_xfer with
* call directly to iw_poke_block
* Revision 1.3  1995/03/01 16:56:45  unknown
* Added file header
* Revision 1.1  1995/02/23 15:14:59  sdsmith
* Initial revision
***************************************************************************/
#include <windows.h>
#include <mmsystem.h>
#include <mmddk.h>
#include <iw.h>        
#include <stdio.h>
#include "patch.h"
#include "midi.h"
#include "wave.h"

int DeferedNotes[MAXDEFEREDNOTES][2];

extern int patch_load_failed;

void redo_patches_assignments(void)
{           
    struct iwu_fast_patch RFAR*fpi;
    int nClient,nChan;
	
    for(nClient = 0;nClient < MAXMIDICLIENTS;nClient++){
	for(nChan = 0;nChan<16;nChan++){
	    if(nChan == 0x09)
		continue;
	    fpi = MidiClients[nClient].CurPatch[nChan];
	    if (fpi && fpi->flags & IWU_PATCH_LOADED) {
		iw_midi_change_program(nClient*16+nChan,fpi->p);
	    }
	}           
    }		
}

void iwu_clear_patch_uds(void)
{
    struct iwu_fast_patch RFAR *fpi;    /* search index */
    struct patch_lib RFAR *pl;
    struct patch_node RFAR *fffn;
    struct fff_file RFAR *fff;
    int i;

    for (pl=plib; pl != 0; pl = pl->next) {
	for (fffn=(struct patch_node RFAR *)pl->fff_list.head; fffn; fffn = fffn->next) {
	    fff = fffn->data;
	    for (fpi = fff->patches, i=0; i < fff->npatches; i++, fpi++) {
		fpi->ud = 0;
	    }
	}
    }
    return;
}


void ProgramAssign(
	int nClient,
	int nChan,
	int nProgram)
{                                                    
	struct iwu_fast_patch RFAR*fpi;
	int nBank;
		  
	nBank =  MidiClients[nClient].CurBank[nChan];
	fpi = iwu_find_patch(nProgram,nBank,0);
	MidiClients[nClient].CurPatch[nChan] = fpi;

	if (fpi && fpi->flags & IWU_PATCH_LOADED) {
	    iw_midi_change_program(nClient*16+nChan,fpi->p);
	} else  {
	    iw_midi_change_program(nClient*16+nChan,0);
	    if (fpi) {
	        PostCallbackMsg(MC_LOADMELODICPATCHES,0L);
	    }
	}
}

int NoteOnDefered(int nChan,int nNote)
{                                                
    int i;
    
    for(i=0;i<MAXDEFEREDNOTES;i++){
	if(DeferedNotes[i][0] == 0xFF){
	    break;
	}
    }             
    if(i==MAXDEFEREDNOTES){
	return 0;
    }            
    DeferedNotes[i][0] = nChan;
    DeferedNotes[i][1] = nNote;
	
    return 1;
}

void DeferedNotePlayed(int nChan,int nNote)
{
    int i;
    
    for(i=0;i<MAXDEFEREDNOTES;i++){
	if((DeferedNotes[i][0] == nChan) && (DeferedNotes[i][1] == nNote)){
	    DeferedNotes[i][0] == 0xFF;
	    return;
	}
    }             
}

int WasNoteOnDefered(int nChan,int nNote)
{
    int i;
    
    for(i=0;i<MAXDEFEREDNOTES;i++){
	if((DeferedNotes[i][0] == nChan) && (DeferedNotes[i][1] == nNote)){
	    return 1;
	}
    }             
    return 0;
}        

void NoteOn(
	int nClient,
	int nChan,
	int nNote,
	int nVel)
{
    struct iwu_fast_patch RFAR*fpi;
    int nBank;

    if(nVel==0)
	    NoteOff(nClient,nChan,nNote);

    nBank = MidiClients[nClient].CurBank[nChan];
    if(nChan == 0x09){      // Drum Channel
	fpi = iwu_find_patch(nNote+128,nBank,0);
	if (fpi) {
	    if (fpi->flags & IWU_PATCH_LOADED) {
		iw_midi_note_on(nClient*16+nChan,nNote,nVel,fpi->p,1);
	    } else {
		iwu_mark_patch(nNote+128,nBank);
		if( NoteOnDefered(nClient*16+nChan,nNote) ){
		    PostCallbackMsg(MC_LOADPATCHES,0L);
		    PostCallbackMsg(MC_NOTEON,MAKELONG(nNote*256+nVel,(nClient*16+nChan)*256+nBank));
		}
	    }
	}
    }else{                  // Melodic Channel
	fpi = MidiClients[nClient].CurPatch[nChan];
	if(fpi) {
	    if (fpi->flags & IWU_PATCH_LOADED){
		iw_midi_note_on(nClient*16+nChan,nNote,nVel,NULL,1);
		return;
	    } else {
		if( NoteOnDefered(nClient*16+nChan,nNote) ){
		    PostCallbackMsg(MC_LOADMELODICPATCHES,0L);
		    PostCallbackMsg(MC_NOTEON,MAKELONG(nNote*256+nVel,(nClient*16+nChan)*256+nBank));
		}
	    }
	}
    }
}

void NoteOff(
	int nClient,
	int nChan,
	int nNote)
{
	if(WasNoteOnDefered(nClient*16+nChan,nNote)){
		PostCallbackMsg(MC_NOTEOFF,MAKELONG(nNote*256,(nClient*16+nChan)*256));
	}else{
		iw_midi_note_off(nClient*16+nChan,nNote);
	}
}

