/*
   GSPLUS - Advanced Apple IIGS Emulator Environment
   Based on the KEGS emulator written by Kent Dickey
   See COPYRIGHT.txt for Copyright information
   See LICENSE.txt for license (GPL v2)
 */

#include "defc.h"

#ifdef ACTIVEIPHONE
void child_sound_init_mac() {}
void macsnd_init(word32 *shmaddr) {}
int mac_send_audio(byte *ptr, int in_size) {}
#else

#include <Carbon/Carbon.h>


#include "sound.h"
#include <unistd.h>

#define MACSND_REBUF_SIZE       (64*1024)
#define MACSND_QUANTA           512
/* MACSND_QUANTA must be >= 128 and a power of 2 */

word32 g_macsnd_rebuf[MACSND_REBUF_SIZE];
volatile word32 *g_macsnd_rebuf_ptr;
volatile word32 *g_macsnd_rebuf_cur;
volatile int g_macsnd_playing = 0;

extern int Verbose;

extern int g_audio_rate;
extern word32 *g_sound_shm_addr;
extern int g_sound_size;


SndChannelPtr g_snd_channel_ptr;
ExtSoundHeader g_snd_hdr;
SndCommand g_snd_cmd;

void mac_snd_callback(SndChannelPtr snd_chan_ptr, SndCommand *in_sndcmd)      {
  OSStatus err;
  int samps;

  // This is an interrupt routine--no printf, etc!

  samps = g_macsnd_rebuf_ptr - g_macsnd_rebuf_cur;
  if(samps < 0) {
    samps += MACSND_REBUF_SIZE;
  }

  samps = samps & -(MACSND_QUANTA);             // quantize to 1024 samples
  if(g_macsnd_rebuf_cur + samps > &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) {
    samps = &(g_macsnd_rebuf[MACSND_REBUF_SIZE]) -
            g_macsnd_rebuf_cur;
  }
  if(samps > 0) {
    g_macsnd_playing = 1;
    g_snd_hdr.numFrames = samps;
    g_snd_hdr.loopEnd = samps;
    g_snd_hdr.samplePtr = (char *)g_macsnd_rebuf_cur;             // OG Cast from byte* to ,char*

    g_snd_cmd.cmd = bufferCmd;
    g_snd_cmd.param1 = 0;
    g_snd_cmd.param2 = (long) &g_snd_hdr;

    g_macsnd_rebuf_cur += samps;
    if(g_macsnd_rebuf_cur >= &(g_macsnd_rebuf[MACSND_REBUF_SIZE])) {
      g_macsnd_rebuf_cur -= MACSND_REBUF_SIZE;
    }

    err = SndDoImmediate(g_snd_channel_ptr, &g_snd_cmd);

    // And set-up callback
    g_snd_cmd.cmd = callBackCmd;
    g_snd_cmd.param1 = 0;
    g_snd_cmd.param2 = 0;
    err = SndDoCommand(g_snd_channel_ptr, &g_snd_cmd, TRUE);
  } else {
    g_macsnd_playing = 0;
  }
}

int mac_send_audio(byte *ptr, int in_size)     {
  SndCommand snd_cmd = {0};
  word32  *wptr, *macptr;
  word32  *eptr;
  int samps;
  int i;

  samps = in_size / 4;
  wptr = (word32 *)ptr;
  macptr = (word32 *)g_macsnd_rebuf_ptr;
  eptr = &g_macsnd_rebuf[MACSND_REBUF_SIZE];
  for(i = 0; i < samps; i++) {
    *macptr++ = *wptr++;
    if(macptr >= eptr) {
      macptr = &g_macsnd_rebuf[0];
    }
  }

  g_macsnd_rebuf_ptr = macptr;

  if(!g_macsnd_playing) {
    mac_snd_callback(g_snd_channel_ptr, &snd_cmd);
  }

  return in_size;
}

void child_sound_init_mac()      {
  OSStatus err;

  mac_printf("In mac child\n");
  fflush(stdout);
  mac_printf("pid: %d\n", getpid());
  fflush(stdout);

  //return;

  //g_snd_channel_ptr = 0;
  err = SndNewChannel(&g_snd_channel_ptr, sampledSynth, initStereo,
                      NewSndCallBackUPP(mac_snd_callback));
  mac_printf("SndNewChannel ret: %d\n", (int)err);
  fflush(stdout);

  memset(&g_snd_hdr, 0, sizeof(g_snd_hdr));
  g_snd_hdr.sampleSize = 16;
  g_snd_hdr.numChannels = 2;
  g_audio_rate = 44100;
  g_snd_hdr.sampleRate = g_audio_rate << 16;
  g_snd_hdr.numFrames = 0;              // will be set in mac_send_audio
  g_snd_hdr.encode = extSH;
  g_snd_hdr.baseFrequency = 0;
  g_snd_hdr.samplePtr = 0;

  set_audio_rate(g_audio_rate);

  mac_printf("End of child_sound_init_mac\n");
  fflush(stdout);
}

void macsnd_init(word32 *shmaddr)      {
  g_macsnd_rebuf_cur = &g_macsnd_rebuf[0];
  g_macsnd_rebuf_ptr = &g_macsnd_rebuf[0];
  mac_printf("macsnd_init called\n");
  child_sound_loop(-1, -1, shmaddr);
}
#endif
