Replace thinning static state with parameter.
[ardour.git] / libs / ardour / audio_unit.cc
index 399ce8aba7c6c19503acffe7e64d3b1d2f10df4a..21f2a78be09a5d0e50234aa7657fb8a21cd056f5 100644 (file)
@@ -19,6 +19,7 @@
 */
 
 #include <sstream>
+#include <fstream>
 #include <errno.h>
 #include <string.h>
 #include <math.h>
 #include "pbd/xml++.h"
 #include "pbd/convert.h"
 #include "pbd/whitespace.h"
-#include "pbd/pathscanner.h"
+#include "pbd/file_utils.h"
 #include "pbd/locale_guard.h"
 
 #include <glibmm/threads.h>
 #include <glibmm/fileutils.h>
 #include <glibmm/miscutils.h>
+#include <glib/gstdio.h>
 
 #include "ardour/ardour.h"
 #include "ardour/audioengine.h"
@@ -65,18 +67,12 @@ using namespace std;
 using namespace PBD;
 using namespace ARDOUR;
 
-#ifndef AU_STATE_SUPPORT
-static bool seen_get_state_message = false;
-static bool seen_set_state_message = false;
-static bool seen_loading_message = false;
-static bool seen_saving_message = false;
-#endif
-
 AUPluginInfo::CachedInfoMap AUPluginInfo::cached_info;
 
 static string preset_search_path = "/Library/Audio/Presets:/Network/Library/Audio/Presets";
 static string preset_suffix = ".aupreset";
 static bool preset_search_path_initialized = false;
+FILE * AUPluginInfo::_crashlog_fd = NULL;
 
 static OSStatus
 _render_callback(void *userData,
@@ -623,11 +619,9 @@ AUPlugin::discover_parameters ()
                        d.logarithmic = (info.flags & kAudioUnitParameterFlag_DisplayLogarithmic);
                        d.unit = info.unit;
 
-                       d.step = 1.0;
-                       d.smallstep = 0.1;
-                       d.largestep = 10.0;
                        d.min_unbound = 0; // lower is bound
                        d.max_unbound = 0; // upper is bound
+                       d.update_steps();
 
                        descriptors.push_back (d);
 
@@ -1005,7 +999,7 @@ AUPlugin::output_streams() const
 }
 
 bool
-AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
+AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out)
 {
        // Note: We never attempt to multiply-instantiate plugins to meet io configurations.
 
@@ -1679,8 +1673,6 @@ void
 AUPlugin::add_state (XMLNode* root) const
 {
        LocaleGuard lg (X_("POSIX"));
-
-#ifdef AU_STATE_SUPPORT
        CFDataRef xmlData;
        CFPropertyListRef propertyList;
 
@@ -1712,20 +1704,11 @@ AUPlugin::add_state (XMLNode* root) const
 
        CFRelease (xmlData);
        CFRelease (propertyList);
-#else
-       if (!seen_get_state_message) {
-               info << string_compose (_("Saving AudioUnit settings is not supported in this build of %1. Consider paying for a newer version"),
-                                       PROGRAM_NAME)
-                    << endmsg;
-               seen_get_state_message = true;
-       }
-#endif
 }
 
 int
 AUPlugin::set_state(const XMLNode& node, int version)
 {
-#ifdef AU_STATE_SUPPORT
        int ret = -1;
        CFPropertyListRef propertyList;
        LocaleGuard lg (X_("POSIX"));
@@ -1735,6 +1718,7 @@ AUPlugin::set_state(const XMLNode& node, int version)
                return -1;
        }
 
+#ifndef NO_PLUGIN_STATE
        if (node.children().empty()) {
                return -1;
        }
@@ -1770,17 +1754,10 @@ AUPlugin::set_state(const XMLNode& node, int version)
                }
                CFRelease (propertyList);
        }
+#endif
 
        Plugin::set_state (node, version);
        return ret;
-#else
-       if (!seen_set_state_message) {
-               info << string_compose (_("Restoring AudioUnit settings is not supported in this build of %1. Consider paying for a newer version"),
-                                       PROGRAM_NAME)
-                    << endmsg;
-       }
-       return Plugin::set_state (node, version);
-#endif
 }
 
 bool
@@ -1788,7 +1765,6 @@ AUPlugin::load_preset (PresetRecord r)
 {
        Plugin::load_preset (r);
 
-#ifdef AU_STATE_SUPPORT
        bool ret = false;
        CFPropertyListRef propertyList;
        Glib::ustring path;
@@ -1836,15 +1812,6 @@ AUPlugin::load_preset (PresetRecord r)
        }
 
        return ret;
-#else
-       if (!seen_loading_message) {
-               info << string_compose (_("Loading AudioUnit presets is not supported in this build of %1. Consider paying for a newer version"),
-                                       PROGRAM_NAME)
-                    << endmsg;
-               seen_loading_message = true;
-       }
-       return true;
-#endif
 }
 
 void
@@ -1855,11 +1822,9 @@ AUPlugin::do_remove_preset (std::string)
 string
 AUPlugin::do_save_preset (string preset_name)
 {
-#ifdef AU_STATE_SUPPORT
        CFPropertyListRef propertyList;
        vector<Glib::ustring> v;
        Glib::ustring user_preset_path;
-       bool ret = true;
 
        std::string m = maker();
        std::string n = name();
@@ -1878,12 +1843,12 @@ AUPlugin::do_save_preset (string preset_name)
 
        if (g_mkdir_with_parents (user_preset_path.c_str(), 0775) < 0) {
                error << string_compose (_("Cannot create user plugin presets folder (%1)"), user_preset_path) << endmsg;
-               return false;
+               return string();
        }
 
        DEBUG_TRACE (DEBUG::AudioUnits, "get current preset\n");
        if (unit->GetAUPreset (propertyList) != noErr) {
-               return false;
+               return string();
        }
 
        // add the actual preset name */
@@ -1898,21 +1863,12 @@ AUPlugin::do_save_preset (string preset_name)
 
        if (save_property_list (propertyList, user_preset_path)) {
                error << string_compose (_("Saving plugin state to %1 failed"), user_preset_path) << endmsg;
-               ret = false;
+               return string();
        }
 
        CFRelease(propertyList);
 
        return string ("file:///") + user_preset_path;
-#else
-       if (!seen_saving_message) {
-               info << string_compose (_("Saving AudioUnit presets is not supported in this build of %1. Consider paying for a newer version"),
-                                       PROGRAM_NAME)
-                    << endmsg;
-               seen_saving_message = true;
-       }
-       return string();
-#endif
 }
 
 //-----------------------------------------------------------------------------
@@ -2079,7 +2035,6 @@ AUPlugin::current_preset() const
 {
        string preset_name;
 
-#ifdef AU_STATE_SUPPORT
        CFPropertyListRef propertyList;
 
        DEBUG_TRACE (DEBUG::AudioUnits, "get current preset for current_preset()\n");
@@ -2087,28 +2042,26 @@ AUPlugin::current_preset() const
                preset_name = get_preset_name_in_plist (propertyList);
                CFRelease(propertyList);
        }
-#endif
+
        return preset_name;
 }
 
 void
 AUPlugin::find_presets ()
 {
-#ifdef AU_STATE_SUPPORT
-       vector<string*>* preset_files;
-       PathScanner scanner;
+       vector<string> preset_files;
 
        user_preset_map.clear ();
 
-       preset_files = scanner (preset_search_path, au_preset_filter, this, true, true, -1, true);
+       find_files_matching_filter (preset_files, preset_search_path, au_preset_filter, this, true, true, true);
 
-       if (!preset_files) {
+       if (preset_files.empty()) {
                return;
        }
 
-       for (vector<string*>::iterator x = preset_files->begin(); x != preset_files->end(); ++x) {
+       for (vector<string>::iterator x = preset_files.begin(); x != preset_files.end(); ++x) {
 
-               string path = *(*x);
+               string path = *x;
                string preset_name;
 
                /* make an initial guess at the preset name using the path */
@@ -2125,11 +2078,8 @@ AUPlugin::find_presets ()
                        user_preset_map[preset_name] = path;
                }
 
-               delete *x;
        }
 
-       delete preset_files;
-
        /* now fill the vector<string> with the names we have */
 
        for (UserPresetMap::iterator i = user_preset_map.begin(); i != user_preset_map.end(); ++i) {
@@ -2143,8 +2093,6 @@ AUPlugin::find_presets ()
                string const uri = string_compose ("%1", _presets.size ());
                _presets.insert (make_pair (uri, Plugin::PresetRecord (uri, i->first, i->second)));
        }
-
-#endif
 }
 
 bool
@@ -2208,6 +2156,8 @@ AUPluginInfo::discover ()
        if (!Glib::file_test (au_cache_path(), Glib::FILE_TEST_EXISTS)) {
                ARDOUR::BootMessage (_("Discovering AudioUnit plugins (could take some time ...)"));
        }
+       // create crash log file
+       au_start_crashlog ();
 
        PluginInfoList* plugs = new PluginInfoList;
 
@@ -2216,6 +2166,9 @@ AUPluginInfo::discover ()
        discover_generators (*plugs);
        discover_instruments (*plugs);
 
+       // all fine if we get here
+       au_remove_crashlog ();
+
        DEBUG_TRACE (DEBUG::PluginManager, string_compose ("AU: discovered %1 plugins\n", plugs->size()));
 
        return plugs;
@@ -2273,10 +2226,57 @@ AUPluginInfo::discover_instruments (PluginInfoList& plugs)
        discover_by_description (plugs, desc);
 }
 
+
+bool
+AUPluginInfo::au_get_crashlog (std::string &msg)
+{
+       string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_crashlog.txt");
+       if (!Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
+               return false;
+       }
+       std::ifstream ifs(fn.c_str());
+       msg.assign ((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
+       au_remove_crashlog ();
+       return true;
+}
+
+void
+AUPluginInfo::au_start_crashlog ()
+{
+       string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_crashlog.txt");
+       assert(!_crashlog_fd);
+       DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("Creating AU Log: %1\n", fn));
+       if (!(_crashlog_fd = fopen(fn.c_str(), "w"))) {
+               PBD::error << "Cannot create AU error-log\n";
+       }
+}
+
+void
+AUPluginInfo::au_remove_crashlog ()
+{
+       if (_crashlog_fd) {
+               ::fclose(_crashlog_fd);
+               _crashlog_fd = NULL;
+       }
+       string fn = Glib::build_filename (ARDOUR::user_cache_directory(), "au_crashlog.txt");
+       ::g_unlink(fn.c_str());
+       DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("Remove AU Log: %1\n", fn));
+}
+
+
+void
+AUPluginInfo::au_crashlog (std::string msg)
+{
+       assert(_crashlog_fd);
+       fprintf(_crashlog_fd, "AU: %s\n", msg.c_str());
+       ::fflush(_crashlog_fd);
+}
+
 void
 AUPluginInfo::discover_by_description (PluginInfoList& plugs, CAComponentDescription& desc)
 {
        Component comp = 0;
+       au_crashlog(string_compose("Start AU discovery for Type: %1", (int)desc.componentType));
 
        comp = FindNextComponent (NULL, &desc);
 
@@ -2284,6 +2284,21 @@ AUPluginInfo::discover_by_description (PluginInfoList& plugs, CAComponentDescrip
                CAComponentDescription temp;
                GetComponentInfo (comp, &temp, NULL, NULL, NULL);
 
+               {
+                       CFStringRef compTypeString = UTCreateStringForOSType(temp.componentType);
+                       CFStringRef compSubTypeString = UTCreateStringForOSType(temp.componentSubType);
+                       CFStringRef compManufacturerString = UTCreateStringForOSType(temp.componentManufacturer);
+                       CFStringRef itemName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ - %@ - %@"),
+                                       compTypeString, compManufacturerString, compSubTypeString);
+                       au_crashlog(string_compose("Scanning ID: %1", CFStringRefToStdString(itemName)));
+                       if (compTypeString != NULL)
+                               CFRelease(compTypeString);
+                       if (compSubTypeString != NULL)
+                               CFRelease(compSubTypeString);
+                       if (compManufacturerString != NULL)
+                               CFRelease(compManufacturerString);
+               }
+
                AUPluginInfoPtr info (new AUPluginInfo
                                      (boost::shared_ptr<CAComponentDescription> (new CAComponentDescription(temp))));
 
@@ -2326,6 +2341,8 @@ AUPluginInfo::discover_by_description (PluginInfoList& plugs, CAComponentDescrip
                }
 
                AUPluginInfo::get_names (temp, info->name, info->creator);
+               ARDOUR::PluginScanMessage(_("AU"), info->name, false);
+               au_crashlog(string_compose("Plugin: %1", info->name));
 
                info->type = ARDOUR::AudioUnit;
                info->unique_id = stringify_descriptor (*info->descriptor);
@@ -2378,8 +2395,10 @@ AUPluginInfo::discover_by_description (PluginInfoList& plugs, CAComponentDescrip
                        error << string_compose (_("Cannot get I/O configuration info for AU %1"), info->name) << endmsg;
                }
 
+               au_crashlog("Success.");
                comp = FindNextComponent (comp, &desc);
        }
+       au_crashlog(string_compose("End AU discovery for Type: %1", (int)desc.componentType));
 }
 
 bool
@@ -2502,7 +2521,7 @@ AUPluginInfo::save_cached_info ()
 
        if (!tree.write (path)) {
                error << string_compose (_("could not save AU cache to %1"), path) << endmsg;
-               unlink (path.c_str());
+               g_unlink (path.c_str());
        }
 }