\ io \ \ io_file_scene \ class used to capture settings ("preferences") io's state. \ \ \ usage: \ \ methods: \ \ SAVE.DEFAULT: ( -- flag , save copy as default "io preferences" ) \ OPEN.DEFAULT: ( -- flag , open "io preferences" if available ) \ \ selectors (scene_pdur_mode, scene_pdur_sec, etc) are available for accessing \ file data. In most cases, file data access is the same as the file.elmnts or \ mac.file.elmnts classes. Input settings, however, are stored/retrieved \ differently. All input settings are stored in packed form (up to 4 settings \ packed into 32 bits). So we define the following methods to handle this: \ \ CLEAR.INPUT: ( -- , erase all input settings ) \ \ PUT.INPUT: ( n indx# elm# -- , store one input parameter ) \ GET.INPUT: ( indx# elm# -- n , retrieve one input parameter ) \ \ in the methods above, n is the data/value to be stored, indx# corresponds \ to the input/parser index, and elm# is the element number or data accessor. \ \ in order to keep track of the changes that may not have been saved, we \ add the following method: \ \ CHANGED: ( -- , mark as different from version on disk ) \ ?CHANGED: ( -- flag , true if different from version on disk ) \ \ note that this is independent from the flag returned by ?SAVED: \ \ \ see modules:io_file for more details on the file I/O used by io. \ \ see the file io_top for more information on io itself. \ \ \ constructor: Han-earl Park \ copyright 2008 buster & friends' C-ALTO Labs \ \ www.busterandfriends.com/io \ \ (Edinburgh, November 1996 - \ (London, August 1997 - \ (Den Haag, October 1997 - \ (Valencia, March 1999 - \ (Southampton, May 2000 - \ (Cork, April 2006 - \ \ (Cork, October 2008 - \ \ REV: 0.0.1 alpha (Southampton, October 2000) \ REV: 0.0.1 beta (Southampton, November 2000) \ REV: 0.0.1 alpha++ (Southampton, July 2004) \ REV: 0.0.1 beta++ (Cork, May 2010) \ \ \ REV: 0.0.1 alpha * Unused * \ REV: 0.0.1 beta * Unused * \ MOD: HeP 04-15-04 Add the io_scene module in an attempt to simplify writing \ reading of settings files. \ MOD: HeP 04-24-04 Make subclass of FILE.ELMNTS (should make things simpler). \ MOD: HeP 04-25-04 Rename as io_file_scene. \ Do _not_ automatically add:/delete: IO.SCENE from \ scene-list during new:/free: methods. \ MOD: HeP 04-29-04 Add GET/PUT.INPUT: and CLEAR.INPUT: methods. \ Append number to all "untitled" files. \ Make IO.SCENE a subclass of MAC.FILE.ELMNTS. \ MOD: HeP 05-01-04 Move all includes (and conditional includes) from the \ individual files to load_io. \ MOD: HeP 05-14-04 Rewrite INSTANTIATE.SCENE to insert a scene after the \ current rather than just adding to the end of the list. \ MOD: HeP 05-14-04 File names are stored in object so are no longer \ overwritten by an external process. \ MOD: HeP 05-15-04 Since file name is stored internally, this simplifies the \ numbering of the "untitled" files. \ Update comments and docs. \ Fixed bug that appended a number when opening files by \ making access to file name exclusively via late bound \ calls to GET/PUT.FILE.NAME: (see myt:file_elmnts and \ myt:file_elmnts_mac). \ MOD: HeP 05-16-04 Add CHANGED: method. \ Modify words that track file save state (SAVED.CHANGE, \ etc) to use OB.IO.SCENE's save state. \ Fix bug in file_elmnts_mac that caused erroneous error \ reports under certain conditions. \ MOD: HeP 05-24-04 Changes from saved file is kept independently of the save \ state. Add method ?CHANGED: and i'var iv-felm-changed? \ MOD: HeP 06-27-04 Check that file format. \ MOD: HeP 06-28-04 Report errors in INSTANTIATE.SCENE. \ MOD: HeP 07-02-04 OPEN.DEFAULT: will not use dialog boxes to report errors. \ REV: 0.0.1 a ++ __________________________________________________________ \ REV: 0.0.1 b ++ __________________________________________________________ \ Version for performance at Blackrock Castle Observatory, \ Cork, Ireland, May 25, 2010. anew task-io_file_scene \ scene list 32 constant max_#scenes ob.objlist scene-list \ storage for the scenes \ number of "untitled" scenes created variable #untitled-scenes \ data access 16 constant scene_#param 00 constant scene_pdur_mode 01 constant scene_pdur_sec 02 constant scene_ui_ctrl 03 constant scene_ui_c1 04 constant scene_ui_c2 05 constant scene_ui_channel 06 constant scene_output_device 07 constant scene_output_channel 08 constant scene_output_device_id 09 constant scene_output_pan 10 constant scene_output_rev 11 constant scene_input_#enabled 12 constant scene_input_enabled? 13 constant scene_input_device 14 constant scene_input_channel 15 constant scene_input_bend \ since we can have several parsers active so we store each parameter as a \ char packed into a 32 bit long word. Thus we can store the state of up to \ four parsers in a single element. \ \ ToDo: this is dependent on io_#input having a value of four or less, rewrite \ to make this adjust to having any arbitrary number of inputs. \ \ q/ could we use 6 bit (0-36) parameters? \ using 8 bits (0-255) here, can't use 4 bits (0-15) 'cause pitch bend \ is in the range of 0-24, but how about 6 bits...? : (INPUT->SCENE) ( n indx# -- n' ) swap $ ff AND swap 8 * shift ; : (SCENE->INPUT) ( n' indx# -- n ) 8 * negate shift $ ff AND ; : INPUT->SCENE { n indx# elm# obj -- , store into io.file object } n indx# (input->scene) elm# get: obj OR elm# put: obj ; : SCENE->INPUT { indx# elm# obj -- n , retrieve from io.file object } elm# get: obj indx# (scene->input) ; \ io.scene class method SAVE.DEFAULT: method OPEN.DEFAULT: method CLEAR.INPUT: method PUT.INPUT: method GET.INPUT: method CHANGED: method ?CHANGED: :class OB.IO.SCENE iv-felm-file-creator -1 iv=> iv-felm-untitled? ;m :m DEFAULT: ( -- ) ;m \ verify file format :m VERIFY: ( file -- flag , verify file format ) dup 0 offset_beginning FSEEK drop \ { | #elm #dim -- } NO@ \ dup #elm 4 FREAD 4 = over #dim 4 FREAD 4 = AND \ #elm @ scene_#param = AND \ check number of elements #dim @ dimension: self = AND \ swap #elm @ #dim @ * cells offset_beginning FSEEK 0>= AND ;m \ keep track of unsaved changes :m CHANGED: ( -- , mark as different from version on disk ) true iv=> iv-felm-changed? ;m :m ?CHANGED: ( -- flag , true if different from version on disk ) iv-felm-changed? ;m \ modify standard menthods to keep track of changes : FELM.SET.CHANGED.STATE ( flag -- ) NOT iv=> iv-felm-changed? ; :m OPEN: ( -- flag ) open: super dup felm.set.changed.state ;m :m SAVE.AS: ( -- flag ) save.as: super dup felm.set.changed.state ;m :m SAVE: ( -- flag ) save: super dup felm.set.changed.state ;m :m REVERT: ( -- flag ) revert: super dup felm.set.changed.state ;m \ allocate memory :m NEW: ( -- ) scene_#param 1 new: super \ #elm #dim -- ;m \ following methods also appends a number if the file is "untitled". \ \ note: be careful since this doesn't really keep track of the number of files \ created or opened, but (if no file name is assigned) the number of \ times GET.FILE.NAME: is called. However, it is okay to send \ GET.FILE.NAME: to the same object since we only count the first call. :m PUT.FILE.NAME: ( $fname | 0 -- ) dup 0= iv=> iv-felm-untitled? \ put.file.name: super ;m :m GET.FILE.NAME: ( -- $fname ) iv-felm-untitled? IF #untitled-scenes @ IF iv&> iv-felm-file-name BL $append.char #untitled-scenes @ n>text iv&> iv-felm-file-name $append THEN \ #untitled-scenes @ 1+ #untitled-scenes ! \ incr counter \ 0 iv=> iv-felm-untitled? \ prevent successive assignments THEN iv&> iv-felm-file-name ;m :m OPEN.DEFAULT: ( -- flag ) false -> felm_dialog_error? \ " io preferences" self put.file.name: [] 0 open.from: self \ true -> felm_dialog_error? ;m :m SAVE.DEFAULT: ( -- flag ) \ \ save current state... iv&> iv-felm-file-name pad $MOVE \ iv-felm-file-ptr iv-felm-open? iv-felm-saved? iv-felm-untitled? \ " io preferences" self put.file.name: [] 0 save.to: self close: self >r \ save error flag \ \ restore state... iv=> iv-felm-untitled? iv=> iv-felm-saved? iv=> iv-felm-open? iv=> iv-felm-file-ptr \ pad iv&> iv-felm-file-name $MOVE \ r> \ save error flag ;m :m CLEAR.INPUT: ( -- ) 0 scene_input_enabled? put: self 0 scene_input_device put: self 0 scene_input_channel put: self 0 scene_input_bend put: self ;m :m PUT.INPUT: { n indx# elm# -- , store input data } n indx# (input->scene) elm# get: self OR elm# put: self ;m :m GET.INPUT: { indx# elm# -- n , retrieve from io.file object } elm# get: self indx# (scene->input) ;m ;class \ instantiate & deinstantiate scenes : SCENE.LIST.FULL? ( -- flag , true if no space left for new scenes ) many: scene-list max.elements: scene-list >= ; : INSTANTIATE.SCENE.ERROR.DLOG ( -- ) " Sorry, unable to create scene in memory (maybe a memory error)." dialog.a ; : SCENE.LIST.FULL.DLOG ( -- ) 0 pad c! \ " Sorry, cannot have more than " count pad $append max_#scenes n>text pad $append " scenes open." count pad $append \ pad dialog.a ; : INSTANTIATE.SCENE { indx -- obj | 0 , create scene and add to list } scene.list.full? IF scene.list.full.dlog 0 ELSE instantiate ob.io.scene dup IF dup new: [] dup indx insert: scene-list ELSE instantiate.scene.error.dlog THEN THEN ; : DEINSTANTIATE.SCENE ( obj -- , clearup scene and remove from list ) dup free: [] dup deinstantiate \ delete: scene-list ; \ setup & clearup : IO.FILE.SCENE.INIT ( -- ) sub" io.file.scene.init" \ true -> felm_dialog_error? \ 0 #untitled-scenes ! \ max_#scenes new: scene-list ; : IO.FILE.SCENE.TERM ( -- ) sub" io.file.scene.term" \ many: scene-list 0 DO i get: scene-list dup free: [] deinstantiate LOOP \ free: scene-list ; if.forgotten io.file.scene.term