| 
							- /*
 -  * DISTRHO Plugin Framework (DPF)
 -  * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
 -  *
 -  * Permission to use, copy, modify, and/or distribute this software for any purpose with
 -  * or without fee is hereby granted, provided that the above copyright notice and this
 -  * permission notice appear in all copies.
 -  *
 -  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
 -  * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
 -  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 -  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 -  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 -  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 -  */
 - 
 - // needed for IDE
 - #include "DistrhoPluginInfo.h"
 - 
 - #include "DistrhoUI.hpp"
 - 
 - #define MPV_TEST
 - // #define KDE_FIFO_TEST
 - 
 - #ifdef KDE_FIFO_TEST
 - // Extra includes for current path and fifo stuff
 - #include <dlfcn.h>
 - #include <fcntl.h>
 - #include <sys/stat.h>
 - #include <sys/types.h>
 - #endif
 - 
 - START_NAMESPACE_DISTRHO
 - 
 - #ifdef KDE_FIFO_TEST
 - // TODO: generate a random, not-yet-existing, filename
 - const char* const kFifoFilename = "/tmp/dpf-fifo-test";
 - 
 - // Helper to get current path of this plugin
 - static const char* getCurrentPluginFilename()
 - {
 -     Dl_info exeInfo;
 -     void* localSymbol = (void*)kFifoFilename;
 -     dladdr(localSymbol, &exeInfo);
 -     return exeInfo.dli_fname;
 - }
 - 
 - // Helper to check if a file exists
 - static bool fileExists(const char* const filename)
 - {
 -     return access(filename, F_OK) != -1;
 - }
 - 
 - // Helper function to keep trying to write until it succeeds or really errors out
 - static ssize_t
 - writeRetry(int fd, const void* src, size_t size)
 - {
 -     ssize_t error;
 -     int attempts = 0;
 - 
 -     do {
 -         error = write(fd, src, size);
 -     } while (error == -1 && (errno == EINTR || errno == EPIPE) && ++attempts < 5);
 - 
 -     return error;
 - }
 - #endif
 - 
 - // -----------------------------------------------------------------------------------------------------------
 - 
 - class ExternalExampleUI : public UI
 - {
 - public:
 -     ExternalExampleUI()
 -         : UI(405, 256),
 -          #ifdef KDE_FIFO_TEST
 -           fFifo(-1),
 -           fExternalScript(getNextBundlePath()),
 -          #endif
 -           fValue(0.0f)
 -     {
 -        #ifdef KDE_FIFO_TEST
 -         if (fExternalScript.isEmpty())
 -         {
 -             fExternalScript = getCurrentPluginFilename();
 -             fExternalScript.truncate(fExternalScript.rfind('/'));
 -         }
 - 
 -         fExternalScript += "/ExternalLauncher.sh";
 -         d_stdout("External script = %s", fExternalScript.buffer());
 -        #endif
 - 
 -         if (isVisible() || isEmbed())
 -             visibilityChanged(true);
 -     }
 - 
 -     ~ExternalExampleUI()
 -     {
 -         if (isEmbed())
 -             terminateAndWaitForExternalProcess();
 -     }
 - 
 - protected:
 -    /* --------------------------------------------------------------------------------------------------------
 -     * DSP/Plugin Callbacks */
 - 
 -    /**
 -       A parameter has changed on the plugin side.
 -       This is called by the host to inform the UI about parameter changes.
 -     */
 -     void parameterChanged(uint32_t index, float value) override
 -     {
 -         if (index != 0)
 -             return;
 - 
 -         fValue = value;
 - 
 -        #ifdef KDE_FIFO_TEST
 -         if (fFifo == -1)
 -             return;
 - 
 -         // NOTE: This is a terrible way to pass values, also locale might get in the way...
 -         char valueStr[24];
 -         std::memset(valueStr, 0, sizeof(valueStr));
 -         std::snprintf(valueStr, 23, "%i\n", static_cast<int>(value + 0.5f));
 - 
 -         DISTRHO_SAFE_ASSERT(writeRetry(fFifo, valueStr, 24) == sizeof(valueStr));
 -        #endif
 -     }
 - 
 -    /* --------------------------------------------------------------------------------------------------------
 -     * External Window overrides */
 - 
 -    /**
 -       Keep-alive.
 -     */
 -     void uiIdle() override
 -     {
 -        #ifdef KDE_FIFO_TEST
 -         if (fFifo == -1)
 -             return;
 - 
 -         writeRetry(fFifo, "idle\n", 5);
 -        #endif
 -     }
 - 
 -    /**
 -       Manage external process and IPC when UI is requested to be visible.
 -     */
 -     void visibilityChanged(const bool visible) override
 -     {
 -        #ifdef KDE_FIFO_TEST
 -         if (visible)
 -         {
 -             DISTRHO_SAFE_ASSERT_RETURN(fileExists(fExternalScript),);
 - 
 -             mkfifo(kFifoFilename, 0666);
 -             sync();
 - 
 -             char winIdStr[24];
 -             std::memset(winIdStr, 0, sizeof(winIdStr));
 -             std::snprintf(winIdStr, 23, "%lu", getTransientWindowId());
 - 
 -             const char* args[] = {
 -                 fExternalScript.buffer(),
 -                 kFifoFilename,
 -                 "--progressbar", "External UI example",
 -                 "--title", getTitle(),
 -                 nullptr,
 -             };
 -             DISTRHO_SAFE_ASSERT_RETURN(startExternalProcess(args),);
 - 
 -             // NOTE: this can lockup the current thread if the other side does not read the file!
 -             fFifo = open(kFifoFilename, O_WRONLY);
 -             DISTRHO_SAFE_ASSERT_RETURN(fFifo != -1,);
 - 
 -             parameterChanged(0, fValue);
 -         }
 -         else
 -         {
 -             if (fFifo != -1)
 -             {
 -                 if (isRunning())
 -                 {
 -                     DISTRHO_SAFE_ASSERT(writeRetry(fFifo, "quit\n", 5) == 5);
 -                     fsync(fFifo);
 -                 }
 -                 ::close(fFifo);
 -                 fFifo = -1;
 -             }
 - 
 -             unlink(kFifoFilename);
 -             terminateAndWaitForExternalProcess();
 -         }
 -        #endif
 -        #ifdef MPV_TEST
 -         if (visible)
 -         {
 -             const char* const file = "/home/falktx/Videos/HD/"; // TODO make this a state file?
 - 
 -             if (isEmbed())
 -             {
 -                 char winIdStr[64];
 -                 snprintf(winIdStr, sizeof(winIdStr), "--wid=%lu", getParentWindowHandle());
 -                 const char* args[] = {
 -                     "mpv",
 -                     "--ao=jack",
 -                     winIdStr,
 -                     file,
 -                     nullptr
 -                 };
 -                 unsetenv("LD_LIBRARY_PATH");
 -                 startExternalProcess(args);
 -             }
 -             else
 -             {
 -                 const char* args[] = {
 -                     "mpv",
 -                     "--ao=jack",
 -                     file,
 -                     nullptr
 -                 };
 -                 startExternalProcess(args);
 -             }
 -         }
 -         else
 -         {
 -             terminateAndWaitForExternalProcess();
 -         }
 -        #endif
 -     }
 - 
 -     // -------------------------------------------------------------------------------------------------------
 - 
 - private:
 -    #ifdef KDE_FIFO_TEST
 -     // IPC Stuff
 -     int fFifo;
 - 
 -     // Path to external ui script
 -     String fExternalScript;
 -    #endif
 - 
 -     // Current value, cached for when UI becomes visible
 -     float fValue;
 - 
 -    /**
 -       Set our UI class as non-copyable and add a leak detector just in case.
 -     */
 -     DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ExternalExampleUI)
 - };
 - 
 - /* ------------------------------------------------------------------------------------------------------------
 -  * UI entry point, called by DPF to create a new UI instance. */
 - 
 - UI* createUI()
 - {
 -     return new ExternalExampleUI();
 - }
 - 
 - // -----------------------------------------------------------------------------------------------------------
 - 
 - END_NAMESPACE_DISTRHO
 
 
  |