1 /* Calf DSP Library Utility Application - calfjackhost
2  * API wrapper for JACK Audio Connection Kit
3  *
4  * Copyright (C) 2007 Krzysztof Foltman
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301, USA.
20  */
21 #ifndef __CALF_JACKHOST_H
22 #define __CALF_JACKHOST_H
23 
24 #include <config.h>
25 
26 #if USE_JACK
27 
28 #include "utils.h"
29 #include "vumeter.h"
30 #include <pthread.h>
31 #include <jack/jack.h>
32 #include <jack/session.h>
33 
34 #ifdef OLD_JACK
35 #define NFRAMES_MAYBE(nframes) nframes
36 #else
37 #define NFRAMES_MAYBE(nframes)
38 #endif
39 
40 namespace calf_plugins {
41 
42 class jack_host;
43 
44 struct automation_iface
45 {
46     virtual uint32_t apply_and_adjust(uint32_t start, uint32_t time) = 0;
~automation_ifaceautomation_iface47     virtual ~automation_iface() {}
48 };
49 
50 class jack_client {
51 protected:
52     std::vector<jack_host *> plugins;
53     calf_utils::ptmutex mutex;
54 
55     /// Common port for MIDI parameter automation
56     jack_port_t *automation_port;
57 
58 public:
59     jack_client_t *client;
60     int input_nr, output_nr, midi_nr;
61     std::string name, input_name, output_name, midi_name;
62     int sample_rate;
63 
64     jack_client();
65     void add(jack_host *plugin);
66     void del(jack_host *plugin);
67     void open(const char *client_name, const char *jack_session_id);
68     std::string get_name();
69     void activate();
70     void deactivate();
71     void delete_plugins();
72     void create_automation_input();
73     void destroy_automation_input();
74     void connect(const std::string &p1, const std::string &p2);
75     void close();
76     void apply_plugin_order(const std::vector<int> &indices);
77     void calculate_plugin_order(std::vector<int> &indices);
78     const char **get_ports(const char *name_re, const char *type_re, unsigned long flags);
79 
80     static int do_jack_process(jack_nframes_t nframes, void *p);
81     static int do_jack_bufsize(jack_nframes_t numsamples, void *p);
82     template<class T>
atomic_swap(T & v1,T & v2)83     void atomic_swap(T &v1, T &v2)
84     {
85         calf_utils::ptlock lock(mutex);
86         std::swap(v1, v2);
87     }
88 };
89 
90 class jack_host: public plugin_ctl_iface {
91 public:
92     struct port {
93         jack_port_t *handle;
94         float *data;
95         std::string name, nice_name;
96         dsp::vumeter meter;
portport97         port() : handle(NULL), data(NULL) {}
~portport98         ~port() { }
99     };
100 public:
101     float **ins, **outs, **params;
102     std::vector<port> inputs, outputs;
103     float *param_values;
104     float midi_meter;
105     audio_module_iface *module;
106     automation_map *cc_mappings;
107     std::vector<int> write_serials;
108     int last_modify_serial;
109     uint32_t last_designator;
110 
111 public:
112     typedef int (*process_func)(jack_nframes_t nframes, void *p);
113     jack_client *client;
114     bool changed;
115     port midi_port;
116     std::string name;
117     std::string instance_name;
118     int in_count, out_count, param_count;
119     const plugin_metadata_iface *metadata;
120 
121 public:
122     jack_host(jack_client *_client, audio_module_iface *_module, const std::string &_name, const std::string &_instance_name, calf_plugins::progress_report_iface *_priface);
123     void create();
124     void create_ports();
125     void rename_ports();
126     void init_module();
127     void destroy();
128     ~jack_host();
129 
130     void rename(std::string name);
131     /// Handle JACK MIDI port data
132     void handle_event(uint8_t *buffer, uint32_t size);
133     /// Process audio and update meters
134     void process_part(unsigned int time, unsigned int len);
135     /// Get meter value for the Nth port
136     virtual float get_level(unsigned int port);
137     /// Process audio/MIDI buffers
138     int process(jack_nframes_t nframes, automation_iface &automation);
139     /// Retrieve and cache output port buffers
140     void cache_ports();
141     /// Retrieve the full list of input ports, audio+MIDI (the pointers are temporary, may point to nowhere after any changes etc.)
142     void get_all_input_ports(std::vector<port *> &ports);
143     /// Retrieve the full list of output ports (the pointers are temporary, may point to nowhere after any changes etc.)
144     void get_all_output_ports(std::vector<port *> &ports);
145     void handle_automation_cc(uint32_t designator, int value);
146 
147 public:
148     // Port access
get_inputs()149     port *get_inputs() { return inputs.empty() ? NULL : &inputs[0]; }
get_outputs()150     port *get_outputs() { return outputs.empty() ? NULL : &outputs[0]; }
get_params()151     float *get_params() { return param_values; }
get_midi_port()152     port *get_midi_port() { return get_metadata_iface()->get_midi() ? &midi_port : NULL; }
153 public:
154     // Implementations of methods in plugin_ctl_iface
activate_preset(int bank,int program)155     bool activate_preset(int bank, int program) { return false; }
get_param_value(int param_no)156     virtual float get_param_value(int param_no) {
157         assert(param_no >= 0 && param_no < param_count);
158         return param_values[param_no];
159     }
set_param_value(int param_no,float value)160     virtual void set_param_value(int param_no, float value) {
161         assert(param_no >= 0 && param_no < param_count);
162         param_values[param_no] = value;
163         changed = true;
164     }
get_instance_name()165     virtual std::string get_instance_name() { return instance_name; }
execute(int cmd_no)166     virtual void execute(int cmd_no) { module->execute(cmd_no); }
167     virtual char *configure(const char *key, const char *value);
send_configures(send_configure_iface * sci)168     virtual void send_configures(send_configure_iface *sci) { module->send_configures(sci); }
169     virtual void send_automation_configures(send_configure_iface *);
send_status_updates(send_updates_iface * sui,int last_serial)170     virtual int send_status_updates(send_updates_iface *sui, int last_serial) { return module->send_status_updates(sui, last_serial); }
get_metadata_iface()171     virtual const plugin_metadata_iface *get_metadata_iface() const { return module->get_metadata_iface(); }
get_line_graph_iface()172     virtual const line_graph_iface *get_line_graph_iface() const { return module->get_line_graph_iface(); }
get_phase_graph_iface()173     virtual const phase_graph_iface *get_phase_graph_iface() const { return module->get_phase_graph_iface(); }
get_write_serial(int param_no)174     virtual int get_write_serial(int param_no) { return write_serials[param_no]; }
175     virtual void add_automation(uint32_t source, const automation_range &dest);
176     virtual void delete_automation(uint32_t source, int param_no);
177     virtual void get_automation(int param_no, std::multimap<uint32_t, automation_range> &dests);
178     virtual uint32_t get_last_automation_source();
179     void replace_automation_map(automation_map *amap);
180 };
181 
182 extern jack_host *create_jack_host(jack_client *_client, const char *name, const std::string &instance_name, calf_plugins::progress_report_iface *priface);
183 
184 };
185 
186 #endif
187 
188 #endif
189