1
1
#
2
2
3
- program_name = 'EasyABC 1.3.7.9 2021-07-20 '
3
+ program_name = 'EasyABC 1.3.7.9 2021-08-25 '
4
4
5
5
# Copyright (C) 2011-2014 Nils Liberg (mail: kotorinl at yahoo.co.uk)
6
- # Copyright (C) 2015-2020 Seymour Shlien (mail: fy733@ncf.ca), Jan Wybren de Jong (jw_de_jong at yahoo dot com)
6
+ # Copyright (C) 2015-2021 Seymour Shlien (mail: fy733@ncf.ca), Jan Wybren de Jong (jw_de_jong at yahoo dot com)
7
7
#
8
8
# This program is free software: you can redistribute it and/or modify
9
9
# it under the terms of the GNU Lesser General Public License as published by
37
37
# pass
38
38
39
39
import sys
40
- PY3 = sys .version_info . major > 2
40
+ PY3 = sys .version_info >= ( 3 , 0 , 0 )
41
41
42
42
abcm2ps_default_encoding = 'utf-8' ## 'latin-1'
43
43
import codecs
@@ -73,7 +73,7 @@ def unicode(s):
73
73
import subprocess
74
74
import hashlib
75
75
76
- if PY3 :
76
+ if sys . version_info >= ( 3 , 0 , 0 ) :
77
77
from urllib .parse import urlparse , urlencode , urlunparse , parse_qsl , quote # py3
78
78
from urllib .request import urlopen , Request , urlretrieve
79
79
from urllib .error import HTTPError , URLError
@@ -132,8 +132,9 @@ def unicode(s):
132
132
import itertools
133
133
from aligner import align_lines , extract_incipit , bar_sep , bar_sep_without_space , get_bar_length , bar_and_voice_overlay_sep
134
134
##from midi_processing import humanize_midi
135
- if PY3 :
135
+ if sys . version_info >= ( 3 , 0 , 0 ) :
136
136
from queue import Queue # 1.3.6.2 [JWdJ] 2015-02
137
+ Empty = Queue .Empty
137
138
else :
138
139
from Queue import Queue # 1.3.6.2 [JWdJ] 2015-02
139
140
@@ -317,6 +318,12 @@ def remove(self, tune_id):
317
318
line_end_re = re .compile ('\r \n |\r |\n ' )
318
319
tune_index_re = re .compile (r'^X:\s*(\d+)' )
319
320
321
+ def note_to_index (abc_note ):
322
+ try :
323
+ return all_notes .index (abc_note )
324
+ except ValueError :
325
+ return None
326
+
320
327
def text_to_lines (text ):
321
328
return line_end_re .split (text )
322
329
@@ -411,7 +418,7 @@ def get_ghostscript_path():
411
418
This function may not see the 64-bit ghostscript installations, especially
412
419
if Python was compiled as a 32-bit application.
413
420
'''
414
- if PY3 :
421
+ if sys . version_info >= ( 3 , 0 , 0 ) :
415
422
import winreg
416
423
else :
417
424
import _winreg as winreg
@@ -1837,7 +1844,7 @@ def run(self):
1837
1844
else :
1838
1845
wx .CallAfter (self .tick2 .Play )
1839
1846
i += 1 #FAU: 20210102: One tick was missing the first time so incrementing i after the tick
1840
-
1847
+
1841
1848
time_offset = self .timedelta_microseconds (datetime .now () - start_time )
1842
1849
if self .midi_in_poll :
1843
1850
if wx .Platform == "__WXMAC__" :
@@ -1861,7 +1868,7 @@ def run(self):
1861
1868
end = float (time_offset ) / self .beat_duration
1862
1869
self .notes .append ([midi_note , start , end ])
1863
1870
#print('note-off', midi_note, float(time_offset)/self.beat_duration)
1864
-
1871
+
1865
1872
1866
1873
finally :
1867
1874
#print('FAU: closing')
@@ -3779,7 +3786,7 @@ def __init__(self, parent, ID, app_dir, settings):
3779
3786
try :
3780
3787
self .mc = FluidSynthPlayer (soundfont_path )
3781
3788
except Exception as e :
3782
- error_msg = '' .join (traceback .format_exception (sys .exc_info ()[0 ], sys .exc_info ()[1 ], sys .exc_info ()[2 ])) + os . linesep + os . linesep . join ( errors )
3789
+ error_msg = '' .join (traceback .format_exception (sys .exc_info ()[0 ], sys .exc_info ()[1 ], sys .exc_info ()[2 ]))
3783
3790
self .mc = None
3784
3791
3785
3792
if self .mc is None :
@@ -3794,7 +3801,8 @@ def __init__(self, parent, ID, app_dir, settings):
3794
3801
backend = wx .media .MEDIABACKEND_WMP10
3795
3802
self .mc = WxMediaPlayer (self , backend )
3796
3803
except NotImplementedError :
3797
- self .mc = DummyMidiPlayer () # if media player not supported on this platform
3804
+ from midiplayer import DummyMidiPlayer
3805
+ self .mc = DummyMidiPlayer () # if media player not supported on this platform
3798
3806
3799
3807
self .mc .OnAfterLoad += self .OnMediaLoaded
3800
3808
self .mc .OnAfterStop += self .OnAfterStop
@@ -4263,8 +4271,7 @@ def OnMouseWheel(self, evt):
4263
4271
4264
4272
def play (self ):
4265
4273
if self .settings .get ('follow_score' , False ) and self .current_page_index != 0 :
4266
- self .current_page_index = 0
4267
- self .UpdateMusicPane ()
4274
+ self .select_page (0 )
4268
4275
wx .CallAfter (self .mc .Play )
4269
4276
4270
4277
def stop_playing (self ):
@@ -4485,8 +4492,7 @@ def FollowScore(self, offset, queue_number):
4485
4492
if future_time_slice is not None :
4486
4493
try :
4487
4494
if future_time_slice .page != self .current_page_index :
4488
- self .current_page_index = future_time_slice .page
4489
- self .UpdateMusicPane ()
4495
+ self .select_page (future_time_slice .page )
4490
4496
self .scroll_to_notes (self .music_pane .current_page , future_time_slice .indices )
4491
4497
elif future_time_slice .svg_row != self .last_played_svg_row and future_time_slice .indices :
4492
4498
self .last_played_svg_row = future_time_slice .svg_row
@@ -4521,7 +4527,7 @@ def OnRecordMetreSelected(self, evt):
4521
4527
menu = evt .EventObject
4522
4528
item = menu .FindItemById (evt .GetId ())
4523
4529
self .settings ['record_metre' ] = item .GetItemLabelText ()
4524
-
4530
+
4525
4531
4526
4532
# 1.3.6.3 [SS] 2015-05-03
4527
4533
def flip_tempobox (self , state ):
@@ -5056,19 +5062,6 @@ def export_html(self, tune, filepath):
5056
5062
def OnExportAllHTML (self , evt ):
5057
5063
self .export_tunes (_ ('HTML file' ), '.html' , self .export_html , only_selected = False , single_file = True )
5058
5064
5059
- def createArchive (self , rootDir , outputPath ):
5060
- cwd = os .getcwd ()
5061
- os .chdir (rootDir )
5062
- fout .write ('mimetype' , compress_type = zipfile .ZIP_STORED )
5063
- fileList = [os .path .join ('META-INF' , 'container.xml' ), os .path .join ('OEBPS' , 'content.opf' )]
5064
- for itemPath in EpubBook .__listManifestItems (os .path .join ('OEBPS' , 'content.opf' )):
5065
- fileList .append (os .path .join ('OEBPS' , itemPath ))
5066
- for filePath in fileList :
5067
- fout .write (filePath , compress_type = zipfile .ZIP_DEFLATED )
5068
- fout .close ()
5069
- os .chdir (cwd )
5070
-
5071
-
5072
5065
def OnExportAllEpub (self , evt ):
5073
5066
tunes = []
5074
5067
for i in range (self .tune_list .GetItemCount ()):
@@ -6306,8 +6299,7 @@ def ScrollMusicPaneToMatchEditor(self, select_closest_note=False, select_closest
6306
6299
break
6307
6300
6308
6301
if new_page_index is not None and new_page_index != self .current_page_index :
6309
- self .current_page_index = new_page_index
6310
- self .UpdateMusicPane ()
6302
+ self .select_page (new_page_index )
6311
6303
6312
6304
closest_xy = None
6313
6305
closest_col = - 9999
@@ -6409,7 +6401,7 @@ def DoReMiToNote(self, char):
6409
6401
if matches :
6410
6402
K = matches [- 1 ]
6411
6403
doremi_index = doremi_prefixes .index (char )
6412
- base_note_index = all_notes . index (K .upper ())
6404
+ base_note_index = note_to_index (K .upper ())
6413
6405
note = all_notes [base_note_index + doremi_index ]
6414
6406
if char == char .upper ():
6415
6407
return note [0 ].upper ()
@@ -6418,8 +6410,7 @@ def DoReMiToNote(self, char):
6418
6410
return char
6419
6411
6420
6412
def OnCharEvent (self , evt ):
6421
- style = self .editor .GetStyleAt (self .editor .GetCurrentPos ())
6422
- is_default_style = (style in [self .styler .STYLE_DEFAULT , self .styler .STYLE_GRACE ])
6413
+ in_music_code = self .position_is_music_code (self .editor .GetCurrentPos ())
6423
6414
6424
6415
# 1.3.7 [JWdJ] 2016-01-06
6425
6416
if self .current_svg_tune and evt .KeyCode in [wx .WXK_PAGEDOWN , wx .WXK_PAGEUP , wx .WXK_HOME , wx .WXK_END ]:
@@ -6435,8 +6426,7 @@ def OnCharEvent(self, evt):
6435
6426
new_page = self .current_page_index - 1
6436
6427
6437
6428
if 0 <= new_page < self .current_svg_tune .page_count and new_page != self .current_page_index :
6438
- self .current_page_index = new_page
6439
- self .UpdateMusicPane ()
6429
+ self .select_page (new_page )
6440
6430
evt .Skip ()
6441
6431
return
6442
6432
@@ -6452,7 +6442,8 @@ def OnCharEvent(self, evt):
6452
6442
6453
6443
at_end_of_line = not self .editor .GetTextRange (self .editor .GetCurrentPos (), self .editor .GetLineEndPosition (self .editor .GetCurrentLine ())).strip ('| : ] [' )
6454
6444
6455
- if self .mni_TA_active .IsChecked () and not is_inside_field and is_default_style :
6445
+ use_typing_assist = self .mni_TA_active .IsChecked ()
6446
+ if use_typing_assist and not is_inside_field and in_music_code :
6456
6447
if c == ' ' :
6457
6448
try :
6458
6449
self .FixNoteDurations ()
@@ -6486,15 +6477,15 @@ def OnCharEvent(self, evt):
6486
6477
if (line .rstrip (), caret ) == (u'X' , 1 ):
6487
6478
wx .CallAfter (self .AutoInsertXNum )
6488
6479
6489
- elif c == '3' and p1 == p2 and self .editor .GetTextRange (p1 - 1 , p1 + 1 ) == '()' and is_default_style :
6480
+ elif c == '3' and p1 == p2 and self .editor .GetTextRange (p1 - 1 , p1 + 1 ) == '()' and in_music_code :
6490
6481
# if the user writes ( which is auto-completed to () and then writes 3, he/she probably
6491
6482
# wants to start a triplet so we delete the right parenthesis
6492
6483
self .editor .BeginUndoAction ()
6493
6484
self .editor .SetSelection (p1 , p1 + 1 )
6494
6485
self .editor .ReplaceSelection (c )
6495
6486
self .editor .EndUndoAction ()
6496
6487
6497
- elif (c in ']}' and self .editor .GetTextRange (p1 , p1 + 1 ) == c and is_default_style ) or \
6488
+ elif (c in ']}' and self .editor .GetTextRange (p1 , p1 + 1 ) == c and in_music_code ) or \
6498
6489
(c == '"' and self .editor .GetTextRange (p1 , p1 + 1 ) == c and self .editor .GetTextRange (p1 - 1 , p1 ) != '\\ ' ):
6499
6490
(text ,pos ) = self .editor .GetCurLine ()
6500
6491
# unless this is not a field line
@@ -6537,7 +6528,7 @@ def OnCharEvent(self, evt):
6537
6528
self .editor .InsertText (p2 + 1 , end )
6538
6529
self .editor .SetSelection (p1 + 1 , p2 + 1 )
6539
6530
self .editor .EndUndoAction ()
6540
- elif is_default_style and ( self . mni_TA_active . IsChecked () and self .mni_TA_add_right .IsChecked () ):
6531
+ elif in_music_code and use_typing_assist and self .mni_TA_add_right .IsChecked ():
6541
6532
line , _ = self .editor .GetCurLine ()
6542
6533
if c == '"' and line .count ('"' ) % 2 == 1 or \
6543
6534
c != '"' and line .count (end ) > line .count (start ):
@@ -6593,7 +6584,7 @@ def OnCharEvent(self, evt):
6593
6584
self .editor .SetSelection (p1 , p2 + total_offset )
6594
6585
finally :
6595
6586
self .editor .EndUndoAction ()
6596
- elif self .keyboard_input_mode and is_default_style :
6587
+ elif self .keyboard_input_mode and in_music_code :
6597
6588
keys = u'asdfghjkl\xf6 \xe4 '
6598
6589
sharp_keys = '' #u'\x00wertyuiop\xe5\x00'
6599
6590
flat_keys = '' #u'<zxcvbnm,.-'
@@ -6615,7 +6606,7 @@ def OnCharEvent(self, evt):
6615
6606
self .editor .ReplaceSelection (accidental + note )
6616
6607
6617
6608
# automatically select uppercase/lowercase - choose the one that will make this note be closest to the previous note
6618
- elif p1 == p2 and at_end_of_line and is_default_style and (self . mni_TA_active . IsChecked () and self .mni_TA_auto_case .IsChecked ()) and \
6609
+ elif p1 == p2 and at_end_of_line and in_music_code and (use_typing_assist and self .mni_TA_auto_case .IsChecked ()) and \
6619
6610
(not self .mni_TA_do_re_mi .IsChecked () and c in 'abcdefgABCDEFG' or \
6620
6611
self .mni_TA_do_re_mi .IsChecked () and c in doremi_prefixes ):
6621
6612
last_note_number = None
@@ -6632,10 +6623,10 @@ def OnCharEvent(self, evt):
6632
6623
6633
6624
# go backwards (to the left from the cursor) and look for the first note
6634
6625
for i in range (len (text )- 1 ):
6635
- if p - i >= 1 and self .editor . GetStyleAt (p - i - 1 ) in [ self . styler . STYLE_DEFAULT , self . styler . STYLE_GRACE ] :
6636
- m = re .match (r"([A-Ga-g]) [,']?" , text [len (text )- 1 - i : len (text )- 1 - i + 2 ])
6626
+ if p - i >= 1 and self .position_is_music_code (p - i - 1 ):
6627
+ m = re .match (r"([A-Ga-g][,']?) " , text [len (text )- 1 - i : len (text )- 1 - i + 2 ])
6637
6628
if m :
6638
- last_note_number = all_notes . index (m .group (0 ))
6629
+ last_note_number = note_to_index (m .group (0 ))
6639
6630
break
6640
6631
6641
6632
if last_note_number is None :
@@ -6660,7 +6651,7 @@ def OnCharEvent(self, evt):
6660
6651
else :
6661
6652
evt .Skip ()
6662
6653
6663
- elif self . mni_TA_active . IsChecked () and self .mni_TA_do_re_mi .IsChecked () and is_default_style :
6654
+ elif use_typing_assist and self .mni_TA_do_re_mi .IsChecked () and in_music_code :
6664
6655
if c in doremi_prefixes :
6665
6656
c = self .DoReMiToNote (c )
6666
6657
self .editor .AddText (c )
@@ -6813,6 +6804,9 @@ def replace_selection(self, text):
6813
6804
self .editor .ReplaceSelection (text )
6814
6805
self .editor .EndUndoAction ()
6815
6806
6807
+ def position_is_music_code (self , position ):
6808
+ return self .editor .GetStyleAt (position ) in [self .styler .STYLE_DEFAULT , self .styler .STYLE_GRACE ]
6809
+
6816
6810
def OnKeyDownEvent (self , evt ):
6817
6811
# temporary work-around for what seems to be a scintilla bug on Mac:
6818
6812
if wx .Platform == "__WXMAC__" and evt .GetRawKeyCode () == 7683 :
@@ -6828,13 +6822,13 @@ def OnKeyDownEvent(self, evt):
6828
6822
6829
6823
line , caret = self .editor .GetCurLine ()
6830
6824
is_inside_field = len (line )>= 2 and line [1 ] == ':' and re .match (r'[A-Za-z]' , line [0 ]) or line .startswith ('%' )
6831
- is_default_style = (self .editor .GetStyleAt (self .editor .GetCurrentPos ()) in
6832
- [self .styler .STYLE_DEFAULT , self .styler .STYLE_GRACE ])
6825
+ in_music_code = self .position_is_music_code (self .editor .GetCurrentPos ())
6833
6826
6827
+ use_typing_assist = self .mni_TA_active .IsChecked ()
6834
6828
if evt .GetKeyCode () == wx .WXK_RETURN :
6835
6829
line = self .editor .GetCurrentLine ()
6836
6830
# 1.3.7.2 [JWDJ] 2016-03-17
6837
- if self . mni_TA_active . IsChecked () and self .mni_TA_add_bar_auto .IsChecked () and not is_inside_field and is_default_style :
6831
+ if use_typing_assist and self .mni_TA_add_bar_auto .IsChecked () and not is_inside_field and in_music_code :
6838
6832
self .add_bar_if_needed ()
6839
6833
6840
6834
# 1.3.6.3 [JWDJ] 2015-04-21 Added line continuation
@@ -6877,7 +6871,7 @@ def StartKeyboardInputMode(self):
6877
6871
if notes :
6878
6872
self .keyboard_input_mode = True
6879
6873
m = re .match (r"([_=^]?)(?P<note>[A-Ga-gz][,']*)" , notes [- 1 ][- 1 ])
6880
- self .keyboard_input_base_note = all_notes . index (m .group ('note' ))
6874
+ self .keyboard_input_base_note = note_to_index (m .group ('note' ))
6881
6875
self .keyboard_input_base_key = None
6882
6876
if self .keyboard_input_base_note == - 1 :
6883
6877
self .keyboard_input_mode = False
@@ -7374,8 +7368,10 @@ def SetErrorMessage(self, error_msg):
7374
7368
self .editor .ScrollToLine (self .editor .LineFromPosition (self .editor .GetCurrentPos ()))
7375
7369
7376
7370
def OnPageSelected (self , evt ):
7377
- # 1.3.6.2 [JWdJ] 2015-02
7378
- self .current_page_index = self .cur_page_combo .GetSelection ()
7371
+ self .select_page (self .cur_page_combo .GetSelection ())
7372
+
7373
+ def select_page (self , page_index ):
7374
+ self .current_page_index = page_index
7379
7375
self .UpdateMusicPane ()
7380
7376
7381
7377
def UpdateMusicPane (self ):
0 commit comments