
/*
**  jazz - a midi sequencer for Linux
**
**  Copyright (C) 1994-1996 Andreas Voss (andreas@avix.rhein-neckar.de)
**
**  Copyright (C) 1995-1996 Per Sigmond (Per.Sigmond@hia.no)
**
**  This program is free software; you can redistribute it and/or modify
**  it under the terms of the GNU General Public License as published by
**  the Free Software Foundation; either version 2 of the License, or
**  (at your option) any later version.
**
**  This program is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**  GNU General Public License for more details.
**
**  You should have received a copy of the GNU General Public License
**  along with this program; if not, write to the Free Software
**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef jazzdll_h
#define jazzdll_h


struct tWinPlayerState;
extern "C" {
void FAR PASCAL midiIntInputHandler(HMIDIIN, WORD, DWORD, DWORD, DWORD);
void FAR PASCAL midiMidiInputHandler(HMIDIIN, WORD, DWORD, DWORD, DWORD);
void FAR PASCAL midiMtcInputHandler(HMIDIIN, WORD, DWORD, DWORD, DWORD);
void FAR PASCAL midiIntTimerHandler(UINT, UINT, DWORD, DWORD, DWORD);
void FAR PASCAL midiMidiTimerHandler(UINT, UINT, DWORD, DWORD, DWORD);
void FAR PASCAL midiMtcTimerHandler(UINT, UINT, DWORD, DWORD, DWORD);
tWinPlayerState FAR * FAR PASCAL NewWinPlayerState();
void FAR PASCAL DeleteWinPlayerState(tWinPlayerState FAR * state);
}


// # events in record/play queue
#define MIDI_BUFFER_SIZE 2048


struct midi_event
{
  DWORD ref; /* Means time or clock depending on sync mode */
  DWORD data;
};


class tMidiQueue
{
  public:
  
    midi_event * get()
    {
      if (wr == rd)
        return 0;
      struct midi_event *e = &buffer[rd];
      rd = (rd + 1) % MIDI_BUFFER_SIZE;
      return e;
    }

    midi_event * peek()
    {
      if (wr == rd)
        return 0;
      return &buffer[rd];
    }
    
    void put(DWORD data, DWORD ref)
    {
      midi_event *e = &buffer[wr];
      e->data = data;
      e->ref = ref;
      wr = (wr + 1) % MIDI_BUFFER_SIZE;
    }
    
    int empty()
    {
      return rd == wr;
    }
    
    
    void clear()
    {
      rd = wr = 0;
    }
    
    tMidiQueue()
    {
      clear();
    }
    
  private:
    int rd, wr;
    midi_event buffer[MIDI_BUFFER_SIZE];
};

#define WIN_SYNC_INTERNAL 0
#define WIN_SYNC_SONGPTR  1
#define WIN_SYNC_MTC      2

#define WIN_MTC_TYPE_24    0
#define WIN_MTC_TYPE_25    1
#define WIN_MTC_TYPE_30DF  2
#define WIN_MTC_TYPE_30NDF 3


struct tWinPlayerMtcTime {
  DWORD hour;
  DWORD min;
  DWORD sec;
  DWORD fm;
  DWORD type;
};

struct tWinPlayerState
{
    HANDLE     hmem;
    HMIDIIN    hinp;
    HMIDIOUT   hout;

    DWORD      start_time;
    DWORD      play_time;
    long       start_clock;
    long       ticks_per_minute;

    long       play_clock;
    long       virtual_clock;
    long       ticks_per_signal;
    DWORD      signal_time;
    DWORD      time_per_tick;

    tWinPlayerMtcTime mtc_start;
    DWORD      mtc_frames;
    BOOL       mtc_valid;
    DWORD      last_qfm;
    DWORD      qfm_bits;
    DWORD      time_per_frame;
    
    UINT       min_timer_period;
    UINT       max_timer_period;
    BOOL       playing;
    BOOL       soft_thru;
    BOOL       doing_mtc_rec;
    
    tMidiQueue recd_buffer;
    tMidiQueue play_buffer;
    tMidiQueue thru_buffer;
};


#endif
