Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello โ I'm @olemoritz on Twitter.
IPhone doesn't make speech.
-
I use the following programs for my wife's wife's iPhone for the visually impaired.
My wife's iPhone seven s max is going to give a speech.
However, I don't make speech in my iPhone XS Max.
Is this due to the difference in the device?
import ui from objc_util import * import clipboard import speech v = ui.View() v.frame = (0,0,500,320) v.name = 'Move cursor in TextView' tv = ui.TextView() tv.name = 'TextView' tv.frame = (120,10,370,140) tv.font = ('Arial Rounded MT Bold',20) tv.text = 'aรฉ๐ข๐ฏ๐ต๐จโ๐จโ๐งโ๐ฉโ๐จ' v.add_subview(tv) tv2 = ui.TextView() tv2.name = 'TextView2' tv2.frame = (120,160,370,140) tv2.font = ('Arial Rounded MT Bold',24) tv2.text = 'second' v.add_subview(tv2) def say_char(tv): # test speech character at cursor idxtopos = IndexToPos(tv,'') # list index to position i = tv.selected_range[0] #print(i,idxtopos) i = idxtopos[i] # used to check if same base character if i < len(tv.text): c = tv.text[i] if c == ' ': c ='space' speech.say(c,'jp-JP') def selected_range(tv,i): tvo = ObjCInstance(tv) p1 = tvo.positionFromPosition_offset_(tvo.beginningOfDocument(), i) p2 = p1 #p2 = tvo.positionFromPosition_offset_(tvo.beginningOfDocument(), i+1) tvo.selectedTextRange = tvo.textRangeFromPosition_toPosition_(p1, p2) say_char(tv) return # some emoji like flags count as 2 for len but as 4 for selected_range def IndexToPos(tv,type): tvo = ObjCInstance(tv) # build array index -> position in range idxtopos = [] pre_x = -1 #print(tv.text) i = 0 for c in tv.text: # nbr characters used e=1 รฉ=1 ๐=1 ๐ฏ๐ต=2 ๐จโ๐จโ๐งโ๐ง=7 # some emoji generate more than one character, # sometimes counted for more than one in range # 1,2,3->1 4->2 nb = 1 + int(len(c.encode('utf-8'))/4) for j in range(0,nb): p1 = tvo.positionFromPosition_offset_(tvo.beginningOfDocument(), len(idxtopos)) p2 = p1 rge = tvo.textRangeFromPosition_toPosition_(p1, p2) rect = tvo.firstRectForRange_(rge) # CGRect x = rect.origin.x if x == float('inf') or x == pre_x: # same x as previous one, composed character pass else: pre_x = x i = len(idxtopos) idxtopos.append(i) # start position of c #print(c,nb,len(idxtopos)-1,i,x) idxtopos.append(i+1) # end position of last c #print(idxtopos) # get index of actual cursor i = tv.selected_range[0] # actual position of cursor # often p is one of sub_chars, not always the first one p = idxtopos[i] # used to check if same base character #print(p,i,idxtopos) if type == 'left': if i == 0: return # already before character while True: i = i - 1 if idxtopos[i] != p: q = idxtopos[i] # seach first sub-character while i > 0: if idxtopos[i-1] != q: break i = i - 1 break elif type == 'right': if i == (len(idxtopos)-1): return # already after last character while True: i = i + 1 if idxtopos[i] != p: break elif type == 'end': i = len(idxtopos)-1 else: return idxtopos r = idxtopos[i] selected_range(tv,i) return idxtopos b_top = ui.Button() b_top.frame = (10,10,100,32) b_top.title = 'begin' b_top.background_color = 'white' b_top.border_width = 1 def b_top_action(sender): name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name()) tv = sender.superview[name] tv.selected_range = (0,0) say_char(tv) b_top.action = b_top_action v.add_subview(b_top) b_left = ui.Button() b_left.frame = (10,50,100,32) b_left.title = 'left' b_left.background_color = 'white' b_left.border_width = 1 def b_left_action(sender): name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name()) tv = sender.superview[name] idxtopos = IndexToPos(tv,'left') # list index to position b_left.action = b_left_action v.add_subview(b_left) b_right = ui.Button() b_right.frame = (10,90,100,32) b_right.title = 'right' b_right.background_color = 'white' b_right.border_width = 1 def b_right_action(sender): name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name()) tv = sender.superview[name] idxtopos = IndexToPos(tv,'right') # list index to position b_right.action = b_right_action v.add_subview(b_right) b_bottom = ui.Button() b_bottom.frame = (10,130,100,32) b_bottom.title = 'end' b_bottom.background_color = 'white' b_bottom.border_width = 1 def b_bottom_action(sender): name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name()) tv = sender.superview[name] idxtopos = IndexToPos(tv,'end') # list index to position b_bottom.action = b_bottom_action v.add_subview(b_bottom) def get_xy(tv): idxtopos = IndexToPos(tv,'') # list index to position tvo = ObjCInstance(tv) x_y = [] for i in range(0,len(idxtopos)+1): # x,y of each character p1 = tvo.positionFromPosition_offset_(tvo.beginningOfDocument(), i) rge = tvo.textRangeFromPosition_toPosition_(p1,p1) rect = tvo.firstRectForRange_(rge) # CGRect x,y = rect.origin.x,rect.origin.y if i == len(idxtopos): if i > 0: x,y = x_y[i-1] else: # text is empty x,y = 0,0 if x == float('inf'): x,y = x_prec+15,y_prec x_prec,y_prec = x,y x_y.append((x,y)) return x_y b_up = ui.Button() b_up.frame = (10,170,100,32) b_up.title = 'up' b_up.background_color = 'white' b_up.border_width = 1 def b_up_action(sender): name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name()) tv = sender.superview[name] x_y = get_xy(tv) c = tv.selected_range[0] xc,yc = x_y[c] i = c - 1 while i >= 0: x,y = x_y[i] if y < yc: # previous row if x <= xc: selected_range(tv,i) return i = i - 1 b_up.action = b_up_action v.add_subview(b_up) b_down = ui.Button() b_down.frame = (10,210,100,32) b_down.title = 'down' b_down.background_color = 'white' b_down.border_width = 1 def b_down_action(sender): name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name()) tv = sender.superview[name] idxtopos = IndexToPos(tv,'') # list index to position x_y = get_xy(tv) c = tv.selected_range[0] #print(x_y,c) xc,yc = x_y[c] i = c# - 1 # I don't remember why this "- 1" while i < len(idxtopos): x,y = x_y[i] if y > yc: # next row if x >= xc: selected_range(tv,i) return else: if (i+1) < len(idxtopos): if x_y[i+1][1] > y: # i = last character of row under cursor selected_range(tv,i) return else: pass # try next x else: # last character of last row selected_range(tv,i) return i = i + 1 b_down.action = b_down_action v.add_subview(b_down) b_copy = ui.Button() b_copy.frame = (10,250,100,32) b_copy.title = 'copy' b_copy.background_color = 'white' b_copy.border_width = 1 def b_copy_action(sender): name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name()) tv = sender.superview[name] clipboard.set(tv.text) b_copy.action = b_copy_action v.add_subview(b_copy) b_clear = ui.Button() b_clear.frame = (10,290,100,32) b_clear.title = 'clear' b_clear.background_color = 'white' b_clear.border_width = 1 def b_clear_action(sender): name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name()) tv = sender.superview[name] tv.text = '' b_clear.action = b_clear_action v.add_subview(b_clear) def typeChar(sender): '''finds active textinput, and types the button's title''' tf=sender.objc_instance.firstResponder() tf.insertText_(sender.title) #create special keys def prev(sender): '''simulates 'tab' key, go to next field ''' s=sender.objc_instance.firstResponder()._previousKeyResponder().becomeFirstResponder() buttons.append(ui.Button(image=ui.Image.named('iob:ios7_arrow_back_32'),action=prev)) def next(sender): '''simulates 'tab' key, go to next field ''' s=sender.objc_instance.firstResponder()._nextKeyResponder().becomeFirstResponder() buttons.append(ui.Button(image=ui.Image.named('iob:ios7_arrow_forward_32'),action=next)) #create normal keys d = 32 dd = 4 emojis = '๐๐๐ฑ๐ฆโ๏ธ๐๐๐๐๐๐ ๐๐คฃโบ๏ธ๐๐๐๐๐๐๐๐ฅฐ๐๐๐๐๐๐๐๐๐คช๐คจ๐ง๐ค๐๐คฉ๐ฅณ๐๐๐๐๐๐๐โน๏ธ๐ฃ๐๐ซ๐ฉ๐ฅบ๐ข๐ญ๐ค๐ ๐ก๐คฌ๐คฏ๐ณ๐ฅต๐ฅถ๐ฑ๐จ๐ฐ๐ฅ๐๐ค๐ค๐คญ๐คซ๐คฅ๐ถ๐๐๐ฌ๐ฆ๐ง๐ฎ๐ฒ๐ด๐คค๐ช๐ต๐ค๐ฅด๐คข๐คฎ๐คง๐ท๐ค๐ค๐ค๐ค ๐' n_emojis_in_set = 10 n_sets = 1 + int((len(emojis)-1)/n_emojis_in_set) tv.i_set = 0 tv.n_sets = n_sets def nextSet(sender): name = str(ObjCClass('UIApplication').sharedApplication().keyWindow().firstResponder().name()) tv = v[name] tv.i_set = tv.i_set + 1 if tv.i_set == tv.n_sets: tv.i_set = 0 #attach our accessory to the textfield, and textview ww = vv_array[tv.i_set] tvo = tv.objc_instance #print(dir(tvo)) tvo.setInputAccessoryView_(ObjCInstance(ww)) tvo.reloadInputViews() vv_array = [] for i_set in range(0,n_sets): l = int(len(emojis)/n_sets) i = i_set * l set_emojis = emojis[i:i+l] w, h = ui.get_screen_size() vv = ui.View(name='set'+str(i_set)) vv.background_color = 'lightgray' h = 0 x = dd y = dd for button_title in set_emojis: b = ui.Button(title=button_title) b_action = typeChar b.action=b_action b.frame = (x,y,d,d) b.font = ('.SFUIText', d) if (y+d+dd) > h: h = y + d + dd vv.add_subview(b) x = x + d + dd if (x+d+dd) > w: x = dd y = y + d + dd device = ObjCClass('UIDevice').currentDevice().model() if str(device) == 'iPhone': bb_target = ui.Button() bb_target.title = 'next emojis' wb,hb = ui.measure_string(bb_target.title,font=bb_target.font) bb_target.action = nextSet bb_target.frame = (dd,h,wb+2,d) vv.add_subview(bb_target) h = h + d + dd vv.frame = (0,0,w,h) vv_array.append(vv) #nextSet(vv_array[n_sets-1]['nextSet']) # display 1st set device = ObjCClass('UIDevice').currentDevice().model() if str(device) == 'iPad': # add a button at right of "typing suggestions", just above the keyboard bb_target = ui.Button() bb_target.action = nextSet UIBarButtonItem = ObjCClass('UIBarButtonItem').alloc().initWithTitle_style_target_action_('next emojis',0,bb_target,sel('invokeAction:')).autorelease() #UIBarButtonItem = ObjCClass('UIBarButtonItem').alloc().initWithImage_style_target_action_(ns(ui.Image.named('emj:Bicycle').with_rendering_mode(ui.RENDERING_MODE_ORIGINAL)),0,bb_target,sel('invokeAction:')).autorelease() UIBarButtonItemGroup = ObjCClass('UIBarButtonItemGroup').alloc().initWithBarButtonItems_representativeItem_([UIBarButtonItem],None) for tv in v.subviews: if 'TextView' in str(type(tv)): tv.i_set = 0 tv.n_sets = n_sets tvo = tv.objc_instance if str(device) == 'iPad': #tvo.inputAssistantItem().setTrailingBarButtonGroups([UIBarButtonItemGroup]) tvo.inputAssistantItem().setLeadingBarButtonGroups([UIBarButtonItemGroup]) #print(dir(tvo)) #print(dir(tvo.inputAssistantItem())) ww = vv_array[tv.i_set] tvo.setInputAccessoryView_(ObjCInstance(ww)) tvo.reloadInputViews() v.present('sheet') v['TextView'].selected_range = (0,0) v['TextView'].begin_editing() #nextSet(vv_array[n_sets-1]['nextSet']) # display 1st set
-
@shinya.ta I sincerely hope somebody will help you. I have a very old iPhone 5s and the script does not work on it...
-
Hi, have you checked the physical mute switch on your phone? There should be a switch near the volume buttons, which, wenn activated, mutes specific sounds including most of pythonista sounds.
-
It was nothing to do with the mute button.
In iPhone seven, this program is activated, and in the case of the current program, it is not responding to Xs Max.
-
@shinya.ta Just to test the speech function on your XS Max, please try this
import speech t = 'hello' speech.say(t)
-
-
@shinya.ta Then we are sure that the reason of "no speech" is not my big script.
Perhaps the iPhone has a problem? -
Even if my wife's iPhone and all the same programs are used, my wife makes speech, but I don't make speech on my iPhone.
I have a problem with my iPhone.