1 /* vim:nowrap
2 * Copyright (C) 2002 - David W. Durham
3 *
4 * This file is part of ReZound, an audio editing application.
5 *
6 * ReZound is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2 of the License,
9 * or (at your option) any later version.
10 *
11 * ReZound is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 */
20
21 #include "CMainWindow.h"
22
23 #include <stdexcept>
24 #include <algorithm>
25 #include <map>
26 #include <string>
27 #include <stdint.h>
28
29 #include <CPath.h>
30
31 #include "CActionMenuCommand.h"
32
33 #include "CSoundFileManager.h"
34
35 #include <CNestedDataFile/CNestedDataFile.h>
36 #include "settings.h"
37
38 #include "CFOXIcons.h"
39
40 #include "CAboutDialog.h"
41
42 #include "../backend/main_controls.h"
43
44 #include "../backend/CLoadedSound.h"
45 #include "../backend/AAction.h"
46 #include "../backend/ASoundClipboard.h"
47
48 #include "../backend/CSoundPlayerChannel.h"
49
50 #include "../backend/File/COpenAudioFileAction.h"
51
52 #include "CSoundWindow.h"
53
54 #include "CMetersWindow.h"
55
56 #include "CUserNotesDialog.h"
57 #include "CCrossfadeEdgesDialog.h"
58
59 #include "CKeyBindingsDialog.h"
60
61 #include "rememberShow.h"
62
63 #define RECORDING_MACRO_TIMER_INTERVAL 1000
64
65 extern void enableAutoRepeat(void *display,bool enable); // QQQ defined in main.cpp
66
67 /* TODO:
68 * - it is necesary for the owner to specifically delete the FXMenuPane objects it creates
69 */
70
71 FXDEFMAP(CMainWindow) CMainWindowMap[]=
72 {
73 //Message_Type ID Message_Handler
74 FXMAPFUNC(SEL_CLOSE, 0, CMainWindow::onQuit),
75
76 // file actions
77 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_REOPEN_FILE, CMainWindow::onFileAction),
78 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_CLOSE_FILE, CMainWindow::onFileAction),
79 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_REVERT_FILE, CMainWindow::onFileAction),
80
81 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_RECORD_MACRO, CMainWindow::onFileAction),
82 FXMAPFUNC(SEL_TIMEOUT, CMainWindow::ID_RECORDING_MACRO_TIMER, CMainWindow::onRecordingMacroTimer),
83
84 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_EDIT_USERNOTES, CMainWindow::onFileAction),
85
86 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SHOW_ABOUT, CMainWindow::onFileAction),
87
88 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SETUP_KEY_BINDINGS, CMainWindow::onSetupKeyBindings),
89
90 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_QUIT, CMainWindow::onQuit),
91
92
93 // play/record/transport controls
94 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_RECORD, CMainWindow::onControlAction),
95
96 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_PLAY_ALL_ONCE, CMainWindow::onControlAction),
97 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_PLAY_ALL_LOOPED, CMainWindow::onControlAction),
98 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_PLAY_SELECTION_ONCE, CMainWindow::onControlAction),
99 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_PLAY_SELECTION_START_TO_END, CMainWindow::onControlAction),
100 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_PLAY_SELECTION_LOOPED, CMainWindow::onControlAction),
101 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_PLAY_SELECTION_LOOPED_SKIP_MOST, CMainWindow::onControlAction),
102 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_PLAY_SELECTION_LOOPED_GAP_BEFORE_REPEAT,CMainWindow::onControlAction),
103 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_PLAY_LEFT_EDGE_OF_SCREEN_TO_END, CMainWindow::onControlAction),
104
105 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_STOP, CMainWindow::onControlAction),
106 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_PAUSE, CMainWindow::onControlAction),
107
108 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_JUMP_TO_BEGINNING, CMainWindow::onControlAction),
109 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_JUMP_TO_SELECTION_START, CMainWindow::onControlAction),
110
111 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_JUMP_TO_NEXT_CUE, CMainWindow::onControlAction),
112 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_JUMP_TO_PREV_CUE, CMainWindow::onControlAction),
113
114 FXMAPFUNC(SEL_LEFTBUTTONRELEASE, CMainWindow::ID_SHUTTLE_DIAL, CMainWindow::onShuttleReturn),
115 FXMAPFUNC(SEL_RIGHTBUTTONRELEASE, CMainWindow::ID_SHUTTLE_DIAL, CMainWindow::onShuttleReturn),
116 FXMAPFUNC(SEL_CHANGED, CMainWindow::ID_SHUTTLE_DIAL, CMainWindow::onShuttleChange),
117 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SHUTTLE_DIAL_SPRING_BUTTON, CMainWindow::onShuttleDialSpringButton),
118 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SHUTTLE_DIAL_SCALE_BUTTON, CMainWindow::onShuttleDialScaleButton),
119
120 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SHUTTLE_RETURN, CMainWindow::onShuttleReturn),
121 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SHUTTLE_BACKWARD, CMainWindow::onKeyboardShuttle),
122 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SHUTTLE_INCREASE_RATE, CMainWindow::onKeyboardShuttle),
123 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SHUTTLE_FORWARD, CMainWindow::onKeyboardShuttle),
124
125 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_FIND_SELECTION_START, CMainWindow::onControlAction),
126 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_FIND_SELECTION_STOP, CMainWindow::onControlAction),
127
128 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_ZOOM_IN, CMainWindow::onControlAction),
129 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_ZOOM_FIT_SELECTION, CMainWindow::onControlAction),
130 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_ZOOM_OUT, CMainWindow::onControlAction),
131 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_ZOOM_OUT_FULL, CMainWindow::onControlAction),
132
133 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_TOGGLE_LEVEL_METERS, CMainWindow::onControlAction),
134 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_TOGGLE_STEREO_PHASE_METERS, CMainWindow::onControlAction),
135 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_TOGGLE_FREQUENCY_ANALYZER, CMainWindow::onControlAction),
136
137 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_UNDO_EDIT, CMainWindow::onControlAction),
138 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_CLEAR_UNDO_HISTORY, CMainWindow::onControlAction),
139
140 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_REDRAW, CMainWindow::onControlAction),
141
142 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_DEFRAG_MENUITEM, CMainWindow::onDebugButton),
143 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_PRINT_SAT_MENUITEM, CMainWindow::onDebugButton),
144 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_VERIFY_SAT_MENUITEM, CMainWindow::onDebugButton),
145
146 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_FOLLOW_PLAY_POSITION_TOGGLE, CMainWindow::onFollowPlayPositionButton),
147
148 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_RENDER_CLIPPING_WARNING_TOGGLE, CMainWindow::onRenderClippingWarningButton),
149
150 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_DRAW_VERTICAL_CUE_POSITIONS_TOGGLE, CMainWindow::onDrawVerticalCuePositionsButton),
151
152 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_CROSSFADE_EDGES_COMBOBOX, CMainWindow::onCrossfadeEdgesComboBox),
153 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_CROSSFADE_EDGES_SETTINGS_BUTTON, CMainWindow::onCrossfadeEdgesSettings),
154
155 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_CLIPBOARD_COMBOBOX, CMainWindow::onClipboardComboBox),
156
157 FXMAPFUNC(SEL_CHANGED, CMainWindow::ID_SOUND_LIST, CMainWindow::onSoundListChange),
158
159 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SOUND_LIST_HOTKEY_PREV, CMainWindow::onSoundListHotKey),
160 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SOUND_LIST_HOTKEY1, CMainWindow::onSoundListHotKey),
161 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SOUND_LIST_HOTKEY2, CMainWindow::onSoundListHotKey),
162 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SOUND_LIST_HOTKEY3, CMainWindow::onSoundListHotKey),
163 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SOUND_LIST_HOTKEY4, CMainWindow::onSoundListHotKey),
164 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SOUND_LIST_HOTKEY5, CMainWindow::onSoundListHotKey),
165 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SOUND_LIST_HOTKEY6, CMainWindow::onSoundListHotKey),
166 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SOUND_LIST_HOTKEY7, CMainWindow::onSoundListHotKey),
167 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SOUND_LIST_HOTKEY8, CMainWindow::onSoundListHotKey),
168 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SOUND_LIST_HOTKEY9, CMainWindow::onSoundListHotKey),
169 FXMAPFUNC(SEL_COMMAND, CMainWindow::ID_SOUND_LIST_HOTKEY10, CMainWindow::onSoundListHotKey),
170
171 FXMAPFUNC(SEL_KEYPRESS, CMainWindow::ID_SOUND_LIST, CMainWindow::onHotKeyFocusFixup),
172 FXMAPFUNC(SEL_KEYPRESS, CMainWindow::ID_CROSSFADE_EDGES_COMBOBOX, CMainWindow::onHotKeyFocusFixup),
173 FXMAPFUNC(SEL_KEYPRESS, CMainWindow::ID_CLIPBOARD_COMBOBOX, CMainWindow::onHotKeyFocusFixup),
174
175 FXMAPFUNC(SEL_KEYPRESS, 0, CMainWindow::onKeyPress),
176 FXMAPFUNC(SEL_KEYRELEASE, 0, CMainWindow::onKeyRelease),
177 FXMAPFUNC(SEL_ENTER, 0, CMainWindow::onMouseEnter),
178 };
179
FXIMPLEMENT(CMainWindow,FXMainWindow,CMainWindowMap,ARRAYNUMBER (CMainWindowMap))180 FXIMPLEMENT(CMainWindow,FXMainWindow,CMainWindowMap,ARRAYNUMBER(CMainWindowMap))
181
182 #include "drawPortion.h" // for backgroundColor
183
184 #include "custom_cursors.h"
185
186 CMainWindow::CMainWindow(FXApp* a) :
187 FXMainWindow(a,"ReZound",FOXIcons->icon_logo_32,FOXIcons->icon_logo_16,DECOR_ALL,10,20,799,600, 0,0,0,0, 0,0),
188 shuttleFont(NULL),
189 soundListFont(NULL),
190 soundListHeaderFont(NULL),
191
192 playMouseCursor(NULL),
193 addCueMouseCursor(NULL),
194
195 toggleLevelMetersMenuItem(NULL),
196 toggleStereoPhaseMetersMenuItem(NULL),
197 toggleFrequencyAnalyzerMenuItem(NULL)
198 {
199 // I'm aware of these two memory leaks, but I'm not concerned
200 playMouseCursor=new FXCursor(a,bytesToBits(playMouseCursorSource,16*16),bytesToBits(playMouseCursorMask,16*16),16,16,14,8);
201 playMouseCursor->create();
202 addCueMouseCursor=new FXCursor(a,bytesToBits(addCueMouseCursorSource,16*16),bytesToBits(addCueMouseCursorMask,16*16),16,16,8,14);
203 addCueMouseCursor->create();
204
205
206 FXFontDesc d;
207
208 menubar=new FXMenuBar(this,LAYOUT_SIDE_TOP|LAYOUT_FILL_X|FRAME_RAISED|FRAME_THICK,0,0,0,0, 0,0,0,0);
209 dummymenu=new FXMenuPane(this);
210
211 contents=new FXVerticalFrame(this,LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 0,0,0,0, 1,0);
212
213 metersWindow=new CMetersWindow(contents);
214
215 FXPacker *s,*t,*u;
216
217 s=new FXHorizontalFrame(contents,LAYOUT_FILL_X|FRAME_RAISED|FRAME_THICK, 0,0,0,0, 0,0,0,0, 2,0);
218
219 #define BUTTON_STYLE FRAME_RAISED|LAYOUT_EXPLICIT
220 // build play control buttons
221 FXPacker *playControlsFrame=new FXPacker(new FXPacker(s,LAYOUT_FILL_Y,0,0,0,0, 4,4,2,2),LAYOUT_FILL_Y|LAYOUT_FIX_WIDTH, 0,0,(32*5)+10/*+10 to make room for 'semitones'*/,0, 0,0,0,0, 0,0);
222 #define PLAY_CONTROLS_BUTTON_STYLE BUTTON_STYLE
223 new FXButton(playControlsFrame,FXString("\t")+_("Play All Once"),FOXIcons->play_all_once,this,ID_PLAY_ALL_ONCE,PLAY_CONTROLS_BUTTON_STYLE, 32,0,32,32);
224 new FXButton(playControlsFrame,FXString("\t")+_("Play Selection Once"),FOXIcons->play_selection_once,this,ID_PLAY_SELECTION_ONCE,PLAY_CONTROLS_BUTTON_STYLE, 32+32,0,32,32);
225 new FXButton(playControlsFrame,FXString("\t")+_("Play From Selection Start to End"),FOXIcons->play_selection_start_to_end,this,ID_PLAY_SELECTION_START_TO_END,PLAY_CONTROLS_BUTTON_STYLE, 32+32+32,0,32,32);
226 new FXButton(playControlsFrame,FXString("\t")+_("Play From Left Edge of Screen to End"),FOXIcons->play_screen,this,ID_PLAY_LEFT_EDGE_OF_SCREEN_TO_END,PLAY_CONTROLS_BUTTON_STYLE, 32+32+32+32,0,32,32);
227 new FXButton(playControlsFrame,FXString("\t")+_("Play All Looped"),FOXIcons->play_all_looped,this,ID_PLAY_ALL_LOOPED,PLAY_CONTROLS_BUTTON_STYLE, 32,32,32,32);
228 new FXButton(playControlsFrame,FXString("\t")+_("Play Selection Looped"),FOXIcons->play_selection_looped,this,ID_PLAY_SELECTION_LOOPED,PLAY_CONTROLS_BUTTON_STYLE, 32+32,32,32,32);
229 new FXButton(playControlsFrame,FXString("\t")+_("Play Selection Looped but Skip Most of the Middle"),FOXIcons->play_selection_looped_skip_most,this,ID_PLAY_SELECTION_LOOPED_SKIP_MOST,PLAY_CONTROLS_BUTTON_STYLE, 32+32+32,32,32,32);
230 new FXButton(playControlsFrame,FXString("\t")+_("Play Selection Looped and Play a Gap Before Repeating"),FOXIcons->play_selection_looped_gap_before_repeat,this,ID_PLAY_SELECTION_LOOPED_GAP_BEFORE_REPEAT,PLAY_CONTROLS_BUTTON_STYLE, 32+32+32+32,32,32,32);
231
232 new FXButton(playControlsFrame,FXString("\t")+_("Stop"),FOXIcons->stop,this,ID_STOP,PLAY_CONTROLS_BUTTON_STYLE, 0,0,32,32),
233 new FXButton(playControlsFrame,FXString("\t")+_("Pause"),FOXIcons->pause,this,ID_PAUSE,PLAY_CONTROLS_BUTTON_STYLE, 0,32,32,32),
234
235 new FXButton(playControlsFrame,FXString("\t")+_("Record"),FOXIcons->record,this,ID_RECORD,PLAY_CONTROLS_BUTTON_STYLE, 32+32+32+32,32+32,32,32),
236
237 new FXButton(playControlsFrame,FXString("\t")+_("Jump to Beginning"),FOXIcons->jump_to_beginning,this,ID_JUMP_TO_BEGINNING,PLAY_CONTROLS_BUTTON_STYLE, 0,32+32,32+32,16);
238 new FXButton(playControlsFrame,FXString("\t")+_("Jump to Start Position"),FOXIcons->jump_to_selection,this,ID_JUMP_TO_SELECTION_START,PLAY_CONTROLS_BUTTON_STYLE, 32+32,32+32,32+32,16);
239
240 new FXButton(playControlsFrame,FXString("\t")+_("Jump to Previous Cue"),FOXIcons->jump_to_previous_q,this,ID_JUMP_TO_PREV_CUE,PLAY_CONTROLS_BUTTON_STYLE, 0,32+32+16,32+32,16);
241 new FXButton(playControlsFrame,FXString("\t")+_("Jump to Next Cue"),FOXIcons->jump_to_next_q,this,ID_JUMP_TO_NEXT_CUE,PLAY_CONTROLS_BUTTON_STYLE, 32+32,32+32+16,32+32,16);
242
243 // shuttle controls
244 t=new FXHorizontalFrame(playControlsFrame,FRAME_NONE | LAYOUT_FIX_X|LAYOUT_FIX_Y, 0,32+32+16+16,0,0, 0,0,0,0, 0,0);
245 u=new FXVerticalFrame(t,FRAME_NONE, 0,0,0,0, 0,0,0,0, 0,0);
246
247 shuttleFont=getApp()->getNormalFont();
248 shuttleFont->getFontDesc(d);
249 d.weight=FONTWEIGHT_LIGHT;
250 d.size=65;
251 shuttleFont=new FXFont(getApp(),d);
252
253 shuttleDial=new FXDial(u,this,ID_SHUTTLE_DIAL,DIAL_HORIZONTAL|DIAL_HAS_NOTCH|LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT|LAYOUT_CENTER_Y, 0,0,32+32+32+32,20);
254 shuttleDial->setRange(-((shuttleDial->getWidth())/2),(shuttleDial->getWidth())/2);
255 shuttleDial->setRevolutionIncrement(shuttleDial->getWidth()*2-1);
256 shuttleDial->setTipText(_("Shuttle Seek While Playing\n(right-click to return to middle)"));
257
258 shuttleLabel=new FXLabel(u,"1x",NULL,LAYOUT_FILL_X | JUSTIFY_CENTER_X, 0,0,0,0, 0,0,0,0);
259 shuttleLabel->setFont(shuttleFont);
260
261 u=new FXVerticalFrame(t,FRAME_NONE,0,0,0,0, 0,0,0,0, 0,0);
262 shuttleDialSpringButton=new FXToggleButton(u,_("free"),_("spring"),NULL,NULL,this,ID_SHUTTLE_DIAL_SPRING_BUTTON,LAYOUT_FILL_X|LAYOUT_SIDE_TOP | JUSTIFY_NORMAL | TOGGLEBUTTON_TOOLBAR | FRAME_RAISED,0,0,0,0, 1,1,0,0);
263 shuttleDialSpringButton->setTipText(_("Set the Shuttle Wheel to Spring Back to the Middle or Not"));
264 shuttleDialSpringButton->setState(true);
265 shuttleDialSpringButton->setFont(shuttleFont);
266
267 shuttleDialScaleButton=new FXButton(u,FXString("100x\t")+_("Set the Maximum Rate Change of the Shuttle Wheel"),NULL,this,ID_SHUTTLE_DIAL_SCALE_BUTTON,LAYOUT_FILL_X|LAYOUT_SIDE_TOP | JUSTIFY_NORMAL | TOGGLEBUTTON_TOOLBAR | FRAME_RAISED,0,0,0,0, 1,1,0,0);
268 shuttleDialScaleButton->setFont(shuttleFont);
269
270 new FXVerticalSeparator(s);
271
272 // build miscellaneous buttons
273 FXPacker *miscControlsFrame=new FXPacker(new FXPacker(s,LAYOUT_FILL_Y,0,0,0,0, 4,4,2,2),LAYOUT_FILL_Y|LAYOUT_FILL_X, 0,0,0,0, 0,0,0,0, 3,2);
274 //t=new FXHorizontalFrame(miscControlsFrame,0, 0,0,0,0, 0,0,0,0);
275 followPlayPositionButton=new FXCheckButton(miscControlsFrame,_("Follow Play Position"),this,ID_FOLLOW_PLAY_POSITION_TOGGLE);
276 followPlayPositionButton->setPadLeft(0); followPlayPositionButton->setPadRight(0); followPlayPositionButton->setPadTop(0); followPlayPositionButton->setPadBottom(0);
277 renderClippingWarningButton=new FXCheckButton(miscControlsFrame,_("Clipping Warning"),this,ID_RENDER_CLIPPING_WARNING_TOGGLE);
278 renderClippingWarningButton->setPadLeft(0); renderClippingWarningButton->setPadRight(0); renderClippingWarningButton->setPadTop(0); renderClippingWarningButton->setPadBottom(0);
279 drawVerticalCuePositionsButton=new FXCheckButton(miscControlsFrame,_("Draw Vertical Cue Positions"),this,ID_DRAW_VERTICAL_CUE_POSITIONS_TOGGLE);
280 drawVerticalCuePositionsButton->setPadLeft(0); drawVerticalCuePositionsButton->setPadRight(0); drawVerticalCuePositionsButton->setPadTop(0); drawVerticalCuePositionsButton->setPadBottom(0);
281 t=new FXHorizontalFrame(miscControlsFrame,0, 0,0,0,0, 0,0,0,0);
282 crossfadeEdgesComboBox=new FXComboBox(t,8,this,ID_CROSSFADE_EDGES_COMBOBOX, FRAME_SUNKEN|FRAME_THICK | COMBOBOX_NORMAL|COMBOBOX_STATIC | LAYOUT_CENTER_Y);
283 crossfadeEdgesComboBox->setNumVisible(3);
284 crossfadeEdgesComboBox->setTipText(_("After Most Actions a Crossfade can be Performed at the Start and Stop \nPositions to Give a Smoother Transition in to and out of the Modified Selection"));
285 crossfadeEdgesComboBox->appendItem(_("No Crossfade"));
286 crossfadeEdgesComboBox->appendItem(_("Crossfade Inner Edges"));
287 crossfadeEdgesComboBox->appendItem(_("Crossfade Outer Edges"));
288 crossfadeEdgesComboBox->setCurrentItem(0);
289 new FXButton(t,FXString("...\t")+_("Change Crossfade Times"),NULL,this,ID_CROSSFADE_EDGES_SETTINGS_BUTTON, BUTTON_NORMAL & ~FRAME_THICK);
290 clipboardComboBox=new FXComboBox(miscControlsFrame,8,this,ID_CLIPBOARD_COMBOBOX, FRAME_SUNKEN|FRAME_THICK | COMBOBOX_NORMAL|COMBOBOX_STATIC);
291 clipboardComboBox->setNumVisible(8);
292
293 // have to 'create' both icons before using them
294 FOXIcons->OffLED1->create();
295 FOXIcons->RedLED1->create();
296
297 recordMacroButton=new FXButton(miscControlsFrame,(_("Record Macro")+string(" ")).c_str(),FOXIcons->OffLED1,this,ID_RECORD_MACRO, BUTTON_NORMAL|ICON_BEFORE_TEXT);
298
299
300 new FXVerticalSeparator(s);
301
302 // build sound list
303 t=new FXPacker(s,LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 4,4,2,3, 0,0);
304 t=new FXPacker(t,LAYOUT_FILL_X|LAYOUT_FILL_Y | FRAME_SUNKEN|FRAME_THICK, 0,0,0,0, 0,0,0,0, 0,0);
305 soundList=new FXIconList(t,this,ID_SOUND_LIST,HSCROLLER_NEVER|ICONLIST_BROWSESELECT|LAYOUT_FILL_X|LAYOUT_FILL_Y);
306
307 soundListFont=getApp()->getNormalFont();
308 shuttleFont->getFontDesc(d);
309 d.weight=FONTWEIGHT_NORMAL;
310 d.size=80;
311 soundListFont=new FXFont(getApp(),d);
312
313 soundList->setFont(soundListFont);
314
315 soundListHeaderFont=getApp()->getNormalFont();
316 shuttleFont->getFontDesc(d);
317 d.weight=FONTWEIGHT_BOLD;
318 d.size=80;
319 soundListHeaderFont=new FXFont(getApp(),d);
320
321 soundList->getHeader()->setFont(soundListHeaderFont);
322 soundList->getHeader()->setPadLeft(2);
323 soundList->getHeader()->setPadRight(2);
324 soundList->getHeader()->setPadTop(0);
325 soundList->getHeader()->setPadBottom(0);
326
327 soundList->appendHeader(" #",NULL,25);
328 soundList->appendHeader("M",NULL,20);
329 soundList->appendHeader(_("Name"),NULL,200);
330 soundList->appendHeader(_("Path"),NULL,9999);
331
332 soundWindowFrame=new FXPacker(contents,LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_RAISED|FRAME_THICK,0,0,0,0, 0,0,0,0, 0,0);
333
334 reopenActionFactory=new COpenAudioFileActionFactory(NULL);
335 }
336
~CMainWindow()337 CMainWindow::~CMainWindow()
338 {
339 delete playMouseCursor;
340 delete addCueMouseCursor;
341 delete shuttleFont;
342 delete soundListFont;
343 delete soundListHeaderFont;
344 delete reopenActionFactory;
345 }
346
show()347 void CMainWindow::show()
348 {
349 FXint wantedWidth=getDefaultWidth();
350 FXint wantedHeight=getDefaultHeight();
351 rememberShow(this,"ReZound");
352 resize(max(getWidth(),wantedWidth),max(getHeight(),wantedHeight));
353
354 FXMainWindow::show();
355
356 followPlayPositionButton->setCheck(gFollowPlayPosition);
357
358 renderClippingWarningButton->setCheck(gRenderClippingWarning);
359
360 drawVerticalCuePositionsButton->setCheck(gDrawVerticalCuePositions);
361
362 if(gCrossfadeEdges>=cetNone && gCrossfadeEdges<=cetOuter)
363 crossfadeEdgesComboBox->setCurrentItem((FXint)gCrossfadeEdges);
364 else
365 crossfadeEdgesComboBox->setCurrentItem(0);
366
367
368 // populate combo box to select clipboard
369 for(size_t t=0;t<AAction::clipboards.size();t++)
370 clipboardComboBox->appendItem(AAction::clipboards[t]->getDescription().c_str());
371
372 if(gWhichClipboard>=AAction::clipboards.size())
373 gWhichClipboard=1;
374
375 clipboardComboBox->setCurrentItem(gWhichClipboard);
376
377 #if REZ_FOX_VERSION>=10119
378 dynamic_cast<FXMenuCheck *>(toggleLevelMetersMenuItem)->setCheck(gLevelMetersEnabled);
379 dynamic_cast<FXMenuCheck *>(toggleStereoPhaseMetersMenuItem)->setCheck(gStereoPhaseMetersEnabled);
380 dynamic_cast<FXMenuCheck *>(toggleFrequencyAnalyzerMenuItem)->setCheck(gFrequencyAnalyzerEnabled);
381 #else // older than 1.1.19 used FXMenuCommand
382 if(gLevelMetersEnabled)
383 toggleLevelMetersMenuItem->check();
384 if(gStereoPhaseMetersEnabled)
385 toggleStereoPhaseMetersMenuItem->check();
386 if(gFrequencyAnalyzerEnabled)
387 toggleFrequencyAnalyzerMenuItem->check();
388 #endif
389
390 }
391
hide()392 void CMainWindow::hide()
393 {
394 rememberHide(this,"ReZound");
395 FXMainWindow::hide();
396 }
397
rebuildSoundWindowList()398 void CMainWindow::rebuildSoundWindowList()
399 {
400 FXint xpos,ypos;
401 soundList->getPosition(xpos,ypos);
402
403 soundList->clearItems();
404 for(size_t t=0;t<gSoundFileManager->getOpenedCount();t++)
405 {
406 CSoundWindow *win=gSoundFileManager->getSoundWindow(t);
407
408 // add to sound window list
409 CPath p(win->loadedSound->getFilename());
410
411 soundList->appendItem(
412 (
413 istring(t+1,2,false)+"\t"+
414 (win->loadedSound->sound->isModified() ? "*" : "")+"\t"+
415 p.baseName()+"\t"+
416 p.dirName()
417 ).c_str(),
418 NULL,NULL,win);
419 }
420
421 soundList->forceRefresh();
422
423 soundList->setPosition(xpos,ypos); // scroll to the same position we were at before
424
425 // if it isn't visible make the active sound visible in the sound list
426 CSoundWindow *active=gSoundFileManager->getActiveWindow();
427 if(active!=NULL)
428 {
429 for(FXint t=0;t<soundList->getNumItems();t++)
430 {
431 if(soundList->getItemData(t)==(void *)active)
432 {
433 soundList->setCurrentItem(t);
434 soundList->makeItemVisible(t);
435 break;
436 }
437 }
438 }
439
440 }
441
onSoundListChange(FXObject * sender,FXSelector sel,void * ptr)442 long CMainWindow::onSoundListChange(FXObject *sender,FXSelector sel,void *ptr)
443 {
444 intptr_t index=(intptr_t)ptr;
445
446 if(index>=0 && index<soundList->getNumItems())
447 {
448 ((CSoundWindow *)soundList->getItemData(index))->setActiveState(true);
449
450 if(AActionFactory::macroRecorder.isRecording())
451 {
452 Warning(_("You have changed the selected audio file while a macro is being recorded to position: ")+istring(index+1)+"\n\n"+_("Note that when the macro is played back the audio file loaded in the same position in the loaded sounds list will be selected at this step in the macro."));
453 AActionFactory::macroRecorder.pushActiveSoundChange(index);
454 }
455 }
456
457
458 return 1;
459 }
460
461 extern CSoundWindow *previousActiveWindow;
onSoundListHotKey(FXObject * sender,FXSelector _sel,void * ptr)462 long CMainWindow::onSoundListHotKey(FXObject *sender,FXSelector _sel,void *ptr)
463 {
464 FXEvent *ev=(FXEvent *)ptr;
465 int sel=FXSELID(_sel);
466
467 if(sel==ID_SOUND_LIST_HOTKEY_PREV)
468 { // switch to previously active window
469 if(previousActiveWindow!=NULL)
470 {
471 int index=0;
472 for(;index<soundList->getNumItems();index++)
473 { // find the index in the sound list of the previous active window so we can set the current item
474 if(((CSoundWindow *)soundList->getItemData(index))==previousActiveWindow)
475 break;
476 }
477 soundList->setCurrentItem(index);
478 soundList->makeItemVisible(soundList->getCurrentItem());
479 return onSoundListChange(NULL,0,(void *)index);
480 }
481 return 1;
482 }
483 else
484 {
485 FXint index=0;
486 switch(sel) // not assuming enum assigned continous increasing values (although it would probably be a safe assumption)
487 {
488 case ID_SOUND_LIST_HOTKEY1: index=0; break;
489 case ID_SOUND_LIST_HOTKEY2: index=1; break;
490 case ID_SOUND_LIST_HOTKEY3: index=2; break;
491 case ID_SOUND_LIST_HOTKEY4: index=3; break;
492 case ID_SOUND_LIST_HOTKEY5: index=4; break;
493 case ID_SOUND_LIST_HOTKEY6: index=5; break;
494 case ID_SOUND_LIST_HOTKEY7: index=6; break;
495 case ID_SOUND_LIST_HOTKEY8: index=7; break;
496 case ID_SOUND_LIST_HOTKEY9: index=8; break;
497 case ID_SOUND_LIST_HOTKEY10: index=9; break;
498 default: return 0;
499 }
500
501 if(index<soundList->getNumItems())
502 {
503 soundList->setCurrentItem(index);
504 soundList->makeItemVisible(soundList->getCurrentItem());
505 return onSoundListChange(NULL,0,(void *)index);
506 }
507 else
508 return 0;
509 }
510 }
511
512 /*
513 This handler steals the key press events from the soundList FXIconList, clipboard
514 FXComboBox, and the crossfade method FXComboBox because when focused they will take
515 all my accelerator keys and search the handle them rather than pass them on to be
516 handled by the accelerator table. So, I steal all the keys except for keys like
517 up, down, tab, et al.
518
519 */
520
onHotKeyFocusFixup(FXObject * sender,FXSelector sel,void * ptr)521 long CMainWindow::onHotKeyFocusFixup(FXObject *sender,FXSelector sel,void *ptr)
522 {
523 switch(((FXEvent*)ptr)->code)
524 {
525 case KEY_Up:
526 case KEY_KP_Up:
527 case KEY_Down:
528 case KEY_KP_Down:
529
530 case KEY_Page_Up:
531 case KEY_KP_Page_Up:
532 case KEY_Page_Down:
533 case KEY_KP_Page_Down:
534
535 case KEY_Home:
536 case KEY_KP_Home:
537 case KEY_End:
538 case KEY_KP_End:
539
540 case KEY_Tab:
541 case KEY_KP_Tab:
542 return 0;
543 }
544
545 // kill the focus (so the generated event won't pass the event back to the
546 // sender), then generate a key press event to the main window, then set
547 // the focus again on the sender
548 dynamic_cast<FXWindow *>(sender)->killFocus();
549 this->handle(sender,FXSEL(SEL_KEYPRESS,0),ptr);
550 static_cast<FXWindow *>(sender)->setFocus();
551 return 1;
552 }
553
554
555
556
557
558
559 // --- stuff for handling that pressing ctrl should cause a play cursor to show on the wave canvas ---------------
560
561 // goofy.. I don't like this, but it's the easiest thing I can think to do right now.. any other way seems to be graceless or rediculus
562 #include "FXWaveCanvas.h"
setMouseCursorForFXWaveCanvas(FXWindow * p,FXCursor * cursor)563 void setMouseCursorForFXWaveCanvas(FXWindow *p,FXCursor *cursor)
564 {
565 if(dynamic_cast<FXWaveCanvas *>(p)!=NULL)
566 {
567 static_cast<FXWaveCanvas *>(p)->setDefaultCursor(cursor);
568 static_cast<FXWaveCanvas *>(p)->setDragCursor(cursor);
569 }
570 else
571 {
572 for(int t=0;t<p->numChildren();t++)
573 setMouseCursorForFXWaveCanvas(p->childAtIndex(t),cursor);
574 }
575 }
576
onKeyPress(FXObject * sender,FXSelector sel,void * ptr)577 long CMainWindow::onKeyPress(FXObject *sender,FXSelector sel,void *ptr)
578 {
579 if(((FXEvent *)ptr)->code==KEY_Control_L || ((FXEvent *)ptr)->code==KEY_Control_R)
580 // set play cursor
581 setMouseCursorForFXWaveCanvas(soundWindowFrame,playMouseCursor);
582 else if(((FXEvent *)ptr)->code==KEY_Shift_L || ((FXEvent *)ptr)->code==KEY_Shift_R)
583 // set addCue cursor
584 setMouseCursorForFXWaveCanvas(soundWindowFrame,addCueMouseCursor);
585
586 return FXMainWindow::handle(sender,sel,ptr); // behave as normal, just intercept ctrl presses
587 }
588
onKeyRelease(FXObject * sender,FXSelector sel,void * ptr)589 long CMainWindow::onKeyRelease(FXObject *sender,FXSelector sel,void *ptr)
590 {
591 if(((FXEvent *)ptr)->code==KEY_Control_L || ((FXEvent *)ptr)->code==KEY_Control_R)
592 // unset play cursor
593 setMouseCursorForFXWaveCanvas(soundWindowFrame,getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
594 else if(((FXEvent *)ptr)->code==KEY_Shift_L || ((FXEvent *)ptr)->code==KEY_Shift_R)
595 // unset addCue cursor
596 setMouseCursorForFXWaveCanvas(soundWindowFrame,getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
597
598 return FXMainWindow::handle(sender,sel,ptr); // behave as normal, just intercept ctrl releases
599 }
600
onMouseEnter(FXObject * sender,FXSelector sel,void * ptr)601 long CMainWindow::onMouseEnter(FXObject *sender,FXSelector sel,void *ptr)
602 {
603 FXint dummy;
604 FXuint keyboardModifierState;
605 getCursorPosition(dummy,dummy,keyboardModifierState);
606
607 if(keyboardModifierState&CONTROLMASK)
608 // set play cursor
609 setMouseCursorForFXWaveCanvas(soundWindowFrame,playMouseCursor);
610 else if(keyboardModifierState&SHIFTMASK)
611 // set addCue cursor
612 setMouseCursorForFXWaveCanvas(soundWindowFrame,addCueMouseCursor);
613 else
614 // unset custom cursor
615 setMouseCursorForFXWaveCanvas(soundWindowFrame,getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
616
617 return 1;
618 }
619
620 // ---------------------------------------------------------------------------------------------------------------
621
622
623
624
625
626
627 extern const string escapeAmpersand(const string i); // defined in CStatusComm.cpp
628
629 /*
630 This is the class for the reopen submenu. It intercepts calls to FXMenuPane::popup ()
631 so it can create the menu items which can change between each popup.
632 */
633 class CReopenPopup : public FXMenuPane
634 {
635 public:
CReopenPopup(FXWindow * owner)636 CReopenPopup(FXWindow *owner) :
637 FXMenuPane(owner)
638 {
639 }
640
~CReopenPopup()641 virtual ~CReopenPopup()
642 {
643 }
644
popup(FXWindow * grabto,FXint x,FXint y,FXint w=0,FXint h=0)645 virtual void popup(FXWindow* grabto, FXint x, FXint y, FXint w=0, FXint h=0)
646 {
647 // clear from previous popup
648 // I can't do this on popdown because the event won't have happened yet needing the menu item's text for the filename)
649 for(size_t t=0;t<items.size();t++)
650 delete items[t];
651 items.clear();
652
653 // create menu items
654 size_t reopenSize=gSoundFileManager->getReopenHistorySize();
655 if(reopenSize<=0)
656 return;
657 for(size_t t=0;t<reopenSize;t++)
658 {
659 FXMenuCommand *item=new FXMenuCommand(this,escapeAmpersand(gSoundFileManager->getReopenHistoryItem(t)).c_str(),NULL,getOwner(),CMainWindow::ID_REOPEN_FILE);
660 item->create();
661 items.push_back(item);
662 }
663
664 FXMenuPane::popup(grabto,x,y,w,h);
665 }
666
667 vector<FXMenuCommand *> items;
668 };
669
670 /*
671 This is the class for the recent action submenu. It intercepts calls to FXMenuPane::popup ()
672 so it can create the menu items which can change between each popup.
673 */
674 class CRecentActionsPopup : public FXMenuPane
675 {
676 public:
CRecentActionsPopup(FXWindow * owner)677 CRecentActionsPopup(FXWindow *owner) :
678 FXMenuPane(owner)
679 {
680 mainWindow=(CMainWindow *)owner;
681 }
682
~CRecentActionsPopup()683 virtual ~CRecentActionsPopup()
684 {
685 }
686
popup(FXWindow * grabto,FXint x,FXint y,FXint w=0,FXint h=0)687 virtual void popup(FXWindow* grabto, FXint x, FXint y, FXint w=0, FXint h=0)
688 {
689 // clear from previous popup
690 // I can't do this on popdown because the event won't have happened yet needing the menu item's text for the filename)
691 for(size_t t=0;t<items.size();t++)
692 delete items[t];
693 items.clear();
694
695 // create menu items
696 const vector<CActionMenuCommand *> &recentActions=mainWindow->recentActions;
697 if(recentActions.size()<=0)
698 return;
699 for(size_t t=0;t<recentActions.size();t++)
700 {
701 CActionMenuCommand *item=new CActionMenuCommand(this,*recentActions[t]);
702 item->create();
703 items.push_back(item);
704 }
705
706 FXMenuPane::popup(grabto,x,y,w,h);
707 }
708
709 vector<CActionMenuCommand *> items;
710 CMainWindow *mainWindow;
711 };
712
actionMenuCommandTriggered(CActionMenuCommand * actionMenuCommand)713 void CMainWindow::actionMenuCommandTriggered(CActionMenuCommand *actionMenuCommand)
714 {
715 for(vector<CActionMenuCommand *>::iterator i=recentActions.begin();i!=recentActions.end();i++)
716 {
717 if((*i)->getText()==actionMenuCommand->getText())
718 {
719 CActionMenuCommand *t=*i;
720 recentActions.erase(i);
721 recentActions.insert(recentActions.begin(),t);
722 return;
723 }
724 }
725
726 if(recentActions.size()>=10)
727 recentActions.pop_back();
728 recentActions.insert(recentActions.begin(),actionMenuCommand);
729 }
730
setWhichClipboard(size_t whichClipboard)731 void CMainWindow::setWhichClipboard(size_t whichClipboard)
732 {
733 if(whichClipboard<AAction::clipboards.size())
734 {
735 clipboardComboBox->setCurrentItem(whichClipboard);
736 gWhichClipboard=whichClipboard;
737 }
738 }
739
740 #include "CChannelSelectDialog.h"
741 #include "CPasteChannelsDialog.h"
742
743 #include "../backend/CActionParameters.h"
744
745 #include "../backend/CRunMacroAction.h"
746
747 #include "../backend/File/FileActions.h"
748 #include "FileActionDialogs.h"
749
750 #include "../backend/Edits/EditActions.h"
751 #include "../backend/Edits/CCueAction.h"
752 #include "EditActionDialogs.h"
753
754 #include "../backend/Effects/EffectActions.h"
755 #include "EffectActionDialogs.h"
756
757 #include "../backend/Filters/FilterActions.h"
758 #include "FilterActionDialogs.h"
759
760 #include "../backend/Looping/LoopingActions.h"
761 #include "LoopingActionDialogs.h"
762
763 #include "../backend/Remaster/RemasterActions.h"
764 #include "RemasterActionDialogs.h"
765
766 #include "../backend/Generate/GenerateActions.h"
767 #include "GenerateActionDialogs.h"
768
769 #include "../backend/LADSPA/LADSPAActions.h"
770
771
stripAmpersand(const string str)772 static const string stripAmpersand(const string str)
773 {
774 string stripped;
775 for(size_t t=0;t<str.length();t++)
776 if(str[t]!='&') stripped+=str[t];
777 return stripped;
778 }
779
stripElipsis(const string str)780 static const string stripElipsis(const string str)
781 {
782 if(str.rfind("...")==str.length()-3 && str.length()>3/*don't strip if that's the whole string*/)
783 return str.substr(0,str.length()-3);
784 return str;
785 }
786
787
788 /* the usual case -- adding a CActionMenuCommand to the menu item registry */
addToActionMap(CActionMenuCommand * item,map<const string,FXMenuCaption * > & menuItemRegistry)789 static void addToActionMap(CActionMenuCommand *item,map<const string,FXMenuCaption *> &menuItemRegistry)
790 {
791 // I use the text right off the item because I don't want to pass a separate string to addToActionMap() just for the name
792 const string strippedItemName=stripElipsis(stripAmpersand(item->getUntranslatedText()));
793 if(menuItemRegistry.find(strippedItemName)!=menuItemRegistry.end()) // something a developer would want to know
794 printf("NOTE: duplicate item name in menu item registry '%s'\n",strippedItemName.c_str());
795 menuItemRegistry[strippedItemName]=item;
796 }
797
798 /* the less usual case -- adding a general menu item to the menu item registry */
addToActionMap(const char * itemText,FXMenuCaption * item,map<const string,FXMenuCaption * > & menuItemRegistry)799 static void addToActionMap(const char *itemText,FXMenuCaption *item,map<const string,FXMenuCaption *> &menuItemRegistry)
800 { /* because I can't get the original text of the menu item with the hotkey in it, I pass it in separately and set the menuitem's text to it (prepended to what was already there).*/
801
802 // I use the text right off the item because I don't want to pass a separate string to addToActionMap() just for the name
803 const string strippedItemName=stripElipsis(stripAmpersand(string(itemText)+item->getText().text()));
804 if(menuItemRegistry.find(strippedItemName)!=menuItemRegistry.end()) // something a developer would want to know
805 printf("NOTE: duplicate item name in menu item registry '%s'\n",strippedItemName.c_str());
806
807 if(itemText[0]) // not blank
808 item->setText(gettext(itemText)+item->getText());
809
810 menuItemRegistry[strippedItemName]=item;
811 }
812
813 // this registry is used to know what menu items exist that we might set key bindings for
814 map<string,FXMenuCommand *> gKeyBindingRegistry; // ??? could make this a datamemeber
815
addActionToKeyBindingRegistery(const string name,FXMenuCommand * mc)816 void CMainWindow::addActionToKeyBindingRegistery(const string name,FXMenuCommand *mc)
817 {
818 gKeyBindingRegistry[name]=mc;
819 }
820
buildActionMap()821 void CMainWindow::buildActionMap()
822 {
823 // This initializes the menu action map, creating the collection of all available menu actions.
824 // This allows menus to be dynamically laid out using a configuration file.
825
826 // I know it's very wide, but it's (supposed to be) neat (tabs need to be set to 8 for it to look right)
827
828 // File
829 addToActionMap( new CActionMenuCommand(new CNewAudioFileActionFactory(new CNewAudioFileActionDialog(this)),dummymenu, FOXIcons->file_new), menuItemRegistry);
830 addToActionMap( new CActionMenuCommand(new COpenAudioFileActionFactory(new COpenAudioFileActionDialog(this)),dummymenu, FOXIcons->file_open), menuItemRegistry);
831 addToActionMap(N_("&Reopen"), new FXMenuCascade(dummymenu, "", FOXIcons->file_open, new CReopenPopup(this)), menuItemRegistry);
832 addToActionMap( new CActionMenuCommand(new CSaveAudioFileActionFactory,dummymenu, FOXIcons->file_save), menuItemRegistry);
833 addToActionMap( new CActionMenuCommand(new CSaveAsAudioFileActionFactory(new CSaveAsAudioFileActionDialog(this)),dummymenu, FOXIcons->file_save_as), menuItemRegistry);
834 addToActionMap( new CActionMenuCommand(new CSaveSelectionAsActionFactory(),dummymenu, FOXIcons->file_save_as), menuItemRegistry);
835 addToActionMap( new CActionMenuCommand(new CSaveAsMultipleFilesActionFactory(new CSaveAsMultipleFilesDialog(this)),dummymenu, FOXIcons->file_save_as), menuItemRegistry);
836 addToActionMap( new CActionMenuCommand(new CBurnToCDActionFactory(new CBurnToCDDialog(this)),dummymenu, FOXIcons->file_burn), menuItemRegistry);
837 // not converting close or revert to AAction classes because they pull the sound object out from under the calling code in AAction
838 addToActionMap(N_("&Close"), new FXMenuCommand(dummymenu, "", FOXIcons->file_close, this, ID_CLOSE_FILE), menuItemRegistry);
839 addToActionMap(N_("Re&vert"), new FXMenuCommand(dummymenu, "", FOXIcons->file_revert, this, ID_REVERT_FILE), menuItemRegistry);
840 // -
841 addToActionMap( new CActionMenuCommand(new CRunMacroActionFactory(new CRunMacroDialog(this)),dummymenu, NULL), menuItemRegistry);
842 addToActionMap(N_("Record Macro..."), new FXMenuCommand(dummymenu, "", FOXIcons->normal_action_buff, this, ID_RECORD_MACRO), menuItemRegistry);
843 // -
844 addToActionMap(N_("User No&tes..."), new FXMenuCommand(dummymenu, "", FOXIcons->notes, this, ID_EDIT_USERNOTES), menuItemRegistry);
845 // -
846 addToActionMap(N_("&About ReZound"), new FXMenuCommand(dummymenu, "", NULL, this, ID_SHOW_ABOUT), menuItemRegistry);
847 addToActionMap(N_("&Setup Hotkeys..."), new FXMenuCommand(dummymenu, "", NULL, this, ID_SETUP_KEY_BINDINGS), menuItemRegistry);
848 // -
849 addToActionMap("- Just for testing", new FXMenuCaption(dummymenu, ""), menuItemRegistry);
850 addToActionMap("Defrag", new FXMenuCommand(dummymenu, "", NULL, this, ID_DEFRAG_MENUITEM), menuItemRegistry);
851 addToActionMap("PrintSAT", new FXMenuCommand(dummymenu, "", NULL, this, ID_PRINT_SAT_MENUITEM), menuItemRegistry);
852 addToActionMap("VerifySAT", new FXMenuCommand(dummymenu, "", NULL, this, ID_VERIFY_SAT_MENUITEM), menuItemRegistry);
853 // -
854 addToActionMap(N_("&Quit"), new FXMenuCommand(dummymenu, "", FOXIcons->exit, this, ID_QUIT), menuItemRegistry);
855
856
857 // Control
858 addToActionMap(N_("Record..."), new FXMenuCommand(dummymenu, "", FOXIcons->small_record, this, ID_RECORD), menuItemRegistry);
859 addToActionMap(N_("Play All Once"), new FXMenuCommand(dummymenu, "", FOXIcons->small_play_all_once, this, ID_PLAY_ALL_ONCE), menuItemRegistry);
860 addToActionMap(N_("Play All Looped"), new FXMenuCommand(dummymenu, "", FOXIcons->small_play_all_looped, this, ID_PLAY_ALL_LOOPED), menuItemRegistry);
861 addToActionMap(N_("Play Selection Once"), new FXMenuCommand(dummymenu, "", FOXIcons->small_play_selection_once, this, ID_PLAY_SELECTION_ONCE), menuItemRegistry);
862 addToActionMap(N_("Play From Left Edge of Screen to End"), new FXMenuCommand(dummymenu, "", FOXIcons->small_play_screen, this, ID_PLAY_LEFT_EDGE_OF_SCREEN_TO_END), menuItemRegistry);
863 addToActionMap(N_("Play From Selection Start to End"), new FXMenuCommand(dummymenu, "", FOXIcons->small_play_selection_start_to_end, this, ID_PLAY_SELECTION_START_TO_END), menuItemRegistry);
864 addToActionMap(N_("Play Selection Looped"), new FXMenuCommand(dummymenu, "", FOXIcons->small_play_selection_looped, this, ID_PLAY_SELECTION_LOOPED), menuItemRegistry);
865 addToActionMap(N_("Loop Selection but Skip Most of the Middle"), new FXMenuCommand(dummymenu, "", FOXIcons->small_play_selection_looped_skip_most, this, ID_PLAY_SELECTION_LOOPED_SKIP_MOST), menuItemRegistry);
866 addToActionMap(N_("Loop Selection and Play a Gap Before Repeating"), new FXMenuCommand(dummymenu, "", FOXIcons->small_play_selection_looped_gap_before_repeat, this, ID_PLAY_SELECTION_LOOPED_GAP_BEFORE_REPEAT), menuItemRegistry);
867 addToActionMap(N_("Stop"), new FXMenuCommand(dummymenu, "", FOXIcons->small_stop, this, ID_STOP), menuItemRegistry);
868 addToActionMap(N_("Pause"), new FXMenuCommand(dummymenu, "", FOXIcons->small_pause, this, ID_PAUSE), menuItemRegistry);
869 // -
870 addToActionMap(N_("Jump to Beginning"), new FXMenuCommand(dummymenu, "", FOXIcons->small_jump_to_beginning, this, ID_JUMP_TO_BEGINNING), menuItemRegistry);
871 addToActionMap(N_("Jump to Selection Start"), new FXMenuCommand(dummymenu, "", FOXIcons->small_jump_to_selection, this, ID_JUMP_TO_SELECTION_START), menuItemRegistry);
872 addToActionMap(N_("Jump to Previous Cue"), new FXMenuCommand(dummymenu, "", FOXIcons->small_jump_to_previous_q, this, ID_JUMP_TO_PREV_CUE), menuItemRegistry);
873 addToActionMap(N_("Jump to Next Cue"), new FXMenuCommand(dummymenu, "", FOXIcons->small_jump_to_next_q, this, ID_JUMP_TO_NEXT_CUE), menuItemRegistry);
874 // -
875 addToActionMap(N_("Shuttle Rewind"), new FXMenuCommand(dummymenu, "", FOXIcons->shuttle_backward, this, ID_SHUTTLE_BACKWARD), menuItemRegistry);
876 addToActionMap(N_("Shuttle Amount"), new FXMenuCommand(dummymenu, "", FOXIcons->shuttle_normal, this, ID_SHUTTLE_INCREASE_RATE), menuItemRegistry);
877 addToActionMap(N_("Shuttle Forward"), new FXMenuCommand(dummymenu, "", FOXIcons->shuttle_forward, this, ID_SHUTTLE_FORWARD), menuItemRegistry);
878
879
880 // View Controls
881 addToActionMap(N_("Zoom Out F&ull"), new FXMenuCommand(dummymenu, "", FOXIcons->zoom_out_full, this, ID_ZOOM_OUT_FULL), menuItemRegistry);
882 addToActionMap(N_("Zoom &Out"), new FXMenuCommand(dummymenu, "", FOXIcons->zoom_out, this, ID_ZOOM_OUT), menuItemRegistry);
883 addToActionMap(N_("Zoom &In"), new FXMenuCommand(dummymenu, "", FOXIcons->zoom_in, this, ID_ZOOM_IN), menuItemRegistry);
884 addToActionMap(N_("Zoom &Fit Selection"), new FXMenuCommand(dummymenu, "", FOXIcons->zoom_fit, this, ID_ZOOM_FIT_SELECTION), menuItemRegistry);
885 // -
886 addToActionMap(N_("Find &Start Position"), new FXMenuCommand(dummymenu, "", FOXIcons->normal_action_buff, this, ID_FIND_SELECTION_START), menuItemRegistry);
887 addToActionMap(N_("Find Sto&p Position"), new FXMenuCommand(dummymenu, "", FOXIcons->normal_action_buff, this, ID_FIND_SELECTION_STOP), menuItemRegistry);
888 // -
889 addToActionMap(N_("&Redraw"), new FXMenuCommand(dummymenu, "", FOXIcons->normal_action_buff, this, ID_REDRAW), menuItemRegistry);
890 // -
891 #if REZ_FOX_VERSION>=10119
892 addToActionMap(N_("Toggle &Level Meters"), toggleLevelMetersMenuItem=new FXMenuCheck(dummymenu, "", this, ID_TOGGLE_LEVEL_METERS), menuItemRegistry);
893 addToActionMap(N_("Toggle &Stereo Phase Meters"), toggleStereoPhaseMetersMenuItem=new FXMenuCheck(dummymenu, "", this, ID_TOGGLE_STEREO_PHASE_METERS), menuItemRegistry);
894 addToActionMap(N_("Toggle Frequency &Analyzer"), toggleFrequencyAnalyzerMenuItem=new FXMenuCheck(dummymenu, "", this, ID_TOGGLE_FREQUENCY_ANALYZER), menuItemRegistry);
895 #else // older than 1.1.19 used FXMenuCommand
896 addToActionMap(N_("Toggle &Level Meters"), toggleLevelMetersMenuItem=new FXMenuCommand(dummymenu, "", NULL, this, ID_TOGGLE_LEVEL_METERS), menuItemRegistry);
897 addToActionMap(N_("Toggle &Stereo Phase Meters"), toggleStereoPhaseMetersMenuItem=new FXMenuCommand(dummymenu, "", NULL, this, ID_TOGGLE_STEREO_PHASE_METERS), menuItemRegistry);
898 addToActionMap(N_("Toggle Frequency &Analyzer"), toggleFrequencyAnalyzerMenuItem=new FXMenuCommand(dummymenu, "", NULL, this, ID_TOGGLE_FREQUENCY_ANALYZER), menuItemRegistry);
899 #endif
900 // -
901 addToActionMap(N_("Switch to Previously Viewed File"), new FXMenuCommand(dummymenu, "", NULL, this, ID_SOUND_LIST_HOTKEY_PREV), menuItemRegistry);
902 addToActionMap(N_("Switch to Loaded File 1"), new FXMenuCommand(dummymenu, "", NULL, this, ID_SOUND_LIST_HOTKEY1), menuItemRegistry);
903 addToActionMap(N_("Switch to Loaded File 2"), new FXMenuCommand(dummymenu, "", NULL, this, ID_SOUND_LIST_HOTKEY2), menuItemRegistry);
904 addToActionMap(N_("Switch to Loaded File 3"), new FXMenuCommand(dummymenu, "", NULL, this, ID_SOUND_LIST_HOTKEY3), menuItemRegistry);
905 addToActionMap(N_("Switch to Loaded File 4"), new FXMenuCommand(dummymenu, "", NULL, this, ID_SOUND_LIST_HOTKEY4), menuItemRegistry);
906 addToActionMap(N_("Switch to Loaded File 5"), new FXMenuCommand(dummymenu, "", NULL, this, ID_SOUND_LIST_HOTKEY5), menuItemRegistry);
907 addToActionMap(N_("Switch to Loaded File 6"), new FXMenuCommand(dummymenu, "", NULL, this, ID_SOUND_LIST_HOTKEY6), menuItemRegistry);
908 addToActionMap(N_("Switch to Loaded File 7"), new FXMenuCommand(dummymenu, "", NULL, this, ID_SOUND_LIST_HOTKEY7), menuItemRegistry);
909 addToActionMap(N_("Switch to Loaded File 8"), new FXMenuCommand(dummymenu, "", NULL, this, ID_SOUND_LIST_HOTKEY8), menuItemRegistry);
910 addToActionMap(N_("Switch to Loaded File 9"), new FXMenuCommand(dummymenu, "", NULL, this, ID_SOUND_LIST_HOTKEY9), menuItemRegistry);
911 addToActionMap(N_("Switch to Loaded File 10"), new FXMenuCommand(dummymenu, "", NULL, this, ID_SOUND_LIST_HOTKEY10), menuItemRegistry);
912
913
914 // Edit
915 addToActionMap(N_("Undo"), new FXMenuCommand(dummymenu, "", FOXIcons->edit_undo, this, ID_UNDO_EDIT), menuItemRegistry);
916 addToActionMap(N_("Clear Undo History"), new FXMenuCommand(dummymenu, "", NULL, this, ID_CLEAR_UNDO_HISTORY), menuItemRegistry);
917 // -
918 addToActionMap(N_("&Recent Actions"), new FXMenuCascade(dummymenu, "", NULL, new CRecentActionsPopup(this)), menuItemRegistry);
919 // -
920 addToActionMap( new CActionMenuCommand(new CCopyEditFactory(gChannelSelectDialog),dummymenu, FOXIcons->edit_copy), menuItemRegistry);
921 addToActionMap( new CActionMenuCommand(new CCopyToNewEditFactory(gChannelSelectDialog),dummymenu, FOXIcons->edit_copy), menuItemRegistry);
922 addToActionMap( new CActionMenuCommand(new CCutEditFactory(gChannelSelectDialog),dummymenu, FOXIcons->edit_cut), menuItemRegistry);
923 addToActionMap( new CActionMenuCommand(new CCutToNewEditFactory(gChannelSelectDialog),dummymenu, FOXIcons->edit_cut), menuItemRegistry);
924 addToActionMap( new CActionMenuCommand(new CDeleteEditFactory(gChannelSelectDialog),dummymenu, FOXIcons->edit_delete), menuItemRegistry);
925 addToActionMap( new CActionMenuCommand(new CCropEditFactory(gChannelSelectDialog),dummymenu, FOXIcons->edit_crop), menuItemRegistry);
926 // -
927 addToActionMap( new CActionMenuCommand(new CInsertPasteEditFactory(gPasteChannelsDialog),dummymenu, FOXIcons->edit_paste), menuItemRegistry);
928 addToActionMap( new CActionMenuCommand(new CReplacePasteEditFactory(gPasteChannelsDialog),dummymenu, FOXIcons->edit_paste), menuItemRegistry);
929 addToActionMap( new CActionMenuCommand(new COverwritePasteEditFactory(gPasteChannelsDialog),dummymenu, FOXIcons->edit_paste), menuItemRegistry);
930 addToActionMap( new CActionMenuCommand(new CLimitedOverwritePasteEditFactory(gPasteChannelsDialog),dummymenu, FOXIcons->edit_paste), menuItemRegistry);
931 addToActionMap( new CActionMenuCommand(new CMixPasteEditFactory(gPasteChannelsDialog),dummymenu, FOXIcons->edit_paste), menuItemRegistry);
932 addToActionMap( new CActionMenuCommand(new CLimitedMixPasteEditFactory(gPasteChannelsDialog),dummymenu, FOXIcons->edit_paste), menuItemRegistry);
933 addToActionMap( new CActionMenuCommand(new CFitMixPasteEditFactory(gPasteChannelsDialog),dummymenu, FOXIcons->edit_paste), menuItemRegistry);
934 addToActionMap( new CActionMenuCommand(new CPasteAsNewEditFactory,dummymenu, FOXIcons->edit_paste), menuItemRegistry);
935 // -
936 addToActionMap( new CActionMenuCommand(new CInsertSilenceEditFactory(gChannelSelectDialog,new CInsertSilenceDialog(this)),dummymenu, NULL), menuItemRegistry);
937 addToActionMap( new CActionMenuCommand(new CMuteEditFactory(gChannelSelectDialog),dummymenu, NULL), menuItemRegistry);
938 // -
939 addToActionMap( new CActionMenuCommand(new CAddChannelsEditFactory(new CAddChannelsDialog(this)),dummymenu, NULL), menuItemRegistry);
940 addToActionMap( new CActionMenuCommand(new CDuplicateChannelEditFactory(new CDuplicateChannelDialog(this)),dummymenu, NULL), menuItemRegistry);
941 addToActionMap( new CActionMenuCommand(new CRemoveChannelsEditFactory(gChannelSelectDialog),dummymenu, NULL), menuItemRegistry);
942 addToActionMap( new CActionMenuCommand(new CSwapChannelsEditFactory(new CSwapChannelsDialog(this)),dummymenu, NULL), menuItemRegistry);
943 // -
944 addToActionMap( new CActionMenuCommand(new CRotateLeftEditFactory(gChannelSelectDialog,new CRotateDialog(this)),dummymenu, NULL), menuItemRegistry);
945 addToActionMap( new CActionMenuCommand(new CRotateRightEditFactory(gChannelSelectDialog,new CRotateDialog(this)),dummymenu, NULL), menuItemRegistry);
946 // -
947 addToActionMap( new CActionMenuCommand(new CSelectionEditFactory(sSelectAll),dummymenu, NULL), menuItemRegistry);
948 addToActionMap( new CActionMenuCommand(new CGrowOrSlideSelectionEditFactory(new CGrowOrSlideSelectionDialog(this)),dummymenu, NULL), menuItemRegistry);
949 addToActionMap( new CActionMenuCommand(new CSelectionEditFactory(sSelectToBeginning),dummymenu, NULL), menuItemRegistry);
950 addToActionMap( new CActionMenuCommand(new CSelectionEditFactory(sSelectToEnd),dummymenu, NULL), menuItemRegistry);
951 addToActionMap( new CActionMenuCommand(new CSelectionEditFactory(sFlopToBeginning),dummymenu, NULL), menuItemRegistry);
952 addToActionMap( new CActionMenuCommand(new CSelectionEditFactory(sFlopToEnd),dummymenu, NULL), menuItemRegistry);
953 addToActionMap( new CActionMenuCommand(new CSelectionEditFactory(sSelectToSelectStart),dummymenu, NULL), menuItemRegistry);
954 addToActionMap( new CActionMenuCommand(new CSelectionEditFactory(sSelectToSelectStop),dummymenu, NULL), menuItemRegistry);
955 // -
956 addToActionMap( new CActionMenuCommand(new CAddCueWhilePlayingActionFactory,dummymenu, NULL), menuItemRegistry);
957
958
959 // Effects
960 addToActionMap( new CActionMenuCommand(new CReverseEffectFactory(gChannelSelectDialog),dummymenu, NULL), menuItemRegistry);
961 // -
962 addToActionMap( new CActionMenuCommand(new CChangeVolumeEffectFactory(gChannelSelectDialog,new CNormalVolumeChangeDialog(this)),dummymenu, NULL), menuItemRegistry);
963 addToActionMap( new CActionMenuCommand(new CSimpleGainEffectFactory(gChannelSelectDialog,new CNormalGainDialog(this)),dummymenu, NULL), menuItemRegistry);
964 addToActionMap( new CActionMenuCommand(new CCurvedGainEffectFactory(gChannelSelectDialog,new CAdvancedGainDialog(this)),dummymenu, NULL), menuItemRegistry);
965 // -
966 addToActionMap( new CActionMenuCommand(new CSimpleChangeRateEffectFactory(gChannelSelectDialog,new CNormalRateChangeDialog(this)),dummymenu, NULL), menuItemRegistry);
967 addToActionMap( new CActionMenuCommand(new CCurvedChangeRateEffectFactory(gChannelSelectDialog,new CAdvancedRateChangeDialog(this)),dummymenu, NULL), menuItemRegistry);
968 // -
969 addToActionMap( new CActionMenuCommand(new CFlangeEffectFactory(gChannelSelectDialog,new CFlangeDialog(this)),dummymenu, NULL), menuItemRegistry);
970 addToActionMap( new CActionMenuCommand(new CSimpleDelayEffectFactory(gChannelSelectDialog,new CSimpleDelayDialog(this)),dummymenu, NULL), menuItemRegistry);
971 addToActionMap( new CActionMenuCommand(new CQuantizeEffectFactory(gChannelSelectDialog,new CQuantizeDialog(this)),dummymenu, NULL), menuItemRegistry);
972 addToActionMap( new CActionMenuCommand(new CDistortionEffectFactory(gChannelSelectDialog,new CDistortionDialog(this)),dummymenu, NULL), menuItemRegistry);
973 addToActionMap( new CActionMenuCommand(new CVariedRepeatEffectFactory(gChannelSelectDialog,new CVariedRepeatDialog(this)),dummymenu, NULL), menuItemRegistry);
974
975 addToActionMap( new CActionMenuCommand(new CTestEffectFactory(gChannelSelectDialog),dummymenu, NULL), menuItemRegistry);
976
977
978 // Filter
979 addToActionMap( new CActionMenuCommand(new CConvolutionFilterFactory(gChannelSelectDialog,new CConvolutionFilterDialog(this)),dummymenu, NULL), menuItemRegistry);
980 addToActionMap( new CActionMenuCommand(new CArbitraryFIRFilterFactory(gChannelSelectDialog,new CArbitraryFIRFilterDialog(this)),dummymenu, FOXIcons->filter_custom), menuItemRegistry);
981 addToActionMap( new CActionMenuCommand(new CMorphingArbitraryFIRFilterFactory(gChannelSelectDialog,new CMorphingArbitraryFIRFilterDialog(this)),dummymenu, FOXIcons->filter_custom), menuItemRegistry);
982 // -
983 addToActionMap( new CActionMenuCommand(new CSinglePoleLowpassFilterFactory(gChannelSelectDialog,new CSinglePoleLowpassFilterDialog(this)),dummymenu, FOXIcons->filter_lowpass), menuItemRegistry);
984 addToActionMap( new CActionMenuCommand(new CSinglePoleHighpassFilterFactory(gChannelSelectDialog,new CSinglePoleHighpassFilterDialog(this)),dummymenu, FOXIcons->filter_highpass), menuItemRegistry);
985 addToActionMap( new CActionMenuCommand(new CBandpassFilterFactory(gChannelSelectDialog,new CBandpassFilterDialog(this)),dummymenu, FOXIcons->filter_bandpass), menuItemRegistry);
986 addToActionMap( new CActionMenuCommand(new CNotchFilterFactory(gChannelSelectDialog,new CNotchFilterDialog(this)),dummymenu, FOXIcons->filter_notch), menuItemRegistry);
987 // -
988 addToActionMap( new CActionMenuCommand(new CBiquadResLowpassFilterFactory(gChannelSelectDialog,new CBiquadResLowpassFilterDialog(this)),dummymenu, FOXIcons->filter_lowpass), menuItemRegistry);
989 addToActionMap( new CActionMenuCommand(new CBiquadResHighpassFilterFactory(gChannelSelectDialog,new CBiquadResHighpassFilterDialog(this)),dummymenu, FOXIcons->filter_highpass), menuItemRegistry);
990 addToActionMap( new CActionMenuCommand(new CBiquadResBandpassFilterFactory(gChannelSelectDialog,new CBiquadResBandpassFilterDialog(this)),dummymenu, FOXIcons->filter_bandpass), menuItemRegistry);
991
992
993 // Looping
994 addToActionMap( new CActionMenuCommand(new CMakeSymetricActionFactory(gChannelSelectDialog),dummymenu, NULL), menuItemRegistry);
995 // -
996 addToActionMap( new CActionMenuCommand(new CAddNCuesActionFactory(new CAddNCuesDialog(this)),dummymenu, NULL), menuItemRegistry);
997 addToActionMap( new CActionMenuCommand(new CAddTimedCuesActionFactory(new CAddTimedCuesDialog(this)),dummymenu, NULL), menuItemRegistry);
998
999
1000 // Remaster
1001 addToActionMap( new CActionMenuCommand(new CSimpleBalanceActionFactory(NULL,new CSimpleBalanceActionDialog(this)),dummymenu, NULL), menuItemRegistry);
1002 addToActionMap( new CActionMenuCommand(new CCurvedBalanceActionFactory(NULL,new CCurvedBalanceActionDialog(this)),dummymenu, NULL), menuItemRegistry);
1003 // -
1004 addToActionMap( new CActionMenuCommand(new CMonoizeActionFactory(NULL,new CMonoizeActionDialog(this)),dummymenu, NULL), menuItemRegistry);
1005 // -
1006 addToActionMap( new CActionMenuCommand(new CNoiseGateActionFactory(gChannelSelectDialog,new CNoiseGateDialog(this)),dummymenu, NULL), menuItemRegistry);
1007 addToActionMap( new CActionMenuCommand(new CCompressorActionFactory(gChannelSelectDialog,new CCompressorDialog(this)),dummymenu, NULL), menuItemRegistry);
1008 addToActionMap( new CActionMenuCommand(new CNormalizeActionFactory(gChannelSelectDialog,new CNormalizeDialog(this)),dummymenu, NULL), menuItemRegistry);
1009 addToActionMap( new CActionMenuCommand(new CAdaptiveNormalizeActionFactory(gChannelSelectDialog,new CAdaptiveNormalizeDialog(this)),dummymenu, NULL), menuItemRegistry);
1010 addToActionMap( new CActionMenuCommand(new CMarkQuietAreasActionFactory(new CMarkQuietAreasDialog(this)),dummymenu, NULL), menuItemRegistry);
1011 addToActionMap( new CActionMenuCommand(new CShortenQuietAreasActionFactory(new CShortenQuietAreasDialog(this)),dummymenu, NULL), menuItemRegistry);
1012 // -
1013 addToActionMap( new CActionMenuCommand(new CResampleActionFactory(gChannelSelectDialog,new CResampleDialog(this)),dummymenu, NULL), menuItemRegistry);
1014 addToActionMap( new CActionMenuCommand(new CChangePitchActionFactory(gChannelSelectDialog,new CChangePitchDialog(this)),dummymenu, NULL), menuItemRegistry);
1015 addToActionMap( new CActionMenuCommand(new CChangeTempoActionFactory(gChannelSelectDialog,new CChangeTempoDialog(this)),dummymenu, NULL), menuItemRegistry);
1016 // -
1017 addToActionMap( new CActionMenuCommand(new CRemoveDCActionFactory(gChannelSelectDialog),dummymenu, NULL), menuItemRegistry);
1018 addToActionMap( new CActionMenuCommand(new CInvertPhaseActionFactory(gChannelSelectDialog),dummymenu, NULL), menuItemRegistry);
1019 // -
1020 addToActionMap( new CActionMenuCommand(new CUnclipActionFactory(gChannelSelectDialog),dummymenu, NULL), menuItemRegistry);
1021
1022 // Generate
1023 addToActionMap( new CActionMenuCommand(new CGenerateNoiseActionFactory(gChannelSelectDialog,new CGenerateNoiseDialog(this)),dummymenu, NULL), menuItemRegistry);
1024 addToActionMap( new CActionMenuCommand(new CGenerateToneActionFactory(gChannelSelectDialog,new CGenerateToneDialog(this)),dummymenu, NULL), menuItemRegistry);
1025
1026
1027
1028 // These are here simply so that xgettext will add entries for these in the rezound.pot file
1029 N_("&File");
1030 N_("&Edit");
1031 N_("Selection");
1032 N_("&View");
1033 N_("&Control");
1034 N_("Effec&ts");
1035 N_("&Looping");
1036 N_("F&ilters");
1037 N_("&Remaster");
1038 N_("&Generate");
1039
1040 // create registry of all actions (for macros)
1041 gRegisteredActionFactories.clear();
1042 for(map<const string,FXMenuCaption *>::iterator i=menuItemRegistry.begin();i!=menuItemRegistry.end();i++)
1043 {
1044 if(dynamic_cast<CActionMenuCommand *>(i->second)!=NULL)
1045 {
1046 gRegisteredActionFactories[i->first]=((CActionMenuCommand *)i->second)->getActionFactory();
1047 }
1048 }
1049
1050 // set key bindings
1051 for(map<const string,FXMenuCaption *>::iterator i=menuItemRegistry.begin();i!=menuItemRegistry.end();i++)
1052 {
1053 if(dynamic_cast<FXMenuCommand *>(i->second)!=NULL)
1054 addActionToKeyBindingRegistery(i->first,(FXMenuCommand *)i->second);
1055 }
1056
1057 }
1058
buildMenu(FXMenuPane * menu,const CNestedDataFile * menuLayoutFile,const string menuKey,const string itemName)1059 void CMainWindow::buildMenu(FXMenuPane *menu,const CNestedDataFile *menuLayoutFile,const string menuKey,const string itemName)
1060 {
1061 if(itemName=="-")
1062 {
1063 if(menu) new FXMenuSeparator(menu);
1064 return;
1065 }
1066
1067 // if the item is a submenu item, recur for each item in it; otherwise, add as normal menu item
1068 if(menuLayoutFile->keyExists(menuKey)==CNestedDataFile::ktScope)
1069 { // add as a submenu
1070 FXMenuPane *submenu=NULL;
1071
1072 const size_t DOTCount=istring(menuKey).count(CNestedDataFile::delim);
1073 if(DOTCount==0)
1074 { // we've been passed just the layout name
1075 // this is the theorical place to create menubar, but for FOX's needs I have to create it in the constructor
1076 }
1077 else if(DOTCount==1)
1078 { // we've been passed a top-level pull-down menu name
1079 submenu=new FXMenuPane(this);
1080 new FXMenuTitle(menubar,_(itemName.c_str()),NULL,submenu);
1081 }
1082 else if(DOTCount>1)
1083 { // submenu of menu
1084 submenu=new FXMenuPane(this);
1085 new FXMenuCascade(menu,_(itemName.c_str()),NULL,submenu);
1086 }
1087
1088 const string menuItemsKey=menuKey DOT "menuitems";
1089 if(menuLayoutFile->keyExists(menuItemsKey)==CNestedDataFile::ktValue)
1090 {
1091 const vector<string> menuItems=menuLayoutFile->getValue<vector<string> >(menuItemsKey);
1092 for(size_t t=0;t<menuItems.size();t++)
1093 {
1094 const string name=menuItems[t];
1095 buildMenu(submenu,menuLayoutFile,menuKey DOT stripAmpersand(name),name);
1096 }
1097 } // else (if it's not an array) something may be screwed up in the layout definition
1098 }
1099 else
1100 { // add as normal item
1101 const string strippedItemName=stripAmpersand(itemName);
1102 if(menuItemRegistry.find(strippedItemName)!=menuItemRegistry.end())
1103 {
1104 if(menuItemRegistry[strippedItemName]->getParent()!=dummymenu) // just a check
1105 printf("NOTE: registered menu item '%s' was mapped more than once in layout; only the last one will be effective\n",strippedItemName.c_str());
1106 menuItemRegistry[strippedItemName]->reparent(menu);
1107
1108 // change menu name's caption if there is an alias defined: 'origMenuName="new menu name";' in the same scope as where menuitems is defined
1109 if(menuLayoutFile->keyExists(menuKey)==CNestedDataFile::ktValue)
1110 {
1111 FXMenuCaption *menuItem=menuItemRegistry[strippedItemName];
1112 const string alias=menuLayoutFile->getValue<string>(menuKey);
1113 menuItem->setText(gettext(alias.c_str()));
1114 }
1115 }
1116 else
1117 {
1118 if(menu)
1119 new FXMenuCommand(menu,(itemName+" (unregistered)").c_str(),NULL,this,0);
1120 else
1121 // since menu is NULL, this is a top-level menu without a defined body
1122 new FXMenuTitle(menubar,(itemName+" (no subitems defined)").c_str(),NULL,new FXMenuPane(this));
1123 }
1124 }
1125 }
1126
1127 #include <CNestedDataFile/CNestedDataFile.h>
createMenus()1128 void CMainWindow::createMenus()
1129 {
1130 buildActionMap();
1131
1132 // Try to find out which set of menu information we should load and which file contains the menu information.
1133 // The default menu layout is 'default' in .../share/.../menu.dat
1134
1135 // ??? make this a global setting instead of a lookup here
1136 // NOTE: this would be the first frontend specific global setting (but this isn't the only lookup (showAbout() also does it))
1137 string menuLayout;
1138 if(gSettingsRegistry->keyExists("MenuLayout"))
1139 menuLayout=gSettingsRegistry->getValue<string>("MenuLayout");
1140 else
1141 menuLayout="default";
1142
1143 tryAgain:
1144
1145 string menuLayoutFilename;
1146 if(menuLayout=="default")
1147 menuLayoutFilename=gSysDataDirectory+CPath::dirDelim+"menu.dat";
1148 else
1149 menuLayoutFilename=gUserDataDirectory+CPath::dirDelim+"menu.dat";
1150
1151 const CNestedDataFile *menuLayoutFile=new CNestedDataFile(menuLayoutFilename);
1152 try
1153 {
1154 if( menuLayoutFile->keyExists(menuLayout)!=CNestedDataFile::ktScope ||
1155 menuLayoutFile->keyExists(menuLayout DOT "menuitems")!=CNestedDataFile::ktValue)
1156 {
1157 Warning(menuLayout+".menuitems array does not exist in requested menu layout '"+ menuLayout+"' in '"+menuLayoutFilename+"'");
1158 menuLayout="default"; // go around again and use the default menu layout
1159 goto tryAgain;
1160 }
1161
1162 buildMenu(NULL,menuLayoutFile,menuLayout,menuLayout);
1163 delete menuLayoutFile;
1164 }
1165 catch(...)
1166 {
1167 delete menuLayoutFile;
1168 throw;
1169 }
1170
1171 // give feedback about actions that didn't get mapped to a menu on screen
1172 for(map<const string,FXMenuCaption *>::iterator i=menuItemRegistry.begin();i!=menuItemRegistry.end();i++)
1173 {
1174 if(i->second->getParent()==dummymenu)
1175 printf("NOTE: registered menu item '%s' was not mapped anywhere in '%s' in layout '%s'\n",i->first.c_str(),menuLayoutFilename.c_str(),menuLayout.c_str());
1176 }
1177
1178
1179 buildLADSPAMenus();
1180
1181 setupKeyBindings();
1182
1183 create(); // it is necessary to call create again which will call it for all new child windows
1184 }
1185
buildLADSPAMenus()1186 void CMainWindow::buildLADSPAMenus()
1187 {
1188 #ifdef USE_LADSPA
1189 // now stick the LADSPA menu in there if it needs to be
1190 // ??? (with dynamic menus, maybe let the layout define WHERE the ladspa submenu goes, (except it might not always be compiled for ladspa, so we wouldn't want to add it to the map if USE_LADSPA wasn't defined)
1191 FXMenuPane *menu=new FXMenuPane(this);
1192 new FXMenuTitle(menubar,"L&ADSPA",NULL,menu);
1193 const vector<CLADSPAActionFactory *> LADSPAActionFactories=getLADSPAActionFactories();
1194 if(LADSPAActionFactories.size()<=0)
1195 {
1196 new FXMenuCaption(menu,_("No LADSPA Plugins Found"));
1197 new FXMenuSeparator(menu);
1198 new FXMenuCaption(menu,_("Like PATH, set LADSPA_PATH to point"));
1199 new FXMenuCaption(menu,_("to a directory(s) containing LADSPA"));
1200 new FXMenuCaption(menu,_("plugin .so file at least once. Or"));
1201 new FXMenuCaption(menu,_("edit the value in ~/.rezound/registry.dat"));
1202 }
1203 else
1204 {
1205 // register all the LADSPA action so they can be used in macros
1206 for(size_t t=0;t<LADSPAActionFactories.size();t++)
1207 gRegisteredActionFactories[LADSPAActionFactories[t]->getName()]=LADSPAActionFactories[t];
1208
1209
1210 // determine number of FXMenuCaption will fit on the screen (msh -> menu screen height)
1211 const FXuint msh=(getApp()->getRootWindow()->getHeight()/(7+getApp()->getNormalFont()->getFontHeight()))-1;
1212
1213 if(LADSPAActionFactories.size()>20)
1214 {
1215 // add a submenu grouped by manufacturer
1216 map<const string,map<const string,CLADSPAActionFactory *> > makerGrouped;
1217 for(size_t t=0;t<LADSPAActionFactories.size();t++)
1218 {
1219 const string maker= LADSPAActionFactories[t]->getDescriptor()->Maker;
1220 makerGrouped[maker][LADSPAActionFactories[t]->getName()]=LADSPAActionFactories[t];
1221 }
1222
1223 if(makerGrouped.size()>1)
1224 { // more than one maker
1225 FXMenuPane *makerMenu=new FXMenuPane(this);
1226 new FXMenuCascade(menu,"By Maker",NULL,makerMenu);
1227
1228 for(map<const string,map<const string,CLADSPAActionFactory *> >::iterator i=makerGrouped.begin();i!=makerGrouped.end();i++)
1229 {
1230 #if REZ_FOX_VERSION<10142
1231 FXMenuPane *submenu=new FXMenuPane(this);
1232 #else
1233 // if menu will be vertically taller than the screen, then make the menu scrollable
1234 FXMenuPane *submenu=i->second.size()>msh ? new FXScrollPane(this,msh) : new FXMenuPane(this);
1235 #endif
1236 new FXMenuCascade(makerMenu,i->first.c_str(),NULL,submenu);
1237
1238 for(map<const string,CLADSPAActionFactory *>::iterator t=i->second.begin();t!=i->second.end();t++)
1239 {
1240 FXMenuCommand *mc=new CActionMenuCommand(t->second,submenu,NULL);
1241 addActionToKeyBindingRegistery(t->second->getName(),mc);
1242 }
1243 }
1244 }
1245
1246 new FXMenuSeparator(menu);
1247
1248
1249
1250 // group by the first letter
1251 map<const char,map<const string,CLADSPAActionFactory *> > nameGrouped;
1252 for(size_t t=0;t<LADSPAActionFactories.size();t++)
1253 {
1254 const char letter= *(istring(LADSPAActionFactories[t]->getName()).upper()).begin();
1255 nameGrouped[letter][LADSPAActionFactories[t]->getName()]=LADSPAActionFactories[t];
1256 }
1257
1258 for(map<const char,map<const string,CLADSPAActionFactory *> >::iterator i=nameGrouped.begin();i!=nameGrouped.end();i++)
1259 {
1260 #if REZ_FOX_VERSION<10142
1261 FXMenuPane *submenu=new FXMenuPane(this);
1262 #else
1263 // if menu will be vertically taller than the screen, then make the menu scrollable
1264 FXMenuPane *submenu=i->second.size()>msh ? new FXScrollPane(this,msh) : new FXMenuPane(this);
1265 #endif
1266 new FXMenuCascade(menu,string(&(i->first),1).c_str(),NULL,submenu);
1267
1268 for(map<const string,CLADSPAActionFactory *>::iterator t=i->second.begin();t!=i->second.end();t++)
1269 {
1270 FXMenuCommand *mc=new CActionMenuCommand(t->second,submenu,NULL);
1271 addActionToKeyBindingRegistery(t->second->getName(),mc);
1272 }
1273 }
1274 }
1275 else
1276 {
1277 for(size_t t=0;t<LADSPAActionFactories.size();t++)
1278 {
1279 FXMenuCommand *mc=new CActionMenuCommand(LADSPAActionFactories[t],menu,NULL);
1280 addActionToKeyBindingRegistery(LADSPAActionFactories[t]->getName(),mc);
1281 }
1282 }
1283 }
1284 #endif
1285 }
1286
1287 /* this function sets a key-binding if one has been defined for the given FXMenuCommand */
setupKeyBindings()1288 void CMainWindow::setupKeyBindings()
1289 {
1290
1291 // clear existing accelerator table (not doing this now.. see below)
1292 //delete getAccelTable();
1293 //setAccelTable(new FXAccelTable());
1294
1295 // reassign all accelerators (would prefer to wipe the slate clean before doing this, but there's no good way to restore the alt-&letter menu key bindings after doing so)
1296 for(map<string,FXMenuCommand *>::iterator i=gKeyBindingRegistry.begin(); i!=gKeyBindingRegistry.end(); i++)
1297 {
1298 const string name=i->first;
1299 FXMenuCommand *mc=i->second;
1300
1301 mc->setAccelText(""); // clear any existing accel text
1302
1303 if(gKeyBindingsStore->keyExists(name)==CNestedDataFile::ktValue)
1304 {
1305 string value=gKeyBindingsStore->getValue<string>(name);
1306 if(value=="")
1307 continue; // no key bound to this action
1308
1309 FXHotKey acckey=parseAccel(value.c_str());
1310 mc->setAccelText(value.c_str());
1311
1312 /* these shuttle controls have to be handle specially because they require key up events to return the shuttle to the middle */
1313 if(i->first=="Shuttle Forward")
1314 getAccelTable()->addAccel(acckey,this,FXSEL(SEL_COMMAND,ID_SHUTTLE_FORWARD),FXSEL(SEL_COMMAND,ID_SHUTTLE_RETURN));
1315 else if(i->first=="Shuttle Rewind")
1316 getAccelTable()->addAccel(acckey,this,FXSEL(SEL_COMMAND,ID_SHUTTLE_BACKWARD),FXSEL(SEL_COMMAND,ID_SHUTTLE_RETURN));
1317 else
1318 getAccelTable()->addAccel(acckey,mc,FXSEL(SEL_COMMAND,FXMenuCommand::ID_ACCEL));
1319 }
1320 }
1321 }
1322
onQuit(FXObject * sender,FXSelector sel,void * ptr)1323 long CMainWindow::onQuit(FXObject *sender,FXSelector sel,void *ptr)
1324 {
1325
1326 if(getApp()->getModality()==MODAL_FOR_WINDOW)
1327 { // don't allow a quit if there is a modal window showing
1328 gStatusComm->beep();
1329 return 1;
1330 }
1331
1332 if(exitReZound(gSoundFileManager))
1333 {
1334 enableAutoRepeat(getApp()->getDisplay(),true); // QQQ (didn't work just putting this after application->run() in main.cpp)
1335
1336 hide();
1337 getApp()->exit(0);
1338 }
1339 return 1;
1340 }
1341
onSetupKeyBindings(FXObject * sender,FXSelector sel,void * ptr)1342 long CMainWindow::onSetupKeyBindings(FXObject *sender,FXSelector sel,void *ptr)
1343 {
1344 // create a list of the keys that are currently bound because we need to remove those from the current accel table before assigning the new key bindings
1345 // this is done to avoid having to delete and re-create the accel table each time in setupKeyBindings() which destroys the alt-&letter key bindings that
1346 // already exist there.
1347 vector<FXHotKey> removeKeyBindingsList;
1348 const vector<string> actionsWithKeyBindings=gKeyBindingsStore->getChildKeys("");
1349 for(size_t t=0;t<actionsWithKeyBindings.size();t++)
1350 removeKeyBindingsList.push_back(parseAccel(gKeyBindingsStore->getValue<string>(actionsWithKeyBindings[t]).c_str()));
1351
1352 if(gKeyBindingsDialog->showIt(gKeyBindingRegistry))
1353 {
1354 for(size_t t=0;t<removeKeyBindingsList.size();t++)
1355 getAccelTable()->removeAccel(removeKeyBindingsList[t]);
1356
1357 setupKeyBindings();
1358 }
1359 return 1;
1360 }
1361
onFollowPlayPositionButton(FXObject * sender,FXSelector sel,void * ptr)1362 long CMainWindow::onFollowPlayPositionButton(FXObject *sender,FXSelector sel,void *ptr)
1363 {
1364 gFollowPlayPosition=followPlayPositionButton->getCheck();
1365 return 1;
1366 }
1367
onRenderClippingWarningButton(FXObject * sender,FXSelector sel,void * ptr)1368 long CMainWindow::onRenderClippingWarningButton(FXObject *sender,FXSelector sel,void *ptr)
1369 {
1370 gRenderClippingWarning=renderClippingWarningButton->getCheck();
1371 if(gSoundFileManager->getActiveWindow())
1372 gSoundFileManager->getActiveWindow()->updateFromEdit();
1373 return 1;
1374 }
1375
onDrawVerticalCuePositionsButton(FXObject * sender,FXSelector sel,void * ptr)1376 long CMainWindow::onDrawVerticalCuePositionsButton(FXObject *sender,FXSelector sel,void *ptr)
1377 {
1378 gDrawVerticalCuePositions=drawVerticalCuePositionsButton->getCheck();
1379 if(gSoundFileManager->getActiveWindow())
1380 gSoundFileManager->getActiveWindow()->updateFromEdit();
1381 return 1;
1382 }
1383
onCrossfadeEdgesComboBox(FXObject * sender,FXSelector sel,void * ptr)1384 long CMainWindow::onCrossfadeEdgesComboBox(FXObject *sender,FXSelector sel,void *ptr)
1385 {
1386 gCrossfadeEdges=(CrossfadeEdgesTypes)crossfadeEdgesComboBox->getCurrentItem();
1387 return 1;
1388 }
1389
onCrossfadeEdgesSettings(FXObject * sender,FXSelector sel,void * ptr)1390 long CMainWindow::onCrossfadeEdgesSettings(FXObject *sender,FXSelector sel,void *ptr)
1391 {
1392 gCrossfadeEdgesDialog->showIt();
1393 return 1;
1394 }
1395
1396
onClipboardComboBox(FXObject * sender,FXSelector sel,void * ptr)1397 long CMainWindow::onClipboardComboBox(FXObject *sender,FXSelector sel,void *ptr)
1398 {
1399 gWhichClipboard=clipboardComboBox->getCurrentItem();
1400 return 1;
1401 }
1402
1403
1404 // file action events
onFileAction(FXObject * sender,FXSelector sel,void * ptr)1405 long CMainWindow::onFileAction(FXObject *sender,FXSelector sel,void *ptr)
1406 {
1407 switch(FXSELID(sel))
1408 {
1409 case ID_REOPEN_FILE:
1410 {
1411 vector<string> filenames;
1412 filenames.push_back(dynamic_cast<FXMenuCommand *>(sender)->getText().text());
1413
1414 CActionParameters actionParameters(gSoundFileManager);
1415 actionParameters.setValue<vector<string> >("filenames",filenames);
1416
1417 reopenActionFactory->performAction(NULL,&actionParameters,false);
1418 break;
1419 }
1420
1421 case ID_CLOSE_FILE:
1422 if(AActionFactory::macroRecorder.isRecording())
1423 {
1424 Message(_("Cannot close a file while recording a macro"));
1425 return 1;
1426 }
1427 closeSound(gSoundFileManager);
1428 break;
1429
1430 case ID_REVERT_FILE:
1431 if(AActionFactory::macroRecorder.isRecording())
1432 {
1433 Message(_("Cannot revert a file while recording a macro"));
1434 return 1;
1435 }
1436 revertSound(gSoundFileManager);
1437 break;
1438
1439 case ID_RECORD_MACRO:
1440 recordMacro();
1441 if(AActionFactory::macroRecorder.isRecording())
1442 {
1443 recordMacroButton->setState(1);
1444 recordMacroButton->setIcon(FOXIcons->RedLED1);
1445 // start blinking LED timer
1446 getApp()->addTimeout(this,CMainWindow::ID_RECORDING_MACRO_TIMER,RECORDING_MACRO_TIMER_INTERVAL);
1447 }
1448 else
1449 {
1450 recordMacroButton->setIcon(FOXIcons->OffLED1);
1451 recordMacroButton->setState(0);
1452 }
1453 break;
1454
1455 case ID_SHOW_ABOUT:
1456 gAboutDialog->execute(PLACEMENT_SCREEN);
1457 break;
1458
1459
1460 case ID_EDIT_USERNOTES:
1461 #warning ??? make this an action?
1462 try
1463 {
1464 CLoadedSound *s=gSoundFileManager->getActive();
1465 if(s!=NULL)
1466 gUserNotesDialog->show(s,PLACEMENT_CURSOR);
1467 else
1468 getApp()->beep();
1469 }
1470 catch(exception &e)
1471 {
1472 Error(e.what());
1473 }
1474 break;
1475
1476 default:
1477 throw runtime_error(string(__func__)+" -- unhandled file button selector");
1478 }
1479 return 1;
1480 }
1481
onRecordingMacroTimer(FXObject * sender,FXSelector sel,void * ptr)1482 long CMainWindow::onRecordingMacroTimer(FXObject *sender,FXSelector sel,void *ptr)
1483 {
1484 static int counter=0;
1485 if(AActionFactory::macroRecorder.isRecording())
1486 {
1487 recordMacroButton->setIcon( (counter%2) ? FOXIcons->RedLED1 : FOXIcons->OffLED1);
1488 counter++;
1489
1490 // schedule for the next timer
1491 getApp()->addTimeout(this,CMainWindow::ID_RECORDING_MACRO_TIMER,RECORDING_MACRO_TIMER_INTERVAL);
1492 }
1493 else
1494 counter=0;
1495
1496 return 1;
1497 }
1498
1499 // play control events
onControlAction(FXObject * sender,FXSelector sel,void * ptr)1500 long CMainWindow::onControlAction(FXObject *sender,FXSelector sel,void *ptr)
1501 {
1502 switch(FXSELID(sel))
1503 {
1504 case ID_PLAY_ALL_ONCE:
1505 metersWindow->resetGrandMaxPeakLevels();
1506 play(gSoundFileManager,CSoundPlayerChannel::ltLoopNone,false);
1507 break;
1508
1509 case ID_PLAY_ALL_LOOPED:
1510 metersWindow->resetGrandMaxPeakLevels();
1511 play(gSoundFileManager,CSoundPlayerChannel::ltLoopNormal,false);
1512 break;
1513
1514 case ID_PLAY_SELECTION_ONCE:
1515 metersWindow->resetGrandMaxPeakLevels();
1516 play(gSoundFileManager,CSoundPlayerChannel::ltLoopNone,true);
1517 break;
1518
1519 case ID_PLAY_SELECTION_START_TO_END:
1520 metersWindow->resetGrandMaxPeakLevels();
1521 if(gSoundFileManager->getActive())
1522 play(gSoundFileManager,gSoundFileManager->getActive()->channel->getStartPosition());
1523 break;
1524
1525 case ID_PLAY_SELECTION_LOOPED:
1526 metersWindow->resetGrandMaxPeakLevels();
1527 play(gSoundFileManager,CSoundPlayerChannel::ltLoopNormal,true);
1528 break;
1529
1530 case ID_PLAY_SELECTION_LOOPED_SKIP_MOST:
1531 metersWindow->resetGrandMaxPeakLevels();
1532 play(gSoundFileManager,CSoundPlayerChannel::ltLoopSkipMost,true);
1533 break;
1534
1535 case ID_PLAY_SELECTION_LOOPED_GAP_BEFORE_REPEAT:
1536 metersWindow->resetGrandMaxPeakLevels();
1537 play(gSoundFileManager,CSoundPlayerChannel::ltLoopGapBeforeRepeat,true);
1538 break;
1539
1540 case ID_PLAY_LEFT_EDGE_OF_SCREEN_TO_END:
1541 if(gSoundFileManager->getActiveWindow())
1542 {
1543 metersWindow->resetGrandMaxPeakLevels();
1544 play(gSoundFileManager,gSoundFileManager->getActiveWindow()->getLeftEdgePosition());
1545 }
1546 break;
1547
1548 case ID_STOP:
1549 stop(gSoundFileManager);
1550 break;
1551
1552 case ID_PAUSE:
1553 pause(gSoundFileManager);
1554 break;
1555
1556 case ID_RECORD:
1557 if(AActionFactory::macroRecorder.isRecording())
1558 {
1559 Message(_("Cannot record audio while recording a macro"));
1560 return 1;
1561 }
1562 recordSound(gSoundFileManager);
1563 break;
1564
1565 case ID_JUMP_TO_BEGINNING:
1566 jumpToBeginning(gSoundFileManager);
1567 break;
1568
1569 case ID_JUMP_TO_SELECTION_START:
1570 jumpToStartPosition(gSoundFileManager);
1571 break;
1572
1573 case ID_JUMP_TO_PREV_CUE:
1574 jumpToPreviousCue(gSoundFileManager);
1575 break;
1576
1577 case ID_JUMP_TO_NEXT_CUE:
1578 jumpToNextCue(gSoundFileManager);
1579 break;
1580
1581
1582 case ID_UNDO_EDIT:
1583 undo(gSoundFileManager);
1584 break;
1585
1586 case ID_CLEAR_UNDO_HISTORY:
1587 clearUndoHistory(gSoundFileManager);
1588 break;
1589
1590
1591 case ID_FIND_SELECTION_START:
1592 if(gSoundFileManager->getActiveWindow())
1593 gSoundFileManager->getActiveWindow()->centerStartPos();
1594 break;
1595
1596 case ID_FIND_SELECTION_STOP:
1597 if(gSoundFileManager->getActiveWindow())
1598 gSoundFileManager->getActiveWindow()->centerStopPos();
1599 break;
1600
1601
1602 case ID_TOGGLE_LEVEL_METERS:
1603 #if REZ_FOX_VERSION>=10119
1604 metersWindow->enableLevelMeters(dynamic_cast<FXMenuCheck *>(sender)->getCheck());
1605 #else // older than 1.1.19 used FXMenuCommand
1606 if(dynamic_cast<FXMenuCommand *>(sender)->isChecked())
1607 dynamic_cast<FXMenuCommand *>(sender)->uncheck();
1608 else
1609 dynamic_cast<FXMenuCommand *>(sender)->check();
1610 metersWindow->enableLevelMeters(dynamic_cast<FXMenuCommand *>(sender)->isChecked());
1611 #endif
1612 break;
1613
1614 case ID_TOGGLE_STEREO_PHASE_METERS:
1615 #if REZ_FOX_VERSION>=10119
1616 metersWindow->enableStereoPhaseMeters(dynamic_cast<FXMenuCheck *>(sender)->getCheck());
1617 #else // older than 1.1.19 used FXMenuCommand
1618 if(dynamic_cast<FXMenuCommand *>(sender)->isChecked())
1619 dynamic_cast<FXMenuCommand *>(sender)->uncheck();
1620 else
1621 dynamic_cast<FXMenuCommand *>(sender)->check();
1622 metersWindow->enableStereoPhaseMeters(dynamic_cast<FXMenuCommand *>(sender)->isChecked());
1623 #endif
1624 break;
1625
1626 case ID_TOGGLE_FREQUENCY_ANALYZER:
1627 #if REZ_FOX_VERSION>=10119
1628 metersWindow->enableFrequencyAnalyzer(dynamic_cast<FXMenuCheck *>(sender)->getCheck());
1629 #else // older than 1.1.19 used FXMenuCommand
1630 if(dynamic_cast<FXMenuCommand *>(sender)->isChecked())
1631 dynamic_cast<FXMenuCommand *>(sender)->uncheck();
1632 else
1633 dynamic_cast<FXMenuCommand *>(sender)->check();
1634 metersWindow->enableFrequencyAnalyzer(dynamic_cast<FXMenuCommand *>(sender)->isChecked());
1635 #endif
1636 break;
1637
1638
1639 case ID_ZOOM_IN:
1640 if(gSoundFileManager->getActiveWindow())
1641 gSoundFileManager->getActiveWindow()->horzZoomInSome();
1642 break;
1643
1644 case ID_ZOOM_FIT_SELECTION:
1645 if(gSoundFileManager->getActiveWindow())
1646 gSoundFileManager->getActiveWindow()->horzZoomSelectionFit();
1647 break;
1648
1649 case ID_ZOOM_OUT:
1650 if(gSoundFileManager->getActiveWindow())
1651 gSoundFileManager->getActiveWindow()->horzZoomOutSome();
1652 break;
1653
1654 case ID_ZOOM_OUT_FULL:
1655 if(gSoundFileManager->getActiveWindow())
1656 gSoundFileManager->getActiveWindow()->horzZoomOutFull();
1657 break;
1658
1659
1660 case ID_REDRAW:
1661 if(gSoundFileManager->getActiveWindow())
1662 gSoundFileManager->getActiveWindow()->redraw();
1663 break;
1664
1665 default:
1666 throw runtime_error(string(__func__)+" -- unhandled play button selector");
1667 }
1668 return 1;
1669 }
1670
onShuttleReturn(FXObject * sender,FXSelector sel,void * ptr)1671 long CMainWindow::onShuttleReturn(FXObject *sender,FXSelector sel,void *ptr)
1672 {
1673 if(((FXEvent *)ptr)->code==LEFTBUTTON && !shuttleDialSpringButton->getState())
1674 return 1; // this wasn't a left click release and where we're in spring-back mode
1675
1676 enableAutoRepeat(getApp()->getDisplay(),true); // QQQ
1677
1678 // return shuttle control to the middle
1679 shuttleDial->setValue(0);
1680 onShuttleChange(NULL,0,NULL);
1681 return 1;
1682 }
1683
onShuttleChange(FXObject * sender,FXSelector sel,void * ptr)1684 long CMainWindow::onShuttleChange(FXObject *sender,FXSelector sel,void *ptr)
1685 {
1686 CSoundWindow *w=gSoundFileManager->getActiveWindow();
1687 if(w!=NULL)
1688 {
1689 CLoadedSound *s=w->loadedSound;
1690
1691 string labelString;
1692
1693 FXint minValue,maxValue;
1694 shuttleDial->getRange(minValue,maxValue);
1695
1696 const FXint shuttlePos=shuttleDial->getValue();
1697 float seekSpeed;
1698
1699 const string text=shuttleDialScaleButton->getText().text();
1700
1701 if(shuttlePos==0)
1702 {
1703 if(text==_("semitones"))
1704 labelString="+ 0";
1705 else
1706 labelString="1x";
1707
1708 seekSpeed=1.0;
1709 }
1710 else
1711 {
1712 if(text=="1x")
1713 { // 1x +/- (0..1]
1714 if(shuttlePos>0)
1715 seekSpeed=(double)shuttlePos/(double)maxValue;
1716 else //if(shuttlePos<0)
1717 seekSpeed=(double)-shuttlePos/(double)minValue;
1718 labelString=istring(seekSpeed,4,3)+"x";
1719 }
1720 else if(text=="2x")
1721 { // 2x +/- [1..2]
1722 if(shuttlePos>0)
1723 seekSpeed=(double)shuttlePos/(double)maxValue+1.0;
1724 else //if(shuttlePos<0)
1725 seekSpeed=(double)-shuttlePos/(double)minValue-1.0;
1726 labelString=istring(seekSpeed,3,2)+"x";
1727 }
1728 else if(text=="100x")
1729 { // 100x +/- [1..100]
1730 // I square the value to give a more useful range
1731 if(shuttlePos>0)
1732 seekSpeed=(pow((double)shuttlePos/(double)maxValue,2.0)*99.0)+1.0;
1733 else //if(shuttlePos<0)
1734 seekSpeed=(pow((double)shuttlePos/(double)minValue,2.0)*-99.0)-1.0;
1735 labelString=istring(seekSpeed,4,2)+"x";
1736 }
1737 else if(text==_("semitones"))
1738 { // semitone + [0.5..2]
1739 float semitones = round((double)shuttlePos/(double)maxValue*12); // +/- 12 semitones
1740 if(shuttlePos>0)
1741 {
1742 semitones = round((double)shuttlePos/(double)maxValue*12);
1743 seekSpeed=pow(2.0,semitones/12.0);
1744 }
1745 else //if(shuttlePos<0)
1746 {
1747 semitones = round((double)shuttlePos/(double)minValue*12);
1748 seekSpeed=pow(0.5,semitones/12.0);
1749 }
1750 labelString = (semitones>=0 ? "+" : "") + istring((int)semitones,2,false) + " ("+istring(seekSpeed,3,2)+"x)";
1751 }
1752 else
1753 throw runtime_error(string(__func__)+" -- internal error -- unhandled text for shuttleDialScaleButton: '"+text+"'");
1754 }
1755
1756 shuttleLabel->setText(labelString.c_str());
1757 w->shuttleControlScalar=shuttleDialScaleButton->getText().text();
1758 w->shuttleControlSpringBack=shuttleDialSpringButton->getState();
1759 s->channel->setSeekSpeed(seekSpeed);
1760 }
1761
1762 return 1;
1763 }
1764
positionShuttleGivenSpeed(double seekSpeed,const string shuttleControlScalar,bool springBack)1765 void CMainWindow::positionShuttleGivenSpeed(double seekSpeed,const string shuttleControlScalar,bool springBack)
1766 {
1767 FXint minValue,maxValue;
1768 shuttleDial->getRange(minValue,maxValue);
1769
1770 FXint shuttlePos;
1771 if(seekSpeed==1.0)
1772 shuttlePos=0;
1773 else
1774 {
1775 const string &text=shuttleControlScalar;
1776 if(text=="1x")
1777 {
1778 if(seekSpeed>0.0)
1779 shuttlePos=(FXint)(seekSpeed*maxValue);
1780 else //if(seekSpeed<0.0)
1781 shuttlePos=(FXint)(-seekSpeed*minValue);
1782 }
1783 else if(text=="2x")
1784 {
1785 if(seekSpeed>0.0)
1786 shuttlePos=(FXint)((seekSpeed-1.0)*maxValue);
1787 else //if(seekSpeed<0.0)
1788 shuttlePos=(FXint)(-(seekSpeed+1.0)*minValue);
1789 }
1790 else if(text=="100x")
1791 {
1792 if(seekSpeed>0.0)
1793 shuttlePos=(FXint)(maxValue*sqrt((seekSpeed-1.0)/100.0));
1794 else //if(seekSpeed<0.0)
1795 shuttlePos=(FXint)(minValue*sqrt((seekSpeed+1.0)/-100.0));
1796 }
1797 else if(text==_("semitones"))
1798 {
1799 if(seekSpeed>0.0)
1800 shuttlePos=(FXint)(log(seekSpeed)/log(2.0)*maxValue);
1801 else //if(seekSpeed<0.0)
1802 shuttlePos=(FXint)(log(seekSpeed)/log(2.0)*minValue);
1803 }
1804 else
1805 throw runtime_error(string(__func__)+" -- internal error -- unhandled text for shuttleDialScaleButton: '"+text+"'");
1806
1807 }
1808
1809 shuttleDialScaleButton->setText(shuttleControlScalar.c_str());
1810 shuttleDialSpringButton->setState(springBack);
1811 shuttleDial->setValue(shuttlePos);
1812 }
1813
onShuttleDialSpringButton(FXObject * sender,FXSelector sel,void * ptr)1814 long CMainWindow::onShuttleDialSpringButton(FXObject *sender,FXSelector sel,void *ptr)
1815 {
1816 shuttleDialSpringButton->killFocus();
1817 if(shuttleDialSpringButton->getState())
1818 {
1819 // return the shuttle control to the middle
1820 shuttleDial->setValue(0);
1821 onShuttleChange(NULL,0,NULL);
1822 }
1823 return 1;
1824 }
1825
onShuttleDialScaleButton(FXObject * sender,FXSelector sel,void * ptr)1826 long CMainWindow::onShuttleDialScaleButton(FXObject *sender,FXSelector sel,void *ptr)
1827 {
1828 shuttleDialScaleButton->killFocus();
1829 const string text=shuttleDialScaleButton->getText().text();
1830 if(text=="100x")
1831 shuttleDialScaleButton->setText("1x");
1832 else if(text=="1x")
1833 shuttleDialScaleButton->setText("2x");
1834 else if(text=="2x")
1835 shuttleDialScaleButton->setText(_("semitones"));
1836 else if(text==_("semitones"))
1837 shuttleDialScaleButton->setText("100x");
1838 else
1839 throw runtime_error(string(__func__)+" -- internal error -- unhandled text for shuttleDialScaleButton: '"+text+"'");
1840
1841 // return the shuttle control to the middle
1842 shuttleDial->setValue(0);
1843 onShuttleChange(NULL,0,NULL);
1844
1845 return 1;
1846 }
1847
onKeyboardShuttle(FXObject * sender,FXSelector sel,void * ptr)1848 long CMainWindow::onKeyboardShuttle(FXObject *sender,FXSelector sel,void *ptr)
1849 {
1850 FXint lo,hi;
1851 shuttleDial->getRange(lo,hi);
1852
1853 FXint inc= (hi-lo)/14; // 7 positions surrounding 0
1854
1855 FXint pos=shuttleDial->getValue();
1856
1857 if(pos==0 && FXSELID(sel)==ID_SHUTTLE_BACKWARD)
1858 {
1859 if((uintptr_t)ptr > 1/*came from keyboard event*/) enableAutoRepeat(getApp()->getDisplay(),false); // QQQ
1860 shuttleDial->setValue(pos-inc);
1861 onShuttleChange(sender,sel,ptr);
1862 }
1863 else if(pos==0 && FXSELID(sel)==ID_SHUTTLE_FORWARD)
1864 {
1865 if((uintptr_t)ptr > 1/*came from keyboard event*/) enableAutoRepeat(getApp()->getDisplay(),false); // QQQ
1866 shuttleDial->setValue(pos+inc);
1867 onShuttleChange(sender,sel,ptr);
1868 }
1869 else if(pos!=0 && FXSELID(sel)==ID_SHUTTLE_INCREASE_RATE)
1870 {
1871 if(pos<0)
1872 { // go more leftward
1873 shuttleDial->setValue(pos-inc);
1874 }
1875 else if(pos>0)
1876 { // go more rightward
1877 shuttleDial->setValue(pos+inc);
1878 }
1879 onShuttleChange(sender,sel,ptr);
1880 }
1881
1882 return 1;
1883 }
1884
onDebugButton(FXObject * sender,FXSelector sel,void * ptr)1885 long CMainWindow::onDebugButton(FXObject *sender,FXSelector sel,void *ptr)
1886 {
1887 CLoadedSound *s=gSoundFileManager->getActive();
1888 if(s!=NULL)
1889 {
1890 if(FXSELID(sel)==ID_DEFRAG_MENUITEM)
1891 {
1892 s->sound->defragPoolFile();
1893 gSoundFileManager->updateAfterEdit();
1894 }
1895 else if(FXSELID(sel)==ID_PRINT_SAT_MENUITEM)
1896 s->sound->printSAT();
1897 else if(FXSELID(sel)==ID_VERIFY_SAT_MENUITEM)
1898 s->sound->verifySAT();
1899 }
1900 else
1901 getApp()->beep();
1902
1903 return 1;
1904 }
1905
1906