+static int
+save_property_list (CFPropertyListRef propertyList, Glib::ustring path)
+
+{
+ CFDataRef xmlData;
+ int fd;
+
+ // Convert the property list into XML data.
+
+ xmlData = CFPropertyListCreateXMLData( kCFAllocatorDefault, propertyList);
+
+ if (!xmlData) {
+ error << _("Could not create XML version of property list") << endmsg;
+ return -1;
+ }
+
+ // Write the XML data to the file.
+
+ fd = open (path.c_str(), O_WRONLY|O_CREAT|O_EXCL, 0664);
+ while (fd < 0) {
+ if (errno == EEXIST) {
+ /* tell any UI's that this file already exists and ask them what to do */
+ bool overwrite = Plugin::PresetFileExists(); // EMIT SIGNAL
+ if (overwrite) {
+ fd = open (path.c_str(), O_WRONLY, 0664);
+ continue;
+ } else {
+ return 0;
+ }
+ }
+ error << string_compose (_("Cannot open preset file %1 (%2)"), path, strerror (errno)) << endmsg;
+ CFRelease (xmlData);
+ return -1;
+ }
+
+ size_t cnt = CFDataGetLength (xmlData);
+
+ if (write (fd, CFDataGetBytePtr (xmlData), cnt) != cnt) {
+ CFRelease (xmlData);
+ close (fd);
+ return -1;
+ }
+
+ close (fd);
+ return 0;
+}
+
+
+static CFPropertyListRef
+load_property_list (Glib::ustring path)
+{
+ int fd;
+ CFPropertyListRef propertyList;
+ CFDataRef xmlData;
+ CFStringRef errorString;
+
+ // Read the XML file.
+
+ if ((fd = open (path.c_str(), O_RDONLY)) < 0) {
+ return propertyList;
+
+ }
+
+ off_t len = lseek (fd, 0, SEEK_END);
+ char* buf = new char[len];
+ lseek (fd, 0, SEEK_SET);
+
+ if (read (fd, buf, len) != len) {
+ delete [] buf;
+ close (fd);
+ return propertyList;
+ }
+
+ close (fd);
+
+ xmlData = CFDataCreateWithBytesNoCopy (kCFAllocatorDefault, (UInt8*) buf, len, kCFAllocatorNull);
+
+ // Reconstitute the dictionary using the XML data.
+
+ propertyList = CFPropertyListCreateFromXMLData( kCFAllocatorDefault,
+ xmlData,
+ kCFPropertyListImmutable,
+ &errorString);
+
+ CFRelease (xmlData);
+ delete [] buf;
+
+ return propertyList;
+}
+
+//-----------------------------------------------------------------------------
+static void
+set_preset_name_in_plist (CFPropertyListRef plist, string preset_name)
+{
+ if (!plist) {
+ return;
+ }
+ CFStringRef pn = CFStringCreateWithCString (kCFAllocatorDefault, preset_name.c_str(), kCFStringEncodingUTF8);
+
+ if (CFGetTypeID (plist) == CFDictionaryGetTypeID()) {
+ CFDictionarySetValue ((CFMutableDictionaryRef)plist, CFSTR(kAUPresetNameKey), pn);
+ }
+
+ CFRelease (pn);
+}
+
+//-----------------------------------------------------------------------------
+static std::string
+get_preset_name_in_plist (CFPropertyListRef plist)
+{
+ std::string ret;
+
+ if (!plist) {
+ return ret;
+ }
+
+ if (CFGetTypeID (plist) == CFDictionaryGetTypeID()) {
+ const void *p = CFDictionaryGetValue ((CFMutableDictionaryRef)plist, CFSTR(kAUPresetNameKey));
+ if (p) {
+ CFStringRef str = (CFStringRef) p;
+ int len = CFStringGetLength(str);
+ len = (len * 2) + 1;
+ char local_buffer[len];
+ if (CFStringGetCString (str, local_buffer, len, kCFStringEncodingUTF8)) {
+ ret = local_buffer;
+ }
+ }
+ }
+ return ret;
+}
+
+//--------------------------------------------------------------------------
+// general implementation for ComponentDescriptionsMatch() and ComponentDescriptionsMatch_Loosely()
+// if inIgnoreType is true, then the type code is ignored in the ComponentDescriptions
+Boolean ComponentDescriptionsMatch_General(const ComponentDescription * inComponentDescription1, const ComponentDescription * inComponentDescription2, Boolean inIgnoreType);
+Boolean ComponentDescriptionsMatch_General(const ComponentDescription * inComponentDescription1, const ComponentDescription * inComponentDescription2, Boolean inIgnoreType)
+{
+ if ( (inComponentDescription1 == NULL) || (inComponentDescription2 == NULL) )
+ return FALSE;
+
+ if ( (inComponentDescription1->componentSubType == inComponentDescription2->componentSubType)
+ && (inComponentDescription1->componentManufacturer == inComponentDescription2->componentManufacturer) )
+ {
+ // only sub-type and manufacturer IDs need to be equal
+ if (inIgnoreType)
+ return TRUE;
+ // type, sub-type, and manufacturer IDs all need to be equal in order to call this a match
+ else if (inComponentDescription1->componentType == inComponentDescription2->componentType)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+//--------------------------------------------------------------------------
+// general implementation for ComponentAndDescriptionMatch() and ComponentAndDescriptionMatch_Loosely()
+// if inIgnoreType is true, then the type code is ignored in the ComponentDescriptions
+Boolean ComponentAndDescriptionMatch_General(Component inComponent, const ComponentDescription * inComponentDescription, Boolean inIgnoreType);
+Boolean ComponentAndDescriptionMatch_General(Component inComponent, const ComponentDescription * inComponentDescription, Boolean inIgnoreType)
+{
+ OSErr status;
+ ComponentDescription desc;
+
+ if ( (inComponent == NULL) || (inComponentDescription == NULL) )
+ return FALSE;
+
+ // get the ComponentDescription of the input Component
+ status = GetComponentInfo(inComponent, &desc, NULL, NULL, NULL);
+ if (status != noErr)
+ return FALSE;
+
+ // check if the Component's ComponentDescription matches the input ComponentDescription
+ return ComponentDescriptionsMatch_General(&desc, inComponentDescription, inIgnoreType);
+}
+
+//--------------------------------------------------------------------------
+// determine if 2 ComponentDescriptions are basically equal
+// (by that, I mean that the important identifying values are compared,
+// but not the ComponentDescription flags)
+Boolean ComponentDescriptionsMatch(const ComponentDescription * inComponentDescription1, const ComponentDescription * inComponentDescription2)
+{
+ return ComponentDescriptionsMatch_General(inComponentDescription1, inComponentDescription2, FALSE);
+}
+
+//--------------------------------------------------------------------------
+// determine if 2 ComponentDescriptions have matching sub-type and manufacturer codes
+Boolean ComponentDescriptionsMatch_Loose(const ComponentDescription * inComponentDescription1, const ComponentDescription * inComponentDescription2)
+{
+ return ComponentDescriptionsMatch_General(inComponentDescription1, inComponentDescription2, TRUE);
+}
+
+//--------------------------------------------------------------------------
+// determine if a ComponentDescription basically matches that of a particular Component
+Boolean ComponentAndDescriptionMatch(Component inComponent, const ComponentDescription * inComponentDescription)
+{
+ return ComponentAndDescriptionMatch_General(inComponent, inComponentDescription, FALSE);
+}
+
+//--------------------------------------------------------------------------
+// determine if a ComponentDescription matches only the sub-type and manufacturer codes of a particular Component
+Boolean ComponentAndDescriptionMatch_Loosely(Component inComponent, const ComponentDescription * inComponentDescription)
+{
+ return ComponentAndDescriptionMatch_General(inComponent, inComponentDescription, TRUE);
+}
+
+