Collection of tools useful for audio production
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

423 lines
13KB

  1. /*
  2. * PatchCanvas test app
  3. */
  4. #include "canvastestapp.h"
  5. #include "ui_canvastestapp.h"
  6. #include <QMessageBox>
  7. #include <QSettings>
  8. #include <QVariant>
  9. #include <QGLWidget>
  10. struct group_name_to_id_t {
  11. int id;
  12. QString name;
  13. };
  14. struct port_name_to_id_t {
  15. int group_id;
  16. int port_id;
  17. QString name;
  18. };
  19. struct connection_to_id_t {
  20. int id;
  21. int port_out;
  22. int port_in;
  23. };
  24. static int last_group_id = 0;
  25. static int last_port_id = 0;
  26. static int last_connection_id = 0;
  27. static CanvasTestApp* main_gui = 0;
  28. static jack_client_t* jack_client = 0;
  29. static QList<group_name_to_id_t> used_group_names;
  30. static QList<port_name_to_id_t> used_port_names;
  31. static QList<connection_to_id_t> used_connections;
  32. int get_group_id(QString group_name)
  33. {
  34. for (int i=0; i < used_group_names.count(); i++)
  35. {
  36. if (used_group_names[i].name == group_name)
  37. {
  38. return used_group_names[i].id;
  39. }
  40. }
  41. return -1;
  42. }
  43. int get_port_id(QString full_port_name)
  44. {
  45. QString group_name = full_port_name.split(":").at(0);
  46. QString port_name = full_port_name.replace(group_name+":", "");
  47. int group_id = get_group_id(group_name);
  48. for (int i=0; i < used_port_names.count(); i++)
  49. {
  50. if (used_port_names[i].group_id == group_id && used_port_names[i].name == port_name)
  51. {
  52. return used_port_names[i].port_id;
  53. }
  54. }
  55. return -1;
  56. }
  57. QString get_full_port_name(int port_id)
  58. {
  59. int group_id = -1;
  60. QString group_name;
  61. QString port_name;
  62. for (int i=0; i < used_port_names.count(); i++)
  63. {
  64. if (used_port_names[i].port_id == port_id)
  65. {
  66. group_id = used_port_names[i].group_id;
  67. port_name = used_port_names[i].name;
  68. }
  69. }
  70. for (int i=0; i < used_group_names.count(); i++)
  71. {
  72. if (used_group_names[i].id == group_id)
  73. {
  74. group_name = used_group_names[i].name;
  75. }
  76. }
  77. return group_name+":"+port_name;
  78. }
  79. void canvas_callback(PatchCanvas::CallbackAction action, int value1, int value2, QString value_str)
  80. {
  81. qDebug("--------------------------- Callback called %i|%i|%i|%s", action, value1, value2, value_str.toStdString().data());
  82. switch (action)
  83. {
  84. case PatchCanvas::ACTION_PORT_INFO:
  85. QMessageBox::information(main_gui, "port info dialog", "dummy text here");
  86. break;
  87. case PatchCanvas::ACTION_PORT_RENAME:
  88. // Unused
  89. break;
  90. case PatchCanvas::ACTION_PORTS_CONNECT:
  91. jack_connect(jack_client, get_full_port_name(value1).toStdString().data(), get_full_port_name(value2).toStdString().data());
  92. break;
  93. case PatchCanvas::ACTION_PORTS_DISCONNECT:
  94. for (int i=0; i < used_connections.count(); i++)
  95. {
  96. if (used_connections[i].id == value1)
  97. {
  98. jack_disconnect(jack_client, get_full_port_name(used_connections[i].port_out).toStdString().data(), get_full_port_name(used_connections[i].port_in).toStdString().data());
  99. break;
  100. }
  101. }
  102. break;
  103. case PatchCanvas::ACTION_GROUP_INFO:
  104. QMessageBox::information(main_gui, "group info dialog", "dummy text here");
  105. break;
  106. case PatchCanvas::ACTION_GROUP_RENAME:
  107. // Unused
  108. break;
  109. case PatchCanvas::ACTION_GROUP_SPLIT:
  110. PatchCanvas::splitGroup(value1);
  111. break;
  112. case PatchCanvas::ACTION_GROUP_JOIN:
  113. PatchCanvas::joinGroup(value1);
  114. break;
  115. default:
  116. break;
  117. }
  118. }
  119. CanvasTestApp::CanvasTestApp(QWidget *parent) :
  120. QMainWindow(parent),
  121. ui(new Ui::CanvasTestApp)
  122. {
  123. ui->setupUi(this);
  124. settings = new QSettings("PatchCanvas", "Canvas-test-app");
  125. restoreGeometry(settings->value("Geometry").toByteArray());
  126. main_gui = this;
  127. used_group_names.clear();
  128. used_port_names.clear();
  129. used_connections.clear();
  130. scene = new PatchScene(this, ui->graphicsView);
  131. ui->graphicsView->setScene(scene);
  132. ui->graphicsView->setRenderHint(QPainter::Antialiasing, true);
  133. ui->graphicsView->setRenderHint(QPainter::TextAntialiasing, true);
  134. //ui->graphicsView->setRenderHint(QPainter::HighQualityAntialiasing, true);
  135. //ui->graphicsView->setViewport(new QGLWidget(ui->graphicsView));
  136. PatchCanvas::options_t options;
  137. options.auto_hide_groups = false;
  138. options.use_bezier_lines = true;
  139. options.antialiasing = PatchCanvas::ANTIALIASING_SMALL;
  140. options.eyecandy = PatchCanvas::EYECANDY_SMALL;
  141. options.theme_name = PatchCanvas::getDefaultThemeName();
  142. PatchCanvas::features_t features;
  143. features.group_info = false;
  144. features.group_rename = false;
  145. features.port_info = false;
  146. features.port_rename = false;
  147. features.handle_group_pos = true;
  148. PatchCanvas::setOptions(&options);
  149. PatchCanvas::setFeatures(&features);
  150. PatchCanvas::init(scene, canvas_callback, true);
  151. connect(this, SIGNAL(clientRegisterCallback(QString,bool)), SLOT(handle_clientRegisterCallback(QString,bool)));
  152. connect(this, SIGNAL(portRegisterCallback(int,bool)), SLOT(handle_portRegisterCallback(int,bool)));
  153. connect(this, SIGNAL(connectionCallback(int,int,bool)), SLOT(handle_connectionCallback(int,int,bool)));
  154. jack_client = jack_client_open("canvas-test-app", JackNullOption, 0);
  155. jack_set_client_registration_callback(jack_client, client_register_callback, 0);
  156. jack_set_port_registration_callback(jack_client, port_register_callback, 0);
  157. jack_set_port_connect_callback(jack_client, port_connect_callback, 0);
  158. jack_activate(jack_client);
  159. // query initial jack ports
  160. QList<QString> parsed_groups;
  161. const char** ports = jack_get_ports(jack_client, 0, 0, 0);
  162. if (ports) {
  163. for (int i=0; ports[i]; i++) {
  164. QString full_name(ports[i]);
  165. QString group_name = full_name.split(":").at(0);
  166. QString port_name = full_name.replace(group_name+":", "");
  167. int group_id = -1;
  168. if (parsed_groups.contains(group_name))
  169. {
  170. group_id = get_group_id(group_name);
  171. }
  172. else
  173. {
  174. group_id = last_group_id;
  175. group_name_to_id_t group_name_to_id;
  176. group_name_to_id.id = group_id;
  177. group_name_to_id.name = group_name;
  178. used_group_names.append(group_name_to_id);
  179. parsed_groups.append(group_name);
  180. PatchCanvas::addGroup(group_id, group_name);
  181. last_group_id++;
  182. }
  183. PatchCanvas::PortMode port_mode;
  184. PatchCanvas::PortType port_type;
  185. jack_port_t* jack_port = jack_port_by_name(jack_client, ports[i]);
  186. if (jack_port_flags(jack_port) & JackPortIsInput)
  187. port_mode = PatchCanvas::PORT_MODE_INPUT;
  188. else
  189. port_mode = PatchCanvas::PORT_MODE_OUTPUT;
  190. if (strcmp(jack_port_type(jack_port), JACK_DEFAULT_AUDIO_TYPE) == 0)
  191. port_type = PatchCanvas::PORT_TYPE_AUDIO_JACK;
  192. else
  193. port_type = PatchCanvas::PORT_TYPE_MIDI_JACK;
  194. port_name_to_id_t port_name_to_id;
  195. port_name_to_id.group_id = group_id;
  196. port_name_to_id.port_id = last_port_id;
  197. port_name_to_id.name = port_name;
  198. used_port_names.append(port_name_to_id);
  199. PatchCanvas::addPort(group_id, last_port_id, port_name, port_mode, port_type);
  200. last_port_id++;
  201. }
  202. jack_free(ports);
  203. }
  204. // query connections, after all ports are in place
  205. ports = jack_get_ports(jack_client, 0, 0, JackPortIsOutput);
  206. if (ports) {
  207. for (int i=0; ports[i]; i++) {
  208. QString this_full_name(ports[i]);
  209. int this_port_id = get_port_id(this_full_name);
  210. jack_port_t* jack_port = jack_port_by_name(jack_client, ports[i]);
  211. const char** connections = jack_port_get_connections(jack_port);
  212. if (connections) {
  213. for (int j=0; connections[j]; j++) {
  214. QString target_full_name(connections[j]);
  215. int target_port_id = get_port_id(target_full_name);
  216. connection_to_id_t connection;
  217. connection.id = last_connection_id;
  218. connection.port_out = this_port_id;
  219. connection.port_in = target_port_id;
  220. used_connections.append(connection);
  221. PatchCanvas::connectPorts(last_connection_id, this_port_id, target_port_id);
  222. last_connection_id++;
  223. }
  224. jack_free(connections);
  225. }
  226. }
  227. jack_free(ports);
  228. }
  229. }
  230. CanvasTestApp::~CanvasTestApp()
  231. {
  232. delete settings;
  233. delete scene;
  234. delete ui;
  235. }
  236. void CanvasTestApp::client_register_callback(const char* name, int register_, void*)
  237. {
  238. main_gui->emit clientRegisterCallback(QString(name), bool(register_));
  239. }
  240. void CanvasTestApp::port_register_callback(jack_port_id_t port_id_jack, int register_, void*)
  241. {
  242. main_gui->emit portRegisterCallback(port_id_jack, bool(register_));
  243. }
  244. void CanvasTestApp::port_connect_callback(jack_port_id_t port_a, jack_port_id_t port_b, int connect, void*)
  245. {
  246. main_gui->emit connectionCallback(port_a, port_b, bool(connect));
  247. }
  248. void CanvasTestApp::handle_clientRegisterCallback(QString name, bool yesno)
  249. {
  250. QString qname(name);
  251. if (yesno)
  252. {
  253. group_name_to_id_t group_name_to_id;
  254. group_name_to_id.id = last_group_id;
  255. group_name_to_id.name = qname;
  256. used_group_names.append(group_name_to_id);
  257. PatchCanvas::addGroup(last_group_id, qname);
  258. last_group_id++;
  259. }
  260. else
  261. {
  262. for (int i=0; i < used_group_names.count(); i++)
  263. {
  264. if (used_group_names[i].name == qname)
  265. {
  266. PatchCanvas::removeGroup(used_group_names[i].id);
  267. used_group_names.takeAt(i);
  268. break;
  269. }
  270. }
  271. }
  272. }
  273. void CanvasTestApp::handle_portRegisterCallback(int port, bool yesno)
  274. {
  275. jack_port_t* jack_port = jack_port_by_id(jack_client, port);
  276. QString full_name(jack_port_name(jack_port));
  277. QString group_name = full_name.split(":").at(0);
  278. QString port_name = full_name.replace(group_name+":", "");
  279. int group_id = get_group_id(group_name);
  280. if (yesno)
  281. {
  282. PatchCanvas::PortMode port_mode;
  283. PatchCanvas::PortType port_type;
  284. if (jack_port_flags(jack_port) & JackPortIsInput)
  285. port_mode = PatchCanvas::PORT_MODE_INPUT;
  286. else
  287. port_mode = PatchCanvas::PORT_MODE_OUTPUT;
  288. if (strcmp(jack_port_type(jack_port), JACK_DEFAULT_AUDIO_TYPE) == 0)
  289. port_type = PatchCanvas::PORT_TYPE_AUDIO_JACK;
  290. else
  291. port_type = PatchCanvas::PORT_TYPE_MIDI_JACK;
  292. port_name_to_id_t port_name_to_id;
  293. port_name_to_id.group_id = group_id;
  294. port_name_to_id.port_id = last_port_id;
  295. port_name_to_id.name = port_name;
  296. used_port_names.append(port_name_to_id);
  297. PatchCanvas::addPort(group_id, last_port_id, port_name, port_mode, port_type);
  298. last_port_id++;
  299. }
  300. else
  301. {
  302. for (int i=0; i < used_port_names.count(); i++)
  303. {
  304. if (used_port_names[i].group_id == group_id && used_port_names[i].name == port_name)
  305. {
  306. PatchCanvas::removePort(used_port_names[i].port_id);
  307. used_port_names.takeAt(i);
  308. break;
  309. }
  310. }
  311. }
  312. }
  313. void CanvasTestApp::handle_connectionCallback(int port_a, int port_b, bool yesno)
  314. {
  315. jack_port_t* jack_port_a = jack_port_by_id(jack_client, port_a);
  316. jack_port_t* jack_port_b = jack_port_by_id(jack_client, port_b);
  317. int port_id_a = get_port_id(QString(jack_port_name(jack_port_a)));
  318. int port_id_b = get_port_id(QString(jack_port_name(jack_port_b)));
  319. if (yesno)
  320. {
  321. connection_to_id_t connection;
  322. connection.id = last_connection_id;
  323. connection.port_out = port_id_a;
  324. connection.port_in = port_id_b;
  325. used_connections.append(connection);
  326. PatchCanvas::connectPorts(last_connection_id, port_id_a, port_id_b);
  327. last_connection_id++;
  328. }
  329. else
  330. {
  331. for (int i=0; i < used_connections.count(); i++)
  332. {
  333. if (used_connections[i].port_out == port_id_a && used_connections[i].port_in == port_id_b)
  334. {
  335. PatchCanvas::disconnectPorts(used_connections[i].id);
  336. used_connections.takeAt(i);
  337. break;
  338. }
  339. }
  340. }
  341. }
  342. void CanvasTestApp::closeEvent(QCloseEvent* event)
  343. {
  344. jack_deactivate(jack_client);
  345. jack_client_close(jack_client);
  346. PatchCanvas::clear();
  347. settings->setValue("Geometry", QVariant(saveGeometry()));
  348. QMainWindow::closeEvent(event);
  349. }
  350. // -------------------------------------------------------------------------------------------------------
  351. #include <QtGui/QApplication>
  352. int main(int argc, char *argv[])
  353. {
  354. QApplication a(argc, argv);
  355. CanvasTestApp w;
  356. w.show();
  357. return a.exec();
  358. }