~s-cecilio/lenmus/v5.3

« back to all changes in this revision

Viewing changes to src/html/TheoMusicReadingCtrolParms.h

  • Committer: cecilios
  • Date: 2012-09-11 16:59:18 UTC
  • Revision ID: svn-v4:2587a929-2f0e-0410-ae78-fe6f687d5efe:branches/TRY-5.0:730
Paths: fixed problem with installation folders. Fixed Chinese ISO language code

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//--------------------------------------------------------------------------------------
2
 
//    LenMus Phonascus: The teacher of music
3
 
//    Copyright (c) 2002-2007 Cecilio Salmeron
4
 
//
5
 
//    This program is free software; you can redistribute it and/or modify it under the 
6
 
//    terms of the GNU General Public License as published by the Free Software Foundation;
7
 
//    either version 2 of the License, or (at your option) any later version.
8
 
//
9
 
//    This program is distributed in the hope that it will be useful, but WITHOUT ANY 
10
 
//    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
11
 
//    PARTICULAR PURPOSE.  See the GNU General Public License for more details.
12
 
//
13
 
//    You should have received a copy of the GNU General Public License along with this 
14
 
//    program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, 
15
 
//    Fifth Floor, Boston, MA  02110-1301, USA.
16
 
//
17
 
//    For any comment, suggestion or feature request, please contact the manager of 
18
 
//    the project at cecilios@users.sourceforge.net
19
 
//
20
 
//-------------------------------------------------------------------------------------
21
 
#ifdef __GNUG__
22
 
// #pragma interface
23
 
#endif
24
 
 
25
 
#ifndef __THEOMUSICREADINGCTROLPARAMS_H__        //to avoid nested includes
26
 
#define __THEOMUSICREADINGCTROLPARAMS_H__
27
 
 
28
 
// For compilers that support precompilation, includes "wx/wx.h".
29
 
#include "wx/wxprec.h"
30
 
 
31
 
#ifdef __BORLANDC__
32
 
#pragma hdrstop
33
 
#endif
34
 
 
35
 
#ifndef WX_PRECOMP
36
 
#include "wx/wx.h"
37
 
#endif
38
 
 
39
 
#include "wx/html/htmlwin.h"
40
 
#include "ObjectParams.h"
41
 
#include "../exercises/ScoreConstrains.h"
42
 
#include "../ldp_parser/AuxString.h"
43
 
 
44
 
//! enum assigning name to the score generation settings source.
45
 
/*
46
 
    Four different ways for choosing the settings:
47
 
 
48
 
    1. By level and lesson: Useful for what? It was necessary with old non-html 
49
 
        organization. Now for each lesson there will be an html page and the
50
 
        score object will have all necessary information for that lesson. So method
51
 
        3 will replace this one.
52
 
 
53
 
    2. Personal settings dialog: the user selects the rithmic patterns to generate.
54
 
        Valid only to generate simple repetitive patterns. Composer must have
55
 
        knowledge for completing bars with rest or single notes.
56
 
 
57
 
    3. Pararameters in html object: the parameters must include all necesary data.
58
 
        Score generation based only on received fragments.
59
 
 
60
 
    4. Reading notes exercises: the parameters are fixed for this exercise (parameters
61
 
        the html object) but certain values (clefs, notes range) would need 
62
 
        user settings
63
 
 
64
 
    Free exercises page will be based only on method 2 in coherence with its purpose
65
 
    (free exercises, user customizable). For practising an specific level/lesson the
66
 
    user must choose the corresponding book/page. In these pages it would be allowed
67
 
    to customize settings by adding/removing fragments or changing clefs and note ranges.
68
 
 
69
 
*/
70
 
 
71
 
/*! This class pack all parameters to set up a Music Reading exercise.
72
 
    The contained lmScoreConstrains object has the constraints for the 'ByProgram'
73
 
    settings mode (default mode). For other modes ('UserSettings' and 'ReadingNotes')
74
 
    the settings must be read/setup by the TheoMusicReadingCtrol object.
75
 
*/
76
 
class lmTheoMusicReadingCtrolParms : public lmObjectParams
77
 
{
78
 
public:
79
 
    lmTheoMusicReadingCtrolParms(const wxHtmlTag& tag, int nWidth, int nHeight,
80
 
                              int nPercent, long nStyle);
81
 
    ~lmTheoMusicReadingCtrolParms();
82
 
 
83
 
    void AddParam(const wxHtmlTag& tag);
84
 
    void CreateHtmlCell(wxHtmlWinParser *pHtmlParser);
85
 
 
86
 
protected:
87
 
    bool AnalyzeClef(wxString sLine);
88
 
    bool AnalyzeTime(wxString sLine);
89
 
    bool AnalyzeKeys(wxString sLine);
90
 
    bool AnalyzeFragments(wxString sLine);
91
 
 
92
 
        // Member variables:
93
 
 
94
 
    // html object window attributes
95
 
    long                        m_nWindowStyle;
96
 
    lmScoreConstrains*          m_pConstrains;
97
 
    lmMusicReadingCtrolOptions*  m_pOptions;
98
 
    wxString                    m_sParamErrors;
99
 
 
100
 
    DECLARE_NO_COPY_CLASS(lmTheoMusicReadingCtrolParms)
101
 
};
102
 
 
103
 
 
104
 
 
105
 
lmTheoMusicReadingCtrolParms::lmTheoMusicReadingCtrolParms(const wxHtmlTag& tag, int nWidth, int nHeight,
106
 
                                   int nPercent, long nStyle)
107
 
    : lmObjectParams(tag, nWidth, nHeight, nPercent)
108
 
{
109
 
 
110
 
    // html object window attributes
111
 
    m_nWindowStyle = nStyle;
112
 
 
113
 
    // construct constraints object
114
 
    m_pConstrains = new lmScoreConstrains();
115
 
 
116
 
    // object options
117
 
    m_pOptions = new lmMusicReadingCtrolOptions();
118
 
 
119
 
    // initializations
120
 
    m_sParamErrors = _T("");    //no errors
121
 
 
122
 
}
123
 
 
124
 
 
125
 
lmTheoMusicReadingCtrolParms::~lmTheoMusicReadingCtrolParms()
126
 
{
127
 
    //Constrains and options will be deleted by the Ctrol. DO NOT DELETE THEM HERE
128
 
    //IF THE CONTROL HAS BEEN CREATED
129
 
    if (m_sParamErrors != _T("")) {
130
 
        if (m_pConstrains) delete m_pConstrains;
131
 
        if (m_pOptions) delete m_pOptions;
132
 
    }
133
 
 
134
 
}
135
 
 
136
 
void lmTheoMusicReadingCtrolParms::AddParam(const wxHtmlTag& tag)
137
 
{
138
 
    /*! @page MusicReadingCtrolParams
139
 
        @verbatim    
140
 
 
141
 
        Params for lmScoreCtrol - html object type="Application/LenMusTheoMusicReading"
142
 
 
143
 
 
144
 
        optional params to include controls: (not yet implemented marked as [])
145
 
        --------------------------------------
146
 
 
147
 
        control_play    Include 'play' link. Default: do not include it.
148
 
                        Value="play label|stop playing label". i.e.: "Play|Stop" Stop label
149
 
                        is optional. Default labels: "Play|Stop"
150
 
 
151
 
        control_solfa   Include 'solfa' link. Default: do not include it.
152
 
                        Value="music read label|stop music reading label". i.e.: 
153
 
                        "Play|Stop". Stop label is optional.
154
 
                        Default labels: "Read|Stop"
155
 
 
156
 
        control_settings    Value="[key for storing the settings]"  
157
 
                            This param forces to include the 'settings' link. The
158
 
                            key will be used both as the key for saving the user settings
159
 
                            and as a tag to select the Setting Dialog options to allow.
160
 
 
161
 
        control_go_back    URL, i.e.: "v2_L2_MusicReading_203.htm"
162
 
 
163
 
        metronome       Set a fixed metronome rate to play this piece of music
164
 
                        Value="MM number". Default: user value in metronome control
165
 
 
166
 
 
167
 
        params to set up the score composer:
168
 
        ------------------------------------
169
 
 
170
 
        fragment*   one param for each fragment to use
171
 
 
172
 
        clef*       one param for each allowed clef. It includes the pitch scope.
173
 
 
174
 
        time        a list of allowed time signatures, i.e.: "68,98,128"
175
 
 
176
 
        key         keyword "all" or a list of allowed key signatures, i.e.: "Do,Fas"
177
 
 
178
 
        max_interval    a number indicating the maximum allowed interval for two consecutive notes
179
 
                        Default: 4
180
 
 
181
 
        @todo: update the example
182
 
        Example:
183
 
        ------------------------------------
184
 
 
185
 
        <object type="Application/LenMusTheoMusicReading" width="100%" height="300" border="0">
186
 
            <param name="control" value="play">
187
 
            <param name="label_play" value="Play|Stop">
188
 
            <param name="control" value="solfa">
189
 
            <param name="mode" value="PersonalSettings">
190
 
            <param name="mode" value="NotesReading">
191
 
            <param name="fragment" value="68,98;(n * n)(n * c +l)(g (n * c)(n * c)(n * c))">
192
 
                <param name="fragment" value="68,98;(n * c)(n * n +l)(g (n * c)(n * c)(n * c))">
193
 
                <param name="fragment" value="68,98;(n * n)(n * c)">
194
 
                <param name="fragment" value="68,98;(g (n * c)(n * c)(n * c))">
195
 
            <param name="clef" value="Sol;a3;a5">
196
 
            <param name="clef" value="Fa4;a2;e4">
197
 
            <param name="time" value="68,98,128">
198
 
            <param name="key" value="all">
199
 
            <param name="max_interval" value="4">
200
 
        </object>
201
 
 
202
 
        @endverbatim
203
 
 
204
 
    */
205
 
 
206
 
    wxString sName = wxEmptyString;
207
 
    wxString sValue = wxEmptyString;
208
 
 
209
 
    // scan name and value
210
 
    if (!tag.HasParam(wxT("NAME"))) return;        // ignore param tag if no name attribute
211
 
    sName = tag.GetParam(_T("NAME"));
212
 
    sName.UpperCase();        //convert to upper case
213
 
 
214
 
    if (!tag.HasParam(_T("VALUE"))) return;        // ignore param tag if no value attribute
215
 
    
216
 
    // control_play
217
 
    if ( sName == _T("CONTROL_PLAY") ) {
218
 
        m_pOptions->SetControlPlay(true, tag.GetParam(_T("VALUE")) );
219
 
    }
220
 
 
221
 
    // control_solfa
222
 
    else if ( sName == _T("CONTROL_SOLFA") ) {
223
 
        m_pOptions->SetControlSolfa(true, tag.GetParam(_T("VALUE")) );
224
 
    }
225
 
 
226
 
    // "Go back to theory" link
227
 
    else if ( sName == _T("CONTROL_GO_BACK") ) {
228
 
        m_pOptions->SetGoBackURL( tag.GetParam(_T("VALUE") ));
229
 
    }
230
 
 
231
 
    // control_settings
232
 
    else if ( sName == _T("CONTROL_SETTINGS") ) {
233
 
        m_pOptions->SetControlSettings(true, tag.GetParam(_T("VALUE")) );
234
 
        m_pConstrains->SetSection( tag.GetParam(_T("VALUE") ));
235
 
    }
236
 
 
237
 
    // metronome
238
 
    else if ( sName == _T("METRONOME") ) {
239
 
        wxString sMM = tag.GetParam(_T("VALUE"));
240
 
        long nMM;
241
 
        bool fOK = sMM.ToLong(&nMM);
242
 
        if (!fOK || nMM < 0 ) {
243
 
            m_sParamErrors += wxString::Format( 
244
 
_("Invalid param value in:\n<param %s >\n \
245
 
Invalid value = %s \n \
246
 
Acceptable values: numeric, greater than 0\n"),
247
 
                tag.GetAllParams(), tag.GetParam(_T("VALUE")) );
248
 
        }
249
 
        else {
250
 
            m_pConstrains->SetMetronomeMM(nMM);
251
 
        }
252
 
    }
253
 
 
254
 
    //fragments   the list of fragmens to use
255
 
    //  <param name="fragment" value="68,98;(n * n)(n * c +l)(g (n * c)(n * c)(n * c))">
256
 
        //  <param name="fragment" value="68,98;(n * c)(n * n +l)(g (n * c)(n * c)(n * c))">
257
 
        //  <param name="fragment" value="68,98;(n * n)(n * c)">
258
 
        //  <param name="fragment" value="68,98;(g (n * c)(n * c)(n * c))">
259
 
 
260
 
    else if ( sName == _T("FRAGMENT") ) {
261
 
        wxString sFragments = tag.GetParam(_T("VALUE"));
262
 
        AnalyzeFragments(sFragments);
263
 
    }
264
 
 
265
 
    //clef*        one param for each allowed clef. It includes the pitch scope.
266
 
    //  <param name="clef" value="Sol;a3;a5" />
267
 
    //  <param name="clef" value="Fa4;a2;e4" />
268
 
 
269
 
    else if ( sName == _T("CLEF") ) {
270
 
        wxString sClef = tag.GetParam(_T("VALUE"));
271
 
        if (AnalyzeClef(sClef)) {
272
 
            m_sParamErrors += wxString::Format(
273
 
_("Invalid param value in:\n<param %s >\n \
274
 
Invalid value = %s \n \
275
 
Acceptable format: <Clef,LowerNote,UpperNote> \n \
276
 
Acceptable clef values: Sol | Fa4 | Fa3 | Do4 | Do3 | Do2 | Do1 \n \
277
 
Acceptable note pitch: c0 - c9"),
278
 
                tag.GetAllParams(), tag.GetParam(_T("VALUE")) );
279
 
        }
280
 
    }
281
 
 
282
 
    //time        a list of allowed time signatures, i.e.: "68,98,128"
283
 
    //    <param name="time" value="68,98,128">
284
 
 
285
 
    else if ( sName == _T("TIME") ) {
286
 
        wxString sTime = tag.GetParam(_T("VALUE"));
287
 
        if (AnalyzeTime(sTime)) {
288
 
            m_sParamErrors += wxString::Format( 
289
 
_("Invalid param value in:\n<param %s >\n \
290
 
Invalid value = %s \n \
291
 
Acceptable format: list of time signatures \n"),
292
 
                tag.GetAllParams(), tag.GetParam(_T("VALUE")) );
293
 
        }
294
 
    }
295
 
 
296
 
    //key         keyword "all" or a list of allowed key signatures, i.e.: "Do,Fas"
297
 
    //    <param name="key" value="all">
298
 
 
299
 
    else if ( sName == _T("KEY") ) {
300
 
        wxString sKeys = tag.GetParam(_T("VALUE"));
301
 
        if (AnalyzeKeys(sKeys)) {
302
 
            m_sParamErrors += wxString::Format(
303
 
_("Invalid param value in:\n<param %s >\n \
304
 
Invalid value = %s \n \
305
 
Acceptable format: list of key signatures or keyword 'all' \n"),
306
 
                tag.GetAllParams(), tag.GetParam(_T("VALUE")) );
307
 
        }
308
 
    }
309
 
 
310
 
    //maxGroupInterval    a number
311
 
    else if ( sName == _T("MAX_INTERVAL") ) {
312
 
        wxString sMaxInterval = tag.GetParam(_T("VALUE"));
313
 
        long nMaxInterval;
314
 
        bool fOK = sMaxInterval.ToLong(&nMaxInterval);
315
 
        if (!fOK || nMaxInterval < 0 ) {
316
 
            m_sParamErrors += wxString::Format( 
317
 
_("Invalid param value in:\n<param %s >\n \
318
 
Invalid value = %s \n \
319
 
Acceptable values: numeric, greater than 0\n"),
320
 
                tag.GetAllParams(), tag.GetParam(_T("VALUE")) );
321
 
        }
322
 
        else {
323
 
            m_pConstrains->SetMaxInterval((int)nMaxInterval);
324
 
        }
325
 
    }
326
 
 
327
 
    // Unknown param
328
 
    else
329
 
        m_sParamErrors += wxString::Format( 
330
 
            _("lmTheoMusicReadingCtrol. Unknown param: <param %s >\n"),
331
 
            tag.GetAllParams() );
332
 
 
333
 
}
334
 
 
335
 
void lmTheoMusicReadingCtrolParms::CreateHtmlCell(wxHtmlWinParser *pHtmlParser)
336
 
{
337
 
    //The <object> tag has been read. If param 'control_settings' has been specified
338
 
    // configuration values must be loaded from the specified section key
339
 
    m_pConstrains->LoadSettings();
340
 
 
341
 
    //verify that all necessary html params has been specified
342
 
    wxWindow* pWnd;
343
 
    m_sParamErrors += m_pConstrains->Verify();
344
 
    if (m_sParamErrors != _T("")) {
345
 
        // there are errors: display a text box with the error message
346
 
        pWnd = new wxTextCtrl((wxWindow*)pHtmlParser->GetWindowInterface()->GetHTMLWindow(), -1, m_sParamErrors,
347
 
            wxPoint(0,0), wxSize(300, 100), wxTE_MULTILINE);
348
 
    }
349
 
    else {
350
 
        // create the TheoMusicReadingCtrol
351
 
        pWnd = new lmTheoMusicReadingCtrol((wxWindow*)pHtmlParser->GetWindowInterface()->GetHTMLWindow(), -1, 
352
 
            m_pOptions, m_pConstrains, wxPoint(0,0), wxSize(m_nWidth, m_nHeight), m_nWindowStyle );
353
 
    }
354
 
    pWnd->Show(true);
355
 
    pHtmlParser->GetContainer()->InsertCell(new wxHtmlWidgetCell(pWnd, m_nPercent));
356
 
 
357
 
}
358
 
 
359
 
/// returns true if error
360
 
bool lmTheoMusicReadingCtrolParms::AnalyzeClef(wxString sLine)
361
 
{
362
 
    //i.e.: "Sol;c4;c5"
363
 
 
364
 
    //get clef
365
 
    int iSemicolon = sLine.Find(_T(";"));
366
 
    wxString sClef = sLine.Left(iSemicolon);
367
 
    EClefType nClef = LDPNameToClef(sClef);
368
 
    if (nClef == (EClefType)-1) return true;    //error
369
 
 
370
 
    //get lower scope
371
 
    sLine = sLine.Mid(iSemicolon+1);
372
 
    iSemicolon = sLine.Find(_T(";"));
373
 
    wxString sLowerScope = sLine.Left(iSemicolon);
374
 
 
375
 
    //get upper scope
376
 
    wxString sUpperScope = sLine.Mid(iSemicolon + 1);
377
 
 
378
 
    //Update information for this clef
379
 
    lmClefConstrain* pClefs = m_pConstrains->GetClefConstrains();
380
 
    pClefs->SetValid(nClef, true);
381
 
    pClefs->SetLowerPitch(nClef, sLowerScope);
382
 
    pClefs->SetUpperPitch(nClef, sUpperScope);
383
 
 
384
 
    return false;   //no error
385
 
 
386
 
}
387
 
 
388
 
/// returns true if error
389
 
bool lmTheoMusicReadingCtrolParms::AnalyzeTime(wxString sLine)
390
 
{
391
 
    //i.e.: "98" , "38,68,128" , "24,44"
392
 
 
393
 
    //build time signatures constraints object
394
 
    lmTimeSignConstrains* pTimeSigns = new lmTimeSignConstrains();
395
 
    if (pTimeSigns->SetConstrains(sLine)) return true;
396
 
 
397
 
    //Replace information about allowed time signatures
398
 
    lmTimeSignConstrains* pOldTimeSigns = m_pConstrains->GetTimeSignConstrains();
399
 
    int i;
400
 
    ETimeSignature nTime;
401
 
    for (i=lmMIN_TIME_SIGN; i <= lmMAX_TIME_SIGN; i++) {
402
 
        nTime = (ETimeSignature)i;
403
 
        pOldTimeSigns->SetValid(nTime, pTimeSigns->IsValid(nTime) );
404
 
    }
405
 
    delete pTimeSigns;
406
 
 
407
 
    return false;   //no error
408
 
 
409
 
}
410
 
 
411
 
/// returns true if error
412
 
bool lmTheoMusicReadingCtrolParms::AnalyzeKeys(wxString sLine)
413
 
{
414
 
    //i.e.: "all" , "do,sol,fa," 
415
 
 
416
 
    if (sLine == _T("all")) {
417
 
        // allow all key signatures
418
 
        lmKeyConstrains* pKeys = m_pConstrains->GetKeyConstrains();
419
 
        int i;
420
 
        for (i=0; i <= earmFa; i++) {
421
 
            pKeys->SetValid((EKeySignatures)i, true);
422
 
        }
423
 
    }
424
 
 
425
 
    else {
426
 
        //analyze and set key signatures
427
 
        lmKeyConstrains* pKeys = m_pConstrains->GetKeyConstrains();
428
 
 
429
 
        //loop to get all keys
430
 
        int iColon;
431
 
        wxString sKey;
432
 
        EKeySignatures nKey;
433
 
        while (sLine != _T("")) {
434
 
            //get key
435
 
            iColon = sLine.Find(_T(","));
436
 
            if (iColon != -1) {
437
 
                sKey = sLine.Left(iColon);
438
 
                sLine = sLine.Mid(iColon + 1);      //skip the colon
439
 
            }
440
 
            else {
441
 
                sKey = sLine;
442
 
                sLine = _T("");
443
 
            }
444
 
            nKey = LDPInternalNameToKey(sKey);
445
 
            if (nKey == (EKeySignatures)-1) return true;
446
 
            pKeys->SetValid(nKey, true);
447
 
        }
448
 
    }
449
 
 
450
 
    return false;   //no error
451
 
 
452
 
}
453
 
 
454
 
/// returns true if error
455
 
bool lmTheoMusicReadingCtrolParms::AnalyzeFragments(wxString sLine)
456
 
{
457
 
    //i.e.: "24,34;(s c)(n * n)(n * s g+)(n * s )(n * c g-)(s c)"
458
 
 
459
 
    //get time signatures
460
 
    int iSemicolon = sLine.Find(_T(";"));
461
 
    wxString sTimeSign = sLine.Left(iSemicolon);
462
 
 
463
 
    //get fragment
464
 
    wxString sFragment = sLine.Mid(iSemicolon + 1);   //skip the semicolon and take the rest
465
 
 
466
 
    //build time signatures constraints object
467
 
    lmTimeSignConstrains* pTimeSigns = new lmTimeSignConstrains();
468
 
    if (pTimeSigns->SetConstrains(sTimeSign)) {
469
 
        m_sParamErrors += wxString::Format(_("Error in fragment. Invalid time signature list '%s'\nIn fragment: '%s'\n"),
470
 
                sTimeSign, sFragment);
471
 
        return true;
472
 
     }
473
 
    // verify fragment to avoid program failures
474
 
    lmLDPParser parserLDP;
475
 
    //! @todo strong verification
476
 
    //lmLDPNode* pRoot = parserLDP.ParseText(sFragment);
477
 
    //if (! pRoot) {
478
 
    if (!parserLDP.ParenthesisMatch(sFragment)) {
479
 
        m_sParamErrors += wxString::Format(_("Invalid fragment. Unmatched parenthesis: '%s'\n"), sFragment);
480
 
        return true;
481
 
     }
482
 
    if (sFragment.Find(_T("(g (")) != -1 || sFragment.Find(_T("(g(")) != -1) {
483
 
        m_sParamErrors += wxString::Format(_("Invalid fragment. Old G syntax: '%s'\n"), sFragment);
484
 
        return true;
485
 
     }
486
 
 
487
 
    // build the entry
488
 
    m_pConstrains->AddFragment(pTimeSigns, sFragment);
489
 
 
490
 
    return false;   //no error
491
 
 
492
 
}
493
 
 
494
 
#endif  // __THEOMUSICREADINGCTROLPARAMS_H__