@@ -783,7 +783,9 @@ typedef enum { | |||||
/*! | /*! | ||||
* A patchbay client has been added. | * A patchbay client has been added. | ||||
* @param pluginId Client Id | * @param pluginId Client Id | ||||
* @param valueStr Client name and icon, as "name:icon" | |||||
* @param value1 Client icon | |||||
* @param valueStr Client name | |||||
* @see PatchbayIcon | |||||
*/ | */ | ||||
ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED = 19, | ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED = 19, | ||||
@@ -803,7 +805,8 @@ typedef enum { | |||||
/*! | /*! | ||||
* A patchbay client icon has changed. | * A patchbay client icon has changed. | ||||
* @param pluginId Client Id | * @param pluginId Client Id | ||||
* @param valueStr New icon name | |||||
* @param value1 New icon | |||||
* @see PatchbayIcon | |||||
*/ | */ | ||||
ENGINE_CALLBACK_PATCHBAY_CLIENT_ICON_CHANGED = 22, | ENGINE_CALLBACK_PATCHBAY_CLIENT_ICON_CHANGED = 22, | ||||
@@ -1083,6 +1086,50 @@ typedef enum { | |||||
} EngineTransportMode; | } EngineTransportMode; | ||||
// ------------------------------------------------------------------------------------------------------------ | |||||
// Patchbay Icon | |||||
/*! | |||||
* The icon of a patchbay client/group. | |||||
*/ | |||||
enum PatchbayIcon { | |||||
/*! | |||||
* Generic application icon.\n | |||||
* Used for all non-plugin clients that don't have a specific icon. | |||||
*/ | |||||
PATCHBAY_ICON_APPLICATION = 0, | |||||
/*! | |||||
* Plugin icon.\n | |||||
* Used for all plugin clients that don't have a specific icon. | |||||
*/ | |||||
PATCHBAY_ICON_PLUGIN = 1, | |||||
/*! | |||||
* Hardware icon.\n | |||||
* Used for hardware (audio or MIDI) clients. | |||||
*/ | |||||
PATCHBAY_ICON_HARDWARE = 2, | |||||
/*! | |||||
* Carla icon.\n | |||||
* Used for the main app. | |||||
*/ | |||||
PATCHBAY_ICON_CARLA = 3, | |||||
/*! | |||||
* DISTRHO icon.\n | |||||
* Used for DISTRHO based plugins. | |||||
*/ | |||||
PATCHBAY_ICON_DISTRHO = 4, | |||||
/*! | |||||
* File icon.\n | |||||
* Used for file type plugins (like GIG and SF2). | |||||
*/ | |||||
PATCHBAY_ICON_FILE = 5 | |||||
}; | |||||
// ------------------------------------------------------------------------------------------------------------ | // ------------------------------------------------------------------------------------------------------------ | ||||
// Carla Backend API (C stuff) | // Carla Backend API (C stuff) | ||||
@@ -474,7 +474,7 @@ public: | |||||
fUsedGroupNames.clear(); | fUsedGroupNames.clear(); | ||||
fUsedPortNames.clear(); | fUsedPortNames.clear(); | ||||
fUsedConnections.clear(); | fUsedConnections.clear(); | ||||
fGroupIconsChanged.clear(); | |||||
//fGroupIconsChanged.clear(); | |||||
#endif | #endif | ||||
} | } | ||||
@@ -551,7 +551,7 @@ public: | |||||
fUsedGroupNames.clear(); | fUsedGroupNames.clear(); | ||||
fUsedPortNames.clear(); | fUsedPortNames.clear(); | ||||
fUsedConnections.clear(); | fUsedConnections.clear(); | ||||
fGroupIconsChanged.clear(); | |||||
//fGroupIconsChanged.clear(); | |||||
fClient = jackbridge_client_open(clientName, JackNullOption, nullptr); | fClient = jackbridge_client_open(clientName, JackNullOption, nullptr); | ||||
@@ -647,7 +647,7 @@ public: | |||||
fUsedGroupNames.clear(); | fUsedGroupNames.clear(); | ||||
fUsedPortNames.clear(); | fUsedPortNames.clear(); | ||||
fUsedConnections.clear(); | fUsedConnections.clear(); | ||||
fGroupIconsChanged.clear(); | |||||
//fGroupIconsChanged.clear(); | |||||
return false; | return false; | ||||
#endif | #endif | ||||
@@ -927,7 +927,7 @@ public: | |||||
fUsedGroupNames.clear(); | fUsedGroupNames.clear(); | ||||
fUsedPortNames.clear(); | fUsedPortNames.clear(); | ||||
fUsedConnections.clear(); | fUsedConnections.clear(); | ||||
fGroupIconsChanged.clear(); | |||||
//fGroupIconsChanged.clear(); | |||||
initJackPatchbay(jackbridge_get_client_name(fClient)); | initJackPatchbay(jackbridge_get_client_name(fClient)); | ||||
@@ -1201,6 +1201,7 @@ protected: | |||||
} | } | ||||
#ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
# if 0 | |||||
void handleCustomAppearanceCallback(const char* client_name, const char* key, jack_custom_change_t change) | void handleCustomAppearanceCallback(const char* client_name, const char* key, jack_custom_change_t change) | ||||
{ | { | ||||
if ((change == JackCustomAdded || change == JackCustomReplaced) && std::strcmp(key, URI_CANVAS_ICON) == 0) | if ((change == JackCustomAdded || change == JackCustomReplaced) && std::strcmp(key, URI_CANVAS_ICON) == 0) | ||||
@@ -1213,6 +1214,7 @@ protected: | |||||
fGroupIconsChanged.append(groupId); | fGroupIconsChanged.append(groupId); | ||||
} | } | ||||
} | } | ||||
# endif | |||||
void handleJackClientRegistrationCallback(const char* const name, const bool reg) | void handleJackClientRegistrationCallback(const char* const name, const bool reg) | ||||
{ | { | ||||
@@ -1227,7 +1229,7 @@ protected: | |||||
GroupNameToId groupNameId(id, name); | GroupNameToId groupNameId(id, name); | ||||
fUsedGroupNames.removeAll(groupNameId); | fUsedGroupNames.removeAll(groupNameId); | ||||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_REMOVED, 0, id, 0, 0.0f, name); | |||||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_REMOVED, id, 0, 0, 0.0f, nullptr); | |||||
} | } | ||||
void handleJackPortRegistrationCallback(const jack_port_id_t port, const bool reg) | void handleJackPortRegistrationCallback(const jack_port_id_t port, const bool reg) | ||||
@@ -1265,13 +1267,13 @@ protected: | |||||
if (jackPortFlags & JackPortIsPhysical) | if (jackPortFlags & JackPortIsPhysical) | ||||
{ | { | ||||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, 0, groupId, 0, 0.0f, groupName); | |||||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, groupId, PATCHBAY_ICON_HARDWARE, 0, 0.0f, groupName); | |||||
// hardware | // hardware | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, 0, groupId, 0, 0.0f, groupName); | |||||
fGroupIconsChanged.append(groupId); | |||||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, groupId, 0, 0, 0.0f, groupName); | |||||
//fGroupIconsChanged.append(groupId); | |||||
// "application" | // "application" | ||||
} | } | ||||
} | } | ||||
@@ -1305,7 +1307,7 @@ protected: | |||||
PortNameToId portNameId(groupId, portId, portName, fullPortName); | PortNameToId portNameId(groupId, portId, portName, fullPortName); | ||||
fUsedPortNames.removeOne(portNameId); | fUsedPortNames.removeOne(portNameId); | ||||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED, 0, groupId, portId, 0.0f, portName); | |||||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED, groupId, portId, 0, 0.0f, nullptr); | |||||
} | } | ||||
} | } | ||||
@@ -1368,7 +1370,7 @@ protected: | |||||
if (std::strcmp(groupNameToId.name, oldName) == 0) | if (std::strcmp(groupNameToId.name, oldName) == 0) | ||||
{ | { | ||||
groupNameToId.rename(newName); | groupNameToId.rename(newName); | ||||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_RENAMED, 0, groupNameToId.id, 0, 0.0f, newName); | |||||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_RENAMED, groupNameToId.id, 0, 0, 0.0f, newName); | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
@@ -1405,7 +1407,7 @@ protected: | |||||
{ | { | ||||
CARLA_ASSERT(portNameId.groupId == groupId); | CARLA_ASSERT(portNameId.groupId == groupId); | ||||
portNameId.rename(portName, newName); | portNameId.rename(portName, newName); | ||||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_RENAMED, 0, groupId, portNameId.portId, 0.0f, newName); | |||||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_RENAMED, groupId, portNameId.portId, 0, 0.0f, newName); | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
@@ -1568,14 +1570,11 @@ private: | |||||
List<GroupNameToId> fUsedGroupNames; | List<GroupNameToId> fUsedGroupNames; | ||||
List<PortNameToId> fUsedPortNames; | List<PortNameToId> fUsedPortNames; | ||||
List<ConnectionToId> fUsedConnections; | List<ConnectionToId> fUsedConnections; | ||||
List<int> fGroupIconsChanged; | |||||
//List<int> fGroupIconsChanged; | |||||
int getGroupId(const char* const name) | int getGroupId(const char* const name) | ||||
{ | { | ||||
CARLA_ASSERT(name != nullptr); | |||||
if (name == nullptr) | |||||
return -1; | |||||
CARLA_SAFE_ASSERT_RETURN(name != nullptr, -1); | |||||
for (List<GroupNameToId>::Itenerator it = fUsedGroupNames.begin(); it.valid(); it.next()) | for (List<GroupNameToId>::Itenerator it = fUsedGroupNames.begin(); it.valid(); it.next()) | ||||
{ | { | ||||
@@ -1590,12 +1589,9 @@ private: | |||||
const char* getGroupName(const int groupId) | const char* getGroupName(const int groupId) | ||||
{ | { | ||||
CARLA_ASSERT(groupId >= 0); | |||||
static const char fallback[1] = { '\0' }; | static const char fallback[1] = { '\0' }; | ||||
if (groupId < 0) | |||||
return fallback; | |||||
CARLA_SAFE_ASSERT_RETURN(groupId >= 0, fallback); | |||||
for (List<GroupNameToId>::Itenerator it = fUsedGroupNames.begin(); it.valid(); it.next()) | for (List<GroupNameToId>::Itenerator it = fUsedGroupNames.begin(); it.valid(); it.next()) | ||||
{ | { | ||||
@@ -1610,10 +1606,7 @@ private: | |||||
int getPortId(const char* const fullName) | int getPortId(const char* const fullName) | ||||
{ | { | ||||
CARLA_ASSERT(fullName != nullptr); | |||||
if (fullName == nullptr) | |||||
return -1; | |||||
CARLA_SAFE_ASSERT_RETURN(fullName != nullptr, -1); | |||||
for (List<PortNameToId>::Itenerator it = fUsedPortNames.begin(); it.valid(); it.next()) | for (List<PortNameToId>::Itenerator it = fUsedPortNames.begin(); it.valid(); it.next()) | ||||
{ | { | ||||
@@ -1645,27 +1638,22 @@ private: | |||||
void initJackPatchbay(const char* const ourName) | void initJackPatchbay(const char* const ourName) | ||||
{ | { | ||||
CARLA_ASSERT(fLastGroupId == 0); | |||||
CARLA_ASSERT(fLastPortId == 0); | |||||
CARLA_ASSERT(fLastConnectionId == 0); | |||||
CARLA_ASSERT(ourName != nullptr); | |||||
#ifdef HAVE_JUCE | |||||
using namespace juce; | |||||
CARLA_SAFE_ASSERT_RETURN(fLastGroupId == 0,); | |||||
CARLA_SAFE_ASSERT_RETURN(fLastPortId == 0,); | |||||
CARLA_SAFE_ASSERT_RETURN(fLastConnectionId == 0,); | |||||
CARLA_SAFE_ASSERT_RETURN(ourName != nullptr,); | |||||
// query initial jack ports | // query initial jack ports | ||||
StringArray parsedGroups; | |||||
QStringList parsedGroups; | |||||
// our client | // our client | ||||
if (ourName != nullptr) | |||||
{ | { | ||||
parsedGroups.add(String(ourName)); | |||||
parsedGroups.append(QString(ourName)); | |||||
GroupNameToId groupNameToId(fLastGroupId++, ourName); | GroupNameToId groupNameToId(fLastGroupId++, ourName); | ||||
fUsedGroupNames.append(groupNameToId); | fUsedGroupNames.append(groupNameToId); | ||||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, 0, groupNameToId.id, 0, 0.0f, ourName); | |||||
// carla | |||||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, groupNameToId.id, PATCHBAY_ICON_CARLA, 0, 0.0f, ourName); | |||||
} | } | ||||
if (const char** ports = jackbridge_get_ports(fClient, nullptr, nullptr, 0)) | if (const char** ports = jackbridge_get_ports(fClient, nullptr, nullptr, 0)) | ||||
@@ -1683,10 +1671,13 @@ private: | |||||
int groupId = -1; | int groupId = -1; | ||||
bool found; | |||||
CarlaString groupName(fullPortName); | CarlaString groupName(fullPortName); | ||||
groupName.truncate(groupName.rfind(portName)-1); | |||||
groupName.truncate(groupName.rfind(portName, &found)-1); | |||||
CARLA_ASSERT(found); | |||||
String qGroupName(groupName); | |||||
QString qGroupName((const char*)groupName); | |||||
if (parsedGroups.contains(qGroupName)) | if (parsedGroups.contains(qGroupName)) | ||||
{ | { | ||||
@@ -1696,37 +1687,55 @@ private: | |||||
else | else | ||||
{ | { | ||||
groupId = fLastGroupId++; | groupId = fLastGroupId++; | ||||
parsedGroups.add(qGroupName); | |||||
parsedGroups.append(qGroupName); | |||||
GroupNameToId groupNameToId(groupId, groupName); | GroupNameToId groupNameToId(groupId, groupName); | ||||
fUsedGroupNames.append(groupNameToId); | fUsedGroupNames.append(groupNameToId); | ||||
PatchbayIcon groupIcon = PATCHBAY_ICON_APPLICATION; | |||||
#if 0 | |||||
void* data = nullptr; | void* data = nullptr; | ||||
size_t dataSize = 0; | size_t dataSize = 0; | ||||
#endif | |||||
if (jackPortFlags & JackPortIsPhysical) | if (jackPortFlags & JackPortIsPhysical) | ||||
{ | { | ||||
// "hardware" | |||||
groupIcon = PATCHBAY_ICON_HARDWARE; | |||||
} | } | ||||
#if 0 | |||||
else if (jackbridge_custom_get_data(fClient, groupName, URI_CANVAS_ICON, &data, &dataSize) && data != nullptr && dataSize != 0) | else if (jackbridge_custom_get_data(fClient, groupName, URI_CANVAS_ICON, &data, &dataSize) && data != nullptr && dataSize != 0) | ||||
{ | { | ||||
//const char* const icon((const char*)data); | |||||
//CARLA_ASSERT(std::strlen(icon)+1 == dataSize); | |||||
// icon | |||||
const char* const icon((const char*)data); | |||||
CARLA_ASSERT(std::strlen(icon)+1 == dataSize); | |||||
if (std::strcmp(icon, "app") == 0 || std::strcmp(icon, "application") == 0) | |||||
groupIcon = PATCHBAY_ICON_APPLICATION; | |||||
else if (std::strcmp(icon, "hardware") == 0) | |||||
groupIcon = PATCHBAY_ICON_HARDWARE; | |||||
else if (std::strcmp(icon, "carla") == 0) | |||||
groupIcon = PATCHBAY_ICON_CARLA; | |||||
else if (std::strcmp(icon, "distrho") == 0) | |||||
groupIcon = PATCHBAY_ICON_DISTRHO; | |||||
else if (std::strcmp(icon, "file") == 0) | |||||
groupIcon = PATCHBAY_ICON_FILE; | |||||
else if (std::strcmp(icon, "plugin") == 0) | |||||
groupIcon = PATCHBAY_ICON_PLUGIN; | |||||
} | } | ||||
#endif | |||||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, 0, groupId, 0, 0.0f, groupName); | |||||
callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, groupId, groupIcon, 0, 0.0f, groupName); | |||||
} | } | ||||
bool portIsInput = (jackPortFlags & JackPortIsInput); | bool portIsInput = (jackPortFlags & JackPortIsInput); | ||||
bool portIsAudio = (std::strcmp(jackbridge_port_type(jackPort), JACK_DEFAULT_AUDIO_TYPE) == 0); | bool portIsAudio = (std::strcmp(jackbridge_port_type(jackPort), JACK_DEFAULT_AUDIO_TYPE) == 0); | ||||
bool portIsCV = (jackPortFlags & JackPortIsControlVoltage); | |||||
bool portIsCV = (portIsAudio && (jackPortFlags & JackPortIsControlVoltage) != 0); | |||||
unsigned int canvasPortFlags = 0x0; | unsigned int canvasPortFlags = 0x0; | ||||
canvasPortFlags |= portIsInput ? PATCHBAY_PORT_IS_INPUT : 0x0; | canvasPortFlags |= portIsInput ? PATCHBAY_PORT_IS_INPUT : 0x0; | ||||
canvasPortFlags |= portIsAudio ? PATCHBAY_PORT_TYPE_AUDIO : PATCHBAY_PORT_TYPE_MIDI; | canvasPortFlags |= portIsAudio ? PATCHBAY_PORT_TYPE_AUDIO : PATCHBAY_PORT_TYPE_MIDI; | ||||
if (portIsAudio && portIsCV) | |||||
if (portIsCV) | |||||
canvasPortFlags |= PATCHBAY_PORT_TYPE_CV; | canvasPortFlags |= PATCHBAY_PORT_TYPE_CV; | ||||
PortNameToId portNameToId(groupId, fLastPortId++, portName, fullPortName); | PortNameToId portNameToId(groupId, fLastPortId++, portName, fullPortName); | ||||
@@ -1735,32 +1744,16 @@ private: | |||||
callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, groupId, portNameToId.portId, canvasPortFlags, 0.0f, portName); | callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, groupId, portNameToId.portId, canvasPortFlags, 0.0f, portName); | ||||
} | } | ||||
#if 0 | |||||
jackbridge_free(ports); | |||||
} | |||||
// query connections, after all ports are in place | |||||
if (const char** ports = jackbridge_get_ports(fClient, nullptr, nullptr, JackPortIsOutput)) | |||||
{ | |||||
#endif | |||||
// query connections, after all ports are in place | |||||
for (int i=0; ports[i] != nullptr; ++i) | for (int i=0; ports[i] != nullptr; ++i) | ||||
{ | { | ||||
jack_port_t* const jackPort(jackbridge_port_by_name(fClient, ports[i])); | jack_port_t* const jackPort(jackbridge_port_by_name(fClient, ports[i])); | ||||
const char* const fullPortName(ports[i]); | const char* const fullPortName(ports[i]); | ||||
CARLA_SAFE_ASSERT_CONTINUE(jackPort != nullptr); | |||||
#if 1 | |||||
const int jackPortFlags(jackbridge_port_flags(jackPort)); | |||||
if (jackPortFlags & JackPortIsInput) | |||||
continue; | |||||
#endif | |||||
const int thisPortId(getPortId(fullPortName)); | const int thisPortId(getPortId(fullPortName)); | ||||
if (thisPortId == -1) | |||||
continue; | |||||
CARLA_SAFE_ASSERT_CONTINUE(jackPort != nullptr); | |||||
CARLA_SAFE_ASSERT_CONTINUE(thisPortId != -1); | |||||
if (const char** connections = jackbridge_port_get_all_connections(fClient, jackPort)) | if (const char** connections = jackbridge_port_get_all_connections(fClient, jackPort)) | ||||
{ | { | ||||
@@ -1776,13 +1769,10 @@ private: | |||||
jackbridge_free(connections); | jackbridge_free(connections); | ||||
} | } | ||||
else | |||||
carla_stderr("jack_port_get_all_connections failed for port %s", fullPortName); | |||||
} | } | ||||
jackbridge_free(ports); | jackbridge_free(ports); | ||||
} | } | ||||
#endif | |||||
} | } | ||||
#endif | #endif | ||||
@@ -1918,10 +1908,12 @@ private: | |||||
} | } | ||||
#ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
# if 0 | |||||
static void carla_jack_custom_appearance_callback(const char* client_name, const char* key, jack_custom_change_t change, void* arg) | static void carla_jack_custom_appearance_callback(const char* client_name, const char* key, jack_custom_change_t change, void* arg) | ||||
{ | { | ||||
handlePtr->handleCustomAppearanceCallback(client_name, key, change); | handlePtr->handleCustomAppearanceCallback(client_name, key, change); | ||||
} | } | ||||
# endif | |||||
static void carla_jack_client_registration_callback(const char* name, int reg, void* arg) | static void carla_jack_client_registration_callback(const char* name, int reg, void* arg) | ||||
{ | { | ||||
@@ -558,7 +558,9 @@ ENGINE_CALLBACK_RELOAD_ALL = 18 | |||||
# A patchbay client has been added. | # A patchbay client has been added. | ||||
# @param pluginId Client Id | # @param pluginId Client Id | ||||
# @param valueStr Client name and icon, as "name:icon" | |||||
# @param value1 Client icon | |||||
# @param valueStr Client name | |||||
# @see PatchbayIcon | |||||
ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED = 19 | ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED = 19 | ||||
# A patchbay client has been removed. | # A patchbay client has been removed. | ||||
@@ -572,7 +574,8 @@ ENGINE_CALLBACK_PATCHBAY_CLIENT_RENAMED = 21 | |||||
# A patchbay client icon has changed. | # A patchbay client icon has changed. | ||||
# @param pluginId Client Id | # @param pluginId Client Id | ||||
# @param valueStr New icon name | |||||
# @param value1 New icon | |||||
# @see PatchbayIcon | |||||
ENGINE_CALLBACK_PATCHBAY_CLIENT_ICON_CHANGED = 22 | ENGINE_CALLBACK_PATCHBAY_CLIENT_ICON_CHANGED = 22 | ||||
# A patchbay port has been added. | # A patchbay port has been added. | ||||
@@ -758,6 +761,34 @@ ENGINE_TRANSPORT_MODE_PLUGIN = 2 | |||||
# Special mode, used in plugin-bridges only. | # Special mode, used in plugin-bridges only. | ||||
ENGINE_TRANSPORT_MODE_BRIDGE = 3 | ENGINE_TRANSPORT_MODE_BRIDGE = 3 | ||||
# ------------------------------------------------------------------------------------------------------------ | |||||
# Patchbay Icon | |||||
# The icon of a patchbay client/group. | |||||
# Generic application icon. | |||||
# Used for all non-plugin clients that don't have a specific icon. | |||||
PATCHBAY_ICON_APPLICATION = 0 | |||||
# Plugin icon. | |||||
# Used for all plugin clients that don't have a specific icon. | |||||
PATCHBAY_ICON_PLUGIN = 1 | |||||
# Hardware icon. | |||||
# Used for hardware (audio or MIDI) clients. | |||||
PATCHBAY_ICON_HARDWARE = 2 | |||||
# Carla icon. | |||||
# Used for the main app. | |||||
PATCHBAY_ICON_CARLA = 3 | |||||
# DISTRHO icon. | |||||
# Used for DISTRHO based plugins. | |||||
PATCHBAY_ICON_DISTRHO = 4 | |||||
# File icon. | |||||
# Used for file type plugins (like GIG and SF2). | |||||
PATCHBAY_ICON_FILE = 5 | |||||
# ------------------------------------------------------------------------------------------------------------ | # ------------------------------------------------------------------------------------------------------------ | ||||
# Carla Backend API (C stuff) | # Carla Backend API (C stuff) | ||||
@@ -121,10 +121,10 @@ class HostWindow(QMainWindow): | |||||
ReloadParametersCallback = pyqtSignal(int) | ReloadParametersCallback = pyqtSignal(int) | ||||
ReloadProgramsCallback = pyqtSignal(int) | ReloadProgramsCallback = pyqtSignal(int) | ||||
ReloadAllCallback = pyqtSignal(int) | ReloadAllCallback = pyqtSignal(int) | ||||
PatchbayClientAddedCallback = pyqtSignal(int, str) | |||||
PatchbayClientAddedCallback = pyqtSignal(int, int, str) | |||||
PatchbayClientRemovedCallback = pyqtSignal(int) | PatchbayClientRemovedCallback = pyqtSignal(int) | ||||
PatchbayClientRenamedCallback = pyqtSignal(int, str) | PatchbayClientRenamedCallback = pyqtSignal(int, str) | ||||
PatchbayClientIconChangedCallback = pyqtSignal(int, str) | |||||
PatchbayClientIconChangedCallback = pyqtSignal(int, int) | |||||
PatchbayPortAddedCallback = pyqtSignal(int, int, int, str) | PatchbayPortAddedCallback = pyqtSignal(int, int, int, str) | ||||
PatchbayPortRemovedCallback = pyqtSignal(int, int) | PatchbayPortRemovedCallback = pyqtSignal(int, int) | ||||
PatchbayPortRenamedCallback = pyqtSignal(int, int, str) | PatchbayPortRenamedCallback = pyqtSignal(int, int, str) | ||||
@@ -1107,13 +1107,13 @@ def engineCallback(ptr, action, pluginId, value1, value2, value3, valueStr): | |||||
elif action == ENGINE_CALLBACK_RELOAD_ALL: | elif action == ENGINE_CALLBACK_RELOAD_ALL: | ||||
Carla.gui.ReloadAllCallback.emit(pluginId) | Carla.gui.ReloadAllCallback.emit(pluginId) | ||||
elif action == ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED: | elif action == ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED: | ||||
Carla.gui.PatchbayClientAddedCallback.emit(pluginId, valueStr) | |||||
Carla.gui.PatchbayClientAddedCallback.emit(pluginId, value1, valueStr) | |||||
elif action == ENGINE_CALLBACK_PATCHBAY_CLIENT_REMOVED: | elif action == ENGINE_CALLBACK_PATCHBAY_CLIENT_REMOVED: | ||||
Carla.gui.PatchbayClientRemovedCallback.emit(pluginId) | Carla.gui.PatchbayClientRemovedCallback.emit(pluginId) | ||||
elif action == ENGINE_CALLBACK_PATCHBAY_CLIENT_RENAMED: | elif action == ENGINE_CALLBACK_PATCHBAY_CLIENT_RENAMED: | ||||
Carla.gui.PatchbayClientRenamedCallback.emit(pluginId, valueStr) | Carla.gui.PatchbayClientRenamedCallback.emit(pluginId, valueStr) | ||||
elif action == ENGINE_CALLBACK_PATCHBAY_CLIENT_ICON_CHANGED: | elif action == ENGINE_CALLBACK_PATCHBAY_CLIENT_ICON_CHANGED: | ||||
Carla.gui.PatchbayClientIconChangedCallback.emit(value1, valueStr) | |||||
Carla.gui.PatchbayClientIconChangedCallback.emit(pluginId, value1) | |||||
elif action == ENGINE_CALLBACK_PATCHBAY_PORT_ADDED: | elif action == ENGINE_CALLBACK_PATCHBAY_PORT_ADDED: | ||||
Carla.gui.PatchbayPortAddedCallback.emit(pluginId, value1, value2, valueStr) | Carla.gui.PatchbayPortAddedCallback.emit(pluginId, value1, value2, valueStr) | ||||
elif action == ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED: | elif action == ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED: | ||||
@@ -19,10 +19,7 @@ | |||||
# ------------------------------------------------------------------------------------------------------------ | # ------------------------------------------------------------------------------------------------------------ | ||||
# Imports (Global) | # Imports (Global) | ||||
from PyQt4.QtGui import QGraphicsView | |||||
#QPrinter, QPrintDialog | |||||
#QImage | |||||
from PyQt4.QtGui import QGraphicsView, QImage, QPrinter, QPrintDialog | |||||
# ------------------------------------------------------------------------------------------------------------ | # ------------------------------------------------------------------------------------------------------------ | ||||
# Imports (Custom Stuff) | # Imports (Custom Stuff) | ||||
@@ -80,7 +77,7 @@ class CarlaPatchbayW(QGraphicsView): | |||||
patchcanvas.setOptions(pOptions) | patchcanvas.setOptions(pOptions) | ||||
patchcanvas.setFeatures(pFeatures) | patchcanvas.setFeatures(pFeatures) | ||||
patchcanvas.init("Carla2", self.scene, CanvasCallback, False) | |||||
patchcanvas.init("Carla2", self.scene, canvasCallback, False) | |||||
tryCanvasSize = parent.fSavedSettings[CARLA_KEY_CANVAS_SIZE].split("x") | tryCanvasSize = parent.fSavedSettings[CARLA_KEY_CANVAS_SIZE].split("x") | ||||
@@ -135,9 +132,9 @@ class CarlaPatchbayW(QGraphicsView): | |||||
parent.ParameterMidiCcChangedCallback.connect(self.slot_handleParameterMidiCcChangedCallback) | parent.ParameterMidiCcChangedCallback.connect(self.slot_handleParameterMidiCcChangedCallback) | ||||
parent.ProgramChangedCallback.connect(self.slot_handleProgramChangedCallback) | parent.ProgramChangedCallback.connect(self.slot_handleProgramChangedCallback) | ||||
parent.MidiProgramChangedCallback.connect(self.slot_handleMidiProgramChangedCallback) | parent.MidiProgramChangedCallback.connect(self.slot_handleMidiProgramChangedCallback) | ||||
#parent.ShowGuiCallback.connect(self.slot_handleShowGuiCallback) | |||||
parent.NoteOnCallback.connect(self.slot_handleNoteOnCallback) | parent.NoteOnCallback.connect(self.slot_handleNoteOnCallback) | ||||
parent.NoteOffCallback.connect(self.slot_handleNoteOffCallback) | parent.NoteOffCallback.connect(self.slot_handleNoteOffCallback) | ||||
parent.ShowGuiCallback.connect(self.slot_handleShowGuiCallback) | |||||
parent.UpdateCallback.connect(self.slot_handleUpdateCallback) | parent.UpdateCallback.connect(self.slot_handleUpdateCallback) | ||||
parent.ReloadInfoCallback.connect(self.slot_handleReloadInfoCallback) | parent.ReloadInfoCallback.connect(self.slot_handleReloadInfoCallback) | ||||
parent.ReloadParametersCallback.connect(self.slot_handleReloadParametersCallback) | parent.ReloadParametersCallback.connect(self.slot_handleReloadParametersCallback) | ||||
@@ -146,12 +143,12 @@ class CarlaPatchbayW(QGraphicsView): | |||||
parent.PatchbayClientAddedCallback.connect(self.slot_handlePatchbayClientAddedCallback) | parent.PatchbayClientAddedCallback.connect(self.slot_handlePatchbayClientAddedCallback) | ||||
parent.PatchbayClientRemovedCallback.connect(self.slot_handlePatchbayClientRemovedCallback) | parent.PatchbayClientRemovedCallback.connect(self.slot_handlePatchbayClientRemovedCallback) | ||||
parent.PatchbayClientRenamedCallback.connect(self.slot_handlePatchbayClientRenamedCallback) | parent.PatchbayClientRenamedCallback.connect(self.slot_handlePatchbayClientRenamedCallback) | ||||
parent.PatchbayClientIconChangedCallback.connect(self.slot_handlePatchbayClientIconChangedCallback) | |||||
parent.PatchbayPortAddedCallback.connect(self.slot_handlePatchbayPortAddedCallback) | parent.PatchbayPortAddedCallback.connect(self.slot_handlePatchbayPortAddedCallback) | ||||
parent.PatchbayPortRemovedCallback.connect(self.slot_handlePatchbayPortRemovedCallback) | parent.PatchbayPortRemovedCallback.connect(self.slot_handlePatchbayPortRemovedCallback) | ||||
parent.PatchbayPortRenamedCallback.connect(self.slot_handlePatchbayPortRenamedCallback) | parent.PatchbayPortRenamedCallback.connect(self.slot_handlePatchbayPortRenamedCallback) | ||||
parent.PatchbayConnectionAddedCallback.connect(self.slot_handlePatchbayConnectionAddedCallback) | parent.PatchbayConnectionAddedCallback.connect(self.slot_handlePatchbayConnectionAddedCallback) | ||||
parent.PatchbayConnectionRemovedCallback.connect(self.slot_handlePatchbayConnectionRemovedCallback) | parent.PatchbayConnectionRemovedCallback.connect(self.slot_handlePatchbayConnectionRemovedCallback) | ||||
#parent.PatchbayIconChangedCallback.connect(self.slot_handlePatchbayIconChangedCallback) | |||||
# ----------------------------------------------------------------- | # ----------------------------------------------------------------- | ||||
@@ -531,12 +528,28 @@ class CarlaPatchbayW(QGraphicsView): | |||||
# ----------------------------------------------------------------- | # ----------------------------------------------------------------- | ||||
@pyqtSlot(int, int, str) | @pyqtSlot(int, int, str) | ||||
def slot_handlePatchbayClientAddedCallback(self, clientId, clientName): | |||||
patchcanvas.addGroup(clientId, clientName) | |||||
def slot_handlePatchbayClientAddedCallback(self, clientId, clientIcon, clientName): | |||||
pcSplit = patchcanvas.SPLIT_UNDEF | |||||
pcIcon = patchcanvas.ICON_APPLICATION | |||||
print("------------------------------------------- new client with icon", clientIcon) | |||||
if clientIcon == PATCHBAY_ICON_PLUGIN: | |||||
pcIcon = patchcanvas.ICON_PLUGIN | |||||
if clientIcon == PATCHBAY_ICON_HARDWARE: | |||||
pcIcon = patchcanvas.ICON_HARDWARE | |||||
elif clientIcon == PATCHBAY_ICON_CARLA: | |||||
pass | |||||
elif clientIcon == PATCHBAY_ICON_DISTRHO: | |||||
pcIcon = patchcanvas.ICON_DISTRHO | |||||
elif clientIcon == PATCHBAY_ICON_FILE: | |||||
pcIcon = patchcanvas.ICON_FILE | |||||
patchcanvas.addGroup(clientId, clientName, pcSplit, pcIcon) | |||||
#QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) | #QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) | ||||
@pyqtSlot(int, str) | |||||
def slot_handlePatchbayClientRemovedCallback(self, clientId, clientName): | |||||
@pyqtSlot(int) | |||||
def slot_handlePatchbayClientRemovedCallback(self, clientId): | |||||
#if not self.fEngineStarted: return | #if not self.fEngineStarted: return | ||||
patchcanvas.removeGroup(clientId) | patchcanvas.removeGroup(clientId) | ||||
#QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) | #QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) | ||||
@@ -546,18 +559,22 @@ class CarlaPatchbayW(QGraphicsView): | |||||
patchcanvas.renameGroup(clientId, newClientName) | patchcanvas.renameGroup(clientId, newClientName) | ||||
#QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) | #QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) | ||||
@pyqtSlot(int, str) | |||||
def slot_handlePatchbayClientIconChangedCallback(self, clientId, iconName): | |||||
patchcanvas.setGroupIcon(clientId, iconName) | |||||
@pyqtSlot(int, int, int, str) | @pyqtSlot(int, int, int, str) | ||||
def slot_handlePatchbayPortAddedCallback(self, clientId, portId, portFlags, portName): | def slot_handlePatchbayPortAddedCallback(self, clientId, portId, portFlags, portName): | ||||
if (portFlags & PATCHBAY_PORT_IS_INPUT): | if (portFlags & PATCHBAY_PORT_IS_INPUT): | ||||
portMode = patchcanvas.PORT_MODE_INPUT | portMode = patchcanvas.PORT_MODE_INPUT | ||||
elif (portFlags & PATCHBAY_PORT_IS_OUTPUT): | |||||
portMode = patchcanvas.PORT_MODE_OUTPUT | |||||
else: | else: | ||||
portMode = patchcanvas.PORT_MODE_NULL | |||||
portMode = patchcanvas.PORT_MODE_OUTPUT | |||||
if (portFlags & PATCHBAY_PORT_IS_AUDIO): | |||||
if (portFlags & PATCHBAY_PORT_TYPE_AUDIO): | |||||
portType = patchcanvas.PORT_TYPE_AUDIO_JACK | portType = patchcanvas.PORT_TYPE_AUDIO_JACK | ||||
elif (portFlags & PATCHBAY_PORT_IS_MIDI): | |||||
elif (portFlags & PATCHBAY_PORT_TYPE_CV): | |||||
portType = patchcanvas.PORT_TYPE_AUDIO_JACK # TODO | |||||
elif (portFlags & PATCHBAY_PORT_TYPE_MIDI): | |||||
portType = patchcanvas.PORT_TYPE_MIDI_JACK | portType = patchcanvas.PORT_TYPE_MIDI_JACK | ||||
else: | else: | ||||
portType = patchcanvas.PORT_TYPE_NULL | portType = patchcanvas.PORT_TYPE_NULL | ||||
@@ -565,8 +582,8 @@ class CarlaPatchbayW(QGraphicsView): | |||||
patchcanvas.addPort(clientId, portId, portName, portMode, portType) | patchcanvas.addPort(clientId, portId, portName, portMode, portType) | ||||
#QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) | #QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) | ||||
@pyqtSlot(int, int, str) | |||||
def slot_handlePatchbayPortRemovedCallback(self, groupId, portId, fullPortName): | |||||
@pyqtSlot(int, int) | |||||
def slot_handlePatchbayPortRemovedCallback(self, groupId, portId): | |||||
#if not self.fEngineStarted: return | #if not self.fEngineStarted: return | ||||
patchcanvas.removePort(portId) | patchcanvas.removePort(portId) | ||||
#QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) | #QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) | ||||
@@ -581,16 +598,12 @@ class CarlaPatchbayW(QGraphicsView): | |||||
patchcanvas.connectPorts(connectionId, portOutId, portInId) | patchcanvas.connectPorts(connectionId, portOutId, portInId) | ||||
#QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) | #QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) | ||||
@pyqtSlot(int) | |||||
def slot_handlePatchbayConnectionRemovedCallback(self, connectionId): | |||||
@pyqtSlot(int, int, int) | |||||
def slot_handlePatchbayConnectionRemovedCallback(self, connectionId, portOutId, portInId): | |||||
#if not self.fEngineStarted: return | #if not self.fEngineStarted: return | ||||
patchcanvas.disconnectPorts(connectionId) | patchcanvas.disconnectPorts(connectionId) | ||||
#QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) | #QTimer.singleShot(0, self.ui.miniCanvasPreview, SLOT("update()")) | ||||
@pyqtSlot(int, int) | |||||
def slot_handlePatchbayIconChangedCallback(self, clientId, icon): | |||||
patchcanvas.setGroupIcon(clientId, icon) | |||||
# ----------------------------------------------------------------- | # ----------------------------------------------------------------- | ||||
@pyqtSlot() | @pyqtSlot() | ||||
@@ -641,10 +654,9 @@ class CarlaPatchbayW(QGraphicsView): | |||||
if newPath: | if newPath: | ||||
self.scene.clearSelection() | self.scene.clearSelection() | ||||
# FIXME - must be a better way... | |||||
if newPath.endswith((".jpg", ".jpG", ".jPG", ".JPG", ".JPg", ".Jpg")): | |||||
if newPath.lower().endswith((".jpg",)): | |||||
imgFormat = "JPG" | imgFormat = "JPG" | ||||
elif newPath.endswith((".png", ".pnG", ".pNG", ".PNG", ".PNg", ".Png")): | |||||
elif newPath.lower().endswith((".png",)): | |||||
imgFormat = "PNG" | imgFormat = "PNG" | ||||
else: | else: | ||||
# File-dialog may not auto-add the extension | # File-dialog may not auto-add the extension | ||||
@@ -396,8 +396,13 @@ def addGroup(group_id, group_name, split=SPLIT_UNDEF, icon=ICON_APPLICATION): | |||||
qWarning("PatchCanvas::addGroup(%i, %s, %s, %s) - group already exists" % (group_id, group_name.encode(), split2str(split), icon2str(icon))) | qWarning("PatchCanvas::addGroup(%i, %s, %s, %s) - group already exists" % (group_id, group_name.encode(), split2str(split), icon2str(icon))) | ||||
return | return | ||||
if split == SPLIT_UNDEF and features.handle_group_pos: | |||||
split = canvas.settings.value("CanvasPositions/%s_SPLIT" % group_name, split, type=int) | |||||
if split == SPLIT_UNDEF: | |||||
isHardware = bool(icon == ICON_HARDWARE) | |||||
if features.handle_group_pos: | |||||
split = canvas.settings.value("CanvasPositions/%s_SPLIT" % group_name, SPLIT_YES if isHardware else split, type=int) | |||||
elif isHardware: | |||||
split = SPLIT_YES | |||||
group_box = CanvasBox(group_id, group_name, icon) | group_box = CanvasBox(group_id, group_name, icon) | ||||
@@ -392,7 +392,7 @@ public: | |||||
if (found != nullptr) | if (found != nullptr) | ||||
*found = false; | *found = false; | ||||
if (fBufferLen == 0 || strBuf != nullptr || strBuf[0] != '\0') | |||||
if (fBufferLen == 0 || strBuf == nullptr || strBuf[0] == '\0') | |||||
return fBufferLen; | return fBufferLen; | ||||
size_t ret = fBufferLen+1; | size_t ret = fBufferLen+1; | ||||