├── 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 | };
--------------------------------------------------------------------------------