| @@ -62,7 +62,7 @@ float randomf(); | |||||
| float randomNormal(); | float randomNormal(); | ||||
| //////////////////// | //////////////////// | ||||
| // Helper functions | |||||
| // String functions | |||||
| //////////////////// | //////////////////// | ||||
| /** Converts a printf format string and optional arguments into a std::string */ | /** Converts a printf format string and optional arguments into a std::string */ | ||||
| @@ -73,6 +73,11 @@ std::string ellipsize(std::string s, size_t len); | |||||
| std::string extractDirectory(std::string path); | std::string extractDirectory(std::string path); | ||||
| std::string extractFilename(std::string path); | std::string extractFilename(std::string path); | ||||
| std::string extractExtension(std::string path); | |||||
| //////////////////// | |||||
| // Operating system functions | |||||
| //////////////////// | |||||
| /** Opens a URL, also happens to work with PDFs and folders. | /** Opens a URL, also happens to work with PDFs and folders. | ||||
| Shell injection is possible, so make sure the URL is trusted or hard coded. | Shell injection is possible, so make sure the URL is trusted or hard coded. | ||||
| @@ -80,6 +85,10 @@ May block, so open in a new thread. | |||||
| */ | */ | ||||
| void openBrowser(std::string url); | void openBrowser(std::string url); | ||||
| //////////////////// | |||||
| // Thread functions | |||||
| //////////////////// | |||||
| /** Threads which obtain a VIPLock will cause wait() to block for other less important threads. | /** Threads which obtain a VIPLock will cause wait() to block for other less important threads. | ||||
| This does not provide the VIPs with an exclusive lock. That should be left up to another mutex shared between the less important thread. | This does not provide the VIPs with an exclusive lock. That should be left up to another mutex shared between the less important thread. | ||||
| */ | */ | ||||
| @@ -60,17 +60,24 @@ void RackWidget::saveDialog() { | |||||
| void RackWidget::saveAsDialog() { | void RackWidget::saveAsDialog() { | ||||
| std::string dir = lastPath.empty() ? assetLocal("") : extractDirectory(lastPath); | std::string dir = lastPath.empty() ? assetLocal("") : extractDirectory(lastPath); | ||||
| char *path = osdialog_file(OSDIALOG_SAVE, dir.c_str(), "Untitled.vcv", NULL); | char *path = osdialog_file(OSDIALOG_SAVE, dir.c_str(), "Untitled.vcv", NULL); | ||||
| if (path) { | if (path) { | ||||
| savePatch(path); | |||||
| lastPath = path; | |||||
| std::string pathStr = path; | |||||
| free(path); | free(path); | ||||
| std::string extension = extractExtension(pathStr); | |||||
| if (extension.empty()) { | |||||
| pathStr += ".vcv"; | |||||
| } | |||||
| savePatch(pathStr); | |||||
| lastPath = pathStr; | |||||
| } | } | ||||
| } | } | ||||
| void RackWidget::savePatch(std::string filename) { | |||||
| printf("Saving patch %s\n", filename.c_str()); | |||||
| FILE *file = fopen(filename.c_str(), "w"); | |||||
| void RackWidget::savePatch(std::string path) { | |||||
| printf("Saving patch %s\n", path.c_str()); | |||||
| FILE *file = fopen(path.c_str(), "w"); | |||||
| if (!file) | if (!file) | ||||
| return; | return; | ||||
| @@ -83,9 +90,9 @@ void RackWidget::savePatch(std::string filename) { | |||||
| fclose(file); | fclose(file); | ||||
| } | } | ||||
| void RackWidget::loadPatch(std::string filename) { | |||||
| printf("Loading patch %s\n", filename.c_str()); | |||||
| FILE *file = fopen(filename.c_str(), "r"); | |||||
| void RackWidget::loadPatch(std::string path) { | |||||
| printf("Loading patch %s\n", path.c_str()); | |||||
| FILE *file = fopen(path.c_str(), "r"); | |||||
| if (!file) { | if (!file) { | ||||
| // Exit silently | // Exit silently | ||||
| return; | return; | ||||
| @@ -36,10 +36,12 @@ float randomNormal(){ | |||||
| std::string stringf(const char *format, ...) { | std::string stringf(const char *format, ...) { | ||||
| va_list args; | va_list args; | ||||
| va_start(args, format); | va_start(args, format); | ||||
| // Compute size of required buffer | |||||
| int size = vsnprintf(NULL, 0, format, args); | int size = vsnprintf(NULL, 0, format, args); | ||||
| va_end(args); | va_end(args); | ||||
| if (size < 0) | if (size < 0) | ||||
| return ""; | return ""; | ||||
| // Create buffer | |||||
| std::string s; | std::string s; | ||||
| s.resize(size); | s.resize(size); | ||||
| va_start(args, format); | va_start(args, format); | ||||
| @@ -69,6 +71,13 @@ std::string extractFilename(std::string path) { | |||||
| return filename; | return filename; | ||||
| } | } | ||||
| std::string extractExtension(std::string path) { | |||||
| const char *ext = strrchr(path.c_str(), '.'); | |||||
| if (!ext) | |||||
| return ""; | |||||
| return ext + 1; | |||||
| } | |||||
| void openBrowser(std::string url) { | void openBrowser(std::string url) { | ||||
| #if ARCH_LIN | #if ARCH_LIN | ||||
| std::string command = "xdg-open " + url; | std::string command = "xdg-open " + url; | ||||