├── Source └── jmde │ └── csurf │ ├── resource.h │ ├── res.rc │ ├── csurf.h │ ├── csurf_bcf2000.cpp │ ├── csurf_main.cpp │ ├── csurf_babyhui.cpp │ ├── csurf_faderport.cpp │ ├── csurf_tranzport.cpp │ └── csurf_alphatrack.cpp ├── Builds ├── VisualStudio2013 │ ├── reaper_csurf.vcxproj.user │ ├── reaper_csurf.sln │ └── reaper_csurf.vcxproj ├── VisualStudio2015 │ ├── reaper_csurf.vcxproj.user │ ├── reaper_csurf.sln │ └── reaper_csurf.vcxproj ├── VisualStudio2017 │ ├── reaper_csurf.vcxproj.user │ ├── reaper_csurf.sln │ └── reaper_csurf.vcxproj └── VisualStudio2019 │ ├── reaper_csurf.vcxproj.user │ ├── reaper_csurf.sln │ └── reaper_csurf.vcxproj ├── README.md └── LICENSE /Source/jmde/csurf/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Developer Studio generated include file. 3 | // Used by res.rc 4 | // 5 | #define IDD_SURFACEEDIT_MCU 264 6 | #define IDD_SURFACEEDIT_MCU1 265 7 | #define IDC_CHECK1 1000 8 | #define IDC_COMBO2 1001 9 | #define IDC_COMBO3 1002 10 | #define IDC_CHECK2 1003 11 | #define IDC_EDIT1 1007 12 | #define IDC_EDIT2 1008 13 | #define IDC_EDIT1_LBL 1276 14 | #define IDC_EDIT2_LBL 1277 15 | #define IDC_EDIT2_LBL2 1278 16 | 17 | // Next default values for new objects 18 | // 19 | #ifdef APSTUDIO_INVOKED 20 | #ifndef APSTUDIO_READONLY_SYMBOLS 21 | #define _APS_NEXT_RESOURCE_VALUE 101 22 | #define _APS_NEXT_COMMAND_VALUE 40001 23 | #define _APS_NEXT_CONTROL_VALUE 1004 24 | #define _APS_NEXT_SYMED_VALUE 101 25 | #endif 26 | #endif 27 | -------------------------------------------------------------------------------- /Builds/VisualStudio2013/reaper_csurf.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | C:\Program Files\REAPER (x64)\reaper.exe 5 | WindowsLocalDebugger 6 | 7 | 8 | C:\Program Files\REAPER (x64)\reaper.exe 9 | WindowsLocalDebugger 10 | 11 | 12 | C:\Program Files (x86)\REAPER\reaper.exe 13 | WindowsLocalDebugger 14 | 15 | 16 | C:\Program Files (x86)\REAPER\reaper.exe 17 | WindowsLocalDebugger 18 | 19 | -------------------------------------------------------------------------------- /Builds/VisualStudio2015/reaper_csurf.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | C:\Program Files\REAPER (x64)\reaper.exe 5 | WindowsLocalDebugger 6 | 7 | 8 | C:\Program Files\REAPER (x64)\reaper.exe 9 | WindowsLocalDebugger 10 | 11 | 12 | C:\Program Files (x86)\REAPER\reaper.exe 13 | WindowsLocalDebugger 14 | 15 | 16 | C:\Program Files (x86)\REAPER\reaper.exe 17 | WindowsLocalDebugger 18 | 19 | -------------------------------------------------------------------------------- /Builds/VisualStudio2017/reaper_csurf.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | C:\Program Files\REAPER (x64)\reaper.exe 5 | WindowsLocalDebugger 6 | 7 | 8 | C:\Program Files\REAPER (x64)\reaper.exe 9 | WindowsLocalDebugger 10 | 11 | 12 | C:\Program Files (x86)\REAPER\reaper.exe 13 | WindowsLocalDebugger 14 | 15 | 16 | C:\Program Files (x86)\REAPER\reaper.exe 17 | WindowsLocalDebugger 18 | 19 | -------------------------------------------------------------------------------- /Builds/VisualStudio2019/reaper_csurf.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | C:\Program Files\REAPER (x64)\reaper.exe 5 | WindowsLocalDebugger 6 | 7 | 8 | C:\Program Files\REAPER (x64)\reaper.exe 9 | WindowsLocalDebugger 10 | 11 | 12 | C:\Program Files (x86)\REAPER\reaper.exe 13 | WindowsLocalDebugger 14 | 15 | 16 | C:\Program Files (x86)\REAPER\reaper.exe 17 | WindowsLocalDebugger 18 | 19 | -------------------------------------------------------------------------------- /Builds/VisualStudio2013/reaper_csurf.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 10.0.40219.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reaper_csurf", "reaper_csurf.vcxproj", "{2611354E-BF02-41DF-A603-57CD6E54EAF7}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Debug|x64.ActiveCfg = Debug|x64 17 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Debug|x64.Build.0 = Debug|x64 18 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Debug|x86.ActiveCfg = Debug|Win32 19 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Debug|x86.Build.0 = Debug|Win32 20 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Release|x64.ActiveCfg = Release|x64 21 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Release|x64.Build.0 = Release|x64 22 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Release|x86.ActiveCfg = Release|Win32 23 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /Builds/VisualStudio2015/reaper_csurf.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reaper_csurf", "reaper_csurf.vcxproj", "{2611354E-BF02-41DF-A603-57CD6E54EAF7}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Debug|x64.ActiveCfg = Debug|x64 17 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Debug|x64.Build.0 = Debug|x64 18 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Debug|x86.ActiveCfg = Debug|Win32 19 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Debug|x86.Build.0 = Debug|Win32 20 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Release|x64.ActiveCfg = Release|x64 21 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Release|x64.Build.0 = Release|x64 22 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Release|x86.ActiveCfg = Release|Win32 23 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /Builds/VisualStudio2017/reaper_csurf.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.15 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reaper_csurf", "reaper_csurf.vcxproj", "{2611354E-BF02-41DF-A603-57CD6E54EAF7}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Debug|x64.ActiveCfg = Debug|x64 17 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Debug|x64.Build.0 = Debug|x64 18 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Debug|x86.ActiveCfg = Debug|Win32 19 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Debug|x86.Build.0 = Debug|Win32 20 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Release|x64.ActiveCfg = Release|x64 21 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Release|x64.Build.0 = Release|x64 22 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Release|x86.ActiveCfg = Release|Win32 23 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /Builds/VisualStudio2019/reaper_csurf.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.15 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reaper_csurf", "reaper_csurf.vcxproj", "{2611354E-BF02-41DF-A603-57CD6E54EAF7}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Debug|x64.ActiveCfg = Debug|x64 17 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Debug|x64.Build.0 = Debug|x64 18 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Debug|x86.ActiveCfg = Debug|Win32 19 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Debug|x86.Build.0 = Debug|Win32 20 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Release|x64.ActiveCfg = Release|x64 21 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Release|x64.Build.0 = Release|x64 22 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Release|x86.ActiveCfg = Release|Win32 23 | {2611354E-BF02-41DF-A603-57CD6E54EAF7}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /Source/jmde/csurf/res.rc: -------------------------------------------------------------------------------- 1 | //Microsoft Developer Studio generated resource script. 2 | // 3 | #include "resource.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | #include "afxres.h" 11 | 12 | ///////////////////////////////////////////////////////////////////////////// 13 | #undef APSTUDIO_READONLY_SYMBOLS 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | // English (U.S.) resources 17 | 18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 19 | #ifdef _WIN32 20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 21 | #pragma code_page(1252) 22 | #endif //_WIN32 23 | 24 | #ifdef APSTUDIO_INVOKED 25 | ///////////////////////////////////////////////////////////////////////////// 26 | // 27 | // TEXTINCLUDE 28 | // 29 | 30 | 1 TEXTINCLUDE DISCARDABLE 31 | BEGIN 32 | "resource.h\0" 33 | END 34 | 35 | 2 TEXTINCLUDE DISCARDABLE 36 | BEGIN 37 | "#include ""afxres.h""\r\n" 38 | "\0" 39 | END 40 | 41 | 3 TEXTINCLUDE DISCARDABLE 42 | BEGIN 43 | "\r\n" 44 | "\0" 45 | END 46 | 47 | #endif // APSTUDIO_INVOKED 48 | 49 | 50 | ///////////////////////////////////////////////////////////////////////////// 51 | // 52 | // Dialog 53 | // 54 | 55 | IDD_SURFACEEDIT_MCU DIALOG DISCARDABLE 0, 0, 268, 77 56 | STYLE DS_CENTER | WS_CHILD 57 | FONT 8, "MS Shell Dlg" 58 | BEGIN 59 | RTEXT "MIDI input:",IDC_STATIC,23,6,56,8 60 | COMBOBOX IDC_COMBO2,81,4,181,105,CBS_DROPDOWNLIST | WS_VSCROLL | 61 | WS_TABSTOP 62 | RTEXT "MIDI output:",IDC_STATIC,23,23,56,8 63 | COMBOBOX IDC_COMBO3,81,21,181,105,CBS_DROPDOWNLIST | WS_VSCROLL | 64 | WS_TABSTOP 65 | RTEXT "Surface offset (tracks):",IDC_EDIT1_LBL,4,42,72,8 66 | EDITTEXT IDC_EDIT1,81,41,24,12,ES_AUTOHSCROLL 67 | RTEXT "Size tweak:",IDC_EDIT2_LBL,30,58,47,8 68 | EDITTEXT IDC_EDIT2,80,55,24,12,ES_AUTOHSCROLL 69 | LTEXT "(leave at 9 unless you know what you're doing)", 70 | IDC_EDIT2_LBL2,108,58,148,8 71 | END 72 | 73 | IDD_SURFACEEDIT_MCU1 DIALOG DISCARDABLE 0, 0, 268, 95 74 | STYLE DS_CENTER | WS_CHILD 75 | FONT 8, "MS Shell Dlg" 76 | BEGIN 77 | RTEXT "MIDI input:",IDC_STATIC,23,6,56,8 78 | COMBOBOX IDC_COMBO2,81,4,181,105,CBS_DROPDOWNLIST | WS_VSCROLL | 79 | WS_TABSTOP 80 | RTEXT "MIDI output:",IDC_STATIC,23,23,56,8 81 | COMBOBOX IDC_COMBO3,81,21,181,105,CBS_DROPDOWNLIST | WS_VSCROLL | 82 | WS_TABSTOP 83 | RTEXT "Surface offset (tracks):",IDC_EDIT1_LBL,4,37,72,8 84 | EDITTEXT IDC_EDIT1,81,36,24,12,ES_AUTOHSCROLL 85 | RTEXT "Size tweak:",IDC_EDIT2_LBL,30,53,47,8 86 | EDITTEXT IDC_EDIT2,80,50,24,12,ES_AUTOHSCROLL 87 | LTEXT "(leave at 9 unless you know what you're doing)", 88 | IDC_EDIT2_LBL2,108,52,148,8 89 | CONTROL "Ignore fader moves when fader is not being touched", 90 | IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,67, 91 | 177,10 92 | CONTROL "Map F1-F8 to go to markers",IDC_CHECK2,"Button", 93 | BS_AUTOCHECKBOX | WS_TABSTOP,4,78,102,10 94 | END 95 | 96 | ///////////////////////////////////////////////////////////////////////////// 97 | // 98 | // DESIGNINFO 99 | // 100 | 101 | #ifdef APSTUDIO_INVOKED 102 | GUIDELINES DESIGNINFO DISCARDABLE 103 | BEGIN 104 | IDD_SURFACEEDIT_MCU, DIALOG 105 | BEGIN 106 | LEFTMARGIN, 4 107 | RIGHTMARGIN, 264 108 | TOPMARGIN, 4 109 | BOTTOMMARGIN, 73 110 | END 111 | 112 | IDD_SURFACEEDIT_MCU1, DIALOG 113 | BEGIN 114 | LEFTMARGIN, 4 115 | RIGHTMARGIN, 264 116 | TOPMARGIN, 4 117 | BOTTOMMARGIN, 91 118 | END 119 | END 120 | #endif // APSTUDIO_INVOKED 121 | 122 | #endif // English (U.S.) resources 123 | ///////////////////////////////////////////////////////////////////////////// 124 | 125 | 126 | 127 | #ifndef APSTUDIO_INVOKED 128 | ///////////////////////////////////////////////////////////////////////////// 129 | // 130 | // Generated from the TEXTINCLUDE 3 resource. 131 | // 132 | 133 | 134 | ///////////////////////////////////////////////////////////////////////////// 135 | #endif // not APSTUDIO_INVOKED 136 | 137 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Building REAPER CSurf with Visual Studio 2 | This repository contains a REAPER Surface Controller (CSurf) project for all Reaper versions, 3 | running on Windows 32 and 64 bit. It describes step by step how to build and debug with 4 | Microsoft Visual Studio (Free Community Edition). 5 | 6 | ## Introduction 7 | A [surface controller](https://en.wikipedia.org/wiki/Audio_control_surface) allows users to control 8 | a DAW ([Digital Audio Workstation](https://en.wikipedia.org/wiki/Digital_audio_workstation)), in this case REAPER. Supporting new surface controllers in REAPER is not well documented. The goal of this project to provide you a quick-start. 9 | 10 | The free C++ REAPER Extension SDK is required to build a Surface Controller for REAPER. It is based on an old Visual C++ 6 project and supports a 32-bit version only for REAPER. Upgrading the project to a newer Visual Studio versions requires some project changes and knowledge which are already applied. 11 | 12 | ## Prerequisites 13 | * Windows (7/8/10) 14 | 15 | * Microsoft Visual Studio (Tested with the free Community Edition): 16 | 17 | * REAPER version 4, 5 and 6. (32 or 64 bit) 18 | 19 | * REAPER Extension SDK 20 | 21 | * A compatible surface, for example: 22 | 23 | * [Behringer X-Touch](https://www.google.nl/search?q=behringer+x-touch) 24 | * [Mackie Controller](https://www.google.nl/search?q=mackie+mcu+pro) 25 | 26 | * [Behringer BCF2000](https://www.google.nl/search?q=behringer+bcf2000) 27 | * [Presonus faderport](https://www.google.nl/search?q=presonus+faderport) 28 | 29 | * C++ knowledge 30 | 31 | ### Installation 32 | 1. Install Visual Studio 2013, 2015, 2017, 2019 (Free Community Edition) or higher. 33 | VS2019 requirements during installation: 34 | * MSVC v142 - VS 2019 C++ x64/x86 build tools. 35 | * Windows 10 SDK 36 | * C++ MFC for latest v142 build tools 37 | * Others are optional 38 | 2. Download REAPER SDK from: 39 | https://www.reaper.fm/sdk/plugin/reaper_extension_sdk.zip 40 | 3. Extract ```reaper_extension_sdk.zip``` for example into ```C:\reaper_extension_sdk\```. 41 | 4. Add an environment variable to the REAPER Extension SDK: 42 | * Start ```Windows Explorer``` 43 | * Right mouse click ```This PC``` 44 | * Click ```Advanced system settings``` 45 | * Click ```Environment Variables...``` 46 | * Create a new ```System variable:``` 47 | * Variable name: ```REAPER_EXTENSION_SDK``` 48 | * Variable value: ```C:\reaper_extension_sdk``` 49 | 50 | 5. Clone this repository with the GIT command: 51 | ```git clone https://github.com/Erriez/reaper_csurf_vs201x.git``` 52 | or download and extract the ZIP of this repository. 53 | 54 | 6. Open the solution ```Builds\VisualStudio\reaper_csurf.sln``` with Visual Studio. 55 | Note: Replace `````` with the Visual Studio version, for example 2013, 2015 or 2017. 56 | 57 | 7. Select in the toolbar: 58 | * ```Debug``` (Default) 59 | * For REAPER 64-bit: ```x64``` (Default) 60 | * For REAPER 32-bit: ```x86``` 61 | 62 | 8. Open the ```Solution Explorer``` | Right mouse click ```reaper_csurf``` | Properties: 63 | * Select ```Configuration```: ```Debug``` or ```Release```. 64 | * Select ```Platform```: ```Win32``` or ```x64```. 65 | * Set ```Debugging | Command:``` 66 | * For REAPER 32-bit: ```C:\Program Files (x86)\REAPER\reaper.exe``` 67 | * For REAPER 64-bit: ```C:\Program Files\REAPER (x64)\reaper.exe``` 68 | * Check the REAPER Extension SDK environment variable: 69 | * ```VC++ Directories | Include Directories:``` should contain ```$(REAPER_EXTENSION_SDK)``` 70 | or the full path to the REAPER Extension SDK. 71 | * Set ``` Build Events | Post-Build Event | Command Line:``` 72 | * For REAPER 32-bit: ```copy "x64\Debug\reaper_csurf_x86.dll" "%APPDATA%\REAPER\UserPlugins\"``` 73 | * For REAPER 64-bit: ```copy "x64\Debug\reaper_csurf_x64.dll" "%APPDATA%\REAPER\UserPlugins\"``` 74 | 75 | 9. Rename original REAPER CSurf DLL to something else to prevent conflicts between the original and 76 | new CSurf: 77 | * For REAPER 32-bit: ```C:\Program Files\REAPER\Plugins\reaper_csurf.dll.org``` 78 | * For REAPER 64-bit: ```C:\Program Files\REAPER (x64)\Plugins\reaper_csurf.dll.org``` 79 | 80 | 10. Set a breakpoint in ```csurf_main.cpp``` function ```REAPER_PLUGIN_ENTRYPOINT()```. 81 | 82 | 11. Click the green ```Local Windows Debugger``` button to build and start debugging. 83 | 84 | 12. REAPER will be started automatically and the breakpoint should be hit. Now you're ready to debug 85 | and add support for new surfaces or change the behavior of existing surfaces. 86 | 87 | 13. In REAPER click ```Tools | Preferences | Control/OSC/web``` Click ```Add``` to add a surface. 88 | 89 | ### Wiki 90 | A more detailed description of the CSurf project settings and code is located on 91 | [the Wiki page](https://github.com/Erriez/reaper_csurf_vs2015/wiki). 92 | 93 | ### FAQ 94 | 95 | > Q: Is OSX supported? 96 | 97 | Short answer: No. 98 | Long answer: I will not support MAC. 99 | 100 | ### Contact 101 | Please use the [REAPER forum](https://forum.cockos.com/showthread.php?p=1884391). 102 | -------------------------------------------------------------------------------- /Source/jmde/csurf/csurf.h: -------------------------------------------------------------------------------- 1 | #ifndef _CSURF_H_ 2 | #define _CSURF_H_ 3 | 4 | #include "../reaper_plugin.h" 5 | #include "WDL/db2val.h" 6 | #include "WDL/wdlstring.h" 7 | #include 8 | #include "resource.h" 9 | 10 | 11 | 12 | extern REAPER_PLUGIN_HINSTANCE g_hInst; // used for dialogs 13 | extern HWND g_hwnd; 14 | /* 15 | ** Calls back to REAPER (all validated on load) 16 | */ 17 | extern double (*DB2SLIDER)(double x); 18 | extern double (*SLIDER2DB)(double y); 19 | extern int (*GetNumMIDIInputs)(); 20 | extern int (*GetNumMIDIOutputs)(); 21 | extern midi_Input *(*CreateMIDIInput)(int dev); 22 | extern midi_Output *(*CreateMIDIOutput)(int dev, bool streamMode, int *msoffset100); 23 | extern bool (*GetMIDIOutputName)(int dev, char *nameout, int nameoutlen); 24 | extern bool (*GetMIDIInputName)(int dev, char *nameout, int nameoutlen); 25 | 26 | 27 | extern int (*CSurf_TrackToID)(MediaTrack *track, bool mcpView); 28 | extern MediaTrack *(*CSurf_TrackFromID)(int idx, bool mcpView); 29 | extern int (*CSurf_NumTracks)(bool mcpView); 30 | 31 | // these will be called from app when something changes 32 | extern void (*CSurf_SetTrackListChange)(); 33 | extern void (*CSurf_SetSurfaceVolume)(MediaTrack *trackid, double volume, IReaperControlSurface *ignoresurf); 34 | extern void (*CSurf_SetSurfacePan)(MediaTrack *trackid, double pan, IReaperControlSurface *ignoresurf); 35 | extern void (*CSurf_SetSurfaceMute)(MediaTrack *trackid, bool mute, IReaperControlSurface *ignoresurf); 36 | extern void (*CSurf_SetSurfaceSelected)(MediaTrack *trackid, bool selected, IReaperControlSurface *ignoresurf); 37 | extern void (*CSurf_SetSurfaceSolo)(MediaTrack *trackid, bool solo, IReaperControlSurface *ignoresurf); 38 | extern void (*CSurf_SetSurfaceRecArm)(MediaTrack *trackid, bool recarm, IReaperControlSurface *ignoresurf); 39 | extern bool (*CSurf_GetTouchState)(MediaTrack *trackid, int isPan); 40 | extern void (*CSurf_SetAutoMode)(int mode, IReaperControlSurface *ignoresurf); 41 | 42 | extern void (*CSurf_SetPlayState)(bool play, bool pause, bool rec, IReaperControlSurface *ignoresurf); 43 | extern void (*CSurf_SetRepeatState)(bool rep, IReaperControlSurface *ignoresurf); 44 | 45 | // these are called by our surfaces, and actually update the project 46 | extern double (*CSurf_OnVolumeChange)(MediaTrack *trackid, double volume, bool relative); 47 | extern double (*CSurf_OnPanChange)(MediaTrack *trackid, double pan, bool relative); 48 | extern bool (*CSurf_OnMuteChange)(MediaTrack *trackid, int mute); 49 | extern bool (*CSurf_OnSelectedChange)(MediaTrack *trackid, int selected); 50 | extern bool (*CSurf_OnSoloChange)(MediaTrack *trackid, int solo); 51 | extern bool (*CSurf_OnFXChange)(MediaTrack *trackid, int en); 52 | extern bool (*CSurf_OnRecArmChange)(MediaTrack *trackid, int recarm); 53 | extern void (*CSurf_OnPlay)(); 54 | extern void (*CSurf_OnStop)(); 55 | extern void (*CSurf_OnFwd)(int seekplay); 56 | extern void (*CSurf_OnRew)(int seekplay); 57 | extern void (*CSurf_OnRecord)(); 58 | extern void (*CSurf_GoStart)(); 59 | extern void (*CSurf_GoEnd)(); 60 | extern void (*CSurf_OnArrow)(int whichdir, bool wantzoom); 61 | extern void (*CSurf_OnTrackSelection)(MediaTrack *trackid); 62 | extern void (*CSurf_ResetAllCachedVolPanStates)(); 63 | extern void (*CSurf_ScrubAmt)(double amt); 64 | 65 | extern void (*kbd_OnMidiEvent)(MIDI_event_t *evt, int dev_index); 66 | 67 | extern const char *(*GetTrackInfo)(INT_PTR track, int *flags); 68 | 69 | extern int (*GetMasterMuteSoloFlags)(); 70 | extern void (*TrackList_UpdateAllExternalSurfaces)(); 71 | 72 | extern void (*MoveEditCursor)(double adjamt, bool dosel); 73 | extern void (*adjustZoom)(double amt, int forceset, bool doupd, int centermode); // 0,true,-1 are defaults 74 | extern double (*GetHZoomLevel)(); // returns pixels/second 75 | 76 | 77 | extern void (*ClearAllRecArmed)(); 78 | extern void (*SetTrackAutomationMode)(MediaTrack *tr, int mode); 79 | extern int (*GetTrackAutomationMode)(MediaTrack *tr); 80 | extern void (*SoloAllTracks)(int solo); // solo=2 for SIP 81 | extern void (*MuteAllTracks)(bool mute); 82 | extern void (*BypassFxAllTracks)(int bypass); // -1 = bypass all if not all bypassed, otherwise unbypass all 83 | extern void (*SetTrackSelected)(MediaTrack *tr, bool sel); 84 | extern int (*GetPlayState)(); 85 | extern double (*GetPlayPosition)(); 86 | extern double (*GetCursorPosition)(); 87 | extern void (*format_timestr_pos)(double tpos, char *buf, int buflen, int modeoverride); // modeoverride=-1 for proj 88 | extern void (*UpdateTimeline)(void); 89 | 90 | extern int (*GetSetRepeat)(int val); 91 | 92 | extern void (*SetAutomationMode)(int mode, bool onlySel); 93 | extern void (*Main_UpdateLoopInfo)(int ignoremask); 94 | 95 | extern double (*TimeMap2_timeToBeats)(void *proj, double tpos, int *measures, int *cml, double *fullbeats, int *cdenom); 96 | 97 | extern void * (*projectconfig_var_addr)(void *proj, int idx); 98 | 99 | extern double (*Track_GetPeakInfo)(MediaTrack *tr, int chidx); 100 | extern bool (*GetTrackUIVolPan)(MediaTrack *tr, double *vol, double *pan); 101 | extern void (*mkvolpanstr)(char *str, double vol, double pan); 102 | extern void (*mkvolstr)(char *str, double vol); 103 | extern void (*mkpanstr)(char *str, double pan); 104 | 105 | extern int (*TrackFX_GetCount)(MediaTrack *tr); 106 | extern int (*TrackFX_GetNumParams)(MediaTrack *tr, int fx); 107 | extern double (*TrackFX_GetParam)(MediaTrack *tr, int fx, int param, double *minval, double *maxval); 108 | extern bool (*TrackFX_SetParam)(MediaTrack *tr, int fx, int param, double val); 109 | extern bool (*TrackFX_GetParamName)(MediaTrack *tr, int fx, int param, char *buf, int buflen); 110 | extern bool (*TrackFX_FormatParamValue)(MediaTrack *tr, int fx, int param, double val, char *buf, int buflen); 111 | extern bool (*TrackFX_GetFXName)(MediaTrack *tr, int fx, char *buf, int buflen); 112 | extern GUID *(*GetTrackGUID)(MediaTrack *tr); 113 | 114 | extern int *g_config_csurf_rate,*g_config_zoommode; 115 | 116 | extern int __g_projectconfig_timemode2, __g_projectconfig_timemode; 117 | extern int __g_projectconfig_timeoffs; 118 | extern int __g_projectconfig_measoffs; 119 | 120 | /* 121 | ** REAPER command message defines 122 | */ 123 | 124 | #define IDC_REPEAT 1068 125 | #define ID_FILE_SAVEAS 40022 126 | #define ID_FILE_NEWPROJECT 40023 127 | #define ID_FILE_OPENPROJECT 40025 128 | #define ID_FILE_SAVEPROJECT 40026 129 | #define IDC_EDIT_UNDO 40029 130 | #define IDC_EDIT_REDO 40030 131 | #define ID_MARKER_PREV 40172 132 | #define ID_MARKER_NEXT 40173 133 | #define ID_INSERT_MARKERRGN 40174 134 | #define ID_INSERT_MARKER 40157 135 | #define ID_LOOP_SETSTART 40222 136 | #define ID_LOOP_SETEND 40223 137 | #define ID_METRONOME 40364 138 | #define ID_GOTO_MARKER1 40161 139 | #define ID_SET_MARKER1 40657 140 | 141 | // Reaper track automation modes 142 | enum AutoMode { 143 | AUTO_MODE_TRIM, 144 | AUTO_MODE_READ, 145 | AUTO_MODE_TOUCH, 146 | AUTO_MODE_WRITE, 147 | AUTO_MODE_LATCH, 148 | }; 149 | 150 | midi_Output *CreateThreadedMIDIOutput(midi_Output *output); // returns null on null 151 | 152 | #endif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /Source/jmde/csurf/csurf_bcf2000.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** reaper_csurf 3 | ** BCFF2k support 4 | ** Copyright (C) 2006-2008 Cockos Incorporated 5 | ** License: LGPL. 6 | */ 7 | 8 | 9 | #include "csurf.h" 10 | 11 | static bool g_csurf_mcpmode=false; // we may wish to allow an action to set this 12 | 13 | static double charToVol(unsigned char val) 14 | { 15 | double pos=((double)val*1000.0)/127.0; 16 | pos=SLIDER2DB(pos); 17 | return DB2VAL(pos); 18 | 19 | } 20 | 21 | static unsigned char volToChar(double vol) 22 | { 23 | double d=(DB2SLIDER(VAL2DB(vol))*127.0/1000.0); 24 | if (d<0.0)d=0.0; 25 | else if (d>127.0)d=127.0; 26 | 27 | return (unsigned char)(d+0.5); 28 | } 29 | 30 | static double charToPan(unsigned char val) 31 | { 32 | double pos=((double)val*1000.0+0.5)/127.0; 33 | 34 | pos=(pos-500.0)/500.0; 35 | if (fabs(pos) < 0.08) pos=0.0; 36 | 37 | return pos; 38 | } 39 | 40 | static unsigned char panToChar(double pan) 41 | { 42 | pan = (pan+1.0)*63.5; 43 | 44 | if (pan<0.0)pan=0.0; 45 | else if (pan>127.0)pan=127.0; 46 | 47 | return (unsigned char)(pan+0.5); 48 | } 49 | 50 | 51 | 52 | 53 | class CSurf_BCF2k : public IReaperControlSurface 54 | { 55 | int m_midi_in_dev,m_midi_out_dev; 56 | int m_offset, m_size; 57 | midi_Output *m_midiout; 58 | midi_Input *m_midiin; 59 | 60 | WDL_String descspace; 61 | char configtmp[1024]; 62 | 63 | unsigned int m_pan_lasttouch[256]; 64 | unsigned int m_vol_lasttouch[256]; 65 | 66 | int m_vol_lastpos[256]; 67 | int m_pan_lastpos[256]; 68 | 69 | void OnMIDIEvent(MIDI_event_t *evt) 70 | { 71 | if ((evt->midi_message[0]&0xf0) == 0xB0) 72 | { 73 | int bank=evt->midi_message[0]&0xf; 74 | 75 | if (evt->midi_message[1] >= 0x51 && evt->midi_message[1] <= 0x58) // volume set 76 | { 77 | int trackid=(evt->midi_message[1]-0x51)+bank*8 + m_offset; 78 | m_vol_lastpos[(trackid)&0xff]=evt->midi_message[2]; 79 | m_vol_lasttouch[(trackid)&0xff]=GetTickCount(); 80 | MediaTrack *tr=CSurf_TrackFromID(trackid,g_csurf_mcpmode); 81 | if (tr) CSurf_SetSurfaceVolume(tr,CSurf_OnVolumeChange(tr,charToVol(evt->midi_message[2]),false),this); 82 | } 83 | else if (evt->midi_message[1] >= 0x21 && evt->midi_message[1] <= 0x28) // pan reset 84 | { 85 | int trackid=((evt->midi_message[1]-0x21)&7)+bank*8 + m_offset; 86 | m_pan_lasttouch[trackid&0xff]=GetTickCount(); 87 | MediaTrack *tr=CSurf_TrackFromID(trackid,g_csurf_mcpmode); 88 | if (tr) CSurf_SetSurfacePan(tr,CSurf_OnPanChange(tr,0.0,false),NULL); 89 | } 90 | else if (evt->midi_message[1] >= 0x41 && evt->midi_message[1] <= 0x50) // mute/solo 91 | { 92 | int trackid=((evt->midi_message[1]-0x41)&7)+bank*8 + m_offset; 93 | int wi=(evt->midi_message[1]-0x41)&8; 94 | MediaTrack *tr=CSurf_TrackFromID(trackid,g_csurf_mcpmode); 95 | 96 | if (tr) 97 | { 98 | if (!wi) 99 | CSurf_SetSurfaceSolo(tr,CSurf_OnSoloChange(tr,evt->midi_message[2]>=0x40),this); 100 | else 101 | CSurf_SetSurfaceMute(tr,CSurf_OnMuteChange(tr,evt->midi_message[2]>=0x40),this); 102 | } 103 | } 104 | else if (evt->midi_message[1] >= 0x01 && evt->midi_message[1] <= 0x08) // pan set 105 | { 106 | int trackid=(evt->midi_message[1]-0x01)+bank*8 + m_offset; 107 | m_pan_lasttouch[trackid&0xff]=GetTickCount(); 108 | m_pan_lastpos[trackid&0xff]=evt->midi_message[2]; 109 | 110 | MediaTrack *tr=CSurf_TrackFromID(trackid,g_csurf_mcpmode); 111 | if (tr) CSurf_SetSurfacePan(tr,CSurf_OnPanChange(tr,charToPan(evt->midi_message[2]),false),this); 112 | } 113 | else if (evt->midi_message[1] == 0x59) CSurf_OnPlay(); 114 | else if (evt->midi_message[1] == 0x5a) CSurf_OnStop(); 115 | else if (evt->midi_message[1] == 0x5b) 116 | { 117 | CSurf_OnRew(1); 118 | evt->midi_message[2]=0; 119 | if (m_midiout) m_midiout->SendMsg(evt,-1); 120 | } 121 | else if (evt->midi_message[1] == 0x5c) 122 | { 123 | CSurf_OnFwd(1); 124 | evt->midi_message[2]=0; 125 | if (m_midiout) m_midiout->SendMsg(evt,-1); 126 | } 127 | } 128 | } 129 | 130 | public: 131 | CSurf_BCF2k(int offset, int size, int indev, int outdev, int *errStats) 132 | { 133 | m_offset=offset; 134 | m_size=size; 135 | m_midi_in_dev=indev; 136 | m_midi_out_dev=outdev; 137 | 138 | memset(m_vol_lastpos,0xff,sizeof(m_vol_lastpos)); 139 | memset(m_pan_lastpos,0xff,sizeof(m_pan_lastpos)); 140 | memset(m_pan_lasttouch,0,sizeof(m_pan_lasttouch)); 141 | memset(m_vol_lasttouch,0,sizeof(m_vol_lasttouch)); 142 | 143 | //create midi hardware access 144 | m_midiin = m_midi_in_dev >= 0 ? CreateMIDIInput(m_midi_in_dev) : NULL; 145 | m_midiout = m_midi_out_dev >= 0 ? CreateThreadedMIDIOutput(CreateMIDIOutput(m_midi_out_dev,false,NULL)) : NULL; 146 | 147 | if (errStats) 148 | { 149 | if (m_midi_in_dev >=0 && !m_midiin) *errStats|=1; 150 | if (m_midi_out_dev >=0 && !m_midiout) *errStats|=2; 151 | } 152 | 153 | if (m_midiin) 154 | m_midiin->start(); 155 | 156 | } 157 | ~CSurf_BCF2k() 158 | { 159 | delete m_midiout; 160 | delete m_midiin; 161 | } 162 | 163 | 164 | const char *GetTypeString() { return "BCF2K"; } 165 | const char *GetDescString() 166 | { 167 | descspace.Set("BCF 2000"); 168 | char tmp[512]; 169 | sprintf(tmp," (dev %d,%d)",m_midi_in_dev,m_midi_out_dev); 170 | descspace.Append(tmp); 171 | return descspace.Get(); 172 | } 173 | const char *GetConfigString() // string of configuration data 174 | { 175 | sprintf(configtmp,"%d %d %d %d",m_offset,m_size,m_midi_in_dev,m_midi_out_dev); 176 | return configtmp; 177 | } 178 | 179 | void CloseNoReset() 180 | { 181 | delete m_midiout; 182 | delete m_midiin; 183 | m_midiout=0; 184 | m_midiin=0; 185 | } 186 | 187 | void Run() 188 | { 189 | if (m_midiin) 190 | { 191 | m_midiin->SwapBufs(timeGetTime()); 192 | int l=0; 193 | MIDI_eventlist *list=m_midiin->GetReadBuf(); 194 | MIDI_event_t *evts; 195 | while ((evts=list->EnumItems(&l))) OnMIDIEvent(evts); 196 | } 197 | } 198 | 199 | void SetTrackListChange() { } // not used 200 | 201 | #define FIXID(id) int id=CSurf_TrackToID(trackid,g_csurf_mcpmode); int oid=id; id -= m_offset; 202 | 203 | void SetSurfaceVolume(MediaTrack *trackid, double volume) 204 | { 205 | FIXID(id) 206 | if (m_midiout && id >= 0 && id < 256 && id < m_size) 207 | { 208 | unsigned char volch=volToChar(volume); 209 | 210 | if (m_vol_lastpos[id]!=volch) 211 | { 212 | m_vol_lastpos[id]=volch; 213 | m_midiout->Send(0xB0+id/8,0x51+(id&7),volch,-1); 214 | } 215 | } 216 | } 217 | void SetSurfacePan(MediaTrack *trackid, double pan) 218 | { 219 | FIXID(id) 220 | if (m_midiout && id >= 0 && id < 256 && id < m_size) 221 | { 222 | unsigned char panch=panToChar(pan); 223 | if (m_pan_lastpos[id] != panch) 224 | { 225 | m_pan_lastpos[id]=panch; 226 | m_midiout->Send(0xb0+id/8,0x1 + (id&7),panch,-1); 227 | } 228 | } 229 | } 230 | void SetSurfaceMute(MediaTrack *trackid, bool mute) 231 | { 232 | FIXID(id) 233 | if (m_midiout && id>=0 && id < 256 && id < m_size) 234 | { 235 | m_midiout->Send(0xb0+id/8,0x49+(id&7),mute?0x7f:0,-1); 236 | } 237 | } 238 | void SetSurfaceSelected(MediaTrack *trackid, bool selected) 239 | { 240 | // not used 241 | } 242 | void SetSurfaceSolo(MediaTrack *trackid, bool solo) 243 | { 244 | FIXID(id) 245 | if (m_midiout && id>=0 && id < 256 && id < m_size) 246 | { 247 | m_midiout->Send(0xb0+id/8,0x41+(id&7),solo?0x7f:0,-1); 248 | } 249 | } 250 | void SetSurfaceRecArm(MediaTrack *trackid, bool recarm) 251 | { 252 | // not used 253 | } 254 | void SetPlayState(bool play, bool pause, bool rec) 255 | { 256 | if (m_midiout) 257 | { 258 | m_midiout->Send(0xb0,0x59,play?0x7f:0,-1); 259 | m_midiout->Send(0xb0,0x5a,pause?0x7f:0,-1); 260 | } 261 | } 262 | void SetRepeatState(bool rep) 263 | { 264 | // not used 265 | } 266 | 267 | void SetTrackTitle(MediaTrack *trackid, const char *title) { } 268 | bool GetTouchState(MediaTrack *trackid, int isPan) 269 | { 270 | FIXID(id) 271 | unsigned int *wb=isPan == 1 ? m_pan_lasttouch : m_vol_lasttouch; 272 | if (oid >= 0 && oid < 256) 273 | { 274 | DWORD now=timeGetTime(); 275 | if ((now= wb[oid]-1000)) // fake touch, go for 3s after last movement 276 | return true; 277 | } 278 | return false; 279 | } 280 | 281 | void SetAutoMode(int mode) { } 282 | 283 | void ResetCachedVolPanStates() 284 | { 285 | memset(m_vol_lastpos,0xff,sizeof(m_vol_lastpos)); 286 | memset(m_pan_lastpos,0xff,sizeof(m_pan_lastpos)); 287 | } 288 | void OnTrackSelection(MediaTrack *trackid) 289 | { 290 | } 291 | 292 | bool IsKeyDown(int key) 293 | { 294 | return false; 295 | } 296 | 297 | 298 | }; 299 | 300 | 301 | static void parseParms(const char *str, int parms[4]) 302 | { 303 | parms[0]=0; 304 | parms[1]=9; 305 | parms[2]=parms[3]=-1; 306 | 307 | const char *p=str; 308 | if (p) 309 | { 310 | int x=0; 311 | while (x<4) 312 | { 313 | while (*p == ' ') p++; 314 | if ((*p < '0' || *p > '9') && *p != '-') break; 315 | parms[x++]=atoi(p); 316 | while (*p && *p != ' ') p++; 317 | } 318 | } 319 | } 320 | 321 | static IReaperControlSurface *createFunc(const char *type_string, const char *configString, int *errStats) 322 | { 323 | int parms[4]; 324 | parseParms(configString,parms); 325 | 326 | return new CSurf_BCF2k(parms[0],parms[1],parms[2],parms[3],errStats); 327 | } 328 | 329 | 330 | static WDL_DLGRET dlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 331 | { 332 | switch (uMsg) 333 | { 334 | case WM_INITDIALOG: 335 | { 336 | int parms[4]; 337 | parseParms((const char *)lParam,parms); 338 | 339 | int n=GetNumMIDIInputs(); 340 | int x=SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_ADDSTRING,0,(LPARAM)"None"); 341 | SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_SETITEMDATA,x,-1); 342 | x=SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_ADDSTRING,0,(LPARAM)"None"); 343 | SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_SETITEMDATA,x,-1); 344 | for (x = 0; x < n; x ++) 345 | { 346 | char buf[512]; 347 | if (GetMIDIInputName(x,buf,sizeof(buf))) 348 | { 349 | int a=SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_ADDSTRING,0,(LPARAM)buf); 350 | SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_SETITEMDATA,a,x); 351 | if (x == parms[2]) SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_SETCURSEL,a,0); 352 | } 353 | } 354 | n=GetNumMIDIOutputs(); 355 | for (x = 0; x < n; x ++) 356 | { 357 | char buf[512]; 358 | if (GetMIDIOutputName(x,buf,sizeof(buf))) 359 | { 360 | int a=SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_ADDSTRING,0,(LPARAM)buf); 361 | SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_SETITEMDATA,a,x); 362 | if (x == parms[3]) SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_SETCURSEL,a,0); 363 | } 364 | } 365 | SetDlgItemInt(hwndDlg,IDC_EDIT1,parms[0],TRUE); 366 | SetDlgItemInt(hwndDlg,IDC_EDIT2,parms[1],FALSE); 367 | } 368 | break; 369 | case WM_USER+1024: 370 | if (wParam > 1 && lParam) 371 | { 372 | char tmp[512]; 373 | 374 | int indev=-1, outdev=-1, offs=0, size=9; 375 | int r=SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_GETCURSEL,0,0); 376 | if (r != CB_ERR) indev = SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_GETITEMDATA,r,0); 377 | r=SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_GETCURSEL,0,0); 378 | if (r != CB_ERR) outdev = SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_GETITEMDATA,r,0); 379 | 380 | BOOL t; 381 | r=GetDlgItemInt(hwndDlg,IDC_EDIT1,&t,TRUE); 382 | if (t) offs=r; 383 | r=GetDlgItemInt(hwndDlg,IDC_EDIT2,&t,FALSE); 384 | if (t) 385 | { 386 | if (r<1)r=1; 387 | else if(r>256)r=256; 388 | size=r; 389 | } 390 | 391 | sprintf(tmp,"%d %d %d %d",offs,size,indev,outdev); 392 | lstrcpyn((char *)lParam, tmp,wParam); 393 | 394 | } 395 | break; 396 | } 397 | return 0; 398 | } 399 | 400 | static HWND configFunc(const char *type_string, HWND parent, const char *initConfigString) 401 | { 402 | return CreateDialogParam(g_hInst,MAKEINTRESOURCE(IDD_SURFACEEDIT_MCU),parent,dlgProc,(LPARAM)initConfigString); 403 | } 404 | 405 | 406 | reaper_csurf_reg_t csurf_bcf_reg = 407 | { 408 | "BCF2K", 409 | "Behringer BCF2000 (using preset 1)", 410 | createFunc, 411 | configFunc, 412 | }; -------------------------------------------------------------------------------- /Source/jmde/csurf/csurf_main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** reaper_csurf 3 | ** Copyright (C) 2006-2008 Cockos Incorporated 4 | ** License: LGPL. 5 | */ 6 | 7 | 8 | #include "csurf.h" 9 | 10 | extern reaper_csurf_reg_t csurf_bcf_reg,csurf_faderport_reg,csurf_hui_reg, 11 | csurf_mcu_reg,csurf_mcuex_reg,csurf_tranzport_reg,csurf_alphatrack_reg,csurf_01X_reg; 12 | 13 | REAPER_PLUGIN_HINSTANCE g_hInst; // used for dialogs, if any 14 | HWND g_hwnd; 15 | 16 | 17 | double (*DB2SLIDER)(double x); 18 | double (*SLIDER2DB)(double y); 19 | int (*GetNumMIDIInputs)(); 20 | int (*GetNumMIDIOutputs)(); 21 | midi_Input *(*CreateMIDIInput)(int dev); 22 | midi_Output *(*CreateMIDIOutput)(int dev, bool streamMode, int *msoffset100); 23 | bool (*GetMIDIOutputName)(int dev, char *nameout, int nameoutlen); 24 | bool (*GetMIDIInputName)(int dev, char *nameout, int nameoutlen); 25 | 26 | void * (*projectconfig_var_addr)(void*proj, int idx); 27 | 28 | 29 | int (*CSurf_TrackToID)(MediaTrack *track, bool mcpView); 30 | MediaTrack *(*CSurf_TrackFromID)(int idx, bool mcpView); 31 | int (*CSurf_NumTracks)(bool mcpView); 32 | 33 | // these will be called from app when something changes 34 | void (*CSurf_SetTrackListChange)(); 35 | void (*CSurf_SetSurfaceVolume)(MediaTrack *trackid, double volume, IReaperControlSurface *ignoresurf); 36 | void (*CSurf_SetSurfacePan)(MediaTrack *trackid, double pan, IReaperControlSurface *ignoresurf); 37 | void (*CSurf_SetSurfaceMute)(MediaTrack *trackid, bool mute, IReaperControlSurface *ignoresurf); 38 | void (*CSurf_SetSurfaceSelected)(MediaTrack *trackid, bool selected, IReaperControlSurface *ignoresurf); 39 | void (*CSurf_SetSurfaceSolo)(MediaTrack *trackid, bool solo, IReaperControlSurface *ignoresurf); 40 | void (*CSurf_SetSurfaceRecArm)(MediaTrack *trackid, bool recarm, IReaperControlSurface *ignoresurf); 41 | bool (*CSurf_GetTouchState)(MediaTrack *trackid, int isPan); 42 | void (*CSurf_SetAutoMode)(int mode, IReaperControlSurface *ignoresurf); 43 | 44 | void (*CSurf_SetPlayState)(bool play, bool pause, bool rec, IReaperControlSurface *ignoresurf); 45 | void (*CSurf_SetRepeatState)(bool rep, IReaperControlSurface *ignoresurf); 46 | 47 | // these are called by our surfaces, and actually update the project 48 | double (*CSurf_OnVolumeChange)(MediaTrack *trackid, double volume, bool relative); 49 | double (*CSurf_OnPanChange)(MediaTrack *trackid, double pan, bool relative); 50 | bool (*CSurf_OnMuteChange)(MediaTrack *trackid, int mute); 51 | bool (*CSurf_OnSelectedChange)(MediaTrack *trackid, int selected); 52 | bool (*CSurf_OnSoloChange)(MediaTrack *trackid, int solo); 53 | bool (*CSurf_OnFXChange)(MediaTrack *trackid, int en); 54 | bool (*CSurf_OnRecArmChange)(MediaTrack *trackid, int recarm); 55 | void (*CSurf_OnPlay)(); 56 | void (*CSurf_OnStop)(); 57 | void (*CSurf_OnFwd)(int seekplay); 58 | void (*CSurf_OnRew)(int seekplay); 59 | void (*CSurf_OnRecord)(); 60 | void (*CSurf_GoStart)(); 61 | void (*CSurf_GoEnd)(); 62 | void (*CSurf_OnArrow)(int whichdir, bool wantzoom); 63 | void (*CSurf_OnTrackSelection)(MediaTrack *trackid); 64 | void (*CSurf_ResetAllCachedVolPanStates)(); 65 | void (*CSurf_ScrubAmt)(double amt); 66 | 67 | void (*kbd_OnMidiEvent)(MIDI_event_t *evt, int dev_index); 68 | void (*TrackList_UpdateAllExternalSurfaces)(); 69 | int (*GetMasterMuteSoloFlags)(); 70 | void (*ClearAllRecArmed)(); 71 | void (*SetTrackAutomationMode)(MediaTrack *tr, int mode); 72 | int (*GetTrackAutomationMode)(MediaTrack *tr); 73 | void (*SoloAllTracks)(int solo); // solo=2 for SIP 74 | void (*MuteAllTracks)(bool mute); 75 | void (*BypassFxAllTracks)(int bypass); // -1 = bypass all if not all bypassed, otherwise unbypass all 76 | const char *(*GetTrackInfo)(INT_PTR track, int *flags); 77 | void (*SetTrackSelected)(MediaTrack *tr, bool sel); 78 | void (*UpdateTimeline)(void); 79 | int (*GetPlayState)(); 80 | double (*GetPlayPosition)(); 81 | double (*GetCursorPosition)(); 82 | int (*GetSetRepeat)(int val); 83 | 84 | void (*format_timestr_pos)(double tpos, char *buf, int buflen, int modeoverride); // modeoverride=-1 for proj 85 | void (*SetAutomationMode)(int mode, bool onlySel); // sets all or selected tracks 86 | void (*Main_UpdateLoopInfo)(int ignoremask); 87 | 88 | double (*TimeMap2_timeToBeats)(void *proj, double tpos, int *measures, int *cml, double *fullbeats, int *cdenom); 89 | double (*Track_GetPeakInfo)(MediaTrack *tr, int chidx); 90 | void (*mkvolpanstr)(char *str, double vol, double pan); 91 | void (*mkvolstr)(char *str, double vol); 92 | void (*mkpanstr)(char *str, double pan); 93 | 94 | bool (*GetTrackUIVolPan)(MediaTrack *tr, double *vol, double *pan); 95 | 96 | 97 | 98 | void (*MoveEditCursor)(double adjamt, bool dosel); 99 | void (*adjustZoom)(double amt, int forceset, bool doupd, int centermode); // forceset=0, doupd=true, centermode=-1 for default 100 | double (*GetHZoomLevel)(); // returns pixels/second 101 | 102 | 103 | int (*TrackFX_GetCount)(MediaTrack *tr); 104 | int (*TrackFX_GetNumParams)(MediaTrack *tr, int fx); 105 | bool (*TrackFX_GetFXName)(MediaTrack *tr, int fx, char *buf, int buflen); 106 | double (*TrackFX_GetParam)(MediaTrack *tr, int fx, int param, double *minval, double *maxval); 107 | bool (*TrackFX_SetParam)(MediaTrack *tr, int fx, int param, double val); 108 | bool (*TrackFX_GetParamName)(MediaTrack *tr, int fx, int param, char *buf, int buflen); 109 | bool (*TrackFX_FormatParamValue)(MediaTrack *tr, int fx, int param, double val, char *buf, int buflen); 110 | GUID *(*GetTrackGUID)(MediaTrack *tr); 111 | 112 | 113 | int *g_config_csurf_rate,*g_config_zoommode; 114 | 115 | int __g_projectconfig_timemode2, __g_projectconfig_timemode; 116 | int __g_projectconfig_measoffs; 117 | int __g_projectconfig_timeoffs; // double 118 | 119 | extern "C" 120 | { 121 | 122 | REAPER_PLUGIN_DLL_EXPORT int REAPER_PLUGIN_ENTRYPOINT(REAPER_PLUGIN_HINSTANCE hInstance, reaper_plugin_info_t *rec) 123 | { 124 | g_hInst=hInstance; 125 | 126 | if (!rec || rec->caller_version != REAPER_PLUGIN_VERSION || !rec->GetFunc) 127 | return 0; 128 | 129 | g_hwnd = rec->hwnd_main; 130 | int errcnt=0; 131 | #define IMPAPI(x) if (!((*((void **)&(x)) = (void *)rec->GetFunc(#x)))) errcnt++; 132 | 133 | IMPAPI(DB2SLIDER) 134 | IMPAPI(SLIDER2DB) 135 | IMPAPI(GetNumMIDIInputs) 136 | IMPAPI(GetNumMIDIOutputs) 137 | IMPAPI(CreateMIDIInput) 138 | IMPAPI(CreateMIDIOutput) 139 | IMPAPI(GetMIDIOutputName) 140 | IMPAPI(GetMIDIInputName) 141 | IMPAPI(CSurf_TrackToID) 142 | IMPAPI(CSurf_TrackFromID) 143 | IMPAPI(CSurf_NumTracks) 144 | IMPAPI(CSurf_SetTrackListChange) 145 | IMPAPI(CSurf_SetSurfaceVolume) 146 | IMPAPI(CSurf_SetSurfacePan) 147 | IMPAPI(CSurf_SetSurfaceMute) 148 | IMPAPI(CSurf_SetSurfaceSelected) 149 | IMPAPI(CSurf_SetSurfaceSolo) 150 | IMPAPI(CSurf_SetSurfaceRecArm) 151 | IMPAPI(CSurf_GetTouchState) 152 | IMPAPI(CSurf_SetAutoMode) 153 | IMPAPI(CSurf_SetPlayState) 154 | IMPAPI(CSurf_SetRepeatState) 155 | IMPAPI(CSurf_OnVolumeChange) 156 | IMPAPI(CSurf_OnPanChange) 157 | IMPAPI(CSurf_OnMuteChange) 158 | IMPAPI(CSurf_OnSelectedChange) 159 | IMPAPI(CSurf_OnSoloChange) 160 | IMPAPI(CSurf_OnFXChange) 161 | IMPAPI(CSurf_OnRecArmChange) 162 | IMPAPI(CSurf_OnPlay) 163 | IMPAPI(CSurf_OnStop) 164 | IMPAPI(CSurf_OnFwd) 165 | IMPAPI(CSurf_OnRew) 166 | IMPAPI(CSurf_OnRecord) 167 | IMPAPI(CSurf_GoStart) 168 | IMPAPI(CSurf_GoEnd) 169 | IMPAPI(CSurf_OnArrow) 170 | IMPAPI(CSurf_OnTrackSelection) 171 | IMPAPI(CSurf_ResetAllCachedVolPanStates) 172 | IMPAPI(CSurf_ScrubAmt) 173 | IMPAPI(TrackList_UpdateAllExternalSurfaces) 174 | IMPAPI(kbd_OnMidiEvent) 175 | IMPAPI(GetMasterMuteSoloFlags) 176 | IMPAPI(ClearAllRecArmed) 177 | IMPAPI(SetTrackAutomationMode) 178 | IMPAPI(GetTrackAutomationMode) 179 | IMPAPI(SoloAllTracks) 180 | IMPAPI(MuteAllTracks) 181 | IMPAPI(BypassFxAllTracks) 182 | IMPAPI(GetTrackInfo) 183 | IMPAPI(SetTrackSelected) 184 | IMPAPI(SetAutomationMode) 185 | IMPAPI(UpdateTimeline) 186 | IMPAPI(Main_UpdateLoopInfo) 187 | IMPAPI(GetPlayState) 188 | IMPAPI(GetPlayPosition) 189 | IMPAPI(GetCursorPosition) 190 | IMPAPI(format_timestr_pos) 191 | IMPAPI(TimeMap2_timeToBeats) 192 | IMPAPI(Track_GetPeakInfo) 193 | IMPAPI(GetTrackUIVolPan) 194 | IMPAPI(GetSetRepeat) 195 | IMPAPI(mkvolpanstr) 196 | IMPAPI(mkvolstr) 197 | IMPAPI(mkpanstr) 198 | IMPAPI(MoveEditCursor) 199 | IMPAPI(adjustZoom) 200 | IMPAPI(GetHZoomLevel) 201 | 202 | IMPAPI(TrackFX_GetCount) 203 | IMPAPI(TrackFX_GetNumParams) 204 | IMPAPI(TrackFX_GetParam) 205 | IMPAPI(TrackFX_SetParam) 206 | IMPAPI(TrackFX_GetParamName) 207 | IMPAPI(TrackFX_FormatParamValue) 208 | IMPAPI(TrackFX_GetFXName) 209 | 210 | IMPAPI(GetTrackGUID) 211 | 212 | void * (*get_config_var)(const char *name, int *szout); 213 | int (*projectconfig_var_getoffs)(const char *name, int *szout); 214 | IMPAPI(get_config_var); 215 | IMPAPI(projectconfig_var_getoffs); 216 | IMPAPI(projectconfig_var_addr); 217 | if (errcnt) return 0; 218 | 219 | int sztmp; 220 | #define IMPVAR(x,nm) if (!((*(void **)&(x)) = get_config_var(nm,&sztmp)) || sztmp != sizeof(*x)) errcnt++; 221 | #define IMPVARP(x,nm,type) if (!((x) = projectconfig_var_getoffs(nm,&sztmp)) || sztmp != sizeof(type)) errcnt++; 222 | IMPVAR(g_config_csurf_rate,"csurfrate") 223 | IMPVAR(g_config_zoommode,"zoommode") 224 | 225 | IMPVARP(__g_projectconfig_timemode,"projtimemode",int) 226 | IMPVARP(__g_projectconfig_timemode2,"projtimemode2",int) 227 | IMPVARP(__g_projectconfig_timeoffs,"projtimeoffs",double); 228 | IMPVARP(__g_projectconfig_measoffs,"projmeasoffs",int); 229 | 230 | 231 | if (errcnt) return 0; 232 | 233 | 234 | rec->Register("csurf",&csurf_bcf_reg); 235 | rec->Register("csurf",&csurf_faderport_reg); 236 | rec->Register("csurf",&csurf_hui_reg); 237 | rec->Register("csurf",&csurf_mcu_reg); 238 | rec->Register("csurf",&csurf_mcuex_reg); 239 | rec->Register("csurf",&csurf_tranzport_reg); 240 | rec->Register("csurf",&csurf_alphatrack_reg); 241 | rec->Register("csurf",&csurf_01X_reg); 242 | 243 | return 1; 244 | 245 | } 246 | 247 | }; 248 | 249 | 250 | 251 | 252 | 253 | #ifndef _WIN32 // MAC resources 254 | #include "../../WDL/swell/swell-dlggen.h" 255 | #include "res.rc_mac_dlg" 256 | #undef BEGIN 257 | #undef END 258 | #include "../../WDL/swell/swell-menugen.h" 259 | #include "res.rc_mac_menu" 260 | #endif 261 | 262 | 263 | #ifndef _WIN32 // let OS X use this threading step 264 | 265 | #include "../../WDL/mutex.h" 266 | #include "../../WDL/ptrlist.h" 267 | 268 | 269 | 270 | class threadedMIDIOutput : public midi_Output 271 | { 272 | public: 273 | threadedMIDIOutput(midi_Output *out) 274 | { 275 | m_output=out; 276 | m_quit=false; 277 | DWORD id; 278 | m_hThread=CreateThread(NULL,0,threadProc,this,0,&id); 279 | } 280 | virtual ~threadedMIDIOutput() 281 | { 282 | if (m_hThread) 283 | { 284 | m_quit=true; 285 | WaitForSingleObject(m_hThread,INFINITE); 286 | CloseHandle(m_hThread); 287 | m_hThread=0; 288 | Sleep(30); 289 | } 290 | 291 | delete m_output; 292 | m_empty.Empty(true); 293 | m_full.Empty(true); 294 | } 295 | 296 | virtual void SendMsg(MIDI_event_t *msg, int frame_offset) // frame_offset can be <0 for "instant" if supported 297 | { 298 | if (!msg) return; 299 | 300 | WDL_HeapBuf *b=NULL; 301 | if (m_empty.GetSize()) 302 | { 303 | m_mutex.Enter(); 304 | b=m_empty.Get(m_empty.GetSize()-1); 305 | m_empty.Delete(m_empty.GetSize()-1); 306 | m_mutex.Leave(); 307 | } 308 | if (!b && m_empty.GetSize()+m_full.GetSize()<500) 309 | b=new WDL_HeapBuf(256); 310 | 311 | if (b) 312 | { 313 | int sz=msg->size; 314 | if (sz<3)sz=3; 315 | int len = msg->midi_message + sz - (unsigned char *)msg; 316 | memcpy(b->Resize(len,false),msg,len); 317 | m_mutex.Enter(); 318 | m_full.Add(b); 319 | m_mutex.Leave(); 320 | } 321 | } 322 | 323 | virtual void Send(unsigned char status, unsigned char d1, unsigned char d2, int frame_offset) // frame_offset can be <0 for "instant" if supported 324 | { 325 | MIDI_event_t evt={0,3,status,d1,d2}; 326 | SendMsg(&evt,frame_offset); 327 | } 328 | 329 | /////////// 330 | 331 | static DWORD WINAPI threadProc(LPVOID p) 332 | { 333 | WDL_HeapBuf *lastbuf=NULL; 334 | threadedMIDIOutput *_this=(threadedMIDIOutput*)p; 335 | unsigned int scnt=0; 336 | for (;;) 337 | { 338 | if (_this->m_full.GetSize()||lastbuf) 339 | { 340 | _this->m_mutex.Enter(); 341 | if (lastbuf) _this->m_empty.Add(lastbuf); 342 | lastbuf=_this->m_full.Get(0); 343 | _this->m_full.Delete(0); 344 | _this->m_mutex.Leave(); 345 | 346 | if (lastbuf) _this->m_output->SendMsg((MIDI_event_t*)lastbuf->Get(),-1); 347 | scnt=0; 348 | } 349 | else 350 | { 351 | Sleep(1); 352 | if (_this->m_quit&&scnt++>3) break; //only quit once all messages have been sent 353 | } 354 | } 355 | delete lastbuf; 356 | return 0; 357 | } 358 | 359 | WDL_Mutex m_mutex; 360 | WDL_PtrList m_full,m_empty; 361 | 362 | HANDLE m_hThread; 363 | bool m_quit; 364 | midi_Output *m_output; 365 | }; 366 | 367 | 368 | 369 | 370 | midi_Output *CreateThreadedMIDIOutput(midi_Output *output) 371 | { 372 | if (!output) return output; 373 | return new threadedMIDIOutput(output); 374 | } 375 | 376 | #else 377 | 378 | // windows doesnt need it since we have threaded midi outputs now 379 | midi_Output *CreateThreadedMIDIOutput(midi_Output *output) 380 | { 381 | return output; 382 | } 383 | 384 | #endif -------------------------------------------------------------------------------- /Builds/VisualStudio2013/reaper_csurf.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | {2611354E-BF02-41DF-A603-57CD6E54EAF7} 43 | 44 | 45 | 46 | DynamicLibrary 47 | v140 48 | false 49 | MultiByte 50 | 51 | 52 | DynamicLibrary 53 | v120 54 | false 55 | MultiByte 56 | 57 | 58 | DynamicLibrary 59 | v140 60 | false 61 | MultiByte 62 | 63 | 64 | DynamicLibrary 65 | v140 66 | false 67 | MultiByte 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | .\Release\ 91 | .\Release\ 92 | false 93 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(REAPER_EXTENSION_SDK) 94 | 95 | 96 | false 97 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(REAPER_EXTENSION_SDK) 98 | 99 | 100 | .\Debug\ 101 | .\Debug\ 102 | true 103 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(REAPER_EXTENSION_SDK) 104 | 105 | 106 | true 107 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(REAPER_EXTENSION_SDK) 108 | 109 | 110 | 111 | MultiThreadedDLL 112 | Default 113 | true 114 | true 115 | MaxSpeed 116 | true 117 | Level3 118 | OldStyle 119 | WIN32;NDEBUG;_WINDOWS;_USRDLL;REAPER_CSURF_EXPORTS;%(PreprocessorDefinitions) 120 | .\Release\ 121 | .\Release\reaper_csurf.pch 122 | .\Release\ 123 | .\Release\ 124 | 125 | 126 | true 127 | NDEBUG;%(PreprocessorDefinitions) 128 | .\Release\reaper_csurf.tlb 129 | true 130 | Win32 131 | 132 | 133 | 0x0409 134 | NDEBUG;%(PreprocessorDefinitions) 135 | 136 | 137 | true 138 | .\Release\reaper_csurf.bsc 139 | 140 | 141 | true 142 | true 143 | Console 144 | $(OutDir)\reaper_csurf_x86.dll 145 | .\Release\reaper_csurf.lib 146 | odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies) 147 | 148 | 149 | 150 | 151 | copy "Release\reaper_csurf_x86.dll" "%APPDATA%\REAPER\UserPlugins\" 152 | 153 | 154 | 155 | 156 | MultiThreadedDLL 157 | Default 158 | true 159 | true 160 | MaxSpeed 161 | true 162 | Level3 163 | OldStyle 164 | WIN32;NDEBUG;_WINDOWS;_USRDLL;REAPER_CSURF_EXPORTS;%(PreprocessorDefinitions) 165 | .\x64\Release\ 166 | .\x64\Release\reaper_csurf.pch 167 | .\x64\Release\ 168 | .\x64\Release\ 169 | 170 | 171 | true 172 | NDEBUG;%(PreprocessorDefinitions) 173 | .\Release\reaper_csurf.tlb 174 | true 175 | 176 | 177 | 0x0409 178 | NDEBUG;%(PreprocessorDefinitions) 179 | 180 | 181 | true 182 | .\x64\Release\reaper_csurf.bsc 183 | 184 | 185 | true 186 | true 187 | Console 188 | $(OutDir)\reaper_csurf_x64.dll 189 | .\x64\Release\reaper_csurf.lib 190 | odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies) 191 | 192 | 193 | 194 | 195 | copy "x64\Release\reaper_csurf_x64.dll" "%APPDATA%\REAPER\UserPlugins\" 196 | 197 | 198 | 199 | 200 | MultiThreadedDebug 201 | Default 202 | true 203 | Disabled 204 | true 205 | Level3 206 | true 207 | EditAndContinue 208 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;REAPER_CSURF_EXPORTS;%(PreprocessorDefinitions) 209 | .\Debug\ 210 | .\Debug\reaper_csurf.pch 211 | .\Debug\ 212 | .\Debug\ 213 | EnableFastChecks 214 | 215 | 216 | true 217 | _DEBUG;%(PreprocessorDefinitions) 218 | .\Debug\reaper_csurf.tlb 219 | true 220 | Win32 221 | 222 | 223 | 0x0409 224 | _DEBUG;%(PreprocessorDefinitions) 225 | 226 | 227 | true 228 | .\Debug\reaper_csurf.bsc 229 | 230 | 231 | true 232 | true 233 | true 234 | Console 235 | $(OutDir)\reaper_csurf_x86.dll 236 | .\Debug\reaper_csurf.lib 237 | odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies) 238 | 239 | 240 | copy "Debug\reaper_csurf_x86.dll" "%APPDATA%\REAPER\UserPlugins\" 241 | 242 | 243 | 244 | 245 | MultiThreadedDebug 246 | Default 247 | true 248 | Disabled 249 | true 250 | Level2 251 | ProgramDatabase 252 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;REAPER_CSURF_EXPORTS;%(PreprocessorDefinitions) 253 | .\x64\Debug\ 254 | .\x64\Debug\reaper_csurf.pch 255 | .\x64\Debug\ 256 | .\x64\Debug\ 257 | EnableFastChecks 258 | 259 | 260 | true 261 | _DEBUG;%(PreprocessorDefinitions) 262 | .\Debug\reaper_csurf.tlb 263 | true 264 | 265 | 266 | 0x0409 267 | _DEBUG;%(PreprocessorDefinitions) 268 | 269 | 270 | true 271 | .\x64\Debug\reaper_csurf.bsc 272 | 273 | 274 | true 275 | true 276 | true 277 | Console 278 | $(OutDir)\reaper_csurf_x64.dll 279 | .\x64\Debug\reaper_csurf_x64.lib 280 | odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies) 281 | 282 | 283 | copy "x64\Debug\reaper_csurf_x64.dll" "%APPDATA%\REAPER\UserPlugins\" 284 | 285 | 286 | 287 | 288 | 289 | -------------------------------------------------------------------------------- /Builds/VisualStudio2015/reaper_csurf.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | {2611354E-BF02-41DF-A603-57CD6E54EAF7} 43 | 44 | 45 | 46 | DynamicLibrary 47 | v140 48 | false 49 | MultiByte 50 | 51 | 52 | DynamicLibrary 53 | v140 54 | false 55 | MultiByte 56 | 57 | 58 | DynamicLibrary 59 | v140 60 | false 61 | MultiByte 62 | 63 | 64 | DynamicLibrary 65 | v140 66 | false 67 | MultiByte 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | .\Release\ 91 | .\Release\ 92 | false 93 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(REAPER_EXTENSION_SDK) 94 | 95 | 96 | false 97 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(REAPER_EXTENSION_SDK) 98 | 99 | 100 | .\Debug\ 101 | .\Debug\ 102 | true 103 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(REAPER_EXTENSION_SDK) 104 | 105 | 106 | true 107 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(REAPER_EXTENSION_SDK) 108 | 109 | 110 | 111 | MultiThreadedDLL 112 | Default 113 | true 114 | true 115 | MaxSpeed 116 | true 117 | Level3 118 | OldStyle 119 | WIN32;NDEBUG;_WINDOWS;_USRDLL;REAPER_CSURF_EXPORTS;%(PreprocessorDefinitions) 120 | .\Release\ 121 | .\Release\reaper_csurf.pch 122 | .\Release\ 123 | .\Release\ 124 | 125 | 126 | true 127 | NDEBUG;%(PreprocessorDefinitions) 128 | .\Release\reaper_csurf.tlb 129 | true 130 | Win32 131 | 132 | 133 | 0x0409 134 | NDEBUG;%(PreprocessorDefinitions) 135 | 136 | 137 | true 138 | .\Release\reaper_csurf.bsc 139 | 140 | 141 | true 142 | true 143 | Console 144 | $(OutDir)\reaper_csurf_x86.dll 145 | .\Release\reaper_csurf.lib 146 | odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies) 147 | 148 | 149 | 150 | 151 | copy "Release\reaper_csurf_x86.dll" "%APPDATA%\REAPER\UserPlugins\" 152 | 153 | 154 | 155 | 156 | MultiThreadedDLL 157 | Default 158 | true 159 | true 160 | MaxSpeed 161 | true 162 | Level3 163 | OldStyle 164 | WIN32;NDEBUG;_WINDOWS;_USRDLL;REAPER_CSURF_EXPORTS;%(PreprocessorDefinitions) 165 | .\x64\Release\ 166 | .\x64\Release\reaper_csurf.pch 167 | .\x64\Release\ 168 | .\x64\Release\ 169 | 170 | 171 | true 172 | NDEBUG;%(PreprocessorDefinitions) 173 | .\Release\reaper_csurf.tlb 174 | true 175 | 176 | 177 | 0x0409 178 | NDEBUG;%(PreprocessorDefinitions) 179 | 180 | 181 | true 182 | .\x64\Release\reaper_csurf.bsc 183 | 184 | 185 | true 186 | true 187 | Console 188 | $(OutDir)\reaper_csurf_x64.dll 189 | .\x64\Release\reaper_csurf.lib 190 | odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies) 191 | 192 | 193 | 194 | 195 | copy "x64\Release\reaper_csurf_x64.dll" "%APPDATA%\REAPER\UserPlugins\" 196 | 197 | 198 | 199 | 200 | MultiThreadedDebug 201 | Default 202 | true 203 | Disabled 204 | true 205 | Level3 206 | true 207 | EditAndContinue 208 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;REAPER_CSURF_EXPORTS;%(PreprocessorDefinitions) 209 | .\Debug\ 210 | .\Debug\reaper_csurf.pch 211 | .\Debug\ 212 | .\Debug\ 213 | EnableFastChecks 214 | 215 | 216 | true 217 | _DEBUG;%(PreprocessorDefinitions) 218 | .\Debug\reaper_csurf.tlb 219 | true 220 | Win32 221 | 222 | 223 | 0x0409 224 | _DEBUG;%(PreprocessorDefinitions) 225 | 226 | 227 | true 228 | .\Debug\reaper_csurf.bsc 229 | 230 | 231 | true 232 | true 233 | true 234 | Console 235 | $(OutDir)\reaper_csurf_x86.dll 236 | .\Debug\reaper_csurf.lib 237 | odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies) 238 | 239 | 240 | copy "Debug\reaper_csurf_x86.dll" "%APPDATA%\REAPER\UserPlugins\" 241 | 242 | 243 | 244 | 245 | MultiThreadedDebug 246 | Default 247 | true 248 | Disabled 249 | true 250 | Level2 251 | ProgramDatabase 252 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;REAPER_CSURF_EXPORTS;%(PreprocessorDefinitions) 253 | .\x64\Debug\ 254 | .\x64\Debug\reaper_csurf.pch 255 | .\x64\Debug\ 256 | .\x64\Debug\ 257 | EnableFastChecks 258 | 259 | 260 | true 261 | _DEBUG;%(PreprocessorDefinitions) 262 | .\Debug\reaper_csurf.tlb 263 | true 264 | 265 | 266 | 0x0409 267 | _DEBUG;%(PreprocessorDefinitions) 268 | 269 | 270 | true 271 | .\x64\Debug\reaper_csurf.bsc 272 | 273 | 274 | true 275 | true 276 | true 277 | Console 278 | $(OutDir)\reaper_csurf_x64.dll 279 | .\x64\Debug\reaper_csurf_x64.lib 280 | odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies) 281 | 282 | 283 | copy "x64\Debug\reaper_csurf_x64.dll" "%APPDATA%\REAPER\UserPlugins\" 284 | 285 | 286 | 287 | 288 | 289 | -------------------------------------------------------------------------------- /Builds/VisualStudio2019/reaper_csurf.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | {2611354E-BF02-41DF-A603-57CD6E54EAF7} 43 | 10.0 44 | 45 | 46 | 47 | DynamicLibrary 48 | v142 49 | false 50 | MultiByte 51 | 52 | 53 | DynamicLibrary 54 | v142 55 | false 56 | MultiByte 57 | 58 | 59 | DynamicLibrary 60 | v142 61 | false 62 | MultiByte 63 | 64 | 65 | DynamicLibrary 66 | v142 67 | false 68 | MultiByte 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | .\Release\ 92 | .\Release\ 93 | false 94 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(REAPER_EXTENSION_SDK) 95 | 96 | 97 | false 98 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(REAPER_EXTENSION_SDK) 99 | 100 | 101 | .\Debug\ 102 | .\Debug\ 103 | true 104 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(REAPER_EXTENSION_SDK) 105 | 106 | 107 | true 108 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(REAPER_EXTENSION_SDK) 109 | 110 | 111 | 112 | MultiThreadedDLL 113 | Default 114 | true 115 | true 116 | MaxSpeed 117 | true 118 | Level3 119 | OldStyle 120 | WIN32;NDEBUG;_WINDOWS;_USRDLL;REAPER_CSURF_EXPORTS;%(PreprocessorDefinitions) 121 | .\Release\ 122 | .\Release\reaper_csurf.pch 123 | .\Release\ 124 | .\Release\ 125 | 126 | 127 | true 128 | NDEBUG;%(PreprocessorDefinitions) 129 | .\Release\reaper_csurf.tlb 130 | true 131 | Win32 132 | 133 | 134 | 0x0409 135 | NDEBUG;%(PreprocessorDefinitions) 136 | 137 | 138 | true 139 | .\Release\reaper_csurf.bsc 140 | 141 | 142 | true 143 | true 144 | Console 145 | $(OutDir)\reaper_csurf_x86.dll 146 | .\Release\reaper_csurf.lib 147 | odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies) 148 | 149 | 150 | 151 | 152 | copy "Release\reaper_csurf_x86.dll" "%APPDATA%\REAPER\UserPlugins\" 153 | 154 | 155 | 156 | 157 | MultiThreadedDLL 158 | Default 159 | true 160 | true 161 | MaxSpeed 162 | true 163 | Level3 164 | OldStyle 165 | WIN32;NDEBUG;_WINDOWS;_USRDLL;REAPER_CSURF_EXPORTS;%(PreprocessorDefinitions) 166 | .\x64\Release\ 167 | .\x64\Release\reaper_csurf.pch 168 | .\x64\Release\ 169 | .\x64\Release\ 170 | 171 | 172 | true 173 | NDEBUG;%(PreprocessorDefinitions) 174 | .\Release\reaper_csurf.tlb 175 | true 176 | 177 | 178 | 0x0409 179 | NDEBUG;%(PreprocessorDefinitions) 180 | 181 | 182 | true 183 | .\x64\Release\reaper_csurf.bsc 184 | 185 | 186 | true 187 | true 188 | Console 189 | $(OutDir)\reaper_csurf_x64.dll 190 | .\x64\Release\reaper_csurf.lib 191 | odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies) 192 | 193 | 194 | 195 | 196 | copy "x64\Release\reaper_csurf_x64.dll" "%APPDATA%\REAPER\UserPlugins\" 197 | 198 | 199 | 200 | 201 | MultiThreadedDebug 202 | Default 203 | true 204 | Disabled 205 | true 206 | Level3 207 | true 208 | EditAndContinue 209 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;REAPER_CSURF_EXPORTS;%(PreprocessorDefinitions) 210 | .\Debug\ 211 | .\Debug\reaper_csurf.pch 212 | .\Debug\ 213 | .\Debug\ 214 | EnableFastChecks 215 | 216 | 217 | true 218 | _DEBUG;%(PreprocessorDefinitions) 219 | .\Debug\reaper_csurf.tlb 220 | true 221 | Win32 222 | 223 | 224 | 0x0409 225 | _DEBUG;%(PreprocessorDefinitions) 226 | 227 | 228 | true 229 | .\Debug\reaper_csurf.bsc 230 | 231 | 232 | true 233 | true 234 | true 235 | Console 236 | $(OutDir)\reaper_csurf_x86.dll 237 | .\Debug\reaper_csurf.lib 238 | odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies) 239 | 240 | 241 | copy "Debug\reaper_csurf_x86.dll" "%APPDATA%\REAPER\UserPlugins\" 242 | 243 | 244 | 245 | 246 | MultiThreadedDebug 247 | Default 248 | true 249 | Disabled 250 | true 251 | Level2 252 | ProgramDatabase 253 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;REAPER_CSURF_EXPORTS;%(PreprocessorDefinitions) 254 | .\x64\Debug\ 255 | .\x64\Debug\reaper_csurf.pch 256 | .\x64\Debug\ 257 | .\x64\Debug\ 258 | EnableFastChecks 259 | 260 | 261 | true 262 | _DEBUG;%(PreprocessorDefinitions) 263 | .\Debug\reaper_csurf.tlb 264 | true 265 | 266 | 267 | 0x0409 268 | _DEBUG;%(PreprocessorDefinitions) 269 | 270 | 271 | true 272 | .\x64\Debug\reaper_csurf.bsc 273 | 274 | 275 | true 276 | true 277 | true 278 | Console 279 | $(OutDir)\reaper_csurf_x64.dll 280 | .\x64\Debug\reaper_csurf_x64.lib 281 | odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies) 282 | 283 | 284 | copy "x64\Debug\reaper_csurf_x64.dll" "%APPDATA%\REAPER\UserPlugins\" 285 | 286 | 287 | 288 | 289 | 290 | -------------------------------------------------------------------------------- /Builds/VisualStudio2017/reaper_csurf.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | {2611354E-BF02-41DF-A603-57CD6E54EAF7} 43 | 10.0.15063.0 44 | 45 | 46 | 47 | DynamicLibrary 48 | v141 49 | false 50 | MultiByte 51 | 52 | 53 | DynamicLibrary 54 | v141 55 | false 56 | MultiByte 57 | 58 | 59 | DynamicLibrary 60 | v141 61 | false 62 | MultiByte 63 | 64 | 65 | DynamicLibrary 66 | v141 67 | false 68 | MultiByte 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | .\Release\ 92 | .\Release\ 93 | false 94 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(REAPER_EXTENSION_SDK) 95 | 96 | 97 | false 98 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(REAPER_EXTENSION_SDK) 99 | 100 | 101 | .\Debug\ 102 | .\Debug\ 103 | true 104 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(REAPER_EXTENSION_SDK) 105 | 106 | 107 | true 108 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(REAPER_EXTENSION_SDK) 109 | 110 | 111 | 112 | MultiThreadedDLL 113 | Default 114 | true 115 | true 116 | MaxSpeed 117 | true 118 | Level3 119 | OldStyle 120 | WIN32;NDEBUG;_WINDOWS;_USRDLL;REAPER_CSURF_EXPORTS;%(PreprocessorDefinitions) 121 | .\Release\ 122 | .\Release\reaper_csurf.pch 123 | .\Release\ 124 | .\Release\ 125 | 126 | 127 | true 128 | NDEBUG;%(PreprocessorDefinitions) 129 | .\Release\reaper_csurf.tlb 130 | true 131 | Win32 132 | 133 | 134 | 0x0409 135 | NDEBUG;%(PreprocessorDefinitions) 136 | 137 | 138 | true 139 | .\Release\reaper_csurf.bsc 140 | 141 | 142 | true 143 | true 144 | Console 145 | $(OutDir)\reaper_csurf_x86.dll 146 | .\Release\reaper_csurf.lib 147 | odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies) 148 | 149 | 150 | 151 | 152 | copy "Release\reaper_csurf_x86.dll" "%APPDATA%\REAPER\UserPlugins\" 153 | 154 | 155 | 156 | 157 | MultiThreadedDLL 158 | Default 159 | true 160 | true 161 | MaxSpeed 162 | true 163 | Level3 164 | OldStyle 165 | WIN32;NDEBUG;_WINDOWS;_USRDLL;REAPER_CSURF_EXPORTS;%(PreprocessorDefinitions) 166 | .\x64\Release\ 167 | .\x64\Release\reaper_csurf.pch 168 | .\x64\Release\ 169 | .\x64\Release\ 170 | 171 | 172 | true 173 | NDEBUG;%(PreprocessorDefinitions) 174 | .\Release\reaper_csurf.tlb 175 | true 176 | 177 | 178 | 0x0409 179 | NDEBUG;%(PreprocessorDefinitions) 180 | 181 | 182 | true 183 | .\x64\Release\reaper_csurf.bsc 184 | 185 | 186 | true 187 | true 188 | Console 189 | $(OutDir)\reaper_csurf_x64.dll 190 | .\x64\Release\reaper_csurf.lib 191 | odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies) 192 | 193 | 194 | 195 | 196 | copy "x64\Release\reaper_csurf_x64.dll" "%APPDATA%\REAPER\UserPlugins\" 197 | 198 | 199 | 200 | 201 | MultiThreadedDebug 202 | Default 203 | true 204 | Disabled 205 | true 206 | Level3 207 | true 208 | EditAndContinue 209 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;REAPER_CSURF_EXPORTS;%(PreprocessorDefinitions) 210 | .\Debug\ 211 | .\Debug\reaper_csurf.pch 212 | .\Debug\ 213 | .\Debug\ 214 | EnableFastChecks 215 | 216 | 217 | true 218 | _DEBUG;%(PreprocessorDefinitions) 219 | .\Debug\reaper_csurf.tlb 220 | true 221 | Win32 222 | 223 | 224 | 0x0409 225 | _DEBUG;%(PreprocessorDefinitions) 226 | 227 | 228 | true 229 | .\Debug\reaper_csurf.bsc 230 | 231 | 232 | true 233 | true 234 | true 235 | Console 236 | $(OutDir)\reaper_csurf_x86.dll 237 | .\Debug\reaper_csurf.lib 238 | odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies) 239 | 240 | 241 | copy "Debug\reaper_csurf_x86.dll" "%APPDATA%\REAPER\UserPlugins\" 242 | 243 | 244 | 245 | 246 | MultiThreadedDebug 247 | Default 248 | true 249 | Disabled 250 | true 251 | Level2 252 | ProgramDatabase 253 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_USRDLL;REAPER_CSURF_EXPORTS;%(PreprocessorDefinitions) 254 | .\x64\Debug\ 255 | .\x64\Debug\reaper_csurf.pch 256 | .\x64\Debug\ 257 | .\x64\Debug\ 258 | EnableFastChecks 259 | 260 | 261 | true 262 | _DEBUG;%(PreprocessorDefinitions) 263 | .\Debug\reaper_csurf.tlb 264 | true 265 | 266 | 267 | 0x0409 268 | _DEBUG;%(PreprocessorDefinitions) 269 | 270 | 271 | true 272 | .\x64\Debug\reaper_csurf.bsc 273 | 274 | 275 | true 276 | true 277 | true 278 | Console 279 | $(OutDir)\reaper_csurf_x64.dll 280 | .\x64\Debug\reaper_csurf_x64.lib 281 | odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies) 282 | 283 | 284 | copy "x64\Debug\reaper_csurf_x64.dll" "%APPDATA%\REAPER\UserPlugins\" 285 | 286 | 287 | 288 | 289 | 290 | -------------------------------------------------------------------------------- /Source/jmde/csurf/csurf_babyhui.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** reaper_csurf 3 | ** "hui"-ish support 4 | ** Copyright (C) 2006-2008 Cockos Incorporated 5 | ** License: LGPL. 6 | */ 7 | 8 | 9 | #include "csurf.h" 10 | 11 | 12 | static bool g_csurf_mcpmode=false; // we may wish to allow an action to set this 13 | 14 | 15 | 16 | static double charToVol(unsigned char val) 17 | { 18 | double pos=((double)val*1000.0)/127.0; 19 | pos=SLIDER2DB(pos); 20 | return DB2VAL(pos); 21 | 22 | } 23 | 24 | static double int14ToVol(unsigned char msb, unsigned char lsb) 25 | { 26 | int val=lsb | (msb<<7); 27 | double pos=((double)val*1000.0)/16383.0; 28 | pos=SLIDER2DB(pos); 29 | return DB2VAL(pos); 30 | } 31 | static double int14ToPan(unsigned char msb, unsigned char lsb) 32 | { 33 | int val=lsb | (msb<<7); 34 | return 1.0 - (val/(16383.0*0.5)); 35 | } 36 | 37 | static int volToInt14(double vol) 38 | { 39 | double d=(DB2SLIDER(VAL2DB(vol))*16383.0/1000.0); 40 | if (d<0.0)d=0.0; 41 | else if (d>16383.0)d=16383.0; 42 | 43 | return (int)(d+0.5); 44 | } 45 | static int panToInt14(double pan) 46 | { 47 | double d=((1.0-pan)*16383.0*0.5); 48 | if (d<0.0)d=0.0; 49 | else if (d>16383.0)d=16383.0; 50 | 51 | return (int)(d+0.5); 52 | } 53 | static unsigned char volToChar(double vol) 54 | { 55 | double d=(DB2SLIDER(VAL2DB(vol))*127.0/1000.0); 56 | if (d<0.0)d=0.0; 57 | else if (d>127.0)d=127.0; 58 | 59 | return (unsigned char)(d+0.5); 60 | } 61 | 62 | static double charToPan(unsigned char val) 63 | { 64 | double pos=((double)val*1000.0+0.5)/127.0; 65 | 66 | pos=(pos-500.0)/500.0; 67 | if (fabs(pos) < 0.08) pos=0.0; 68 | 69 | return pos; 70 | } 71 | 72 | static unsigned char panToChar(double pan) 73 | { 74 | pan = (pan+1.0)*63.5; 75 | 76 | if (pan<0.0)pan=0.0; 77 | else if (pan>127.0)pan=127.0; 78 | 79 | return (unsigned char)(pan+0.5); 80 | } 81 | 82 | 83 | 84 | 85 | 86 | 87 | class CSurf_BabyHUI : public IReaperControlSurface 88 | { 89 | int m_midi_in_dev,m_midi_out_dev; 90 | int m_offset, m_size; 91 | midi_Output *m_midiout; 92 | midi_Input *m_midiin; 93 | 94 | WDL_String descspace; 95 | char configtmp[1024]; 96 | 97 | int m_babyhui_wt; 98 | unsigned char m_babyhui_track_msb[16][8]; 99 | int m_bank_offset; 100 | char m_fader_touchstate[256]; 101 | int m_button_states; // 1=rew, 2=ffwd 102 | unsigned int m_pan_lasttouch[256]; 103 | 104 | int m_vol_lastpos[256]; 105 | int m_pan_lastpos[256]; 106 | 107 | void OnMIDIEvent(MIDI_event_t *evt) 108 | { 109 | if ((evt->midi_message[0]&0xf0) == 0xB0) 110 | { 111 | if (evt->midi_message[1] == 0x0f) // select track 112 | { 113 | m_babyhui_wt=evt->midi_message[2]; 114 | } 115 | else if (evt->midi_message[1] == 0x2f) 116 | { 117 | if (m_babyhui_wt>=0) 118 | { 119 | int allow_passthru=0; 120 | if (m_babyhui_wt == 0xa && evt->midi_message[2] >= 0x40 && evt->midi_message[2] <= 0x43) 121 | { 122 | if (evt->midi_message[2] > 0x41) // increase by X 123 | { 124 | m_bank_offset+=(evt->midi_message[2]&1) ? max((m_size&~7),8) : 1; 125 | int msize=CSurf_NumTracks(g_csurf_mcpmode); 126 | 127 | if (m_bank_offset >= msize) m_bank_offset=msize-1; 128 | } 129 | else 130 | { 131 | m_bank_offset-=(evt->midi_message[2]&1) ? max((m_size&~7),8) : 1; 132 | if (m_bank_offset<0)m_bank_offset=0; 133 | } 134 | // update all of the sliders 135 | TrackList_UpdateAllExternalSurfaces(); 136 | } 137 | else if (evt->midi_message[2] == 0x40) // touch 138 | { 139 | if (m_babyhui_wt < 8) 140 | { 141 | int trackid=m_babyhui_wt; 142 | if ((evt->midi_message[0]&15)<(m_size/8)) 143 | trackid+=(evt->midi_message[0]&15)*8; 144 | m_fader_touchstate[trackid]=1; 145 | } 146 | else allow_passthru=1; 147 | } 148 | else if (evt->midi_message[2] == 0x0) // un touch 149 | { 150 | if (m_babyhui_wt < 8) 151 | { 152 | int trackid=m_babyhui_wt; 153 | if ((evt->midi_message[0]&15)<(m_size/8)) trackid+=(evt->midi_message[0]&15)*8; 154 | m_fader_touchstate[trackid]=0; 155 | } 156 | else allow_passthru=1; 157 | } 158 | else if (evt->midi_message[2] == 0x41) 159 | { 160 | if (m_babyhui_wt == 0xe) 161 | { 162 | m_button_states|=1; 163 | if (m_midiout) 164 | { 165 | m_midiout->Send(0xb0,0x0c,0xe,-1); 166 | m_midiout->Send(0xb0,0x2c,evt->midi_message[2],-1); 167 | } 168 | } 169 | else if (m_babyhui_wt<8) 170 | { 171 | int trackid=m_babyhui_wt; 172 | if ((evt->midi_message[0]&15)<(m_size/8)) trackid+=(evt->midi_message[0]&15)*8; 173 | 174 | MediaTrack *tr=CSurf_TrackFromID(m_offset+m_bank_offset+trackid,g_csurf_mcpmode); 175 | 176 | if (tr) CSurf_OnSelectedChange(tr,-1); 177 | } 178 | else allow_passthru=1; 179 | } 180 | else if (evt->midi_message[2] == 0x42) // mute click (0x02 is when you let go) 181 | { 182 | if (m_babyhui_wt == 0xe) 183 | { 184 | m_button_states|=2; 185 | if (m_midiout) 186 | { 187 | m_midiout->Send(0xb0,0x0c,0xe,-1); 188 | m_midiout->Send(0xb0,0x2c,evt->midi_message[2],-1); 189 | } 190 | } 191 | else if (m_babyhui_wt < 8) 192 | { 193 | int trackid=m_babyhui_wt; 194 | if ((evt->midi_message[0]&15)<(m_size/8)) trackid+=(evt->midi_message[0]&15)*8; 195 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset+m_offset+trackid,g_csurf_mcpmode); 196 | if (tr) CSurf_SetSurfaceMute(tr,CSurf_OnMuteChange(tr,-1),NULL); 197 | } 198 | else allow_passthru=1; 199 | } 200 | else if (evt->midi_message[2] == 0x43) // solo click (0x03 is when you let go) 201 | { 202 | if (m_babyhui_wt == 0xe) 203 | { 204 | CSurf_OnStop(); 205 | } 206 | else if (m_babyhui_wt < 8) 207 | { 208 | int trackid=m_babyhui_wt; 209 | if ((evt->midi_message[0]&15)<(m_size/8)) trackid+=(evt->midi_message[0]&15)*8; 210 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset+m_offset+trackid,g_csurf_mcpmode); 211 | if (tr) CSurf_SetSurfaceSolo(tr,CSurf_OnSoloChange(tr,-1),NULL); 212 | } 213 | else allow_passthru=1; 214 | } 215 | else if (evt->midi_message[2] == 0x44) 216 | { 217 | if (m_babyhui_wt == 0xe) 218 | { 219 | CSurf_OnPlay(); 220 | } 221 | else if (m_babyhui_wt<8) 222 | { 223 | int trackid=m_babyhui_wt; 224 | if ((evt->midi_message[0]&15)<(m_size/8)) trackid+=(evt->midi_message[0]&15)*8; 225 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset+m_offset+trackid,g_csurf_mcpmode); 226 | if (tr) CSurf_SetSurfacePan(tr,CSurf_OnPanChange(tr,0.0,false),NULL); 227 | } 228 | else allow_passthru=1; 229 | } 230 | else if (evt->midi_message[2] == 0x45) // rec 231 | { 232 | if (m_babyhui_wt == 0xe) 233 | { 234 | CSurf_OnRecord(); 235 | } 236 | else allow_passthru=1; 237 | } 238 | else if (evt->midi_message[2] == 0x47) 239 | { 240 | if (m_babyhui_wt<8) 241 | { 242 | int trackid=m_babyhui_wt; 243 | if ((evt->midi_message[0]&15)<(m_size/8)) trackid+=(evt->midi_message[0]&15)*8; 244 | 245 | MediaTrack *tr=CSurf_TrackFromID(trackid+m_bank_offset+m_offset,g_csurf_mcpmode); 246 | if (tr) CSurf_OnRecArmChange(tr,-1); 247 | // if ((evt->midi_message[0]&15)<(m_size/8)) trackid+=(evt->midi_message[0]&15)*8; 248 | // CSurf_SetSurfacePan(m_bank_offset+m_offset+trackid,CSurf_OnPanChange(m_bank_offset+m_offset+trackid,0.0)); 249 | } 250 | else allow_passthru=1; 251 | } 252 | else if (evt->midi_message[2] == 0x01) 253 | { 254 | if (m_babyhui_wt == 0xe) 255 | { 256 | m_button_states&=~1; 257 | if (m_midiout) 258 | { 259 | m_midiout->Send(0xb0,0x0c,0xe,-1); 260 | m_midiout->Send(0xb0,0x2c,evt->midi_message[2],-1); 261 | } 262 | } 263 | else allow_passthru=1; 264 | } 265 | else if (evt->midi_message[2] == 0x02) 266 | { 267 | if (m_babyhui_wt == 0xe) 268 | { 269 | m_button_states&=~2; 270 | if (m_midiout) 271 | { 272 | m_midiout->Send(0xb0,0x0c,0xe,-1); 273 | m_midiout->Send(0xb0,0x2c,evt->midi_message[2],-1); 274 | } 275 | } 276 | else allow_passthru=1; 277 | } 278 | else allow_passthru=1; 279 | 280 | if (evt->midi_message[2] >= 0x40 && allow_passthru) 281 | { 282 | MIDI_event_t evt2={0,3,{evt->midi_message[0]^0x0f,((evt->midi_message[2]<<4)&0xf0)|m_babyhui_wt,0x40}}; 283 | kbd_OnMidiEvent(&evt2,-1); 284 | } 285 | 286 | } 287 | } 288 | else if (evt->midi_message[1] >= 0x20 && evt->midi_message[1] < 0x28) // lsb 289 | { 290 | int trackid=evt->midi_message[1]-0x20; 291 | if ((evt->midi_message[0]&15)<(m_size/8)) trackid+=(evt->midi_message[0]&15)*8; 292 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset+m_offset+trackid,g_csurf_mcpmode); 293 | if (tr) CSurf_SetSurfaceVolume(tr,CSurf_OnVolumeChange(tr,int14ToVol(m_babyhui_track_msb[evt->midi_message[0]&15][trackid],evt->midi_message[2]),false),this); 294 | } 295 | else if (evt->midi_message[1] >= 0x40 && evt->midi_message[1] < 0x48) // lsb 296 | { 297 | int trackid=evt->midi_message[1]-0x40; 298 | if ((evt->midi_message[0]&15)<(m_size/8)) trackid+=(evt->midi_message[0]&15)*8; 299 | double adj=(evt->midi_message[2]&0x3f)/-63.0; 300 | if (evt->midi_message[2]&0x40) adj=-adj; 301 | 302 | MediaTrack *tr=CSurf_TrackFromID(trackid+m_bank_offset+m_offset,g_csurf_mcpmode); 303 | if (tr) CSurf_SetSurfacePan(tr,CSurf_OnPanChange(tr,adj,true),NULL); 304 | 305 | m_pan_lasttouch[trackid&0xff]=timeGetTime(); 306 | } 307 | else if (evt->midi_message[1] >= 0x0 && evt->midi_message[1] < 0x8) // msb 308 | { 309 | m_babyhui_track_msb[evt->midi_message[0]&15][evt->midi_message[1]-0x0]=evt->midi_message[2]; 310 | } 311 | 312 | } 313 | } 314 | 315 | public: 316 | CSurf_BabyHUI(int offset, int size, int indev, int outdev, int *errStats) 317 | { 318 | m_offset=offset; 319 | m_size=size; 320 | m_midi_in_dev=indev; 321 | m_midi_out_dev=outdev; 322 | 323 | m_button_states=0; 324 | m_bank_offset=0; 325 | m_babyhui_wt=-1; 326 | memset(m_babyhui_track_msb,0,sizeof(m_babyhui_track_msb)); 327 | memset(m_fader_touchstate,0,sizeof(m_fader_touchstate)); 328 | memset(m_pan_lasttouch,0,sizeof(m_pan_lasttouch)); 329 | memset(m_vol_lastpos,0xff,sizeof(m_vol_lastpos)); 330 | memset(m_pan_lastpos,0xff,sizeof(m_pan_lastpos)); 331 | 332 | //create midi hardware access 333 | m_midiin = m_midi_in_dev >= 0 ? CreateMIDIInput(m_midi_in_dev) : NULL; 334 | m_midiout = m_midi_out_dev >= 0 ? CreateThreadedMIDIOutput(CreateMIDIOutput(m_midi_out_dev,false,NULL)) : NULL; 335 | 336 | if (errStats) 337 | { 338 | if (m_midi_in_dev >=0 && !m_midiin) *errStats|=1; 339 | if (m_midi_out_dev >=0 && !m_midiout) *errStats|=2; 340 | } 341 | 342 | if (m_midiin) 343 | m_midiin->start(); 344 | 345 | } 346 | ~CSurf_BabyHUI() 347 | { 348 | CloseNoReset(); 349 | } 350 | 351 | 352 | const char *GetTypeString() { return "HUI"; } 353 | const char *GetDescString() 354 | { 355 | descspace.Set("HUI(partial)"); 356 | char tmp[512]; 357 | sprintf(tmp," (dev %d,%d)",m_midi_in_dev,m_midi_out_dev); 358 | descspace.Append(tmp); 359 | return descspace.Get(); 360 | } 361 | const char *GetConfigString() // string of configuration data 362 | { 363 | sprintf(configtmp,"%d %d %d %d",m_offset,m_size,m_midi_in_dev,m_midi_out_dev); 364 | return configtmp; 365 | } 366 | 367 | void CloseNoReset() 368 | { 369 | int i; 370 | for (i = 0; i < 256; ++i) { 371 | SetTrackTitleImpl(i, ""); 372 | } 373 | 374 | delete m_midiout; 375 | delete m_midiin; 376 | m_midiout=0; 377 | m_midiin=0; 378 | } 379 | 380 | void Run() 381 | { 382 | if (m_midiin) 383 | { 384 | m_midiin->SwapBufs(timeGetTime()); 385 | int l=0; 386 | MIDI_eventlist *list=m_midiin->GetReadBuf(); 387 | MIDI_event_t *evts; 388 | while ((evts=list->EnumItems(&l))) OnMIDIEvent(evts); 389 | } 390 | } 391 | 392 | void SetTrackListChange() 393 | { 394 | int trackid; 395 | for (trackid = 0; trackid < 256; ++trackid) { 396 | MediaTrack* tr = CSurf_TrackFromID(m_offset+m_bank_offset+trackid,g_csurf_mcpmode); 397 | if (!tr) SetTrackTitleImpl(trackid, ""); 398 | } 399 | } 400 | 401 | 402 | #define FIXID(id) int id=CSurf_TrackToID(trackid,g_csurf_mcpmode); int oid=id; id -= m_offset+m_bank_offset; 403 | 404 | void SetSurfaceVolume(MediaTrack *trackid, double volume) 405 | { 406 | FIXID(id) 407 | if (m_midiout && id >= 0 && id < 256 && id < m_size) 408 | { 409 | int volint=volToInt14(volume); 410 | 411 | if (m_vol_lastpos[id]!=volint) 412 | { 413 | m_vol_lastpos[id]=volint; 414 | m_midiout->Send(0xb0+(id/8),id&7,(volint>>7)&0x7f,-1); 415 | m_midiout->Send(0xb0+(id/8),0x20+(id&7),volint&0x7f,-1); 416 | } 417 | } 418 | } 419 | void SetSurfacePan(MediaTrack *trackid, double pan) 420 | { 421 | FIXID(id) 422 | if (m_midiout && id >= 0 && id < 256 && id < m_size) 423 | { 424 | unsigned char panch=panToChar(pan); 425 | if (m_pan_lastpos[id] != panch) 426 | { 427 | m_pan_lastpos[id]=panch; 428 | m_midiout->Send(0xb0+(id/8),0x10+(id&7),1+((panch*11)>>7),-1); 429 | } 430 | } 431 | } 432 | void SetSurfaceMute(MediaTrack *trackid, bool mute) 433 | { 434 | FIXID(id) 435 | if (m_midiout && id>=0 && id < 256 && id < m_size) 436 | { 437 | m_midiout->Send(0xB0+(id/8),0x0c,id&7,-1); 438 | m_midiout->Send(0xB0+(id/8),0x2c,mute?0x42:0x02,-1); 439 | } 440 | } 441 | void SetSurfaceSelected(MediaTrack *trackid, bool selected) 442 | { 443 | FIXID(id) 444 | if (m_midiout && id >= 0 && id < 256 && id < m_size) 445 | { 446 | m_midiout->Send(0xb0+(id/8),0x0c,id&7,-1); 447 | m_midiout->Send(0xb0+(id/8),0x2c,selected?0x41:0x01,-1); 448 | } 449 | } 450 | void SetSurfaceSolo(MediaTrack *trackid, bool solo) 451 | { 452 | FIXID(id) 453 | if (m_midiout && id>=0 && id < 256 && id < m_size) 454 | { 455 | if (!oid) solo=!!(GetMasterMuteSoloFlags()&2); 456 | m_midiout->Send(0xb0+(id/8),0x0c,id&7,-1); 457 | m_midiout->Send(0xb0+(id/8),0x2c,solo?0x43:0x03,-1); 458 | } 459 | } 460 | void SetSurfaceRecArm(MediaTrack *trackid, bool recarm) 461 | { 462 | FIXID(id) 463 | if (m_midiout && id>=0 && id < 256 && id < m_size) 464 | { 465 | m_midiout->Send(0xb0+(id/8),0x0c,id&7,-1); 466 | m_midiout->Send(0xb0+(id/8),0x2c,recarm?0x47:0x07,-1); 467 | } 468 | } 469 | void SetPlayState(bool play, bool pause, bool rec) 470 | { 471 | if (m_midiout) 472 | { 473 | m_midiout->Send(0xb0,0x0c,0xe,-1); 474 | m_midiout->Send(0xb0,0x2c,play?0x44:0x04,-1); 475 | m_midiout->Send(0xb0,0x0c,0xe,-1); 476 | m_midiout->Send(0xb0,0x2c,pause?0x43:0x03,-1); 477 | m_midiout->Send(0xb0,0x0c,0xe,-1); 478 | m_midiout->Send(0xb0,0x2c,rec?0x45:0x05,-1); 479 | } 480 | } 481 | void SetRepeatState(bool rep) 482 | { 483 | // not used 484 | } 485 | 486 | void SetTrackTitleImpl(int trackid, const char* title) 487 | { 488 | if (m_midiout && trackid >= 0 && trackid < 256) { 489 | #define SYSEX_TRACKTITLE_LEN 13 490 | unsigned char sysex[SYSEX_TRACKTITLE_LEN] = { 0xF0, 0x00, 0x00, 0x66, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF7 }; 491 | sysex[7] = trackid; 492 | int i, len = (title?strlen(title):0); 493 | for (i = 0; i < min(len, 4) && title[i]; ++i) { 494 | sysex[8+i] = title[i]; 495 | } 496 | 497 | char buf[sizeof(MIDI_event_t)+SYSEX_TRACKTITLE_LEN]; 498 | MIDI_event_t* msg = (MIDI_event_t*) buf; 499 | msg->frame_offset = -1; 500 | msg->size = SYSEX_TRACKTITLE_LEN; 501 | memcpy(msg->midi_message, sysex, SYSEX_TRACKTITLE_LEN); 502 | m_midiout->SendMsg(msg, -1); 503 | } 504 | } 505 | 506 | void SetTrackTitle(MediaTrack *trackid, const char *title) 507 | { 508 | FIXID(id) 509 | SetTrackTitleImpl(id, title); 510 | } 511 | 512 | bool GetTouchState(MediaTrack *trackid, int isPan) 513 | { 514 | FIXID(id) 515 | if (isPan==1) 516 | { 517 | if (id >= 0 && id < 256 && id < m_size) 518 | { 519 | DWORD now=timeGetTime(); 520 | if ((now= m_pan_lasttouch[id]-1000)) // fake touch, go for 3s after last movement 521 | return true; 522 | } 523 | return false; 524 | } 525 | if (id >= 0 && id < 256 && id < m_size) 526 | return !!m_fader_touchstate[id]; 527 | return false; 528 | } 529 | 530 | void SetAutoMode(int mode) { } 531 | 532 | void ResetCachedVolPanStates() 533 | { 534 | memset(m_vol_lastpos,0xff,sizeof(m_vol_lastpos)); 535 | memset(m_pan_lastpos,0xff,sizeof(m_pan_lastpos)); 536 | } 537 | void OnTrackSelection(MediaTrack *trackid) 538 | { 539 | } 540 | 541 | bool IsKeyDown(int key) 542 | { 543 | return false; 544 | } 545 | 546 | 547 | }; 548 | 549 | 550 | static void parseParms(const char *str, int parms[4]) 551 | { 552 | parms[0]=0; 553 | parms[1]=9; 554 | parms[2]=parms[3]=-1; 555 | 556 | const char *p=str; 557 | if (p) 558 | { 559 | int x=0; 560 | while (x<4) 561 | { 562 | while (*p == ' ') p++; 563 | if ((*p < '0' || *p > '9') && *p != '-') break; 564 | parms[x++]=atoi(p); 565 | while (*p && *p != ' ') p++; 566 | } 567 | } 568 | } 569 | 570 | static IReaperControlSurface *createFunc(const char *type_string, const char *configString, int *errStats) 571 | { 572 | int parms[4]; 573 | parseParms(configString,parms); 574 | 575 | return new CSurf_BabyHUI(parms[0],parms[1],parms[2],parms[3],errStats); 576 | } 577 | 578 | 579 | static WDL_DLGRET dlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 580 | { 581 | switch (uMsg) 582 | { 583 | case WM_INITDIALOG: 584 | { 585 | int parms[4]; 586 | parseParms((const char *)lParam,parms); 587 | 588 | int n=GetNumMIDIInputs(); 589 | int x=SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_ADDSTRING,0,(LPARAM)"None"); 590 | SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_SETITEMDATA,x,-1); 591 | x=SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_ADDSTRING,0,(LPARAM)"None"); 592 | SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_SETITEMDATA,x,-1); 593 | for (x = 0; x < n; x ++) 594 | { 595 | char buf[512]; 596 | if (GetMIDIInputName(x,buf,sizeof(buf))) 597 | { 598 | int a=SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_ADDSTRING,0,(LPARAM)buf); 599 | SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_SETITEMDATA,a,x); 600 | if (x == parms[2]) SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_SETCURSEL,a,0); 601 | } 602 | } 603 | n=GetNumMIDIOutputs(); 604 | for (x = 0; x < n; x ++) 605 | { 606 | char buf[512]; 607 | if (GetMIDIOutputName(x,buf,sizeof(buf))) 608 | { 609 | int a=SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_ADDSTRING,0,(LPARAM)buf); 610 | SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_SETITEMDATA,a,x); 611 | if (x == parms[3]) SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_SETCURSEL,a,0); 612 | } 613 | } 614 | SetDlgItemInt(hwndDlg,IDC_EDIT1,parms[0],TRUE); 615 | SetDlgItemInt(hwndDlg,IDC_EDIT2,parms[1],FALSE); 616 | } 617 | break; 618 | case WM_USER+1024: 619 | if (wParam > 1 && lParam) 620 | { 621 | char tmp[512]; 622 | 623 | int indev=-1, outdev=-1, offs=0, size=9; 624 | int r=SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_GETCURSEL,0,0); 625 | if (r != CB_ERR) indev = SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_GETITEMDATA,r,0); 626 | r=SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_GETCURSEL,0,0); 627 | if (r != CB_ERR) outdev = SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_GETITEMDATA,r,0); 628 | 629 | BOOL t; 630 | r=GetDlgItemInt(hwndDlg,IDC_EDIT1,&t,TRUE); 631 | if (t) offs=r; 632 | r=GetDlgItemInt(hwndDlg,IDC_EDIT2,&t,FALSE); 633 | if (t) 634 | { 635 | if (r<1)r=1; 636 | else if(r>256)r=256; 637 | size=r; 638 | } 639 | 640 | sprintf(tmp,"%d %d %d %d",offs,size,indev,outdev); 641 | lstrcpyn((char *)lParam, tmp,wParam); 642 | 643 | } 644 | break; 645 | } 646 | return 0; 647 | } 648 | 649 | static HWND configFunc(const char *type_string, HWND parent, const char *initConfigString) 650 | { 651 | return CreateDialogParam(g_hInst,MAKEINTRESOURCE(IDD_SURFACEEDIT_MCU),parent,dlgProc,(LPARAM)initConfigString); 652 | } 653 | 654 | 655 | reaper_csurf_reg_t csurf_hui_reg = 656 | { 657 | "HUI", 658 | "HUI (partial)", 659 | createFunc, 660 | configFunc, 661 | }; -------------------------------------------------------------------------------- /Source/jmde/csurf/csurf_faderport.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** reaper_csurf 3 | ** FaderPort support 4 | ** Copyright (C) 2007-2008 Cockos Incorporated 5 | ** License: LGPL. 6 | */ 7 | 8 | 9 | #include "csurf.h" 10 | 11 | /* 12 | ** Todo: automation status, automation mode setting using "auto" button, more 13 | */ 14 | 15 | 16 | static bool g_csurf_mcpmode=false; // we may wish to allow an action to set this 17 | 18 | 19 | 20 | 21 | static double int14ToVol(unsigned char msb, unsigned char lsb) 22 | { 23 | int val=lsb | (msb<<7); 24 | double pos=((double)val*1000.0)/16383.0; 25 | pos=SLIDER2DB(pos); 26 | return DB2VAL(pos); 27 | } 28 | static double int14ToPan(unsigned char msb, unsigned char lsb) 29 | { 30 | int val=lsb | (msb<<7); 31 | return 1.0 - (val/(16383.0*0.5)); 32 | } 33 | 34 | static int volToInt14(double vol) 35 | { 36 | double d=(DB2SLIDER(VAL2DB(vol))*16383.0/1000.0); 37 | if (d<0.0)d=0.0; 38 | else if (d>16383.0)d=16383.0; 39 | 40 | return (int)(d+0.5); 41 | } 42 | static int panToInt14(double pan) 43 | { 44 | double d=((1.0-pan)*16383.0*0.5); 45 | if (d<0.0)d=0.0; 46 | else if (d>16383.0)d=16383.0; 47 | 48 | return (int)(d+0.5); 49 | } 50 | 51 | 52 | 53 | class CSurf_FaderPort : public IReaperControlSurface 54 | { 55 | int m_midi_in_dev,m_midi_out_dev; 56 | midi_Output *m_midiout; 57 | midi_Input *m_midiin; 58 | 59 | int m_vol_lastpos; 60 | int m_flipmode; 61 | int m_faderport_lasthw,m_faderport_buttonstates; 62 | 63 | char m_fader_touchstate; 64 | int m_bank_offset; 65 | 66 | DWORD m_frameupd_lastrun; 67 | int m_button_states; 68 | DWORD m_buttonstate_lastrun; 69 | DWORD m_pan_lasttouch; 70 | 71 | WDL_String descspace; 72 | char configtmp[1024]; 73 | 74 | void OnMIDIEvent(MIDI_event_t *evt) 75 | { 76 | if (evt->midi_message[0] == 0xb0) 77 | { 78 | if (evt->midi_message[1]==0) 79 | m_faderport_lasthw=evt->midi_message[2]; 80 | else if (evt->midi_message[1] == 0x20) 81 | { 82 | int tid=m_bank_offset; 83 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 84 | 85 | if (tr) 86 | { 87 | if (m_flipmode) 88 | { 89 | CSurf_SetSurfacePan(tr,CSurf_OnPanChange(tr,int14ToPan(m_faderport_lasthw,evt->midi_message[2]),false),NULL); 90 | } 91 | else 92 | CSurf_SetSurfaceVolume(tr,CSurf_OnVolumeChange(tr,int14ToVol(m_faderport_lasthw,evt->midi_message[2]),false),NULL); 93 | } 94 | } 95 | } 96 | else if (evt->midi_message[0] == 0xa0) 97 | { 98 | if (evt->midi_message[1]==0x7f) 99 | { 100 | m_fader_touchstate=!!evt->midi_message[2]; 101 | } 102 | else if (evt->midi_message[1] == 0x2) // shift 103 | { 104 | if (evt->midi_message[2]) 105 | m_faderport_buttonstates|=2; 106 | else 107 | m_faderport_buttonstates&=~2; 108 | 109 | if (m_midiout) m_midiout->Send(0xa0,5,evt->midi_message[2],-1); 110 | } 111 | else if (evt->midi_message[1] == 0x10) // rec arm key push 112 | { 113 | if (evt->midi_message[2]) 114 | { 115 | if (m_faderport_buttonstates&2) 116 | ClearAllRecArmed(); 117 | else 118 | { 119 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 120 | if (tr) SetSurfaceRecArm(tr,CSurf_OnRecArmChange(tr,-1)); 121 | } 122 | } 123 | } 124 | else if (evt->midi_message[1] == 0x17) // automation off 125 | { 126 | if (evt->midi_message[2]) 127 | { 128 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 129 | 130 | if (tr) 131 | { 132 | SetTrackAutomationMode(tr,0); 133 | CSurf_SetAutoMode(-1,NULL); 134 | } 135 | } 136 | } 137 | else if (evt->midi_message[1] == 0x8) // automation touch 138 | { 139 | if (evt->midi_message[2]) 140 | { 141 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 142 | 143 | if (tr) 144 | { 145 | SetTrackAutomationMode(tr,2); 146 | CSurf_SetAutoMode(-1,NULL); 147 | } 148 | } 149 | } 150 | else if (evt->midi_message[1] == 0x9) // automation write 151 | { 152 | if (evt->midi_message[2]) 153 | { 154 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 155 | 156 | if (tr) 157 | { 158 | SetTrackAutomationMode(tr,3); 159 | CSurf_SetAutoMode(-1,NULL); 160 | } 161 | } 162 | } 163 | else if (evt->midi_message[1] == 0xa) // automation read 164 | { 165 | if (evt->midi_message[2]) 166 | { 167 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 168 | 169 | if (tr) 170 | { 171 | SetTrackAutomationMode(tr,1); 172 | CSurf_SetAutoMode(-1,NULL); 173 | } 174 | } 175 | } 176 | else if (evt->midi_message[1] == 0xb || evt->midi_message[1] == 0xc || evt->midi_message[1] == 0xd) // automation read 177 | { 178 | if (evt->midi_message[2]) 179 | { 180 | int a=(evt->midi_message[1]-0xb)+8; 181 | if (m_faderport_buttonstates&2) a+=3; 182 | MIDI_event_t evt={0,3,{0xbf,a,0}}; 183 | kbd_OnMidiEvent(&evt,-1); 184 | } 185 | } 186 | else if (evt->midi_message[1] == 0x3) // rew 187 | { 188 | m_button_states&=~1; 189 | if (evt->midi_message[2]) 190 | { 191 | if ((m_faderport_buttonstates&2)) 192 | CSurf_GoStart(); 193 | else 194 | m_button_states|=1; 195 | } 196 | if (m_midiout) m_midiout->Send(0xa0,4,evt->midi_message[2],-1); 197 | } 198 | else if (evt->midi_message[1] == 0x4) // fwd 199 | { 200 | m_button_states&=~2; 201 | if (evt->midi_message[2]) 202 | { 203 | if ((m_faderport_buttonstates&2)) 204 | { 205 | CSurf_GoEnd(); 206 | } 207 | else m_button_states|=2; 208 | } 209 | if (m_midiout) m_midiout->Send(0xa0,3,evt->midi_message[2],-1); 210 | } 211 | else if (evt->midi_message[1] == 0x5) // stop 212 | { 213 | if (evt->midi_message[2]) 214 | { 215 | CSurf_OnStop(); 216 | } 217 | } 218 | else if (evt->midi_message[1] == 0x1) // punch 219 | { 220 | if (evt->midi_message[2]) 221 | { 222 | if ((m_faderport_buttonstates&2)) 223 | { 224 | SendMessage(g_hwnd,WM_COMMAND,ID_MARKER_PREV,0); 225 | } 226 | else 227 | SendMessage(g_hwnd,WM_COMMAND,ID_LOOP_SETSTART,0); 228 | } 229 | } 230 | else if (evt->midi_message[1] == 0x0) // user 231 | { 232 | if (evt->midi_message[2]) 233 | { 234 | if ((m_faderport_buttonstates&2)) 235 | { 236 | SendMessage(g_hwnd,WM_COMMAND,ID_MARKER_NEXT,0); 237 | } 238 | else 239 | SendMessage(g_hwnd,WM_COMMAND,ID_LOOP_SETEND,0); 240 | } 241 | } 242 | else if (evt->midi_message[1] == 0xf) // loop 243 | { 244 | if (evt->midi_message[2]) 245 | { 246 | if ((m_faderport_buttonstates&2)) 247 | { 248 | SendMessage(g_hwnd,WM_COMMAND,ID_INSERT_MARKER,0); 249 | } 250 | else 251 | SendMessage(g_hwnd,WM_COMMAND,IDC_REPEAT,0); 252 | } 253 | } 254 | else if (evt->midi_message[1] == 0x6) // play 255 | { 256 | if (evt->midi_message[2]) 257 | { 258 | CSurf_OnPlay(); 259 | } 260 | } 261 | else if (evt->midi_message[1] == 0x7) // rec 262 | { 263 | if (evt->midi_message[2]) 264 | { 265 | 266 | CSurf_OnRecord(); 267 | 268 | } 269 | } 270 | else if (evt->midi_message[1] == 0x0e) // undo/redo 271 | { 272 | if (evt->midi_message[2]) 273 | { 274 | 275 | SendMessage(g_hwnd,WM_COMMAND,(m_faderport_buttonstates&2)?IDC_EDIT_REDO:IDC_EDIT_UNDO,0); 276 | } 277 | } 278 | else if (evt->midi_message[1] == 0x16) // output (flip) 279 | { 280 | if (evt->midi_message[2]) 281 | { 282 | m_flipmode=!m_flipmode; 283 | if (m_midiout) m_midiout->Send(0xa0, 0x11,m_flipmode?1:0,-1); 284 | CSurf_ResetAllCachedVolPanStates(); 285 | TrackList_UpdateAllExternalSurfaces(); 286 | } 287 | } 288 | else if (evt->midi_message[1] == 0x11) // solo key push 289 | { 290 | if (evt->midi_message[2]) 291 | { 292 | if (m_faderport_buttonstates&2) 293 | SoloAllTracks(false); 294 | else 295 | { 296 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 297 | if (tr) SetSurfaceSolo(tr,CSurf_OnSoloChange(tr,-1)); 298 | } 299 | } 300 | } 301 | else if (evt->midi_message[1] == 0x12) // mute key push 302 | { 303 | if (evt->midi_message[2]) 304 | { 305 | if (m_faderport_buttonstates&2) 306 | MuteAllTracks(false); 307 | else 308 | { 309 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 310 | if (tr) SetSurfaceMute(tr,CSurf_OnMuteChange(tr,-1)); 311 | } 312 | } 313 | } 314 | else if (evt->midi_message[1] == 0x13) // prevchan 315 | { 316 | if (evt->midi_message[2]) 317 | { 318 | AdjustBankOffset((m_faderport_buttonstates&1)?-8:-1,true); 319 | TrackList_UpdateAllExternalSurfaces(); 320 | } 321 | if (m_midiout) m_midiout->Send(0xa0,0x14,evt->midi_message[2],-1); 322 | } 323 | else if (evt->midi_message[1] == 0x14) // bank 324 | { 325 | if (evt->midi_message[2]) 326 | m_faderport_buttonstates|=1; 327 | else 328 | m_faderport_buttonstates&=~1; 329 | 330 | if (m_midiout) m_midiout->Send(0xa0,0x13,evt->midi_message[2],-1); 331 | } 332 | else if (evt->midi_message[1] == 0x15) // nextchan 333 | { 334 | if (evt->midi_message[2]) 335 | { 336 | AdjustBankOffset((m_faderport_buttonstates&1)?8:1,true); 337 | TrackList_UpdateAllExternalSurfaces(); 338 | } 339 | if (m_midiout) m_midiout->Send(0xa0,0x12,evt->midi_message[2],-1); 340 | } 341 | else if (evt->midi_message[1] == 0x16) // output 342 | { 343 | } 344 | } 345 | else if (evt->midi_message[0] == 0xe0) 346 | { 347 | if (!evt->midi_message[1]) 348 | { 349 | m_pan_lasttouch=timeGetTime(); 350 | 351 | double adj=0.02; 352 | if (evt->midi_message[2]>0x3f) adj=-adj; 353 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 354 | 355 | if (tr) 356 | { 357 | if (m_flipmode) 358 | { 359 | CSurf_SetSurfaceVolume(tr,CSurf_OnVolumeChange(tr,adj*11.0,true),NULL); 360 | } 361 | else 362 | CSurf_SetSurfacePan(tr,CSurf_OnPanChange(tr,adj,true),NULL); 363 | } 364 | } 365 | } 366 | 367 | } 368 | 369 | void AdjustBankOffset(int amt, bool dosel) 370 | { 371 | if (!amt) return; 372 | 373 | if (amt<0) 374 | { 375 | if (m_bank_offset>0) 376 | { 377 | m_bank_offset += amt; 378 | if (m_bank_offset<0) m_bank_offset=0; 379 | 380 | if (dosel) 381 | { 382 | int x; 383 | MediaTrack *t=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 384 | for (x = 0; ; x ++) 385 | { 386 | int f=0; 387 | if (!GetTrackInfo(x-1,&f)) break; 388 | 389 | MediaTrack *tt=CSurf_TrackFromID(x,false); 390 | bool sel=tt == t; 391 | if (tt && !(f&2) == sel) 392 | { 393 | SetTrackSelected(tt,sel); 394 | } 395 | } 396 | } 397 | } 398 | } 399 | else 400 | { 401 | int msize=CSurf_NumTracks(g_csurf_mcpmode); 402 | 403 | if (m_bank_offsetmsize) m_bank_offset=msize; 407 | 408 | if (dosel) 409 | { 410 | int x; 411 | MediaTrack *t=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 412 | for (x = 0; ; x ++) 413 | { 414 | int f=0; 415 | if (!GetTrackInfo(x-1,&f)) break; 416 | 417 | MediaTrack *tt=CSurf_TrackFromID(x,false); 418 | bool sel=tt == t; 419 | if (tt && !(f&2) == sel) 420 | { 421 | SetTrackSelected(tt,sel); 422 | } 423 | } 424 | } 425 | } 426 | } 427 | 428 | } 429 | 430 | 431 | 432 | public: 433 | CSurf_FaderPort(int indev, int outdev, int *errStats) 434 | { 435 | m_midi_in_dev=indev; 436 | m_midi_out_dev=outdev; 437 | 438 | 439 | m_faderport_lasthw=0; 440 | m_faderport_buttonstates=0; 441 | m_flipmode=0; 442 | m_vol_lastpos=-1000; 443 | 444 | m_fader_touchstate=0; 445 | 446 | m_bank_offset=0; 447 | m_frameupd_lastrun=0; 448 | m_button_states=0; 449 | m_buttonstate_lastrun=0; 450 | m_pan_lasttouch=0; 451 | 452 | //create midi hardware access 453 | m_midiin = m_midi_in_dev >= 0 ? CreateMIDIInput(m_midi_in_dev) : NULL; 454 | m_midiout = m_midi_out_dev >= 0 ? CreateThreadedMIDIOutput(CreateMIDIOutput(m_midi_out_dev,false,NULL)) : NULL; 455 | 456 | if (errStats) 457 | { 458 | if (m_midi_in_dev >=0 && !m_midiin) *errStats|=1; 459 | if (m_midi_out_dev >=0 && !m_midiout) *errStats|=2; 460 | } 461 | 462 | if (m_midiin) 463 | m_midiin->start(); 464 | 465 | if (m_midiout) 466 | { 467 | m_midiout->Send(0xb0,0x00,0x06,-1); 468 | m_midiout->Send(0xb0,0x20,0x27,-1); 469 | 470 | int x; 471 | for (x = 0; x < 0x30; x ++) // lights out 472 | m_midiout->Send(0xa0,x,0x00,-1); 473 | 474 | //m_midiout->Send(0xa0,0xf,m_flipmode?1:0);// fucko 475 | 476 | m_midiout->Send(0x91,0x00,0x64,-1); // send these every so often? 477 | } 478 | 479 | } 480 | ~CSurf_FaderPort() 481 | { 482 | if (m_midiout) 483 | { 484 | int x; 485 | for (x = 0; x < 0x30; x ++) // lights out 486 | m_midiout->Send(0xa0,x,0x00,-1); 487 | Sleep(5); 488 | } 489 | 490 | delete m_midiout; 491 | delete m_midiin; 492 | } 493 | 494 | 495 | const char *GetTypeString() { return "FADERPORT"; } 496 | const char *GetDescString() 497 | { 498 | descspace.Set("PreSonus FaderPort"); 499 | char tmp[512]; 500 | sprintf(tmp," (dev %d,%d)",m_midi_in_dev,m_midi_out_dev); 501 | descspace.Append(tmp); 502 | return descspace.Get(); 503 | } 504 | const char *GetConfigString() // string of configuration data 505 | { 506 | sprintf(configtmp,"0 0 %d %d",m_midi_in_dev,m_midi_out_dev); 507 | return configtmp; 508 | } 509 | 510 | void CloseNoReset() 511 | { 512 | delete m_midiout; 513 | delete m_midiin; 514 | m_midiout=0; 515 | m_midiin=0; 516 | } 517 | 518 | void Run() 519 | { 520 | if (m_midiin) 521 | { 522 | m_midiin->SwapBufs(timeGetTime()); 523 | int l=0; 524 | MIDI_eventlist *list=m_midiin->GetReadBuf(); 525 | MIDI_event_t *evts; 526 | while ((evts=list->EnumItems(&l))) OnMIDIEvent(evts); 527 | 528 | if (m_button_states) 529 | { 530 | DWORD now=timeGetTime(); 531 | if (now >= m_buttonstate_lastrun + 100) 532 | { 533 | m_buttonstate_lastrun=now; 534 | 535 | if ((m_button_states&3) != 3) 536 | { 537 | if (m_button_states&1) 538 | { 539 | CSurf_OnRew(1); 540 | } 541 | else if (m_button_states&2) 542 | { 543 | CSurf_OnFwd(1); 544 | } 545 | } 546 | 547 | } 548 | } 549 | } 550 | } 551 | 552 | void SetTrackListChange() 553 | { 554 | SetAutoMode(0); 555 | } 556 | 557 | #define FIXID(id) int id=CSurf_TrackToID(trackid,g_csurf_mcpmode); int oid=id; id -= m_bank_offset; 558 | 559 | void SetSurfaceVolume(MediaTrack *trackid, double volume) 560 | { 561 | FIXID(id) 562 | if (m_midiout && !id && !m_flipmode) 563 | { 564 | int volint=volToInt14(volume); 565 | volint/=16; 566 | 567 | if (m_vol_lastpos!=volint) 568 | { 569 | m_vol_lastpos=volint; 570 | m_midiout->Send(0xb0,0x00,volint>>7,-1); 571 | m_midiout->Send(0xb0,0x20,volint&127,-1); 572 | 573 | } 574 | } 575 | } 576 | void SetSurfacePan(MediaTrack *trackid, double pan) 577 | { 578 | FIXID(id) 579 | if (m_midiout && !id && m_flipmode) 580 | { 581 | int volint=panToInt14(pan); 582 | volint/=16; 583 | 584 | if (m_vol_lastpos!=volint) 585 | { 586 | m_vol_lastpos=volint; 587 | m_midiout->Send(0xb0,0x00,volint>>7,-1); 588 | m_midiout->Send(0xb0,0x20,volint&127,-1); 589 | } 590 | } 591 | } 592 | void SetSurfaceMute(MediaTrack *trackid, bool mute) 593 | { 594 | FIXID(id) 595 | if (!id && m_midiout) 596 | m_midiout->Send(0xa0,0x15,mute?1:0,-1); 597 | } 598 | void SetSurfaceSelected(MediaTrack *trackid, bool selected) 599 | { 600 | } 601 | void SetSurfaceSolo(MediaTrack *trackid, bool solo) 602 | { 603 | FIXID(id) 604 | if (!id && m_midiout) 605 | m_midiout->Send(0xa0,0x16,solo?1:0,-1); 606 | } 607 | void SetSurfaceRecArm(MediaTrack *trackid, bool recarm) 608 | { 609 | FIXID(id) 610 | if (!id && m_midiout) 611 | m_midiout->Send(0xa0,0x17,recarm?1:0,-1); 612 | } 613 | void SetPlayState(bool play, bool pause, bool rec) 614 | { 615 | if (m_midiout) 616 | { 617 | m_midiout->Send(0xa0, 0,rec?1:0,-1); 618 | m_midiout->Send(0xa0, 1,play?1:0,-1); 619 | m_midiout->Send(0xa0, 2,(!play&&!pause)?1:0,-1); 620 | } 621 | } 622 | void SetRepeatState(bool rep) 623 | { 624 | if (m_midiout) m_midiout->Send(0xa0, 8,rep?1:0,-1); 625 | 626 | } 627 | 628 | void SetTrackTitle(MediaTrack *trackid, const char *title) { } 629 | 630 | bool GetTouchState(MediaTrack *trackid, int isPan) 631 | { 632 | FIXID(id) 633 | if (!id) 634 | { 635 | if (!m_flipmode != !isPan) 636 | { 637 | DWORD now=timeGetTime(); 638 | if (m_pan_lasttouch==1 || (now= m_pan_lasttouch-1000)) // fake touch, go for 3s after last movement 639 | { 640 | return true; 641 | } 642 | return false; 643 | } 644 | return !!m_fader_touchstate; 645 | } 646 | return false; 647 | } 648 | 649 | void SetAutoMode(int mode) 650 | { 651 | if (m_midiout) 652 | { 653 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 654 | if (tr) mode=GetTrackAutomationMode(tr); 655 | 656 | if (mode<0) return; 657 | 658 | m_midiout->Send(0xa0,0x10,0,-1);//mode==0); // dont set off light, it disables the fader?! 659 | m_midiout->Send(0xa0,0xf,mode==2||mode==4,-1); 660 | m_midiout->Send(0xa0,0xe,mode==3,-1); 661 | m_midiout->Send(0xa0,0xd,mode==1,-1); 662 | } 663 | } 664 | 665 | void ResetCachedVolPanStates() 666 | { 667 | m_vol_lastpos=-1000; 668 | } 669 | 670 | void OnTrackSelection(MediaTrack *trackid) 671 | { 672 | int newpos=CSurf_TrackToID(trackid,g_csurf_mcpmode); 673 | if (newpos>=0 && newpos != m_bank_offset) 674 | { 675 | AdjustBankOffset(newpos-m_bank_offset,false); 676 | TrackList_UpdateAllExternalSurfaces(); 677 | } 678 | } 679 | 680 | bool IsKeyDown(int key) 681 | { 682 | return false; 683 | } 684 | 685 | 686 | }; 687 | 688 | 689 | static void parseParms(const char *str, int parms[4]) 690 | { 691 | parms[0]=0; 692 | parms[1]=9; 693 | parms[2]=parms[3]=-1; 694 | 695 | const char *p=str; 696 | if (p) 697 | { 698 | int x=0; 699 | while (x<4) 700 | { 701 | while (*p == ' ') p++; 702 | if ((*p < '0' || *p > '9') && *p != '-') break; 703 | parms[x++]=atoi(p); 704 | while (*p && *p != ' ') p++; 705 | } 706 | } 707 | } 708 | 709 | static IReaperControlSurface *createFunc(const char *type_string, const char *configString, int *errStats) 710 | { 711 | int parms[4]; 712 | parseParms(configString,parms); 713 | 714 | return new CSurf_FaderPort(parms[2],parms[3],errStats); 715 | } 716 | 717 | 718 | static WDL_DLGRET dlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 719 | { 720 | switch (uMsg) 721 | { 722 | case WM_INITDIALOG: 723 | { 724 | int parms[4]; 725 | parseParms((const char *)lParam,parms); 726 | 727 | ShowWindow(GetDlgItem(hwndDlg,IDC_EDIT1),SW_HIDE); 728 | ShowWindow(GetDlgItem(hwndDlg,IDC_EDIT1_LBL),SW_HIDE); 729 | ShowWindow(GetDlgItem(hwndDlg,IDC_EDIT2),SW_HIDE); 730 | ShowWindow(GetDlgItem(hwndDlg,IDC_EDIT2_LBL),SW_HIDE); 731 | ShowWindow(GetDlgItem(hwndDlg,IDC_EDIT2_LBL2),SW_HIDE); 732 | 733 | int n=GetNumMIDIInputs(); 734 | int x=SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_ADDSTRING,0,(LPARAM)"None"); 735 | SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_SETITEMDATA,x,-1); 736 | x=SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_ADDSTRING,0,(LPARAM)"None"); 737 | SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_SETITEMDATA,x,-1); 738 | for (x = 0; x < n; x ++) 739 | { 740 | char buf[512]; 741 | if (GetMIDIInputName(x,buf,sizeof(buf))) 742 | { 743 | int a=SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_ADDSTRING,0,(LPARAM)buf); 744 | SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_SETITEMDATA,a,x); 745 | if (x == parms[2]) SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_SETCURSEL,a,0); 746 | } 747 | } 748 | n=GetNumMIDIOutputs(); 749 | for (x = 0; x < n; x ++) 750 | { 751 | char buf[512]; 752 | if (GetMIDIOutputName(x,buf,sizeof(buf))) 753 | { 754 | int a=SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_ADDSTRING,0,(LPARAM)buf); 755 | SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_SETITEMDATA,a,x); 756 | if (x == parms[3]) SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_SETCURSEL,a,0); 757 | } 758 | } 759 | } 760 | break; 761 | case WM_USER+1024: 762 | if (wParam > 1 && lParam) 763 | { 764 | char tmp[512]; 765 | 766 | int indev=-1, outdev=-1, offs=0, size=9; 767 | int r=SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_GETCURSEL,0,0); 768 | if (r != CB_ERR) indev = SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_GETITEMDATA,r,0); 769 | r=SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_GETCURSEL,0,0); 770 | if (r != CB_ERR) outdev = SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_GETITEMDATA,r,0); 771 | 772 | sprintf(tmp,"0 0 %d %d",indev,outdev); 773 | lstrcpyn((char *)lParam, tmp,wParam); 774 | 775 | } 776 | break; 777 | } 778 | return 0; 779 | } 780 | 781 | static HWND configFunc(const char *type_string, HWND parent, const char *initConfigString) 782 | { 783 | return CreateDialogParam(g_hInst,MAKEINTRESOURCE(IDD_SURFACEEDIT_MCU),parent,dlgProc,(LPARAM)initConfigString); 784 | } 785 | 786 | 787 | reaper_csurf_reg_t csurf_faderport_reg = 788 | { 789 | "FADERPORT", 790 | "PreSonus FaderPort", 791 | createFunc, 792 | configFunc, 793 | }; -------------------------------------------------------------------------------- /Source/jmde/csurf/csurf_tranzport.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** reaper_csurf 3 | ** TranzPort support 4 | ** Copyright (C) 2006-2008 Cockos Incorporated 5 | ** License: LGPL. 6 | */ 7 | 8 | #include "csurf.h" 9 | 10 | 11 | static bool g_csurf_mcpmode=false; // we may wish to allow an action to set this 12 | 13 | 14 | 15 | 16 | class CSurf_TranzPort : public IReaperControlSurface 17 | { 18 | int m_midi_in_dev,m_midi_out_dev; 19 | midi_Output *m_midiout; 20 | midi_Input *m_midiin; 21 | 22 | int m_tranz_shiftstate; 23 | int m_tranz_anysolo_poop; 24 | int m_tranz_curmode; 25 | int m_arrowstates,m_button_states; 26 | int m_bank_offset; 27 | DWORD m_pan_lasttouch,m_vol_lasttouch; 28 | DWORD m_buttonstate_lastrun; 29 | DWORD m_frameupd_lastrun; 30 | char m_tranz_oldbuf[128]; 31 | 32 | WDL_String descspace; 33 | char configtmp[1024]; 34 | 35 | void OnMIDIEvent(MIDI_event_t *evt) 36 | { 37 | if (evt->midi_message[0] == 0xb0) 38 | { 39 | if (evt->midi_message[1] == 0x3c) 40 | { 41 | int v=evt->midi_message[2]&0x3f; 42 | if (evt->midi_message[2]&0x40) v=-v; 43 | if (v) 44 | { 45 | if (m_tranz_shiftstate) 46 | { 47 | if (v > 0) 48 | { 49 | m_tranz_curmode++; 50 | if (m_tranz_curmode>2)m_tranz_curmode=0; 51 | } 52 | else if (v < 0) 53 | { 54 | m_tranz_curmode--; 55 | if (m_tranz_curmode<0)m_tranz_curmode=2; 56 | } 57 | } 58 | else 59 | { 60 | if (m_tranz_curmode==0) 61 | { 62 | // seek 63 | if (v > 0) 64 | CSurf_OnFwd(128); 65 | if (v < 0) 66 | CSurf_OnRew(128); 67 | } 68 | else if (m_tranz_curmode==1) 69 | { 70 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 71 | m_vol_lasttouch=timeGetTime(); 72 | if (tr) 73 | CSurf_SetSurfaceVolume(tr,CSurf_OnVolumeChange(tr,v/3.0,true),this); 74 | } 75 | else if (m_tranz_curmode == 2) 76 | { 77 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 78 | m_pan_lasttouch=timeGetTime(); 79 | if (tr) CSurf_SetSurfacePan(tr,CSurf_OnPanChange(tr,v/20.0,true),this); 80 | } 81 | } 82 | m_tranz_shiftstate&=5; 83 | } 84 | 85 | } 86 | } 87 | else if (evt->midi_message[0] == 0x90) 88 | { 89 | bool ispress=evt->midi_message[2] == 0x7f; 90 | switch (evt->midi_message[1]) 91 | { 92 | case 0x00: // rec arm 93 | if (ispress) 94 | { 95 | if (m_tranz_shiftstate) 96 | { 97 | ClearAllRecArmed(); 98 | } 99 | else 100 | { 101 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 102 | CSurf_SetSurfaceRecArm(tr,CSurf_OnRecArmChange(tr,-1),NULL); 103 | } 104 | m_tranz_shiftstate&=5; 105 | } 106 | break; 107 | case 0x10: // mute 108 | if (ispress) 109 | { 110 | if (m_tranz_shiftstate) 111 | { 112 | MuteAllTracks(false); 113 | } 114 | else 115 | { 116 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 117 | if (tr) CSurf_SetSurfaceMute(tr,CSurf_OnMuteChange(tr,-1),NULL); 118 | } 119 | m_tranz_shiftstate&=5; 120 | } 121 | break; 122 | case 0x08: //solo 123 | if (ispress) 124 | { 125 | if (m_tranz_shiftstate) 126 | { 127 | SoloAllTracks(false); 128 | } 129 | else 130 | { 131 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 132 | if (tr) CSurf_SetSurfaceSolo(tr,CSurf_OnSoloChange(tr,-1),NULL); 133 | } 134 | m_tranz_shiftstate&=5; 135 | } 136 | break; 137 | case 0x4c: 138 | if (ispress) 139 | { 140 | SendMessage(g_hwnd,WM_COMMAND,m_tranz_shiftstate?IDC_EDIT_REDO:IDC_EDIT_UNDO,0); 141 | m_tranz_shiftstate&=5; 142 | } 143 | break; 144 | case 0x52: // add marker 145 | if (ispress) 146 | { 147 | SendMessage(g_hwnd,WM_COMMAND,m_tranz_shiftstate?ID_INSERT_MARKERRGN:ID_INSERT_MARKER,0); 148 | m_tranz_shiftstate&=5; 149 | } 150 | break; 151 | case 0x54: // prev marker 152 | if (ispress) 153 | SendMessage(g_hwnd,WM_COMMAND,ID_MARKER_PREV,0); 154 | break; 155 | case 0x55: // next marker 156 | if (ispress) 157 | SendMessage(g_hwnd,WM_COMMAND,ID_MARKER_NEXT,0); 158 | break; 159 | case 0x56: 160 | if (ispress) 161 | { 162 | SendMessage(g_hwnd,WM_COMMAND,IDC_REPEAT,0); 163 | 164 | } 165 | break; 166 | case 0x57: 167 | if (ispress) 168 | { 169 | if (m_tranz_shiftstate) m_arrowstates=64|8; 170 | else 171 | { 172 | SendMessage(g_hwnd,WM_COMMAND,ID_LOOP_SETSTART,0); 173 | // set loop region to start at this position 174 | } 175 | m_tranz_shiftstate&=5; 176 | } 177 | else m_arrowstates=0; 178 | break; 179 | case 0x58: 180 | if (ispress) 181 | { 182 | if (m_tranz_shiftstate) m_arrowstates=64|4; 183 | else 184 | { 185 | // set loop region to end at this position 186 | SendMessage(g_hwnd,WM_COMMAND,ID_LOOP_SETEND,0); 187 | } 188 | m_tranz_shiftstate&=5; 189 | } 190 | else m_arrowstates=0; 191 | break; 192 | case 0x5d: 193 | if (ispress) CSurf_OnStop(); 194 | break; 195 | case 0x5e: 196 | if (ispress) CSurf_OnPlay(); 197 | break; 198 | case 0x5f: 199 | if (ispress) CSurf_OnRecord(); 200 | break; 201 | case 0x5b: 202 | if (ispress && m_tranz_shiftstate) 203 | { 204 | CSurf_GoStart(); 205 | m_button_states=0; 206 | m_tranz_shiftstate&=5; 207 | } 208 | else m_button_states=ispress?1:0; 209 | break; 210 | case 0x5c: 211 | if (ispress && m_tranz_shiftstate) 212 | { 213 | CSurf_GoEnd(); 214 | m_button_states=0; 215 | m_tranz_shiftstate&=5; 216 | } 217 | else m_button_states=ispress?2:0; 218 | break; 219 | case 0x30: // prev track 220 | if (ispress) 221 | { 222 | if (m_tranz_shiftstate) 223 | { 224 | m_tranz_curmode--; 225 | if (m_tranz_curmode<0)m_tranz_curmode=2; 226 | } 227 | else 228 | { 229 | AdjustBankOffset(-1,true); 230 | TrackList_UpdateAllExternalSurfaces(); 231 | } 232 | } 233 | break; 234 | case 0x31: // next track 235 | if (ispress) 236 | { 237 | if (m_tranz_shiftstate) 238 | { 239 | m_tranz_curmode++; 240 | if (m_tranz_curmode>2)m_tranz_curmode=0; 241 | } 242 | else 243 | { 244 | AdjustBankOffset(1,true); 245 | TrackList_UpdateAllExternalSurfaces(); 246 | } 247 | } 248 | break; 249 | case 0x79: 250 | m_tranz_shiftstate=ispress; 251 | break; 252 | } 253 | } 254 | } 255 | 256 | void AdjustBankOffset(int amt, bool dosel) 257 | { 258 | if (!amt) return; 259 | 260 | if (amt<0) 261 | { 262 | if (m_bank_offset>0) 263 | { 264 | m_bank_offset += amt; 265 | if (m_bank_offset<0) m_bank_offset=0; 266 | 267 | if (dosel) 268 | { 269 | int x; 270 | MediaTrack *t=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 271 | for (x = 0; ; x ++) 272 | { 273 | int f=0; 274 | if (!GetTrackInfo(x-1,&f)) break; 275 | 276 | MediaTrack *tt=CSurf_TrackFromID(x,false); 277 | bool sel=tt == t; 278 | if (tt && !(f&2) == sel) 279 | { 280 | SetTrackSelected(tt,sel); 281 | } 282 | } 283 | } 284 | } 285 | } 286 | else 287 | { 288 | int msize=CSurf_NumTracks(g_csurf_mcpmode); 289 | 290 | if (m_bank_offsetmsize) m_bank_offset=msize; 294 | 295 | if (dosel) 296 | { 297 | int x; 298 | MediaTrack *t=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 299 | for (x = 0; ; x ++) 300 | { 301 | int f=0; 302 | if (!GetTrackInfo(x-1,&f)) break; 303 | 304 | MediaTrack *tt=CSurf_TrackFromID(x,false); 305 | bool sel=tt == t; 306 | if (tt && !(f&2) == sel) 307 | { 308 | SetTrackSelected(tt,sel); 309 | } 310 | } 311 | } 312 | } 313 | } 314 | 315 | } 316 | 317 | void UpdateTranzDisplay(int pos, const char *text, int pad, char *oldbuf) 318 | { 319 | // compare oldbuf to text 320 | oldbuf += pos; 321 | 322 | int l=strlen(text); 323 | if (pad ml-pos)l=ml-pos; 326 | 327 | int minpos=256; 328 | int maxpos=0; 329 | 330 | const char *p=text; 331 | char *obp=oldbuf; 332 | int cnt=0; 333 | while (cnt < l || cnt < pad) 334 | { 335 | char c=cnt < l ? *p++ : ' '; 336 | if (c>127||c<0) c=0; 337 | if (c != *obp) 338 | { 339 | if (cnt < minpos) minpos=cnt; 340 | if (cnt > maxpos) maxpos=cnt; 341 | *obp = c; 342 | } 343 | obp++; 344 | cnt++; 345 | } 346 | if (maxpos < minpos) return; // do nothing! 347 | 348 | oldbuf += minpos; 349 | l=(maxpos-minpos)+1; 350 | 351 | struct 352 | { 353 | MIDI_event_t evt; 354 | char data[512]; 355 | } 356 | poo; 357 | poo.evt.frame_offset=0; 358 | poo.evt.size=0; 359 | poo.evt.midi_message[poo.evt.size++]=0xF0; 360 | poo.evt.midi_message[poo.evt.size++]=0x00; 361 | poo.evt.midi_message[poo.evt.size++]=0x01; 362 | poo.evt.midi_message[poo.evt.size++]=0x40; 363 | poo.evt.midi_message[poo.evt.size++]=0x10; 364 | poo.evt.midi_message[poo.evt.size++]=0x00; 365 | 366 | poo.evt.midi_message[poo.evt.size++]=pos+minpos; 367 | 368 | while (l-->0) poo.evt.midi_message[poo.evt.size++]=*oldbuf++; 369 | poo.evt.midi_message[poo.evt.size++]=0xF7; 370 | 371 | m_midiout->SendMsg(&poo.evt,-1); 372 | } 373 | 374 | 375 | public: 376 | CSurf_TranzPort(int indev, int outdev, int *errStats) 377 | { 378 | m_midi_in_dev=indev; 379 | m_midi_out_dev=outdev; 380 | 381 | memset(m_tranz_oldbuf,' ',sizeof(m_tranz_oldbuf)); 382 | m_frameupd_lastrun=0; 383 | m_bank_offset=0; 384 | m_pan_lasttouch=0; 385 | m_vol_lasttouch=0; 386 | m_tranz_shiftstate=0; 387 | m_tranz_curmode=0; 388 | m_tranz_anysolo_poop=0; 389 | m_arrowstates=0; 390 | m_button_states=0; 391 | m_buttonstate_lastrun=0; 392 | 393 | //create midi hardware access 394 | m_midiin = m_midi_in_dev >= 0 ? CreateMIDIInput(m_midi_in_dev) : NULL; 395 | m_midiout = m_midi_out_dev >= 0 ? CreateThreadedMIDIOutput(CreateMIDIOutput(m_midi_out_dev,false,NULL)) : NULL; 396 | 397 | if (errStats) 398 | { 399 | if (m_midi_in_dev >=0 && !m_midiin) *errStats|=1; 400 | if (m_midi_out_dev >=0 && !m_midiout) *errStats|=2; 401 | } 402 | 403 | if (m_midiin) 404 | m_midiin->start(); 405 | 406 | } 407 | ~CSurf_TranzPort() 408 | { 409 | if (m_midiout) 410 | { 411 | UpdateTranzDisplay(0,"",0x28,m_tranz_oldbuf); 412 | Sleep(5); 413 | } 414 | delete m_midiout; 415 | delete m_midiin; 416 | } 417 | 418 | 419 | const char *GetTypeString() { return "TRANZPORT"; } 420 | const char *GetDescString() 421 | { 422 | descspace.Set("Frontier TranzPort"); 423 | char tmp[512]; 424 | sprintf(tmp," (dev %d,%d)",m_midi_in_dev,m_midi_out_dev); 425 | descspace.Append(tmp); 426 | return descspace.Get(); 427 | } 428 | const char *GetConfigString() // string of configuration data 429 | { 430 | sprintf(configtmp,"0 0 %d %d",m_midi_in_dev,m_midi_out_dev); 431 | return configtmp; 432 | } 433 | 434 | void CloseNoReset() 435 | { 436 | delete m_midiout; 437 | delete m_midiin; 438 | m_midiout=0; 439 | m_midiin=0; 440 | } 441 | 442 | void Run() 443 | { 444 | DWORD now=timeGetTime(); 445 | 446 | if (now >= m_frameupd_lastrun+(1000/max(*g_config_csurf_rate,1)) || now < m_frameupd_lastrun-250) 447 | { 448 | m_frameupd_lastrun=now; 449 | if (m_midiout) 450 | { 451 | if (m_tranz_anysolo_poop&1) 452 | { 453 | int bla=(now%1000)>500; 454 | if (!!(m_tranz_anysolo_poop&2) != bla) 455 | { 456 | m_tranz_anysolo_poop^=2; 457 | m_midiout->Send(0x90,0x73,bla?0x7f:0,-1); 458 | } 459 | } 460 | double pp=(GetPlayState()&1) ? GetPlayPosition() : GetCursorPosition(); 461 | char timebuf[512]; 462 | 463 | MediaTrack *t=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 464 | 465 | memset(timebuf,' ',40); 466 | timebuf[40]=0; 467 | 468 | if (t == CSurf_TrackFromID(0,false)) memcpy(timebuf,"master",6); 469 | else if (t) 470 | { 471 | char tmp[64]; 472 | const char *name=GetTrackInfo((INT_PTR)t,NULL); 473 | sprintf(tmp,"%d)%.9s",m_bank_offset,name?name:""); 474 | memcpy(timebuf,tmp,strlen(tmp)); 475 | } 476 | 477 | if (t) 478 | { 479 | double vol=1.0,pan=0.0; 480 | GetTrackUIVolPan(t,&vol,&pan); 481 | 482 | double dv=VAL2DB(vol); 483 | char vb[128]; 484 | if (m_tranz_curmode==1) vb[0]=0x7e; 485 | else vb[0]=' '; 486 | char pb[64]; 487 | if (m_tranz_curmode==2) pb[0]=0x7e; 488 | else pb[0]=' '; 489 | 490 | if (fabs(dv)>=10.0) sprintf(vb+1,"%s%.0f",vol>=1.0?"+":"",dv); 491 | else sprintf(vb+1,"%s%.1f",vol>=1.0?"+":"",dv); 492 | 493 | mkpanstr(pb+1,pan); 494 | if (!strnicmp(pb+1,"cent",4)) strcpy(pb+1,"ctr"); 495 | else if (strstr(pb+1,"%")) 496 | { 497 | char *p=strstr(pb+1,"%"); 498 | p[0]=p[1]; 499 | p[1]=0; 500 | } 501 | strcat(vb,pb); 502 | 503 | if (strlen(vb)<20) 504 | memcpy(timebuf+20-strlen(vb),vb,strlen(vb)); 505 | 506 | } 507 | 508 | 509 | char buf[256]; 510 | 511 | format_timestr_pos(pp,buf,sizeof(buf),-1); 512 | 513 | char *p; 514 | int x; 515 | 516 | memset(timebuf+20,' ',20); 517 | if (strlen(buf)>=13) 518 | memcpy(p=timebuf+20+7,buf,13); 519 | else memcpy(p=timebuf+20+20-strlen(buf),buf,strlen(buf)); 520 | if (m_tranz_curmode==0) p[-1]=0x7e; 521 | 522 | // vu meter! 523 | int v[2]={0,0}; 524 | if (t) 525 | { 526 | double p1,p2; 527 | 528 | p1=VAL2DB(Track_GetPeakInfo(t,0)); 529 | p2=VAL2DB(Track_GetPeakInfo(t,1)); 530 | v[0]=(int)((p1+60.0)/5.0); 531 | v[1]=(int)((p2+60.0)/5.0); 532 | } 533 | for (x = 0; x < 6; x ++) 534 | { 535 | int pos1=v[0]-x*2; 536 | int pos2=v[1]-x*2; 537 | if (pos1>2)pos1=2; 538 | else if (pos1<0)pos1=0; 539 | if (pos2>2)pos2=2; 540 | else if (pos2<0)pos2=0; 541 | 542 | char c; 543 | if (!pos1 && !pos2) continue; 544 | 545 | if (pos1) 546 | { 547 | if (pos2==0) c=pos1-1; 548 | else if (pos2==1) c=2+pos1; 549 | else c=5+pos1; 550 | } 551 | else 552 | { 553 | if (pos2==1) c=2; 554 | else c=5; 555 | } 556 | if (!c)c=-128; 557 | 558 | 559 | timebuf[20+x]=c; 560 | } 561 | if (v[0]>=12 || v[1]>=12) 562 | timebuf[20+x]='*'; 563 | else 564 | timebuf[20+x]='|'; 565 | timebuf[40]=0; 566 | 567 | UpdateTranzDisplay(0,timebuf,40,m_tranz_oldbuf); 568 | 569 | } 570 | } 571 | if (m_midiin) 572 | { 573 | m_midiin->SwapBufs(timeGetTime()); 574 | int l=0; 575 | MIDI_eventlist *list=m_midiin->GetReadBuf(); 576 | MIDI_event_t *evts; 577 | while ((evts=list->EnumItems(&l))) OnMIDIEvent(evts); 578 | 579 | if (m_arrowstates||m_button_states) 580 | { 581 | DWORD now=timeGetTime(); 582 | if (now >= m_buttonstate_lastrun + 100) 583 | { 584 | m_buttonstate_lastrun=now; 585 | 586 | 587 | if (m_arrowstates) 588 | { 589 | int iszoom=m_arrowstates&64; 590 | 591 | if (m_arrowstates&1) 592 | CSurf_OnArrow(0,!!iszoom); 593 | if (m_arrowstates&2) 594 | CSurf_OnArrow(1,!!iszoom); 595 | if (m_arrowstates&4) 596 | CSurf_OnArrow(2,!!iszoom); 597 | if (m_arrowstates&8) 598 | CSurf_OnArrow(3,!!iszoom); 599 | 600 | } 601 | 602 | if ((m_button_states&3) != 3) 603 | { 604 | if (m_button_states&1) 605 | { 606 | CSurf_OnRew(1); 607 | } 608 | else if (m_button_states&2) 609 | { 610 | CSurf_OnFwd(1); 611 | } 612 | } 613 | 614 | } 615 | } 616 | } 617 | } 618 | 619 | void SetTrackListChange() { } // not used 620 | 621 | #define FIXID(id) int id=CSurf_TrackToID(trackid,g_csurf_mcpmode); int oid=id; id -= m_bank_offset; 622 | 623 | void SetSurfaceVolume(MediaTrack *trackid, double volume) 624 | { 625 | } 626 | void SetSurfacePan(MediaTrack *trackid, double pan) 627 | { 628 | } 629 | void SetSurfaceMute(MediaTrack *trackid, bool mute) 630 | { 631 | FIXID(id) 632 | if (m_midiout && !id) m_midiout->Send(0x90,0x10,mute?0x7f:0,-1); 633 | } 634 | void SetSurfaceSelected(MediaTrack *trackid, bool selected) 635 | { 636 | // not used 637 | } 638 | void SetSurfaceSolo(MediaTrack *trackid, bool solo) 639 | { 640 | FIXID(id) 641 | if (m_midiout) 642 | { 643 | if (!oid) m_midiout->Send(0x90, 0x73,(m_tranz_anysolo_poop=!!solo)?0x7f:0,-1); 644 | 645 | if (!id) m_midiout->Send(0x90,0x08,solo?0x7f:0,-1); 646 | } 647 | } 648 | void SetSurfaceRecArm(MediaTrack *trackid, bool recarm) 649 | { 650 | FIXID(id) 651 | if (m_midiout) 652 | { 653 | if (!id) 654 | m_midiout->Send(0x90,0x00,recarm?0x7f:0,-1); 655 | 656 | } 657 | } 658 | void SetPlayState(bool play, bool pause, bool rec) 659 | { 660 | if (m_midiout) m_midiout->Send(0x90,0x5f,rec ? 0x7f:0,-1); 661 | } 662 | void SetRepeatState(bool rep) 663 | { 664 | if (m_midiout) m_midiout->Send(0x90,0x56,rep ? 0x7f:0,-1); 665 | } 666 | 667 | void SetTrackTitle(MediaTrack *trackid, const char *title) { } 668 | 669 | bool GetTouchState(MediaTrack *trackid, int isPan) 670 | { 671 | FIXID(id) 672 | if (!id) 673 | { 674 | DWORD lt=m_vol_lasttouch; 675 | if (isPan==1) lt=m_pan_lasttouch; 676 | DWORD now=timeGetTime(); 677 | if ((now= lt-1000)) // fake touch, go for 3s after last movement 678 | return true; 679 | } 680 | return false; 681 | } 682 | 683 | void SetAutoMode(int mode) { } 684 | 685 | void ResetCachedVolPanStates() 686 | { 687 | } 688 | void OnTrackSelection(MediaTrack *trackid) 689 | { 690 | int newpos=CSurf_TrackToID(trackid,g_csurf_mcpmode); 691 | if (newpos>=0 && newpos != m_bank_offset) 692 | { 693 | AdjustBankOffset(newpos-m_bank_offset,false); 694 | TrackList_UpdateAllExternalSurfaces(); 695 | } 696 | } 697 | 698 | bool IsKeyDown(int key) 699 | { 700 | return false; 701 | } 702 | 703 | 704 | }; 705 | 706 | 707 | static void parseParms(const char *str, int parms[4]) 708 | { 709 | parms[0]=0; 710 | parms[1]=9; 711 | parms[2]=parms[3]=-1; 712 | 713 | const char *p=str; 714 | if (p) 715 | { 716 | int x=0; 717 | while (x<4) 718 | { 719 | while (*p == ' ') p++; 720 | if ((*p < '0' || *p > '9') && *p != '-') break; 721 | parms[x++]=atoi(p); 722 | while (*p && *p != ' ') p++; 723 | } 724 | } 725 | } 726 | 727 | static IReaperControlSurface *createFunc(const char *type_string, const char *configString, int *errStats) 728 | { 729 | int parms[4]; 730 | parseParms(configString,parms); 731 | 732 | return new CSurf_TranzPort(parms[2],parms[3],errStats); 733 | } 734 | 735 | 736 | static WDL_DLGRET dlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 737 | { 738 | switch (uMsg) 739 | { 740 | case WM_INITDIALOG: 741 | { 742 | int parms[4]; 743 | parseParms((const char *)lParam,parms); 744 | 745 | ShowWindow(GetDlgItem(hwndDlg,IDC_EDIT1),SW_HIDE); 746 | ShowWindow(GetDlgItem(hwndDlg,IDC_EDIT1_LBL),SW_HIDE); 747 | ShowWindow(GetDlgItem(hwndDlg,IDC_EDIT2),SW_HIDE); 748 | ShowWindow(GetDlgItem(hwndDlg,IDC_EDIT2_LBL),SW_HIDE); 749 | ShowWindow(GetDlgItem(hwndDlg,IDC_EDIT2_LBL2),SW_HIDE); 750 | 751 | int n=GetNumMIDIInputs(); 752 | int x=SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_ADDSTRING,0,(LPARAM)"None"); 753 | SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_SETITEMDATA,x,-1); 754 | x=SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_ADDSTRING,0,(LPARAM)"None"); 755 | SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_SETITEMDATA,x,-1); 756 | for (x = 0; x < n; x ++) 757 | { 758 | char buf[512]; 759 | if (GetMIDIInputName(x,buf,sizeof(buf))) 760 | { 761 | int a=SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_ADDSTRING,0,(LPARAM)buf); 762 | SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_SETITEMDATA,a,x); 763 | if (x == parms[2]) SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_SETCURSEL,a,0); 764 | } 765 | } 766 | n=GetNumMIDIOutputs(); 767 | for (x = 0; x < n; x ++) 768 | { 769 | char buf[512]; 770 | if (GetMIDIOutputName(x,buf,sizeof(buf))) 771 | { 772 | int a=SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_ADDSTRING,0,(LPARAM)buf); 773 | SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_SETITEMDATA,a,x); 774 | if (x == parms[3]) SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_SETCURSEL,a,0); 775 | } 776 | } 777 | } 778 | break; 779 | case WM_USER+1024: 780 | if (wParam > 1 && lParam) 781 | { 782 | char tmp[512]; 783 | 784 | int indev=-1, outdev=-1, offs=0, size=9; 785 | int r=SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_GETCURSEL,0,0); 786 | if (r != CB_ERR) indev = SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_GETITEMDATA,r,0); 787 | r=SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_GETCURSEL,0,0); 788 | if (r != CB_ERR) outdev = SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_GETITEMDATA,r,0); 789 | 790 | sprintf(tmp,"0 0 %d %d",indev,outdev); 791 | lstrcpyn((char *)lParam, tmp,wParam); 792 | 793 | } 794 | break; 795 | } 796 | return 0; 797 | } 798 | 799 | static HWND configFunc(const char *type_string, HWND parent, const char *initConfigString) 800 | { 801 | return CreateDialogParam(g_hInst,MAKEINTRESOURCE(IDD_SURFACEEDIT_MCU),parent,dlgProc,(LPARAM)initConfigString); 802 | } 803 | 804 | 805 | reaper_csurf_reg_t csurf_tranzport_reg = 806 | { 807 | "TRANZPORT", 808 | "Frontier Tranzport", 809 | createFunc, 810 | configFunc, 811 | }; -------------------------------------------------------------------------------- /Source/jmde/csurf/csurf_alphatrack.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ** reaper_csurf 3 | ** AlphaTrack support 4 | ** Copyright (C) 2007-2008 Cockos Incorporated 5 | ** License: LGPL. 6 | */ 7 | 8 | #include "csurf.h" 9 | 10 | /* 11 | ** Todo: automation status, automation mode setting using "auto" button, more 12 | */ 13 | 14 | static bool g_csurf_mcpmode=false; // we may wish to allow an action to set this 15 | 16 | 17 | 18 | 19 | static double int14ToVol(unsigned char msb, unsigned char lsb) 20 | { 21 | int val=lsb | (msb<<7); 22 | double pos=((double)val*1000.0)/16383.0; 23 | pos=SLIDER2DB(pos); 24 | return DB2VAL(pos); 25 | } 26 | static double int14ToPan(unsigned char msb, unsigned char lsb) 27 | { 28 | int val=lsb | (msb<<7); 29 | return 1.0 - (val/(16383.0*0.5)); 30 | } 31 | 32 | static int volToInt14(double vol) 33 | { 34 | double d=(DB2SLIDER(VAL2DB(vol))*16383.0/1000.0); 35 | if (d<0.0)d=0.0; 36 | else if (d>16383.0)d=16383.0; 37 | 38 | return (int)(d+0.5); 39 | } 40 | static int panToInt14(double pan) 41 | { 42 | double d=((1.0-pan)*16383.0*0.5); 43 | if (d<0.0)d=0.0; 44 | else if (d>16383.0)d=16383.0; 45 | 46 | return (int)(d+0.5); 47 | } 48 | 49 | 50 | 51 | class CSurf_AlphaTrack : public IReaperControlSurface 52 | { 53 | int m_midi_in_dev,m_midi_out_dev; 54 | midi_Output *m_midiout; 55 | midi_Input *m_midiin; 56 | 57 | int m_vol_lastpos; 58 | int m_alphatrack_flipmode; 59 | int m_alphatrack_nfingers,m_alphatrack_fingerpos,m_alphatrack_fingerposcenter; 60 | 61 | char m_fader_touchstate; 62 | int m_alpha_fx, m_alpha_fxparm; 63 | int m_alpha_fxcap; 64 | int m_bank_offset; 65 | int m_tranz_shiftstate; 66 | 67 | DWORD m_frameupd_lastrun; 68 | DWORD m_frameupd_lastrun2; 69 | int m_arrowstates,m_button_states; 70 | DWORD m_buttonstate_lastrun; 71 | DWORD m_pan_lasttouch; 72 | int m_tranz_anysolo_poop; 73 | char m_tranz_oldbuf[128]; 74 | 75 | WDL_String descspace; 76 | char configtmp[1024]; 77 | 78 | void OnMIDIEvent(MIDI_event_t *evt) 79 | { 80 | if (evt->midi_message[0] == 0xe0) 81 | { 82 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 83 | 84 | if (tr) 85 | { 86 | if (m_alphatrack_flipmode) 87 | { 88 | CSurf_SetSurfacePan(tr,CSurf_OnPanChange(tr,int14ToPan(evt->midi_message[2],evt->midi_message[1]),false),NULL); 89 | } 90 | else 91 | CSurf_SetSurfaceVolume(tr,CSurf_OnVolumeChange(tr,int14ToVol(evt->midi_message[2],evt->midi_message[1]),false),NULL); 92 | } 93 | } 94 | if (evt->midi_message[0] == 0xe9 && evt->midi_message[1] == 0) 95 | { 96 | m_alphatrack_fingerpos=evt->midi_message[2]; 97 | if (m_alphatrack_fingerposcenter<0) 98 | m_alphatrack_fingerposcenter=evt->midi_message[2]; 99 | } 100 | 101 | if (evt->midi_message[0] == 0xb0) 102 | { 103 | if (evt->midi_message[1] == 0x11 || evt->midi_message[1] == 0x12) 104 | { 105 | int adj=(evt->midi_message[2]&0x3f); 106 | if (evt->midi_message[2]&0x40) adj=-adj; 107 | 108 | MediaTrack *t=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 109 | if (m_alpha_fx<0)m_alpha_fx=0; 110 | int nfx=TrackFX_GetCount(t); 111 | if (t && nfx>0) 112 | { 113 | if (m_alpha_fx>=nfx) m_alpha_fx=nfx-1; 114 | if (m_alpha_fx >= 0) 115 | { 116 | int np=TrackFX_GetNumParams(t,m_alpha_fx); 117 | if (m_alpha_fxparm<0)m_alpha_fxparm=0; 118 | else if (m_alpha_fxparm>=np) m_alpha_fxparm=np-1; 119 | 120 | if (evt->midi_message[1]==0x12) 121 | { 122 | double dadj=adj/16.0; 123 | // tweak parm 124 | if (m_alpha_fxcap&16) dadj*=0.2; 125 | 126 | double v,oov=0; 127 | if (m_alpha_fxparm == np-1) 128 | { 129 | v=adj>0?1.0:0.0; 130 | } 131 | else 132 | { 133 | 134 | double minval=0.0, maxval=1.0; 135 | oov=v=TrackFX_GetParam(t,m_alpha_fx,m_alpha_fxparm, &minval, &maxval); 136 | 137 | v += dadj * (maxval-minval); 138 | if (vmaxval) v=maxval; 140 | } 141 | TrackFX_SetParam(t,m_alpha_fx,m_alpha_fxparm,v); 142 | if (m_alpha_fxparm != np-1) 143 | { 144 | double minval,maxval; 145 | double ov=TrackFX_GetParam(t,m_alpha_fx,m_alpha_fxparm, &minval, &maxval); 146 | if ((fabs(ov-minval)<0.001 ||fabs(ov-maxval)<0.001) && fabs(oov-ov)<0.001) 147 | TrackFX_SetParam(t,m_alpha_fx,m_alpha_fxparm,adj>0?maxval:minval); 148 | } 149 | 150 | } 151 | else if (evt->midi_message[1]==0x11) 152 | { 153 | if (m_alpha_fxcap&8) 154 | { 155 | m_alpha_fxparm=0; 156 | m_alpha_fx+=adj; 157 | } 158 | else 159 | { 160 | if (adj<0) 161 | { 162 | if ((m_alpha_fxparm+=adj) < 0) 163 | { 164 | if (m_alpha_fx>0) 165 | { 166 | m_alpha_fxparm=TrackFX_GetNumParams(t,--m_alpha_fx)-1; 167 | if (m_alpha_fxparm<0)m_alpha_fxparm=0; 168 | } 169 | else 170 | m_alpha_fxparm=0; 171 | } 172 | } 173 | else 174 | { 175 | if ((m_alpha_fxparm += adj)>=np) 176 | { 177 | if (m_alpha_fx+1 < TrackFX_GetCount(t)) 178 | { 179 | ++m_alpha_fx; 180 | m_alpha_fxparm=0; 181 | } 182 | else m_alpha_fxparm=np-1; 183 | } 184 | } 185 | } 186 | } 187 | } 188 | else if (evt->midi_message[1]==0x11) 189 | { 190 | m_alpha_fx += adj; m_alpha_fxparm=0; 191 | } 192 | m_frameupd_lastrun=0; // force immediate redraw 193 | m_frameupd_lastrun2=0; 194 | } 195 | } 196 | else if (evt->midi_message[1] == 0x10) 197 | { 198 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 199 | 200 | if (tr) 201 | { 202 | double adj=(evt->midi_message[2]&0x3f)/13.0; 203 | if (evt->midi_message[2]&0x40) adj=-adj; 204 | if (m_alphatrack_flipmode) 205 | { 206 | CSurf_SetSurfaceVolume(tr,CSurf_OnVolumeChange(tr,adj*11.0,true),NULL); 207 | } 208 | else 209 | { 210 | CSurf_SetSurfacePan(tr,CSurf_OnPanChange(tr,adj,true),NULL); 211 | } 212 | } 213 | } 214 | } 215 | else if (evt->midi_message[0] == 0x90) 216 | { 217 | bool ispress=evt->midi_message[2] == 0x7f; 218 | switch (evt->midi_message[1]) 219 | { 220 | case 0x00: // rec arm 221 | if (ispress) 222 | { 223 | if (m_tranz_shiftstate) 224 | { 225 | ClearAllRecArmed(); 226 | } 227 | else 228 | { 229 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 230 | CSurf_SetSurfaceRecArm(tr,CSurf_OnRecArmChange(tr,-1),NULL); 231 | } 232 | m_tranz_shiftstate&=5; 233 | } 234 | break; 235 | case 0x32: 236 | 237 | if (ispress) 238 | { 239 | m_alphatrack_flipmode=!m_alphatrack_flipmode; 240 | if (m_midiout) m_midiout->Send(0x90, 0x32,m_alphatrack_flipmode?0x7f:0,-1); 241 | CSurf_ResetAllCachedVolPanStates(); 242 | TrackList_UpdateAllExternalSurfaces(); 243 | } 244 | 245 | break; 246 | 247 | case 0x10: // mute 248 | if (ispress) 249 | { 250 | if (m_tranz_shiftstate) 251 | { 252 | MuteAllTracks(false); 253 | } 254 | else 255 | { 256 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 257 | if (tr) CSurf_SetSurfaceMute(tr,CSurf_OnMuteChange(tr,-1),NULL); 258 | } 259 | m_tranz_shiftstate&=5; 260 | } 261 | break; 262 | case 0x08: //solo 263 | if (ispress) 264 | { 265 | if (m_tranz_shiftstate) 266 | { 267 | SoloAllTracks(false); 268 | } 269 | else 270 | { 271 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 272 | if (tr) CSurf_SetSurfaceSolo(tr,CSurf_OnSoloChange(tr,-1),NULL); 273 | } 274 | m_tranz_shiftstate&=5; 275 | } 276 | break; 277 | case 0x4c: 278 | if (ispress) 279 | { 280 | SendMessage(g_hwnd,WM_COMMAND,m_tranz_shiftstate?IDC_EDIT_REDO:IDC_EDIT_UNDO,0); 281 | m_tranz_shiftstate&=5; 282 | } 283 | break; 284 | case 0x52: // add marker 285 | if (ispress) 286 | { 287 | SendMessage(g_hwnd,WM_COMMAND,m_tranz_shiftstate?ID_INSERT_MARKERRGN:ID_INSERT_MARKER,0); 288 | m_tranz_shiftstate&=5; 289 | } 290 | break; 291 | case 0x54: // prev marker 292 | if (ispress) 293 | SendMessage(g_hwnd,WM_COMMAND,ID_MARKER_PREV,0); 294 | break; 295 | case 0x55: // next marker 296 | if (ispress) 297 | SendMessage(g_hwnd,WM_COMMAND,ID_MARKER_NEXT,0); 298 | break; 299 | case 0x56: 300 | if (ispress) 301 | { 302 | SendMessage(g_hwnd,WM_COMMAND,IDC_REPEAT,0); 303 | 304 | } 305 | break; 306 | case 0x57: 307 | if (ispress) 308 | { 309 | if (m_tranz_shiftstate) 310 | SendMessage(g_hwnd,WM_COMMAND,ID_LOOP_SETSTART,0); 311 | else 312 | { 313 | AdjustBankOffset(-1,true); 314 | TrackList_UpdateAllExternalSurfaces(); 315 | } 316 | m_tranz_shiftstate&=5; 317 | } 318 | else m_arrowstates=0; 319 | break; 320 | case 0x58: 321 | if (ispress) 322 | { 323 | if (m_tranz_shiftstate) 324 | SendMessage(g_hwnd,WM_COMMAND,ID_LOOP_SETEND,0); 325 | else 326 | { 327 | AdjustBankOffset(1,true); 328 | TrackList_UpdateAllExternalSurfaces(); 329 | } 330 | m_tranz_shiftstate&=5; 331 | } 332 | else m_arrowstates=0; 333 | break; 334 | case 0x5d: 335 | if (ispress) CSurf_OnStop(); 336 | break; 337 | case 0x5e: 338 | if (ispress) CSurf_OnPlay(); 339 | break; 340 | case 0x5f: 341 | if (ispress) CSurf_OnRecord(); 342 | break; 343 | case 0x5b: 344 | if (ispress && m_tranz_shiftstate) 345 | { 346 | CSurf_GoStart(); 347 | m_button_states=0; 348 | m_tranz_shiftstate&=5; 349 | } 350 | else m_button_states=ispress?1:0; 351 | break; 352 | case 0x5c: 353 | if (ispress && m_tranz_shiftstate) 354 | { 355 | CSurf_GoEnd(); 356 | m_button_states=0; 357 | m_tranz_shiftstate&=5; 358 | } 359 | else m_button_states=ispress?2:0; 360 | break; 361 | case 0x46: 362 | if (ispress && (m_tranz_shiftstate&4)) m_tranz_shiftstate=1; // if pressed and a stuck shift state is on, remove it 363 | else if (!ispress && (m_tranz_shiftstate&2)) // end of press, shift state wasnt touched, stick it 364 | m_tranz_shiftstate=4; 365 | else m_tranz_shiftstate=ispress?3:0; 366 | if (m_midiout) m_midiout->Send(0x90,0x46,m_tranz_shiftstate?0x7f:0,-1); 367 | break; 368 | case 0x68: 369 | m_fader_touchstate=ispress; 370 | break; 371 | case 0x78: 372 | m_pan_lasttouch=!!ispress; 373 | break; 374 | case 0x79: 375 | case 0x7a: 376 | { 377 | int mask=evt->midi_message[1]==0x79 ? 1:2; 378 | if (ispress) m_alpha_fxcap|=mask; 379 | else m_alpha_fxcap&=~mask; 380 | } 381 | break; 382 | case 0x74: 383 | case 0x7b: 384 | { 385 | int mask=(evt->midi_message[1]==0x74)?1:2; 386 | if (ispress) 387 | m_alphatrack_nfingers|=mask; 388 | else 389 | m_alphatrack_nfingers&=~mask; 390 | 391 | if (!m_alphatrack_nfingers) 392 | { 393 | m_alphatrack_fingerpos=-1; 394 | m_alphatrack_fingerposcenter=-1; 395 | } 396 | } 397 | break; 398 | case 0x36: 399 | case 0x37: 400 | case 0x38: 401 | case 0x39: 402 | if (ispress) 403 | { 404 | int a=evt->midi_message[1]-0x36; 405 | if (m_tranz_shiftstate) a+= 4; 406 | MIDI_event_t evt={0,3,{0xbf,a,0}}; 407 | kbd_OnMidiEvent(&evt,-1); 408 | } 409 | break; 410 | case 0x21: 411 | case 0x22: 412 | if (ispress) m_alpha_fxcap |= (8<<(evt->midi_message[1]-0x21)); 413 | else m_alpha_fxcap &= ~(8<<(evt->midi_message[1]-0x21)); 414 | break; 415 | case 0x20: 416 | if (ispress) 417 | { 418 | MediaTrack *tr=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 419 | if (tr) 420 | { 421 | if (m_alphatrack_flipmode) 422 | { 423 | CSurf_SetSurfaceVolume(tr,CSurf_OnVolumeChange(tr,1.0,false),NULL); 424 | } 425 | else 426 | { 427 | CSurf_SetSurfacePan(tr,CSurf_OnPanChange(tr,0.0,false),NULL); 428 | } 429 | } 430 | } 431 | break; 432 | } 433 | } 434 | } 435 | 436 | void AdjustBankOffset(int amt, bool dosel) 437 | { 438 | if (!amt) return; 439 | 440 | if (amt<0) 441 | { 442 | if (m_bank_offset>0) 443 | { 444 | m_bank_offset += amt; 445 | if (m_bank_offset<0) m_bank_offset=0; 446 | 447 | if (dosel) 448 | { 449 | int x; 450 | MediaTrack *t=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 451 | for (x = 0; ; x ++) 452 | { 453 | int f=0; 454 | if (!GetTrackInfo(x-1,&f)) break; 455 | 456 | MediaTrack *tt=CSurf_TrackFromID(x,false); 457 | bool sel=tt == t; 458 | if (tt && !(f&2) == sel) 459 | { 460 | SetTrackSelected(tt,sel); 461 | } 462 | } 463 | } 464 | } 465 | } 466 | else 467 | { 468 | int msize=CSurf_NumTracks(g_csurf_mcpmode); 469 | 470 | if (m_bank_offsetmsize) m_bank_offset=msize; 474 | 475 | if (dosel) 476 | { 477 | int x; 478 | MediaTrack *t=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 479 | for (x = 0; ; x ++) 480 | { 481 | int f=0; 482 | if (!GetTrackInfo(x-1,&f)) break; 483 | 484 | MediaTrack *tt=CSurf_TrackFromID(x,false); 485 | bool sel=tt == t; 486 | if (tt && !(f&2) == sel) 487 | { 488 | SetTrackSelected(tt,sel); 489 | } 490 | } 491 | } 492 | } 493 | } 494 | 495 | } 496 | 497 | void UpdateTranzDisplay(int pos, const char *text, int pad, char *oldbuf) 498 | { 499 | // compare oldbuf to text 500 | oldbuf += pos; 501 | 502 | int l=strlen(text); 503 | if (pad ml-pos)l=ml-pos; 506 | 507 | int minpos=256; 508 | int maxpos=0; 509 | 510 | const char *p=text; 511 | char *obp=oldbuf; 512 | int cnt=0; 513 | while (cnt < l || cnt < pad) 514 | { 515 | char c=cnt < l ? *p++ : ' '; 516 | if (c>127||c<0) c=0; 517 | if (c != *obp) 518 | { 519 | if (cnt < minpos) minpos=cnt; 520 | if (cnt > maxpos) maxpos=cnt; 521 | *obp = c; 522 | } 523 | obp++; 524 | cnt++; 525 | } 526 | if (maxpos < minpos) return; // do nothing! 527 | 528 | oldbuf += minpos; 529 | l=(maxpos-minpos)+1; 530 | 531 | struct 532 | { 533 | MIDI_event_t evt; 534 | char data[512]; 535 | } 536 | poo; 537 | poo.evt.frame_offset=0; 538 | poo.evt.size=0; 539 | poo.evt.midi_message[poo.evt.size++]=0xF0; 540 | poo.evt.midi_message[poo.evt.size++]=0x00; 541 | poo.evt.midi_message[poo.evt.size++]=0x01; 542 | poo.evt.midi_message[poo.evt.size++]=0x40; 543 | poo.evt.midi_message[poo.evt.size++]=0x20; 544 | poo.evt.midi_message[poo.evt.size++]=0x00; 545 | 546 | poo.evt.midi_message[poo.evt.size++]=pos+minpos; 547 | 548 | while (l-->0) poo.evt.midi_message[poo.evt.size++]=*oldbuf++; 549 | poo.evt.midi_message[poo.evt.size++]=0xF7; 550 | 551 | m_midiout->SendMsg(&poo.evt,-1); 552 | } 553 | 554 | 555 | public: 556 | CSurf_AlphaTrack(int indev, int outdev, int *errStats) 557 | { 558 | m_midi_in_dev=indev; 559 | m_midi_out_dev=outdev; 560 | 561 | m_alpha_fx=m_alpha_fxparm=0; 562 | m_alpha_fxcap=0; 563 | m_alphatrack_flipmode=0; 564 | m_alphatrack_nfingers=0; 565 | m_alphatrack_fingerposcenter=-1; 566 | m_alphatrack_fingerpos=-1; 567 | m_vol_lastpos=-1000; 568 | 569 | m_fader_touchstate=0; 570 | 571 | m_tranz_shiftstate=0; 572 | m_bank_offset=0; 573 | m_frameupd_lastrun=0; 574 | m_frameupd_lastrun2=0; 575 | m_arrowstates=0; 576 | m_button_states=0; 577 | m_buttonstate_lastrun=0; 578 | m_pan_lasttouch=0; 579 | memset(m_tranz_oldbuf,' ',sizeof(m_tranz_oldbuf)); 580 | m_tranz_anysolo_poop=0; 581 | 582 | //create midi hardware access 583 | m_midiin = m_midi_in_dev >= 0 ? CreateMIDIInput(m_midi_in_dev) : NULL; 584 | m_midiout = m_midi_out_dev >= 0 ? CreateThreadedMIDIOutput(CreateMIDIOutput(m_midi_out_dev,false,NULL)) : NULL; 585 | 586 | if (errStats) 587 | { 588 | if (m_midi_in_dev >=0 && !m_midiin) *errStats|=1; 589 | if (m_midi_out_dev >=0 && !m_midiout) *errStats|=2; 590 | } 591 | 592 | if (m_midiin) 593 | m_midiin->start(); 594 | 595 | } 596 | ~CSurf_AlphaTrack() 597 | { 598 | if (m_midiout) 599 | { 600 | UpdateTranzDisplay(0,"",0x20,m_tranz_oldbuf); 601 | Sleep(5); 602 | } 603 | delete m_midiout; 604 | delete m_midiin; 605 | } 606 | 607 | 608 | const char *GetTypeString() { return "ALPHATRACK"; } 609 | const char *GetDescString() 610 | { 611 | descspace.Set("Frontier AlphaTrack"); 612 | char tmp[512]; 613 | sprintf(tmp," (dev %d,%d)",m_midi_in_dev,m_midi_out_dev); 614 | descspace.Append(tmp); 615 | return descspace.Get(); 616 | } 617 | const char *GetConfigString() // string of configuration data 618 | { 619 | sprintf(configtmp,"0 0 %d %d",m_midi_in_dev,m_midi_out_dev); 620 | return configtmp; 621 | } 622 | 623 | void CloseNoReset() 624 | { 625 | delete m_midiout; 626 | delete m_midiin; 627 | m_midiout=0; 628 | m_midiin=0; 629 | } 630 | 631 | void Run() 632 | { 633 | DWORD now=timeGetTime(); 634 | 635 | if (now > m_frameupd_lastrun2) 636 | { 637 | if (m_alphatrack_fingerpos >=0 && m_alphatrack_fingerposcenter>=0 && m_alphatrack_nfingers && m_alphatrack_fingerposcenter != m_alphatrack_fingerpos) 638 | { 639 | if (m_alphatrack_nfingers&2) // two fingers, seek 640 | { 641 | double dpos=m_alphatrack_fingerposcenter-m_alphatrack_fingerpos; 642 | 643 | // if (dpos<0) dpos=-pow(-dpos,0.25); 644 | // else dpos=pow(dpos,0.25); 645 | 646 | CSurf_ScrubAmt((dpos * (double)(now-m_frameupd_lastrun2))*-0.003); 647 | } 648 | else if (m_alphatrack_nfingers&1) //zoom 649 | { 650 | adjustZoom(((m_alphatrack_fingerposcenter-m_alphatrack_fingerpos) * (int)(now-m_frameupd_lastrun2))/-3000.0,0,true,*g_config_zoommode>2?0:*g_config_zoommode); 651 | // 652 | } 653 | } 654 | m_frameupd_lastrun2=now; 655 | } 656 | if (now >= m_frameupd_lastrun+(1000/max(*g_config_csurf_rate,1)) || now < m_frameupd_lastrun-250) 657 | { 658 | if (m_midiout && m_tranz_shiftstate) 659 | { 660 | m_midiout->Send(0x90,0x46,(now%1000)>200?0x7f:0,-1); 661 | } 662 | 663 | 664 | m_frameupd_lastrun=now; 665 | 666 | if (m_midiout) 667 | { 668 | if (m_tranz_anysolo_poop&1) 669 | { 670 | int bla=(now%1000)>500; 671 | if (!!(m_tranz_anysolo_poop&2) != bla) 672 | { 673 | m_tranz_anysolo_poop^=2; 674 | m_midiout->Send(0x90,0x73,bla?0x7f:0,-1); 675 | } 676 | } 677 | double pp=(GetPlayState()&1) ? GetPlayPosition() : GetCursorPosition(); 678 | char timebuf[512]; 679 | 680 | MediaTrack *t=CSurf_TrackFromID(m_bank_offset,g_csurf_mcpmode); 681 | 682 | timebuf[0]=0; 683 | 684 | if (t && (m_alpha_fxcap&1)) 685 | { 686 | // show fx/parm find 687 | strcpy(timebuf,""); 688 | 689 | if (m_alpha_fx>=TrackFX_GetCount(t)) m_alpha_fx=TrackFX_GetCount(t)-1; 690 | if (m_alpha_fx<0)m_alpha_fx=0; 691 | 692 | int np=TrackFX_GetNumParams(t,m_alpha_fx); 693 | if (m_alpha_fxparm>=np) m_alpha_fxparm=np-1; 694 | if (m_alpha_fxparm<0)m_alpha_fxparm=0; 695 | 696 | char buf[32]; 697 | buf[0]=0; 698 | TrackFX_GetParamName(t,m_alpha_fx,m_alpha_fxparm,buf,sizeof(buf)); 699 | 700 | char tmpbuf[512]; 701 | TrackFX_GetFXName(t,m_alpha_fx,tmpbuf,sizeof(tmpbuf)); 702 | char *p=tmpbuf; 703 | if (p && *p && strstr(p,":")) 704 | { 705 | p=strstr(p,":"); 706 | p++; 707 | while (*p == ' ') p++; 708 | } 709 | UpdateTranzDisplay(0,p,16,m_tranz_oldbuf); 710 | UpdateTranzDisplay(16,buf,16,m_tranz_oldbuf); 711 | } 712 | else if (t && (m_alpha_fxcap&2)) 713 | { 714 | strcpy(timebuf,""); 715 | if (m_alpha_fx>=TrackFX_GetCount(t)) m_alpha_fx=TrackFX_GetCount(t)-1; 716 | if (m_alpha_fx<0)m_alpha_fx=0; 717 | 718 | int np=TrackFX_GetNumParams(t,m_alpha_fx); 719 | if (m_alpha_fxparm>=np) m_alpha_fxparm=np-1; 720 | if (m_alpha_fxparm<0)m_alpha_fxparm=0; 721 | 722 | char buf[32]; 723 | buf[0]=0; 724 | TrackFX_GetParamName(t,m_alpha_fx,m_alpha_fxparm,buf,sizeof(buf)); 725 | double mv,mmv; 726 | double v=TrackFX_GetParam(t,m_alpha_fx,m_alpha_fxparm,&mv,&mmv); 727 | UpdateTranzDisplay(0,buf,16,m_tranz_oldbuf); 728 | timebuf[0]=0; 729 | TrackFX_FormatParamValue(t,m_alpha_fx,m_alpha_fxparm,v,timebuf,sizeof(timebuf)); 730 | if (!timebuf[0]) sprintf(timebuf,"%.3f",v); 731 | UpdateTranzDisplay(16,timebuf,16,m_tranz_oldbuf); 732 | } 733 | else 734 | { 735 | if (t == CSurf_TrackFromID(0,false)) sprintf(timebuf,"master"); 736 | else if (t) 737 | { 738 | const char *name=GetTrackInfo((INT_PTR)t,NULL); 739 | sprintf(timebuf,"%d:%.12s",m_bank_offset,name?name:""); 740 | } 741 | UpdateTranzDisplay(0,timebuf,16,m_tranz_oldbuf); 742 | 743 | format_timestr_pos(pp,timebuf,sizeof(timebuf),-1); 744 | if (t) 745 | { 746 | { 747 | int showvol=m_fader_touchstate; 748 | int showpan=m_pan_lasttouch==1; 749 | if (m_alphatrack_flipmode) 750 | { 751 | int t=showvol; 752 | showvol=showpan; 753 | showpan=t; 754 | } 755 | 756 | double vol=1.0,pan=0.0; 757 | GetTrackUIVolPan(t,&vol,&pan); 758 | 759 | if (showvol) mkvolstr(timebuf,vol); 760 | else if (showpan) mkpanstr(timebuf,pan); 761 | } 762 | } 763 | UpdateTranzDisplay(16,timebuf,16,m_tranz_oldbuf); 764 | } 765 | 766 | } 767 | } 768 | if (m_midiin) 769 | { 770 | m_midiin->SwapBufs(timeGetTime()); 771 | int l=0; 772 | MIDI_eventlist *list=m_midiin->GetReadBuf(); 773 | MIDI_event_t *evts; 774 | while ((evts=list->EnumItems(&l))) OnMIDIEvent(evts); 775 | 776 | if (m_arrowstates||m_button_states) 777 | { 778 | DWORD now=timeGetTime(); 779 | if (now >= m_buttonstate_lastrun + 100) 780 | { 781 | m_buttonstate_lastrun=now; 782 | 783 | 784 | if (m_arrowstates) 785 | { 786 | int iszoom=m_arrowstates&64; 787 | 788 | if (m_arrowstates&1) 789 | CSurf_OnArrow(0,!!iszoom); 790 | if (m_arrowstates&2) 791 | CSurf_OnArrow(1,!!iszoom); 792 | if (m_arrowstates&4) 793 | CSurf_OnArrow(2,!!iszoom); 794 | if (m_arrowstates&8) 795 | CSurf_OnArrow(3,!!iszoom); 796 | 797 | } 798 | 799 | if ((m_button_states&3) != 3) 800 | { 801 | if (m_button_states&1) 802 | { 803 | CSurf_OnRew(1); 804 | } 805 | else if (m_button_states&2) 806 | { 807 | CSurf_OnFwd(1); 808 | } 809 | } 810 | 811 | } 812 | } 813 | } 814 | } 815 | 816 | void SetTrackListChange() { } // not used 817 | 818 | #define FIXID(id) int id=CSurf_TrackToID(trackid,g_csurf_mcpmode); int oid=id; id -= m_bank_offset; 819 | 820 | void SetSurfaceVolume(MediaTrack *trackid, double volume) 821 | { 822 | FIXID(id) 823 | if (m_midiout && !id && !m_alphatrack_flipmode) 824 | { 825 | int volint=volToInt14(volume); 826 | if (m_vol_lastpos!=volint) 827 | { 828 | m_vol_lastpos=volint; 829 | m_midiout->Send(0xe0,volint&127,volint>>7,-1); 830 | } 831 | } 832 | } 833 | void SetSurfacePan(MediaTrack *trackid, double pan) 834 | { 835 | FIXID(id) 836 | if (m_midiout && !id && m_alphatrack_flipmode) 837 | { 838 | int panint=panToInt14(pan); 839 | if (m_vol_lastpos!=panint) 840 | { 841 | m_vol_lastpos=panint; 842 | m_midiout->Send(0xe0,panint&127,panint>>7,-1); 843 | } 844 | } 845 | } 846 | void SetSurfaceMute(MediaTrack *trackid, bool mute) 847 | { 848 | FIXID(id) 849 | if (m_midiout && !id) m_midiout->Send(0x90,0x10,mute?0x7f:0,-1); 850 | } 851 | void SetSurfaceSelected(MediaTrack *trackid, bool selected) 852 | { 853 | // not used 854 | } 855 | void SetSurfaceSolo(MediaTrack *trackid, bool solo) 856 | { 857 | FIXID(id) 858 | if (m_midiout) 859 | { 860 | if (!oid) m_midiout->Send(0x90, 0x73,(m_tranz_anysolo_poop=!!solo)?0x7f:0,-1); 861 | 862 | if (!id) m_midiout->Send(0x90,0x08,solo?0x7f:0,-1); 863 | } 864 | } 865 | void SetSurfaceRecArm(MediaTrack *trackid, bool recarm) 866 | { 867 | FIXID(id) 868 | if (m_midiout) 869 | { 870 | if (!id) 871 | m_midiout->Send(0x90,0x00,recarm?0x7f:0,-1); 872 | 873 | } 874 | } 875 | void SetPlayState(bool play, bool pause, bool rec) 876 | { 877 | if (m_midiout) m_midiout->Send(0x90,0x5f,rec ? 0x7f:0,-1); 878 | } 879 | void SetRepeatState(bool rep) 880 | { 881 | if (m_midiout) m_midiout->Send(0x90,0x56,rep ? 0x7f:0,-1); 882 | } 883 | 884 | void SetTrackTitle(MediaTrack *trackid, const char *title) { } 885 | 886 | bool GetTouchState(MediaTrack *trackid, int isPan) 887 | { 888 | FIXID(id) 889 | if (!id) 890 | { 891 | if (!m_alphatrack_flipmode != !isPan) 892 | { 893 | DWORD now=timeGetTime(); 894 | if (m_pan_lasttouch==1 || (now= m_pan_lasttouch-1000)) // fake touch, go for 3s after last movement 895 | { 896 | return true; 897 | } 898 | return false; 899 | } 900 | return !!m_fader_touchstate; 901 | } 902 | return false; 903 | } 904 | 905 | void SetAutoMode(int mode) { } 906 | 907 | void ResetCachedVolPanStates() 908 | { 909 | m_vol_lastpos=-1000; 910 | } 911 | void OnTrackSelection(MediaTrack *trackid) 912 | { 913 | int newpos=CSurf_TrackToID(trackid,g_csurf_mcpmode); 914 | if (newpos>=0 && newpos != m_bank_offset) 915 | { 916 | AdjustBankOffset(newpos-m_bank_offset,false); 917 | TrackList_UpdateAllExternalSurfaces(); 918 | } 919 | } 920 | 921 | bool IsKeyDown(int key) 922 | { 923 | return false; 924 | } 925 | 926 | 927 | }; 928 | 929 | 930 | static void parseParms(const char *str, int parms[4]) 931 | { 932 | parms[0]=0; 933 | parms[1]=9; 934 | parms[2]=parms[3]=-1; 935 | 936 | const char *p=str; 937 | if (p) 938 | { 939 | int x=0; 940 | while (x<4) 941 | { 942 | while (*p == ' ') p++; 943 | if ((*p < '0' || *p > '9') && *p != '-') break; 944 | parms[x++]=atoi(p); 945 | while (*p && *p != ' ') p++; 946 | } 947 | } 948 | } 949 | 950 | static IReaperControlSurface *createFunc(const char *type_string, const char *configString, int *errStats) 951 | { 952 | int parms[4]; 953 | parseParms(configString,parms); 954 | 955 | return new CSurf_AlphaTrack(parms[2],parms[3],errStats); 956 | } 957 | 958 | 959 | static WDL_DLGRET dlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 960 | { 961 | switch (uMsg) 962 | { 963 | case WM_INITDIALOG: 964 | { 965 | int parms[4]; 966 | parseParms((const char *)lParam,parms); 967 | 968 | ShowWindow(GetDlgItem(hwndDlg,IDC_EDIT1),SW_HIDE); 969 | ShowWindow(GetDlgItem(hwndDlg,IDC_EDIT1_LBL),SW_HIDE); 970 | ShowWindow(GetDlgItem(hwndDlg,IDC_EDIT2),SW_HIDE); 971 | ShowWindow(GetDlgItem(hwndDlg,IDC_EDIT2_LBL),SW_HIDE); 972 | ShowWindow(GetDlgItem(hwndDlg,IDC_EDIT2_LBL2),SW_HIDE); 973 | 974 | int n=GetNumMIDIInputs(); 975 | int x=SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_ADDSTRING,0,(LPARAM)"None"); 976 | SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_SETITEMDATA,x,-1); 977 | x=SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_ADDSTRING,0,(LPARAM)"None"); 978 | SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_SETITEMDATA,x,-1); 979 | for (x = 0; x < n; x ++) 980 | { 981 | char buf[512]; 982 | if (GetMIDIInputName(x,buf,sizeof(buf))) 983 | { 984 | int a=SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_ADDSTRING,0,(LPARAM)buf); 985 | SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_SETITEMDATA,a,x); 986 | if (x == parms[2]) SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_SETCURSEL,a,0); 987 | } 988 | } 989 | n=GetNumMIDIOutputs(); 990 | for (x = 0; x < n; x ++) 991 | { 992 | char buf[512]; 993 | if (GetMIDIOutputName(x,buf,sizeof(buf))) 994 | { 995 | int a=SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_ADDSTRING,0,(LPARAM)buf); 996 | SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_SETITEMDATA,a,x); 997 | if (x == parms[3]) SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_SETCURSEL,a,0); 998 | } 999 | } 1000 | } 1001 | break; 1002 | case WM_USER+1024: 1003 | if (wParam > 1 && lParam) 1004 | { 1005 | char tmp[512]; 1006 | 1007 | int indev=-1, outdev=-1, offs=0, size=9; 1008 | int r=SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_GETCURSEL,0,0); 1009 | if (r != CB_ERR) indev = SendDlgItemMessage(hwndDlg,IDC_COMBO2,CB_GETITEMDATA,r,0); 1010 | r=SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_GETCURSEL,0,0); 1011 | if (r != CB_ERR) outdev = SendDlgItemMessage(hwndDlg,IDC_COMBO3,CB_GETITEMDATA,r,0); 1012 | 1013 | sprintf(tmp,"0 0 %d %d",indev,outdev); 1014 | lstrcpyn((char *)lParam, tmp,wParam); 1015 | 1016 | } 1017 | break; 1018 | } 1019 | return 0; 1020 | } 1021 | 1022 | static HWND configFunc(const char *type_string, HWND parent, const char *initConfigString) 1023 | { 1024 | return CreateDialogParam(g_hInst,MAKEINTRESOURCE(IDD_SURFACEEDIT_MCU),parent,dlgProc,(LPARAM)initConfigString); 1025 | } 1026 | 1027 | 1028 | reaper_csurf_reg_t csurf_alphatrack_reg = 1029 | { 1030 | "ALPHATRACK", 1031 | "Frontier AlphaTrack", 1032 | createFunc, 1033 | configFunc, 1034 | }; --------------------------------------------------------------------------------