/* jack.vapi
 *
 * Copyright (C) 2009  Alberto Colombo
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 *
 * As a special exception, if you use inline functions from this file, this
 * file does not by itself cause the resulting executable to be covered by
 * the GNU Lesser General Public License.
 * 
 * Authors:
 * 	Alberto Colombo <albx79@gmail.com>
 *	Raffaele Sandrini <rasa@gmx.ch>
 *	Mathias Hasselmann <mathias.hasselmann@gmx.de>
 *  Harry Van Haaren
 */

// NOTES: 
//  1) there are no bindings for deprecated methods;
//  2) this vapi file is to be considered "beta" version, since some bindings may be incorrect; 
//     however, correct bindings are not subject to change.

[CCode (lower_case_cprefix = "jack_", cheader_filename = "jack/jack.h")]
namespace Jack {
    public const int MAX_FRAMES;
    public const int LOAD_INIT_LIMIT;
    public const string DEFAULT_AUDIO_TYPE;
    public const string DEFAULT_MIDI_TYPE;
    [CCode (cname = "JackOpenOptions")]
    public const Options OPEN_OPTIONS;
    [CCode (cname = "JackLoadOptions")]
    public const Options LOAD_OPTIONS;

    [SimpleType]
    [CCode (cname = "jack_shmsize_t")]
    public struct ShmSize : int32 {}    
    [SimpleType]
    [IntegerType (rank = 7)]
    [CCode (cname = "jack_nframes_t", cheader_filename = "jack/jack.h",  type_id = "G_TYPE_UINT", marshaller_type_name = "UINT", get_value_function = "g_value_get_uint", set_value_function = "g_value_set_uint", default_value = "0U", type_signature = "u")]
    public struct NFrames : uint32 {}
    [SimpleType]
    [CCode (cname = "jack_time_t")]
    public struct Time : uint64 {}
    [SimpleType]
    [CCode (cname = "jack_intclient_t", cprefix = "jack_internal_client", cheader_filename = "jack/intclient.h")]
    public struct InternalClient : uint64 {
        public static void close (string name);
    }
    [Compact]
    [CCode (cname = "jack_port_t", cprefix = "jack_port_")]
    public class Port {
        public void* get_buffer (NFrames nframes);
        public unowned string name ();
        public unowned string short_name ();
        public int flags ();
        public unowned string type ();
        public bool connected ();
        public bool connected_to (string name);
        [CCode (array_null_terminated = true)]
        [CCode (array_length = false)]
        public string[] get_connections ();
        public NFrames get_latency ();
        public NFrames get_total_latency ();
        public void set_latency (NFrames nframes);
        public int set_name (string name);
        public int set_alias (string alias);
        public int unset_alias (string alias);        
        public int get_aliases ([CCode (array_null_terminated = true, array_length = false)] out unowned string[] aliases);
        public int request_monitor (bool onoff);
        public int ensure_monitor (bool onoff);
        public int monitoring_input ();
        public static int name_size ();
        public static int type_size ();

        [CCode (cname = "enum JackPortFlags")]
        [Flags]
        public enum Flags{
           [CCode (cname = "JackPortIsInput")]    IS_INPUT,
           [CCode (cname = "JackPortIsOutput")]   IS_OUTPUT,
           [CCode (cname = "JackPortIsPhysical")] IS_PHYSICAL,
           [CCode (cname = "JackPortCanMonitor")] CAN_MONITOR,
           [CCode (cname = "JackPortIsTerminal")] IS_TERMINAL
        }        
    }
    [Compact]
    [CCode (cname = "jack_client_t", free_function = "jack_client_close", cprefix = "jack_")]
    public class Client {
        // creation and manipulation
        [CCode (cname = "jack_client_open")]
        public static Client? open (string name, Jack.Options options, out Jack.Status status, ...);
        [CCode (cname = "jack_client_name_size")]
        public static int get_name_size();
        [CCode (cname = "jack_get_client_name")]
        public string get_name ();
        public int activate ();
        public int deactivate ();
        /*
        [CCode (cname="jack_client_thread_id")]
        public GLib.Thread get_thread_id();
        */
        
        // setting callbacks 
        public int set_thread_init_callback (ThreadInitCallback cb);
        public void on_shutdown (ShutdownFunc f);
        public int set_process_callback (ProcessCallback cb);
        public int set_freewheel_callback (FreewheelCallback cb);
        public int set_buffer_size_callback (BufferSizeCallback cb);
        public int set_sample_rate_callback (SampleRateCallback cb);
        public int set_client_registration_callback (ClientRegistrationCallback cb);
        public int set_port_registration_callback (PortRegistrationCallback cb);
        public int set_port_connect_callback (PortConnectCallback cb);
        public int set_graph_order_callback (GraphOrderCallback cb);
        public int set_xrun_callback (XRunCallback cb);
        
        // controlling and querying server operations
        /*
        [CCode (cname="jack_client_create_thread")]
        public int create_thread(out GLib.Thread thread, int priority, bool realtime, ThreadCallback cb);
        */
        [CCode (cname = "jack_client_real_time_priority")]
        public int get_real_time_priority ();
        [CCode (cname = "jack_client_max_real_time_priority")]
        public int get_max_real_time_priority ();
        public bool is_realtime ();
        public int set_freewheel (bool onoff);
        public int set_buffer_size (NFrames nframes);
        public NFrames get_sample_rate ();
        public NFrames get_buffer_size ();
        public float cpu_load ();
        
        // creating and manipulating ports
        public unowned Port port_register (string name, string type, Port.Flags flags, ulong buffer_size);
        public int port_unregister (Port p);
        public bool port_is_mine (Port p);
        [CCode (array_null_terminated = true, array_length = false)]
        public string[] port_get_all_connections (Port p);
        public int recompute_total_latency (Port p);
        public int recompute_total_latencies ();
        public int port_request_monitor_by_name (string port_name, bool onoff);
        public int connect (string source_port, string destination_port);
        public int disconnect (string source_port, string destination_port);
        public int port_disconnect (Port p);
        
        // looking up ports
        [CCode (array_null_terminated = true, array_length = false)]
        public unowned string[] get_ports (string name_pattern, string type_pattern, Port.Flags flags);
        public unowned Port port_by_name (string name);
        public unowned Port port_by_id (PortId id);
        
        // handling time
        public NFrames frames_since_cycle_start ();
        public NFrames frame_time ();
        public NFrames last_frame_time ();
        public Time frames_to_time (NFrames nframes);
        public NFrames time_to_frames (Time t);
        public Time get_time ();
        
        // non-callback API
        public NFrames cycle_wait ();
        public void cycle_signal (bool should_exit);
        public int set_process_thread (ThreadCallback cb);
        
        // statistics
        [CCode (cheader_filename = "jack/statistics.h")]
        public float get_max_delayed_usecs ();
        [CCode (cheader_filename = "jack/statistics.h")]
        public float get_xrun_delayed_usecs ();
        [CCode (cheader_filename = "jack/statistics.h")]
        public void reset_max_delayed_usecs ();
        
        // internal clients
        [CCode (cheader_filename = "jack/intclient.h")]
        public string get_internal_client_name (InternalClient intclient);
        [CCode (cheader_filename = "jack/intclient.h")]
        public InternalClient internal_client_handle (string name, out Status s);
        public InternalClient internal_client_load (string name, Options opts, out Status s, ...);
        public Status internal_client_unload (InternalClient intclient);
        
        // transport and timebase control
        public int release_timebase ();
        public int set_sync_callback (SyncCallback cb);
        public int set_sync_timeout (Jack.Time timeout);
        public int set_timebase_callback (bool conditional, TimebaseCallback cb);
        public int transport_locate (NFrames frame);
        public TransportState transport_query (out Position pos);
        public NFrames get_current_transport_frame ();
        public int transport_reposition (ref Position p);
        public void transport_start ();
        public void transport_stop ();
    }
    [SimpleType]
    [CCode (cname = "jack_port_id_t")]
    public struct PortId : uint32 {}
    
    public delegate void* ThreadCallback ();
    public delegate void ThreadInitCallback ();
    public delegate void ShutdownFunc ();
    public delegate int ProcessCallback (NFrames nframes);
    public delegate void FreewheelCallback (bool starting);
    public delegate int BufferSizeCallback (NFrames nframes);
    public delegate int SampleRateCallback (NFrames nframes);
    // do not change the parameter name to "register" because it will generate
    // errors at C-compile time
    public delegate void ClientRegistrationCallback (string name, bool reg);
    public delegate void PortRegistrationCallback (PortId id, bool reg);
    public delegate void PortConnectCallback (PortId a, PortId b, bool connect);
    public delegate int GraphOrderCallback ();
    public delegate int XRunCallback ();
    
    [SimpleType]
    [CCode (cname = "jack_default_audio_sample_t")]
    public struct DefaultAudioSample : float {}
        
    [CCode (cname = "jack_options_t")]
    [Flags]
    public enum Options {
        [CCode (cname = "JackNullOption")]    NULL_OPTION, 
        [CCode (cname = "JackNoStartServer")] NO_START_SERVER, 
        [CCode (cname = "JackUseExactName")]  USE_EXACT_NAME, 
        [CCode (cname = "JackServerName")]    SERVER_NAME, 
        [CCode (cname = "JackLoadName")]      LOAD_NAME, 
        [CCode (cname = "JackLoadInit")]      LOAD_INIT
    }
    
    [CCode (cname = "jack_status_t")]
    [Flags]
    public enum Status {
        [CCode (cname = "JackFailure")]       FAILURE, 
        [CCode (cname = "JackInvalidOption")] INVALID_OPTION, 
        [CCode (cname = "JackNameNotUnique")] NAME_NOT_UNIQUE, 
        [CCode (cname = "JackServerStarted")] SERVER_STARTED, 
        [CCode (cname = "JackServerFailed")]  SERVER_FAILED, 
        [CCode (cname = "JackServerError")]   SERVER_ERROR,
        [CCode (cname = "JackNoSuchClient")]  NO_SUCH_CLIENT,
        [CCode (cname = "JackLoadFailure")]   LOAD_FAILURE,
        [CCode (cname = "JackInitFailure")]   INIT_FAILURE,
        [CCode (cname = "JackShmFailure")]    SHM_FAILURE,
        [CCode (cname = "JackVersionError")]  VERSION_ERROR,
        [CCode (cname = "JackBackendError")]  BACKEND_ERROR,
        [CCode (cname = "JackClientZombie")]  CLIENT_ZOMBIE
    }

    /*    
    public int drop_real_time_scheduling(GLib.Thread t);
    public int acquire_real_time_scheduling(GLib.Thread t, int priority);
    */
    
    // error / information output
    [CCode (has_target = false)]
    public delegate void MessageFunc (string msg);
    void set_error_function (MessageFunc f);
    void set_info_function (MessageFunc f);    
    public MessageFunc error_callback;
    public MessageFunc info_callback;
    [CCode (cname = "default_jack_error_callback")]
    public void default_error_callback (string msg);
    [CCode (cname = "silent_jack_error_callback")]
    public void silent_error_callback (string msg);
    
    // MIDI
    [CCode (lower_case_cprefix = "jack_midi_", cheader_filename = "jack/midiport.h")]
    namespace Midi {
        [SimpleType]
        [CCode (cname = "jack_midi_data_t")]
        public struct Data : uchar {}
        [CCode (cname = "jack_midi_event_t", cprefix = "jack_midi_event_", destroy_function = "")]
        public struct Event {
            public NFrames time;
            public size_t size;
            [CCode (array_length_cname = "size")]
            public unowned Data[] buffer;
            public static int get (out Event e, void *port_buffer, NFrames event_index);
            public static Data* reserve (void *port_buffer, NFrames time, size_t data_size);
            public static int write (void *port_buffer, NFrames time, Data* data, size_t data_size);
        }
        public NFrames get_event_count (void *port_buffer);
        public void clear_buffer (void *port_buffer);
        public size_t max_event_size (void *port_buffer);
        public NFrames get_lost_event_count (void *port_buffer);
    }
    
    // ringbuffer
    [Compact]
    [CCode (cname = "jack_ringbuffer_t", cprefix ="jack_ringbuffer_", free_function="jack_ringbuffer_free", cheader_filename = "jack/ringbuffer.h")]
    public class Ringbuffer {
        [CCode (cname = "jack_ringbuffer_data_t")]
        public struct Data {
            [CCode (array_length = false)]
            public uint8[] buf;
        }
        
        [CCode (array_length_cname = "size", array_length_type = "size_t")]
        public uint8[] buf;
        public size_t write_ptr;
        public size_t read_ptr;
        public size_t size;
        public size_t size_mask;
        public int mlocked;
        
        public static Ringbuffer create (size_t sz);
        public void get_read_vector ([CCode (array_length = false)] out unowned Data[] vec);
        public void get_write_vector ([CCode (array_length = false)] out unowned Data[] vec);
        public size_t read ([CCode (array_length_type = "size_t")] uint8[] dest);
        public size_t peek ([CCode (array_length_type = "size_t")] uint8[] dest);
        public void read_advance (size_t cnt);
        public size_t read_space ();
        public int mlock ();
        public void reset ();
        public size_t write ([CCode (array_length_type = "size_t")] uint8[] src);
        public void write_advance (size_t cnt);
        public size_t write_space ();        
    }
 
    // transport and timebase
    public delegate int SyncCallback (TransportState s, Position p);
    public delegate void TimebaseCallback (TransportState s, NFrames nframes, Position p); 
    [CCode (cname = "jack_transport_state_t")]
    public enum TransportState {
        [CCode (cname = "JackTransportStopped")]  STOPPED,
        [CCode (cname = "JackTransportRolling")]  ROLLING,
        [CCode (cname = "JackTransportLooping")]  LOOPING,
        [CCode (cname = "JackTransportStarting")] STARTING
    }
    
    [SimpleType]
    [CCode (cname = "jack_unique_t")]
    public struct Unique : uint64 {}
    
    [CCode (cname = "enum jack_position_bits_t")]
    [Flags]
    public enum PositionBits {
        [CCode (cname = "JackPositionBBT")]       POSITION_BBT,
        [CCode (cname = "JackPositionTimecode")]  POSITION_TIMECODE,
        [CCode (cname = "JackBBTFrameOffset")]    BBT_FRAME_OFFSET,
        [CCode (cname = "JackAudioVideoRatio")]   AUDIO_VIDEO_RATIO,
        [CCode (cname = "JackVideoFrameOffset")]  VIDEO_FRAME_OFFSET
    }

    [CCode (cname = "jack_position_t", free_function = "", destroy_function = "")]
    public struct Position {
        public Unique 	unique_1;
        public Jack.Time 	usecs;
        public NFrames 	frame_rate;
        public NFrames 	frame;
        public PositionBits 	valid;
        public int32 	bar;
        public int32 	beat;
        public int32 	tick;
        public double 	bar_start_tick;
        public float 	beats_per_bar;
        public float 	beat_type;
        public double 	ticks_per_beat;
        public double 	beats_per_minute;
        public double 	frame_time;
        public double 	next_time;
        public NFrames 	bbt_offset;
        public float 	audio_frames_per_video_frame;
        public NFrames 	video_offset;
        public int32	padding[7];
        public Unique 	unique_2;
    }
}

