1
// RCS-ID: $Id: TheoSideReadingCtrolParms.h,v 1.14 2006/03/03 15:01:11 cecilios Exp $
2
//--------------------------------------------------------------------------------------
3
// LenMus Phonascus: The teacher of music
4
// Copyright (c) 2002-2006 Cecilio Salmeron
6
// This program is free software; you can redistribute it and/or modify it under the
7
// terms of the GNU General Public License as published by the Free Software Foundation;
8
// either version 2 of the License, or (at your option) any later version.
10
// This program is distributed in the hope that it will be useful, but WITHOUT ANY
11
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
12
// PARTICULAR PURPOSE. See the GNU General Public License for more details.
14
// You should have received a copy of the GNU General Public License along with this
15
// program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
16
// Fifth Floor, Boston, MA 02110-1301, USA.
18
// For any comment, suggestion or feature request, please contact the manager of
19
// the project at cecilios@users.sourceforge.net
21
//-------------------------------------------------------------------------------------
22
/*! @file TheoSideReadingCtrolParms.h
23
@brief Header file for class lmTheoSideReadingCtrolParms
24
@ingroup html_controls
30
#ifndef __THEOSIDEREADINGCTROLPARMS_H__ //to avoid nested includes
31
#define __THEOSIDEREADINGCTROLPARMS_H__
33
// For compilers that support precompilation, includes "wx/wx.h".
34
#include "wx/wxprec.h"
44
#include "ObjectParams.h"
45
#include "../exercises/ScoreConstrains.h"
46
#include "../ldp_parser/AuxString.h"
48
//! enum assigning name to the score generation settings source.
50
Four different ways for choosing the settings:
52
1. By level and lesson: Useful for what? It was necessary with old non-html
53
organization. Now for each lesson there will be an html page and the
54
score object will have all necessary information for that lesson. So method
55
3 will replace this one.
57
2. Personal settings dialog: the user selects the rithmic patterns to generate.
58
Valid only to generate simple repetitive patterns. Composer must have
59
knowledge for completing bars with rest or single notes.
61
3. Pararameters in html object: the parameters must include all necesary data.
62
Score generation based only on received fragments.
64
4. Reading notes exercises: the parameters are fixed for this exercise (parameters
65
the html object) but certain values (clefs, notes range) would need
68
Free exercises page will be based only on method 2 in coherence with its purpose
69
(free exercises, user customizable). For practising an specific level/lesson the
70
user must choose the corresponding book/page. In these pages it would be allowed
71
to customize settings by adding/removing fragments or changing clefs and note ranges.
75
/*! This class pack all parameters to set up a Side Reading exercise.
76
The contained lmScoreConstrains object has the constrains for the 'ByProgram'
77
settings mode (default mode). For other modes ('UserSettings' and 'ReadingNotes')
78
the settings must be read/setup by the TheoSideReadingCtrol object.
80
class lmTheoSideReadingCtrolParms : public lmObjectParams
83
lmTheoSideReadingCtrolParms(const wxHtmlTag& tag, int nWidth, int nHeight,
84
int nPercent, long nStyle);
85
~lmTheoSideReadingCtrolParms();
87
void AddParam(const wxHtmlTag& tag);
88
void CreateHtmlCell(wxHtmlWinParser *pHtmlParser);
91
bool AnalyzeClef(wxString sLine);
92
bool AnalyzeTime(wxString sLine);
93
bool AnalyzeKeys(wxString sLine);
94
bool AnalyzeFragments(wxString sLine);
98
// html object window attributes
100
lmScoreConstrains* m_pConstrains;
101
lmSideReadingCtrolOptions* m_pOptions;
102
wxString m_sParamErrors;
104
DECLARE_NO_COPY_CLASS(lmTheoSideReadingCtrolParms)
109
lmTheoSideReadingCtrolParms::lmTheoSideReadingCtrolParms(const wxHtmlTag& tag, int nWidth, int nHeight,
110
int nPercent, long nStyle)
111
: lmObjectParams(tag, nWidth, nHeight, nPercent)
114
// html object window attributes
115
m_nWindowStyle = nStyle;
117
// construct constrains object
118
m_pConstrains = new lmScoreConstrains();
121
m_pOptions = new lmSideReadingCtrolOptions();
124
m_sParamErrors = _T(""); //no errors
129
lmTheoSideReadingCtrolParms::~lmTheoSideReadingCtrolParms()
131
//Constrains and options will be deleted by the Ctrol. DO NOT DELETE THEM HERE
132
//IF THE CONTROL HAS BEEN CREATED
133
if (m_sParamErrors != _T("")) {
134
if (m_pConstrains) delete m_pConstrains;
135
if (m_pOptions) delete m_pOptions;
140
void lmTheoSideReadingCtrolParms::AddParam(const wxHtmlTag& tag)
142
/*! @page SideReadingCtrolParams
145
Params for lmScoreCtrol - html object type="Application/LenMusTheoSideReading"
148
optional params to include controls: (not yet implemented marked as [])
149
--------------------------------------
151
control_play Include 'play' link. Default: do not include it.
152
Value="play label|stop playing label". i.e.: "Play|Stop" Stop label
153
is optional. Default labels: "Play|Stop"
155
control_solfa Include 'solfa' link. Default: do not include it.
156
Value="side read label|stop side reading label". i.e.:
157
"Play|Stop". Stop label is optional.
158
Default labels: "Read|Stop"
160
control_settings Value="[key for storing the settings]"
161
This param forces to include the 'settings' link. The
162
key will be used both as the key for saving the user settings
163
and as a tag to select the Setting Dialog options to allow.
165
control_go_back URL, i.e.: "v2_L2_SideReading_203.htm"
168
params to set up the score composer:
169
------------------------------------
171
fragment* one param for each fragment to use
173
clef* one param for each allowed clef. It includes the pitch scope.
175
time a list of allowed time signatures, i.e.: "68,98,128"
177
key keyword "all" or a list of allowed key signatures, i.e.: "Do,Fas"
179
maxInterval a number indicating the maximum allowed interval for two consecutive notes
182
@todo: update the example
184
------------------------------------
186
<object type="Application/LenMusTheoSideReading" width="100%" height="300" border="0">
187
<param name="control" value="play">
188
<param name="label_play" value="Play|Stop">
189
<param name="control" value="solfa">
190
<param name="mode" value="PersonalSettings">
191
<param name="mode" value="NotesReading">
192
<param name="fragment" value="68,98;(n * n)(n * c +l)(g (n * c)(n * c)(n * c))">
193
<param name="fragment" value="68,98;(n * c)(n * n +l)(g (n * c)(n * c)(n * c))">
194
<param name="fragment" value="68,98;(n * n)(n * c)">
195
<param name="fragment" value="68,98;(g (n * c)(n * c)(n * c))">
196
<param name="clef" value="Sol;a3;a5">
197
<param name="clef" value="Fa4;a2;e4">
198
<param name="time" value="68,98,128">
199
<param name="key" value="all">
200
<param name="maxInterval" value="4">
207
wxString sName = wxEmptyString;
208
wxString sValue = wxEmptyString;
210
// scan name and value
211
if (!tag.HasParam(wxT("NAME"))) return; // ignore param tag if no name attribute
212
sName = tag.GetParam(_T("NAME"));
213
sName.UpperCase(); //convert to upper case
215
if (!tag.HasParam(_T("VALUE"))) return; // ignore param tag if no value attribute
218
if ( sName == _T("CONTROL_PLAY") ) {
219
m_pOptions->SetControlPlay(true, tag.GetParam(_T("VALUE")) );
223
else if ( sName == _T("CONTROL_SOLFA") ) {
224
m_pOptions->SetControlSolfa(true, tag.GetParam(_T("VALUE")) );
227
// "Go back to theory" link
228
else if ( sName == _T("CONTROL_GO_BACK") ) {
229
m_pOptions->SetGoBackURL( tag.GetParam(_T("VALUE") ));
233
else if ( sName == _T("CONTROL_SETTINGS") ) {
234
m_pOptions->SetControlSettings(true, tag.GetParam(_T("VALUE")) );
235
m_pConstrains->SetSection( tag.GetParam(_T("VALUE") ));
238
//fragments the list of fragmens to use
239
// <param name="fragment" value="68,98;(n * n)(n * c +l)(g (n * c)(n * c)(n * c))">
240
// <param name="fragment" value="68,98;(n * c)(n * n +l)(g (n * c)(n * c)(n * c))">
241
// <param name="fragment" value="68,98;(n * n)(n * c)">
242
// <param name="fragment" value="68,98;(g (n * c)(n * c)(n * c))">
244
else if ( sName == _T("FRAGMENT") ) {
245
wxString sFragments = tag.GetParam(_T("VALUE"));
246
AnalyzeFragments(sFragments);
249
//clef* one param for each allowed clef. It includes the pitch scope.
250
// <param name="clef" value="Sol;a3;a5" />
251
// <param name="clef" value="Fa4;a2;e4" />
253
else if ( sName == _T("CLEF") ) {
254
wxString sClef = tag.GetParam(_T("VALUE"));
255
if (AnalyzeClef(sClef)) {
256
m_sParamErrors += wxString::Format( wxGetTranslation(
257
_T("Invalid param value in:\n<param %s >\n")
258
_T("Invalid value = %s \n")
259
_T("Acceptable format: <Clef,LowerNote,UpperNote> \n")
260
_T("Acceptable clef values: Sol | Fa4 | Fa3 | Do4 | Do3 | Do2 | Do1 \n")
261
_T("Acceptable note pitch: c0 - c9")),
262
tag.GetAllParams(), tag.GetParam(_T("VALUE")) );
266
//time a list of allowed time signatures, i.e.: "68,98,128"
267
// <param name="time" value="68,98,128">
269
else if ( sName == _T("TIME") ) {
270
wxString sTime = tag.GetParam(_T("VALUE"));
271
if (AnalyzeTime(sTime)) {
272
m_sParamErrors += wxString::Format( wxGetTranslation(
273
_T("Invalid param value in:\n<param %s >\n")
274
_T("Invalid value = %s \n")
275
_T("Acceptable format: list of time signatures \n")),
276
tag.GetAllParams(), tag.GetParam(_T("VALUE")) );
280
//key keyword "all" or a list of allowed key signatures, i.e.: "Do,Fas"
281
// <param name="key" value="all">
283
else if ( sName == _T("KEY") ) {
284
wxString sKeys = tag.GetParam(_T("VALUE"));
285
if (AnalyzeKeys(sKeys)) {
286
m_sParamErrors += wxString::Format( wxGetTranslation(
287
_T("Invalid param value in:\n<param %s >\n")
288
_T("Invalid value = %s \n")
289
_T("Acceptable format: list of key signatures or keyword 'all' \n")),
290
tag.GetAllParams(), tag.GetParam(_T("VALUE")) );
294
//maxGroupInterval a number
295
else if ( sName == _T("MAXINTERVAL") ) {
296
wxString sMaxInterval = tag.GetParam(_T("VALUE"));
298
bool fOK = sMaxInterval.ToLong(&nMaxInterval);
299
if (!fOK || nMaxInterval < 0 ) {
300
m_sParamErrors += wxString::Format( wxGetTranslation(
301
_T("Invalid param value in:/n<param %s >/n")
302
_T("Invalid value = %s /n")
303
_T("Acceptable values: numeric, greater than 0\n") ),
304
tag.GetAllParams(), tag.GetParam(_T("VALUE")) );
307
m_pConstrains->SetMaxInterval((int)nMaxInterval);
313
m_sParamErrors += wxString::Format(
314
_("lmTheoSideReadingCtrol. Unknown param: <param %s >\n"),
315
tag.GetAllParams() );
319
void lmTheoSideReadingCtrolParms::CreateHtmlCell(wxHtmlWinParser *pHtmlParser)
321
//The <object> tag has been read. If param 'control_settings' has been specified
322
// configuration values must be loaded from the specified section key
323
m_pConstrains->LoadSettings();
325
//verify that all necessary html params has been specified
327
m_sParamErrors += m_pConstrains->Verify();
328
if (m_sParamErrors != _T("")) {
329
// there are errors: display a text box with the error message
330
pWnd = new wxTextCtrl((wxWindow*)pHtmlParser->GetWindow(), -1, m_sParamErrors,
331
wxPoint(0,0), wxSize(300, 100), wxTE_MULTILINE);
334
// create the TheoSideReadingCtrol
335
pWnd = new lmTheoSideReadingCtrol((wxWindow*)pHtmlParser->GetWindow(), -1,
336
m_pOptions, m_pConstrains, wxPoint(0,0), wxSize(m_nWidth, m_nHeight), m_nWindowStyle );
339
pHtmlParser->GetContainer()->InsertCell(new wxHtmlWidgetCell(pWnd, m_nPercent));
343
/// returns true if error
344
bool lmTheoSideReadingCtrolParms::AnalyzeClef(wxString sLine)
349
int iSemicolon = sLine.Find(_T(";"));
350
wxString sClef = sLine.Left(iSemicolon);
351
EClefType nClef = LDPNameToClef(sClef);
352
if (nClef == (EClefType)-1) return true; //error
355
sLine = sLine.Mid(iSemicolon+1);
356
iSemicolon = sLine.Find(_T(";"));
357
wxString sLowerScope = sLine.Left(iSemicolon);
360
wxString sUpperScope = sLine.Mid(iSemicolon + 1);
362
//Update information for this clef
363
lmClefConstrain* pClefs = m_pConstrains->GetClefConstrains();
364
pClefs->SetValid(nClef, true);
365
pClefs->SetLowerPitch(nClef, sLowerScope);
366
pClefs->SetUpperPitch(nClef, sUpperScope);
368
return false; //no error
372
/// returns true if error
373
bool lmTheoSideReadingCtrolParms::AnalyzeTime(wxString sLine)
375
//i.e.: "98" , "38,68,128" , "24,44"
377
//build time signatures constrains object
378
lmTimeSignConstrains* pTimeSigns = new lmTimeSignConstrains();
379
if (pTimeSigns->SetConstrains(sLine)) return true;
381
//Replace information about allowed time signatures
382
lmTimeSignConstrains* pOldTimeSigns = m_pConstrains->GetTimeSignConstrains();
384
ETimeSignature nTime;
385
for (i=lmMIN_TIME_SIGN; i <= lmMAX_TIME_SIGN; i++) {
386
nTime = (ETimeSignature)i;
387
pOldTimeSigns->SetValid(nTime, pTimeSigns->IsValid(nTime) );
391
return false; //no error
395
/// returns true if error
396
bool lmTheoSideReadingCtrolParms::AnalyzeKeys(wxString sLine)
398
//i.e.: "all" , "do,sol,fa,"
400
if (sLine == _T("all")) {
401
// allow all key signatures
402
lmKeyConstrains* pKeys = m_pConstrains->GetKeyConstrains();
404
for (i=0; i <= earmFa; i++) {
405
pKeys->SetValid((EKeySignatures)i, true);
410
//analyze and set key signatures
411
lmKeyConstrains* pKeys = m_pConstrains->GetKeyConstrains();
413
//loop to get all keys
417
while (sLine != _T("")) {
419
iColon = sLine.Find(_T(","));
421
sKey = sLine.Left(iColon);
422
sLine = sLine.Mid(iColon + 1); //skip the colon
428
nKey = LDPNameToKey(sKey);
429
if (nKey == (EKeySignatures)-1) return true;
430
pKeys->SetValid(nKey, true);
434
return false; //no error
438
/// returns true if error
439
bool lmTheoSideReadingCtrolParms::AnalyzeFragments(wxString sLine)
441
//i.e.: "24,34;(s c)(n * n)(n * s g+)(n * s )(n * c g-)(s c)"
443
//get time signatures
444
int iSemicolon = sLine.Find(_T(";"));
445
wxString sTimeSign = sLine.Left(iSemicolon);
448
wxString sFragment = sLine.Mid(iSemicolon + 1); //skip the semicolon and take the rest
450
//build time signatures constrains object
451
lmTimeSignConstrains* pTimeSigns = new lmTimeSignConstrains();
452
if (pTimeSigns->SetConstrains(sTimeSign)) {
453
m_sParamErrors += wxString::Format(_("Error in fragment. Invalid time signature list '%s'\nIn fragment: '%s'\n"),
454
sTimeSign, sFragment);
457
// verify fragment to avoid program failures
458
lmLDPParser parserLDP;
459
//! @todo strong verification
460
//lmLDPNode* pRoot = parserLDP.ParseText(sFragment);
462
if (!parserLDP.ParenthesisMatch(sFragment)) {
463
m_sParamErrors += wxString::Format(_("Invalid fragment. Unmatched parenthesis: '%s'\n"), sFragment);
466
if (sFragment.Find(_T("(g (")) != -1 || sFragment.Find(_T("(g(")) != -1) {
467
m_sParamErrors += wxString::Format(_("Invalid fragment. Old G syntax: '%s'\n"), sFragment);
472
m_pConstrains->AddFragment(pTimeSigns, sFragment);
474
return false; //no error
478
#endif // __THEOSIDEREADINGCTROLPARMS_H__