1# nb.rb -- translation of nb.scm 2 3# Translator/Author: Michael Scholz <mi-scholz@users.sourceforge.net> 4# Created: 02/12/10 22:08:15 5# Changed: 14/11/13 03:02:23 6 7# Tested with Snd 15.x, Ruby 2.x.x 8# 9# type nb = make_nb 10# nb.help 11# or xnb = make_nb_motif (installs a popup menu on info widget) 12# 13# global variable: 14# $nb_database 15# 16# make_nb(path) 17# 18# class NB 19# initialize(path) 20# 21# getter and setter: 22# name=(filename) 23# name 24# notes=(new_notes) 25# notes 26# 27# interactive methods: 28# unb 29# prune_db 30# open(path) 31# close 32# help (alias info and description) 33# 34=begin 35nb = make_nb 36nb.name 37nb.notes 38nb.notes = "new text" 39nb.prune_db # deletes empty entries 40nb.unb # deletes entry of current file 41nb.open # adds mouse hooks 42nb.close # removes mouse hooks 43nb.help # this help 44=end 45 46require "hooks" 47with_silence do 48 unless defined? DBM.open 49 require "dbm" 50 end 51end 52 53$nb_database = "nb" unless defined? $nb_database 54 55if provided?("snd-motif") and (not provided?("xm")) 56 with_silence(LoadError) do 57 require "libxm" 58 end 59end 60 61module Kernel 62 # XM_NB should only create one instance of the popup menu on the 63 # info_widget. 64 @@XM_NB = false 65 66 def Kernel.xm_nb 67 @@XM_NB 68 end 69 70 def Kernel.xm_nb=(val) 71 @@XM_NB = val 72 end 73end 74 75def make_nb(path = $nb_database) 76 NB.new(path) 77end 78 79def make_nb_motif(path = $nb_database) 80 if Kernel.xm_nb.kind_of?(XM_NB) 81 Kernel.xm_nb.open(path) 82 else 83 Kernel.xm_nb = XM_NB.new(path) 84 end 85end if provided?("xm") 86 87class NB 88 include Info 89 90 Region_viewer = 2 91 View_files_dialog = 8 92 Info_dialog = 20 93 94 def initialize(path) 95 @nb_database = path 96 @type = nil 97 @position = nil 98 @name = nil 99 @notes = "" 100 @alert_color = make_color(1.0, 1.0, 0.94) 101 @db_hook_name = format("%s-nb-hook", @nb_database) 102 set_help 103 create 104 end 105 attr_reader :name, :notes 106 alias help description 107 108 def inspect 109 format("#<%s: nb_database: %s, open: %s, name: %s>", 110 self.class, 111 @nb_database.inspect, 112 $mouse_enter_label_hook.member?(@db_hook_name).inspect, 113 @name.inspect) 114 end 115 116 def name=(filename) 117 if filename and File.exist?(File.expand_path(filename)) 118 @name = filename 119 show_popup_info 120 else 121 Snd.warning("no such file: %s", filename.inspect) 122 end 123 end 124 125 def notes=(new_notes) 126 @notes = new_notes 127 nb 128 @notes 129 end 130 131 def with_dbm(&body) 132 ret = nil 133 db = DBM.open(@nb_database) 134 ret = body.call(db) 135 db.close 136 ret 137 rescue 138 Snd.warning("%s#%s", self.class, get_func_name) 139 end 140 141 def prune_db 142 with_dbm do |db| 143 db.delete_if do |k, v| k.empty? end 144 end 145 self 146 end 147 148 def open(path = @nb_database) 149 @nb_database = path 150 create 151 self 152 end 153 154 def close 155 $mouse_enter_label_hook.remove_hook!(@db_hook_name) 156 $mouse_leave_label_hook.remove_hook!(@db_hook_name) 157 self 158 end 159 160 def unb 161 if @name and File.exist?(File.expand_path(@name)) 162 with_dbm do |db| 163 db.delete(@name) 164 end 165 show_popup_info 166 else 167 Snd.warning("no such file: %s", @name.inspect) 168 end 169 end 170 171 private 172 def create 173 close 174 $mouse_enter_label_hook.add_hook!(@db_hook_name) do |t, p, n| 175 files_popup_info(t, p, n) unless t == Region_viewer 176 end 177 end 178 179 def nb 180 if @name and File.exist?(File.expand_path(@name)) 181 with_dbm do |db| 182 db[@name] = @notes 183 end 184 show_popup_info 185 else 186 Snd.warning("no such file: %s", @name.inspect) 187 end 188 end 189 190 def files_popup_info(type, position, name) 191 @type = type 192 @position = position 193 @name = name 194 show_popup_info 195 end 196 197 def show_popup_info 198 let(dialog_widgets[Info_dialog]) do |info_exists_p| 199 info_dialog(@name, file_info) 200 if info_widget = dialog_widgets[Info_dialog] 201 unless info_exists_p 202 width, height = widget_size(dialog_widgets[View_files_dialog]) 203 set_widget_position(info_widget, [width + 10, 10]) 204 end 205 end 206 end 207 @name 208 end 209 210 def file_info 211 with_dbm do |db| 212 @notes = (db[@name] or "") 213 end 214 cs = mus_sound_chans(@name) 215 sr = mus_sound_srate(@name) 216 len = format("%1.3f", mus_sound_samples(@name).to_f / (cs * sr.to_f)) 217 d_format = mus_sample_type_name(mus_sound_sample_type(@name)) 218 h_type = mus_header_type_name(mus_sound_header_type(@name)) 219 frms = mus_sound_framples(@name) 220 max_amp = "" 221 if mus_sound_maxamp_exists?(@name) 222 str = "" 223 mus_sound_maxamp(@name).each_pair do |s, v| 224 str << format("%1.3f (%1.3fs), ", v, s / sr.to_f) 225 end 226 max_amp = format("\n maxamp: [%s]", str[0..-3]) 227 end 228 fdate = Time.at(mus_sound_write_date(@name)) 229 date = fdate.localtime.strftime("%a %d-%b-%y %H:%M %z") 230 info_string = format("\ 231 chans: %d, srate: %d 232 length: %1.3f (%d frms) 233 format: %s [%s]%s 234written: %s\n", cs, sr, len, frms, d_format, h_type, max_amp, date) 235 if defined?($info_comment_hook) and hook?($info_comment_hook) 236 if $info_comment_hook.empty? 237 if s = mus_sound_comment(@name) 238 info_string += format("comment: %s\n", s) 239 end 240 else 241 $info_comment_hook.run_hook do |prc| 242 info_string = prc.call(@name, info_string) 243 end 244 end 245 else 246 if s = mus_sound_comment(@name) 247 info_string += format("comment: %s\n", s) 248 end 249 end 250 info_string += "\n" + @notes 251 end 252 253 def set_help 254 self.description = "\ 255# global variable: 256# $nb_database (#{$nb_database}) 257# 258# make_nb(path) 259# make_nb_motif(path) 260# 261# class NB 262# initialize(path) 263# 264# getter and setter: 265# name=(filename) 266# name 267# notes=(new_notes) 268# notes 269# 270# interactive methods: 271# unb 272# prune_db 273# open(path) 274# close 275# help (alias info and description) 276 277nb = make_nb 278nb.name 279nb.notes 280nb.notes = \"new text\" 281nb.prune_db # deletes empty entries 282nb.unb # deletes entry of current file 283nb.open # adds mouse hooks 284nb.close # removes mouse hooks 285nb.help # this help 286" 287 end 288end 289 290class XM_NB < NB 291 require "popup" 292 293 def initialize(path) 294 @dialog = nil 295 @file_name = nil 296 @text_widget = nil 297 @message_widget = nil 298 super 299 @db_str = format("DB: %s", File.basename(@nb_database)) 300 @popup_nb_hook = Hook.new("@popup_nb_hook", 2, "\ 301lambda do |snd, info| ... \"new info\" end: called in popup.rb on 302graph-popup-menu entry `Info'. Its primary use is to communicate 303between popup.rb and nb.rb. To add your own information to the info 304string, you may use $info_comment_hook. 305 306The current selected SND is called with string INFO. If more than one 307hook procedures exists, each procedure's result is passed as input to 308the next. E.g. if an instance of NB or XM_NB is created (see nb.rb), 309the $nb_database entries of SND will be returned.") 310 @popup_nb_hook.add_hook!("initialize-nb-hook") do |snd, info| 311 @name = file_name(snd) 312 with_dbm do |db| 313 @notes = (db[@name] or "") 314 end 315 unless @notes.empty? 316 info += "\n" unless info.empty? 317 info += @notes 318 end 319 info 320 end 321 install_menu 322 end 323 attr_reader :popup_nb_hook 324 325 def close 326 if @dialog.kind_of?(Dialog) and 327 RWidget?(@dialog.dialog) and 328 RXtIsManaged(@dialog.dialog) 329 RXtUnmanageChild(@dialog.dialog) 330 end 331 super 332 end 333 334 protected 335 def post_edit 336 if !@name and RWidget?(@message_widget) 337 @name = if File.exist?(file = current_label(@message_widget).split[0]) 338 file 339 else 340 format("no such file: %s", file.inspect) 341 end 342 end 343 unless @dialog.kind_of?(Dialog) and RWidget?(@dialog.dialog) 344 @dialog = make_dialog(@db_str, 345 :help_cb, lambda do |w, c, i| 346 help_cb 347 end, :clear_cb, lambda do |w, c, i| 348 RXmTextSetString(@text_widget, "") 349 end) do |w, c, i| 350 self.notes = RXmTextGetString(@text_widget) 351 end 352 @file_name = @dialog.add_label(@name) 353 @text_widget = @dialog.add_text(:rows, 16, :columns, 60, 354 :wordwrap, true, :value, @notes) 355 @dialog.doit_string("Submit") 356 end 357 activate_dialog(@dialog.dialog) 358 show_edit_info 359 end 360 361 def help_cb 362 help_dialog(@db_str, 363 "Edit info DB of sound files (see nb.scm). 364 365Provides pop-up help in the Files viewer. \ 366If you have `dbm', any data associated with \ 367the file in the dbm database will also be posted. \ 368The database name is defined by $nb_database \ 369(#{$nb_database.inspect}). 370 371o Edit info: opens the edit widget 372 373o Prune DB: clears non-existent file references 374 out of the database 375 376o Clear: removes info entry from current file 377 378o Close: removes mouse hooks and popup menu; 379 type `make_nb_motif' to reinstall 380 the hooks and popup menu 381 382o Submit: submits info from edit widget 383 to file info database 384 385#{self.description}", 386 ["{Libxm}: graphics module", 387 "{Ruby}: extension language", 388 "{Motif}: Motif extensions via libxm"]) 389 end 390 391 def post_popup? 392 $mouse_enter_label_hook.member?(@db_hook_name) and 393 File.exist?(current_label(@message_widget).split[0]) 394 end 395 396 private 397 def create 398 @db_hook_name = format("%s-xm-nb-hook", @nb_database) 399 super 400 end 401 402 def install_menu 403 if RWidget?(wid = dialog_widgets[Info_dialog]) 404 setup_menu(wid) 405 else 406 $new_widget_hook.add_hook!("nb-edit-hook") do |w| 407 if w == dialog_widgets[Info_dialog] 408 setup_menu(w) 409 $new_widget_hook.remove_hook!("nb-edit-hook") 410 end 411 end 412 end 413 end 414 415 def setup_menu(wid) 416 @message_widget = find_child(wid, "Message") 417 make_snd_popup("NB Edit Info", 418 :where, :event, 419 :parent, find_child(wid, "post-it-text")) do 420 entry("Edit Info") do |w, snd, chn| Kernel.xm_nb.post_edit end 421 entry("Prune DB") do |w, snd, chn| Kernel.xm_nb.prune_db end 422 entry("Clear current Info") do |w, snd, chn| Kernel.xm_nb.unb end 423 entry("Close NB Edit") do |w, snd, chn| Kernel.xm_nb.close end 424 separator 425 entry("Help") do |w, snd, chn| Kernel.xm_nb.help_cb end 426 before_popup_hook.add_hook!("NB Edit Info") do |d1, d2, d3| 427 Kernel.xm_nb.post_popup? 428 end 429 end 430 end 431 432 def files_popup_info(type, position, name) 433 super 434 show_edit_info 435 end 436 437 def show_edit_info 438 xfname = string2compound(@name) 439 if RWidget?(@file_name) 440 RXtVaSetValues(@file_name, [RXmNlabelString, xfname]) 441 end 442 if RWidget?(@text_widget) 443 RXtVaSetValues(@text_widget, [RXmNvalue, @notes]) 444 end 445 RXmStringFree(xfname) 446 end 447end if provided?("xm") 448 449# nb.rb ends here 450