diff --git a/media-sound/waveedit/additional-files/waveedit.rdef.in b/media-sound/waveedit/additional-files/waveedit.rdef.in new file mode 100644 index 000000000..8eadeb1f3 --- /dev/null +++ b/media-sound/waveedit/additional-files/waveedit.rdef.in @@ -0,0 +1,36 @@ + +resource app_flags B_MULTIPLE_LAUNCH; + +resource app_version { + major = @MAJOR@, + middle = @MIDDLE@, + minor = 0, + + variety = B_APPV_FINAL, + internal = 0, + + short_info = "WaveEdit", + long_info = "@LONG_INFO@" +}; + +resource app_signature "@APP_SIGNATURE@"; + +resource vector_icon { + $"6E6369660A01010000720301000002001604BCB5EBBC97D73C97D7BCB5EB4A1A" + $"E14807AE00035523ADF5FF9302001602BAC614BC147A3C147ABAC6144A490A48" + $"35EB0023FFB9020006023A38000000000000003A380048BD994A474700990808" + $"FFFC96960379010102001602B8551EB97F5C397F5CB8551E492EB848DE1400DC" + $"FFFF02001603BC33AEBC1B5C3C1B5CBC33AE485C2848270A003C75D9FF4505FF" + $"04C4A4070605FF024C5AC2685A5254594D5353C862C4425248C83EC39A4A483D" + $"4845483DC5FE3C5A020927332733B4A4BB45223D2239224634572A523A5A4457" + $"415A47554B51495351494E3D4F3F4A343E2D4831382B2F2D332A2B3027332B30" + $"27330205223D223D223334342A303E38464D453EC267C8E734573E5C2A52223D" + $"2247223D0205223D223D223334342A303E38464E4644465834573E5C2A52223D" + $"2247223D0205B62DBA8AB62DBA8A2B323335B8B8BA9F3DBCF4464E4644464236" + $"3340383031B62DBA8A2A31B62DBA8A0404BE253528462444B89AC3583940BA9B" + $"BE91414442560404BE2736304DB81D4D354D3D46BB924342484256070A000100" + $"2027220A01010130242001178400040A0201012024200A03010202400E380000" + $"0000000040000043F1C70000000A0701042023200A090103123F13B100000000" + $"00003F3C68458EC3459A3001178322040A08020605123F13B10000000000003F" + $"3C68458EC3459A300117832204" +}; diff --git a/media-sound/waveedit/patches/osdialog.patchset b/media-sound/waveedit/patches/osdialog.patchset new file mode 100644 index 000000000..5feb54f07 --- /dev/null +++ b/media-sound/waveedit/patches/osdialog.patchset @@ -0,0 +1,161 @@ +From 43917c33d6c824ab6a5662c34c2479596f1dd88d Mon Sep 17 00:00:00 2001 +From: Gerasim Troeglazov <3dEyes@gmail.com> +Date: Thu, 21 Apr 2022 14:48:55 +1000 +Subject: Add Haiku support + + +diff --git a/osdialog_haiku.cpp b/osdialog_haiku.cpp +new file mode 100644 +index 0000000..b100791 +--- /dev/null ++++ b/osdialog_haiku.cpp +@@ -0,0 +1,146 @@ ++#include "osdialog.h" ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++class DirectoryRefFilter : public BRefFilter { ++public: ++ virtual ~DirectoryRefFilter() { }; ++ virtual bool Filter(const entry_ref* ref, BNode* node, ++ struct stat_beos* stat, const char* filetype) ++ { ++ return node->IsDirectory(); ++ } ++}; ++ ++class FilePanelLooper :public BLooper { ++public: ++ FilePanelLooper(BFilePanel *panel); ++ virtual void MessageReceived(BMessage* message); ++ BPath GetPath() { return path; } ++ uint32 GetState() { return state; } ++private: ++ BFilePanel *filePanel; ++ uint32 state; ++ BPath path; ++}; ++ ++FilePanelLooper::FilePanelLooper(BFilePanel *panel) : ++ BLooper("PanelLooper"), ++ filePanel(panel), ++ state(B_ERROR) ++{ ++ path.Unset(); ++} ++ ++void FilePanelLooper::MessageReceived(BMessage* message) ++{ ++ switch (message->what) { ++ case B_REFS_RECEIVED: ++ { ++ entry_ref ref; ++ if (message->FindRef("refs", &ref) == B_OK) { ++ path.SetTo(&ref); ++ state = B_OK; ++ } ++ break; ++ } ++ case B_SAVE_REQUESTED: ++ { ++ entry_ref ref; ++ const char *name; ++ message->FindRef("directory", &ref); ++ BDirectory dir(&ref); ++ path.SetTo(&dir, NULL, false); ++ message->FindString("name", &name); ++ path.Append(name); ++ state = B_OK; ++ break; ++ } ++ case B_CANCEL: ++ { ++ if (state != B_OK) ++ state = B_CANCEL; ++ break; ++ } ++ default: ++ break; ++ } ++} ++ ++char *osdialog_file(osdialog_file_action action, const char *path, const char *filename, const char *filters) { ++ if (action == OSDIALOG_OPEN || action == OSDIALOG_OPEN_DIR) { ++ bool openDirMode = action == OSDIALOG_OPEN_DIR; ++ uint32 flavors = openDirMode ? B_DIRECTORY_NODE: (B_FILE_NODE | B_SYMLINK_NODE); ++ BFilePanel openPanel(B_OPEN_PANEL, NULL, NULL, flavors, false, NULL, ++ openDirMode ? new DirectoryRefFilter() : NULL, true, true); ++ FilePanelLooper *looper = new FilePanelLooper(&openPanel); ++ openPanel.SetTarget(BMessenger(looper)); ++ openPanel.SetPanelDirectory(path); ++ if (openDirMode) ++ openPanel.Window()->SetTitle("Open Folder"); ++ looper->Run(); ++ openPanel.Show(); ++ ++ while (openPanel.IsShowing()) ++ snooze(100); ++ ++ printf("open %d %d (%d %d %d)\n", openDirMode, looper->GetState(), B_CANCEL, B_OK, B_ERROR); ++ ++ entry_ref ref; ++ openPanel.Rewind(); ++ if (openPanel.GetNextSelectedRef(&ref) == B_OK && looper->GetState() != B_CANCEL) { ++ looper->Lock(); ++ looper->Quit(); ++ BPath path(&ref); ++ return strdup(path.Path()); ++ } ++ if (openDirMode && looper->GetState() != B_CANCEL) { ++ looper->Lock(); ++ looper->Quit(); ++ openPanel.GetPanelDirectory(&ref); ++ BPath path(&ref); ++ return strdup(path.Path()); ++ } ++ ++ looper->Lock(); ++ looper->Quit(); ++ } else if (action == OSDIALOG_SAVE) { ++ BFilePanel savePanel(B_SAVE_PANEL, NULL, NULL, 0, false, NULL, NULL, true, true); ++ FilePanelLooper *looper = new FilePanelLooper(&savePanel); ++ savePanel.SetTarget(BMessenger(looper)); ++ savePanel.SetPanelDirectory(path); ++ savePanel.SetSaveText(filename); ++ looper->Run(); ++ savePanel.Show(); ++ ++ while (savePanel.IsShowing()) ++ snooze(100); ++ ++ if (looper->GetPath().InitCheck() == B_OK && looper->GetState() == B_OK) { ++ BPath path = looper->GetPath(); ++ looper->Lock(); ++ looper->Quit(); ++ return strdup(path.Path()); ++ } ++ ++ looper->Lock(); ++ looper->Quit(); ++ } ++ ++ return NULL; ++} ++ ++ ++void osdialog_color_picker() { ++ printf("osdialog_color_picker\n"); ++} +-- +2.30.2 + diff --git a/media-sound/waveedit/patches/waveedit-1.1.patchset b/media-sound/waveedit/patches/waveedit-1.1.patchset new file mode 100644 index 000000000..5044b40a4 --- /dev/null +++ b/media-sound/waveedit/patches/waveedit-1.1.patchset @@ -0,0 +1,248 @@ +From 6d84ad2b98e14f421128acf37533ca08d2953221 Mon Sep 17 00:00:00 2001 +From: Gerasim Troeglazov <3dEyes@gmail.com> +Date: Thu, 21 Apr 2022 19:11:49 +1000 +Subject: Add Haiku support + + +diff --git a/Makefile b/Makefile +index b961d79..4adace6 100644 +--- a/Makefile ++++ b/Makefile +@@ -27,7 +27,12 @@ ifeq ($(ARCH),lin) + -lGL -lpthread \ + -Ldep/lib -lSDL2 -lsamplerate -lsndfile -ljansson -lcurl \ + -lgtk-x11-2.0 -lgobject-2.0 +- SOURCES += ext/osdialog/osdialog_gtk2.c ++ SOURCES += ext/osdialog/osdialog_gtk2.c ++else ifeq ($(ARCH),haiku) ++ # Haiku ++ FLAGS += -DARCH_HAIKU $(shell pkg-config --cflags sdl2) ++ LDFLAGS += -lGL -lSDL2 -lsamplerate -lsndfile -ljansson -lcurl -lbe -ltracker -lnetwork ++ SOURCES += ext/osdialog/osdialog_haiku.cpp + else ifeq ($(ARCH),mac) + # Mac + FLAGS += -DARCH_MAC \ +diff --git a/Makefile-arch.inc b/Makefile-arch.inc +index 0ff5fce..ceb7b2f 100644 +--- a/Makefile-arch.inc ++++ b/Makefile-arch.inc +@@ -8,6 +8,9 @@ ifneq (,$(findstring linux,$(MACHINE))) + else ifneq (,$(findstring apple,$(MACHINE))) + # Mac + ARCH = mac ++else ifneq (,$(findstring haiku,$(MACHINE))) ++ # Haiku ++ ARCH = haiku + else ifneq (,$(findstring mingw,$(MACHINE))) + # Windows + ARCH = win +@@ -15,4 +18,4 @@ else + $(error Could not detect architecture. Specify manually with `make ARCH=...`) + endif + +-endif +\ No newline at end of file ++endif +diff --git a/src/catalog.cpp b/src/catalog.cpp +index e2758fa..6126e13 100644 +--- a/src/catalog.cpp ++++ b/src/catalog.cpp +@@ -5,6 +5,16 @@ + #include + #include + ++#ifdef ARCH_HAIKU ++typedef struct dirent_haiku { ++ dev_t d_dev; ++ dev_t d_pdev; ++ ino_t d_ino; ++ ino_t d_pino; ++ unsigned short d_reclen; ++ char d_name[MAXNAMLEN]; ++} dirent_haiku_t; ++#endif + + std::vector catalogCategories; + +@@ -19,6 +29,24 @@ int alphaEntryComp(const void *a, const void *b) { + Sorts alphabetically, omits entries beginning with "." + Returns number of entries read + */ ++#ifdef ARCH_HAIKU ++static int dirEntries(DIR *dir, struct dirent_haiku *entries, int len) { ++ if (!dir) ++ return 0; ++ int i = 0; ++ while (i < len) { ++ struct dirent_haiku *entry = (dirent_haiku_t*)readdir(dir); ++ if (!entry) ++ break; ++ if (entry->d_name[0] == '.') ++ continue; ++ entries[i] = *entry; ++ i++; ++ } ++ qsort(entries, i, sizeof(struct dirent_haiku), alphaEntryComp); ++ return i; ++} ++#else + static int dirEntries(DIR *dir, struct dirent *entries, int len) { + if (!dir) + return 0; +@@ -39,12 +67,16 @@ static int dirEntries(DIR *dir, struct dirent *entries, int len) { + qsort(entries, i, sizeof(struct dirent), alphaEntryComp); + return i; + } +- ++#endif + + void catalogInit() { + static const char *rootPath = "catalog"; + DIR *rootDir = opendir(rootPath); ++#ifdef ARCH_HAIKU ++ struct dirent_haiku categoryEntries[128]; ++#else + struct dirent categoryEntries[128]; ++#endif + int categoriesLength = dirEntries(rootDir, categoryEntries, 128); + + for (int i = 0; i < categoriesLength; i++) { +@@ -67,7 +99,11 @@ void catalogInit() { + catalogCategory.name = name; + + DIR *categoryDir = opendir(categoryPath); ++#ifdef ARCH_HAIKU ++ struct dirent_haiku fileEntries[128]; ++#else + struct dirent fileEntries[128]; ++#endif + int filesLength = dirEntries(categoryDir, fileEntries, 128); + + for (int j = 0; j < filesLength; j++) { +diff --git a/src/main.cpp b/src/main.cpp +index d77d894..6353a01 100644 +--- a/src/main.cpp ++++ b/src/main.cpp +@@ -10,6 +10,23 @@ + #include "imgui/examples/sdl_opengl2_example/imgui_impl_sdl.h" + + ++#ifdef ARCH_HAIKU ++#include ++#include ++#include ++ ++void fixWorkingDirectory() { ++ int32 cookie = 0; ++ image_info info; ++ while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) { ++ if (info.type != B_APP_IMAGE) ++ continue; ++ chdir(dirname(realpath(info.name, nullptr))); ++ break; ++ } ++} ++#endif ++ + #ifdef ARCH_MAC + + #include // for chdir +@@ -45,7 +62,7 @@ __asm__(".symver realpath,realpath@GLIBC_2.2.5"); + int main(int argc, char **argv) { + srand(time(NULL)); + +-#ifdef ARCH_MAC ++#if defined(ARCH_MAC) || defined(ARCH_HAIKU) + fixWorkingDirectory(); + #endif + +@@ -79,7 +96,15 @@ int main(int argc, char **argv) { + // Initialize modules + uiInit(); + historyClear(); ++#ifdef ARCH_HAIKU ++ char settingsFile[PATH_MAX]; ++ char *settingsPath = SDL_GetPrefPath("Synthesis", "WaveEdit"); ++ snprintf(settingsFile, PATH_MAX, "%s/autosave.dat", settingsPath); ++ SDL_free(settingsPath); ++ currentBank.load(settingsFile); ++#else + currentBank.load("autosave.dat"); ++#endif + historyPush(); + catalogInit(); + audioInit(); +@@ -135,7 +160,11 @@ int main(int argc, char **argv) { + SDL_GL_SwapWindow(window); + } + ++#ifdef ARCH_HAIKU ++ currentBank.save(settingsFile); ++#else + currentBank.save("autosave.dat"); ++#endif + + // Cleanup + uiDestroy(); +diff --git a/src/ui.cpp b/src/ui.cpp +index 21b3f11..13d051a 100644 +--- a/src/ui.cpp ++++ b/src/ui.cpp +@@ -6,6 +6,9 @@ + #ifdef ARCH_MAC + #include + #endif ++#ifdef ARCH_HAIKU ++ #include ++#endif + #include + + #include +@@ -1072,7 +1075,15 @@ void uiInit() { + // Load UI settings + // If this gets any more complicated, it should be JSON. + { ++#ifdef ARCH_HAIKU ++ char settingsFile[PATH_MAX]; ++ char *settingsPath = SDL_GetPrefPath("Synthesis", "WaveEdit"); ++ snprintf(settingsFile, PATH_MAX, "%s/ui.dat", settingsPath); ++ SDL_free(settingsPath); ++ FILE *f = fopen(settingsFile, "rb"); ++#else + FILE *f = fopen("ui.dat", "rb"); ++#endif + if (f) { + fread(&styleId, sizeof(styleId), 1, f); + fclose(f); +@@ -1086,7 +1097,15 @@ void uiInit() { + void uiDestroy() { + // Save UI settings + { ++#ifdef ARCH_HAIKU ++ char settingsFile[PATH_MAX]; ++ char *settingsPath = SDL_GetPrefPath("Synthesis", "WaveEdit"); ++ snprintf(settingsFile, PATH_MAX, "%s/ui.dat", settingsPath); ++ SDL_free(settingsPath); ++ FILE *f = fopen(settingsFile, "wb"); ++#else + FILE *f = fopen("ui.dat", "wb"); ++#endif + if (f) { + fwrite(&styleId, sizeof(styleId), 1, f); + fclose(f); +diff --git a/src/util.cpp b/src/util.cpp +index 7c91bb0..d813d73 100644 +--- a/src/util.cpp ++++ b/src/util.cpp +@@ -15,7 +15,7 @@ void openBrowser(const char *url) { + snprintf(command, sizeof(command), "xdg-open %s", url); + system(command); + #endif +-#if defined(__APPLE__) ++#if defined(__APPLE__) || defined(__HAIKU__) + char command[1024]; + snprintf(command, sizeof(command), "open %s", url); + system(command); +-- +2.30.2 + diff --git a/media-sound/waveedit/waveedit-1.1.recipe b/media-sound/waveedit/waveedit-1.1.recipe new file mode 100644 index 000000000..5a8c19a6c --- /dev/null +++ b/media-sound/waveedit/waveedit-1.1.recipe @@ -0,0 +1,92 @@ +SUMMARY="A waveform editor for the E370 and E352 Eurorack synthesizer modules" +DESCRIPTION="WaveEdit is a free tool on PC/Mac/Linux that allows powerful creation and editing of wavetables \ +for the E352 and E370 VCOs. Using standard WAV formats, the editor includes a full toolbox of shortcuts. \ +An audio Preview is available to audition the waves before loading into the module." +HOMEPAGE="https://synthtech.com/waveedit/" +COPYRIGHT="1998-2022 Synthesis Technology" +LICENSE="GNU GPL v3" +REVISION="1" +SOURCE_URI="https://github.com/AndrewBelt/WaveEdit/archive/refs/tags/v$portVersion.tar.gz" +CHECKSUM_SHA256="d3c1fadeb99f6f12ba75cae7b40df11b3074b608767f83cf0722d97fa917a608" +SOURCE_DIR="WaveEdit-$portVersion" +srcGitRev_2="cfb1dd6cae8f4dbbcb36377edfec52a9cd874308" +SOURCE_URI_2="https://github.com/AndrewBelt/imgui/archive/$srcGitRev_2.tar.gz" +CHECKSUM_SHA256_2="1a73b8d66dff7515c072cf4aa4432fffd4256d22f231ff891329ea14e4f2de86" +SOURCE_DIR_2="imgui-$srcGitRev_2" +srcGitRev_3="8a0f16afe74a6abf85e3b45e9558283022021a59" +SOURCE_URI_3="https://github.com/lvandeve/lodepng/archive/$srcGitRev_3.zip" +CHECKSUM_SHA256_3="30a99e0b6e928f496d0c7837770c09cd36d27f48cc84e7089bea3e2b2bf8c0e7" +SOURCE_DIR_3="lodepng-$srcGitRev_3" +srcGitRev_4="c5062dc2dd6c1f053ca85fc53cc3bfbfd30e13d1" +SOURCE_URI_4="https://github.com/marton78/pffft/archive/$srcGitRev_4.zip" +CHECKSUM_SHA256_4="2922f36fef17d6a52860bb42f67e6c01192d0352edb424971a667422d767746e" +SOURCE_DIR_4="pffft-$srcGitRev_4" +srcGitRev_5="e66caf0f9d3266a79c513dcc73b57b6b3eb38120" +SOURCE_URI_5="https://github.com/AndrewBelt/osdialog/archive/$srcGitRev_5.zip" +CHECKSUM_SHA256_5="db03216390234adbadd5fe92d7adbdc8ae2d2de7752b19ffa18767c0c5392305" +SOURCE_DIR_5="osdialog-$srcGitRev_5" +PATCHES="waveedit-$portVersion.patchset" +PATCHES_5="osdialog.patchset" +ADDITIONAL_FILES="waveedit.rdef.in" + +ARCHITECTURES="all !x86_gcc2" +SECONDARY_ARCHITECTURES="x86" + +PROVIDES=" + waveedit$secondaryArchSuffix = $portVersion + app:WaveEdit = $portVersion + " +REQUIRES=" + haiku$secondaryArchSuffix + lib:libGL$secondaryArchSuffix + lib:libcurl$secondaryArchSuffix + lib:libjansson$secondaryArchSuffix + lib:libsamplerate$secondaryArchSuffix + lib:libsndfile$secondaryArchSuffix + lib:libsdl2_2.0$secondaryArchSuffix + " + +BUILD_REQUIRES=" + haiku${secondaryArchSuffix}_devel + devel:libGL$secondaryArchSuffix + devel:libcurl$secondaryArchSuffix + devel:libjansson$secondaryArchSuffix + devel:libsamplerate$secondaryArchSuffix + devel:libsndfile$secondaryArchSuffix + devel:libsdl2_2.0$secondaryArchSuffix + " +BUILD_PREREQUIRES=" + cmd:gcc$secondaryArchSuffix + cmd:make + cmd:pkg_config$secondaryArchSuffix + " + +BUILD() +{ + cp -Rf $sourceDir2/* ext/imgui + cp -Rf $sourceDir3/* ext/lodepng + cp -Rf $sourceDir4/* ext/pffft + cp -Rf $sourceDir5/* ext/osdialog + + make ARCH=haiku +} + +INSTALL() +{ + mkdir -p $appsDir/WaveEdit + cp -R {WaveEdit,logo-dark.png,logo-light.png,fonts,catalog,banks,doc/manual.pdf} $appsDir/WaveEdit + + local APP_SIGNATURE="application/x-vnd.synthesis-waveedit" + local MAJOR="`echo "$portVersion" | cut -d. -f1`" + local MIDDLE="`echo "$portVersion" | cut -d. -f2`" + local LONG_INFO="$SUMMARY" + sed \ + -e "s|@APP_SIGNATURE@|$APP_SIGNATURE|" \ + -e "s|@MAJOR@|$MAJOR|" \ + -e "s|@MIDDLE@|$MIDDLE|" \ + -e "s|@LONG_INFO@|$LONG_INFO|" \ + $portDir/additional-files/waveedit.rdef.in > waveedit.rdef + + addResourcesToBinaries waveedit.rdef $appsDir/WaveEdit/WaveEdit + addAppDeskbarSymlink $appsDir/WaveEdit/WaveEdit +}