//======================================================================================= // FileSystem implementation //======================================================================================= InputStream* FileSystem::open_input_stream(const string& filelocator) { //factory method to create InputStream objects DocLocator loc(filelocator); switch( loc.get_protocol() ) { case DocLocator::k_file: { switch( loc.get_inner_protocol() ) { case DocLocator::k_none: return LOMSE_NEW LocalInputStream(filelocator); #if (LOMSE_ENABLE_COMPRESSION == 1) case DocLocator::k_zip: return LOMSE_NEW ZipInputStream(filelocator); #endif default: { LOMSE_LOG_ERROR("Invalid file locator protocol"); throw runtime_error("[FileSystem::open_input_stream] Invalid file locator protocol"); } } } default: { LOMSE_LOG_ERROR("Invalid file locator protocol"); throw runtime_error("[FileSystem::open_input_stream] Invalid file locator protocol"); } } return nullptr; //compiler happy }
//--------------------------------------------------------------------------------------- void CaretPositioner::layout_caret(Caret* pCaret, DocCursor* pCursor, GraphicModel* pGModel) { m_pCursor = pCursor; if (m_pCursor->is_inside_terminal_node()) { ImoObj* pTopLevel = m_pCursor->get_parent_object(); GmoBox* pBox = pGModel->get_box_for_imo(pCursor->get_parent_id()); if (!pBox) { LOMSE_LOG_ERROR("No box for cursor pointed object"); } else { pCaret->set_top_level_box( pBox->get_bounds() ); InnerLevelCaretPositioner* p = new_positioner(pTopLevel, pGModel); p->layout_caret(pCaret, m_pCursor); } } else { TopLevelCaretPositioner p(pGModel); p.layout_caret(pCaret, m_pCursor); } }
//--------------------------------------------------------------------------------------- void SelectionSet::add_staffobj_to_collection(ImoStaffObj* pSO) { //add it to staffobjs internal collection if (!m_pMasterCollection) { ImoScore* pScore = pSO->get_score(); m_pMasterCollection = pScore->get_staffobjs_table(); } //find entry in master collection ColStaffObjsIterator it = m_pMasterCollection->find(pSO); if (it == m_pMasterCollection->end()) { //(impossible) error! not found! LOMSE_LOG_ERROR("Impossible error: staffobj not found when added to SelectionSet"); return; } ColStaffObjsEntry* pEntry = *it; //add to local collection if (!m_pCollection) m_pCollection = LOMSE_NEW ColStaffObjs(); m_pCollection->add_entry(pEntry->measure(), pEntry->num_instrument(), pEntry->line(), pEntry->staff(), pEntry->imo_object() ); }
//======================================================================================= // GmoBoxLink //======================================================================================= void GmoBoxLink::notify_event(SpEventInfo pEvent) { if (pEvent->is_mouse_in_event()) { LOMSE_LOG_DEBUG(Logger::k_events, "set hover true"); set_hover(true); set_dirty(true); } else if (pEvent->is_mouse_out_event()) { LOMSE_LOG_DEBUG(Logger::k_events, "set hover false"); set_hover(false); set_dirty(true); } else if (pEvent->is_on_click_event()) { LOMSE_LOG_ERROR("is_on_click_event: TODO"); //TODO: GmoBoxLink::notify_event, on_click_event // m_visited = true; // m_prevColor = m_visitedColor; } else { LOMSE_LOG_DEBUG(Logger::k_events, "event ignored"); } }
//--------------------------------------------------------------------------------------- void ScoreCaretPositioner::set_caret_y_pos_and_height(URect* pBounds, ImoId id, int iStaff) { URect staffBounds; if (id >= 0) { GmoShape* pShape = get_shape_for_imo(id, iStaff); GmoBox* pBox = pShape->get_owner_box(); while (pBox && !pBox->is_box_system()) pBox = pBox->get_owner_box(); if (!pBox) { LOMSE_LOG_ERROR("[ScoreCaretPositioner::set_caret_y_pos_and_height] Invalid boxes structure"); throw runtime_error("[ScoreCaretPositioner::set_caret_y_pos_and_height] Invalid boxes structure"); } m_pBoxSystem = static_cast<GmoBoxSystem*>(pBox); int staff = m_spState->staff(); int instr = m_spState->instrument(); GmoShapeStaff* pStaff = m_pBoxSystem->get_staff_shape(instr, staff); staffBounds = pStaff->get_bounds(); } else { //score is empty staffBounds = *pBounds; } //set position and size pBounds->y = staffBounds.y - tenths_to_logical(10); pBounds->height = staffBounds.height + tenths_to_logical(20); }
//--------------------------------------------------------------------------------------- TimeUnits get_duration_for_ref_note(int bottomNumber) { // returns beat duration (in LDP notes duration units) switch(bottomNumber) { case 1: return pow(2.0, (10 - k_whole)); case 2: return pow(2.0, (10 - k_half)); case 4: return pow(2.0, (10 - k_quarter)); case 8: return pow(2.0, (10 - k_eighth)); case 16: return pow(2.0, (10 - k_16th)); case 32: return pow(2.0, (10 - k_32nd)); case 64: return pow(2.0, (10 - k_64th)); default: { string msg = str( boost::format( "[get_duration_for_ref_note] Invalid bottom number %d") % bottomNumber ); LOMSE_LOG_ERROR(msg); throw runtime_error(msg); } } }
//--------------------------------------------------------------------------------------- int MetronomeMarkEngraver::select_glyph(int noteType) { switch (noteType) { case k_whole: return k_glyph_small_whole_note; case k_half: return k_glyph_small_half_note; case k_quarter: return k_glyph_small_quarter_note; case k_eighth: return k_glyph_small_eighth_note; case k_16th: return k_glyph_small_16th_note; case k_32nd: return k_glyph_small_32nd_note; case k_64th: return k_glyph_small_64th_note; case k_128th: return k_glyph_small_128th_note; case k_256th: return k_glyph_small_256th_note; default: { string msg = str( boost::format( "[MetronomeMarkEngraver::select_glyph] invalid note type %d") % noteType ); LOMSE_LOG_ERROR(msg); throw runtime_error(msg); } } }
//--------------------------------------------------------------------------------------- wxImage ArtProvider::get_image(const wxArtID& id, const wxArtClient& client, const wxSize& size) { wxFileName oFilename = get_filepath(id, client, size); //LOMSE_LOG_INFO(str(boost::format("Art: Filepath='%s'") // % oFilename.GetFullPath().wx_str() )); if (oFilename.GetFullPath() == "null") { wxBitmap oBitmap(null_xpm); return oBitmap.ConvertToImage(); } wxImage image; if (image.LoadFile(oFilename.GetFullPath(), wxBITMAP_TYPE_PNG)) return image; else { // if file not found we need to return something. Otherwise, for tool bars // and other objects a crash will be produced LOMSE_LOG_ERROR(str(boost::format("File %s not found. Error icon returned") % oFilename.GetFullPath().wx_str() )); wxBitmap oBitmap(error_16_xpm); return oBitmap.ConvertToImage(); } }
//--------------------------------------------------------------------------------------- GmoShape* MetronomeMarkEngraver::create_shape(ImoMetronomeMark* pImo, UPoint uPos, Color color) { ImoStyle* pStyle = m_pMeter->get_metronome_style_info(); m_fontSize = pStyle->font_size() * 1.5f; m_pCreatorImo = pImo; m_uPos = uPos; m_uPos.y -= m_pMeter->tenths_to_logical(20.0f, m_iInstr, m_iStaff); m_color = color; create_main_container_shape(); int markType = pImo->get_mark_type(); switch(markType) { case ImoMetronomeMark::k_note_value: return create_shape_note_value(); case ImoMetronomeMark::k_note_note: return create_shape_note_note(); case ImoMetronomeMark::k_value: return create_shape_mm_value(); default: { string msg = str( boost::format( "[MetronomeMarkEngraver::create_shape] invalid mark type %d") % markType ); LOMSE_LOG_ERROR(msg); throw runtime_error(msg); } } }
//======================================================================================= // LocalInputStream implementation //======================================================================================= LocalInputStream::LocalInputStream(const std::string& filelocator) : InputStream() , m_file(filelocator.c_str(), ios::in | ios::binary) { if(!m_file.is_open()) { stringstream s; s << "[LocalInputStream::LocalInputStream] File not found: \"" << filelocator << "\""; LOMSE_LOG_ERROR(s.str()); throw runtime_error(s.str()); } }
//--------------------------------------------------------------------------------------- void ChordEngraver::set_end_staffobj(ImoRelObj* UNUSED(pRO), ImoStaffObj* pSO, GmoShape* pStaffObjShape, int UNUSED(iInstr), int UNUSED(iStaff), int UNUSED(iSystem), int UNUSED(iCol), LUnits UNUSED(xRight), LUnits UNUSED(xLeft), LUnits UNUSED(yTop)) { add_note(pSO, pStaffObjShape); if (m_numNotesMissing != 0) { LOMSE_LOG_ERROR("[ChordEngraver::set_end_staffobj] Num added notes doesn't match exzpected notes in chord"); throw runtime_error("[ChordEngraver::set_end_staffobj] Num added notes doesn't match exzpected notes in chord"); } }
//--------------------------------------------------------------------------------------- string DiatonicPitch::get_ldp_name() { // Returns the LDP note name (without accidentals). For example, // pitch 29 will return "c4". if (is_valid()) return m_sNoteName[step()] + m_sOctave[octave()]; else { LOMSE_LOG_ERROR("Operation on non-valid DiatonicPitch %d", m_dp); return "*"; //throw runtime_error("Operation on non-valid DiatonicPitch"); } }
//--------------------------------------------------------------------------------------- EScaleType ScalesConstrains::GetRandomScaleType() { int nWatchDog = 0; int nType = RandomGenerator::random_number(0, est_Max-1); while (!IsScaleValid((EScaleType)nType)) { nType = RandomGenerator::random_number(0, est_Max-1); if (nWatchDog++ == 1000) { LOMSE_LOG_ERROR("Program error: Loop detected"); return (EScaleType)0; } } return (EScaleType)nType; }
//--------------------------------------------------------------------------------------- void Paths::create_folders() { //create temp folder if it does not exist. Otherwise the program will //fail when the user tries to open an eMusicBook if (!::wxDirExists(m_sTemp)) { //bypass for bug in unicode build (GTK) for wxMkdir //::wxMkDir(m_sTemp.wx_str()); wxFileName oFN(m_sTemp); oFN.Mkdir(0777); if (!::wxDirExists(m_sTemp)) LOMSE_LOG_ERROR(to_std_string( wxString::Format("Failed to create '%s'." , oFN.GetFullPath().wx_str() ))); } #if (LENMUS_PLATFORM_UNIX == 1) //create folders if they don't exist if (!::wxDirExists(m_sLogs)) { wxFileName oFN(m_sLogs); oFN.Mkdir(0777); if (!::wxDirExists(m_sLogs)) LOMSE_LOG_ERROR(to_std_string( wxString::Format("Failed to create '%s'." , oFN.GetFullPath().wx_str() ))); } if (!::wxDirExists(m_sConfig)) { wxFileName oFN(m_sConfig); oFN.Mkdir(0777); if (!::wxDirExists(m_sConfig)) LOMSE_LOG_ERROR(to_std_string( wxString::Format("Failed to create '%s'." , oFN.GetFullPath().wx_str() ))); } #endif }
//--------------------------------------------------------------------------------------- Image::Image(const Image& img) { m_bmpSize = img.m_bmpSize; m_imgSize = img.m_imgSize; m_format = img.m_format; m_error = ""; int bmpsize = m_bmpSize.width * m_bmpSize.height * get_bits_per_pixel()/8; if ((m_bmap = (unsigned char*)malloc(bmpsize)) == NULL) { LOMSE_LOG_ERROR("[Image copy constructor]: not enough memory for image buffer"); throw runtime_error("[Image copy constructor]: not enough memory for image buffer"); } memcpy(m_bmap, img.m_bmap, bmpsize); }
//--------------------------------------------------------------------------------------- URect ScoreCaretPositioner::get_bounds_for_imo(ImoId id, int iStaff) { GmoShape* pShape = get_shape_for_imo(id, iStaff); if (!pShape) { LOMSE_LOG_ERROR("[ScoreCaretPositioner::get_bounds_for_imo] No shape for requested object!"); return URect(0,0,0,0); } GmoBoxSliceInstr* pBSI = static_cast<GmoBoxSliceInstr*>( pShape->get_owner_box() ); GmoBoxSlice* pBS = static_cast<GmoBoxSlice*>( pBSI->get_parent_box() ); m_pBoxSystem = static_cast<GmoBoxSystem*>( pBS->get_parent_box() ); return pShape->get_bounds(); }
//--------------------------------------------------------------------------------------- EKeySignature get_relative_major_key(EKeySignature nMinorKey) { switch(nMinorKey) { case k_key_a: return k_key_C; case k_key_e: return k_key_G; case k_key_b: return k_key_D; case k_key_fs: return k_key_A; case k_key_cs: return k_key_E; case k_key_gs: return k_key_B; case k_key_ds: return k_key_Fs; case k_key_as: return k_key_Cs; case k_key_d: return k_key_F; case k_key_g: return k_key_Bf; case k_key_c: return k_key_Ef; case k_key_f: return k_key_Af; case k_key_bf: return k_key_Df; case k_key_ef: return k_key_Gf; case k_key_af: return k_key_Cf; default: { string msg = str( boost::format( "[get_relative_major_key] Invalid key signature %d") % nMinorKey ); LOMSE_LOG_ERROR(msg); //throw runtime_error(msg); return k_key_c; } } }
//--------------------------------------------------------------------------------------- EKeySignature get_relative_minor_key(EKeySignature nMajorKey) { switch(nMajorKey) { case k_key_C: return k_key_a; case k_key_G: return k_key_e; case k_key_D: return k_key_b; case k_key_A: return k_key_fs; case k_key_E: return k_key_cs; case k_key_B: return k_key_gs; case k_key_Fs: return k_key_ds; case k_key_Cs: return k_key_as; case k_key_F: return k_key_d; case k_key_Bf: return k_key_g; case k_key_Ef: return k_key_c; case k_key_Af: return k_key_f; case k_key_Df: return k_key_bf; case k_key_Gf: return k_key_ef; case k_key_Cf: return k_key_af; default: { string msg = str( boost::format( "[get_relative_minor_key] Invalid key signature %d") % nMajorKey ); LOMSE_LOG_ERROR(msg); throw runtime_error(msg); } } }
//--------------------------------------------------------------------------------------- FPitch::FPitch(const string& note) { // 'note' must be a note name in ldp format: a letter followed by a number // (i.e.: "c4" ) optionally precedeed by accidentals (i.e.: "++c4") // It is assumed that 'note' is trimmed (no spaces before or after data) // and lower case. int step, octave; EAccidentals accidentals; if (LdpAnalyser::ldp_pitch_to_components(note, &step, &octave, &accidentals)) { LOMSE_LOG_ERROR(note); create(k_step_C, k_octave_4, 0); //error } else { int acc = accidentals_to_number(accidentals); create(step, octave, acc); } }
//--------------------------------------------------------------------------------------- Image::Image() : m_error("") { //Build default img: grey square 24x24 px m_bmpSize = VSize(24, 24); //TODO: get display reolution from lomse initialization. Here it is assumed 96 ppi m_imgSize = USize(24.0 * 2540.0f / 96.0f, 24.0 * 2540.0f / 96.0f); m_format = k_pix_format_rgba32; //allocate a buffer for the bitmap int bmpsize = 24 * 24 * 4; //24px width, 24px height, 4bytes per pixel (RGBA) if ((m_bmap = (unsigned char*)malloc(bmpsize)) == NULL) { LOMSE_LOG_ERROR("[Image constructor]: not enough memory for image buffer"); throw runtime_error("[Image constructor]: not enough memory for image buffer"); } unsigned char no_image = 0x77; memset(m_bmap, no_image, bmpsize); }
//--------------------------------------------------------------------------------------- int get_beat_position(TimeUnits timePos, ImoTimeSignature* pTS) { // Some times it is necessary to know the type of beat (strong, medium, weak, // off-beat) at which a note or rest is positioned. // This function receives the time for a note/rest and the current time signature // and returns the type of beat: either an integer positive value 0..n, meaning // 'on-beat', where n is the beat number, or -1 meaning 'off-beat' int beatType = pTS->get_bottom_number(); // coumpute beat duration int beatDuration; switch (beatType) { case 1: beatDuration = int( to_duration(k_whole, 0) ); break; case 2: beatDuration = int( to_duration(k_half, 0) ); break; case 4: beatDuration = int( to_duration(k_quarter, 0) ); break; case 8: beatDuration = 3 * int( to_duration(k_eighth, 0) ); break; case 16: beatDuration = int( to_duration(k_eighth, 0) ); break; default: { string msg = str( boost::format("[get_beat_position] BeatType %d unknown.") % beatType ); LOMSE_LOG_ERROR(msg); throw runtime_error(msg); } } // compute relative position of this note/rest with reference to the beat int beatNum = int(timePos) / beatDuration; //number of beat TimeUnits beatShift = fabs(timePos - TimeUnits(beatDuration * beatNum)); if (beatShift < 1.0) //on-beat return beatNum; else // off-beat return k_off_beat; }
//--------------------------------------------------------------------------------------- Image& Image::operator=(const Image &img) { if (this != &img) { if (m_bmap) free(m_bmap); m_bmpSize = img.m_bmpSize; m_imgSize = img.m_imgSize; m_format = img.m_format; m_error = ""; int bmpsize = m_bmpSize.width * m_bmpSize.height * get_bits_per_pixel()/8; if ((m_bmap = (unsigned char*)malloc(bmpsize)) == NULL) { LOMSE_LOG_ERROR("[Image::operator=]: not enough memory for image buffer"); throw runtime_error("[Image::operator=]: not enough memory for image buffer"); } memcpy(m_bmap, img.m_bmap, bmpsize); } return *this; }
//--------------------------------------------------------------------------------------- void ScoreCaretPositioner::layout_caret(Caret* pCaret, DocCursor* pCursor) { //save cursor and related data m_pDocCursor = pCursor; m_pScoreCursor = static_cast<ScoreCursor*>(pCursor->get_inner_cursor()); m_pDoc = pCursor->get_document(); m_pBoxSystem = NULL; //get score cursor state DocCursorState state = m_pDocCursor->get_state(); m_spState = SpScoreCursorState( static_pointer_cast<ScoreCursorState>( state.get_delegate_state() )); //get score ImoId id = state.get_parent_level_id(); m_pScore = static_cast<ImoScore*>( m_pDoc->get_pointer_to_imo(id) ); //create score meter m_pMeter = LOMSE_NEW ScoreMeter(m_pScore); if (m_pScoreCursor->is_pointing_object()) caret_on_pointed_object(pCaret); else if (m_pScoreCursor->is_at_empty_place()) caret_on_empty_timepos(pCaret); else if (m_pScoreCursor->is_at_end_of_empty_score()) caret_at_start_of_score(pCaret); else if (m_pScoreCursor->is_at_end_of_staff()) caret_at_end_of_staff(pCaret); else { LOMSE_LOG_ERROR("[ScoreCaretPositioner::layout_caret] Score cursor is incoherent!"); caret_at_start_of_score(pCaret); } pCaret->set_active_system(m_pBoxSystem); }
//--------------------------------------------------------------------------------------- bool Image::has_alpha() { switch(m_format) { case k_pix_format_undefined: // By default. No conversions are applied // case k_pix_format_gray8: // Simple 256 level grayscale case k_pix_format_gray16: // Simple 65535 level grayscale case k_pix_format_rgb555: // 15 bit rgb. Depends on the byte ordering! case k_pix_format_rgb565: // 16 bit rgb. Depends on the byte ordering! case k_pix_format_rgbAAA: // 30 bit rgb. Depends on the byte ordering! case k_pix_format_rgbBBA: // 32 bit rgb. Depends on the byte ordering! case k_pix_format_bgrAAA: // 30 bit bgr. Depends on the byte ordering! case k_pix_format_bgrABB: // 32 bit bgr. Depends on the byte ordering! case k_pix_format_rgb24: // R-G-B, one byte per color component case k_pix_format_bgr24: // B-G-R, native win32 BMP format. case k_pix_format_rgb48: // R-G-B, 16 bits per color component case k_pix_format_bgr48: // B-G-R, native win32 BMP format. return false; case k_pix_format_rgba32: // R-G-B-A, one byte per color component case k_pix_format_argb32: // A-R-G-B, native MAC format case k_pix_format_abgr32: // A-B-G-R, one byte per color component case k_pix_format_bgra32: // B-G-R-A, native win32 BMP format case k_pix_format_rgba64: // R-G-B-A, 16 bits byte per color component case k_pix_format_argb64: // A-R-G-B, native MAC format case k_pix_format_abgr64: // A-B-G-R, one byte per color component case k_pix_format_bgra64: // B-G-R-A, native win32 BMP format return true; default: { stringstream s; s << "[Image::has_alpha] unsupported pixel format " << m_format; LOMSE_LOG_ERROR(s.str()); throw runtime_error(s.str()); } } return false; //compiler happy }
//--------------------------------------------------------------------------------------- DiatonicPitch get_diatonic_pitch_for_first_line(EClef nClef) { // Returns the diatonic pitch for first line, when using received clef. switch(nClef) { case k_clef_G2: return DiatonicPitch(k_step_E, k_octave_4); case k_clef_F4: return DiatonicPitch(k_step_G, k_octave_2); case k_clef_F3: return DiatonicPitch(k_step_B, k_octave_2); case k_clef_C1: return DiatonicPitch(k_step_C, k_octave_4); case k_clef_C2: return DiatonicPitch(k_step_A, k_octave_3); case k_clef_C3: return DiatonicPitch(k_step_F, k_octave_3); case k_clef_C4: return DiatonicPitch(k_step_D, k_octave_3); case k_clef_C5: return DiatonicPitch(k_step_B, k_octave_2); case k_clef_F5: return DiatonicPitch(k_step_E, k_octave_2); case k_clef_G1: return DiatonicPitch(k_step_G, k_octave_4); case k_clef_8_G2: return DiatonicPitch(k_step_E, k_octave_5); //8 above case k_clef_G2_8: return DiatonicPitch(k_step_E, k_octave_3); //8 below case k_clef_8_F4: return DiatonicPitch(k_step_G, k_octave_3); //8 above case k_clef_F4_8: return DiatonicPitch(k_step_G, k_octave_1); //8 below case k_clef_15_G2: return DiatonicPitch(k_step_E, k_octave_6); //15 above case k_clef_G2_15: return DiatonicPitch(k_step_E, k_octave_2); //15 below case k_clef_15_F4: return DiatonicPitch(k_step_G, k_octave_4); //15 above case k_clef_F4_15: return DiatonicPitch(k_step_G, k_octave_0); //15 below case k_clef_undefined: case k_clef_percussion: return NO_DPITCH; default: { string msg = str( boost::format( "[get_diatonic_pitch_for_first_line] Invalid clef %d") % nClef ); LOMSE_LOG_ERROR(msg); throw runtime_error(msg); } } return NO_DPITCH; }
//--------------------------------------------------------------------------------------- int MidiPitch::step(EKeySignature nKey) { int remainder = m_pitch % 12; //remainder goes from 0 (Do) to 11 (Si) switch (nKey) { case k_key_C: case k_key_a: { // scale: C D E F G A B semitones E B // T T S T T T S // C C+ D D+ E F F+ G G+ A A+ B // int steps[12] = {0,0, 1,1, 2, 3,3, 4,4, 5,5, 6}; return steps[remainder]; } //sharps --------------------------------------- case k_key_G: case k_key_e: { // scale: G A B C D E F+ semitones B F+ // T T S T T T S // C C+ D D+ E E+ F G G+ A A+ B int steps[12] = {0,0, 1,1, 2,2, 3, 4,4, 5,5, 6}; return steps[remainder]; } case k_key_D: case k_key_b: { // scale: D E F+ G A B C+ semitones F+ C+ // T T S T T T S // B+ C+ D D+ E E+ F G G+ A A+ B int steps[12] = {6, 0, 1,1, 2,2, 3, 4,4, 5,5, 6}; return steps[remainder]; } case k_key_A: case k_key_fs: { // scale: A B C+ D E F+ G+ semitones C+, G+ // T T S T T T S // B+ C+ D D+ E E+ F+ Fx G+ A A+ B int steps[12] = {6, 0, 1,1, 2,2, 3, 3, 4, 5,5, 6}; return steps[remainder]; } case k_key_E: case k_key_cs: { // scale: E F+ G+ A B C+ D+ semitones G+, D+ // T T S T T T S // B+ C+ Cx D+ E E+ F+ Fx G+ A A+ B int steps[12] = {6, 0, 0, 1, 2,2, 3, 3, 4, 5,5, 6}; return steps[remainder]; } case k_key_B: case k_key_gs: { // scale: B C+ D+ E F+ G+ A+ semitones D+ A+ // T T S T T T S // B+ C+ Cx D+ E E+ F+ Fx G+ Gx A+ B int steps[12] = {6, 0, 0, 1, 2,2, 3, 3, 4, 4, 5, 6}; return steps[remainder]; } case k_key_Fs: case k_key_ds: { // scale: F+ G+ A+ B C+ D+ E+ semitones A+ E+ // T T S T T T S // B+ C+ Cx D+ Dx E+ F+ Fx G+ Gx A+ B int steps[12] = {6, 0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 6}; return steps[remainder]; } case k_key_Cs: case k_key_as: { // scale: C+ D+ E+ F+ G+ A+ B+ semitones E+ B+ // T T S T T T S // B+ C+ Cx D+ Dx E+ F+ Fx G+ Gx A+ Ax int steps[12] = {6, 0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 5}; return steps[remainder]; } //flats ------------------------------------------- case k_key_F: case k_key_d: { // scale: F G A B- C D E semitones A E // T T S T T T S // C C+ D D+ E F F+ G G+ A B- B int steps[12] = {0,0, 1,1, 2, 3,3, 4,4, 5, 6, 6}; return steps[remainder]; } case k_key_Bf: case k_key_g: { // scale: B- C D E- F G A semitones D A // T T S T T T S // C C+ D E- E F F+ G G+ A B- B int steps[12] = {0,0, 1, 2, 2, 3,3, 4,4, 5, 6, 6}; return steps[remainder]; } case k_key_Ef: case k_key_c: { // scale: E- F G A- B- C D semitones G D // T T S T T T S // C C+ D E- E F F+ G A- A B- B int steps[12] = {0,0, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6}; return steps[remainder]; } case k_key_Af: case k_key_f: { // scale: A- B- C D- E- F G semitones C G // T T S T T T S // C D- D E- E F F+ G A- A B- B int steps[12] = {0, 1, 1, 2, 2, 3,3, 4, 5, 5, 6, 6}; return steps[remainder]; } case k_key_Df: case k_key_bf: { // scale: D- E- F G- A- B- C semitones F C // T T S T T T S // C D- D E- E F G- G A- A B- B int steps[12] = {0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 6}; return steps[remainder]; } case k_key_Gf: case k_key_ef: { // scale: G- A- B- C- D- E- F semitones B- F // T T S T T T S // C D- D E- E F G- G A- A B- C- int steps[12] = {0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 0}; return steps[remainder]; } case k_key_Cf: case k_key_af: { // scale: C- D- E- F- G- A- B- semitones E- B- // T T S T T T S // C D- D E- F- F G- G A- A B- C- int steps[12] = {0, 1, 1, 2, 3, 3, 4, 4, 5, 5, 6, 0}; return steps[remainder]; } default: { LOMSE_LOG_ERROR("Invalid key signature %d. C major assumed.", nKey); int steps[12] = {0,0,1,1,2,3,3,4,4,5,5,6}; return steps[remainder]; } } }
//======================================================================================= // Paths implementation //======================================================================================= Paths::Paths(wxString sBinPath, ApplicationScope& appScope) : m_appScope(appScope) { //Receives the full path to the LenMus executable folder (/bin) and //extracts the root path m_sBin = sBinPath; #if (LENMUS_DEBUG_BUILD == 1 || LENMUS_RELEASE_INSTALL == 0) m_root.AssignDir(LENMUS_SOURCE_ROOT); #if (LENMUS_PLATFORM_WIN32 == 1) //Ignore drive letter in Windows wxFileName drive; drive.GetCwd(); m_root.SetVolume( drive.GetVolume() ); #endif #else m_root.AssignDir(sBinPath); m_root.RemoveLastDir(); #endif m_root.Normalize(); // ------------------------------------------------------------------------------ // Linux Windows Windows (Debug) // Default <prefix> = /usr/local // // 0. The lenmus program // ------------------------------------------------------------------------------ // <prefix> lenmus lm\temp\lenmus // + /bin + \bin + \z_bin // // 1. Shared non-modificable files (INSTALL_ROOT): // ------------------------------------------------------------------------------ // <prefix>/share/lenmus lenmus lm\projects\lenmus\trunk // + /xrc + \xrc // + /res + \res // + /locale + \locale // + /books + \books // + /templates + \templates // + /test-scores + \test-scores // + /samples // // 2. Logs & temporal files (ROOT_G2) // ------------------------------------------------------------------------------ // ~/.config/lenmus/ lenmus lm\temp\lenmus // + /logs + \logs // + /temp + \temp // // 3. Configuration files (user dependent): // ------------------------------------------------------------------------------ // ~/.config/lenmus/5.0/ lenmus\bin lm\temp\lenmus // // 4. User data: scores, samples, etc. // ------------------------------------------------------------------------------ // ~/lenmus lenmus lm\projects\lenmus\trunk // + /scores + \scores (INSTALL_ROOT) // + /5.0/samples + \5.0\samples // wxFileName path; wxString sVersion = m_appScope.get_version_string(); #if (LENMUS_DEBUG_BUILD == 1 || LENMUS_RELEASE_INSTALL == 0) //Debug version or Release version for tests. //Use source tree wxFileName oInstallHome = m_root; wxFileName oLogsHome = m_root; oLogsHome.AssignDir(sBinPath); wxFileName oConfigHome = m_root; oConfigHome.AssignDir(sBinPath); wxFileName oDataHome = m_root; #elif (LENMUS_PLATFORM_WIN32 == 1) //Windows Release version, to install //Use install root. Binaries in /bin folder //Configuration files in /bin, All others in install root wxFileName oInstallHome = m_root; wxFileName oLogsHome = m_root; wxFileName oConfigHome = m_root; oConfigHome.AppendDir("bin"); wxFileName oDataHome = m_root; #elif (LENMUS_PLATFORM_UNIX == 1) //Linux Release version, to install //Use install root. Binaries in /bin folder //Configuration and user dependent files in /home //get user home folder char* homedir = getenv("HOME"); if (homedir == NULL) { struct passwd* pw = getpwuid(getuid()); homedir = pw->pw_dir; } string sHomedir(homedir); wxString sHome = to_wx_string(sHomedir); //1. Shared non-modificable files: LENMUS_INSTALL_ROOT (<prefix>/share/lenmus) wxFileName oInstallHome; oInstallHome.AssignDir( LENMUS_INSTALL_ROOT ); //2. Logs & temporal files: ~/.config/lenmus/ wxFileName oLogsHome; oLogsHome.AssignDir( sHome ); oLogsHome.AppendDir(".config"); if (!::wxDirExists( oLogsHome.GetFullPath() )) { oLogsHome.Mkdir(0777); if (!::wxDirExists( oLogsHome.GetFullPath() )) LOMSE_LOG_ERROR(to_std_string( wxString::Format("Failed to create '%s'." , oLogsHome.GetFullPath().wx_str() ))); } oLogsHome.AppendDir("lenmus"); if (!::wxDirExists( oLogsHome.GetFullPath() )) { oLogsHome.Mkdir(0777); if (!::wxDirExists( oLogsHome.GetFullPath() )) LOMSE_LOG_ERROR(to_std_string( wxString::Format("Failed to create '%s'." , oLogsHome.GetFullPath().wx_str() ))); } //3. Configuration files: ~/.config/lenmus/5.x/ wxFileName oConfigHome; oConfigHome.AssignDir( sHome ); oConfigHome.AppendDir(".config"); oConfigHome.AppendDir("lenmus"); oConfigHome.AppendDir(sVersion); if (!::wxDirExists( oConfigHome.GetFullPath() )) { oConfigHome.Mkdir(0777); if (!::wxDirExists( oConfigHome.GetFullPath() )) LOMSE_LOG_ERROR(to_std_string( wxString::Format("Failed to create '%s'." , oConfigHome.GetFullPath().wx_str() ))); } //4. User data: ~/lenmus/ wxFileName oDataHome; oDataHome.AssignDir( sHome ); oDataHome.AppendDir("lenmus"); if (!::wxDirExists( oDataHome.GetFullPath() )) { oDataHome.Mkdir(0777); if (!::wxDirExists( oDataHome.GetFullPath() )) LOMSE_LOG_ERROR(to_std_string( wxString::Format("Failed to create '%s'." , oDataHome.GetFullPath().wx_str() ))); } #endif // Group 1. Software and essentials path = oInstallHome; path.AppendDir("xrc"); m_sXrc = path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); path = oInstallHome; path.AppendDir("res"); path.AppendDir("icons"); m_sImages = path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); path = oInstallHome; path.AppendDir("res"); path.AppendDir("cursors"); m_sCursors = path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); path = oInstallHome; path.AppendDir("res"); path.AppendDir("sounds"); m_sSounds = path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); path = oInstallHome; path.AppendDir("locale"); m_sLocaleRoot = path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); path = oInstallHome; path.AppendDir("templates"); m_sTemplates = path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); path = oInstallHome; path.AppendDir("test-scores"); m_sTestScores = path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); path = oInstallHome; path.AppendDir("res"); path.AppendDir("fonts"); m_sFonts = path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); // Group 2. Logs and temporal files path = oLogsHome; path.AppendDir("temp"); m_sTemp = path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); if (!::wxDirExists( path.GetFullPath() )) { path.Mkdir(0777); if (!::wxDirExists( path.GetFullPath() )) LOMSE_LOG_ERROR(to_std_string( wxString::Format("Failed to create '%s'." , path.GetFullPath().wx_str() ))); } path = oLogsHome; path.AppendDir("logs"); m_sLogs = path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); if (!::wxDirExists( path.GetFullPath() )) { path.Mkdir(0777); if (!::wxDirExists( path.GetFullPath() )) LOMSE_LOG_ERROR(to_std_string( wxString::Format("Failed to create '%s'." , path.GetFullPath().wx_str() ))); } // Group 3. Configuration files, user dependent path = oConfigHome; m_sConfig = path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); // Group 4. User scores and samples path = oDataHome; //TODO: Else code fails: no permision to create folders if they do not exist #if 1 m_sScores = path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); m_sSamples = path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); #else path.AppendDir("scores"); m_sScores = path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); if (!::wxDirExists( path.GetFullPath() )) { path.Mkdir(0777); if (!::wxDirExists( path.GetFullPath() )) LOMSE_LOG_ERROR(to_std_string( wxString::Format("Failed to create '%s'." , path.GetFullPath().wx_str() ))); } path.AppendDir(sVersion); if (!::wxDirExists( path.GetFullPath() )) { path.Mkdir(0777); if (!::wxDirExists( path.GetFullPath() )) LOMSE_LOG_ERROR(to_std_string( wxString::Format("Failed to create '%s'." , path.GetFullPath().wx_str() ))); } path.AppendDir("samples"); m_sSamples = path.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); if (!::wxDirExists( path.GetFullPath() )) { path.Mkdir(0777); if (!::wxDirExists( path.GetFullPath() )) LOMSE_LOG_ERROR(to_std_string( wxString::Format("Failed to create '%s'." , path.GetFullPath().wx_str() ))); } #endif }
//--------------------------------------------------------------------------------------- bool MidiPitch::is_natural_note_for(EKeySignature nKey) { // Returns true if the Midi note is natural for the key signature scale //Prepare string with "1" in natural tones of the scale string sScale; switch (nKey) { case k_key_C: case k_key_a: // C D EF G A B sScale = "101011010101"; break; //sharps --------------------------------------- case k_key_G: case k_key_e: // C D EF G A B sScale = "101010110101"; break; case k_key_D: case k_key_b: // C D EF G A B sScale = "011010110101"; break; case k_key_A: case k_key_fs: // C D EF G A B sScale = "011010101101"; break; case k_key_E: case k_key_cs: // C D EF G A B sScale = "010110101101"; break; case k_key_B: case k_key_gs: // C D EF G A B sScale = "010110101011"; break; case k_key_Fs: case k_key_ds: // C D EF G A B sScale = "010101101011"; break; case k_key_Cs: case k_key_as: // C D EF G A B sScale = "110101101010"; break; //flats ------------------------------------------- case k_key_F: case k_key_d: // C D EF G A B sScale = "101011010110"; break; case k_key_Bf: case k_key_g: // C D EF G A B sScale = "101101010110"; break; case k_key_Ef: case k_key_c: // C D EF G A B sScale = "101101011010"; break; case k_key_Af: case k_key_f: // C D EF G A B sScale = "110101011010"; break; case k_key_Df: case k_key_bf: // C D EF G A B sScale = "110101101010"; break; case k_key_Gf: case k_key_ef: // C D EF G A B sScale = "010101101011"; break; case k_key_Cf: case k_key_af: // C D EF G A B sScale = "010110101011"; break; default: { LOMSE_LOG_ERROR("[MidiPitch::is_natural_note_for]. Invalid key signature"); throw runtime_error("[MidiPitch::is_natural_note_for]. Invalid key signature"); } } int nRemainder = m_pitch % 12; //nRemainder goes from 0 (Do) to 11 (Si) return (sScale.substr(nRemainder, 1) == "1"); }
//--------------------------------------------------------------------------------------- int key_signature_to_num_fifths(int keyType) { // Retunrs the number of fifths that corresponds to the encoded key signature int nFifths = 0; //num accidentals to return (0..7) switch(keyType) { case k_key_C: case k_key_a: nFifths = 0; break; //Sharps --------------------------------------- case k_key_G: case k_key_e: nFifths = 1; break; case k_key_D: case k_key_b: nFifths = 2; break; case k_key_A: case k_key_fs: nFifths = 3; break; case k_key_E: case k_key_cs: nFifths = 4; break; case k_key_B: case k_key_gs: nFifths = 5; break; case k_key_Fs: case k_key_ds: nFifths = 6; break; case k_key_Cs: case k_key_as: nFifths = 7; break; //Flats ------------------------------------------- case k_key_F: case k_key_d: nFifths = -1; break; case k_key_Bf: case k_key_g: nFifths = -2; break; case k_key_Ef: case k_key_c: nFifths = -3; break; case k_key_Af: case k_key_f: nFifths = -4; break; case k_key_Df: case k_key_bf: nFifths = -5; break; case k_key_Gf: case k_key_ef: nFifths = -6; break; case k_key_Cf: case k_key_af: nFifths = -7; break; default: { string msg = str( boost::format( "[key_signature_to_num_fifths] Invalid key signature %d") % keyType ); LOMSE_LOG_ERROR(msg); throw runtime_error(msg); } } return nFifths; }
//--------------------------------------------------------------------------------------- int ArticulationEngraver::find_glyph() { int type = m_pArticulation->get_articulation_type(); switch( type ) { //accents case k_articulation_accent: return (m_fAbove ? k_glyph_accent_above : k_glyph_accent_below); case k_articulation_marccato: return (m_fAbove ? k_glyph_marcato_above : k_glyph_marcato_below); case k_articulation_staccato: return (m_fAbove ? k_glyph_staccato_above : k_glyph_staccato_below); case k_articulation_tenuto: return (m_fAbove ? k_glyph_tenuto_above : k_glyph_tenuto_below); case k_articulation_mezzo_staccato: return (m_fAbove ? k_glyph_tenuto_staccato_above : k_glyph_tenuto_staccato_below); case k_articulation_staccatissimo: return (m_fAbove ? k_glyph_staccatissimo_above : k_glyph_staccatissimo_below); case k_articulation_legato_duro: return (m_fAbove ? k_glyph_marcato_tenuto_above : k_glyph_marcato_tenuto_below); case k_articulation_marccato_legato: return (m_fAbove ? k_glyph_tenuto_accent_above : k_glyph_tenuto_accent_below); case k_articulation_marccato_staccato: return (m_fAbove ? k_glyph_accent_staccato_above : k_glyph_accent_staccato_below); case k_articulation_staccato_duro: return (m_fAbove ? k_glyph_marcato_staccato_above : k_glyph_marcato_staccato_below); //TODO: No glyphs for these case k_articulation_marccato_staccatissimo: // symbol > with black triangle under it case k_articulation_mezzo_staccatissimo: // symbol - with black triangle under it case k_articulation_staccatissimo_duro: // symbol ^ with black triangle under it { stringstream s; s << "Incomplete code: No glyph for articulation " << type << " in ArticulationEngraver." << endl; LOMSE_LOG_ERROR(s.str()); return (m_fAbove ? k_glyph_accent_above : k_glyph_accent_below); } //TODO: There are more glyphs for articulations: // return (m_fAbove ? k_glyph_staccatissimo_wedge_above : k_glyph_staccatissimo_wedge_below); // return (m_fAbove ? k_glyph_staccatissimo_stroke_above : k_glyph_staccatissimo_stroke_below); // return (m_fAbove ? k_glyph_stress_above : k_glyph_stress_below); // return (m_fAbove ? k_glyph_unstress_above : k_glyph_unstress_below); // return (m_fAbove ? k_glyph_laissez_vibrer_above : k_glyph_laissez_vibrer_below); //jazz pitch articulations case k_articulation_scoop: return k_glyph_brass_scoop; case k_articulation_plop: return k_glyph_brass_plop; case k_articulation_doit: return k_glyph_brass_doit_medium; case k_articulation_falloff: return k_glyph_brass_fall_lip_medium; //breath marks case k_articulation_breath_mark: switch (static_cast<ImoArticulationSymbol*>(m_pArticulation)->get_symbol()) { case ImoArticulationSymbol::k_breath_tick: return k_glyph_breath_mark_tick; case ImoArticulationSymbol::k_breath_comma: return k_glyph_breath_mark_comma; case ImoArticulationSymbol::k_breath_v: return k_glyph_breath_mark_v; case ImoArticulationSymbol::k_breath_salzedo: return k_glyph_breath_mark_salzedo; default: return k_glyph_breath_mark_comma; } case k_articulation_caesura: switch (static_cast<ImoArticulationSymbol*>(m_pArticulation)->get_symbol()) { case ImoArticulationSymbol::k_caesura_normal: return k_glyph_caesura; case ImoArticulationSymbol::k_caesura_thick: return k_glyph_caesura_thick; case ImoArticulationSymbol::k_caesura_short: return k_glyph_caesura_short; case ImoArticulationSymbol::k_caesura_curved: return k_glyph_caesura_curved; default: return k_glyph_caesura; } //stress accents case k_articulation_stress: return (m_fAbove ? k_glyph_stress_above : k_glyph_stress_below); case k_articulation_unstress: return (m_fAbove ? k_glyph_unstress_above : k_glyph_unstress_below); //other in MusicXML case k_articulation_spiccato: //The dot is an alternate sign for spiccato return (m_fAbove ? k_glyph_staccato_above : k_glyph_staccato_below); //unexpected types: code maintenance problem default: stringstream s; s << "Code incoherence: articulation " << type << " not expected in ArticulationEngraver." << endl; LOMSE_LOG_ERROR(s.str()); return (m_fAbove ? k_glyph_accent_above : k_glyph_accent_below); } }