/* main.c */
/* Ties the module together */

#include "kernel.h"

#include "errors.h"
#include "generic.h"
#include "log.h"
#include "replay.h"
#include "vidc.h"
#include "wav.h"

_kernel_oserror *
initialise(char *cmd_tail, int podule_base, void *pw)
{
  _kernel_oserror *e;
#ifdef MAKELOG
  log_open("THSoundLog");
#endif
  e = vidc_initialise();
  if (e)
    return e;
  e = replay_initialise(pw);
  if (e)
    vidc_finalise();
  return e;
}

_kernel_oserror *
finalise(int fatal, int podule_base, void *pw)
{
  _kernel_oserror *e, *e2;
  e = vidc_finalise();
  e2 = replay_finalise();
#ifdef MAKELOG
  log_close();
#endif
  return e ? e : e2;
}

enum {
  InstallSample, RemoveSample, GetVoiceSlot, ChannelInUse, GetPollWord,
  InstallLinear,
  ReadReplayHeaders, ReadReplayFileHeaders, RemoveReplay,
  PrepareReplayCodec, SetUpReplayBuffers, CompleteReplayTimingCheck,
  PlayReplay, StopReplay,
  PrepareGeneric, PrepareGenericFile,
  CheckWAV, CheckWAVFile, ReadWAVChunks, ReadWAVFileChunks,
  Log
};


_kernel_oserror *
swi_handler(int swi_no, _kernel_swi_regs *regs, void *pw)
{
  _kernel_oserror *e;
  switch (swi_no)
  {
    case InstallSample:
      e = vidc_install_sample((const char *) regs->r[0], (size_t) regs->r[1],
                              regs->r[2], 0,
                              (vidc_handle *) &regs->r[0], &regs->r[2]);
      if (!e)
        regs->r[1] = regs->r[2];
      return e;
    case RemoveSample:
      return vidc_remove_sample((vidc_handle) regs->r[0]);
    case GetVoiceSlot:
      return vidc_get_voice_slot((vidc_handle) regs->r[0], &regs->r[1]);
    case ChannelInUse:
      return vidc_channel_in_use(regs->r[0], &regs->r[0]);
    case GetPollWord:
      /* Check whether it's a Replay handle first */
      regs->r[1] = (int) replay_get_pollword((replay_handle) regs->r[0]);
      if (regs->r[1])
        return 0;
      return vidc_get_poll_word((vidc_handle) regs->r[0],
                                (int **) &regs->r[1]);
    case InstallLinear:
      e = vidc_install_sample((const char *) regs->r[0], (size_t) regs->r[1],
                              regs->r[2], 1,
                              (vidc_handle *) &regs->r[0], &regs->r[2]);
      if (!e)
        regs->r[1] = regs->r[2];
      return e;
    case ReadReplayHeaders:
      return replay_read_headers((const char *) regs->r[0],
                                 (size_t) regs->r[1], regs->r[2], 0,
                                 (replay_handle *) &regs->r[0],
                                 (const char **) &regs->r[1],
                                 (const char **) &regs->r[2],
                                 &regs->r[3], &regs->r[4], &regs->r[5],
                                 &regs->r[6], &regs->r[7]);
    case ReadReplayFileHeaders:
      return replay_read_headers((const char *) regs->r[0],
                                 (size_t) regs->r[1], regs->r[2], 1,
                                 (replay_handle *) &regs->r[0],
                                 (const char **) &regs->r[1],
                                 (const char **) &regs->r[2],
                                 &regs->r[3], &regs->r[4], &regs->r[5],
                                 &regs->r[6], &regs->r[7]);
    case RemoveReplay:
      return replay_remove((replay_handle) regs->r[0]);
    case PrepareReplayCodec:
      return replay_prepare_codec((replay_handle) regs->r[0],
                                  (replay_codec *) regs->r[1],
                                  (replay_mute *) regs->r[2],
                                  regs->r[3], regs->r[4], regs->r[5]);
    case SetUpReplayBuffers:
      return replay_setup_buffers((replay_handle) regs->r[0],
                                  (char *) regs->r[1], regs->r[2],
                                  (char *) regs->r[3], regs->r[4]);
    case CompleteReplayTimingCheck:
      return replay_complete_timing_check((replay_handle) regs->r[0],
                                          &regs->r[1]);
    case PlayReplay:
      return replay_play((replay_handle) regs->r[0], regs->r[1]);
    case StopReplay:
      return replay_stop((replay_handle) regs->r[0]);
    case PrepareGeneric:
      return generic_prepare((const char *) regs->r[0], regs->r[1], 0,
                             (const char *) regs->r[3], 0,
                             (replay_handle *) &regs->r[0], &regs->r[1]);
    case PrepareGenericFile:
      return generic_prepare((const char *) regs->r[0], regs->r[1],
                             regs->r[2],
                             (const char *) regs->r[3], 1,
                             (replay_handle *) &regs->r[0], &regs->r[1]);
    case CheckWAV:
      return wav_check((const char *) regs->r[0], regs->r[1], &regs->r[2]);
    case CheckWAVFile:
      return wav_check((const char *) regs->r[0], 0, &regs->r[2]);
    case ReadWAVChunks:
      return wav_read_chunks((const char *) regs->r[0], regs->r[1],
                             (replay_handle *) &regs->r[0],
                             (const char **) &regs->r[1],
                             (const char **) &regs->r[2],
                             &regs->r[3], &regs->r[4], &regs->r[5],
                             &regs->r[6], &regs->r[7]);
    case ReadWAVFileChunks:
      return wav_read_chunks((const char *) regs->r[0], 0,
                             (replay_handle *) &regs->r[0],
                             (const char **) &regs->r[1],
                             (const char **) &regs->r[2],
                             &regs->r[3], &regs->r[4], &regs->r[5],
                             &regs->r[6], &regs->r[7]);
    case Log:
      LOG(((const char *) regs->r[0]));
      return 0;
  }
  return &error_no_such_swi;
}
