psychopy 2024.2.4__py3-none-any.whl → 2025.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of psychopy might be problematic. Click here for more details.

Files changed (903) hide show
  1. psychopy/CHANGELOG.txt +208 -4
  2. psychopy/LICENSE.txt +1 -1
  3. psychopy/VERSION +1 -1
  4. psychopy/__init__.py +10 -7
  5. psychopy/alerts/__init__.py +1 -1
  6. psychopy/alerts/_alerts.py +53 -17
  7. psychopy/alerts/_errorHandler.py +3 -4
  8. psychopy/alerts/alertsCatalogue/3210.yaml +27 -0
  9. psychopy/alerts/alertsCatalogue/3610.yaml +19 -0
  10. psychopy/alerts/alertsCatalogue/4130.yaml +19 -0
  11. psychopy/alerts/alertsCatalogue/alertCategories.yaml +8 -1
  12. psychopy/alerts/alertsCatalogue/alertmsg.py +1 -1
  13. psychopy/alerts/alerttools.py +0 -16
  14. psychopy/app/Resources/betasplash.png +0 -0
  15. psychopy/app/Resources/betasplash@2x.png +0 -0
  16. psychopy/app/Resources/classic/case.png +0 -0
  17. psychopy/app/Resources/classic/case@2x.png +0 -0
  18. psychopy/app/Resources/classic/fileaudio.png +0 -0
  19. psychopy/app/Resources/classic/fileaudio@2x.png +0 -0
  20. psychopy/app/Resources/classic/filecss.png +0 -0
  21. psychopy/app/Resources/classic/filecss@2x.png +0 -0
  22. psychopy/app/Resources/classic/filecsv.png +0 -0
  23. psychopy/app/Resources/classic/filecsv@2x.png +0 -0
  24. psychopy/app/Resources/classic/filedesign.png +0 -0
  25. psychopy/app/Resources/classic/filedesign@2x.png +0 -0
  26. psychopy/app/Resources/classic/filefont.png +0 -0
  27. psychopy/app/Resources/classic/filefont@2x.png +0 -0
  28. psychopy/app/Resources/classic/filegit.png +0 -0
  29. psychopy/app/Resources/classic/filegit@2x.png +0 -0
  30. psychopy/app/Resources/classic/filehtml.png +0 -0
  31. psychopy/app/Resources/classic/filehtml@2x.png +0 -0
  32. psychopy/app/Resources/classic/fileimage.png +0 -0
  33. psychopy/app/Resources/classic/fileimage@2x.png +0 -0
  34. psychopy/app/Resources/classic/fileinfo.png +0 -0
  35. psychopy/app/Resources/classic/fileinfo@2x.png +0 -0
  36. psychopy/app/Resources/classic/filejs.png +0 -0
  37. psychopy/app/Resources/classic/filejs@2x.png +0 -0
  38. psychopy/app/Resources/classic/filejson.png +0 -0
  39. psychopy/app/Resources/classic/filejson@2x.png +0 -0
  40. psychopy/app/Resources/classic/filepkg.png +0 -0
  41. psychopy/app/Resources/classic/filepkg@2x.png +0 -0
  42. psychopy/app/Resources/classic/filepsyexp.png +0 -0
  43. psychopy/app/Resources/classic/filepsyexp@2x.png +0 -0
  44. psychopy/app/Resources/classic/filepy.png +0 -0
  45. psychopy/app/Resources/classic/filepy@2x.png +0 -0
  46. psychopy/app/Resources/classic/filetxt.png +0 -0
  47. psychopy/app/Resources/classic/filetxt@2x.png +0 -0
  48. psychopy/app/Resources/classic/fileunknown.png +0 -0
  49. psychopy/app/Resources/classic/fileunknown@2x.png +0 -0
  50. psychopy/app/Resources/classic/filevideo.png +0 -0
  51. psychopy/app/Resources/classic/filevideo@2x.png +0 -0
  52. psychopy/app/Resources/classic/find.png +0 -0
  53. psychopy/app/Resources/classic/find@2x.png +0 -0
  54. psychopy/app/Resources/classic/loop.png +0 -0
  55. psychopy/app/Resources/classic/loop@2x.png +0 -0
  56. psychopy/app/Resources/classic/regex.png +0 -0
  57. psychopy/app/Resources/classic/regex@2x.png +0 -0
  58. psychopy/app/Resources/dark/case.png +0 -0
  59. psychopy/app/Resources/dark/case@2x.png +0 -0
  60. psychopy/app/Resources/dark/fileaudio.png +0 -0
  61. psychopy/app/Resources/dark/fileaudio@2x.png +0 -0
  62. psychopy/app/Resources/dark/filecss.png +0 -0
  63. psychopy/app/Resources/dark/filecss@2x.png +0 -0
  64. psychopy/app/Resources/dark/filecsv.png +0 -0
  65. psychopy/app/Resources/dark/filecsv@2x.png +0 -0
  66. psychopy/app/Resources/dark/filedesign.png +0 -0
  67. psychopy/app/Resources/dark/filedesign@2x.png +0 -0
  68. psychopy/app/Resources/dark/filefont.png +0 -0
  69. psychopy/app/Resources/dark/filefont@2x.png +0 -0
  70. psychopy/app/Resources/dark/filegit.png +0 -0
  71. psychopy/app/Resources/dark/filegit@2x.png +0 -0
  72. psychopy/app/Resources/dark/filehtml.png +0 -0
  73. psychopy/app/Resources/dark/filehtml@2x.png +0 -0
  74. psychopy/app/Resources/dark/fileimage.png +0 -0
  75. psychopy/app/Resources/dark/fileimage@2x.png +0 -0
  76. psychopy/app/Resources/dark/fileinfo.png +0 -0
  77. psychopy/app/Resources/dark/fileinfo@2x.png +0 -0
  78. psychopy/app/Resources/dark/filejs.png +0 -0
  79. psychopy/app/Resources/dark/filejs@2x.png +0 -0
  80. psychopy/app/Resources/dark/filejson.png +0 -0
  81. psychopy/app/Resources/dark/filejson@2x.png +0 -0
  82. psychopy/app/Resources/dark/filepkg.png +0 -0
  83. psychopy/app/Resources/dark/filepkg@2x.png +0 -0
  84. psychopy/app/Resources/dark/filepsyexp.png +0 -0
  85. psychopy/app/Resources/dark/filepsyexp@2x.png +0 -0
  86. psychopy/app/Resources/dark/filepy.png +0 -0
  87. psychopy/app/Resources/dark/filepy@2x.png +0 -0
  88. psychopy/app/Resources/dark/filetxt.png +0 -0
  89. psychopy/app/Resources/dark/filetxt@2x.png +0 -0
  90. psychopy/app/Resources/dark/fileunknown.png +0 -0
  91. psychopy/app/Resources/dark/fileunknown@2x.png +0 -0
  92. psychopy/app/Resources/dark/filevideo.png +0 -0
  93. psychopy/app/Resources/dark/filevideo@2x.png +0 -0
  94. psychopy/app/Resources/dark/find.png +0 -0
  95. psychopy/app/Resources/dark/find@2x.png +0 -0
  96. psychopy/app/Resources/dark/loop.png +0 -0
  97. psychopy/app/Resources/dark/loop@2x.png +0 -0
  98. psychopy/app/Resources/dark/regex.png +0 -0
  99. psychopy/app/Resources/dark/regex@2x.png +0 -0
  100. psychopy/app/Resources/light/case.png +0 -0
  101. psychopy/app/Resources/light/case@2x.png +0 -0
  102. psychopy/app/Resources/light/fileaudio.png +0 -0
  103. psychopy/app/Resources/light/fileaudio@2x.png +0 -0
  104. psychopy/app/Resources/light/filecss.png +0 -0
  105. psychopy/app/Resources/light/filecss@2x.png +0 -0
  106. psychopy/app/Resources/light/filecsv.png +0 -0
  107. psychopy/app/Resources/light/filecsv@2x.png +0 -0
  108. psychopy/app/Resources/light/filedesign.png +0 -0
  109. psychopy/app/Resources/light/filedesign@2x.png +0 -0
  110. psychopy/app/Resources/light/filefont.png +0 -0
  111. psychopy/app/Resources/light/filefont@2x.png +0 -0
  112. psychopy/app/Resources/light/filegit.png +0 -0
  113. psychopy/app/Resources/light/filegit@2x.png +0 -0
  114. psychopy/app/Resources/light/filehtml.png +0 -0
  115. psychopy/app/Resources/light/filehtml@2x.png +0 -0
  116. psychopy/app/Resources/light/fileimage.png +0 -0
  117. psychopy/app/Resources/light/fileimage@2x.png +0 -0
  118. psychopy/app/Resources/light/fileinfo.png +0 -0
  119. psychopy/app/Resources/light/fileinfo@2x.png +0 -0
  120. psychopy/app/Resources/light/filejs.png +0 -0
  121. psychopy/app/Resources/light/filejs@2x.png +0 -0
  122. psychopy/app/Resources/light/filejson.png +0 -0
  123. psychopy/app/Resources/light/filejson@2x.png +0 -0
  124. psychopy/app/Resources/light/filepkg.png +0 -0
  125. psychopy/app/Resources/light/filepkg@2x.png +0 -0
  126. psychopy/app/Resources/light/filepsyexp.png +0 -0
  127. psychopy/app/Resources/light/filepsyexp@2x.png +0 -0
  128. psychopy/app/Resources/light/filepy.png +0 -0
  129. psychopy/app/Resources/light/filepy@2x.png +0 -0
  130. psychopy/app/Resources/light/filetxt.png +0 -0
  131. psychopy/app/Resources/light/filetxt@2x.png +0 -0
  132. psychopy/app/Resources/light/fileunknown.png +0 -0
  133. psychopy/app/Resources/light/fileunknown@2x.png +0 -0
  134. psychopy/app/Resources/light/filevideo.png +0 -0
  135. psychopy/app/Resources/light/filevideo@2x.png +0 -0
  136. psychopy/app/Resources/light/find.png +0 -0
  137. psychopy/app/Resources/light/find@2x.png +0 -0
  138. psychopy/app/Resources/light/loop.png +0 -0
  139. psychopy/app/Resources/light/loop@2x.png +0 -0
  140. psychopy/app/Resources/light/regex.png +0 -0
  141. psychopy/app/Resources/light/regex@2x.png +0 -0
  142. psychopy/app/Resources/routine_templates/Basic.psyexp +0 -1
  143. psychopy/app/Resources/routine_templates/Misc.psyexp +0 -1
  144. psychopy/app/Resources/routine_templates/Online.psyexp +0 -2
  145. psychopy/app/Resources/routine_templates/Trials.psyexp +0 -1
  146. psychopy/app/Resources/splash.png +0 -0
  147. psychopy/app/Resources/splash@2x.png +0 -0
  148. psychopy/app/__init__.py +49 -8
  149. psychopy/app/__main__.py +3 -0
  150. psychopy/app/_psychopyApp.py +134 -125
  151. psychopy/app/builder/builder.py +42 -22
  152. psychopy/app/builder/dialogs/__init__.py +44 -11
  153. psychopy/app/builder/dialogs/dlgsCode.py +1 -1
  154. psychopy/app/builder/dialogs/dlgsConditions.py +1 -1
  155. psychopy/app/builder/dialogs/findDlg.py +106 -20
  156. psychopy/app/builder/dialogs/paramCtrls.py +42 -1
  157. psychopy/app/builder/validators.py +1 -1
  158. psychopy/app/coder/codeEditorBase.py +8 -8
  159. psychopy/app/coder/coder.py +32 -29
  160. psychopy/app/coder/fileBrowser.py +68 -22
  161. psychopy/app/coder/folding.py +1 -1
  162. psychopy/app/coder/psychoParser.py +1 -1
  163. psychopy/app/coder/repl.py +1 -1
  164. psychopy/app/coder/sourceTree.py +1 -1
  165. psychopy/app/connections/__init__.py +1 -1
  166. psychopy/app/connections/news.py +1 -1
  167. psychopy/app/connections/sendusage.py +1 -1
  168. psychopy/app/connections/updates.py +1 -1
  169. psychopy/app/console.py +1 -1
  170. psychopy/app/errorDlg.py +1 -1
  171. psychopy/app/frametracker.py +1 -1
  172. psychopy/app/idle.py +1 -1
  173. psychopy/app/jobs.py +5 -2
  174. psychopy/app/linuxconfig/__init__.py +1 -1
  175. psychopy/app/locale/ar_001/LC_MESSAGE/messages.mo +0 -0
  176. psychopy/app/locale/ar_001/LC_MESSAGE/messages.po +1514 -3259
  177. psychopy/app/locale/cs_CZ/LC_MESSAGE/messages.mo +0 -0
  178. psychopy/app/locale/da_DK/LC_MESSAGE/messages.mo +0 -0
  179. psychopy/app/locale/de_DE/LC_MESSAGE/messages.mo +0 -0
  180. psychopy/app/locale/de_DE/LC_MESSAGE/messages.po +3 -3
  181. psychopy/app/locale/el_GR/LC_MESSAGE/messages.mo +0 -0
  182. psychopy/app/locale/en_NZ/LC_MESSAGE/messages.mo +0 -0
  183. psychopy/app/locale/en_US/LC_MESSAGE/messages.mo +0 -0
  184. psychopy/app/locale/es_CO/LC_MESSAGE/messages.mo +0 -0
  185. psychopy/app/locale/es_CO/LC_MESSAGE/messages.po +4 -4
  186. psychopy/app/locale/es_ES/LC_MESSAGE/messages.mo +0 -0
  187. psychopy/app/locale/es_ES/LC_MESSAGE/messages.po +4 -4
  188. psychopy/app/locale/es_US/LC_MESSAGE/messages.mo +0 -0
  189. psychopy/app/locale/es_US/LC_MESSAGE/messages.po +4 -4
  190. psychopy/app/locale/et_EE/LC_MESSAGE/messages.mo +0 -0
  191. psychopy/app/locale/et_EE/LC_MESSAGE/messages.po +2 -2
  192. psychopy/app/locale/fa_IR/LC_MESSAGE/messages.mo +0 -0
  193. psychopy/app/locale/fa_IR/LC_MESSAGE/messages.po +1 -1
  194. psychopy/app/locale/fi_FI/LC_MESSAGE/messages.mo +0 -0
  195. psychopy/app/locale/fr_FR/LC_MESSAGE/messages.mo +0 -0
  196. psychopy/app/locale/fr_FR/LC_MESSAGE/messages.po +2 -2
  197. psychopy/app/locale/he_IL/LC_MESSAGE/messages.mo +0 -0
  198. psychopy/app/locale/he_IL/LC_MESSAGE/messages.po +2 -2
  199. psychopy/app/locale/hi_IN/LC_MESSAGE/messages.mo +0 -0
  200. psychopy/app/locale/hi_IN/LC_MESSAGE/messages.po +2 -2
  201. psychopy/app/locale/hu_HU/LC_MESSAGE/messages.mo +0 -0
  202. psychopy/app/locale/it_IT/LC_MESSAGE/messages.mo +0 -0
  203. psychopy/app/locale/it_IT/LC_MESSAGE/messages.po +2 -2
  204. psychopy/app/locale/ja_JP/LC_MESSAGE/messages.mo +0 -0
  205. psychopy/app/locale/ja_JP/LC_MESSAGE/messages.po +3421 -2396
  206. psychopy/app/locale/ko_KR/LC_MESSAGE/messages.mo +0 -0
  207. psychopy/app/locale/ms_MY/LC_MESSAGE/messages.mo +0 -0
  208. psychopy/app/locale/ms_MY/LC_MESSAGE/messages.po +2 -2
  209. psychopy/app/locale/nl_NL/LC_MESSAGE/messages.mo +0 -0
  210. psychopy/app/locale/nn_NO/LC_MESSAGE/messages.mo +0 -0
  211. psychopy/app/locale/pl_PL/LC_MESSAGE/messages.mo +0 -0
  212. psychopy/app/locale/pt_PT/LC_MESSAGE/messages.mo +0 -0
  213. psychopy/app/locale/pt_PT/LC_MESSAGE/messages.po +4 -4
  214. psychopy/app/locale/ro_RO/LC_MESSAGE/messages.mo +0 -0
  215. psychopy/app/locale/ru_RU/LC_MESSAGE/messages.mo +0 -0
  216. psychopy/app/locale/sv_SE/LC_MESSAGE/messages.mo +0 -0
  217. psychopy/app/locale/sv_SE/LC_MESSAGE/messages.po +2 -2
  218. psychopy/app/locale/tr_TR/LC_MESSAGE/messages.mo +0 -0
  219. psychopy/app/locale/tr_TR/LC_MESSAGE/messages.po +2 -2
  220. psychopy/app/locale/zh_CN/LC_MESSAGE/messages.mo +0 -0
  221. psychopy/app/locale/zh_CN/LC_MESSAGE/messages.po +3 -3
  222. psychopy/app/locale/zh_TW/LC_MESSAGE/messages.mo +0 -0
  223. psychopy/app/locale/zh_TW/LC_MESSAGE/messages.po +2 -2
  224. psychopy/app/{builder/localizedStrings.py → localizedStrings.py} +173 -26
  225. psychopy/app/pavlovia_ui/__init__.py +1 -1
  226. psychopy/app/pavlovia_ui/_base.py +1 -1
  227. psychopy/app/pavlovia_ui/functions.py +1 -1
  228. psychopy/app/pavlovia_ui/menu.py +1 -1
  229. psychopy/app/pavlovia_ui/project.py +1 -1
  230. psychopy/app/pavlovia_ui/search.py +1 -1
  231. psychopy/app/pavlovia_ui/sync.py +1 -1
  232. psychopy/app/pavlovia_ui/user.py +1 -1
  233. psychopy/app/plugin_manager/dialog.py +34 -96
  234. psychopy/app/plugin_manager/packages.py +10 -14
  235. psychopy/app/plugin_manager/plugins.py +64 -4
  236. psychopy/app/preferencesDlg.py +12 -37
  237. psychopy/app/psychopyApp.py +130 -44
  238. psychopy/app/ribbon.py +1 -0
  239. psychopy/app/runner/runner.py +37 -15
  240. psychopy/app/runner/scriptProcess.py +11 -6
  241. psychopy/app/stdout/stdOutRich.py +9 -2
  242. psychopy/app/themes/fonts.py +1 -1
  243. psychopy/app/themes/icons.py +2 -38
  244. psychopy/app/ui/__init__.py +1 -1
  245. psychopy/app/utils.py +3 -3
  246. psychopy/assets/default.mp3 +0 -0
  247. psychopy/assets/fonts/NotoSans-Bold.ttf +0 -0
  248. psychopy/assets/fonts/NotoSans-BoldItalic.ttf +0 -0
  249. psychopy/assets/fonts/NotoSans-Italic.ttf +0 -0
  250. psychopy/assets/fonts/NotoSans-Regular.ttf +0 -0
  251. psychopy/assets/voicekeyThresholdStim.wav +0 -0
  252. psychopy/clock.py +4 -1
  253. psychopy/colors.py +2 -0
  254. psychopy/core.py +1 -1
  255. psychopy/data/base.py +1 -1
  256. psychopy/data/experiment.py +151 -46
  257. psychopy/data/routine.py +27 -1
  258. psychopy/data/staircase.py +2 -1
  259. psychopy/data/trial.py +62 -14
  260. psychopy/data/utils.py +1 -1
  261. psychopy/demos/builder/Design Templates/branchedExperiment/branchedExperiment.psyexp +333 -218
  262. psychopy/demos/builder/Design Templates/psychophysicsStaircase/psychophysicsStaircase.psyexp +261 -239
  263. psychopy/demos/builder/Design Templates/psychophysicsStairsInterleaved/psychophysicsStaircaseInterleaved.psyexp +319 -180
  264. psychopy/demos/builder/Design Templates/randomisedBlocks/randomisedBlocks.psyexp +204 -116
  265. psychopy/demos/builder/Experiments/BART/assets/background.jpg +0 -0
  266. psychopy/demos/builder/Experiments/BART/assets/blueBalloon.png +0 -0
  267. psychopy/demos/builder/Experiments/BART/assets/greenBalloon.png +0 -0
  268. psychopy/demos/builder/Experiments/BART/assets/redBalloon.png +0 -0
  269. psychopy/demos/builder/Experiments/BART/bart.psyexp +779 -866
  270. psychopy/demos/builder/Experiments/BigFiveInventory/BFI.psyexp +242 -180
  271. psychopy/demos/builder/Experiments/GoNoGo/gng.psyexp +419 -406
  272. psychopy/demos/builder/Experiments/dragAndDrop/README.md +2 -37
  273. psychopy/demos/builder/Experiments/dragAndDrop/drag_and_drop.psyexp +460 -1204
  274. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/blank_grid.png +0 -0
  275. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/make_shapes.psyexp +221 -0
  276. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/readme.md +4 -0
  277. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_1.png +0 -0
  278. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_10.png +0 -0
  279. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_2.png +0 -0
  280. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_3.png +0 -0
  281. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_4.png +0 -0
  282. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_5.png +0 -0
  283. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_6.png +0 -0
  284. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_7.png +0 -0
  285. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_8.png +0 -0
  286. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solution_9.png +0 -0
  287. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/solutions.xlsx +0 -0
  288. psychopy/demos/builder/Experiments/mentalRotation/MentalRotation.psyexp +583 -542
  289. psychopy/demos/builder/Experiments/navon/NavonTask.psyexp +458 -427
  290. psychopy/demos/builder/Experiments/sternberg/sternberg.psyexp +588 -550
  291. psychopy/demos/builder/Experiments/stroop/stroop.psyexp +303 -207
  292. psychopy/demos/builder/Experiments/stroopExtended/stroop.psyexp +390 -215
  293. psychopy/demos/builder/Experiments/stroopExtended/stroopReverse.psyexp +390 -215
  294. psychopy/demos/builder/Experiments/stroopVoice/stroopVoice.psyexp +357 -331
  295. psychopy/demos/builder/Feature Demos/buttonBox/buttonBoxDemo.psyexp +3 -2
  296. psychopy/demos/builder/Feature Demos/counterbalance/counterbalance.psyexp +287 -277
  297. psychopy/demos/builder/Feature Demos/gratings/gratings.psyexp +370 -320
  298. psychopy/demos/builder/Feature Demos/noise/noise.psyexp +452 -399
  299. psychopy/demos/builder/Feature Demos/panorama/panorama.psyexp +168 -133
  300. psychopy/demos/builder/Feature Demos/pilotMode/pilotMode.psyexp +4 -3
  301. psychopy/demos/builder/Feature Demos/progress/progressBar.psyexp +420 -392
  302. psychopy/demos/builder/Feature Demos/sliders/sliders.psyexp +917 -871
  303. psychopy/demos/builder/Feature Demos/visualValidator/readme.md +7 -0
  304. psychopy/demos/builder/Feature Demos/visualValidator/visualValidator.psyexp +200 -0
  305. psychopy/demos/builder/Hardware/EEG_parallel_component/EEG_triggers_parallel_comp.psyexp +25 -9
  306. psychopy/demos/builder/Hardware/EEG_serial_code/EEG_triggers_serial_code.psyexp +372 -361
  307. psychopy/demos/builder/Hardware/EEG_serial_component/EEG_triggers_serial_comp.psyexp +25 -9
  308. psychopy/demos/builder/Hardware/EGI_netstation/stroop.psyexp +320 -235
  309. psychopy/demos/builder/Hardware/Eyetracking_visual_search/visualSearch.psyexp +790 -651
  310. psychopy/demos/builder/Hardware/camera/camera.psyexp +326 -246
  311. psychopy/demos/builder/Hardware/eyetracking/eyetracking.psyexp +432 -327
  312. psychopy/demos/builder/Hardware/eyetracking_custom_cal/eyetracking_custom_cal.psyexp +440 -321
  313. psychopy/demos/builder/Hardware/fMRI/fMRI_demo.psyexp +190 -181
  314. psychopy/demos/builder/Hardware/lab_streaming_layer/lsl_triggers_demo.psyexp +323 -312
  315. psychopy/demos/builder/Hardware/lab_streaming_layer/lsl_triggers_demo_legacy.psyexp +360 -0
  316. psychopy/demos/builder/{Feature Demos/eyetracking/eyetracking.xml → Hardware/lab_streaming_layer/lsl_triggers_demo_legacy_legacy.psyexp} +154 -140
  317. psychopy/demos/builder/Hardware/lab_streaming_layer_legacy/lsl_triggers_demo_legacy.psyexp +329 -273
  318. psychopy/demos/builder/Hardware/lab_streaming_layer_legacy/lsl_triggers_demo_legacy_legacy.psyexp +360 -0
  319. psychopy/demos/builder/Hardware/lab_streaming_layer_legacy/lsl_triggers_demo_legacy_legacy_legacy.psyexp +312 -0
  320. psychopy/demos/builder/Hardware/microphone/microphone.psyexp +450 -404
  321. psychopy/demos/builder/Hardware/pump/pump.psyexp +593 -329
  322. psychopy/demos/builder/Helper Tools/achorVSalignment/FlowCircular-Regular.ttf +0 -0
  323. psychopy/demos/builder/Helper Tools/achorVSalignment/anchorAlignment.psyexp +336 -274
  324. psychopy/demos/builder/Helper Tools/clockFace/clockFace.psyexp +200 -149
  325. psychopy/demos/builder/Helper Tools/colors/colors.psyexp +300 -279
  326. psychopy/demos/builder/Helper Tools/drawPolygon/drawPolygon.psyexp +677 -564
  327. psychopy/demos/builder/Helper Tools/keyNameFinder/keyNameFinder.psyexp +214 -158
  328. psychopy/demos/builder/Helper Tools/spatialUnits/unitDemo.psyexp +195 -146
  329. psychopy/demos/coder/experiment control/runtimeInfo.py +1 -1
  330. psychopy/devices/__init__.py +1 -1
  331. psychopy/event.py +1 -1
  332. psychopy/exceptions.py +1 -1
  333. psychopy/experiment/__init__.py +1 -1
  334. psychopy/experiment/_experiment.py +62 -16
  335. psychopy/experiment/components/__init__.py +1 -6
  336. psychopy/experiment/components/_base.py +44 -19
  337. psychopy/experiment/components/aperture/__init__.py +1 -1
  338. psychopy/experiment/components/brush/__init__.py +2 -2
  339. psychopy/experiment/components/button/__init__.py +24 -28
  340. psychopy/experiment/components/camera/__init__.py +38 -39
  341. psychopy/experiment/components/code/__init__.py +1 -1
  342. psychopy/experiment/components/dots/__init__.py +1 -1
  343. psychopy/experiment/components/eyetracker_record/__init__.py +7 -3
  344. psychopy/experiment/components/form/__init__.py +3 -3
  345. psychopy/experiment/components/grating/__init__.py +1 -1
  346. psychopy/experiment/components/image/__init__.py +1 -1
  347. psychopy/experiment/components/joyButtons/__init__.py +2 -2
  348. psychopy/experiment/components/joyButtons/virtualJoyButtons.py +1 -1
  349. psychopy/experiment/components/joystick/__init__.py +3 -3
  350. psychopy/experiment/components/joystick/virtualJoystick.py +1 -1
  351. psychopy/experiment/components/keyboard/__init__.py +98 -122
  352. psychopy/experiment/components/microphone/__init__.py +54 -98
  353. psychopy/experiment/components/mouse/__init__.py +92 -93
  354. psychopy/experiment/components/movie/__init__.py +28 -50
  355. psychopy/experiment/components/parallelOut/__init__.py +3 -3
  356. psychopy/experiment/components/polygon/__init__.py +2 -3
  357. psychopy/experiment/components/roi/__init__.py +2 -2
  358. psychopy/experiment/components/routineSettings/__init__.py +2 -0
  359. psychopy/experiment/components/serialOut/__init__.py +7 -7
  360. psychopy/experiment/components/settings/__init__.py +317 -313
  361. psychopy/experiment/components/settings/eyetracking.py +108 -0
  362. psychopy/experiment/components/slider/__init__.py +5 -5
  363. psychopy/experiment/components/sound/__init__.py +168 -78
  364. psychopy/experiment/components/soundsensor/__init__.py +361 -0
  365. psychopy/experiment/components/soundsensor/classic/soundsensor.png +0 -0
  366. psychopy/experiment/components/soundsensor/classic/soundsensor@2x.png +0 -0
  367. psychopy/experiment/components/soundsensor/dark/soundsensor.png +0 -0
  368. psychopy/experiment/components/soundsensor/dark/soundsensor@2x.png +0 -0
  369. psychopy/experiment/components/soundsensor/light/soundsensor.png +0 -0
  370. psychopy/experiment/components/soundsensor/light/soundsensor@2x.png +0 -0
  371. psychopy/experiment/components/static/__init__.py +59 -33
  372. psychopy/experiment/components/text/__init__.py +2 -6
  373. psychopy/experiment/components/textbox/__init__.py +3 -7
  374. psychopy/experiment/components/unknown/__init__.py +2 -0
  375. psychopy/experiment/components/unknownPlugin/__init__.py +2 -0
  376. psychopy/experiment/exports.py +1 -1
  377. psychopy/experiment/flow.py +2 -2
  378. psychopy/experiment/localization.py +1 -1
  379. psychopy/experiment/loops.py +43 -10
  380. psychopy/experiment/params.py +6 -4
  381. psychopy/experiment/plugins.py +8 -1
  382. psychopy/experiment/py2js.py +1 -1
  383. psychopy/experiment/py2js_transpiler.py +1 -1
  384. psychopy/experiment/routines/__init__.py +1 -1
  385. psychopy/experiment/routines/_base.py +23 -24
  386. psychopy/experiment/routines/audioValidator/__init__.py +343 -0
  387. psychopy/experiment/routines/audioValidator/classic/audio_validator.png +0 -0
  388. psychopy/experiment/routines/audioValidator/classic/audio_validator@2x.png +0 -0
  389. psychopy/experiment/routines/audioValidator/dark/audio_validator.png +0 -0
  390. psychopy/experiment/routines/audioValidator/dark/audio_validator@2x.png +0 -0
  391. psychopy/experiment/routines/audioValidator/light/audio_validator.png +0 -0
  392. psychopy/experiment/routines/audioValidator/light/audio_validator@2x.png +0 -0
  393. psychopy/experiment/routines/eyetracker_calibrate/__init__.py +76 -17
  394. psychopy/experiment/routines/eyetracker_validate/__init__.py +1 -1
  395. psychopy/experiment/routines/unknown/__init__.py +2 -0
  396. psychopy/experiment/routines/{photodiodeValidator → visualValidator}/__init__.py +89 -120
  397. psychopy/experiment/routines/visualValidator/classic/visual_validator.png +0 -0
  398. psychopy/experiment/routines/visualValidator/classic/visual_validator@2x.png +0 -0
  399. psychopy/experiment/routines/visualValidator/dark/visual_validator.png +0 -0
  400. psychopy/experiment/routines/visualValidator/dark/visual_validator@2x.png +0 -0
  401. psychopy/experiment/routines/visualValidator/light/visual_validator.png +0 -0
  402. psychopy/experiment/routines/visualValidator/light/visual_validator@2x.png +0 -0
  403. psychopy/experiment/utils.py +1 -1
  404. psychopy/gui/__init__.py +1 -1
  405. psychopy/gui/qtgui.py +15 -6
  406. psychopy/gui/wxgui.py +1 -1
  407. psychopy/hardware/__init__.py +0 -1
  408. psychopy/hardware/base.py +147 -16
  409. psychopy/hardware/bbtk/__init__.py +10 -16
  410. psychopy/hardware/brainproducts.py +7 -13
  411. psychopy/hardware/button.py +21 -2
  412. psychopy/hardware/buttonbox/__init__.py +1 -1
  413. psychopy/hardware/camera/__init__.py +16 -3
  414. psychopy/hardware/cedrus.py +5 -16
  415. psychopy/hardware/crs/__init__.py +1 -1
  416. psychopy/hardware/crs/bits.py +36 -33
  417. psychopy/hardware/crs/colorcal.py +8 -11
  418. psychopy/hardware/crs/optical.py +7 -10
  419. psychopy/hardware/crs/shaders.py +18 -5
  420. psychopy/hardware/emotiv.py +1 -1
  421. psychopy/hardware/emulator.py +11 -5
  422. psychopy/hardware/exceptions.py +86 -0
  423. psychopy/hardware/forp.py +18 -23
  424. psychopy/hardware/gammasci.py +8 -3
  425. psychopy/hardware/iolab.py +8 -19
  426. psychopy/hardware/joystick/__init__.py +865 -266
  427. psychopy/hardware/joystick/_base.py +251 -0
  428. psychopy/hardware/joystick/backend_glfw.py +306 -0
  429. psychopy/hardware/joystick/backend_pyglet.py +309 -0
  430. psychopy/hardware/joystick/mappings.py +287 -0
  431. psychopy/hardware/keyboard.py +4 -2
  432. psychopy/hardware/labhackers.py +1 -1
  433. psychopy/hardware/labjacks.py +9 -13
  434. psychopy/hardware/{photodiode.py → lightsensor.py} +146 -203
  435. psychopy/hardware/listener.py +9 -8
  436. psychopy/hardware/manager.py +24 -35
  437. psychopy/hardware/microphone.py +534 -154
  438. psychopy/hardware/minolta.py +14 -4
  439. psychopy/hardware/mouse/__init__.py +1 -1
  440. psychopy/hardware/photometer/__init__.py +2 -2
  441. psychopy/hardware/pr.py +14 -4
  442. psychopy/hardware/qmix.py +18 -27
  443. psychopy/hardware/serialdevice.py +43 -12
  444. psychopy/hardware/soundsensor.py +473 -0
  445. psychopy/hardware/spatial/__init__.py +231 -0
  446. psychopy/hardware/speaker.py +298 -36
  447. psychopy/hardware/triggerbox/__init__.py +1 -1
  448. psychopy/hardware/triggerbox/base.py +1 -1
  449. psychopy/hardware/triggerbox/parallel.py +1 -1
  450. psychopy/info.py +1 -1
  451. psychopy/iohub/client/__init__.py +17 -0
  452. psychopy/iohub/client/keyboard.py +5 -0
  453. psychopy/iohub/devices/eyetracker/__init__.py +10 -18
  454. psychopy/iohub/devices/eyetracker/calibration/procedure.py +15 -33
  455. psychopy/iohub/devices/eyetracker/hw/pupil_labs/neon/__init__.py +1 -0
  456. psychopy/iohub/devices/mouse/linux2.py +6 -1
  457. psychopy/iohub/devices/mouse/win32.py +5 -0
  458. psychopy/layout.py +1 -1
  459. psychopy/liaison.py +91 -39
  460. psychopy/locale_setup.py +11 -1
  461. psychopy/localization/__init__.py +1 -1
  462. psychopy/localization/_localization.py +1 -1
  463. psychopy/localization/messages.pot +2 -2
  464. psychopy/logging.py +14 -12
  465. psychopy/microphone.py +4 -3
  466. psychopy/misc.py +1 -1
  467. psychopy/monitors/MonitorCenter.py +3 -3
  468. psychopy/monitors/__init__.py +1 -1
  469. psychopy/monitors/calibData.py +1 -1
  470. psychopy/monitors/calibTools.py +3 -2
  471. psychopy/platform_specific/__init__.py +1 -1
  472. psychopy/platform_specific/darwin.py +1 -1
  473. psychopy/platform_specific/linux.py +1 -1
  474. psychopy/platform_specific/win32.py +1 -1
  475. psychopy/plugins/__init__.py +26 -17
  476. psychopy/plugins/util.py +65 -0
  477. psychopy/preferences/Darwin.spec +11 -3
  478. psychopy/preferences/FreeBSD.spec +11 -3
  479. psychopy/preferences/Linux.spec +11 -3
  480. psychopy/preferences/Windows.spec +11 -3
  481. psychopy/preferences/__init__.py +1 -1
  482. psychopy/preferences/baseNoArch.spec +11 -3
  483. psychopy/preferences/hints.py +78 -61
  484. psychopy/preferences/preferences.py +82 -13
  485. psychopy/projects/__init__.py +1 -1
  486. psychopy/projects/pavlovia.py +29 -13
  487. psychopy/scripts/psyexpCompile.py +1 -1
  488. psychopy/session.py +81 -8
  489. psychopy/sound/__init__.py +25 -10
  490. psychopy/sound/_base.py +134 -34
  491. psychopy/sound/audioclip.py +38 -15
  492. psychopy/sound/audiodevice.py +1 -1
  493. psychopy/sound/backend_ptb.py +53 -321
  494. psychopy/sound/backend_pygame.py +7 -3
  495. psychopy/sound/backend_pyo.py +53 -22
  496. psychopy/sound/backend_pysound.py +10 -27
  497. psychopy/sound/backend_sounddevice.py +33 -21
  498. psychopy/sound/exceptions.py +1 -1
  499. psychopy/sound/microphone.py +83 -5
  500. psychopy/sound/transcribe.py +3 -3
  501. psychopy/tests/data/test_basic_run.py +1 -0
  502. psychopy/tests/data/test_loaded_namespace/test_counterbalance.psyexp +142 -0
  503. psychopy/tests/data/test_loaded_namespace/test_custom_missing.psyexp +129 -0
  504. psychopy/tests/data/test_loaded_namespace/test_missing_counterbalance.psyexp +116 -0
  505. psychopy/tests/data/test_loaded_namespace/test_mix_exp.psyexp +181 -0
  506. psychopy/tests/data/test_loaded_namespace/test_mix_missing.psyexp +140 -0
  507. psychopy/tests/data/test_loaded_namespace/test_mix_name_calibration.psyexp +164 -0
  508. psychopy/tests/data/test_sounds/default_16000.wav +0 -0
  509. psychopy/tests/data/test_sounds/default_192000.wav +0 -0
  510. psychopy/tests/data/test_sounds/default_22050.wav +0 -0
  511. psychopy/tests/data/test_sounds/default_32000.wav +0 -0
  512. psychopy/tests/data/test_sounds/default_44100.wav +0 -0
  513. psychopy/tests/data/test_sounds/default_48000.wav +0 -0
  514. psychopy/tests/data/test_sounds/default_8000.wav +0 -0
  515. psychopy/tests/data/test_sounds/default_96000.wav +0 -0
  516. psychopy/tests/test_alerts/test_alerttools.py +2 -1
  517. psychopy/tests/test_app/test_command_line.py +65 -0
  518. psychopy/tests/test_data/test_TrialHandler2.py +18 -7
  519. psychopy/tests/test_demos/test_builder_demos.py +1 -1
  520. psychopy/tests/test_experiment/needs_wx/componsTemplate.txt +5238 -4188
  521. psychopy/tests/test_experiment/needs_wx/test_components.py +1 -1
  522. psychopy/tests/test_experiment/test_components/test_RoutineSettingsComponent.py +16 -0
  523. psychopy/tests/test_experiment/test_components/test_all_components.py +1 -1
  524. psychopy/tests/test_experiment/test_components/test_base_components.py +26 -17
  525. psychopy/tests/test_experiment/test_experiment.py +96 -0
  526. psychopy/tests/test_experiment/test_loops.py +12 -4
  527. psychopy/tests/test_experiment/test_params.py +17 -4
  528. psychopy/tests/test_experiment/test_routines/test_PhotodiodeValidationRoutine.py +2 -2
  529. psychopy/tests/test_hardware/test_photodiode.py +66 -0
  530. psychopy/tests/test_liaison/test_Liaison.py +4 -4
  531. psychopy/tests/test_misc/test_clock.py +2 -0
  532. psychopy/tests/test_misc/test_color.py +2 -0
  533. psychopy/tests/test_misc/test_event.py +1 -0
  534. psychopy/tests/test_plugins/test_plugin_stubs.py +125 -0
  535. psychopy/tests/test_sound/test_sound.py +111 -40
  536. psychopy/tests/test_tools/test_colorspacetools.py +24 -23
  537. psychopy/tests/test_tools/test_mathtools.py +9 -9
  538. psychopy/tests/test_tools/test_viewtools.py +101 -0
  539. psychopy/tests/test_validators/__init__.py +0 -0
  540. psychopy/tests/test_validators/test_voicekeyValidator.py +95 -0
  541. psychopy/tests/test_visual/test_all_stimuli.py +2 -2
  542. psychopy/tests/test_visual/test_basevisual.py +37 -7
  543. psychopy/tests/test_visual/test_button.py +2 -2
  544. psychopy/tests/test_visual/test_circle.py +10 -2
  545. psychopy/tests/test_visual/test_dots.py +1 -1
  546. psychopy/tests/test_visual/test_form.py +13 -13
  547. psychopy/tests/test_visual/test_gamma.py +3 -3
  548. psychopy/tests/test_visual/test_image.py +2 -2
  549. psychopy/tests/test_visual/test_progress.py +2 -2
  550. psychopy/tests/test_visual/test_roi.py +8 -2
  551. psychopy/tests/test_visual/test_shape.py +2 -2
  552. psychopy/tests/test_visual/test_slider.py +2 -2
  553. psychopy/tests/test_visual/test_target.py +2 -2
  554. psychopy/tests/test_visual/test_textbox.py +6 -8
  555. psychopy/tests/test_visual/test_winScalePos.py +6 -5
  556. psychopy/tests/test_visual/test_window.py +17 -0
  557. psychopy/tests/utils.py +51 -1
  558. psychopy/tools/__init__.py +1 -1
  559. psychopy/tools/arraytools.py +2 -2
  560. psychopy/tools/attributetools.py +52 -1
  561. psychopy/tools/audiotools.py +4 -1
  562. psychopy/tools/colorspacetools.py +6 -4
  563. psychopy/tools/coordinatetools.py +1 -1
  564. psychopy/tools/fileerrortools.py +21 -9
  565. psychopy/tools/filetools.py +2 -2
  566. psychopy/tools/fontmanager.py +47 -28
  567. psychopy/tools/gltools.py +2964 -558
  568. psychopy/tools/imagetools.py +1 -1
  569. psychopy/tools/mathtools.py +997 -127
  570. psychopy/tools/monitorunittools.py +7 -1
  571. psychopy/tools/movietools.py +1 -2
  572. psychopy/tools/pkgtools.py +157 -127
  573. psychopy/tools/plottools.py +1 -1
  574. psychopy/tools/rifttools.py +1 -1
  575. psychopy/tools/stereotools.py +1 -1
  576. psychopy/tools/stimulustools.py +172 -2
  577. psychopy/tools/stringtools.py +22 -2
  578. psychopy/tools/systemtools.py +1 -1
  579. psychopy/tools/typetools.py +1 -1
  580. psychopy/tools/unittools.py +1 -1
  581. psychopy/tools/versionchooser.py +3 -1
  582. psychopy/tools/viewtools.py +54 -70
  583. psychopy/tools/wizard.py +2 -2
  584. psychopy/validation/__init__.py +6 -0
  585. psychopy/validation/audio.py +74 -0
  586. psychopy/validation/visual.py +115 -0
  587. psychopy/visual/__init__.py +1 -4
  588. psychopy/visual/aperture.py +9 -6
  589. psychopy/visual/backends/__init__.py +1 -1
  590. psychopy/visual/backends/_base.py +1 -1
  591. psychopy/visual/backends/gamma.py +1 -1
  592. psychopy/visual/backends/glfwbackend.py +8 -12
  593. psychopy/visual/backends/pygamebackend.py +1 -1
  594. psychopy/visual/backends/pygletbackend.py +32 -11
  595. psychopy/visual/basevisual.py +93 -13
  596. psychopy/visual/brush.py +1 -1
  597. psychopy/visual/bufferimage.py +90 -10
  598. psychopy/visual/button.py +1 -1
  599. psychopy/visual/circle.py +12 -20
  600. psychopy/visual/custommouse.py +1 -1
  601. psychopy/visual/dot.py +80 -14
  602. psychopy/visual/elementarray.py +84 -10
  603. psychopy/visual/filters.py +1 -1
  604. psychopy/visual/form.py +43 -28
  605. psychopy/visual/grating.py +105 -25
  606. psychopy/visual/helpers.py +1 -1
  607. psychopy/visual/image.py +98 -20
  608. psychopy/visual/line.py +15 -25
  609. psychopy/visual/movie.py +1 -1
  610. psychopy/visual/movie2.py +4 -3
  611. psychopy/visual/movie3.py +4 -3
  612. psychopy/visual/movies/__init__.py +1 -1
  613. psychopy/visual/movies/frame.py +1 -1
  614. psychopy/visual/movies/metadata.py +1 -1
  615. psychopy/visual/movies/players/__init__.py +1 -1
  616. psychopy/visual/movies/players/_base.py +1 -1
  617. psychopy/visual/movies/players/ffpyplayer_player.py +2 -3
  618. psychopy/visual/nnlvs.py +9 -6
  619. psychopy/visual/noise.py +4 -16
  620. psychopy/visual/patch.py +4 -3
  621. psychopy/visual/pie.py +3 -14
  622. psychopy/visual/polygon.py +21 -28
  623. psychopy/visual/radial.py +4 -18
  624. psychopy/visual/ratingscale.py +4 -3
  625. psychopy/visual/rect.py +16 -25
  626. psychopy/visual/rift.py +8 -2
  627. psychopy/visual/secondorder.py +4 -16
  628. psychopy/visual/shaders.py +620 -286
  629. psychopy/visual/shape.py +281 -90
  630. psychopy/visual/simpleimage.py +1 -1
  631. psychopy/visual/slider.py +78 -25
  632. psychopy/visual/stim3d.py +5 -608
  633. psychopy/visual/text.py +13 -3
  634. psychopy/visual/textbox2/textbox2.py +188 -56
  635. psychopy/visual/vlcmoviestim.py +1 -1
  636. psychopy/visual/window.py +373 -200
  637. psychopy/web.py +1 -1
  638. {psychopy-2024.2.4.dist-info → psychopy-2025.1.0.dist-info}/METADATA +9 -9
  639. {psychopy-2024.2.4.dist-info → psychopy-2025.1.0.dist-info}/RECORD +653 -660
  640. psychopy/.DS_Store +0 -0
  641. psychopy/__init__.py.orig +0 -65
  642. psychopy/app/.DS_Store +0 -0
  643. psychopy/app/Resources/.DS_Store +0 -0
  644. psychopy/app/Resources/classic/filecsv16.png +0 -0
  645. psychopy/app/Resources/classic/fileimage16.png +0 -0
  646. psychopy/app/Resources/classic/fileunknown16.png +0 -0
  647. psychopy/app/Resources/dark/filecsv16.png +0 -0
  648. psychopy/app/Resources/dark/filecsv16@2x.png +0 -0
  649. psychopy/app/Resources/dark/fileimage16.png +0 -0
  650. psychopy/app/Resources/dark/fileimage16@2x.png +0 -0
  651. psychopy/app/Resources/dark/fileunknown16.png +0 -0
  652. psychopy/app/Resources/dark/fileunknown16@2x.png +0 -0
  653. psychopy/app/Resources/fonts/OpenSans-Bold.ttf +0 -0
  654. psychopy/app/Resources/fonts/OpenSans-BoldItalic.ttf +0 -0
  655. psychopy/app/Resources/fonts/OpenSans-ExtraBold.ttf +0 -0
  656. psychopy/app/Resources/fonts/OpenSans-ExtraBoldItalic.ttf +0 -0
  657. psychopy/app/Resources/fonts/OpenSans-Italic.ttf +0 -0
  658. psychopy/app/Resources/fonts/OpenSans-Light.ttf +0 -0
  659. psychopy/app/Resources/fonts/OpenSans-LightItalic.ttf +0 -0
  660. psychopy/app/Resources/fonts/OpenSans-Regular.ttf +0 -0
  661. psychopy/app/Resources/fonts/OpenSans-SemiBold.ttf +0 -0
  662. psychopy/app/Resources/fonts/OpenSans-SemiBoldItalic.ttf +0 -0
  663. psychopy/app/Resources/light/filecsv16.png +0 -0
  664. psychopy/app/Resources/light/filecsv16@2x.png +0 -0
  665. psychopy/app/Resources/light/fileimage16.png +0 -0
  666. psychopy/app/Resources/light/fileimage16@2x.png +0 -0
  667. psychopy/app/Resources/light/fileunknown16.png +0 -0
  668. psychopy/app/Resources/light/fileunknown16@2x.png +0 -0
  669. psychopy/app/Resources/psychopySplash.png +0 -0
  670. psychopy/app/Resources/psychopySplash@2x.png +0 -0
  671. psychopy/app/builder/builder.py.orig +0 -3932
  672. psychopy/app/builder/dialogs/__init__.py.orig +0 -1679
  673. psychopy/app/builder/dialogs/paramCtrls.py.orig +0 -713
  674. psychopy/app/colorpicker/__init__.py.orig +0 -411
  675. psychopy/app/locale/zh_CN/LC_MESSAGE/zh_CN.mo +0 -0
  676. psychopy/app/locale/zh_CN/LC_MESSAGE/zh_CN.po +0 -6127
  677. psychopy/app/locale/zh_CN/LC_MESSAGE/zh_CN_allFlagged.mo +0 -0
  678. psychopy/app/locale/zh_CN/LC_MESSAGE/zh_CN_allFlagged.po +0 -7366
  679. psychopy/core.py.orig +0 -169
  680. psychopy/demos/builder/.DS_Store +0 -0
  681. psychopy/demos/builder/Design Templates/randomisedBlocks/html/index.html +0 -23
  682. psychopy/demos/builder/Design Templates/randomisedBlocks/html/randomisedBlocks-legacy-browsers.js +0 -423
  683. psychopy/demos/builder/Design Templates/randomisedBlocks/html/randomisedBlocks.js +0 -427
  684. psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/chooseBlock.xlsx +0 -0
  685. psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/facesBlock.xlsx +0 -0
  686. psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/housesBlock.xlsx +0 -0
  687. psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/stims/face01.jpg +0 -0
  688. psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/stims/face02.jpg +0 -0
  689. psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/stims/face03.jpg +0 -0
  690. psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/stims/house01.jpg +0 -0
  691. psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/stims/house02.jpg +0 -0
  692. psychopy/demos/builder/Design Templates/randomisedBlocks/html/resources/stims/house03.jpg +0 -0
  693. psychopy/demos/builder/Design Templates/randomisedBlocks/randomisedBlocks.py +0 -330
  694. psychopy/demos/builder/Design Templates/randomisedBlocks/randomisedBlocks_lastrun.py +0 -330
  695. psychopy/demos/builder/Experiments/.DS_Store +0 -0
  696. psychopy/demos/builder/Experiments/dragAndDrop/archived_conditions.xlsx +0 -0
  697. psychopy/demos/builder/Experiments/dragAndDrop/draw grid stim.py +0 -61
  698. psychopy/demos/builder/Experiments/dragAndDrop/shapeMaker.psyexp +0 -91
  699. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_1.png +0 -0
  700. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_10.png +0 -0
  701. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_2.png +0 -0
  702. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_3.png +0 -0
  703. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_4.png +0 -0
  704. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_5.png +0 -0
  705. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_6.png +0 -0
  706. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_7.png +0 -0
  707. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_8.png +0 -0
  708. psychopy/demos/builder/Experiments/dragAndDrop/stimuli/grid_image_9.png +0 -0
  709. psychopy/demos/builder/Experiments/dragAndDrop/updated_conditions.xlsx +0 -0
  710. psychopy/demos/builder/Feature Demos/eyetracking/eyetracking.xsd +0 -120
  711. psychopy/demos/builder/Tools/.DS_Store +0 -0
  712. psychopy/demos/builder/Tools/gammaCalibration/.DS_Store +0 -0
  713. psychopy/demos/builder/Tools/gammaCalibration/data/.DS_Store +0 -0
  714. psychopy/demos/builder/Tools/gammaCalibration/data/_gamma_correction_visual_2022-05-18_14h18.29.439.csv +0 -38
  715. psychopy/demos/builder/Tools/gammaCalibration/data/_gamma_correction_visual_2022-05-18_14h18.29.439.log +0 -3418
  716. psychopy/demos/builder/Tools/gammaCalibration/data/_gamma_correction_visual_2022-05-18_14h18.29.439.psydat +0 -0
  717. psychopy/demos/builder/Tools/gammaCalibration/data/x1_gamma_correction_visual_2022-05-17_13h59.42.928.csv +0 -2
  718. psychopy/demos/builder/Tools/gammaCalibration/data/x1_gamma_correction_visual_2022-05-17_13h59.42.928.log +0 -15
  719. psychopy/demos/builder/Tools/gammaCalibration/data/x1_gamma_correction_visual_2022-05-17_13h59.42.928.psydat +0 -0
  720. psychopy/demos/builder/Tools/gammaCalibration/gamma_correction_visual.psyexp +0 -323
  721. psychopy/demos/builder/Tools/gammaCalibration/gamma_correction_visual.py +0 -562
  722. psychopy/demos/builder/Tools/gammaCalibration/gamma_correction_visual_lastrun.py +0 -562
  723. psychopy/demos/builder/Tools/gammaCalibration/questStairs.xlsx +0 -0
  724. psychopy/demos/builder/Tools/gammaCalibration/resources/low_contrast.png +0 -0
  725. psychopy/demos/builder/Tools/gammaCalibration/resources/make_2nd_order_tex.py +0 -59
  726. psychopy/demos/builder/Tools/gammaCalibration/resources/second_order_tex.png +0 -0
  727. psychopy/demos/coder/.DS_Store +0 -0
  728. psychopy/demos/coder/experiment control/info_gamma.pickle +0 -0
  729. psychopy/demos/coder/iohub/.iohpid +0 -1
  730. psychopy/demos/coder/iohub/eyetracking/.iohpid +0 -1
  731. psychopy/demos/coder/iohub/wintab/.DS_Store +0 -0
  732. psychopy/demos/coder/stimuli/.DS_Store +0 -0
  733. psychopy/demos/coder/stimuli/radialGratingContracting.py +0 -29
  734. psychopy/experiment/_experiment.py.orig +0 -1032
  735. psychopy/experiment/components/.DS_Store +0 -0
  736. psychopy/experiment/components/_base.py.orig +0 -823
  737. psychopy/experiment/components/form/.DS_Store +0 -0
  738. psychopy/experiment/components/microphone/__init__.py.orig +0 -490
  739. psychopy/experiment/components/settings/__init__.py.orig +0 -1337
  740. psychopy/experiment/components/textbox/__init__.py.orig +0 -310
  741. psychopy/experiment/components/webcam/.DS_Store +0 -0
  742. psychopy/experiment/components/webcam/light/.DS_Store +0 -0
  743. psychopy/experiment/loops.py.orig +0 -829
  744. psychopy/experiment/params.py.orig +0 -408
  745. psychopy/experiment/routine.py.orig +0 -503
  746. psychopy/experiment/routines/photodiodeValidator/classic/photodiode_validator.png +0 -0
  747. psychopy/experiment/routines/photodiodeValidator/classic/photodiode_validator@2x.png +0 -0
  748. psychopy/experiment/routines/photodiodeValidator/dark/photodiode_validator.png +0 -0
  749. psychopy/experiment/routines/photodiodeValidator/dark/photodiode_validator@2x.png +0 -0
  750. psychopy/experiment/routines/photodiodeValidator/light/photodiode_validator.png +0 -0
  751. psychopy/experiment/routines/photodiodeValidator/light/photodiode_validator@2x.png +0 -0
  752. psychopy/hardware/.DS_Store +0 -0
  753. psychopy/hardware/brainproducts.py.orig +0 -680
  754. psychopy/hardware/iolab.py.orig +0 -238
  755. psychopy/hardware/serialport.py +0 -51
  756. psychopy/iohub/datastore/__init__.py.orig +0 -443
  757. psychopy/iohub/datastore/util.py.orig +0 -692
  758. psychopy/iohub/devices/mouse/darwin.py.orig +0 -427
  759. psychopy/iohub/devices/mouse/linux2.py.orig +0 -198
  760. psychopy/preferences/.DS_Store +0 -0
  761. psychopy/projects/pavlovia.py.orig +0 -1295
  762. psychopy/tests/.DS_Store +0 -0
  763. psychopy/tests/data/.DS_Store +0 -0
  764. psychopy/tests/data/TestCircle_fill_local.png +0 -0
  765. psychopy/tests/data/__test.png +0 -0
  766. psychopy/tests/data/aperture1_normHexbackground_local.png +0 -0
  767. psychopy/tests/data/aperture1_norm_local.png +0 -0
  768. psychopy/tests/data/aperture2_normHexbackground_local.png +0 -0
  769. psychopy/tests/data/beatandrcos_height_local.png +0 -0
  770. psychopy/tests/data/beatandrcos_normAddBlend_local.png +0 -0
  771. psychopy/tests/data/beatandrcos_normHexbackground_local.png +0 -0
  772. psychopy/tests/data/beatandrcos_norm_local.png +0 -0
  773. psychopy/tests/data/beatandrcos_stencil_local.png +0 -0
  774. psychopy/tests/data/blend_add_height_local.png +0 -0
  775. psychopy/tests/data/blend_add_normAddBlend_local.png +0 -0
  776. psychopy/tests/data/blend_add_normHexbackground_local.png +0 -0
  777. psychopy/tests/data/blend_add_normNoShade_local.png +0 -0
  778. psychopy/tests/data/blend_add_norm_local.png +0 -0
  779. psychopy/tests/data/blend_add_stencil_local.png +0 -0
  780. psychopy/tests/data/bufferimg_gabor_height_local.png +0 -0
  781. psychopy/tests/data/bufferimg_gabor_normAddBlend_local.png +0 -0
  782. psychopy/tests/data/bufferimg_gabor_normHexbackground_local.png +0 -0
  783. psychopy/tests/data/bufferimg_gabor_normNoShade_local.png +0 -0
  784. psychopy/tests/data/bufferimg_gabor_norm_local.png +0 -0
  785. psychopy/tests/data/bufferimg_gabor_stencil_local.png +0 -0
  786. psychopy/tests/data/circleHex_height_local.png +0 -0
  787. psychopy/tests/data/circleHex_normAddBlend_local.png +0 -0
  788. psychopy/tests/data/circleHex_normHexbackground_local.png +0 -0
  789. psychopy/tests/data/circleHex_normNoShade_local.png +0 -0
  790. psychopy/tests/data/circleHex_norm_local.png +0 -0
  791. psychopy/tests/data/circleHex_stencil_local.png +0 -0
  792. psychopy/tests/data/color_comparison_local.png +0 -0
  793. psychopy/tests/data/corrFullRandom_local.csv +0 -16
  794. psychopy/tests/data/corrFullRandom_local.tsv +0 -6
  795. psychopy/tests/data/correctScript/.DS_Store +0 -0
  796. psychopy/tests/data/dots_height_local.png +0 -0
  797. psychopy/tests/data/dots_normAddBlend_local.png +0 -0
  798. psychopy/tests/data/dots_normHexbackground_local.png +0 -0
  799. psychopy/tests/data/dots_normNoShade_local.png +0 -0
  800. psychopy/tests/data/dots_norm_local.png +0 -0
  801. psychopy/tests/data/dots_stencil_local.png +0 -0
  802. psychopy/tests/data/elarray1_height_local.png +0 -0
  803. psychopy/tests/data/elarray1_normAddBlend_local.png +0 -0
  804. psychopy/tests/data/elarray1_normHexbackground_local.png +0 -0
  805. psychopy/tests/data/elarray1_norm_local.png +0 -0
  806. psychopy/tests/data/elarray1_stencil_local.png +0 -0
  807. psychopy/tests/data/envelopeandrcos_height_local.png +0 -0
  808. psychopy/tests/data/envelopeandrcos_normAddBlend_local.png +0 -0
  809. psychopy/tests/data/envelopeandrcos_normHexbackground_local.png +0 -0
  810. psychopy/tests/data/envelopeandrcos_norm_local.png +0 -0
  811. psychopy/tests/data/envelopeandrcos_stencil_local.png +0 -0
  812. psychopy/tests/data/envelopepowerandrcos_height_local.png +0 -0
  813. psychopy/tests/data/envelopepowerandrcos_normAddBlend_local.png +0 -0
  814. psychopy/tests/data/envelopepowerandrcos_normHexbackground_local.png +0 -0
  815. psychopy/tests/data/envelopepowerandrcos_norm_local.png +0 -0
  816. psychopy/tests/data/envelopepowerandrcos_stencil_local.png +0 -0
  817. psychopy/tests/data/gabor1_height_local.png +0 -0
  818. psychopy/tests/data/gabor1_normAddBlend_local.png +0 -0
  819. psychopy/tests/data/gabor1_normHexbackground_local.png +0 -0
  820. psychopy/tests/data/gabor1_normNoShade_local.png +0 -0
  821. psychopy/tests/data/gabor1_norm_local.png +0 -0
  822. psychopy/tests/data/gabor1_stencil_local.png +0 -0
  823. psychopy/tests/data/greyscale_normHexbackground_local.png +0 -0
  824. psychopy/tests/data/imageAndGauss_height_local.png +0 -0
  825. psychopy/tests/data/imageAndGauss_normAddBlend_local.png +0 -0
  826. psychopy/tests/data/imageAndGauss_normHexbackground_local.png +0 -0
  827. psychopy/tests/data/imageAndGauss_normNoShade_local.png +0 -0
  828. psychopy/tests/data/imageAndGauss_norm_local.png +0 -0
  829. psychopy/tests/data/imageAndGauss_stencil_local.png +0 -0
  830. psychopy/tests/data/movFrame1_stencil_local.png +0 -0
  831. psychopy/tests/data/noiseAndRcos_height_local.png +0 -0
  832. psychopy/tests/data/noiseAndRcos_normAddBlend_local.png +0 -0
  833. psychopy/tests/data/noiseAndRcos_normHexbackground_local.png +0 -0
  834. psychopy/tests/data/noiseAndRcos_normNoShade_local.png +0 -0
  835. psychopy/tests/data/noiseAndRcos_norm_local.png +0 -0
  836. psychopy/tests/data/noiseAndRcos_stencil_local.png +0 -0
  837. psychopy/tests/data/noiseFiltersAndRcos_height_local.png +0 -0
  838. psychopy/tests/data/noiseFiltersAndRcos_normAddBlend_local.png +0 -0
  839. psychopy/tests/data/noiseFiltersAndRcos_normHexbackground_local.png +0 -0
  840. psychopy/tests/data/noiseFiltersAndRcos_normNoShade_local.png +0 -0
  841. psychopy/tests/data/noiseFiltersAndRcos_norm_local.png +0 -0
  842. psychopy/tests/data/noiseFiltersAndRcos_stencil_local.png +0 -0
  843. psychopy/tests/data/numpyImage_height_local.png +0 -0
  844. psychopy/tests/data/numpyImage_normAddBlend_local.png +0 -0
  845. psychopy/tests/data/numpyImage_normHexbackground_local.png +0 -0
  846. psychopy/tests/data/numpyImage_normNoShade_local.png +0 -0
  847. psychopy/tests/data/numpyImage_norm_local.png +0 -0
  848. psychopy/tests/data/numpyImage_stencil_local.png +0 -0
  849. psychopy/tests/data/shape2_1_normAddBlend_local.png +0 -0
  850. psychopy/tests/data/shape2_1_normHexbackground_local.png +0 -0
  851. psychopy/tests/data/shape2_1_normNoShade_local.png +0 -0
  852. psychopy/tests/data/shape2_1_norm_local.png +0 -0
  853. psychopy/tests/data/shape2_1_stencil_local.png +0 -0
  854. psychopy/tests/data/testLoopsBlocks.psyexp_local.py +0 -328
  855. psychopy/tests/data/text1_height_local.png +0 -0
  856. psychopy/tests/data/text1_normAddBlend_local.png +0 -0
  857. psychopy/tests/data/text1_normHexbackground_local.png +0 -0
  858. psychopy/tests/data/text1_norm_local.png +0 -0
  859. psychopy/tests/data/text1_stencil_local.png +0 -0
  860. psychopy/tests/data/text2_height.png +0 -0
  861. psychopy/tests/data/text2_normAddBlend.png +0 -0
  862. psychopy/tests/data/text2_normHexbackground.png +0 -0
  863. psychopy/tests/data/text2_stencil.png +0 -0
  864. psychopy/tests/data/wedge1_height_local.png +0 -0
  865. psychopy/tests/data/wedge1_normAddBlend_local.png +0 -0
  866. psychopy/tests/data/wedge1_normHexbackground_local.png +0 -0
  867. psychopy/tests/data/wedge1_normNoShade_local.png +0 -0
  868. psychopy/tests/data/wedge1_norm_local.png +0 -0
  869. psychopy/tests/data/wedge1_stencil_local.png +0 -0
  870. psychopy/tests/test_app/.DS_Store +0 -0
  871. psychopy/tests/test_app/test_builder/.DS_Store +0 -0
  872. psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1206.csv +0 -9
  873. psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1206.log +0 -177
  874. psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1206.psydat +0 -0
  875. psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1206.xlsx +0 -0
  876. psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1324.csv +0 -9
  877. psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1324.log +0 -168
  878. psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1324.psydat +0 -0
  879. psychopy/tests/test_app/test_builder/data/_2021_ 5_03_1324.xlsx +0 -0
  880. psychopy/tests/test_data/.DS_Store +0 -0
  881. psychopy/tests/test_hardware/test_CRS_BitsSharp.py +0 -67
  882. psychopy/tests/test_hardware/test_CRS_BitsSharp.py.orig +0 -68
  883. psychopy/tests/test_hardware/test_CRS_bitsShaders.py +0 -110
  884. psychopy/tests/test_visual/test_image.py.orig +0 -219
  885. psychopy/visual/basevisual.py.orig +0 -1723
  886. psychopy/visual/form.py.orig +0 -1181
  887. psychopy/visual/text.py.orig +0 -752
  888. psychopy/visual/textbox2/textbox2.py.orig +0 -1315
  889. psychopy/visual/windowwarp.py.orig +0 -463
  890. /psychopy/{app/cortex.log → alerts/alertsCatalogue/3600.yaml} +0 -0
  891. /psychopy/{app/Resources → assets}/fonts/Arvo-Bold.ttf +0 -0
  892. /psychopy/{app/Resources → assets}/fonts/Arvo-BoldItalic.ttf +0 -0
  893. /psychopy/{app/Resources → assets}/fonts/Arvo-Italic.ttf +0 -0
  894. /psychopy/{app/Resources → assets}/fonts/Arvo-Regular.ttf +0 -0
  895. /psychopy/{app/Resources → assets}/fonts/DejaVuSerif.ttf +0 -0
  896. /psychopy/{app/Resources → assets}/fonts/IndieFlower-Regular.ttf +0 -0
  897. /psychopy/{app/Resources → assets}/fonts/JetBrainsMono-Italic-VariableFont_wght.ttf +0 -0
  898. /psychopy/{app/Resources → assets}/fonts/JetBrainsMono-VariableFont_wght.ttf +0 -0
  899. /psychopy/demos/builder/Experiments/{GoNoGo → goNoGo}/readme.md +0 -0
  900. /psychopy/{demos/builder/Tools/gammaCalibration/readme.md → tests/test_plugins/__init__.py} +0 -0
  901. {psychopy-2024.2.4.dist-info → psychopy-2025.1.0.dist-info}/WHEEL +0 -0
  902. {psychopy-2024.2.4.dist-info → psychopy-2025.1.0.dist-info}/entry_points.txt +0 -0
  903. {psychopy-2024.2.4.dist-info → psychopy-2025.1.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,37 +1,284 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ """Classes and functions managing physical speaker devices for audio playback.
4
+ """
5
+
6
+ # Part of the PsychoPy library
7
+ # Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2025 Open Science Tools Ltd.
8
+ # Distributed under the terms of the GNU General Public License (GPL).
9
+
10
+ import io
11
+ import sys
12
+ import contextlib
13
+ from types import SimpleNamespace
14
+ import psychtoolbox.audio as ptb
15
+ from psychopy.hardware.exceptions import DeviceNotConnectedError
16
+ from psychopy.localization import _translate
17
+ from psychopy.preferences import prefs
1
18
  from psychopy.hardware import BaseDevice
2
- from psychopy.sound import setDevice, getDevices, backend
3
19
  from psychopy import logging
20
+ from psychopy.tools import systemtools
21
+
22
+ __all__ = [
23
+ "SpeakerDevice",
24
+ ]
4
25
 
5
26
 
6
27
  class SpeakerDevice(BaseDevice):
7
- def __init__(self, index):
8
- profiles = self.getAvailableDevices()
9
-
10
- # if index is default (-1), setup a default device index
11
- if not isinstance(index, (int, float)):
12
- index = profiles[0]['index'] # initialize as the first device
13
-
14
- # check if a default device is already set and update index
15
- if hasattr(backend, 'defaultOutput'):
16
- defaultDevice = backend.defaultOutput
17
- if isinstance(defaultDevice, (int, float)):
18
- # if a default device index is set, use it
19
- index = defaultDevice
20
- elif isinstance(defaultDevice, str):
21
- # if a default device is set by name, find it
22
- for profile in profiles:
23
- if profile['deviceName'] == defaultDevice:
24
- index = profile['index']
25
-
26
- available_index = [profile['index'] for profile in profiles] + [-1]
27
- if index not in available_index:
28
- logging.error("No speaker device found with index %d" % index)
29
-
30
- # store index
28
+ """Class for managing a physical speaker device for audio playback.
29
+
30
+ Parameters
31
+ ----------
32
+ index : int, optional
33
+ Numeric index for the physical speaker device, according to psychtoolbox. Leave as None to
34
+ find the speaker by name.
35
+ name : str, optional
36
+ String name for the physical speaker device, according to your operating system. Leave as
37
+ None to find the speaker by numeric index.
38
+ latencyClass : int
39
+ One of:
40
+
41
+ * 0: Don't take exclusive control over the speaker, so other apps can still use it. Send
42
+ sounds via the system mixer so that sample rates are all handled, even though this
43
+ introduces latency.
44
+
45
+ * 1: Don't take exclusive control over the speaker, so other apps can still use it. Send
46
+ sounds directly to reduce latency, so sounds will need to match the sample rate of the
47
+ speaker. **Recommended in most cases; if `resample` is True then sample rates are
48
+ already handled on load!**
49
+
50
+ * 2: Take exclusive control over the speaker, so other apps can't use it. Send sounds
51
+ directly to reduce latency, so sounds will need to be the same sample rate as one
52
+ another, but this can be any sample rate supported by the speaker.
53
+
54
+ * 3: Take exclusive control over the speaker, so other apps can't use it. Send sounds
55
+ directly to reduce latency, so sounds will need to be the same sample rate as one
56
+ another, but this can be any sample rate supported by the speaker. Force the system to
57
+ prioritise resources towards playing sounds on this speaker for absolute minimum
58
+ latency, but fallback to mode 2 if the system rejects this.
59
+
60
+ * 4: Take exclusive control over the speaker, so other apps can't use it. Send sounds
61
+ directly to reduce latency, so sounds will need to be the same sample rate as one
62
+ another, but this can be any sample rate supported by the speaker. Force the system to
63
+ prioritise resources towards playing sounds on this speaker for absolute minimum
64
+ latency, and raise an error if the system rejects this.
65
+ resample : bool, optional
66
+ If the sample rate of an audio clip doesn't match the sample rate of the speaker, should
67
+ PsychoPy resample the sound on load?
68
+ """
69
+ # dict of extant streams, by numeric index
70
+ streams = {}
71
+
72
+ def __init__(self, index=None, name=None, latencyClass=1, resample=True):
73
+ if index is not None and name is not None:
74
+ logging.warn(
75
+ "Both 'index' and 'name' were provided to SpeakerDevice; ignoring 'index'"
76
+ )
77
+ index = None
78
+ # try simple integerisation of index
79
+ if isinstance(index, str):
80
+ try:
81
+ index = float(index)
82
+ except ValueError:
83
+ pass
84
+
85
+ # if index is default, get default speaker device
86
+ if index in (-1, None) and name is None:
87
+ index = None # set to none so we can find by name later
88
+ pref = prefs.hardware['audioDevice']
89
+ pref = pref[0] if isinstance(pref, (list, tuple)) else pref
90
+
91
+ if pref in ("default", "None"):
92
+ # if no pref, use first device
93
+ name = self.getAvailableDevices()[0]['deviceName']
94
+ # warn the user, this speaker might be a virtual device with no audio or something
95
+ logging.warn(
96
+ _translate(
97
+ "No default speaker specified in Preferences / Hardware, using first speaker found: {}"
98
+ ).format(name)
99
+ )
100
+ else:
101
+ # if pref is a name, use that
102
+ name = pref
103
+
104
+ # store name and index
105
+ self.name = name
31
106
  self.index = index
32
- # set global device (best we can do for now)
33
- setDevice(index)
34
107
 
108
+ # store playback prefs
109
+ self.resample = resample
110
+ self.latencyClass = latencyClass
111
+ # create stream
112
+ self.createStream()
113
+ # start off open
114
+ self.open()
115
+
116
+ @property
117
+ def exclusive(self):
118
+ """
119
+ Returns
120
+ -------
121
+ bool
122
+ Does PsychoPy have exclusive control of this speaker? If True then other apps will not be
123
+ able to play sounds on the same speaker.
124
+ """
125
+ return self.latencyClass >= 2
126
+
127
+ def createStream(self):
128
+ """
129
+ Create the psychtoolbox audio stream
130
+
131
+ Attributes
132
+ ----------
133
+ Calling this method will set the following attributes:
134
+
135
+ profile : dict
136
+ The profile from psychtoolbox, a dict with the following keys: Active, State,
137
+ RequestedStartTime, StartTime, CaptureStartTime, RequestedStopTime, EstimatedStopTime,
138
+ CurrentStreamTime, ElapsedOutSamples, PositionSecs, RecordedSecs, ReadSecs,
139
+ SchedulePosition, XRuns, TotalCalls, TimeFailed, BufferSize, CPULoad, PredictedLatency,
140
+ LatencyBias, SampleRate, OutDeviceIndex, InDeviceIndex
141
+ index : int
142
+ A numeric index referring to the device. This may differ from the value of `index` this
143
+ object was initialised with, as this will be the numeric index of the actual physical
144
+ speaker best matching what was requested.
145
+ name : str
146
+ A string name referring to the device. This may differ from the value of `name` this
147
+ object was initialised with, as this will be the system-reported name of the actual
148
+ physical speaker best matching what was requested.
149
+ """
150
+
151
+ # get the devices from psychtoolbox
152
+ try:
153
+ wasapiPref = prefs.hardware['audioWASAPIOnly']
154
+ except KeyError:
155
+ wasapiPref = False
156
+
157
+ if sys.platform == 'win32' and wasapiPref:
158
+ allFoundDevices = ptb.get_devices(device_type=13)
159
+ else:
160
+ allFoundDevices = ptb.get_devices()
161
+
162
+ if not allFoundDevices:
163
+ raise DeviceNotConnectedError(
164
+ _translate("No audio devices found!"),
165
+ deviceClass=SpeakerDevice
166
+ )
167
+
168
+ # find ptb profile for this device
169
+ findByName = self.index is None and self.name is not None
170
+ self.profile = None
171
+ for thisProfile in allFoundDevices:
172
+ # skip input-only devices (microphones)
173
+ if thisProfile['NrOutputChannels'] == 0:
174
+ continue
175
+
176
+ if findByName and self.name == thisProfile['DeviceName']:
177
+ self.profile = thisProfile
178
+ break
179
+ else: # use index instead
180
+ if self.index == thisProfile['DeviceIndex']:
181
+ self.profile = thisProfile
182
+ break
183
+
184
+ # raise error if device not found
185
+ if self.profile is None:
186
+ raise DeviceNotConnectedError(
187
+ _translate(
188
+ "No speaker device found with {key} '{name}'"
189
+ ).format(name=self.name, key="name" if findByName else "index"),
190
+ deviceClass=SpeakerDevice
191
+ )
192
+
193
+ logging.debug(
194
+ f"Found speaker device: {self.profile['DeviceName']} ({self.profile['DeviceIndex']})"
195
+ )
196
+
197
+ # if physical device already has a stream, use it rather than making a new one
198
+ if self.profile['DeviceIndex'] in SpeakerDevice.streams:
199
+ self.stream = SpeakerDevice.streams['DeviceIndex']
200
+ else:
201
+ self.stream = None
202
+ # try to connect using profile at various sample rates
203
+ for sampleRateHz in (
204
+ # start with the rate from profile (this will usually work)
205
+ int(self.profile['DefaultSampleRate']),
206
+ # if that fails, try some common sample rates
207
+ 48000,
208
+ 44100,
209
+ 22050,
210
+ 16000
211
+ ):
212
+ # stop trying new options once we have a stream
213
+ if self.stream is not None:
214
+ continue
215
+ # try this sample rate
216
+ try:
217
+ # redirect stderr to a buffer to avoid ptb error spam
218
+ outBuff = io.StringIO()
219
+ errBuff = io.StringIO()
220
+ with contextlib.redirect_stdout(outBuff):
221
+ with contextlib.redirect_stderr(errBuff):
222
+ self.stream = ptb.Stream(
223
+ mode=1+8,
224
+ device_id=self.profile['DeviceIndex'],
225
+ freq=sampleRateHz,
226
+ channels=self.profile['NrOutputChannels'],
227
+ latency_class=[self.latencyClass],
228
+ )
229
+ # if it worked, set own parameters
230
+ self.index = self.profile['DeviceIndex']
231
+ self.name = self.profile['DeviceName']
232
+ self.sampleRateHz = sampleRateHz
233
+ self.channels = self.profile['NrOutputChannels']
234
+ # ...and log/print the stderr from psychtoolbox (only if successful!)
235
+ logs = errBuff.getvalue() + outBuff.getvalue()
236
+ for line in logs.split("\n"):
237
+ if line.startswith("PTB-INFO: "):
238
+ logging.info(line[10:])
239
+ elif line.startswith("PTB-ERROR: "):
240
+ logging.error(line[11:])
241
+ elif line.strip():
242
+ print(line)
243
+ except:
244
+ pass
245
+ # if everything failed, raise an error
246
+ if self.stream is None:
247
+ raise ConnectionError(
248
+ "Failed to setup a PsychToolBox audio stream for device %(DeviceName)s "
249
+ "(%(DeviceIndex)s)." % self.profile
250
+ )
251
+
252
+ logging.info(
253
+ f"Created stream for speaker device: {self.profile['DeviceName']} "
254
+ f"({self.profile['DeviceIndex']})"
255
+ )
256
+
257
+ def open(self):
258
+ """
259
+ Open the audio stream for this speaker so that sound can be played to it.
260
+ """
261
+ if not self.isOpen:
262
+ self.stream.start(0, 0, 1)
263
+
264
+ def close(self):
265
+ """
266
+ Close the audio stream for this speaker.
267
+ """
268
+ if self.isOpen:
269
+ self.stream.close()
270
+
271
+ @property
272
+ def isOpen(self):
273
+ """
274
+ Is this speaker "open", i.e. is it active and ready for a Sound to play tracks on it
275
+ """
276
+ # sometimes a closed stream will have an integer for status
277
+ if not isinstance(self.stream.status, dict):
278
+ return False
279
+
280
+ return bool(self.stream.status['Active'])
281
+
35
282
  def isSameDevice(self, other):
36
283
  """
37
284
  Determine whether this object represents the same physical speaker as a given other object.
@@ -47,7 +294,7 @@ class SpeakerDevice(BaseDevice):
47
294
  bool
48
295
  True if the two objects represent the same physical device
49
296
  """
50
- if isinstance(other, SpeakerDevice):
297
+ if isinstance(other, type(self)):
51
298
  # if given another object, get index
52
299
  index = other.index
53
300
  elif isinstance(other, dict) and "index" in other:
@@ -57,8 +304,8 @@ class SpeakerDevice(BaseDevice):
57
304
  # if the other object is the wrong type or doesn't have an index, it's not this
58
305
  return False
59
306
 
60
- return self.index == index
61
-
307
+ return index in (self.index, self.name)
308
+
62
309
  def testDevice(self):
63
310
  """
64
311
  Play a simple sound to check whether this device is working.
@@ -67,22 +314,37 @@ class SpeakerDevice(BaseDevice):
67
314
  import time
68
315
  # create a basic sound
69
316
  snd = Sound(
70
- speaker=self.index,
71
- value="A"
317
+ speaker=self,
318
+ value="A",
319
+ stereo=self.channels > 1,
320
+ sampleRate=self.sampleRateHz
72
321
  )
73
322
  # play the sound for 1s
74
323
  snd.play()
75
324
  time.sleep(1)
76
325
  snd.stop()
77
-
326
+
78
327
  @staticmethod
79
328
  def getAvailableDevices():
329
+ # skip in vm
330
+ if systemtools.isVM_CI(): # GitHub actions VM does not have a sound device
331
+ return []
332
+ # only show WASAPI drivers for Windows
333
+ if sys.platform == 'win32':
334
+ deviceType = 13
335
+ else:
336
+ deviceType = None
337
+
80
338
  devices = []
81
-
82
- for profile in getDevices(kind="output").values():
339
+ for profile in ptb.get_devices(device_type=deviceType):
340
+ # skip input-only devices (microphones)
341
+ if profile['NrOutputChannels'] == 0:
342
+ continue
343
+ # construct profile
83
344
  device = {
84
- 'deviceName': profile.get('DeviceName', "Unknown Microphone"),
345
+ 'deviceName': profile.get('DeviceName', "Unknown Speaker"),
85
346
  'index': profile.get('DeviceIndex', None),
347
+ 'name': profile.get('DeviceName', None)
86
348
  }
87
349
  devices.append(device)
88
350
 
@@ -18,7 +18,7 @@ file.
18
18
  """
19
19
 
20
20
  # Part of the PsychoPy library
21
- # Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2024 Open Science Tools Ltd.
21
+ # Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2025 Open Science Tools Ltd.
22
22
  # Distributed under the terms of the GNU General Public License (GPL).
23
23
 
24
24
  __all__ = [
@@ -10,7 +10,7 @@ trigger boxes from within PsychoPy.
10
10
  """
11
11
 
12
12
  # Part of the PsychoPy library
13
- # Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2024 Open Science Tools Ltd.
13
+ # Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2025 Open Science Tools Ltd.
14
14
  # Distributed under the terms of the GNU General Public License (GPL).
15
15
 
16
16
  __all__ = ['BaseTriggerBox']
@@ -8,7 +8,7 @@ port.
8
8
  """
9
9
 
10
10
  # Part of the PsychoPy library
11
- # Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2024 Open Science Tools Ltd.
11
+ # Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2025 Open Science Tools Ltd.
12
12
  # Distributed under the terms of the GNU General Public License (GPL).
13
13
 
14
14
  __all__ = [
psychopy/info.py CHANGED
@@ -2,7 +2,7 @@
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
4
  # Part of the PsychoPy library
5
- # Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2024 Open Science Tools Ltd.
5
+ # Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2025 Open Science Tools Ltd.
6
6
  # Distributed under the terms of the GNU General Public License (GPL).
7
7
 
8
8
  """This module has tools for fetching data about the system or the current
@@ -10,6 +10,7 @@ import time
10
10
  import subprocess
11
11
  import json
12
12
  import signal
13
+ import atexit
13
14
  from weakref import proxy
14
15
 
15
16
  import psutil
@@ -31,6 +32,8 @@ from psychopy import constants
31
32
 
32
33
  getTime = Computer.getTime
33
34
 
35
+ SHUTDOWN_FUNCS = []
36
+
34
37
  _currentSessionInfo = None
35
38
 
36
39
  def windowInfoDict(win):
@@ -1000,6 +1003,9 @@ class ioHubConnection():
1000
1003
  Computer.iohub_process_id = self._server_process.pid
1001
1004
  Computer.iohub_process = psutil.Process(self._server_process.pid)
1002
1005
 
1006
+ global SHUTDOWN_FUNCS
1007
+ SHUTDOWN_FUNCS.append(self._shutDownServer)
1008
+
1003
1009
  # >>>>> Create open UDP port to ioHub Server
1004
1010
  server_udp_port = self._iohub_server_config.get('udp_port', 9000)
1005
1011
  from ..net import UDPClientConnection
@@ -1451,6 +1457,17 @@ class ioEvent():
1451
1457
  self.type,
1452
1458
  self.id)
1453
1459
 
1460
+
1461
+ def shutdownActiveConnections():
1462
+ """Shutdown any active ioHub connections that are currently running.
1463
+ """
1464
+ activeConnection = ioHubConnection.getActiveConnection()
1465
+ if activeConnection is not None and hasattr(activeConnection, 'shutdown'):
1466
+ activeConnection.shutdown()
1467
+
1468
+
1469
+ atexit.register(shutdownActiveConnections)
1470
+
1454
1471
  _lazyImports = """
1455
1472
  from psychopy.iohub.client.connect import launchHubServer
1456
1473
  from psychopy.iohub.client import keyboard
@@ -229,6 +229,11 @@ class Keyboard(ioHubDeviceView):
229
229
  """
230
230
  kb_state = self.getCurrentDeviceState()
231
231
 
232
+ # catch anything that is not a dictionary, usually indicates an error
233
+ if type(kb_state) is not dict:
234
+ raise RuntimeError(
235
+ 'Keyboard device state request failed, got: %s' % kb_state)
236
+
232
237
  events = {int(k): v for k, v in list(kb_state.get('events').items())}
233
238
  pressed_keys = {int(k): v for k, v in list(kb_state.get('pressed_keys', {}).items())}
234
239
 
@@ -6,6 +6,7 @@ from .. import Device, ioDeviceError
6
6
  from ...constants import DeviceConstants, EyeTrackerConstants
7
7
  from . import hw
8
8
  from ...errors import print2err
9
+ from psychopy.tools.stimulustools import serialize, actualize
9
10
 
10
11
 
11
12
  class EyeTrackerDevice(Device):
@@ -268,25 +269,16 @@ class EyeTrackerDevice(Device):
268
269
  dict
269
270
  Dict describing the given Calibration object
270
271
  """
272
+ targetAttributes = serialize(calib.target, includeClass=True)
273
+ # target animation
274
+ targetAttributes['animate'] = {
275
+ 'enable': calib.movementAnimation,
276
+ 'expansion_ratio': calib.expandScale,
277
+ 'contract_only': calib.expandScale == 1,
278
+ }
279
+
271
280
  return {
272
- 'target_attributes': {
273
- # target outer circle
274
- 'outer_diameter': calib.target.radius * 2,
275
- 'outer_stroke_width': calib.target.outer.lineWidth,
276
- 'outer_fill_color': getattr(calib.target.outer._fillColor, calib.colorSpace) if calib.target.outer._fillColor else getattr(calib.target.win._color, calib.colorSpace),
277
- 'outer_line_color': getattr(calib.target.outer._borderColor, calib.colorSpace) if calib.target.outer._borderColor else getattr(calib.target.win._color, calib.colorSpace),
278
- # target inner circle
279
- 'inner_diameter': calib.target.innerRadius * 2,
280
- 'inner_stroke_width': calib.target.inner.lineWidth,
281
- 'inner_fill_color': getattr(calib.target.inner._borderColor, calib.colorSpace) if calib.target.inner._borderColor else getattr(calib.target.win._color, calib.colorSpace),
282
- 'inner_line_color': getattr(calib.target.inner._borderColor, calib.colorSpace) if calib.target.inner._borderColor else getattr(calib.target.win._color, calib.colorSpace),
283
- # target animation
284
- 'animate':{
285
- 'enable': calib.movementAnimation,
286
- 'expansion_ratio': calib.expandScale,
287
- 'contract_only': calib.expandScale == 1,
288
- },
289
- },
281
+ 'target_attributes': targetAttributes,
290
282
  'type': calib.targetLayout,
291
283
  'randomize': calib.randomisePos,
292
284
  'auto_pace': calib.progressMode == "time",
@@ -12,6 +12,7 @@ from psychopy.iohub.constants import EventConstants as EC
12
12
  from psychopy.iohub.devices.keyboard import KeyboardInputEvent
13
13
  from psychopy.iohub.errors import print2err
14
14
  from psychopy.constants import PLAYING
15
+ from psychopy.tools.stimulustools import serialize, actualize
15
16
 
16
17
  currentTime = Computer.getTime
17
18
 
@@ -46,7 +47,11 @@ class BaseCalibrationProcedure:
46
47
  self._lastCalibrationOK = False
47
48
  self._device_config = self._eyetracker.getConfiguration()
48
49
  display = self._eyetracker._display_device
49
- updateSettings(self._device_config.get('calibration'), calibration_args)
50
+ # apply calibration args to defaults
51
+ self._device_config['calibration'].update(calibration_args)
52
+ # get target attributes (ignore default keys as args can vary)
53
+ self._device_config['calibration']['target_attributes'] = calibration_args['target_attributes']
54
+ # use modified default config for calibration args
50
55
  self._calibration_args = self._device_config.get('calibration')
51
56
  unit_type = self.getCalibSetting('unit_type')
52
57
  if unit_type is None:
@@ -154,38 +159,15 @@ class BaseCalibrationProcedure:
154
159
  color_type = self.getCalibSetting('color_type')
155
160
  unit_type = self.getCalibSetting('unit_type')
156
161
 
157
- def setDefaultCalibrationTarget():
158
- # convert sizes to stimulus units
159
- radiusPix = self.getCalibSetting(['target_attributes', 'outer_diameter']) / 2
160
- radiusObj = layout.Size(radiusPix, units=unit_type, win=self.window)
161
- radius = getattr(radiusObj, unit_type)[1]
162
- innerRadiusPix = self.getCalibSetting(['target_attributes', 'inner_diameter']) / 2
163
- innerRadiusObj = layout.Size(innerRadiusPix, units=unit_type, win=self.window)
164
- innerRadius = getattr(innerRadiusObj, unit_type)[1]
165
- # make target
166
- self.targetStim = visual.TargetStim(
167
- self.window, name="CP", style="circles",
168
- radius=radius,
169
- fillColor=self.getCalibSetting(['target_attributes', 'outer_fill_color']),
170
- borderColor=self.getCalibSetting(['target_attributes', 'outer_line_color']),
171
- lineWidth=self.getCalibSetting(['target_attributes', 'outer_stroke_width']),
172
- innerRadius=innerRadius,
173
- innerFillColor=self.getCalibSetting(['target_attributes', 'inner_fill_color']),
174
- innerBorderColor=self.getCalibSetting(['target_attributes', 'inner_line_color']),
175
- innerLineWidth=self.getCalibSetting(['target_attributes', 'inner_stroke_width']),
176
- pos=(0, 0),
177
- units=unit_type,
178
- colorSpace=color_type,
179
- autoLog=False
180
- )
181
-
182
- if self._calibration_args.get('target_type') == 'CIRCLE_TARGET':
183
- setDefaultCalibrationTarget()
184
- else:
185
- self.targetStim = createCustomCalibrationStim(self.window, self._calibration_args)
186
- if self.targetStim is None:
187
- # Error creating custom stim, so use default target stim type
188
- setDefaultCalibrationTarget()
162
+ # get attributes to create target
163
+ targetAttrs = self._calibration_args.get('target_attributes').copy()
164
+ # sanitize for creating
165
+ if "animate" in targetAttrs:
166
+ targetAttrs.pop("animate")
167
+ if "win" in targetAttrs:
168
+ targetAttrs['win'] = self.window
169
+
170
+ self.targetStim = actualize(targetAttrs)
189
171
 
190
172
  self.originalTargetSize = self.targetStim.size
191
173
  self.targetClassHasPlayPause = hasattr(self.targetStim, 'play') and hasattr(self.targetStim, 'pause')
@@ -14,6 +14,7 @@ try:
14
14
  import psychopy_eyetracker_pupil_labs.pupil_labs.pupil_core as __plugin__
15
15
  from psychopy_eyetracker_pupil_labs.pupil_labs.neon import (
16
16
  __file__,
17
+ MonocularEyeSampleEvent,
17
18
  BinocularEyeSampleEvent,
18
19
  EyeTracker)
19
20
  except (ModuleNotFoundError, ImportError, NameError):
@@ -6,7 +6,8 @@
6
6
  from ctypes import cdll
7
7
 
8
8
  from . import MouseDevice
9
- from .. import Keyboard, Computer, Device, xlib
9
+ from .. import Computer, Device, xlib
10
+ from ..keyboard import Keyboard
10
11
  from ...constants import MouseConstants
11
12
  from ...errors import print2err, printExceptionDetailsToStdErr
12
13
 
@@ -90,6 +91,10 @@ class Mouse(MouseDevice):
90
91
  logged_time = currentSec()
91
92
  event_array = event[0]
92
93
 
94
+ if self._iohub_server is None or self._iohub_server._psychopy_windows is None:
95
+ # Do not report event if no ioHub server is running or no psychopy window is open
96
+ return True
97
+
93
98
  psychowins = self._iohub_server._psychopy_windows.keys()
94
99
  report_all = self.getConfiguration().get('report_system_wide_events', True)
95
100
  if report_all is False and psychowins and event_array[-1] not in psychowins:
@@ -178,6 +178,11 @@ class Mouse(MouseDevice):
178
178
  if self.isReportingEvents():
179
179
  logged_time = currentSec()
180
180
  report_system_wide_events = self.getConfiguration().get('report_system_wide_events', True)
181
+
182
+ if self._iohub_server is None or self._iohub_server._psychopy_windows is None:
183
+ # Do not report event if no ioHub server is running or no psychopy window is open
184
+ return True
185
+
181
186
  pyglet_window_hnds = self._iohub_server._psychopy_windows.keys()
182
187
  if event.Window in pyglet_window_hnds:
183
188
  pass
psychopy/layout.py CHANGED
@@ -2,7 +2,7 @@
2
2
  # -*- coding: utf-8 -*-
3
3
 
4
4
  # Part of the PsychoPy library
5
- # Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2024 Open Science Tools Ltd.
5
+ # Copyright (C) 2002-2018 Jonathan Peirce (C) 2019-2025 Open Science Tools Ltd.
6
6
  # Distributed under the terms of the GNU General Public License (GPL).
7
7
 
8
8
  """Classes and functions for working with coordinates systems."""