// Copyright (c) 2021 Giorgos Vougioukas
//
// The plug-in mechanism derived from REAPER plug-in API
// Copyright (c) 2006-2009, Cockos Incorporated
//
// This software is provided 'as-is', without any express or implied
// warranty.  In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
//  1. The origin of this software must not be misrepresented; you must not
//     claim that you wrote the original software. If you use this software
//     in a product, an acknowledgment in the product documentation would be
//     appreciated but is not required.
//  2. Altered source versions must be plainly marked as such, and must not be
//     misrepresented as being the original software.
//  3. This notice may not be removed or altered from any source distribution.
//
//  Notes: the C++ interfaces used require MSVC on win32, or at least the
//  MSVC-compatible C++ ABI. Sorry, mingw users :(

#ifndef _RSI_PLUGIN_PUBLIC_H_
#define _RSI_PLUGIN_PUBLIC_H_

#ifdef _WIN32
#include <windows.h>

#define RSI_PLUGIN_EXPORT __declspec(dllexport)
#define RSI_PLUGIN_HINSTANCE HINSTANCE
#else
#include <pthread.h>
#include "WDL/swell/swell.h"

#define RSI_PLUGIN_EXPORT __attribute__((visibility("default")))
#define RSI_PLUGIN_HINSTANCE void *
#endif

#include "WDL/wdltypes.h"
#include "RSI/sample_format.h"

#define RSI_PLUGIN_ENTRYPOINT rsi_plugin_entry
#define RSI_PLUGIN_ENTRYPOINT_NAME "rsi_plugin_entry"

#define RSI_PLUGIN_VERSION 120

struct RSI_PluginInfo
{
  int caller_version;

  HWND hwnd_main;

  int (*Register)(const char *name, void *info_struct);

  void *(*GetFunc)(const char *name);
};

class RSI_IFileInput
{
public:
  virtual ~RSI_IFileInput()
  {}

  //virtual void Open(const char *filename) = 0;

  //virtual bool IsAvailable() = 0;

  virtual const char *GetType() const = 0;

  // return NULL if no filename (not purely a file)
  virtual const char *GetFileName() const = 0;

  // return number of channels
  virtual int GetChannels() const = 0;

  // returns preferred sample rate. if < 1.0 then it is assumed to be silent
  virtual double GetSampleRate() const = 0;

  // length in seconds
  virtual double GetLength() const = 0;

  // returns bits/sample, if available. only used for metadata purposes,
  // since everything returns as doubles anyway.
  virtual int GetBitsPerSample() const = 0;

  virtual double GetPosition() const = 0;

  virtual void Seek(double time) = 0;

  virtual int GetSamples(SAM *buffer, int length) = 0;

  virtual bool IsStreaming() const = 0;

  virtual int Extended(int call, void *parm1, void *parm2, void *parm3) = 0;
};

struct RSI_FileInputRegister
{
  RSI_IFileInput *(*CreateFromType)(const char *type);
  RSI_IFileInput *(*CreateFromFile)(const char *filename);
};

class RSI_IFileTag
{
public:
  virtual ~RSI_IFileTag()
  {}

  virtual const char *GetType() const = 0;

  virtual const char *GetTitle() const = 0;
  virtual const char *GetArtist() const = 0;
  virtual const char *GetAlbum() const = 0;
  virtual const char *GetGenre() const = 0;
  virtual const char *GetTrack() const = 0;
  virtual const char *GetYear() const = 0;
  virtual const char *GetComment() const = 0;

  virtual WDL_INT64 GetFileSize() const = 0;
  virtual const char *GetFileName() const = 0;
  virtual const char *GetFilePath() const = 0;
  virtual const char *GetFileExtension() const = 0;
};

struct RSI_FileTagRegister
{
  RSI_IFileTag *(*CreateFromFile)(const char *filename);
};

class RSI_IFilePic
{
public:
  virtual ~RSI_IFilePic()
  {}

  virtual int GetPicSize() const = 0;
  virtual void *GetPic() const = 0;
};

struct RSI_FilePicRegister
{
  RSI_IFilePic *(*CreateFromFile)(const char *filename);
};

class RSI_IPitchShift
{
public:
  virtual ~RSI_IPitchShift()
  {}

  virtual void set_srate(double srate) = 0;
  virtual void set_nch(int nch) = 0;
  virtual void set_shift(double shift) = 0;
  virtual void set_formant_shift(double shift) = 0; // shift can be <0 for "only shift when in formant preserve mode", so that you can use it for effective rate changes etc in that mode
  virtual void set_tempo(double tempo) = 0;

  virtual void Reset() = 0;  // reset all buffers/latency
  virtual SAM *GetBuffer(int size) = 0;
  virtual void BufferDone(int input_filled) = 0;

  virtual void FlushSamples() = 0; // make sure all output is available

  virtual bool IsReset() = 0;

  virtual int GetSamples(int requested_output, SAM *buffer) = 0; // returns number of samplepairs returned

  virtual void SetQualityParameter(int parm) = 0; // set to: (mode<<16)+(submode), or -1 for "project default" (default)
  virtual int Extended(int call, void *parm1, void *parm2, void *parm3) { return 0; } // return 0 if unsupported
};

struct RSI_PitchShiftRegister
{
  RSI_IPitchShift *(*CreatePitchShift)();
};

#endif // _RSI_PLUGIN_PUBLIC_H_
