1 /*
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 "CPasteChannelsDialog.h"
22
23 #include <algorithm>
24
25 #include <istring>
26
27 #include "settings.h"
28
29 #include "../backend/AAction.h"
30 #include "../backend/CActionSound.h"
31 #include "../backend/CActionParameters.h"
32 #include "../backend/ASoundClipboard.h"
33
34 #include "../backend/ActionParamMappers.h"
35
36 CPasteChannelsDialog *gPasteChannelsDialog=NULL;
37
38
39 FXDEFMAP(CPasteChannelsDialog) CPasteChannelsDialogMap[]=
40 {
41 // Message_Type ID Message_Handler
42 FXMAPFUNC(SEL_COMMAND, CPasteChannelsDialog::ID_DEFAULT_BUTTON, CPasteChannelsDialog::onDefaultButton),
43 FXMAPFUNC(SEL_COMMAND, CPasteChannelsDialog::ID_CLEAR_BUTTON, CPasteChannelsDialog::onClearButton),
44
45 FXMAPFUNC(SEL_COMMAND, CPasteChannelsDialog::ID_REPEAT_TYPE_COMBOBOX, CPasteChannelsDialog::onRepeatTypeChange),
46 };
47
48
FXIMPLEMENT(CPasteChannelsDialog,FXModalDialogBox,CPasteChannelsDialogMap,ARRAYNUMBER (CPasteChannelsDialogMap))49 FXIMPLEMENT(CPasteChannelsDialog,FXModalDialogBox,CPasteChannelsDialogMap,ARRAYNUMBER(CPasteChannelsDialogMap))
50
51
52
53 // ----------------------------------------
54
55 // ??? derive this from CActionDialog if I can so that it can have presets, maybe not possible as it is
56
57 #include "FXConstantParamValue.h"
58
59 CPasteChannelsDialog::CPasteChannelsDialog(FXWindow *mainWindow) :
60 FXModalDialogBox(mainWindow,N_("Paste Channels"),100,100,FXModalDialogBox::ftVertical,FXModalDialogBox::stShrinkWrap),
61
62 label(new FXLabel(getFrame(),_("Pasting Parameters:"),NULL,LAYOUT_CENTER_X)),
63 horzSeparator(new FXHorizontalSeparator(getFrame())),
64 topFrame(new FXHorizontalFrame(getFrame())),
65 routingContents(new FXMatrix(topFrame,2,MATRIX_BY_COLUMNS | LAYOUT_FILL_X|LAYOUT_FILL_Y)),
66 vertSeparator(new FXVerticalSeparator(topFrame)),
67 repeatFrame(new FXVerticalFrame(topFrame,LAYOUT_CENTER_X))
68 {
69 // setup the repeat type controls
70
71 repeatTypeSwitcher=new FXSwitcher(repeatFrame,LAYOUT_CENTER_X);
72
73 repeatCountSlider=new FXConstantParamValue(
74 new CActionParamMapper_linear_bipolar(1.0,4,100),
75 false,
76 repeatTypeSwitcher,
77 LAYOUT_CENTER_X,_("Repeat Count")
78 );
79 repeatCountSlider->setUnits("x");
80
81 repeatTimeSlider=new FXConstantParamValue(
82 new CActionParamMapper_linear_bipolar(10.0,60,3600),
83 false,
84 repeatTypeSwitcher,
85 LAYOUT_CENTER_X,_("Repeat Time")
86 );
87 repeatTimeSlider->setUnits("s");
88
89 repeatTypeSwitcher->setCurrent(0);
90
91 repeatTypeComboBox=new FXComboBox(repeatFrame,0,this,ID_REPEAT_TYPE_COMBOBOX,COMBOBOX_NORMAL|COMBOBOX_STATIC | FRAME_SUNKEN|FRAME_THICK | LAYOUT_CENTER_X);
92 repeatTypeComboBox->setNumVisible(2);
93 repeatTypeComboBox->appendItem(_("Repeat X Times"));
94 repeatTypeComboBox->appendItem(_("Repeat for X Seconds"));
95 repeatTypeComboBox->setCurrentItem(0);
96
97
98
99 getFrame()->setVSpacing(1);
100 getFrame()->setHSpacing(1);
101
102 // add clear and default buffers, and the dropdown list for choosing the mix type
103 FXPacker *buttonPacker=new FXHorizontalFrame((/*this cast might cause a problem in the future*/FXComposite *)(getFrame()->getParent()),LAYOUT_FILL_X | FRAME_RAISED|FRAME_THICK);
104 new FXButton(buttonPacker,_("Default"),NULL,this,ID_DEFAULT_BUTTON,BUTTON_NORMAL|LAYOUT_CENTER_Y);
105 new FXButton(buttonPacker,_("Clear"),NULL,this,ID_CLEAR_BUTTON,BUTTON_NORMAL|LAYOUT_CENTER_Y);
106 mixTypeFrame=new FXHorizontalFrame(buttonPacker,LAYOUT_CENTER_X|LAYOUT_CENTER_Y);
107 new FXLabel(mixTypeFrame,_("Mix Type:"),NULL,LAYOUT_CENTER_Y);
108 mixTypeComboBox=new FXComboBox(mixTypeFrame,16,NULL,0, COMBOBOX_NORMAL|FRAME_SUNKEN|FRAME_THICK | COMBOBOX_STATIC | LAYOUT_CENTER_Y);
109 mixTypeComboBox->setNumVisible(4);
110 mixTypeComboBox->appendItem(_("Add"),(void *)mmAdd);
111 mixTypeComboBox->appendItem(_("Subtract"),(void *)mmSubtract);
112 mixTypeComboBox->appendItem(_("Multiply"),(void *)mmMultiply);
113 mixTypeComboBox->appendItem(_("Average"),(void *)mmAverage);
114
115
116 new FXLabel(routingContents,"");
117 sourceLabel=new FXLabel(routingContents,_("Clipboard"),NULL,LAYOUT_CENTER_X);
118 destinationLabel=new FXLabel(routingContents,_("Destination"),NULL,LAYOUT_CENTER_Y);
119 checkBoxMatrix=new FXMatrix(routingContents,MAX_CHANNELS+1,MATRIX_BY_COLUMNS | LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 0,0,0,0, 0,0);
120
121 // put top source labels
122 new FXLabel(checkBoxMatrix,"");
123 for(unsigned t=0;t<MAX_CHANNELS;t++)
124 new FXLabel(checkBoxMatrix,(_("Channel ")+istring(t)).c_str());
125
126 for(unsigned t=0;t<MAX_CHANNELS;t++)
127 {
128 // put side destination label
129 new FXLabel(checkBoxMatrix,(_("Channel ")+istring(t)).c_str(),NULL,LAYOUT_RIGHT);
130
131 // built a row of check boxes
132 for(unsigned col=0;col<MAX_CHANNELS;col++)
133 new FXCheckButton(checkBoxMatrix,"",NULL,0,CHECKBUTTON_NORMAL | LAYOUT_CENTER_X);
134 }
135
136 }
137
~CPasteChannelsDialog()138 CPasteChannelsDialog::~CPasteChannelsDialog()
139 {
140 }
141
show(CActionSound * _actionSound,CActionParameters * actionParameters)142 bool CPasteChannelsDialog::show(CActionSound *_actionSound,CActionParameters *actionParameters)
143 {
144 actionSound=_actionSound; // save for use in the reset and default handler buttons
145
146 const ASoundClipboard *clipboard=AAction::clipboards[gWhichClipboard];
147 if(clipboard->isEmpty())
148 return false;
149
150 // only show the checkboxes that matter
151 for(unsigned row=0;row<MAX_CHANNELS;row++)
152 for(unsigned col=0;col<MAX_CHANNELS;col++)
153 {
154 FXCheckButton *cb=(FXCheckButton *)checkBoxMatrix->childAtRowCol(row+1,col+1);
155
156 cb->enable();
157
158 if(row<actionSound->sound->getChannelCount() && col<clipboard->getChannelCount())
159 cb->show();
160 else
161 cb->hide();
162
163 // let it show, but disabled since there is no data for that channel in the clipboard
164 if(!clipboard->getWhichChannels()[col])
165 cb->disable();
166 }
167
168 // show/hide labels across the top that matter
169 for(unsigned col=0;col<MAX_CHANNELS;col++)
170 {
171 if(col<clipboard->getChannelCount())
172 checkBoxMatrix->childAtRowCol(0,col+1)->show();
173 else
174 checkBoxMatrix->childAtRowCol(0,col+1)->hide();
175 }
176
177 // show/hide labels on the left that matter
178 for(unsigned row=0;row<MAX_CHANNELS;row++)
179 {
180 if(row<actionSound->sound->getChannelCount())
181 checkBoxMatrix->childAtRowCol(row+1,0)->show();
182 else
183 checkBoxMatrix->childAtRowCol(row+1,0)->hide();
184 }
185
186 // by default check a 1:1 paste mapping
187 onDefaultButton(NULL,0,NULL);
188
189 // if there is only one checkbox, then make it checked and hide it and the labels
190 if(actionSound->sound->getChannelCount()==1 && clipboard->getChannelCount()==1)
191 {
192 ((FXCheckButton *)(checkBoxMatrix->childAtRowCol(1,1)))->setCheck(true);
193 routingContents->hide();
194 vertSeparator->hide();
195 }
196 else
197 {
198 routingContents->show();
199 vertSeparator->show();
200 }
201
202 // when the number of hidden and shown widgets change, the matrix needs to be told to recalc
203 checkBoxMatrix->recalc();
204
205 if(execute(PLACEMENT_CURSOR))
206 {
207 pasteChannels.clear();
208
209 actionParameters->setValue<unsigned>(_("MixMethod"),(uintptr_t)(mixTypeComboBox->getItemData(mixTypeComboBox->getCurrentItem())));
210
211 if(repeatTypeComboBox->getCurrentItem()==0)
212 { // repeating it a given number of times
213 actionParameters->setValue<double>(_("Repeat Count"),repeatCountSlider->getValue());
214 }
215 else
216 { // repeating it for a given number of seconds
217 actionParameters->setValue<double>(_("Repeat Count"),
218 (double)( (sample_fpos_t)repeatTimeSlider->getValue() * actionSound->sound->getSampleRate() / clipboard->getLength(actionSound->sound->getSampleRate()) )
219 );
220 }
221
222 bool ret=false; // or all the checks together, if they're all false, it's like hitting cancel
223 for(unsigned row=0;row<MAX_CHANNELS;row++)
224 {
225 pasteChannels.push_back(vector<bool>());
226 actionSound->doChannel[row]=false; // set doChannel for backend's crossfading's sake
227 for(unsigned col=0;col<MAX_CHANNELS;col++)
228 {
229 FXCheckButton *cb=(FXCheckButton *)checkBoxMatrix->childAtRowCol(row+1,col+1);
230 pasteChannels[row].push_back(cb->shown() ? cb->getCheck() : false);
231 ret|=pasteChannels[row][col];
232 actionSound->doChannel[row]|=pasteChannels[row][col]; // set doChannel for backend's crossfading's sake
233 }
234 }
235
236 return ret;
237 }
238 return false;
239
240 }
241
hide()242 void CPasteChannelsDialog::hide()
243 {
244 FXModalDialogBox::hide();
245 }
246
getUserData()247 void *CPasteChannelsDialog::getUserData()
248 {
249 return(&pasteChannels);
250 }
251
252
onDefaultButton(FXObject * sender,FXSelector sel,void * ptr)253 long CPasteChannelsDialog::onDefaultButton(FXObject *sender,FXSelector sel,void *ptr)
254 {
255 for(unsigned row=0;row<MAX_CHANNELS;row++)
256 for(unsigned col=0;col<MAX_CHANNELS;col++)
257 {
258 FXCheckButton *cb=(FXCheckButton *)checkBoxMatrix->childAtRowCol(row+1,col+1);
259 cb->setCheck(FALSE);
260 }
261
262 for(unsigned t=0;t<actionSound->sound->getChannelCount();t++)
263 {
264 FXCheckButton *cb=(FXCheckButton *)checkBoxMatrix->childAtRowCol(t+1,t+1);
265 if(cb->shown() && cb->isEnabled())
266 cb->setCheck(TRUE);
267 }
268
269 return 1;
270 }
271
onClearButton(FXObject * sender,FXSelector sel,void * ptr)272 long CPasteChannelsDialog::onClearButton(FXObject *sender,FXSelector sel,void *ptr)
273 {
274 for(unsigned row=0;row<MAX_CHANNELS;row++)
275 for(unsigned col=0;col<MAX_CHANNELS;col++)
276 {
277 FXCheckButton *cb=(FXCheckButton *)checkBoxMatrix->childAtRowCol(row+1,col+1);
278 cb->setCheck(FALSE);
279 }
280
281 return 1;
282 }
283
onRepeatTypeChange(FXObject * sender,FXSelector sel,void * ptr)284 long CPasteChannelsDialog::onRepeatTypeChange(FXObject *sender,FXSelector sel,void *ptr)
285 {
286 repeatTypeSwitcher->setCurrent(repeatTypeComboBox->getCurrentItem());
287 return 1;
288 }
289