diff --git a/frontend/README-tcltk b/frontend/README-tcltk index e6c3c384..2b499d96 100644 --- a/frontend/README-tcltk +++ b/frontend/README-tcltk @@ -24,16 +24,38 @@ See man xorriso for a documentation of xorriso concepts and commands. See man xorrecord for details of the burn image file feature. -Quick start: + Quick start - xorriso -launch_frontend $(which xorriso-tcltk) --stdio -- +In the xorriso build directory, without installation of xorriso: + xorriso/xorriso -launch_frontend frontend/xorriso-tcltk --stdio -- + +After installation of xorriso by make install: + + xorriso-tcltk + + + Overview of GUI + +The window is separated into three main areas: +- Connection to xorriso. +- Management of drives and image files. +- Inspection, manipulation, and exploitation of xorriso ISO image model. + +Click the rightmost mouse button while being over any of the GUI elements +in order to get the particular help text for that element. +There is no need to close the help window. Just click another element to +get another help text. + + + Program start options The Tcl shell "wish" is allergic to options which start by "-h". So here is the output of xorriso-tcltk --help : ------------------------------------------------------------------------ + Usage: - xorriso-tcltk [options] + frontend/xorriso-tcltk [options] Options: All options must be given with two dashes ("--option") in order to distinguish them from any options of the Tcl shell. @@ -51,6 +73,9 @@ Options: It is important that the parent of xorriso and of this tcl/tk frontend opens the named pipe for commands before it opens the named pipe for replies. This avoids deadlock. + --silent_start + Do not issue the start message xorriso-tcltk-version. + This works only if --silent_start is the first argument. --geometry {+|-}X{+|-}Y Sets the position of the main window. --click_to_focus @@ -63,229 +88,12 @@ Options: Set a file address for logging of xorriso commands and reply messages. The log lines will be appended. -Either --stdio or --named_pipes must be given for a program run. +If neither --stdio nor --named_pipes is given, then this script +will try to locate itself in the filesystem and start a xorriso +run that launches it again. + +In the running GUI, click with the rightmost mouse button on +any GUI element to get its particular help text. ------------------------------------------------------------------------ - - Overview of GUI elements - -The window is separated into three main areas: -- Connection to xorriso. -- Management of drives and image files. -- Inspection, manipulation, and exploitation of xorriso ISO image model. - ------------------------------------------------------------------------- - - Connection to xorriso - -The "End" button leads to the end of frontend and xorriso process. - -The ready/busy field indicates whether a xorriso command is being executed -and the frontend is still waiting for its reply messages. - -The "Command:" field can be used to send commands to xorriso. - -The "Refresh state display" button causes the other two main areas to update -their display after manually transmitted commands may have changed the state -of drives or ISO model. - -The "Log pipes" switch controls whether all xorriso commands and replies -shall be logged to standard error resp. to the file that has been iven -with program argumen --log_file. Caution: This log is verbous. - -The message box displays commands sent to xorriso and messages recieved -from xorriso. -Many commands which are emitted by the GUI will hide themselves and their -replies from this display. -All event messages with severity WARNING or higher will show up, nevertheless. - -The "Recent problem:" field shows the most severe event message that occured -during the execution of the most recent command. It also displays the most -recent problem message from the frontend program itself. -Several commands emitted by the GUI will not clear this display. But any -manually transmitted command and the major GUI gestures will do. - -The "Worst problem:" field shows the most severe event message that occured -since last time the "Clear" button was hit. It will not clear automatically. - - ------------------------------------------------------------------------- - - Management of drives and image files - -The "Scan for drives" button executes command -devices and puts the list -of found optical drives into the box underneath the button. - -The "Pick input drive" button executes command -indev and obtains some -information about the medium status. This info is displayed in the -"Input drive or image" line. -Further it causes the display of the ISO image model to be updated. - -The "Pick output drive" button executes command -outdev and displays the -related info in the "Output drive or image" line. - -The "Pick drive for both roles" button executes command -dev and displays -info in both "... drive or image" lines. - -The "Give up drives" executes commands -indev "" -outdev "" and clears -both "... drive or image" lines, as well as the ISO model. - -The "Calm drives" button executes command -calm_drives which tells the -aquired optical drives to stop spinning until the next drive activity -gets triggered. - -The "Rollback" button excutes command -rollbackwhich drops all pending -changes of the ISO model and reloads it from the input drive, if one is -aquired. - -The box underneath these buttons shows the optical drives found by the -"Can for drives" button. -A double-click on a drive item has the same effect as button "Pick drive -for both roles". - -The line "Input drive or image" displays address and medium status of -the input drive. -Its "Eject" button excutes command -eject "in". -Editing the drive address and pressing the Return key causes the execution -of command -indev with the field content as drive address. Use this to -load the model from ISO image data files on hard disk. - -The line "Output drive or image" does about the same for the output drive. -The text input field can be used to address an existing ISO image data -file or to address a data file that does not yet exist. In the latter -case, the ,edium status will be blank. - -The "Blank" button executes command -blank "as_needed" on the output drive. -This also applies to ISO image data files, which will get invalidated by -a small write operation. - -The "Format" button executes -format "as_needed". -This only applies to real optical drives and s of interest only with DVD-RW -or BD-R media, which both can be used formatted and unformatted. Other media -types which mandatorily need formatting will be formatted by the write -commands. - -The "Write ISO session" executes command -commit, which writes a session -with all pending changes to the output drive. The output drive must be -either blank or it must be the same as the input drive. - -The "Close" switch controls whether command -close "on" is emitted with -"Write ISO session" or whether -as cdrecord option -multi is omitted with -"Burn image file:". - -The "TAO" switch controls whether an incremental write type shall be -enforced with write commands. Normally xorriso will decide by medium status -and job parameters which write type to choose. - -The "Defect Mgt" switch controls whether slow and error-prone drive internal -check reading shall be enabled with formatted BD-R or with BD-RE. - -The "Burn image file:" button executes command -as "cdrecord" with the -content of its text field as disk file address of a data file that is -to be written to the output drive. -The medium in the drive may be blank or appendable. - - ------------------------------------------------------------------------- - - Inspection, manipulation, and exploitation of xorriso ISO image model - -The "Extract to disk:" button executes command -extract with the whole -tree of the current ISO directory or with the selected items of the box -underneath "ISO directory:". -This copies the selected files or directory trees from the input drive -to the address on hard disk which is given by the text filed right of -the button. - -The "Underneath" switch controls the effective hard disk address of an item -if the address in the text field points to a directory. If "Underneath" -is enabled, then the file object from the ISO filesystem will be copied to its -name underneath the hard disk directory. -If "Underneath" is disabled then an ISO directory tree item will be merged -with the disk directory tree at the given address. -Example: -Selected are "/iso_dir" and "/iso_file". -Address for hard disk is "/tmp/from_iso". Switch "Selected" is enabled. -"Underneath" enabled causes commands: - -extract /iso_dir /tmp/from_iso/iso_dir - -extract /iso_file /tmp/from_iso/iso_file -"Underneath" disabled: - -extract /iso_dir /tmp/from_iso - -extract /iso_file /tmp/from_iso -The last command will fail because /tmp/from_iso already exists as directory. - -The "Selected" switch controls whether the whole current ISO directory, -or only the selected items shall be copied to to hard disk. - -The "Overwrite files" switch controls whether existing files may be -overwritten in the ISO image or by extraction on hard disk. -The frontend program will only detect the most obvious name collisions, -but xorriso will reliably refuse to overwrite files if this is banned. - -The "Overwrite ISO dirs" switch controls whether it is allowed to replace -an ISO directory by a non-directory file. -If a directory is copied to a directory, then both directory trees will -be merged. So this switch applies only to situations where non-directories -hit directories. - -The "Enforce disk dir write access" switch enables the options "auto_chmod_on" -and "sort_lba_on". "auto_chmod_on" allows xorriso to give itself temporariy -w-permission to all disk directories which are owned by the xorriso user. -This is not without dangers, of course, but comes in handy with restoring of -backups. -Option "sort_lba_on" reduces head-moves of optical drives and thus can -speed up extraction substantially. It is bound to "auto_chmod_on" because -else it might get in trouble when restoring ISO directories which offer -no w-permission. - -The "Refresh avail:" button triggers a time consuming exact prediction -of the free space on the medium in the output drive. For this purpose, -the size of an ISO session with the pending changes is computed. -With image files rather than real optical drives, the free space of -the hosting filesystem is displayed. - -The "Insert from disk:" button executes command -map with the disk file -address that is given by the text field right to the button. - -The switch "Underneath" has the same effect as with file extraction: -If enabled, a directory from disk will not be unpacked to its single files -but put underneath the target address by its own leaf name. -If the switch "Selected" is enabled, then the given disk file or tree will -be inserted at or underneath the only selected item in the box inderneath -"ISO directory:". - -The text field in the "ISO directory:" line displays the current ISO -directory and can be used to toggle its path directly. Hitting the -Return key causes the current directory to change and the display in -the box underneath to be refreshed. - -The "Up" buttons move the current ISO directory one directory level up. - -The "Verify" button executes -md5_check_r "SORRY" with the current ISO -directory. ISO images bear MD5s for each data file if they were produced -by xorriso with -md5 "on" resp. -for_backup. This frontend enables this -feature on startup. - -The list box underneath the "ISO directory:" line displays the files in -the current ISO directory. One or more item can be selected and play a -role with extraction or insertion of files. -Most of the buttons underneath the box operate on the selected items -unconditionally. - -The "Verify" button in the "ISO selection:" line executes command --md5_check_r "SORRY" with each of the selected items. - -The "Delete" button executes command -rm_r with each of the selected items. - -The "Rename to:" button iuses command -mv to move each of the selected -items to the address that is given by the text field right to the button. -If this address points to an existing ISO directory, then the items will -be moved underneath that directory and keep their leaf names. -Else there may be only one selected item which will be renamed to the -given address. - -The "Make dir" button executes command -mkdir with the address in the -text field to its left (the same as used by "Rename to:"). Useful to -create a target directory before moving the selection. - diff --git a/frontend/xorriso-tcltk b/frontend/xorriso-tcltk index ee76ab0d..595a7960 100755 --- a/frontend/xorriso-tcltk +++ b/frontend/xorriso-tcltk @@ -39,6 +39,9 @@ proc print_usage {argv0} { puts stderr " It is important that the parent of xorriso and of this" puts stderr " tcl/tk frontend opens the named pipe for commands before" puts stderr " it opens the named pipe for replies. This avoids deadlock." + puts stderr " --silent_start" + puts stderr " Do not issue the start message xorriso-tcltk-version." + puts stderr " This works only if --silent_start is the first argument." puts stderr " --geometry {+|-}X{+|-}Y" puts stderr " Sets the position of the main window." puts stderr " --click_to_focus" @@ -51,7 +54,12 @@ proc print_usage {argv0} { puts stderr " Set a file address for logging of xorriso commands and" puts stderr " reply messages. The log lines will be appended." puts stderr "" - puts stderr "Either --stdio or --named_pipes must be given for a program run." + puts stderr "If neither --stdio nor --named_pipes is given, then this script" + puts stderr "will try to locate itself in the filesystem and start a xorriso" + puts stderr "run that launches it again." + puts stderr "" + puts stderr "In the running GUI, click with the rightmost mouse button on" + puts stderr "any GUI element to get its particular help text." puts stderr "" } @@ -716,6 +724,7 @@ proc setup_xorriso {} { set cmd "$cmd -hardlinks off" set cmd "$cmd -abort_on NEVER" + set cmd "$cmd -return_with ABORT 32" set cmd "$cmd -report_about UPDATE" set cmd "$cmd -osirrox on" set cmd "$cmd -iso_rr_pattern off" @@ -1014,10 +1023,11 @@ set busy_text_exists 0 # Whether to demand a click before focus goes to entry or listbox set click_to_focus "0" -# Whether .ack_window resp. .yesno_window is already displayed +# Whether .ack_window , .yesno_window , .help_window is already displayed # (>>> Better would be to block user interaction until they are gone) set ack_window_is_active 0 set yesno_window_is_active 0 +set help_window_is_active 0 # ------ GUI callback procedures ---- @@ -1207,6 +1217,7 @@ proc scan_for_drives {} { .drivelist delete 0 [expr "$max_idx-1"] set devlist "" + reset_highest_cmd_sev clear_sieve send_marked_cmd "-devices" set max_idx 0 @@ -2282,6 +2293,56 @@ proc window_ack {question button_color where} { } +# Destroy the help pop-up window. +# +proc destroy_help {w} { + global help_window_is_active + + if {"$w" != ""} { + destroy "$w" + } + set help_window_is_active 0 +} + + +# Pop-up a window which shows a help text and a Close button. +# +proc window_help {about_what button_color} { + global help_window_is_active + global .help_window + + set color "#F0F0F0" + + set re_use_widgets 0 + set w {.help_window} + if {"$help_window_is_active" == 0} { + toplevel $w -borderwidth 20 -class Help + wm title $w "xorriso-tcltk help text" + set help_window_is_active 1 + } else { + set re_use_widgets 1 + } + set helptext [tell_helptext "$about_what"] + if {"$re_use_widgets" == 1} { + $w.text configure -state normal + $w.text delete 1.0 end + $w.text insert end "$helptext" + raise $w + } else { + # wm geometry $w +0+0 + set destroy_cmd "destroy_help $w" + + text $w.text -width 80 -height 20 -relief flat -borderwidth 0 + $w.text insert end "$helptext" + button $w.close -text "Close" -command "$destroy_cmd" \ + -background "$button_color" + pack $w.text -side top -expand 1 -fill both + pack $w.close -side top + } + $w.text configure -state disabled +} + + # Display the busy/ready state of xorriso. # Called with 1 by sender of commands and with 0 by receivers of replies . # @@ -2390,30 +2451,38 @@ proc init_input {} { -side top -anchor w -expand 1 -fill both button .end_button -text "End" -command "end_xorriso" + bind_help .end_button "End" + if {[string length "$xorriso_version"] > 10} { set xorriso_version [string range "$xorriso_version" 0 9] } label .xorriso_version -text "xorriso-$xorriso_version" + bind_help .xorriso_version "version" frame .busy -relief ridge -borderwidth 2 label .busy_text -width 5 -text "busy" + bind_help .busy_text "ready/busy" set busy_text_exists 1 pack .busy_text -in .busy button .refresh_state -text "Refresh state display" \ -command "refresh_state" + bind_help .refresh_state "Refresh state display" checkbutton .log_pipes_switch -text "Log pipes" \ -indicatoron 1 -selectcolor "" \ -relief ridge -borderwidth 2 \ -variable logging \ -onvalue 1 -offvalue 0 + bind_help .log_pipes_switch "Log pipes" + button .help -text "Help" -command {window_help "Help" "grey"} + bind_help .help "Help" init_cmdline pack .end_button .xorriso_version .busy -in .input_line1 -side left pack .cmdline \ -in .input_line1 -side left -expand 1 -fill both - pack .refresh_state .log_pipes_switch -in .input_line1 -side left + pack .refresh_state .log_pipes_switch .help -in .input_line1 -side left } @@ -2426,9 +2495,11 @@ proc init_cmdline {} { frame .cmdline -borderwidth 0 label .cmdline_text -width 10 -text "Command:" + bind_help .cmdline_text "Command:" entry .cmdline_entry -width 60 -relief sunken -bd 1 \ -textvariable cmdline bind_entry_keys .cmdline_entry {cmdline_return} + bind_help .cmdline_entry "Command:" # >>> is there a chance to get a history on an entry ? @@ -2451,6 +2522,7 @@ proc init_msgbox {} { -yscrollcommand ".msgscroll set" \ -exportselection $export_msg_selection bind_listbox_keys ".msglist" "$msglist_lines" + bind_help .msglist "message box" set msglist_running 1 foreach i "$pre_msglist" { @@ -2493,9 +2565,12 @@ proc init_cmd_errmsg {} { frame .cmd_errmsg -borderwidth "$borderwidth" label .cmd_errmsg_label -width 14 -text "Recent problem:" - entry .cmd_errmsg_msg -width 80 -relief raised -bd 1 \ - -textvariable highest_cmd_sev_msg + bind_help .cmd_errmsg_label "Recent problem:" + label .cmd_errmsg_msg -width 80 -relief ridge -bd 2 \ + -anchor w \ + -textvariable highest_cmd_sev_msg # (no keys, no focus) + bind_help .cmd_errmsg_msg "Recent problem:" pack .cmd_errmsg_label -in .cmd_errmsg -side left pack .cmd_errmsg_msg -in .cmd_errmsg -side left -expand 1 -fill both } @@ -2511,12 +2586,16 @@ proc init_total_errmsg {} { frame .total_errmsg -borderwidth "$borderwidth" label .total_errmsg_label -text "Worst problem:" -width 14 + bind_help .total_errmsg_label "Worst problem:" button .total_errmsg_clear -text "Clear" \ -width 5 \ -command "clear_total_errmsg" - entry .total_errmsg_msg -width 80 -relief raised -bd 1 \ - -textvariable highest_total_sev_msg + bind_help .total_errmsg_clear "Clear" + label .total_errmsg_msg -width 80 -relief ridge -bd 2 \ + -anchor w \ + -textvariable highest_total_sev_msg # (no keys, no focus) + bind_help .total_errmsg_msg "Worst problem:" pack .total_errmsg_label -in .total_errmsg -side left pack .total_errmsg_msg -in .total_errmsg -side left -expand 1 -fill both pack .total_errmsg_clear -in .total_errmsg -side left @@ -2540,6 +2619,7 @@ proc init_drivebox {} { -yscrollcommand ".drivescroll set" \ -exportselection $export_selection bind_listbox_keys ".drivelist" "$drivelist_lines" + bind_help .drivelist "drivelist" scrollbar .drivescroll -command ".drivelist yview" pack .drivelist -in .drivelistbox -side left -expand 1 -fill both @@ -2548,17 +2628,24 @@ proc init_drivebox {} { frame .drive_picker -borderwidth $borderwidth button .drive_scan -text "Scan for drives" \ -command "scan_for_drives" + bind_help .drive_scan "Scan for drives" button .drive_pick_in -text "Pick input drive" \ -command "pick_indev" + bind_help .drive_pick_in "Pick input drive" button .drive_pick_out -text "Pick output drive" \ -command "pick_outdev" + bind_help .drive_pick_out "Pick output drive" button .drive_pick_both -text "Pick drive for both roles" \ -command "pick_dev" + bind_help .drive_pick_both "Pick drive for both roles" button .drive_drop_both -text "Give up drives" \ -command "give_up_dev" + bind_help .drive_drop_both "Give up drives" button .drive_calm -text "Calm drives" \ -command "calm_drives" + bind_help .drive_calm "Calm drives" button .iso_rollback_button -text "Rollback" -command {iso_rollback} + bind_help .iso_rollback_button "Rollback" pack .drive_scan \ .drive_pick_in .drive_pick_out .drive_pick_both \ @@ -2601,11 +2688,15 @@ proc init_indev {} { frame .indev -borderwidth $borderwidth button .indev_eject -text "Eject" -command {eject_indev} + bind_help .indev_eject "Eject (indev)" label .indev_label -width 22 -text "Input drive or image " + bind_help .indev_label "Input drive or image" entry .indev_entry -width 40 -relief sunken -bd 1 \ -textvariable indev_adr bind_entry_keys .indev_entry {indev_return} + bind_help .indev_entry "Input drive or image" label .indev_summary -width 65 -text "" -relief ridge -borderwidth 2 + bind_help .indev_summary "input drive info" pack .indev_eject .indev_label .indev_entry .indev_summary \ -in .indev -side left -expand 1 -fill both } @@ -2620,11 +2711,15 @@ proc init_outdev {} { frame .outdev -borderwidth $borderwidth button .outdev_eject -text "Eject" -command {eject_outdev} + bind_help .outdev_eject "Eject (outdev)" label .outdev_label -width 22 -text "Output drive or image" + bind_help .outdev_label "Output drive or image" entry .outdev_entry -width 40 -relief sunken -bd 1 \ -textvariable outdev_adr bind_entry_keys .outdev_entry {outdev_return} + bind_help .outdev_entry "Output drive or image" label .outdev_summary -width 65 -text "" -relief ridge -borderwidth 2 + bind_help .outdev_summary "output drive info" pack .outdev_eject .outdev_label .outdev_entry .outdev_summary \ -in .outdev -side left -expand 1 -fill both } @@ -2643,30 +2738,38 @@ proc init_burn {} { button .burn_blank_button -text "Blank" \ -command {burn_blank} + bind_help .burn_blank_button "Blank" button .burn_format_button -text "Format" \ -command {burn_format} + bind_help .burn_format_button "Format" button .burn_commit_button -text "Write ISO session" \ -command {burn_commit} + bind_help .burn_commit_button "Write ISO session" button .burn_write_image -text "Burn image file:" \ -command {burn_write_image} + bind_help .burn_write_image "Burn image file:" entry .burn_write_image_entry -width 40 -relief sunken -bd 1 \ -textvariable burn_write_image_adr bind_entry_keys .burn_write_image_entry {burn_write_image} + bind_help .burn_write_image_entry "Burn image file:" checkbutton .burn_write_close -text "Close" \ -indicatoron 1 -selectcolor "" \ -relief ridge -borderwidth 2 \ -variable burn_write_close \ -onvalue 1 -offvalue 0 + bind_help .burn_write_close "Close" checkbutton .burn_write_tao -text "TAO" \ -indicatoron 1 -selectcolor "" \ -relief ridge -borderwidth 2 \ -variable burn_write_tao \ -onvalue 1 -offvalue 0 + bind_help .burn_write_tao "TAO" checkbutton .burn_write_defect_mgt -text "Defect Mgt" \ -indicatoron 1 -selectcolor "" \ -relief ridge -borderwidth 2 \ -variable burn_write_defect_mgt \ -onvalue 1 -offvalue 0 + bind_help .burn_write_defect_mgt "Defect Mgt" pack .burn_blank_button .burn_format_button \ .burn_commit_button .burn_write_close .burn_write_tao \ .burn_write_defect_mgt \ @@ -2687,12 +2790,17 @@ proc init_isobox {} { label .isodir_label -text "ISO directory:" \ -width 14 + bind_help .isodir_label "ISO directory:" entry .isodir_entry -width 60 -relief sunken -bd 1 \ -textvariable isodir_adr bind_entry_keys .isodir_entry {isodir_return "isodir_entry"} + bind_help .isodir_entry "ISO directory:" button .isodir_verify -text "Verify" -command {isodir_verify} + bind_help .isodir_verify "Verify" button .isodir_up -text "Up" -command {isodir_up} + bind_help .isodir_up "Up" button .isodir_up2 -text "Up" -command {isodir_up} + bind_help .isodir_up2 "Up" pack .isodir_label .isodir_up \ -in .isodir -side left pack .isodir_entry \ @@ -2705,6 +2813,7 @@ proc init_isobox {} { -yscrollcommand ".isoscroll_y set" \ -xscrollcommand ".isoscroll_x set" \ -exportselection $export_selection + bind_help .isolist "isolist" bind_listbox_keys ".isolist" "$isolist_lines" scrollbar .isoscroll_y -command ".isolist yview" scrollbar .isoscroll_x -orient horizontal -command ".isolist xview" @@ -2731,19 +2840,25 @@ proc init_isomanip {} { frame .isomanip_move -borderwidth 0 label .isomanip_prefix -text "ISO selection:" + bind_help .isomanip_prefix "ISO selection:" button .isomanip_verify_button -width 8 -text "Verify" \ -command {isomanip_verify} + bind_help .isomanip_verify_button "Verify (selection)" button .isomanip_rm_r_button -width 8 -text "Delete" \ -command {isomanip_rm_r} + bind_help .isomanip_rm_r_button "Delete" button .isomanip_move_button -text "Rename to:" \ -command {isomanip_mv} + bind_help .isomanip_move_button "Rename to:" button .isomanip_mkdir_button -width 8 -text "Make dir" \ -command {isomanip_mkdir} + bind_help .isomanip_mkdir_button "Make dir" entry .isomanip_move_target -width 60 -relief sunken -bd 1 \ -textvariable isomanip_move_target # bind_entry_keys .isomanip_move_target {isomanip_mv} bind_entry_keys .isomanip_move_target "" + bind_help .isomanip_move_target "rename and mkdir target" pack .isomanip_prefix .isomanip_verify_button .isomanip_rm_r_button \ .isomanip_move_button .isomanip_move_target .isomanip_mkdir_button \ -in .isomanip_move -side left -expand 1 -fill both @@ -2783,19 +2898,23 @@ proc init_extract {} { button .extract_button -text "Extract to disk:" \ -width 17 \ -command {extract_to} + bind_help .extract_button "Extract to disk:" entry .extract_entry -width 40 -relief sunken -bd 1 \ -textvariable "extract_to_adr" bind_entry_keys .extract_entry {extract_to} + bind_help .extract_entry "Extract to disk:" checkbutton .extract_underneath -text "Underneath" \ -indicatoron 1 -selectcolor "" \ -relief ridge -borderwidth 2 \ -variable extract_underneath \ -onvalue 1 -offvalue 0 + bind_help .extract_underneath "Underneath (extract)" checkbutton .extract_from_selected -text "Selected" \ -indicatoron 1 -selectcolor "" \ -relief ridge -borderwidth 2 \ -variable extract_from_selected \ -onvalue 1 -offvalue 0 + bind_help .extract_from_selected "Selected (extract)" pack .extract_button -in .extract_frame -side left pack .extract_entry \ -in .extract_frame -side left -expand 1 -fill both @@ -2818,23 +2937,28 @@ proc init_localfs_aux {} { -relief ridge -borderwidth 2 \ -variable overwrite_files \ -onvalue 1 -offvalue 0 + bind_help .overwrite_files_button "Overwrite files" checkbutton .overwrite_dir_button -text "Overwrite ISO dirs" \ -indicatoron 1 -selectcolor "" \ -relief ridge -borderwidth 2 \ -variable overwrite_dirs \ -onvalue 1 -offvalue 0 + bind_help .overwrite_dir_button "Overwrite ISO dirs" checkbutton .extract_auto_chmod -text "Enforce disk dir write access" \ -indicatoron 1 -selectcolor "" \ -relief ridge -borderwidth 2 \ -variable extract_auto_chmod \ -onvalue 1 -offvalue 0 + bind_help .extract_auto_chmod "Enforce disk dir write access" pack .overwrite_files_button .overwrite_dir_button .extract_auto_chmod \ -in .localfs_aux_frame -side left button .avail_button -text "Refresh avail:" \ -command {refresh_avail} + bind_help .avail_button "Refresh avail:" frame .avail_label_frame -relief ridge -borderwidth 2 label .avail_label -width 10 -text "" + bind_help .avail_label "Refresh avail:" pack .avail_label -in .avail_label_frame pack .avail_label_frame .avail_button -in .localfs_aux_frame -side right @@ -2855,19 +2979,23 @@ proc init_insert {} { button .insert_button -text "Insert from disk:" \ -width 17 \ -command {insert_from} + bind_help .insert_button "Insert from disk:" entry .insert_entry -width 40 -relief sunken -bd 1 \ -textvariable "insert_from_adr" bind_entry_keys .insert_entry {insert_from} + bind_help .insert_entry "Insert from disk:" checkbutton .insert_underneath -text "Underneath" \ -indicatoron 1 -selectcolor "" \ -relief ridge -borderwidth 2 \ -variable insert_underneath \ -onvalue 1 -offvalue 0 + bind_help .insert_underneath "Underneath (insert)" checkbutton .insert_at_selected -text "Selected" \ -indicatoron 1 -selectcolor "" \ -relief ridge -borderwidth 2 \ -variable insert_at_selected \ -onvalue 1 -offvalue 0 + bind_help .insert_at_selected "Selected (insert)" pack .insert_button -in .insert_from_frame -side left pack .insert_entry \ -in .insert_from_frame -side left -expand 1 -fill both @@ -2937,6 +3065,550 @@ proc bind_entry_keys {entry return_cmd} { } +# Bind a help text to a widget. +# +proc bind_help {to_what help_name} { + bind $to_what "window_help \"$help_name\" grey" +} + + +# The central storage for help texts. +# +proc tell_helptext {what} { + global own_version argv0 + + if {"$what" == "Help"} { + return \ +"For getting particular help texts: + +Click the rightmost mouse button on any button, list, or text field of the GUI. + +----------------------------------------------------------------------------- + +xorriso-tcltk is mainly a proof of concept for a frontend that operates +xorriso in dialog mode. + +It demonstrates some of xorriso's multi-session features with ISO 9660 +filesystems on optical media (CD, DVD, BD) or in disk files. + +Copyright (C) 2012, Thomas Schmitt , libburnia-project.org +Provided under GNU GPL version 2 or later. + +----------------------------------------------------------------------------- + +For a help text about startup options of this frontend, execute: + + $argv0 --help" + } + if {"$what" == "End"} { + return \ +"The \"End\" button leads to the end of frontend and xorriso process." + } + if {"$what" == "version"} { + return \ +"The field between \"End\" button and ready/busy field displays the +version of the serving xorriso program. + +xorriso is a program which copies file objects from POSIX compliant +filesystems into Rock Ridge enhanced ISO 9660 filesystems and allows +session-wise manipulation of such filesystems. It can load the management +information of existing ISO images and it writes the session results to +optical media or to filesystem objects. +Vice versa xorriso is able to restore file objects from ISO 9660 filesystems. + +xorriso-tcltk-$own_version is mainly a proof of concept for a frontend +that operates xorriso in dialog mode. + +It exercises several fundamental gestures of communication: +- connecting via two pipes +- sending commands +- receiving replies +- inquiring the xorriso message sieve +- using the xorriso parsing service + +Note that any other language than Tcl/Tk could be used, if it only can +do i/o via standard input and standard output or via named pipes. +Further it has to perform integer arithmetics and string manipulations. +And, well, a graphical widget set would be nice." + } + if {"$what" == "Refresh state display"} { + return \ +"The \"Refresh state display\" button causes several text fields and list +boxes to update their display after manually transmitted commands may +have changed the state of drives or ISO model." + } + if {"$what" == "ready/busy"} { + return \ +"The ready/busy field indicates whether a xorriso command is being executed +and the frontend is still waiting for its reply messages." + } + if {"$what" == "Command:"} { + return \ +"The \"Command:\" field can be used to send commands to xorriso. +See the manual page of xorriso for its concepts and commands." + } + if {"$what" == "Refresh state display"} { + return \ +"The \"Refresh state display\" button causes the other two main areas to update +their display after manually transmitted commands may have changed the state +of drives or ISO model." + } + if {"$what" == "Log pipes"} { + return \ +"The \"Log pipes\" switch controls whether all xorriso commands and replies +shall be logged to standard error resp. to the file that has been given +with program argument --log_file. + +Caution: This log is verbous." + } + if {"$what" == "message box"} { + return \ +"The message box displays commands sent to xorriso and messages received +from xorriso. + +Many commands which are emitted by the GUI will hide themselves and their +replies from this display. All event messages with severity WARNING or +higher will show up, nevertheless." + } + if {"$what" == "Recent problem:"} { + return \ +"The \"Recent problem:\" field shows the most severe event message that occured +during the execution of the most recent command. It also displays the most +recent problem message from the frontend program itself. + +Several commands emitted by the GUI will not clear this display. But any +manually transmitted command and the major GUI gestures will do. +" + } + if {"$what" == "Worst problem:"} { + return \ +"The \"Worst problem:\" field shows the most severe event message that occured +since last time the \"Clear\" button was hit. It will not clear automatically." + } + if {"$what" == "Clear"} { + return \ +"The \"Clear\" button removes the message from the \"Worst problem:\" field." + } + if {"$what" == "Scan for drives"} { + return \ +"The \"Scan for drives\" button executes command -devices and puts the list +of found optical drives into the box underneath the button. + +Scanning should be done before any ISO image manipulations because xorriso +has to give up its aquired drives in order to perform the scan run. + +To become visible and to be usable, the drives have to offer rw-permission +to the user of this program. If drives do not show up, then consider to +become superuser and to execute + xorriso -devices +Then apply + chmod a+rw +to the listed device files. (Consider to use finer means of permission +granting for a permanent solution.)" + } + if {"$what" == "Pick input drive"} { + return \ +"The \"Pick input drive\" button executes command -indev and obtains some +information about the medium status. This info is displayed in the +\"Input drive or image\" line. +Further it causes the display of the ISO image model to be updated. + +The medium in the input drive must be blank or contain a valid ISO 9660 +filesystem. +Choosing an input drive causes a root directory to be created in the ISO +model of xorriso. If there is a valid ISO filesystem in the input drive +then its directory tree gets loaded underneath that model root directory. + +The input drive may also be a data file on hard disk if that file contains +an ISO 9660 filesystem image. See field \"Input drive or image\"." + } + if {"$what" == "Pick output drive"} { + return \ +"The \"Pick output drive\" button executes command -outdev and obtains some +information about the medium status. This info is displayed in the +\"Output drive or image\" line. + +The output drive may be empty or loaded with a medium, that may be blank, +appendable or closed. +It is usable for writing only if there is a medium inserted which is either +blank or appendable. Button \"Blank\" can bring appendable or closed media +into blank state. + +The output drive may also be a data file on hard disk. See field +\"Output drive or image\"." +It is considered appendable if it contains an ISO 9660 filesystem image. +It is considered blank if it is empty or marked as blank by button \"Blank\". +It is considered closed if it contains other data." + } + if {"$what" == "Pick drive for both roles"} { + return \ +"The \"Pick drive for both roles\" button executes command -dev and obtains some +information about the medium status. This info is displayed in the +\"Input drive or image\" line and in the \"Output drive or image\" line. +Further it causes the display of the ISO image model to be updated. + +The medium in the drive must be blank or contain a valid ISO 9660 filesystem. +Else the drive will only be aquired as output drive. + +This drive configuration is the most usual one with xorriso. It loads +an eventual ISO image, allows to manipulate it by insertion, deletion, +and renaming. When this is done, the changes get written to the drive +via button \"Write ISO session\". + +The drive may also be a data file on hard disk. +See fields \"Input drive or image\" and \"Output drive or image\". +It is considered appendable if it contains an ISO 9660 filesystem image. +It is considered blank if it is empty or marked as blank by button \"Blank\". +It is considered closed if it contains other data." + } + if {"$what" == "Give up drives"} { + return \ +"The \"Give up drives\" button executes commands -indev \"\" -outdev \"\" +and clears both \"... drive or image\" lines, as well as the ISO model." + } + if {"$what" == "Calm drives"} { + return \ +"The \"Calm drives\" button executes command -calm_drives which tells the +aquired optical drives to stop spinning until the next drive activity +gets triggered." + } + if {"$what" == "Rollback"} { + return \ +"The \"Rollback\" button executes command -rollback which drops all pending +changes of the ISO model and reloads it from the input drive, if one is +aquired." + } + if {"$what" == "drivelist"} { + return \ +"The box underneath the \"Scan for drives\" button shows the optical drives +which were found by the most recent scan run. + +A double-click on a drive item has the same effect as button +\"Pick drive for both roles\". +" + } + if {"$what" == "Input drive or image"} { + return \ +"The \"Input drive or image\" field displays the address of the input drive. +Editing the drive address and pressing the Return key causes the execution +of command -indev with the field content as drive address. + +Use this to load the model from an ISO image data file on hard disk. +It is of course permissible that input image and output image are the +same file. +" + } + if {"$what" == "input drive info"} { + return \ +"The text field beneath the \"Input drive or image\" field displays the medium +status of the input drive. It tells about the writability, the medium type, +the number of ISO sessions, and the amount of readable data." + } + if {"$what" == "Eject (indev)"} { + return \ +"The \"Eject\" button beneath the \"Input drive or image\" field excutes +command -eject \"in\"." + } + if {"$what" == "Output drive or image"} { + return \ +"The \"Output drive or image\" field displays the address of the output drive. +Editing the drive address and pressing the Return key causes the execution +of command -outdev with the field content as drive address. + +Use this to direct writing to an ISO image data file on hard disk. +It is of course permissible that input image and output image are the +same file. +" + } + if {"$what" == "output drive info"} { + return \ +"The text beneath the \"Output drive or image\" field displays the medium +status of the output drive. It tells about the writability, the medium type, +the number of ISO sessions, and the amount of free space." + } + if {"$what" == "Eject (outdev)"} { + return \ +"The \"Eject\" button beneath the \"Output drive or image\" field excutes +command -eject \"out\"." + } + if {"$what" == "Blank"} { + return \ +"The \"Blank\" button executes command -blank \"as_needed\" on the output drive. + +This also applies to ISO image data files and overwritable media like DVD+RW, +which will get invalidated by a small write operation." + } + if {"$what" == "Format"} { + return \ +"The \"Format\" button executes -format \"as_needed\". + +This only applies to real optical drives and is of interest only with DVD-RW +or BD-R media, which both can be used formatted and unformatted. Other media +types which mandatorily need formatting will be formatted by the write +commands. + +Formatted DVD-RW media have the advantage of being overwritable and thus +being quickly blankable while maintaining the capability for multi-session. + +Formatted BD-R can perform Defect Management, which is of questionable value." + } + if {"$what" == "Write ISO session"} { + return \ +"The \"Write ISO session\" executes command -commit, which writes a session +with all pending changes to the output drive. + +The output drive must be either blank or it must be the same as the input +drive. + +Writing the session is the last step in the course of creating a new ISO +filesystem or an add-on session that expands or changes the ISO filesystem +on the medium of the output drive. +So first choose a drive, then insert files from hard disk or do other +manipulations, and then click \"Write ISO session\" to let xorriso +write the data to medium or ISO image file. +" + } + if {"$what" == "Close"} { + return \ +"The \"Close\" switch controls whether command -close \"on\" is emitted with +\"Write ISO session\" or whether -as cdrecord option -multi is omitted with +\"Burn image file:\". + +Closed optical media cannot be written any more unless they get blanked, +which is not possible with CD-R, DVD-R, DVD+R, and BD-R. +" + } + if {"$what" == "TAO"} { + return \ +"The \"TAO\" switch controls whether an incremental MMC write type shall be +enforced with write commands. + +Normally xorriso will decide by medium status and job parameters which +MMC write type to choose. Some drives at the edge of failure might work +with the one write type while already failing with the other." + } + if {"$what" == "Defect Mgt"} { + return \ +"The \"Defect Mgt\" switch controls whether slow and error-prone drive internal +check-reading shall be enabled when writing to formatted BD-R or BD-RE. +" + } + if {"$what" == "Burn image file:"} { + return \ +"The \"Burn image file:\" button executes command -as \"cdrecord\" to +burn a data file from hard disk onto the output drive. +The address of the disk file is taken from the neighboring text field. + +The medium in the drive may be blank or appendable." + } + if {"$what" == "Extract to disk:"} { + return \ +"The \"Extract to disk:\" button executes command -extract with the whole +tree of the current ISO directory or with the selected items of the box +underneath \"ISO directory:\". + +This copies the selected files or directory trees from the input drive +to the address on hard disk which is given by the text field right of +the button." + } + if {"$what" == "Underneath (extract)"} { + return \ +"The \"Underneath\" switch controls the effective hard disk target address +of an item if the address in the \"Extract to disk:\" field points to a +directory. + +If \"Underneath\" is enabled, then the file object from the ISO filesystem +will be copied to its name underneath the hard disk directory. +If \"Underneath\" is disabled then an ISO directory tree item will be merged +with the disk directory tree at the given address. + +Example: +Selected are \"/iso_dir\" and \"/iso_file\". +Address for hard disk is \"/tmp/from_iso\". Switch \"Selected\" is enabled. +\"Underneath\" enabled causes commands: + -extract /iso_dir /tmp/from_iso/iso_dir + -extract /iso_file /tmp/from_iso/iso_file +\"Underneath\" disabled: + -extract /iso_dir /tmp/from_iso + -extract /iso_file /tmp/from_iso +The last command will fail because /tmp/from_iso already exists as directory." + } + if {"$what" == "Selected (extract)"} { + return \ +"The \"Selected\" switch controls whether the whole current ISO directory, +or only the selected items shall be copied to hard disk. +" + } + if {"$what" == "Overwrite files"} { + return \ +"The \"Overwrite files\" switch controls whether existing files may be +overwritten in the ISO image or by extraction on hard disk. + +The frontend program will only detect the most obvious name collisions, +but xorriso will reliably refuse to overwrite files if this is banned." + } + if {"$what" == "Overwrite ISO dirs"} { + return \ +"The \"Overwrite ISO dirs\" switch controls whether it is allowed to replace +an ISO directory by a non-directory file. + +If a directory is copied to a directory, then both directory trees will +be merged. So this switch applies only to situations where non-directories +hit directories." + } + if {"$what" == "Enforce disk dir write access"} { + return \ +"The \"Enforce disk dir write access\" switch enables the options -osirrox +\"auto_chmod_on\" and \"sort_lba_on\" which influence file extraction. + +\"auto_chmod_on\" allows xorriso to give itself temporariy w-permission to +all disk directories which are owned by the xorriso user. This is not +without dangers, of course, but comes in handy with restoring of backups. + +Option \"sort_lba_on\" reduces head-moves of optical drives and thus can +speed up extraction substantially. It is bound to \"auto_chmod_on\" because +else it might get in trouble when restoring ISO directories which offer +no w-permission." + } + if {"$what" == "Refresh avail:"} { + return \ +"The \"Refresh avail:\" button triggers a time consuming exact prediction +of the free space on the medium in the output drive. For this purpose, +the size of an ISO session with the pending changes is computed. +With image files rather than real optical drives, the free space of +the hosting filesystem is displayed." + } + if {"$what" == "Insert from disk:"} { + return \ +"The \"Insert from disk:\" button executes command -map with the disk file +address that is given by the text field right to the button. + +This inserts files or directory trees into the ISO image model and +schedules them for being copied with the next \"Write ISO session\" run. + +The switches \"Underneath\" and \"Selected\" control what ISO address +the inserted files shall have. You may use buttons \"Delete\" and +\"Rename to:\" for further adjustments. +" + } + if {"$what" == "Underneath (insert)"} { + return \ +"The \"Underneath\" switch controls the effective ISO target address +if the address in the \"Insert from disk:\" field points to a hard disk +directory. + +If \"Underneath\" is enabled, a directory from disk will not be unpacked +to its single files but be put underneath the target address by its own +leaf name." + +If \"Underneath\" is disabled then the directory itself will not show up in +the ISO image but only its files and sub directories will do." + } + if {"$what" == "Selected (insert)"} { + return \ +"If the switch \"Selected\" is enabled, then the given disk file or tree will +be inserted at or underneath the only selected item in the box underneath +\"ISO directory:\"." + } + if {"$what" == "ISO directory:"} { + return \ +"The current ISO directory shall be used to navigate in the ISO image model +of xorriso. By default it is the target of file insertions and the source +of file extractions. + +The text field in the \"ISO directory:\" line displays the current ISO +directory and can be used to toggle its path directly. +Hitting the Return key causes the current directory to change and the +display in the box underneath to be refreshed. + +It is possible to choose the ISO directory by double-clicking an item +in the box underneath the \"ISO directory:\" line. +" + } + if {"$what" == "Up"} { + return \ +"The \"Up\" buttons move the current ISO directory one directory level up." + } + if {"$what" == "Verify"} { + return \ +"The \"Verify\" button executes -md5_check_r \"SORRY\" with the current ISO +directory. + +This reads the content of all data files which are underneath the current ISO +directory and which have MD5 checksums in the ISO image. +ISO images bear MD5 checksums for each data file if they were produced +by xorriso with -md5 \"on\" resp. -for_backup. This frontend enables +this feature on startup." + } + if {"$what" == "isolist"} { + return \ +"The list box underneath the \"ISO directory:\" line displays the files in +the current ISO directory. One or more item can be selected and play a +role with extraction or insertion of files. + +Most of the buttons underneath the box operate on the selected items +unconditionally." + } + if {"$what" == "ISO selection:"} { + return \ +"The ISO selection consists of the items which are selected in the list box +above the \"ISO selection:\" line. + +If the respective \"Selected\" switches are enabled, then the ISO selection +is source of file extraction and target of file insertion. + +In any case it is the old nome of the \"Rename to:\" button, the victim +of the \"Delete\" button, and the subject of the \"Verify\" button." + } + if {"$what" == "Verify (selection)"} { + return \ +"The \"Verify\" button in the \"ISO selection:\" line executes command +-md5_check_r \"SORRY\" with each of the selected items. + +This reads the content of all data files which are selected or underneath +selected directories and which have MD5 checksums in the ISO image. +ISO images bear MD5 checksums for each data file if they were produced +by xorriso with -md5 \"on\" resp. -for_backup. This frontend enables +this feature on startup." + } + if {"$what" == "Delete"} { + return \ +"The \"Delete\" button executes command -rm_r with each of the selected items. + +This removes the affected files and directory trees from the ISO model. +They will not show up in the directory tree of the next session that +is written via \"Write ISO session\". Nevertheless they will stay present +in earlier sessions if they were not freshly inserted after loading the +ISO model from the input drive. +" + } + if {"$what" == "Rename to:"} { + return \ +"The \"Rename to:\" button uses command -mv to move each of the selected +items to the address that is given by the text field right to the button. + +If this address points to an existing ISO directory, then the items will +be moved underneath that directory and keep their leaf names. +Else there may be only one selected item which will be renamed to the +given address." + } + if {"$what" == "Make dir"} { + return \ +"The \"Make dir\" button executes command -mkdir with the address in the +text field to its left (the same as used by \"Rename to:\"). + +Useful to create a target directory before moving the selection." + } + if {"$what" == "rename and mkdir target"} { + return \ +"The text field between the \"Rename to:\" button and the \"Make dir\" button +serves both buttons by providing the target address for renaming +resp. directory creation." + } + return "--- No help text found for topic '$what'" +} + + # ------- Misc helper procedures ------- @@ -3116,6 +3788,65 @@ proc central_exit {value} { exit $value } + +# Start a xorriso process which will in return launch another frontend +# process. This is necessary until i learned how to create a pair of pipes +# and to fork in Tcl. +# +proc start_xorriso {} { + global argv0 argv + + set self "" + if {[string first "/" "$argv0"] != -1} { + set self "$argv0" + } + if {"$self" == ""} { + set self "/usr/bin/xorriso-tcltk" + if {[file executable "$self"] == 0} {set self ""} + } + if {"$self" == ""} { + set self "/usr/local/bin/xorriso-tcltk" + if {[file executable "$self"] == 0} {set self ""} + } + if {"$self" == ""} { + catch { + set conn [open "|which xorriso-tcltk" r] + set self [gets $conn] + close $conn + } + } + if {"$self" == ""} { + catch { + set conn [open "|sh -c \"type -p xorriso-tcltk\"" r] + set self [gets $conn] + close $conn + } + } + if {"$self" == ""} { + puts stderr "$argv0 :\n Cannot locate address of script xorriso-tcltk in filesystem.\n" + puts stderr "You will have to use --stdio or --named_pipes." + puts stderr "See $argv0 --help\n" + central_exit 1 + } + + # eval is used to split $argv into single words + eval exec xorriso -launch_frontend "\"$self\"" --silent_start --stdio $argv -- 2>@stderr + + central_exit 0 +} + + +# Print a startup message to stderr if not the first argument is --silent_start +# +proc yell_xorriso_tcltk {} { + global argv own_version + + if {[llength "$argv"] > 0} { + if {[lindex "$argv" 0] == "--silent_start"} {return ""} + } + puts stderr "xorriso-tcltk $own_version : Proof of concept for GUI frontends of xorriso\n" +} + # -------- start living @@ -3140,6 +3871,9 @@ proc setup_by_args {argv0 argv} { print_usage "$argv0" central_exit 0 } + if {"$opt" == "--silent_start"} { + set ok "1" + } if {"$opt" == "--stdio"} { set ok "1" set connection_defined 1 @@ -3161,6 +3895,7 @@ proc setup_by_args {argv0 argv} { # Just in case -geometry does not get eaten by wish incr i set main_window_geometry [lrange "$argv" "$i" "$i"] + set give_geometry [lrange "$argv" "$i" "$i"] } if {"$opt" == "--click_to_focus"} { set ok "1" @@ -3194,9 +3929,7 @@ proc setup_by_args {argv0 argv} { } if {"$connection_defined" == 0} { - puts stderr "$argv0 : Either --stdio or --named_pipes must be given for a program run.\n" - print_usage "$argv0" - central_exit 1 + start_xorriso } if {"$cmd_pipe_adr" == "" || "$reply_pipe_adr" == "" || @@ -3209,8 +3942,7 @@ proc setup_by_args {argv0 argv} { } } - -puts stderr "xorriso-tcltk $own_version : Proof of concept for GUI frontends\n" +yell_xorriso_tcltk setup_by_args "$argv0" "$argv" check_xorriso_version