aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE.txt676
-rwxr-xr-xMakefile.in513
-rw-r--r--README.txt122
-rw-r--r--bin/linux/libsndfile.abin0 -> 1458218 bytes
-rwxr-xr-xbin/linux/libsndfile.sobin0 -> 1008269 bytes
-rwxr-xr-xbin/linux/libsndfile.so.1bin0 -> 1008269 bytes
-rwxr-xr-xbin/linux/libsndfile.so.1.0.17bin0 -> 1008269 bytes
-rwxr-xr-xbin/ppc_10.3/libsndfile.1.0.16.dylibbin0 -> 1108848 bytes
-rwxr-xr-xbin/ppc_10.3/libsndfile.1.dylibbin0 -> 1108848 bytes
-rwxr-xr-xbin/ppc_10.3/libsndfile.dylibbin0 -> 1108848 bytes
-rw-r--r--bin/ppc_10.4/libportaudio.abin0 -> 97728 bytes
-rw-r--r--bin/ppc_10.4/libportaudio.dylibbin0 -> 174848 bytes
-rw-r--r--bin/ppc_10.4/libportaudio.dylib.0.0.18bin0 -> 105132 bytes
-rwxr-xr-xbin/ppc_10.4/libsndfile.1.dylib.gzbin0 -> 628026 bytes
-rwxr-xr-xbin/win32/libsndfile-1.dllbin0 -> 1235390 bytes
-rwxr-xr-xconfigure120
-rw-r--r--configure.in41
-rw-r--r--doc/ADATFS.txt529
-rw-r--r--doc/COMPILING.txt39
-rw-r--r--doc/DEVELOPING.txt270
-rw-r--r--doc/HARDWARE.txt34
-rw-r--r--doc/LIVERECOVERY.txt25
-rw-r--r--doc/MAILING.txt28
-rw-r--r--doc/RELEASE.txt474
-rw-r--r--doc/SYXformat.txt22
-rw-r--r--doc/TESTPLAN.txt130
-rw-r--r--doc/artwork/DMG_Background.pngbin0 -> 101824 bytes
-rw-r--r--doc/artwork/DMG_Background.psdbin0 -> 521073 bytes
-rw-r--r--doc/artwork/HD24Connect.icnsbin0 -> 122133 bytes
-rw-r--r--doc/artwork/HD24_vipower.jpgbin0 -> 118233 bytes
-rw-r--r--doc/artwork/Icon.psdbin0 -> 263021 bytes
-rw-r--r--doc/artwork/hd24connect.jpgbin0 -> 17791 bytes
-rw-r--r--doc/artwork/hd24display.pngbin0 -> 84562 bytes
-rw-r--r--doc/artwork/hd24pc.jpgbin0 -> 72433 bytes
-rw-r--r--doc/hd24tools_manual.odtbin0 -> 1243066 bytes
-rw-r--r--doc/hd24tools_manual.pdfbin0 -> 2167182 bytes
-rw-r--r--images/longliverec.h24bin0 -> 986112 bytes
-rw-r--r--images/unquickformat.h24bin0 -> 10752 bytes
-rw-r--r--scripts/backupscript.txt5174
-rwxr-xr-xscripts/decodemtc127
-rwxr-xr-xscripts/encode_smpte.pl181
-rwxr-xr-xscripts/genbackupscript.pl98
-rwxr-xr-xscripts/hd24arm12
-rwxr-xr-xscripts/hd24arm1-162
-rwxr-xr-xscripts/hd24arm1-242
-rwxr-xr-xscripts/hd24arm22
-rwxr-xr-xscripts/hd24getinfo2
-rwxr-xr-xscripts/hd24idreq3
-rwxr-xr-xscripts/hd24mute12
-rwxr-xr-xscripts/hd24play3
-rwxr-xr-xscripts/hd24stop3
-rwxr-xr-xscripts/hd24unarmall2
-rw-r--r--scripts/midi.c40
-rwxr-xr-xscripts/mtcspeak34
-rwxr-xr-xscripts/off2sec.pl19
-rwxr-xr-xscripts/sec2off.pl17
-rwxr-xr-xscripts/showstoppedmtc33
-rwxr-xr-xscripts/sl2o.pl23
-rw-r--r--src/frontend/WidgetPDial.fl131
-rwxr-xr-xsrc/frontend/dialog_choosedevice.fl99
-rwxr-xr-xsrc/frontend/dialog_filesize.fl131
-rwxr-xr-xsrc/frontend/dialog_fromto.fl50
-rwxr-xr-xsrc/frontend/dialog_newproject.fl86
-rwxr-xr-xsrc/frontend/dialog_newsong.fl352
-rwxr-xr-xsrc/frontend/dialog_options.fl131
-rwxr-xr-xsrc/frontend/dialog_rate.fl58
-rwxr-xr-xsrc/frontend/dialog_rename.fl89
-rwxr-xr-xsrc/frontend/dialog_setlength.fl204
-rwxr-xr-xsrc/frontend/dialog_setlocate.fl209
-rwxr-xr-xsrc/frontend/hd24connect.cpp326
-rw-r--r--src/frontend/hd24connect.icobin0 -> 4286 bytes
-rw-r--r--src/frontend/images/7seg_0.gifbin0 -> 1154 bytes
-rw-r--r--src/frontend/images/7seg_1.gifbin0 -> 610 bytes
-rw-r--r--src/frontend/images/7seg_2.gifbin0 -> 1090 bytes
-rw-r--r--src/frontend/images/7seg_3.gifbin0 -> 1102 bytes
-rw-r--r--src/frontend/images/7seg_4.gifbin0 -> 687 bytes
-rw-r--r--src/frontend/images/7seg_5.gifbin0 -> 694 bytes
-rw-r--r--src/frontend/images/7seg_6.gifbin0 -> 1120 bytes
-rw-r--r--src/frontend/images/7seg_7.gifbin0 -> 633 bytes
-rw-r--r--src/frontend/images/7seg_8.gifbin0 -> 1162 bytes
-rw-r--r--src/frontend/images/7seg_9.gifbin0 -> 1107 bytes
-rw-r--r--src/frontend/images/HD24_matrix.gifbin0 -> 4205 bytes
-rw-r--r--src/frontend/images/HD24_matrix_100.gifbin0 -> 175 bytes
-rw-r--r--src/frontend/images/HD24_matrix_101.gifbin0 -> 143 bytes
-rw-r--r--src/frontend/images/HD24_matrix_102.gifbin0 -> 163 bytes
-rw-r--r--src/frontend/images/HD24_matrix_103.gifbin0 -> 164 bytes
-rw-r--r--src/frontend/images/HD24_matrix_104.gifbin0 -> 170 bytes
-rw-r--r--src/frontend/images/HD24_matrix_105.gifbin0 -> 101 bytes
-rw-r--r--src/frontend/images/HD24_matrix_106.gifbin0 -> 127 bytes
-rw-r--r--src/frontend/images/HD24_matrix_107.gifbin0 -> 138 bytes
-rw-r--r--src/frontend/images/HD24_matrix_108.gifbin0 -> 128 bytes
-rw-r--r--src/frontend/images/HD24_matrix_109.gifbin0 -> 141 bytes
-rw-r--r--src/frontend/images/HD24_matrix_110.gifbin0 -> 136 bytes
-rw-r--r--src/frontend/images/HD24_matrix_111.gifbin0 -> 166 bytes
-rw-r--r--src/frontend/images/HD24_matrix_112.gifbin0 -> 163 bytes
-rw-r--r--src/frontend/images/HD24_matrix_113.gifbin0 -> 160 bytes
-rw-r--r--src/frontend/images/HD24_matrix_114.gifbin0 -> 157 bytes
-rw-r--r--src/frontend/images/HD24_matrix_115.gifbin0 -> 160 bytes
-rw-r--r--src/frontend/images/HD24_matrix_116.gifbin0 -> 138 bytes
-rw-r--r--src/frontend/images/HD24_matrix_117.gifbin0 -> 136 bytes
-rw-r--r--src/frontend/images/HD24_matrix_118.gifbin0 -> 125 bytes
-rw-r--r--src/frontend/images/HD24_matrix_119.gifbin0 -> 137 bytes
-rw-r--r--src/frontend/images/HD24_matrix_120.gifbin0 -> 128 bytes
-rw-r--r--src/frontend/images/HD24_matrix_121.gifbin0 -> 160 bytes
-rw-r--r--src/frontend/images/HD24_matrix_122.gifbin0 -> 163 bytes
-rw-r--r--src/frontend/images/HD24_matrix_123.gifbin0 -> 173 bytes
-rw-r--r--src/frontend/images/HD24_matrix_124.gifbin0 -> 173 bytes
-rw-r--r--src/frontend/images/HD24_matrix_125.gifbin0 -> 173 bytes
-rw-r--r--src/frontend/images/HD24_matrix_126.gifbin0 -> 173 bytes
-rw-r--r--src/frontend/images/HD24_matrix_127.gifbin0 -> 173 bytes
-rw-r--r--src/frontend/images/HD24_matrix_32.gifbin0 -> 129 bytes
-rw-r--r--src/frontend/images/HD24_matrix_33.gifbin0 -> 119 bytes
-rw-r--r--src/frontend/images/HD24_matrix_34.gifbin0 -> 106 bytes
-rw-r--r--src/frontend/images/HD24_matrix_35.gifbin0 -> 172 bytes
-rw-r--r--src/frontend/images/HD24_matrix_36.gifbin0 -> 172 bytes
-rw-r--r--src/frontend/images/HD24_matrix_37.gifbin0 -> 134 bytes
-rw-r--r--src/frontend/images/HD24_matrix_38.gifbin0 -> 140 bytes
-rw-r--r--src/frontend/images/HD24_matrix_39.gifbin0 -> 113 bytes
-rw-r--r--src/frontend/images/HD24_matrix_40.gifbin0 -> 104 bytes
-rw-r--r--src/frontend/images/HD24_matrix_41.gifbin0 -> 79 bytes
-rw-r--r--src/frontend/images/HD24_matrix_42.gifbin0 -> 125 bytes
-rw-r--r--src/frontend/images/HD24_matrix_43.gifbin0 -> 123 bytes
-rw-r--r--src/frontend/images/HD24_matrix_44.gifbin0 -> 113 bytes
-rw-r--r--src/frontend/images/HD24_matrix_45.gifbin0 -> 117 bytes
-rw-r--r--src/frontend/images/HD24_matrix_46.gifbin0 -> 140 bytes
-rw-r--r--src/frontend/images/HD24_matrix_47.gifbin0 -> 117 bytes
-rw-r--r--src/frontend/images/HD24_matrix_48.gifbin0 -> 154 bytes
-rw-r--r--src/frontend/images/HD24_matrix_49.gifbin0 -> 128 bytes
-rw-r--r--src/frontend/images/HD24_matrix_50.gifbin0 -> 172 bytes
-rw-r--r--src/frontend/images/HD24_matrix_51.gifbin0 -> 172 bytes
-rw-r--r--src/frontend/images/HD24_matrix_52.gifbin0 -> 170 bytes
-rw-r--r--src/frontend/images/HD24_matrix_53.gifbin0 -> 171 bytes
-rw-r--r--src/frontend/images/HD24_matrix_54.gifbin0 -> 168 bytes
-rw-r--r--src/frontend/images/HD24_matrix_55.gifbin0 -> 163 bytes
-rw-r--r--src/frontend/images/HD24_matrix_56.gifbin0 -> 175 bytes
-rw-r--r--src/frontend/images/HD24_matrix_57.gifbin0 -> 168 bytes
-rw-r--r--src/frontend/images/HD24_matrix_58.gifbin0 -> 124 bytes
-rw-r--r--src/frontend/images/HD24_matrix_59.gifbin0 -> 122 bytes
-rw-r--r--src/frontend/images/HD24_matrix_60.gifbin0 -> 126 bytes
-rw-r--r--src/frontend/images/HD24_matrix_61.gifbin0 -> 131 bytes
-rw-r--r--src/frontend/images/HD24_matrix_62.gifbin0 -> 124 bytes
-rw-r--r--src/frontend/images/HD24_matrix_63.gifbin0 -> 131 bytes
-rw-r--r--src/frontend/images/HD24_matrix_64.gifbin0 -> 173 bytes
-rw-r--r--src/frontend/images/HD24_matrix_65.gifbin0 -> 177 bytes
-rw-r--r--src/frontend/images/HD24_matrix_66.gifbin0 -> 177 bytes
-rw-r--r--src/frontend/images/HD24_matrix_67.gifbin0 -> 167 bytes
-rw-r--r--src/frontend/images/HD24_matrix_68.gifbin0 -> 175 bytes
-rw-r--r--src/frontend/images/HD24_matrix_69.gifbin0 -> 176 bytes
-rw-r--r--src/frontend/images/HD24_matrix_70.gifbin0 -> 169 bytes
-rw-r--r--src/frontend/images/HD24_matrix_71.gifbin0 -> 176 bytes
-rw-r--r--src/frontend/images/HD24_matrix_72.gifbin0 -> 171 bytes
-rw-r--r--src/frontend/images/HD24_matrix_73.gifbin0 -> 166 bytes
-rw-r--r--src/frontend/images/HD24_matrix_74.gifbin0 -> 163 bytes
-rw-r--r--src/frontend/images/HD24_matrix_75.gifbin0 -> 170 bytes
-rw-r--r--src/frontend/images/HD24_matrix_76.gifbin0 -> 162 bytes
-rw-r--r--src/frontend/images/HD24_matrix_77.gifbin0 -> 171 bytes
-rw-r--r--src/frontend/images/HD24_matrix_78.gifbin0 -> 172 bytes
-rw-r--r--src/frontend/images/HD24_matrix_79.gifbin0 -> 175 bytes
-rw-r--r--src/frontend/images/HD24_matrix_80.gifbin0 -> 170 bytes
-rw-r--r--src/frontend/images/HD24_matrix_81.gifbin0 -> 178 bytes
-rw-r--r--src/frontend/images/HD24_matrix_82.gifbin0 -> 177 bytes
-rw-r--r--src/frontend/images/HD24_matrix_83.gifbin0 -> 168 bytes
-rw-r--r--src/frontend/images/HD24_matrix_84.gifbin0 -> 159 bytes
-rw-r--r--src/frontend/images/HD24_matrix_85.gifbin0 -> 172 bytes
-rw-r--r--src/frontend/images/HD24_matrix_86.gifbin0 -> 164 bytes
-rw-r--r--src/frontend/images/HD24_matrix_87.gifbin0 -> 171 bytes
-rw-r--r--src/frontend/images/HD24_matrix_88.gifbin0 -> 169 bytes
-rw-r--r--src/frontend/images/HD24_matrix_89.gifbin0 -> 140 bytes
-rw-r--r--src/frontend/images/HD24_matrix_90.gifbin0 -> 169 bytes
-rw-r--r--src/frontend/images/HD24_matrix_91.gifbin0 -> 173 bytes
-rw-r--r--src/frontend/images/HD24_matrix_92.gifbin0 -> 173 bytes
-rw-r--r--src/frontend/images/HD24_matrix_93.gifbin0 -> 173 bytes
-rw-r--r--src/frontend/images/HD24_matrix_94.gifbin0 -> 173 bytes
-rw-r--r--src/frontend/images/HD24_matrix_95.gifbin0 -> 173 bytes
-rw-r--r--src/frontend/images/HD24_matrix_96.gifbin0 -> 173 bytes
-rw-r--r--src/frontend/images/HD24_matrix_97.gifbin0 -> 164 bytes
-rw-r--r--src/frontend/images/HD24_matrix_98.gifbin0 -> 173 bytes
-rw-r--r--src/frontend/images/HD24_matrix_99.gifbin0 -> 158 bytes
-rw-r--r--src/frontend/images/HD24_matrix_arrowleft.gifbin0 -> 152 bytes
-rw-r--r--src/frontend/images/HD24_matrix_arrowright.gifbin0 -> 149 bytes
-rw-r--r--src/frontend/images/HD24_matrix_realsize.gifbin0 -> 173 bytes
-rw-r--r--src/frontend/images/HD24_matrix_writeenabled.gifbin0 -> 176 bytes
-rw-r--r--src/frontend/images/HD24_matrix_writeprotected.gifbin0 -> 177 bytes
-rw-r--r--src/frontend/images/aqua.bmpbin0 -> 2559154 bytes
-rw-r--r--src/frontend/images/aqua.rarbin0 -> 44464 bytes
-rw-r--r--src/frontend/images/aquabutton_down.gifbin0 -> 1898 bytes
-rw-r--r--src/frontend/images/aquabutton_up.gifbin0 -> 1306 bytes
-rw-r--r--src/frontend/images/button.gifbin0 -> 3290 bytes
-rw-r--r--src/frontend/images/button.xcfbin0 -> 23360 bytes
-rw-r--r--src/frontend/images/button_ffwd.gifbin0 -> 2380 bytes
-rw-r--r--src/frontend/images/button_ffwd_dn.gifbin0 -> 2284 bytes
-rw-r--r--src/frontend/images/button_lrc.gifbin0 -> 1786 bytes
-rw-r--r--src/frontend/images/button_lrc_dn.gifbin0 -> 1708 bytes
-rw-r--r--src/frontend/images/button_lrc_led.gifbin0 -> 1807 bytes
-rw-r--r--src/frontend/images/button_lrc_led_dn.gifbin0 -> 1781 bytes
-rw-r--r--src/frontend/images/button_lrc_led_on.gifbin0 -> 1833 bytes
-rw-r--r--src/frontend/images/button_lrc_led_on_dn.gifbin0 -> 1765 bytes
-rw-r--r--src/frontend/images/button_mute.gifbin0 -> 1114 bytes
-rw-r--r--src/frontend/images/button_mute_dn.gifbin0 -> 1139 bytes
-rw-r--r--src/frontend/images/button_play.gifbin0 -> 2321 bytes
-rw-r--r--src/frontend/images/button_play_dn.gifbin0 -> 2231 bytes
-rw-r--r--src/frontend/images/button_rec.gifbin0 -> 2159 bytes
-rw-r--r--src/frontend/images/button_rec_dn.gifbin0 -> 2174 bytes
-rw-r--r--src/frontend/images/button_rew.gifbin0 -> 2331 bytes
-rw-r--r--src/frontend/images/button_rew_dn.gifbin0 -> 2214 bytes
-rw-r--r--src/frontend/images/button_small.gifbin0 -> 1145 bytes
-rw-r--r--src/frontend/images/button_small_dn.gifbin0 -> 1151 bytes
-rw-r--r--src/frontend/images/button_solo.gifbin0 -> 1089 bytes
-rw-r--r--src/frontend/images/button_solo_dn.gifbin0 -> 1139 bytes
-rw-r--r--src/frontend/images/button_stop.gifbin0 -> 2434 bytes
-rw-r--r--src/frontend/images/button_stop_dn.gifbin0 -> 2252 bytes
-rw-r--r--src/frontend/images/button_stop_uplit.gifbin0 -> 2321 bytes
-rw-r--r--src/frontend/images/ch21.gifbin0 -> 2870 bytes
-rw-r--r--src/frontend/images/ch21.pngbin0 -> 92167 bytes
-rw-r--r--src/frontend/images/down.gifbin0 -> 344 bytes
-rw-r--r--src/frontend/images/fader.gifbin0 -> 1312 bytes
-rwxr-xr-xsrc/frontend/images/ffwd.gifbin0 -> 396 bytes
-rwxr-xr-xsrc/frontend/images/hd24connect.pngbin0 -> 31182 bytes
-rw-r--r--src/frontend/images/hd24connect.xpm38
-rw-r--r--src/frontend/images/hd24connect_64x64.xpm355
-rw-r--r--src/frontend/images/led1.gifbin0 -> 524 bytes
-rw-r--r--src/frontend/images/led10.gifbin0 -> 323 bytes
-rw-r--r--src/frontend/images/led2.gifbin0 -> 523 bytes
-rw-r--r--src/frontend/images/led3.gifbin0 -> 523 bytes
-rw-r--r--src/frontend/images/led4.gifbin0 -> 522 bytes
-rw-r--r--src/frontend/images/led5.gifbin0 -> 525 bytes
-rw-r--r--src/frontend/images/led6.gifbin0 -> 524 bytes
-rw-r--r--src/frontend/images/led7.gifbin0 -> 525 bytes
-rw-r--r--src/frontend/images/led8.gifbin0 -> 531 bytes
-rw-r--r--src/frontend/images/led9.gifbin0 -> 526 bytes
-rw-r--r--src/frontend/images/leds_3.gifbin0 -> 1272 bytes
-rw-r--r--src/frontend/images/leds_32.gifbin0 -> 1272 bytes
-rwxr-xr-xsrc/frontend/images/loop.gifbin0 -> 619 bytes
-rwxr-xr-xsrc/frontend/images/nextcue.gifbin0 -> 591 bytes
-rwxr-xr-xsrc/frontend/images/play.gifbin0 -> 322 bytes
-rwxr-xr-xsrc/frontend/images/prevcue.gifbin0 -> 606 bytes
-rwxr-xr-xsrc/frontend/images/rec.gifbin0 -> 1035 bytes
-rwxr-xr-xsrc/frontend/images/rew.gifbin0 -> 400 bytes
-rwxr-xr-xsrc/frontend/images/rewindtozero.gifbin0 -> 685 bytes
-rwxr-xr-xsrc/frontend/images/stop.gifbin0 -> 363 bytes
-rw-r--r--src/frontend/images/up.gifbin0 -> 343 bytes
-rwxr-xr-xsrc/frontend/images/wave.gifbin0 -> 301 bytes
-rw-r--r--src/frontend/images/xpbutton_dn.gifbin0 -> 1336 bytes
-rw-r--r--src/frontend/images/xpbutton_up.gifbin0 -> 921 bytes
-rw-r--r--src/frontend/images/xpbutton_uplit.gifbin0 -> 921 bytes
-rw-r--r--src/frontend/resource.rc2
-rw-r--r--src/frontend/selftest.cpp646
-rwxr-xr-xsrc/frontend/ui_hd24connect.fl4597
-rw-r--r--src/frontend/ui_hd24connect.txt387
-rw-r--r--src/frontend/ui_hd24trackchannel.fl322
-rwxr-xr-xsrc/frontend/ui_help_about.fl68
-rw-r--r--src/frontend/ui_mixer.fl2225
-rw-r--r--src/frontend/ui_recorder.fl3639
-rwxr-xr-xsrc/hd24hexview.cpp923
-rwxr-xr-xsrc/hd24info.cpp111
-rw-r--r--src/hd24syx2bin.cpp113
-rwxr-xr-xsrc/hd24towav.cpp233
-rwxr-xr-xsrc/hd24wavefix.cpp207
-rw-r--r--src/installer/PkgInfo.hd24connect2
-rw-r--r--src/installer/PkgInfo.setup2
-rw-r--r--src/installer/bin2c.c72
-rw-r--r--src/installer/hd24connect_icon.pngbin0 -> 6895 bytes
-rw-r--r--src/installer/icon.icnsbin0 -> 39662 bytes
-rw-r--r--src/installer/info.plist.hd24connect23
-rw-r--r--src/installer/info.plist.setup23
-rwxr-xr-xsrc/installer/setup.cpp353
-rw-r--r--src/installer/setupapi.cpp473
-rwxr-xr-xsrc/installer/starthd24connect.command5
-rw-r--r--src/installer/ui_askpasswd.fl78
-rw-r--r--src/installer/ui_instdir.fl105
-rw-r--r--src/installer/ui_license.fl80
-rw-r--r--src/installer/ui_ready.fl49
-rw-r--r--src/installer/ui_welcome.fl66
-rw-r--r--src/installer/welcome.pngbin0 -> 81217 bytes
-rw-r--r--src/lib/FL/FLTKstuff.H6
-rw-r--r--src/lib/FL/Fl_Image_Button.H20
-rw-r--r--src/lib/FL/Fl_Image_Button.cxx110
-rw-r--r--src/lib/FL/Fl_Image_Repeat_Button.H20
-rw-r--r--src/lib/FL/Fl_Image_Repeat_Button.cxx86
-rw-r--r--src/lib/FL/Fl_Image_Toggle_Button.H20
-rw-r--r--src/lib/FL/Fl_Image_Toggle_Button.cxx92
-rw-r--r--src/lib/FL/Fl_Native_File_Chooser.H40
-rw-r--r--src/lib/FL/Fl_Native_File_Chooser.cxx44
-rw-r--r--src/lib/FL/Fl_Native_File_Chooser_FLTK.H89
-rw-r--r--src/lib/FL/Fl_Native_File_Chooser_FLTK.cxx339
-rw-r--r--src/lib/FL/Fl_Native_File_Chooser_MAC.H138
-rw-r--r--src/lib/FL/Fl_Native_File_Chooser_MAC.cxx833
-rw-r--r--src/lib/FL/Fl_Native_File_Chooser_WIN32.H114
-rw-r--r--src/lib/FL/Fl_Native_File_Chooser_WIN32.cxx765
-rw-r--r--src/lib/FL/WidgetPDial.fl131
-rw-r--r--src/lib/FL/common.cxx60
-rwxr-xr-xsrc/lib/config.h11
-rwxr-xr-xsrc/lib/convertlib.cpp311
-rwxr-xr-xsrc/lib/convertlib.h39
-rw-r--r--src/lib/hd24devicenamegenerator.cpp286
-rwxr-xr-xsrc/lib/hd24devicenamegenerator.h52
-rwxr-xr-xsrc/lib/hd24fs.cpp3002
-rwxr-xr-xsrc/lib/hd24fs.h432
-rwxr-xr-xsrc/lib/hd24project.cpp477
-rw-r--r--src/lib/hd24sndfile.cpp270
-rw-r--r--src/lib/hd24sndfile.h37
-rwxr-xr-xsrc/lib/hd24song.cpp2188
-rw-r--r--src/lib/hd24transferengine.cpp2143
-rw-r--r--src/lib/hd24transferengine.h188
-rwxr-xr-xsrc/lib/hd24utils.cpp637
-rwxr-xr-xsrc/lib/hd24utils.h64
-rw-r--r--src/lib/memutils.cpp27
-rw-r--r--src/lib/memutils.h15
-rwxr-xr-xsrc/lib/nojack.cpp223
-rwxr-xr-xsrc/lib/nojack.h467
-rw-r--r--src/lib/portwin.h6
-rw-r--r--src/lib/sharedlibs.cpp332
-rw-r--r--src/lib/sharedlibs.h88
-rw-r--r--src/lib/smpte.cpp221
-rw-r--r--src/lib/smpte.h41
-rw-r--r--src/lib/soundlibs.h15
-rw-r--r--src/lib/xplat_dlfcn.h12
-rwxr-xr-xsrc/test/co2
-rw-r--r--src/test/portaudiotest.cpp158
-rw-r--r--src/test/portaudiotest.h33
-rw-r--r--src/test/portaudiotestold.cpp157
-rw-r--r--windows/hd24connect.dsp338
-rw-r--r--windows/hd24connect.dsw29
-rw-r--r--windows/hd24hexview.dsp118
-rw-r--r--windows/hd24info.dsp118
-rw-r--r--windows/hd24tools.dsw65
-rw-r--r--windows/hd24towav.dsp111
327 files changed, 41475 insertions, 0 deletions
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..f15a692
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,676 @@
1HD24tools is released under the following license.
2
3 GNU GENERAL PUBLIC LICENSE
4 Version 3, 29 June 2007
5
6 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
7 Everyone is permitted to copy and distribute verbatim copies
8 of this license document, but changing it is not allowed.
9
10 Preamble
11
12 The GNU General Public License is a free, copyleft license for
13software and other kinds of works.
14
15 The licenses for most software and other practical works are designed
16to take away your freedom to share and change the works. By contrast,
17the GNU General Public License is intended to guarantee your freedom to
18share and change all versions of a program--to make sure it remains free
19software for all its users. We, the Free Software Foundation, use the
20GNU General Public License for most of our software; it applies also to
21any other work released this way by its authors. You can apply it to
22your programs, too.
23
24 When we speak of free software, we are referring to freedom, not
25price. Our General Public Licenses are designed to make sure that you
26have the freedom to distribute copies of free software (and charge for
27them if you wish), that you receive source code or can get it if you
28want it, that you can change the software or use pieces of it in new
29free programs, and that you know you can do these things.
30
31 To protect your rights, we need to prevent others from denying you
32these rights or asking you to surrender the rights. Therefore, you have
33certain responsibilities if you distribute copies of the software, or if
34you modify it: responsibilities to respect the freedom of others.
35
36 For example, if you distribute copies of such a program, whether
37gratis or for a fee, you must pass on to the recipients the same
38freedoms that you received. You must make sure that they, too, receive
39or can get the source code. And you must show them these terms so they
40know their rights.
41
42 Developers that use the GNU GPL protect your rights with two steps:
43(1) assert copyright on the software, and (2) offer you this License
44giving you legal permission to copy, distribute and/or modify it.
45
46 For the developers' and authors' protection, the GPL clearly explains
47that there is no warranty for this free software. For both users' and
48authors' sake, the GPL requires that modified versions be marked as
49changed, so that their problems will not be attributed erroneously to
50authors of previous versions.
51
52 Some devices are designed to deny users access to install or run
53modified versions of the software inside them, although the manufacturer
54can do so. This is fundamentally incompatible with the aim of
55protecting users' freedom to change the software. The systematic
56pattern of such abuse occurs in the area of products for individuals to
57use, which is precisely where it is most unacceptable. Therefore, we
58have designed this version of the GPL to prohibit the practice for those
59products. If such problems arise substantially in other domains, we
60stand ready to extend this provision to those domains in future versions
61of the GPL, as needed to protect the freedom of users.
62
63 Finally, every program is threatened constantly by software patents.
64States should not allow patents to restrict development and use of
65software on general-purpose computers, but in those that do, we wish to
66avoid the special danger that patents applied to a free program could
67make it effectively proprietary. To prevent this, the GPL assures that
68patents cannot be used to render the program non-free.
69
70 The precise terms and conditions for copying, distribution and
71modification follow.
72
73 TERMS AND CONDITIONS
74
75 0. Definitions.
76
77 "This License" refers to version 3 of the GNU General Public License.
78
79 "Copyright" also means copyright-like laws that apply to other kinds of
80works, such as semiconductor masks.
81
82 "The Program" refers to any copyrightable work licensed under this
83License. Each licensee is addressed as "you". "Licensees" and
84"recipients" may be individuals or organizations.
85
86 To "modify" a work means to copy from or adapt all or part of the work
87in a fashion requiring copyright permission, other than the making of an
88exact copy. The resulting work is called a "modified version" of the
89earlier work or a work "based on" the earlier work.
90
91 A "covered work" means either the unmodified Program or a work based
92on the Program.
93
94 To "propagate" a work means to do anything with it that, without
95permission, would make you directly or secondarily liable for
96infringement under applicable copyright law, except executing it on a
97computer or modifying a private copy. Propagation includes copying,
98distribution (with or without modification), making available to the
99public, and in some countries other activities as well.
100
101 To "convey" a work means any kind of propagation that enables other
102parties to make or receive copies. Mere interaction with a user through
103a computer network, with no transfer of a copy, is not conveying.
104
105 An interactive user interface displays "Appropriate Legal Notices"
106to the extent that it includes a convenient and prominently visible
107feature that (1) displays an appropriate copyright notice, and (2)
108tells the user that there is no warranty for the work (except to the
109extent that warranties are provided), that licensees may convey the
110work under this License, and how to view a copy of this License. If
111the interface presents a list of user commands or options, such as a
112menu, a prominent item in the list meets this criterion.
113
114 1. Source Code.
115
116 The "source code" for a work means the preferred form of the work
117for making modifications to it. "Object code" means any non-source
118form of a work.
119
120 A "Standard Interface" means an interface that either is an official
121standard defined by a recognized standards body, or, in the case of
122interfaces specified for a particular programming language, one that
123is widely used among developers working in that language.
124
125 The "System Libraries" of an executable work include anything, other
126than the work as a whole, that (a) is included in the normal form of
127packaging a Major Component, but which is not part of that Major
128Component, and (b) serves only to enable use of the work with that
129Major Component, or to implement a Standard Interface for which an
130implementation is available to the public in source code form. A
131"Major Component", in this context, means a major essential component
132(kernel, window system, and so on) of the specific operating system
133(if any) on which the executable work runs, or a compiler used to
134produce the work, or an object code interpreter used to run it.
135
136 The "Corresponding Source" for a work in object code form means all
137the source code needed to generate, install, and (for an executable
138work) run the object code and to modify the work, including scripts to
139control those activities. However, it does not include the work's
140System Libraries, or general-purpose tools or generally available free
141programs which are used unmodified in performing those activities but
142which are not part of the work. For example, Corresponding Source
143includes interface definition files associated with source files for
144the work, and the source code for shared libraries and dynamically
145linked subprograms that the work is specifically designed to require,
146such as by intimate data communication or control flow between those
147subprograms and other parts of the work.
148
149 The Corresponding Source need not include anything that users
150can regenerate automatically from other parts of the Corresponding
151Source.
152
153 The Corresponding Source for a work in source code form is that
154same work.
155
156 2. Basic Permissions.
157
158 All rights granted under this License are granted for the term of
159copyright on the Program, and are irrevocable provided the stated
160conditions are met. This License explicitly affirms your unlimited
161permission to run the unmodified Program. The output from running a
162covered work is covered by this License only if the output, given its
163content, constitutes a covered work. This License acknowledges your
164rights of fair use or other equivalent, as provided by copyright law.
165
166 You may make, run and propagate covered works that you do not
167convey, without conditions so long as your license otherwise remains
168in force. You may convey covered works to others for the sole purpose
169of having them make modifications exclusively for you, or provide you
170with facilities for running those works, provided that you comply with
171the terms of this License in conveying all material for which you do
172not control copyright. Those thus making or running the covered works
173for you must do so exclusively on your behalf, under your direction
174and control, on terms that prohibit them from making any copies of
175your copyrighted material outside their relationship with you.
176
177 Conveying under any other circumstances is permitted solely under
178the conditions stated below. Sublicensing is not allowed; section 10
179makes it unnecessary.
180
181 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
182
183 No covered work shall be deemed part of an effective technological
184measure under any applicable law fulfilling obligations under article
18511 of the WIPO copyright treaty adopted on 20 December 1996, or
186similar laws prohibiting or restricting circumvention of such
187measures.
188
189 When you convey a covered work, you waive any legal power to forbid
190circumvention of technological measures to the extent such circumvention
191is effected by exercising rights under this License with respect to
192the covered work, and you disclaim any intention to limit operation or
193modification of the work as a means of enforcing, against the work's
194users, your or third parties' legal rights to forbid circumvention of
195technological measures.
196
197 4. Conveying Verbatim Copies.
198
199 You may convey verbatim copies of the Program's source code as you
200receive it, in any medium, provided that you conspicuously and
201appropriately publish on each copy an appropriate copyright notice;
202keep intact all notices stating that this License and any
203non-permissive terms added in accord with section 7 apply to the code;
204keep intact all notices of the absence of any warranty; and give all
205recipients a copy of this License along with the Program.
206
207 You may charge any price or no price for each copy that you convey,
208and you may offer support or warranty protection for a fee.
209
210 5. Conveying Modified Source Versions.
211
212 You may convey a work based on the Program, or the modifications to
213produce it from the Program, in the form of source code under the
214terms of section 4, provided that you also meet all of these conditions:
215
216 a) The work must carry prominent notices stating that you modified
217 it, and giving a relevant date.
218
219 b) The work must carry prominent notices stating that it is
220 released under this License and any conditions added under section
221 7. This requirement modifies the requirement in section 4 to
222 "keep intact all notices".
223
224 c) You must license the entire work, as a whole, under this
225 License to anyone who comes into possession of a copy. This
226 License will therefore apply, along with any applicable section 7
227 additional terms, to the whole of the work, and all its parts,
228 regardless of how they are packaged. This License gives no
229 permission to license the work in any other way, but it does not
230 invalidate such permission if you have separately received it.
231
232 d) If the work has interactive user interfaces, each must display
233 Appropriate Legal Notices; however, if the Program has interactive
234 interfaces that do not display Appropriate Legal Notices, your
235 work need not make them do so.
236
237 A compilation of a covered work with other separate and independent
238works, which are not by their nature extensions of the covered work,
239and which are not combined with it such as to form a larger program,
240in or on a volume of a storage or distribution medium, is called an
241"aggregate" if the compilation and its resulting copyright are not
242used to limit the access or legal rights of the compilation's users
243beyond what the individual works permit. Inclusion of a covered work
244in an aggregate does not cause this License to apply to the other
245parts of the aggregate.
246
247 6. Conveying Non-Source Forms.
248
249 You may convey a covered work in object code form under the terms
250of sections 4 and 5, provided that you also convey the
251machine-readable Corresponding Source under the terms of this License,
252in one of these ways:
253
254 a) Convey the object code in, or embodied in, a physical product
255 (including a physical distribution medium), accompanied by the
256 Corresponding Source fixed on a durable physical medium
257 customarily used for software interchange.
258
259 b) Convey the object code in, or embodied in, a physical product
260 (including a physical distribution medium), accompanied by a
261 written offer, valid for at least three years and valid for as
262 long as you offer spare parts or customer support for that product
263 model, to give anyone who possesses the object code either (1) a
264 copy of the Corresponding Source for all the software in the
265 product that is covered by this License, on a durable physical
266 medium customarily used for software interchange, for a price no
267 more than your reasonable cost of physically performing this
268 conveying of source, or (2) access to copy the
269 Corresponding Source from a network server at no charge.
270
271 c) Convey individual copies of the object code with a copy of the
272 written offer to provide the Corresponding Source. This
273 alternative is allowed only occasionally and noncommercially, and
274 only if you received the object code with such an offer, in accord
275 with subsection 6b.
276
277 d) Convey the object code by offering access from a designated
278 place (gratis or for a charge), and offer equivalent access to the
279 Corresponding Source in the same way through the same place at no
280 further charge. You need not require recipients to copy the
281 Corresponding Source along with the object code. If the place to
282 copy the object code is a network server, the Corresponding Source
283 may be on a different server (operated by you or a third party)
284 that supports equivalent copying facilities, provided you maintain
285 clear directions next to the object code saying where to find the
286 Corresponding Source. Regardless of what server hosts the
287 Corresponding Source, you remain obligated to ensure that it is
288 available for as long as needed to satisfy these requirements.
289
290 e) Convey the object code using peer-to-peer transmission, provided
291 you inform other peers where the object code and Corresponding
292 Source of the work are being offered to the general public at no
293 charge under subsection 6d.
294
295 A separable portion of the object code, whose source code is excluded
296from the Corresponding Source as a System Library, need not be
297included in conveying the object code work.
298
299 A "User Product" is either (1) a "consumer product", which means any
300tangible personal property which is normally used for personal, family,
301or household purposes, or (2) anything designed or sold for incorporation
302into a dwelling. In determining whether a product is a consumer product,
303doubtful cases shall be resolved in favor of coverage. For a particular
304product received by a particular user, "normally used" refers to a
305typical or common use of that class of product, regardless of the status
306of the particular user or of the way in which the particular user
307actually uses, or expects or is expected to use, the product. A product
308is a consumer product regardless of whether the product has substantial
309commercial, industrial or non-consumer uses, unless such uses represent
310the only significant mode of use of the product.
311
312 "Installation Information" for a User Product means any methods,
313procedures, authorization keys, or other information required to install
314and execute modified versions of a covered work in that User Product from
315a modified version of its Corresponding Source. The information must
316suffice to ensure that the continued functioning of the modified object
317code is in no case prevented or interfered with solely because
318modification has been made.
319
320 If you convey an object code work under this section in, or with, or
321specifically for use in, a User Product, and the conveying occurs as
322part of a transaction in which the right of possession and use of the
323User Product is transferred to the recipient in perpetuity or for a
324fixed term (regardless of how the transaction is characterized), the
325Corresponding Source conveyed under this section must be accompanied
326by the Installation Information. But this requirement does not apply
327if neither you nor any third party retains the ability to install
328modified object code on the User Product (for example, the work has
329been installed in ROM).
330
331 The requirement to provide Installation Information does not include a
332requirement to continue to provide support service, warranty, or updates
333for a work that has been modified or installed by the recipient, or for
334the User Product in which it has been modified or installed. Access to a
335network may be denied when the modification itself materially and
336adversely affects the operation of the network or violates the rules and
337protocols for communication across the network.
338
339 Corresponding Source conveyed, and Installation Information provided,
340in accord with this section must be in a format that is publicly
341documented (and with an implementation available to the public in
342source code form), and must require no special password or key for
343unpacking, reading or copying.
344
345 7. Additional Terms.
346
347 "Additional permissions" are terms that supplement the terms of this
348License by making exceptions from one or more of its conditions.
349Additional permissions that are applicable to the entire Program shall
350be treated as though they were included in this License, to the extent
351that they are valid under applicable law. If additional permissions
352apply only to part of the Program, that part may be used separately
353under those permissions, but the entire Program remains governed by
354this License without regard to the additional permissions.
355
356 When you convey a copy of a covered work, you may at your option
357remove any additional permissions from that copy, or from any part of
358it. (Additional permissions may be written to require their own
359removal in certain cases when you modify the work.) You may place
360additional permissions on material, added by you to a covered work,
361for which you have or can give appropriate copyright permission.
362
363 Notwithstanding any other provision of this License, for material you
364add to a covered work, you may (if authorized by the copyright holders of
365that material) supplement the terms of this License with terms:
366
367 a) Disclaiming warranty or limiting liability differently from the
368 terms of sections 15 and 16 of this License; or
369
370 b) Requiring preservation of specified reasonable legal notices or
371 author attributions in that material or in the Appropriate Legal
372 Notices displayed by works containing it; or
373
374 c) Prohibiting misrepresentation of the origin of that material, or
375 requiring that modified versions of such material be marked in
376 reasonable ways as different from the original version; or
377
378 d) Limiting the use for publicity purposes of names of licensors or
379 authors of the material; or
380
381 e) Declining to grant rights under trademark law for use of some
382 trade names, trademarks, or service marks; or
383
384 f) Requiring indemnification of licensors and authors of that
385 material by anyone who conveys the material (or modified versions of
386 it) with contractual assumptions of liability to the recipient, for
387 any liability that these contractual assumptions directly impose on
388 those licensors and authors.
389
390 All other non-permissive additional terms are considered "further
391restrictions" within the meaning of section 10. If the Program as you
392received it, or any part of it, contains a notice stating that it is
393governed by this License along with a term that is a further
394restriction, you may remove that term. If a license document contains
395a further restriction but permits relicensing or conveying under this
396License, you may add to a covered work material governed by the terms
397of that license document, provided that the further restriction does
398not survive such relicensing or conveying.
399
400 If you add terms to a covered work in accord with this section, you
401must place, in the relevant source files, a statement of the
402additional terms that apply to those files, or a notice indicating
403where to find the applicable terms.
404
405 Additional terms, permissive or non-permissive, may be stated in the
406form of a separately written license, or stated as exceptions;
407the above requirements apply either way.
408
409 8. Termination.
410
411 You may not propagate or modify a covered work except as expressly
412provided under this License. Any attempt otherwise to propagate or
413modify it is void, and will automatically terminate your rights under
414this License (including any patent licenses granted under the third
415paragraph of section 11).
416
417 However, if you cease all violation of this License, then your
418license from a particular copyright holder is reinstated (a)
419provisionally, unless and until the copyright holder explicitly and
420finally terminates your license, and (b) permanently, if the copyright
421holder fails to notify you of the violation by some reasonable means
422prior to 60 days after the cessation.
423
424 Moreover, your license from a particular copyright holder is
425reinstated permanently if the copyright holder notifies you of the
426violation by some reasonable means, this is the first time you have
427received notice of violation of this License (for any work) from that
428copyright holder, and you cure the violation prior to 30 days after
429your receipt of the notice.
430
431 Termination of your rights under this section does not terminate the
432licenses of parties who have received copies or rights from you under
433this License. If your rights have been terminated and not permanently
434reinstated, you do not qualify to receive new licenses for the same
435material under section 10.
436
437 9. Acceptance Not Required for Having Copies.
438
439 You are not required to accept this License in order to receive or
440run a copy of the Program. Ancillary propagation of a covered work
441occurring solely as a consequence of using peer-to-peer transmission
442to receive a copy likewise does not require acceptance. However,
443nothing other than this License grants you permission to propagate or
444modify any covered work. These actions infringe copyright if you do
445not accept this License. Therefore, by modifying or propagating a
446covered work, you indicate your acceptance of this License to do so.
447
448 10. Automatic Licensing of Downstream Recipients.
449
450 Each time you convey a covered work, the recipient automatically
451receives a license from the original licensors, to run, modify and
452propagate that work, subject to this License. You are not responsible
453for enforcing compliance by third parties with this License.
454
455 An "entity transaction" is a transaction transferring control of an
456organization, or substantially all assets of one, or subdividing an
457organization, or merging organizations. If propagation of a covered
458work results from an entity transaction, each party to that
459transaction who receives a copy of the work also receives whatever
460licenses to the work the party's predecessor in interest had or could
461give under the previous paragraph, plus a right to possession of the
462Corresponding Source of the work from the predecessor in interest, if
463the predecessor has it or can get it with reasonable efforts.
464
465 You may not impose any further restrictions on the exercise of the
466rights granted or affirmed under this License. For example, you may
467not impose a license fee, royalty, or other charge for exercise of
468rights granted under this License, and you may not initiate litigation
469(including a cross-claim or counterclaim in a lawsuit) alleging that
470any patent claim is infringed by making, using, selling, offering for
471sale, or importing the Program or any portion of it.
472
473 11. Patents.
474
475 A "contributor" is a copyright holder who authorizes use under this
476License of the Program or a work on which the Program is based. The
477work thus licensed is called the contributor's "contributor version".
478
479 A contributor's "essential patent claims" are all patent claims
480owned or controlled by the contributor, whether already acquired or
481hereafter acquired, that would be infringed by some manner, permitted
482by this License, of making, using, or selling its contributor version,
483but do not include claims that would be infringed only as a
484consequence of further modification of the contributor version. For
485purposes of this definition, "control" includes the right to grant
486patent sublicenses in a manner consistent with the requirements of
487this License.
488
489 Each contributor grants you a non-exclusive, worldwide, royalty-free
490patent license under the contributor's essential patent claims, to
491make, use, sell, offer for sale, import and otherwise run, modify and
492propagate the contents of its contributor version.
493
494 In the following three paragraphs, a "patent license" is any express
495agreement or commitment, however denominated, not to enforce a patent
496(such as an express permission to practice a patent or covenant not to
497sue for patent infringement). To "grant" such a patent license to a
498party means to make such an agreement or commitment not to enforce a
499patent against the party.
500
501 If you convey a covered work, knowingly relying on a patent license,
502and the Corresponding Source of the work is not available for anyone
503to copy, free of charge and under the terms of this License, through a
504publicly available network server or other readily accessible means,
505then you must either (1) cause the Corresponding Source to be so
506available, or (2) arrange to deprive yourself of the benefit of the
507patent license for this particular work, or (3) arrange, in a manner
508consistent with the requirements of this License, to extend the patent
509license to downstream recipients. "Knowingly relying" means you have
510actual knowledge that, but for the patent license, your conveying the
511covered work in a country, or your recipient's use of the covered work
512in a country, would infringe one or more identifiable patents in that
513country that you have reason to believe are valid.
514
515 If, pursuant to or in connection with a single transaction or
516arrangement, you convey, or propagate by procuring conveyance of, a
517covered work, and grant a patent license to some of the parties
518receiving the covered work authorizing them to use, propagate, modify
519or convey a specific copy of the covered work, then the patent license
520you grant is automatically extended to all recipients of the covered
521work and works based on it.
522
523 A patent license is "discriminatory" if it does not include within
524the scope of its coverage, prohibits the exercise of, or is
525conditioned on the non-exercise of one or more of the rights that are
526specifically granted under this License. You may not convey a covered
527work if you are a party to an arrangement with a third party that is
528in the business of distributing software, under which you make payment
529to the third party based on the extent of your activity of conveying
530the work, and under which the third party grants, to any of the
531parties who would receive the covered work from you, a discriminatory
532patent license (a) in connection with copies of the covered work
533conveyed by you (or copies made from those copies), or (b) primarily
534for and in connection with specific products or compilations that
535contain the covered work, unless you entered into that arrangement,
536or that patent license was granted, prior to 28 March 2007.
537
538 Nothing in this License shall be construed as excluding or limiting
539any implied license or other defenses to infringement that may
540otherwise be available to you under applicable patent law.
541
542 12. No Surrender of Others' Freedom.
543
544 If conditions are imposed on you (whether by court order, agreement or
545otherwise) that contradict the conditions of this License, they do not
546excuse you from the conditions of this License. If you cannot convey a
547covered work so as to satisfy simultaneously your obligations under this
548License and any other pertinent obligations, then as a consequence you may
549not convey it at all. For example, if you agree to terms that obligate you
550to collect a royalty for further conveying from those to whom you convey
551the Program, the only way you could satisfy both those terms and this
552License would be to refrain entirely from conveying the Program.
553
554 13. Use with the GNU Affero General Public License.
555
556 Notwithstanding any other provision of this License, you have
557permission to link or combine any covered work with a work licensed
558under version 3 of the GNU Affero General Public License into a single
559combined work, and to convey the resulting work. The terms of this
560License will continue to apply to the part which is the covered work,
561but the special requirements of the GNU Affero General Public License,
562section 13, concerning interaction through a network will apply to the
563combination as such.
564
565 14. Revised Versions of this License.
566
567 The Free Software Foundation may publish revised and/or new versions of
568the GNU General Public License from time to time. Such new versions will
569be similar in spirit to the present version, but may differ in detail to
570address new problems or concerns.
571
572 Each version is given a distinguishing version number. If the
573Program specifies that a certain numbered version of the GNU General
574Public License "or any later version" applies to it, you have the
575option of following the terms and conditions either of that numbered
576version or of any later version published by the Free Software
577Foundation. If the Program does not specify a version number of the
578GNU General Public License, you may choose any version ever published
579by the Free Software Foundation.
580
581 If the Program specifies that a proxy can decide which future
582versions of the GNU General Public License can be used, that proxy's
583public statement of acceptance of a version permanently authorizes you
584to choose that version for the Program.
585
586 Later license versions may give you additional or different
587permissions. However, no additional obligations are imposed on any
588author or copyright holder as a result of your choosing to follow a
589later version.
590
591 15. Disclaimer of Warranty.
592
593 THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
594APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
595HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
596OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
597THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
598PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
599IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
600ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
601
602 16. Limitation of Liability.
603
604 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
605WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
606THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
607GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
608USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
609DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
610PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
611EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
612SUCH DAMAGES.
613
614 17. Interpretation of Sections 15 and 16.
615
616 If the disclaimer of warranty and limitation of liability provided
617above cannot be given local legal effect according to their terms,
618reviewing courts shall apply local law that most closely approximates
619an absolute waiver of all civil liability in connection with the
620Program, unless a warranty or assumption of liability accompanies a
621copy of the Program in return for a fee.
622
623 END OF TERMS AND CONDITIONS
624
625 How to Apply These Terms to Your New Programs
626
627 If you develop a new program, and you want it to be of the greatest
628possible use to the public, the best way to achieve this is to make it
629free software which everyone can redistribute and change under these terms.
630
631 To do so, attach the following notices to the program. It is safest
632to attach them to the start of each source file to most effectively
633state the exclusion of warranty; and each file should have at least
634the "copyright" line and a pointer to where the full notice is found.
635
636 <one line to give the program's name and a brief idea of what it does.>
637 Copyright (C) <year> <name of author>
638
639 This program is free software: you can redistribute it and/or modify
640 it under the terms of the GNU General Public License as published by
641 the Free Software Foundation, either version 3 of the License, or
642 (at your option) any later version.
643
644 This program is distributed in the hope that it will be useful,
645 but WITHOUT ANY WARRANTY; without even the implied warranty of
646 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
647 GNU General Public License for more details.
648
649 You should have received a copy of the GNU General Public License
650 along with this program. If not, see <http://www.gnu.org/licenses/>.
651
652Also add information on how to contact you by electronic and paper mail.
653
654 If the program does terminal interaction, make it output a short
655notice like this when it starts in an interactive mode:
656
657 <program> Copyright (C) <year> <name of author>
658 This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
659 This is free software, and you are welcome to redistribute it
660 under certain conditions; type `show c' for details.
661
662The hypothetical commands `show w' and `show c' should show the appropriate
663parts of the General Public License. Of course, your program's commands
664might be different; for a GUI interface, you would use an "about box".
665
666 You should also get your employer (if you work as a programmer) or school,
667if any, to sign a "copyright disclaimer" for the program, if necessary.
668For more information on this, and how to apply and follow the GNU GPL, see
669<http://www.gnu.org/licenses/>.
670
671 The GNU General Public License does not permit incorporating your program
672into proprietary programs. If your program is a subroutine library, you
673may consider it more useful to permit linking proprietary applications with
674the library. If this is what you want to do, use the GNU Lesser General
675Public License instead of this License. But first, please read
676<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/Makefile.in b/Makefile.in
new file mode 100755
index 0000000..85bcfde
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,513 @@
1
2# ===============================================
3#
4# GENERIC CONFIG
5#
6# ===============================================
7RELEASENUM=1.0.0alpha11
8INSTALLDIR=/usr/bin
9INST_UI=src/installer/
10INST_BIN=bin/installer/
11BINDIR=bin/
12SRCDIR=src/
13UI=src/frontend/
14LIB=src/lib/
15
16CCARGS=$(TMPCCARGS) -DLIBSND=Yes -DLIBJACK -DLIBPORTAUDIO
17
18# ===============================================
19#
20# ARCH DEPENDENT CONFIG
21#
22# ===============================================
23ifeq ($(BUILD_ARCH), Win32)
24PLATFORM=win32
25CC=gcc -Wall -Werror -DWINDOWS -DRELEASENUM=$(RELEASENUM) -DLIBFILE_SNDFILE=\"libsndfile-1.dll\" -DLIBFILE_PORTAUDIO=\"portaudio.dll\" -DLIBFILE_JACK=\"libjackmp.dll\" -DDEFAULTLIBPATH=\"C\:/WINDOWS\;C\:/WINDOWS/SYSTEM32\"
26INCLUDEDIRS=-I src/frontend -I src/lib -I src/backend -I /local/include -I /local/lib -I setup -I src -Bsrc -Bsrc/lib
27LIBDIRS=-L/usr/local/lib -L/usr/X11R6/lib/ -L/local/lib/ -Lsrc/lib/ -Lsrc/
28UILIBS=-lstdc++ -lfltk -lm -lfltk_forms -lfltk_images -lgdi32 -lkernel32 -lole32 -luuid -lmsvcrt -luser32 -lwsock32 -lcomctl32 -lsupc++ `fltk-config --ldstaticflags`
29CONSLIBS=-lstdc++ -lm -lkernel32 -lole32 -luuid -lmsvcrt -luser32 -lwsock32 -lcomctl32 -lsupc++
30PROGICON=$(BINDIR)icon.o
31RESOURCE_LIBSNDFILE_1=$(BINDIR)win32/libsndfile-1.dll
32RESOURCE_LIBSNDFILE_1_FILENAME=libsndfile-1.dll
33RESOURCE_LIBSNDFILE_2=
34RESOURCE_LIBSNDFILE_3=
35CONSDEPS=-mwindows -mconsole
36WINDEPS=$(BINDIR)nojack.o
37WINEXT=.exe
38endif
39
40ifeq ($(BUILD_ARCH), Darwin)
41PLATFORM=OSX10.4
42CFLAGS=-no-cpp-precomp -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk
43CXXFLAGS=-no-cpp-precomp -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk
44CC=g++ -O3 $(CXXFLAGS) -Wall -DDARWIN -DRELEASENUM=$(RELEASENUM) -DLIBFILE_SNDFILE=\"libsndfile.1.dylib\" -DLIBFILE_PORTAUDIO=\"libportaudio.dylib\" -DLIBFILE_JACK=\"libjack.dylib\" -DDEFAULTLIBPATH=\"/usr/lib/:/usr/local/lib/:/lib/\"
45LIBDIRS=-L/usr/local/lib -Lsrc/lib/ -L/sw/lib/
46INCLUDEDIRS=-I /usr/local/include -I /sw/include -I src/frontend -I src/lib -I src/backend -I setup
47UILIBS=-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices `fltk-config --ldstaticflags`
48CONSLIBS=-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices `fltk-config --ldstaticflags`
49RESOURCE_LIBSNDFILE_1=$(BINDIR)ppc10.4/libsndfile.dylib
50RESOURCE_LIBSNDFILE_1_FILENAME=libsndfile.1.dylib
51endif
52
53ifeq ($(BUILD_ARCH), LinuxGNU)
54PLATFORM=linux
55CC=g++ -O3 -g $(TESTFLAGS) -Wall -Werror -DLINUX -DRELEASENUM=$(RELEASENUM) -DLIBFILE_SNDFILE=\"libsndfile.so.1\" -DLIBFILE_PORTAUDIO=\"libportaudio.so\" -DLIBFILE_JACK=\"libjack.so\" -DDEFAULTLIBPATH=\"/usr/lib/:/usr/local/lib/:/lib/\"
56LIBDIRS=-L/usr/local/lib -L/usr/X11R6/lib/ -L/local/lib/ -Lsrc/lib/
57INCLUDEDIRS=-I /usr/local/lib -I src/frontend -I src/lib -I src/backend -I /local/include -I setup
58UILIBS=-lstdc++ -lgcc -lXpm `fltk-config --ldstaticflags`
59CONSLIBS=-lstdc++ -lgcc
60RESOURCE_LIBSNDFILE_1=$(BINDIR)linux/libsndfile.so
61RESOURCE_LIBSNDFILE_1_FILENAME=libsndfile.so.1
62endif
63
64ifeq ($(BUILD_ARCH), Win32Linux)
65PLATFORM=win32
66CC=i586-mingw32msvc-gcc -Wall -Werror -DWINDOWS -DRELEASENUM=$(RELEASENUM) -DLIBFILE_SNDFILE=\"libsndfile-1.dll\" -DLIBFILE_PORTAUDIO=\"libportaudio.dll\" -DLIBFILE_JACK=\"libjackmp.dll\" -DDEFAULTLIBPATH=\"C\:\\WINDOWS\;C\:\\WINDOWS\\SYSTEM32\"
67INCLUDEDIRS=-I src/frontend -I src/lib -I src/backend -I /local/include -I /local/lib -I setup -I src -Bsrc -Bsrc/lib
68LIBDIRS=-L/usr/local/lib -L/usr/X11R6/lib/ -L/local/lib/ -Lsrc/lib/ -Lsrc/
69UILIBS=-lstdc++ -lfltk -lm -lfltk_forms -lfltk_images -lgdi32 -lkernel32 -lole32 -luuid -lmsvcrt -luser32 -lwsock32 -lcomctl32 -lsupc++ `fltk-config --ldstaticflags`
70CONSLIBS=-lstdc++ -lm -lkernel32 -lole32 -luuid -lmsvcrt -luser32 -lwsock32 -lcomctl32 -lsupc++
71WINDEPS=$(BINDIR)nojack.o
72PROGICON=$(BINDIR)icon.o
73RESOURCE_LIBSNDFILE_1=$(BINDIR)win32/libsndfile-1.dll
74RESOURCE_LIBSNDFILE_1_FILENAME=libsndfile-1.dll
75RESOURCE_LIBSNDFILE_2=
76RESOURCE_LIBSNDFILE_3=
77CONSDEPS=-mwindows -mconsole
78WINEXT=.exe
79endif
80
81# ===============================================
82#
83# DEFAULT TARGET
84#
85# ===============================================
86all: hd24info hd24hexview hd24connect #hd24towav hd24wavefix
87
88# ===============================================
89#
90# CLEANUP TARGETS
91#
92# ===============================================
93clean:
94 @rm -f $(BINDIR)*.o \
95 $(BINDIR)*.cpp \
96 $(BINDIR)*.cxx \
97 $(UI)*.cxx \
98 $(UI)*.h \
99 hd24connect$(WINEXT) \
100 hd24hexview$(WINEXT) \
101 hd24towav$(WINEXT) \
102 hd24wavefix$(WINEXT) \
103 hd24info$(WINEXT) \
104 src/lib/*~ \
105 src/*~ \
106 src/installer/*~ \
107 src/installer/resource_*.c \
108 src/installer/*.o \
109 src/installer/ui_*.cxx \
110 src/installer/ui_*.h \
111 src/installer/bin2c \
112 silent
113
114distclean: clean
115 @rm -f Makefile \
116 makeincludes \
117 setup/config.h \
118 setup/Makefile.setup
119
120# ===============================================
121#
122# INSTALL TARGET
123#
124# ===============================================
125install: hd24connect$(WINEXT) hd24hexview$(WINEXT)
126 cp hd24connect$(WINEXT) $(INSTALLDIR)
127 cp hd24info$(WINEXT) $(INSTALLDIR)
128 cp hd24hexview$(WINEXT) $(INSTALLDIR)
129 cp hd24towav$(WINEXT) $(INSTALLDIR)
130 cp hd24wavefix$(WINEXT) $(INSTALLDIR)
131
132# ===============================================
133#
134# INSTALL BUILDING
135#
136# ===============================================
137installer: $(PLATFORM)_installer
138 echo Making installer for $(PLATFORM)...
139
140win32_installer:
141linux_installer: hd24connect$(WINEXT) hd24hexview$(WINEXT) $(BINDIR)Fl_Native_File_Chooser.o
142 $(CC) $(CCARGS) $(SRCDIR)installer/bin2c.c -o $(SRCDIR)installer/bin2c$(WINEXT)
143 # create installer resources include file
144 echo // This file contains installer resources >$(SRCDIR)installer/installer_resources.h
145 $(SRCDIR)installer/bin2c$(WINEXT) images/longliverec.h24 $(SRCDIR)installer/resource_longliverec.c resource_longliverec
146 echo \#include \"resource_longliverec.c\" >>$(SRCDIR)installer/installer_resources.h
147 echo \#define resource_longliverec_filename \"longliverec.h24\" >>$(SRCDIR)installer/installer_resources.h
148 $(SRCDIR)installer/bin2c$(WINEXT) doc/hd24tools_manual.pdf $(SRCDIR)installer/resource_hd24tools_manual.c resource_hd24tools_manual
149 echo \#include \"resource_hd24tools_manual.c\" >>$(SRCDIR)installer/installer_resources.h
150 echo \#define resource_hd24tools_manual_filename \"hd24tools_manual.pdf\" >>$(SRCDIR)installer/installer_resources.h
151 $(SRCDIR)installer/bin2c$(WINEXT) images/unquickformat.h24 $(SRCDIR)installer/resource_unquickformat.c resource_unquickformat
152 echo \#include \"resource_unquickformat.c\" >>$(SRCDIR)installer/installer_resources.h
153 echo \#define resource_unquickformat_filename \"unquickformat.h24\" >>$(SRCDIR)installer/installer_resources.h
154 $(SRCDIR)installer/bin2c$(WINEXT) hd24connect$(WINEXT) $(SRCDIR)installer/resource_hd24connect.c resource_hd24connect
155 echo \#include \"resource_hd24connect.c\" >>$(SRCDIR)installer/installer_resources.h
156 echo \#define resource_hd24connect_filename \"hd24connect$(WINEXT)\" >>$(SRCDIR)installer/installer_resources.h
157 $(SRCDIR)installer/bin2c$(WINEXT) hd24hexview$(WINEXT) $(SRCDIR)installer/resource_hd24hexview.c resource_hd24hexview
158 echo \#include \"resource_hd24hexview.c\" >>$(SRCDIR)installer/installer_resources.h
159 echo \#define resource_hd24hexview_filename \"hd24hexview$(WINEXT)\" >>$(SRCDIR)installer/installer_resources.h
160 $(SRCDIR)installer/bin2c$(WINEXT) $(RESOURCE_LIBSNDFILE_1) $(SRCDIR)installer/resource_libsndfile_1.c resource_libsndfile_1
161 echo \#include \"resource_libsndfile_1.c\" >>$(SRCDIR)installer/installer_resources.h
162 echo \#define resource_libsndfile_1_filename \"$(RESOURCE_LIBSNDFILE_1_FILENAME)\" >>$(SRCDIR)installer/installer_resources.h
163 echo \#define sharedlibdir \"\" >>$(SRCDIR)installer/installer_resources.h
164 echo // These are apple specific resources >>$(SRCDIR)installer/installer_resources.h
165 $(SRCDIR)installer/bin2c$(WINEXT) $(SRCDIR)installer/info.plist.hd24connect $(SRCDIR)installer/resource_plistconnect.c resource_plist_connect
166 echo \#include \"resource_plistconnect.c\" >>$(SRCDIR)installer/installer_resources.h
167 $(SRCDIR)installer/bin2c$(WINEXT) $(SRCDIR)installer/PkgInfo.hd24connect $(SRCDIR)installer/resource_pkginfoconnect.c resource_pkginfo_connect
168 echo \#include \"resource_pkginfoconnect.c\" >>$(SRCDIR)installer/installer_resources.h
169 fluid -c $(SRCDIR)installer/ui_welcome.fl; \
170 cat ui_welcome.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(SRCDIR)installer/ui_welcome.cxx; \
171 mv ui_welcome.h $(SRCDIR)installer; \
172 rm ui_welcome.cxx; \
173 \
174 fluid -c $(SRCDIR)installer/ui_license.fl; \
175 cat ui_license.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(SRCDIR)installer/ui_license.cxx; \
176 mv ui_license.h $(SRCDIR)installer; \
177 rm ui_license.cxx; \
178 \
179 fluid -c $(SRCDIR)installer/ui_instdir.fl; \
180 cat ui_instdir.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(SRCDIR)installer/ui_instdir.cxx; \
181 mv ui_instdir.h $(SRCDIR)installer; \
182 rm ui_instdir.cxx; \
183 \
184 fluid -c $(SRCDIR)installer/ui_ready.fl; \
185 cat ui_ready.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(SRCDIR)installer/ui_ready.cxx; \
186 mv ui_ready.h $(SRCDIR)installer; \
187 rm ui_ready.cxx; \
188 \
189 $(CC) $(CCARGS) -c $(SRCDIR)installer/ui_welcome.cxx -o $(SRCDIR)installer/ui_welcome.o $(INCLUDEDIRS) $(LIBDIRS);\
190 $(CC) $(CCARGS) -c $(SRCDIR)installer/ui_license.cxx -o $(SRCDIR)installer/ui_license.o $(INCLUDEDIRS) $(LIBDIRS);\
191 $(CC) $(CCARGS) -c $(SRCDIR)installer/ui_instdir.cxx -o $(SRCDIR)installer/ui_instdir.o $(INCLUDEDIRS) $(LIBDIRS);\
192 $(CC) $(CCARGS) -c $(SRCDIR)installer/ui_ready.cxx -o $(SRCDIR)installer/ui_ready.o $(INCLUDEDIRS) $(LIBDIRS);\
193 #@echo -e "\n\nInstaller spec files built. You must now make the appropriate target to get an installer file."
194 $(CREATEINSTALLERPACKAGE)
195
196createinstallerpackage_win32:
197 $(CC) $(CCARGS) $(SRCDIR)installer/setup.cpp $(BINDIR)Fl_Native_File_Chooser.o $(SRCDIR)installer/ui_license.o $(SRCDIR)installer/ui_welcome.o $(SRCDIR)installer/ui_instdir.o $(SRCDIR)installer/ui_ready.o -o $(SRCDIR)installer/setup$(WINEXT) $(INCLUDEDIRS) $(LIBDIRS) $(UILIBS)
198 fltk-config --post $(SRCDIR)installer/setup$(WINEXT)
199 echo Win32 setup post processing
200 mv src/installer/setup.exe .
201 zip a hd24tools_setup_$(RELEASENUM)_win32.zip setup.exe
202 mv setup.exe src/installer
203
204createinstallerpackage_linux:
205 $(CC) $(CCARGS) -static-libgcc $(SRCDIR)installer/setup.cpp $(BINDIR)Fl_Native_File_Chooser.o $(SRCDIR)installer/ui_license.o $(SRCDIR)installer/ui_welcome.o $(SRCDIR)installer/ui_instdir.o $(SRCDIR)installer/ui_ready.o -o $(SRCDIR)installer/setup$(WINEXT) $(INCLUDEDIRS) $(LIBDIRS) $(UILIBS)
206 fltk-config --post $(SRCDIR)installer/setup
207 echo Linux setup post processing
208 mv setup setup.bck
209 mv src/installer/setup .
210 tar cvfz hd24tools_setup_$(RELEASENUM)_linuxi386.tgz setup
211 mv setup src/installer
212 mv setup.bck setup
213
214OSX10.4_installer: hd24connect$(WINEXT) hd24hexview$(WINEXT) $(BINDIR)Fl_Native_File_Chooser.o createinstallerpackage_mac
215createinstallerpackage_mac:
216# $(CC) $(CCARGS) $(SRCDIR)installer/setup.cpp $(BINDIR)Fl_Native_File_Chooser.o $(SRCDIR)installer/ui_license.o $(SRCDIR)installer/ui_welcome.o $(SRCDIR)installer/ui_instdir.o $(SRCDIR)installer/ui_ready.o -o $(SRCDIR)installer/setup$(WINEXT) $(INCLUDEDIRS) $(LIBDIRS) $(UILIBS)
217# fltk-config --post $(SRCDIR)installer/setup$(WINEXT)
218 echo Mac setup post processing
219 rm -rf result
220 mkdir result
221 ditto hd24hexview result/
222 mkdir result/HD24connect.app
223 mkdir result/HD24connect.app/Contents
224 cat $(SRCDIR)installer/info.plist.hd24connect|sed -e 's/HD24VERSION/$(RELEASENUM)/' > $(SRCDIR)installer/info.plist.hd24c; \
225 ditto $(SRCDIR)installer/info.plist.hd24c result/HD24connect.app/Contents/info.plist
226 ditto $(SRCDIR)installer/PkgInfo.hd24connect result/HD24connect.app/Contents/
227 mkdir result/HD24connect.app/Contents/MacOS
228 mkdir result/HD24connect.app/Contents/Resources
229 ditto $(SRCDIR)installer/icon.icns result/HD24connect.app/Contents/Resources
230 ditto hd24connect result/HD24connect.app/Contents/MacOS
231# ditto doc/hd24tools_manual.pdf result
232 ditto images/longliverec.h24 result
233 ditto images/unquickformat.h24 result
234 cd bin/ppc_10.4/;gunzip libsnd*.gz; cd ../..
235 ditto bin/ppc_10.4/*dylib* result/HD24connect.app/Contents/MacOS
236 cd bin/ppc_10.4/;gzip libsnd*; cd ../..
237# cp src/installer/starthd24connect.command result/
238 rm -rf HD24tools.dmg
239 hdiutil create -fs HFS+ -srcfolder "result/" -volname "HD24tools" HD24tools.dmg
240 rm -rf hd24tools_$(RELEASENUM)-$(PLATFORM).dmg
241 hdiutil convert -format UDZO -o hd24tools_$(RELEASENUM)-$(PLATFORM).dmg HD24tools.dmg
242
243 rm -rf HD24tools.dmg
244 rm -rf result
245
246#macrelease:
247# rm -rf RELEASE
248# rm -rf hd24_$(RELEASE_NUM)*.gz
249# mkdir RELEASE
250# mkdir RELEASE/usr
251# mkdir RELEASE/usr/local
252# mkdir RELEASE/usr/local/lib
253# find HD24connect.app -print | cpio -pvcmdB RELEASE
254# cp hd24connect RELEASE/HD24connect.app/Contents/MacOS
255# cp hd24hexview RELEASE
256# cp /usr/local/lib/libsndfile.1.0.16.dylib RELEASE/usr/local/lib
257# cd RELEASE/usr/local/lib ; \
258# ln -s libsndfile.1.0.16.dylib libsndfile.1.dylib \
259# ln -s libsndfile.1.0.16.dylib libsndfile.dylib
260# cd RELEASE ; \
261# find . -print | cpio -ovcB >../hd24_$(RELEASE_NUM)mac10.4.cpio
262# gzip hd24_$(RELEASE_NUM)mac10.4.cpio
263# cd RELEASE ; \
264# tar -cf ../hd24_$(RELEASE_NUM)mac10.4.tar .
265# gzip hd24_$(RELEASE_NUM)mac10.4.tar
266
267# ===============================================
268#
269# CODE BUILDING
270#
271# ===============================================
272hd24info: $(SRCDIR)hd24info.cpp $(BINDIR)hd24fs.o $(BINDIR)convertlib.o
273 $(CC) $(CCARGS) $(SRCDIR)hd24info.cpp $(BINDIR)memutils.o $(BINDIR)hd24fs.o $(BINDIR)hd24devicenamegenerator.o $(BINDIR)convertlib.o -o hd24info $(LIBDIRS) $(INCLUDEDIRS) $(CONSLIBS) $(CONSDEPS)
274
275hd24wavefix: $(SRCDIR)hd24wavefix.cpp $(BINDIR)convertlib.o
276 $(CC) $(CCARGS) $(SRCDIR)hd24wavefix.cpp $(BINDIR)memutils.o $(BINDIR)convertlib.o -lsndfile -o hd24wavefix $(LIBDIRS) $(INCLUDEDIRS) $(CONSLIBS)
277
278hd24towav: $(SRCDIR)hd24towav.cpp $(BINDIR)convertlib.o
279 $(CC) $(CCARGS) $(SRCDIR)hd24towav.cpp $(BINDIR)memutils.o $(BINDIR)convertlib.o -lsndfile -o hd24towav $(LIBDIRS) $(INCLUDEDIRS) $(CONSLIBS)
280
281hd24hexview: $(SRCDIR)hd24hexview.cpp $(BINDIR)hd24fs.o
282 $(CC) $(CCARGS) $(SRCDIR)hd24hexview.cpp $(BINDIR)memutils.o $(BINDIR)hd24fs.o $(BINDIR)hd24devicenamegenerator.o $(BINDIR)convertlib.o -o hd24hexview$(WINEXT) $(LIBDIRS) $(INCLUDEDIRS) $(CONSLIBS) $(CONSDEPS)
283
284$(BINDIR)Fl_Native_File_Chooser.o: $(LIB)FL/Fl_Native_File_Chooser.H $(LIB)FL/Fl_Native_File_Chooser.cxx
285 $(CC) $(CCARGS) -c $(LIB)FL/Fl_Native_File_Chooser.cxx -o $(BINDIR)Fl_Native_File_Chooser.o $(INCLUDEDIRS) $(LIBDIRS)
286
287$(BINDIR)Fl_Image_Button.o: $(LIB)FL/Fl_Image_Button.H $(LIB)FL/Fl_Image_Button.cxx
288 $(CC) $(CCARGS) -c $(LIB)FL/Fl_Image_Button.cxx -o $(BINDIR)Fl_Image_Button.o $(INCLUDEDIRS) $(LIBDIRS)
289
290$(BINDIR)Fl_Image_Repeat_Button.o: $(LIB)FL/Fl_Image_Repeat_Button.H $(LIB)FL/Fl_Image_Repeat_Button.cxx
291 $(CC) $(CCARGS) -c $(LIB)FL/Fl_Image_Repeat_Button.cxx -o $(BINDIR)Fl_Image_Repeat_Button.o $(INCLUDEDIRS) $(LIBDIRS)
292
293$(BINDIR)Fl_Image_Toggle_Button.o: $(LIB)FL/Fl_Image_Toggle_Button.H $(LIB)FL/Fl_Image_Toggle_Button.cxx
294 $(CC) $(CCARGS) -c $(LIB)FL/Fl_Image_Toggle_Button.cxx -o $(BINDIR)Fl_Image_Toggle_Button.o $(INCLUDEDIRS) $(LIBDIRS)
295
296hd24connect: $(BINDIR)WidgetPDial.o $(BINDIR)hd24connect.o $(PROGICON) $(BINDIR)Fl_Native_File_Chooser.o $(BINDIR)Fl_Image_Button.o $(BINDIR)Fl_Image_Toggle_Button.o $(BINDIR)Fl_Image_Repeat_Button.o $(BINDIR)ui_hd24connect.o $(BINDIR)hd24sndfile.o $(BINDIR)hd24transferengine.o $(BINDIR)smpte.o $(BINDIR)hd24fs.o $(BINDIR)hd24utils.o $(BINDIR)sharedlibs.o $(BINDIR)convertlib.o $(BINDIR)dialog_rename.o $(BINDIR)dialog_options.o $(BINDIR)dialog_filesize.o $(BINDIR)dialog_newsong.o $(BINDIR)dialog_newproject.o $(BINDIR)dialog_fromto.o $(BINDIR)dialog_setlocate.o $(BINDIR)dialog_setlength.o $(BINDIR)ui_help_about.o $(BINDIR)ui_recorder.o $(BINDIR)ui_mixer.o $(BINDIR)dialog_choosedevice.o $(BINDIR)ui_hd24trackchannel.o $(MOREDEPS)
297 $(CC) $(TESTLINKERFLAGS) $(CCARGS) $(BINDIR)hd24connect.o $(BINDIR)memutils.o $(BINDIR)hd24sndfile.o $(BINDIR)hd24transferengine.o $(BINDIR)WidgetPDial.o $(BINDIR)dialog_rename.o $(BINDIR)dialog_options.o $(BINDIR)dialog_filesize.o $(BINDIR)dialog_newsong.o $(BINDIR)dialog_newproject.o $(PROGICON) $(BINDIR)dialog_fromto.o $(BINDIR)dialog_choosedevice.o $(MOREDEPS) $(BINDIR)dialog_setlocate.o $(BINDIR)dialog_setlength.o $(BINDIR)ui_hd24connect.o $(BINDIR)smpte.o $(BINDIR)hd24fs.o $(BINDIR)hd24utils.o $(BINDIR)hd24devicenamegenerator.o $(BINDIR)sharedlibs.o $(BINDIR)convertlib.o $(BINDIR)ui_help_about.o $(BINDIR)ui_recorder.o $(BINDIR)ui_mixer.o $(BINDIR)Fl_Native_File_Chooser.o $(BINDIR)Fl_Image_Button.o $(BINDIR)Fl_Image_Repeat_Button.o $(BINDIR)Fl_Image_Toggle_Button.o $(BINDIR)ui_hd24trackchannel.o -o hd24connect $(INCLUDEDIRS) $(LIBDIRS) $(MORELIBS) $(UILIBS); fltk-config --post hd24connect
298
299$(BINDIR)icon.o: $(UI)resource.rc
300 windres $(UI)resource.rc $(BINDIR)icon.o
301
302$(BINDIR)convertlib.o: $(LIB)convertlib.cpp $(LIB)convertlib.h
303 $(CC) $(CCARGS) -c $(LIB)convertlib.cpp -o $(BINDIR)convertlib.o $(INCLUDEDIRS) $(LIBDIRS)
304
305$(BINDIR)sharedlibs.o: $(LIB)sharedlibs.cpp $(LIB)sharedlibs.h
306 $(CC) $(CCARGS) -c $(LIB)sharedlibs.cpp -o $(BINDIR)sharedlibs.o $(INCLUDEDIRS) $(LIBDIRS)
307
308$(BINDIR)nojack.o: $(LIB)nojack.cpp $(LIB)nojack.h
309$(BINDIR)nojack.o: $(LIB)nojack.cpp $(LIB)nojack.h
310 $(CC) $(CCARGS) -c $(LIB)nojack.cpp -o $(BINDIR)nojack.o $(INCLUDEDIRS) $(LIBDIRS)
311
312$(BINDIR)ui_hd24connect.cxx: $(UI)ui_hd24trackchannel.h $(UI)ui_hd24connect.cxx $(UI)ui_hd24connect.h $(BINDIR)dialog_rename.o $(BINDIR)dialog_options.o $(BINDIR)dialog_filesize.o $(BINDIR)dialog_newsong.o $(BINDIR)dialog_newproject.o $(BINDIR)dialog_fromto.o $(BINDIR)dialog_setlocate.o $(BINDIR)dialog_setlength.o $(BINDIR)ui_help_about.o $(BINDIR)ui_recorder.o $(BINDIR)ui_mixer.o $(BINDIR)dialog_choosedevice.o $(BINDIR)Fl_Native_File_Chooser.o
313 cat $(UI)ui_hd24connect.cxx|sed -e 's/HD24VERSION/$(RELEASENUM)/' >$(BINDIR)ui_hd24connect.cxx
314# $(CC) $(CCARGS) -E $(UI)ui_hd24connect.cxx -o $(BINDIR)ui_hd24connect.cpp $(INCLUDEDIRS) $(LIBDIRS); cat $(BINDIR)ui_hd24connect.cpp|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(BINDIR)ui_hd24connect.cxx
315
316$(BINDIR)ui_hd24connect.o: $(BINDIR)ui_hd24connect.cxx
317 $(CC) $(CCARGS) -c $(BINDIR)ui_hd24connect.cxx -o $(BINDIR)ui_hd24connect.o $(INCLUDEDIRS) $(LIBDIRS)
318
319$(BINDIR)hd24devicenamegenerator.o: $(LIB)hd24devicenamegenerator.h $(LIB)hd24devicenamegenerator.cpp $(BINDIR)convertlib.o
320 $(CC) $(CCARGS) -c $(LIB)hd24devicenamegenerator.cpp -o $(BINDIR)hd24devicenamegenerator.o $(INCLUDEDIRS) $(LIBDIRS)
321
322$(BINDIR)hd24utils.o: $(LIB)hd24utils.cpp $(LIB)hd24utils.h $(LIB)hd24project.cpp $(LIB)hd24song.cpp $(BINDIR)convertlib.o $(BINDIR)hd24devicenamegenerator.o
323 $(CC) $(CCARGS) -c $(LIB)hd24utils.cpp -o $(BINDIR)hd24utils.o $(INCLUDEDIRS) $(LIBDIRS)
324
325$(BINDIR)hd24sndfile.o: $(LIB)hd24sndfile.cpp $(LIB)hd24sndfile.h $(BINDIR)convertlib.o
326 $(CC) $(CCARGS) -c $(LIB)hd24sndfile.cpp -o $(BINDIR)hd24sndfile.o $(INCLUDEDIRS) $(LIBDIRS)
327
328$(BINDIR)hd24transferengine.o: $(LIB)hd24transferengine.cpp $(LIB)hd24transferengine.h $(LIB)hd24project.cpp $(LIB)hd24song.cpp $(BINDIR)convertlib.o $(BINDIR)ui_mixer.o
329 $(CC) $(CCARGS) -c $(LIB)hd24transferengine.cpp -o $(BINDIR)hd24transferengine.o $(INCLUDEDIRS) $(LIBDIRS)
330
331$(BINDIR)memutils.o: $(LIB)memutils.cpp $(LIB)memutils.h
332 $(CC) $(CCARGS) -c $(LIB)memutils.cpp -o $(BINDIR)memutils.o $(INCLUDEDIRS) $(LIBDIRS)
333
334$(BINDIR)smpte.o: $(LIB)smpte.cpp $(LIB)smpte.h
335 $(CC) $(CCARGS) -c $(LIB)smpte.cpp -o $(BINDIR)smpte.o $(INCLUDEDIRS) $(LIBDIRS)
336
337$(BINDIR)hd24fs.o: $(BINDIR)memutils.o $(LIB)hd24fs.cpp $(LIB)hd24fs.h $(LIB)hd24project.cpp $(LIB)hd24song.cpp $(BINDIR)convertlib.o $(BINDIR)hd24devicenamegenerator.o
338 $(CC) $(CCARGS) -c $(LIB)hd24fs.cpp -o $(BINDIR)hd24fs.o $(INCLUDEDIRS) $(LIBDIRS)
339
340$(BINDIR)ui_help_about.o: $(UI)ui_help_about.cxx
341 $(CC) $(CCARGS) -c $(UI)ui_help_about.cxx -o $(BINDIR)ui_help_about.o $(INCLUDEDIRS) $(LIBDIRS)
342
343$(BINDIR)ui_mixer.o: $(UI)ui_mixer.cxx
344 $(CC) $(CCARGS) -c $(UI)ui_mixer.cxx -o $(BINDIR)ui_mixer.o $(INCLUDEDIRS) $(LIBDIRS)
345
346$(BINDIR)ui_recorder.o: $(UI)ui_recorder.cxx
347 $(CC) $(CCARGS) -c $(UI)ui_recorder.cxx -o $(BINDIR)ui_recorder.o $(INCLUDEDIRS) $(LIBDIRS)
348
349$(BINDIR)ui_hd24trackchannel.o: $(UI)ui_hd24trackchannel.cxx
350 $(CC) $(CCARGS) -c $(UI)ui_hd24trackchannel.cxx -o $(BINDIR)ui_hd24trackchannel.o $(INCLUDEDIRS) $(LIBDIRS)
351
352$(BINDIR)dialog_fromhd24.o: $(UI)dialog_fromhd24.cxx $(UI)dialog_fromhd24.h
353 $(CC) $(CCARGS) -c $(UI)dialog_fromhd24.cxx -o $(BINDIR)dialog_fromhd24.o $(INCLUDEDIRS) $(LIBDIRS)
354
355$(BINDIR)dialog_rename.o: $(UI)dialog_rename.cxx
356 $(CC) $(CCARGS) -c $(UI)dialog_rename.cxx -o $(BINDIR)dialog_rename.o $(INCLUDEDIRS) $(LIBDIRS)
357
358$(BINDIR)dialog_options.o: $(UI)dialog_options.cxx
359 $(CC) $(CCARGS) -c $(UI)dialog_options.cxx -o $(BINDIR)dialog_options.o $(INCLUDEDIRS) $(LIBDIRS)
360
361$(BINDIR)dialog_choosedevice.o: $(UI)dialog_choosedevice.cxx
362 $(CC) $(CCARGS) -c $(UI)dialog_choosedevice.cxx -o $(BINDIR)dialog_choosedevice.o $(INCLUDEDIRS) $(LIBDIRS)
363
364$(BINDIR)dialog_setlength.o: $(UI)dialog_setlength.cxx
365 $(CC) $(CCARGS) -c $(UI)dialog_setlength.cxx -o $(BINDIR)dialog_setlength.o $(INCLUDEDIRS) $(LIBDIRS)
366
367$(BINDIR)dialog_filesize.o: $(UI)dialog_filesize.cxx
368 $(CC) $(CCARGS) -c $(UI)dialog_filesize.cxx -o $(BINDIR)dialog_filesize.o $(INCLUDEDIRS) $(LIBDIRS)
369
370$(BINDIR)dialog_newsong.o: $(UI)dialog_newsong.cxx
371 $(CC) $(CCARGS) -c $(UI)dialog_newsong.cxx -o $(BINDIR)dialog_newsong.o $(INCLUDEDIRS) $(LIBDIRS)
372
373$(UI)dialog_newsong.h: $(UI)dialog_newsong.fl
374 fluid -c $(UI)dialog_newsong.fl; \
375 mv dialog_newsong.h $(UI); \
376 mv dialog_newsong.cxx $(UI)
377
378$(UI)dialog_newsong.cxx: $(UI)dialog_newsong.fl
379 fluid -c $(UI)dialog_newsong.fl; \
380 mv dialog_newsong.h $(UI); \
381 mv dialog_newsong.cxx $(UI)
382
383$(BINDIR)dialog_newproject.o: $(UI)dialog_newproject.cxx
384 $(CC) $(CCARGS) -c $(UI)dialog_newproject.cxx -o $(BINDIR)dialog_newproject.o $(INCLUDEDIRS) $(LIBDIRS)
385
386$(UI)dialog_newproject.h: $(UI)dialog_newproject.fl
387 fluid -c $(UI)dialog_newproject.fl; \
388 mv dialog_newproject.h $(UI); \
389 mv dialog_newproject.cxx $(UI)
390
391$(UI)dialog_newproject.cxx: $(UI)dialog_newproject.fl
392 fluid -c $(UI)dialog_newproject.fl; \
393 mv dialog_newproject.h $(UI); \
394 mv dialog_newproject.cxx $(UI)
395
396$(BINDIR)dialog_setlocate.o: $(UI)dialog_setlocate.cxx
397 $(CC) $(CCARGS) -c $(UI)dialog_setlocate.cxx -o $(BINDIR)dialog_setlocate.o $(INCLUDEDIRS) $(LIBDIRS)
398
399$(BINDIR)dialog_fromto.o: $(UI)dialog_fromto.cxx
400 $(CC) $(CCARGS) -c $(UI)dialog_fromto.cxx -o $(BINDIR)dialog_fromto.o $(INCLUDEDIRS) $(LIBDIRS)
401
402$(BINDIR)hd24connect.o: $(UI)hd24connect.cpp $(UI)selftest.cpp $(BINDIR)ui_hd24connect.o $(BINDIR)hd24fs.o $(BINDIR)hd24utils.o
403 $(CC) $(CCARGS) -c $(UI)hd24connect.cpp -o $(BINDIR)hd24connect.o $(INCLUDEDIRS) $(LIBDIRS)
404
405$(UI)ui_hd24connect.h: $(UI)ui_hd24connect.fl $(UI)dialog_fromto.cxx $(UI)dialog_choosedevice.h
406 fluid -c $(UI)ui_hd24connect.fl; \
407 cat ui_hd24connect.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(UI)ui_hd24connect.cxx; \
408 mv ui_hd24connect.h $(UI); \
409 rm ui_hd24connect.cxx
410
411$(UI)ui_help_about.cxx: $(UI)ui_help_about.fl
412 fluid -c $(UI)ui_help_about.fl; \
413 cat ui_help_about.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(UI)ui_help_about.cxx; \
414 mv ui_help_about.h $(UI); \
415 rm ui_help_about.cxx
416
417$(UI)ui_recorder.cxx: $(UI)ui_recorder.fl $(UI)ui_hd24connect.h $(UI)ui_mixer.cxx
418 fluid -c $(UI)ui_recorder.fl; \
419 cat ui_recorder.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(UI)ui_recorder.cxx; \
420 mv ui_recorder.h $(UI); \
421 rm ui_recorder.cxx
422
423$(UI)ui_mixer.cxx: $(UI)ui_mixer.fl $(UI)ui_hd24connect.h
424 fluid -c $(UI)ui_mixer.fl; \
425 cat ui_mixer.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(UI)ui_mixer.cxx; \
426 mv ui_mixer.h $(UI); \
427 rm ui_mixer.cxx
428
429$(UI)ui_hd24trackchannel.h: $(UI)ui_hd24trackchannel.fl $(UI)ui_hd24connect.h
430 fluid -c $(UI)ui_hd24trackchannel.fl; \
431 cat ui_hd24trackchannel.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(UI)ui_hd24trackchannel.cxx; \
432 mv ui_hd24trackchannel.h $(UI); \
433 rm ui_hd24trackchannel.cxx
434
435$(UI)ui_hd24trackchannel.cxx: $(UI)ui_hd24trackchannel.fl $(UI)ui_hd24connect.h
436 fluid -c $(UI)ui_hd24trackchannel.fl; \
437 cat ui_hd24trackchannel.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(UI)ui_hd24trackchannel.cxx; \
438 mv ui_hd24trackchannel.h $(UI); \
439 rm ui_hd24trackchannel.cxx
440
441$(UI)dialog_filesize.h: $(UI)dialog_filesize.fl
442 fluid -c $(UI)dialog_filesize.fl; \
443 mv dialog_filesize.h $(UI); \
444 mv dialog_filesize.cxx $(UI)
445
446$(UI)dialog_filesize.cxx: $(UI)dialog_filesize.fl
447 fluid -c $(UI)dialog_filesize.fl; \
448 mv dialog_filesize.h $(UI); \
449 mv dialog_filesize.cxx $(UI)
450
451$(UI)dialog_setlength.cxx: $(UI)dialog_setlength.fl
452 fluid -c $(UI)dialog_setlength.fl; \
453 mv dialog_setlength.h $(UI); \
454 mv dialog_setlength.cxx $(UI)
455
456$(UI)dialog_setlocate.cxx: $(UI)dialog_setlocate.fl
457 fluid -c $(UI)dialog_setlocate.fl; \
458 mv dialog_setlocate.h $(UI); \
459 mv dialog_setlocate.cxx $(UI)
460
461$(UI)dialog_fromhd24.h: $(UI)dialog_fromhd24.fl
462 fluid -c $(UI)dialog_fromhd24.fl; \
463 mv dialog_fromhd24.h $(UI); \
464 mv dialog_fromhd24.cxx $(UI)
465
466$(UI)dialog_fromhd24.cxx: $(UI)dialog_fromhd24.fl
467 fluid -c $(UI)dialog_fromhd24.fl; \
468 mv dialog_fromhd24.h $(UI); \
469 mv dialog_fromhd24.cxx $(UI)
470
471$(UI)dialog_rename.cxx: $(UI)dialog_rename.fl
472 fluid -c $(UI)dialog_rename.fl; \
473 mv dialog_rename.h $(UI); \
474 mv dialog_rename.cxx $(UI)
475
476$(UI)dialog_options.cxx: $(UI)dialog_options.fl
477 fluid -c $(UI)dialog_options.fl; \
478 mv dialog_options.h $(UI); \
479 mv dialog_options.cxx $(UI)
480
481$(UI)dialog_fromto.cxx: $(UI)dialog_fromto.fl
482 fluid -c $(UI)dialog_fromto.fl; \
483 mv dialog_fromto.h $(UI); \
484 mv dialog_fromto.cxx $(UI)
485
486$(UI)ui_hd24connect.cxx: $(UI)ui_hd24connect.fl
487 fluid -c $(UI)ui_hd24connect.fl; \
488 cat ui_hd24connect.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(UI)ui_hd24connect.cxx; \
489 mv ui_hd24connect.h $(UI); \
490 rm ui_hd24connect.cxx
491
492$(UI)dialog_choosedevice.cxx: $(UI)dialog_choosedevice.fl
493 fluid -c $(UI)dialog_choosedevice.fl; \
494 mv dialog_choosedevice.h $(UI); \
495 mv dialog_choosedevice.cxx $(UI)
496
497$(UI)dialog_choosedevice.h: $(UI)dialog_choosedevice.fl
498 fluid -c $(UI)dialog_choosedevice.fl; \
499 mv dialog_choosedevice.h $(UI); \
500 mv dialog_choosedevice.cxx $(UI)
501
502
503$(BINDIR)WidgetPDial.o: $(UI)WidgetPDial.cxx $(UI)WidgetPDial.h
504 $(CC) $(CCARGS) -c $(UI)WidgetPDial.cxx -o $(BINDIR)WidgetPDial.o $(INCLUDEDIRS) $(LIBDIRS)
505
506$(UI)WidgetPDial.h: $(UI)WidgetPDial.fl
507 fluid -c $(UI)WidgetPDial.fl; mv WidgetPDial.h $(UI); mv WidgetPDial.cc $(UI)WidgetPDial.cxx
508
509$(UI)WidgetPDial.cxx: $(UI)WidgetPDial.fl
510 fluid -c $(UI)WidgetPDial.fl; mv WidgetPDial.h $(UI); mv WidgetPDial.cc $(UI)WidgetPDial.cxx
511
512$(UI)WidgetPDial.fl: $(LIB)FL/WidgetPDial.fl
513 cp $(LIB)FL/WidgetPDial.fl $(UI)WidgetPDial.fl
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..ec642eb
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,122 @@
1What is the HD24tools suite?
2============================
3
4The HD24tools suite is a simple software suite that allows
5Linux users to read disks of their Alesis HD24 ADAT recorders.
6Developed in a cross-platform manner, it currently also compiles
7for Windows and Mac, providing users with a free alternative to
8Alesis' offering.
9
10Open source policy
11==================
12
13The software was written as an independent effort. It contains
14no code by Alesis, and is not supported by Alesis.
15
16In the development of this software, no Alesis-confidential
17information was used. Instead, the necessary parts were
18reverse-engineered, which is legal in the Netherlands.
19
20However, as a result, the correctness nor completeness of the
21file system specifications can not be guaranteed.
22Therefore, you are reminded that you use this software at your
23own risk.
24
25AnalogFilter Class
26==================
27The author of ZynAddSubFX has granted me permission to use his
28AnalogFilter class in HD24tools in closed-source form:
29
30"You may use the AnalogFilter class, but please acknowledge the
31copyright of the AnalogFilter class (and tell that I give you a
32specific permission to do so, to avoid confusion about GPL 2
33license)"
34
35This permission is no longer relevant because
361. I never ended up using this class; and
372. HD24tools is now open-source.
38
39General operation
40=================
41Most of the programs automatically detect and access the presence
42of HD24 disks.
43
44If multiple HD24 disks are present, the first HD24 disk found will
45be used by default. The tools search for HD24 disks in the following
46order:
47
48/dev/hda,/dev/hdb,/dev/hdc,/dev/hdd
49/dev/sda,/dev/sdb,/dev/sdc,/dev/sdd
50
51This should find most HD24 disks, regardless of the way that they
52are connected to your PC (be it using a VIPowER drive bay, USB
53connection or firewire interface). Should you be using another
54device as disk, you can use the --dev=x option to point to
55HD24 device with device path x.
56
57To be able to use the tools, the user running the programs must
58have direct read access to the disk device. It is possible to
59re-assign access rights of the disk device each time, but it
60is probably more practical to update your group permissions and/or
61add an entry to your /etc/fstab, for instance:
62
63/dev/hdc none auto devmode=0664 0 0
64
65(I have not extensively tested this for optimal security).
66You can ignore any boot time complaints about linux not being able
67to mount the drive; it will try all the file system types it
68knows but of course doesn't know how to work with HD24 drives.
69
70When using an internal drivebay, keep in mind that it may not
71support hot-swapping. You probably need to switch off power to
72exchange drives. In other words, if you fry your motherboard,
73don't complain to me.
74
75The HD24 only accepts drives configured as master. As such, if
76you use an internal drive bay, you probably end up with the HD24
77disk as /dev/hdc.
78
79The programs
80============
81hd24hexview A debug-style hex viewer for (binary files and) hd24 disks.
82
83 Without command line arguments, accesses the first
84 found hd24 disk in hex mode.
85
86 Type ? in the program for help.
87
88 Call the program with --dev=/dev/hdc to use
89 /dev/hdc as hd24 disk. If this disk is not
90 recognized as hd24 disk, use the --force option
91 to view the disk contents anyway. Use --expert
92 to enable write mode.
93
94 All other programs that directly access the disk
95 support the --dev=x option but not the --force
96 option.
97
98hd24connect A program to download files from HD24 disks.
99
100hd24info A program that displays some info about the
101 hd24 disk. Mostly useful to detect the presence
102 or absence of hd24 disks.
103 (obsolete)
104
105hd24wavefix A program that attempts to fix corrupted audio that
106 sometimes occurs in long live recordings, usually when
107 recording to very high capacity drives.
108
109genbackupscript.pl
110
111 A perl script to generate a script for hd24hexview
112 which will create a backup of the file system information
113 to the end of the drive. Now obsolete; this functionality
114 is now built-in into the HD24 library.
115
116syx2bin A program that attempts to decode the 7 bit HD24 .syx file
117 to a 8 bit binary file.
118
119hd24towav.cpp A program that converts raw hd24 data to wav files.
120 (obsolete)
121
122
diff --git a/bin/linux/libsndfile.a b/bin/linux/libsndfile.a
new file mode 100644
index 0000000..eccdf14
--- /dev/null
+++ b/bin/linux/libsndfile.a
Binary files differ
diff --git a/bin/linux/libsndfile.so b/bin/linux/libsndfile.so
new file mode 100755
index 0000000..002351f
--- /dev/null
+++ b/bin/linux/libsndfile.so
Binary files differ
diff --git a/bin/linux/libsndfile.so.1 b/bin/linux/libsndfile.so.1
new file mode 100755
index 0000000..002351f
--- /dev/null
+++ b/bin/linux/libsndfile.so.1
Binary files differ
diff --git a/bin/linux/libsndfile.so.1.0.17 b/bin/linux/libsndfile.so.1.0.17
new file mode 100755
index 0000000..002351f
--- /dev/null
+++ b/bin/linux/libsndfile.so.1.0.17
Binary files differ
diff --git a/bin/ppc_10.3/libsndfile.1.0.16.dylib b/bin/ppc_10.3/libsndfile.1.0.16.dylib
new file mode 100755
index 0000000..656c8a6
--- /dev/null
+++ b/bin/ppc_10.3/libsndfile.1.0.16.dylib
Binary files differ
diff --git a/bin/ppc_10.3/libsndfile.1.dylib b/bin/ppc_10.3/libsndfile.1.dylib
new file mode 100755
index 0000000..656c8a6
--- /dev/null
+++ b/bin/ppc_10.3/libsndfile.1.dylib
Binary files differ
diff --git a/bin/ppc_10.3/libsndfile.dylib b/bin/ppc_10.3/libsndfile.dylib
new file mode 100755
index 0000000..656c8a6
--- /dev/null
+++ b/bin/ppc_10.3/libsndfile.dylib
Binary files differ
diff --git a/bin/ppc_10.4/libportaudio.a b/bin/ppc_10.4/libportaudio.a
new file mode 100644
index 0000000..fad24ca
--- /dev/null
+++ b/bin/ppc_10.4/libportaudio.a
Binary files differ
diff --git a/bin/ppc_10.4/libportaudio.dylib b/bin/ppc_10.4/libportaudio.dylib
new file mode 100644
index 0000000..7124677
--- /dev/null
+++ b/bin/ppc_10.4/libportaudio.dylib
Binary files differ
diff --git a/bin/ppc_10.4/libportaudio.dylib.0.0.18 b/bin/ppc_10.4/libportaudio.dylib.0.0.18
new file mode 100644
index 0000000..3c36dda
--- /dev/null
+++ b/bin/ppc_10.4/libportaudio.dylib.0.0.18
Binary files differ
diff --git a/bin/ppc_10.4/libsndfile.1.dylib.gz b/bin/ppc_10.4/libsndfile.1.dylib.gz
new file mode 100755
index 0000000..1663a01
--- /dev/null
+++ b/bin/ppc_10.4/libsndfile.1.dylib.gz
Binary files differ
diff --git a/bin/win32/libsndfile-1.dll b/bin/win32/libsndfile-1.dll
new file mode 100755
index 0000000..31cfd6c
--- /dev/null
+++ b/bin/win32/libsndfile-1.dll
Binary files differ
diff --git a/configure b/configure
new file mode 100755
index 0000000..836c6e0
--- /dev/null
+++ b/configure
@@ -0,0 +1,120 @@
1#!/bin/bash
2
3#######################################################################
4# OS Setup Routines
5#######################################################################
6setup_win32()
7{
8 echo "Build environment... Microsoft Windows";
9 BUILD_FOR='Win32'
10 PORTAUDIO_MAKEOPTS='-lwinmm'
11 MORELIBS="$MORELIBS -lwinmm -mwindows"
12# MOREDEPS="$MOREDEPS \$(BINDIR)nojack.o"
13}
14
15
16setup_linux_gnu()
17{
18 echo "Build environment... GNU/Linux";
19 BUILD_FOR='LinuxGNU'
20 PORTAUDIO_MAKEOPTS='-pthread'
21}
22
23
24setup_linux_win32()
25{
26 echo "Build environment... Microsoft Windows (Linux)"
27 BUILD_FOR='Win32Linux'
28 PORTAUDIO_MAKEOPTS='-lwinmm'
29 GCC='i586-mingw32msvc-gcc'
30}
31
32
33setup_darwin()
34{
35 echo "Build environment... Macintosh OS X";
36 BUILD_FOR='Darwin'
37 JACK_MAKEOPTS='-L/sw/lib -I/sw/include'
38 PORTAUDIO_MAKEOPTS='-L/sw/lib -I/sw/include'
39 export CFLAGS="-no-cpp-precomp -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk"
40 export CXXFLAGS="-no-cpp-precomp -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk"
41}
42
43
44#######################################################################
45# Library Tests
46#######################################################################
47find_fltk()
48{
49 TEST=`fltk-config --version | awk \
50 'BEGIN {FS="=";version="Unavailable"} 1==1 {version=$1} END {print version}'`
51
52 if [ $? == 0 ]; then
53 echo "Searching for FLTK... found $TEST"
54 TMPCCARGS="$TMPCCARGS -DLIBFLTK=\"$TEST\""
55 else
56 echo "Searching for FLTK... not found"
57 echo "Can't continue."
58 exit 1
59 fi
60}
61
62
63#######################################################################
64# Main Configure Routine
65#######################################################################
66main()
67{
68 [[ -e Makefile ]] && make clean
69
70 MORELIBS='' # Extra libraries
71 MOREDEPS='' # Extra dependencies
72 BUILD_FOR='' # Build architecture
73 GCC='gcc' # GCC Command (different if building Win32 on Linux)
74 TMPCCARGS='' # Extra CC Arguments
75
76 # Check for Windows
77 if [[ $BUILD_FOR == '' && \
78 ($WINDIR == "C:\\WINNT" || $WINDIR == "C:\\WINDOWS") ]];
79 then
80 setup_win32
81 fi
82
83 # Check for Linux or Win32 building on Linux
84 if [[ $BUILD_FOR == '' && \
85 `if [ -e /proc/version ]; then cat /proc/version | grep Linux; fi` != "" ]]
86 then
87 if [ "$1" = "--os=win32" ]; then
88 setup_linux_win32
89 else
90 setup_linux_gnu
91 fi
92 fi
93
94 # Check for Mac OS X
95 if [[ $BUILD_FOR == '' && \
96 ("`echo $version|grep powerpc-apple-darwin`" != "" || \
97 "`echo $OSTYPE|grep darwin`" != "") ]]
98 then
99 setup_darwin $1
100 fi
101
102 # Check for Essential Libraries
103 find_fltk
104
105 # Create the Makefile
106 echo "BUILD_ARCH=$BUILD_FOR" > Makefile
107 echo "MORELIBS=$MORELIBS" >> Makefile
108 echo "MOREDEPS=$MOREDEPS" >> Makefile
109 echo "TMPCCARGS=$TMPCCARGS" >> Makefile
110
111 if [[ $1 == '--with-universal' ]]; then
112 echo "UNIVERSAL=true" >> Makefile
113 fi
114
115 cat Makefile.in >> Makefile
116
117 echo -e "\nConfiguration complete. If all looked OK, now run make.";
118}
119
120main $1
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..a2149a4
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,41 @@
1#
2# This is the start of an autotools build system. It's still very much a work
3# in-progress and can't be reliably used yet. ~mcrute
4#
5m4_define(HD24TOOLS_VERSION, 1.0)
6
7AC_PREREQ(2.61)
8AC_INIT(hd24tools, HD24TOOLS_VERSION, http://hd24tools.com/)
9
10# Checks for programs.
11AC_PROG_CXX
12AC_PROG_CC
13
14# Checks for libraries.
15AC_SEARCH_LIBS([XpmCreatePixmapFromData], [Xpm])
16AC_SEARCH_LIBS([sf_command], [sndfile])
17AC_SEARCH_LIBS([jack_client_new], [jack])
18AC_SEARCH_LIBS([Pa_Initialize], [portaudio])
19
20AC_HEADER_DIRENT
21AC_HEADER_STDC
22AC_CHECK_HEADERS([FL/Fl.H arpa/inet.h fcntl.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/statvfs.h unistd.h])
23
24AC_HEADER_STDBOOL
25AC_C_CONST
26AC_TYPE_SIZE_T
27AC_TYPE_SSIZE_T
28AC_STRUCT_TM
29
30AC_FUNC_CLOSEDIR_VOID
31AC_FUNC_MALLOC
32AC_FUNC_MEMCMP
33AC_FUNC_STAT
34AC_FUNC_STRFTIME
35AC_FUNC_STRTOD
36AC_CHECK_FUNCS([floor getcwd memchr memset mkdir strchr strdup strtol])
37AC_CONFIG_FILES([Makefile])
38
39AC_OUTPUT
40
41# vim:syntax=m4:
diff --git a/doc/ADATFS.txt b/doc/ADATFS.txt
new file mode 100644
index 0000000..e373690
--- /dev/null
+++ b/doc/ADATFS.txt
@@ -0,0 +1,529 @@
1HD24 ADAT file system format
2
3Reading ADAT HD24 disks
4-----------------------
5In the ADAT FST file system, the part of the file system
6that contains directory and song info is grouped in
732-bit words. When read on a regular PC, each group of
84 bytes will appear reversed. As such, when
9a sector contains a string 'TADATSF ', we should read this
10as 'ADAT FST'. In this document, we will assume that
11doing the byte swapping needed to properly read the sectors
12has already been done.
13
14It should be noted that the actual audio data has not
15undergone such byte swapping. As such, WAV data
16retrieved from the HD24 by FTP is stored in the same
17byte order as the data on disk.
18
19The sector size used on HD24 disks is 512 bytes.
20ADAT FST boasts disk support for disks up to 2 Terabyte.
21This is achieved by using 32-bit pointers that point to
22sector numbers. We will refer to these pointers as
23sectorpointers.
24
25Writing ADAT HD24 disks
26-----------------------
27Writing HD24 disks is slightly tricky, because FST
28filesystems contain backup copies of file system
29sectors to help guarantee data consistency.
30As a result, when we make an alteration to only the
31first copy of the file system structure on disk, the
32disk is considered inconsistent and the backup copy will
33be written back by the HD24 recorder at the next use.
34
35The backup data is stored at the end of the disk,
36in block-reverse order.
37The original order is something like this:
38
39block 0
40 sector 0
41block 1
42 sector 1
43block 2
44 sectors 2,3,4
45block 3
46 sectors 5,6,7,8,9,10,11,12,13,14,15,16,17,18,19
47block 4-102
48 1 sector of project info
49block 103-
50 song info block (2 sectors)
51 song allocation info block (5 sectors)
52
53The backup blocks are stored in reverse order,
54however each backup block maintains the original
55sector ordering. That is,
56
57block 0 has a backup at sector (end-0)
58 (where end=the last sector on disk)
59
60block 1 has a backup at sector (end-1)
61
62block 2, sectors 2,3,4 are backed up at sectors
63 end-4, end-3, end-2, respectively;
64
65block 3, sectors 5,6,7,8,9,10,11,12,13,14,15,16,17,18,19
66 are backed up at sectors
67 end-19,end-18,end-17,end-16,end-15,...end-5,
68 respectively.
69
70The validity of a block is indicated by a checksum which
71is stored in the last 4 bytes of a block (bytes 0x1FC,
720x1FD, 0x1FE, 0x1FF of the last sector of a block).
73
74The value of the checksum is such that sum of all 32-bit
75words in the block (which may span several sectors) is 0.
76When writing a block, we must make sure that the resulting
77checksum of the block adds up to 0 again.
78
79A second check refers to bytes 0x1f8-0x1fb of the last
80sector of a block. Bytes 0x1F8 and 0x1F9 contain the
81least significant 16 bit of the sector number at which
82the block starts. Thus, a project block which contains
831 sector and starts on sector 0x14 will contain the
84values 0x14, 0x00 on bytes 0x1f8 and 0x1f9; a song entry
852 sectors long, and ending on sector 0x78 will contain
86the byte values 0x77, 0x00 on offset 0x1f8 and 0x1f9,
87respectively (because the song entry starts on sector
880x77). Bytes 0x1FA and 0x1FB of the last sector of the
89block contain the bit-inverted value of 0x1F8 and 0x1F9**.
90
91** This paragraph assumes the sector is not byte-swapped
92as described in the first paragraph of the document.
93
94When a block is not equal to its backup, the checksum
95of both is validated. If one is valid and the other is
96not, the valid copy is written over the invalid copy.
97
98General ADAT FST layout
99-----------------------
100The general ADAT FST layout is as follows:
101
102-----------------------------------------------------------
103Sector 0 / Offset 0000:0000h
104Superblock, identifies drive as an ADAT FST drive.
105Size=512 bytes/0200h
106-----------------------------------------------------------
107Sector 1 / Offset 0000:0200h
108Drive info
109Size=512 bytes/0200h
110-----------------------------------------------------------
111Offset 0000:0400h
1123 sectors, Song Entry Usage Table
113Size=600h
114-----------------------------------------------------------
115Offset 0800h
11615 sectors, Drive Usage Table
117size=1e00h
118-----------------------------------------------------------
119 / Offset 0000:2800h
120Project info, 1 sector (512 bytes) per project entry
121Size: 99*200h=c600h
122-----------------------------------------------------------
123 / Offset 0000:ee00h
124Song info, 7 sectors (3584 bytes) per song entry
125-----------------------------------------------------------
126 Undo info
127-----------------------------------------------------------
128 Audio data
129-----------------------------------------------------------
130 File system backup
131-----------------------------------------------------------
132
133
134Superblock layout
135-----------------
136Offset 0-0fh Header line:
137 Offset 0 'ADAT FST'
138 Offset 8 Version number, e.g. '110 '
139 Offset 12 signature bytes: 55h, aah, cch, 33h
140Offset 10h-13h Size of audio block (0x480)
141Offset 14h-17h Number of audio blocks per allocation cluster
142Offset 18h-1fh 0 ?
143Offset 20h-23h 0 ?
144Offset 24h-27h 0 ?
145Offset 28h-2bh 1 ? sectors in superblock?
146Offset 2ch-2fh 1 ? sectors in drive info block
147
148Offset 30h-33h 2 ? sectornum of song entry usage table?
149Offset 34h-37h 3 ? sectors in song entry usage table?
150
151Offset 38h-3bh 5 ? sectornum containing allocation info?
152Offset 3ch-3fh 15/0fh - Number of sectors in allocation table?
153
154Offset 40h-43h 042fh=1071 ?? (anything to do with undo buffer?)
155 --
156 On 1.2gb drive this formats as 0x20 00 00 00
157 --
158Offset 44h-47h Number of free audio clusters on disk
159Offset 48h-4bh SectorPointer to project info
160Offset 4ch-4fh 1
161Offset 50h-53h Max allowed no. of projects?
162Offset 54h-57h Max allowed no. of songs per project?
163Offset 58h-5bh SectorPointer to first song info entry
164
165Offset 5ch-5fh 2 (sectors of song info entry w/o alloc info?)
166Offset 60h-63h 5 (sectors of alloc info per song entry?)
167Offset 64h-67h 7 (number of sectors that song info entries are apart?)
168Offset 68h-6bh current number of songs on disk
169Offset 78h-7bh 041fh (number of audio blocks reserved for undo buffer).
170 1055 audio blocks=72 track minutes at 48 khz
171 Multiply by contents of offset 14h-17h for number of sectors
172 in undo buffer.
173
174Offset 7ch-7fh Sector pointer to audio data block on disk (0x1397f6).
175Offset 80h-83h 32-bit word
176 number almost as big as number of sectors on disk
177
178 This number is related to that on offset 0084h and
179 always seems to have a difference of 0x14a46B to
180 the end of the disk.
181
182 0084h 0080h
183 40 gb disk:
184 0x04c92d7f - 0x04B48914 = 0x14A46B
185 120gb disk:
186 0x0df94baf - 0x0de4a744 = 0x14A46B
187
188 Perhaps the value is the number of allocatable sectors
189 on disk?
190 (1397f6 used in the beginning; an undo buffer is not
191 needed at the end of the drive)
192
193 0x10C75 used for actual filesystem.?
194 0x1397f6 (first data sector on drive) - (0x41f(size of undo buffer in audio blocks) * 0x480(size of audio block in sectors)) = 0x10C76
195 first data sector is not part of FS so this makes sense.
196
197offset 84h-87h 32-bit word, highest sector number on disk.
198 A backup of the first sector can be found here.
199offset 88h-1F7 (empty, zero - reserved for future use?)
200offset 1f8-1FF Checksum information.
201
202Drive info layout
203-----------------
204Sector 1
205Offset 0 8 byte drive name (for compatibility with
206 older ADAT FST versions), should be considered
207 obsolete. Replaced by name at offset 01bh.
208Offset 8-9 null bytes
209Offset 0ah-0bh 2 more bytes for drive name. Should be considered
210 obsolete
211Offset 10h SectorPointer to last active project.
212offset 20h List of 32-bit sector pointers to all projects.
213Offset 01b8h 64-byte drive name. Null-byte terminated
214 when shorter than 64 chars.
215
216Song Entry Usage Table
217----------------------
218FST 1.10 allows for 99 projects of 99 songs each, giving for
2199801 song entries. Each song entry is not necessarily pre-
220allocated to any given project; song entry 0 may belong to
221project 0, while song entry 1 may belong to another project.
222The Song Entry Usage Table provides a quick way to look up
223the next free song entry without having to go through all
224projects to see which song entries are in use.
225
226Each bit in the Song Entry Usage Table represents a song.
227When 0, the song entry is not in use; when 1, it is.
228
229Drive Usage Table
230-----------------
231Each bit in the Drive Usage Table represents a cluster. When 0, the
232cluster is free; when 1, the cluster is in use.
23332-bit words are filled one by one, least-significant bit first,
234until the entire word has the value 0xFFFFFFFF. In other words, the
235table starting with the following words have the meaning as described:
236
2370x1 contains 1 bit on -> first cluster allocated
2380x3 contains 2 bits on -> first 2 clusters allocated
2390x1f contains 5 bits on -> first 5 clusters allocated
2400x1ff contains 9 bits on -> first 9 clusters allocated.
241
242At the end of the drive usage table, some space seems to be reserved,
243possibly representing the backup of the file system info, or something
244along those lines. The last 32-bit word of the Drive Usage Table is a
245checksum. When all 32-bit words in the entire Drive Usage Table are
246summed, the result must be 0.
247
248Project info
249----------------------
250The project info consists of (by default) 99 entries of 512 bytes each.
251The actual number of projects is contained by the superblock.
252
253100 project entries would be 0xc800 bytes.
254As projects are numbered starting at 01, a maximum of 99 projects
255is possible, giving for 0xc600 bytes.
256
257How to distinguish between an empty project and an unused project entry?
258Answer: Sector 1 (Drive info) contains the project list.
259
260Projects not mentioned in the drive info project list are empty projects.
261
262Each project entry has the following layout:
263
264Offset 0 8-byte project name (obsolete)
265Offset 8 4-byte (2 bytes of which are partial project name too)
266offset 0ch-0fh Number of songs in use in project
267offset 10h-19bh Song info table (a list of 32-bit pointers to the
268 initial sectors of song info). Length of table should be
269 396 bytes for 99 songs per project.
270 First entry in the table is the last accessed song.
271 Zero char means unused entry.
272Offset 01b8h 64-byte project name. Null-byte terminated if project
273 name is less than 64 bytes long.
274
275Song info table
276---------------
277The song info table is part of a project entry. It is a list of 32-bit
278pointers to sectors containing song info.
279
280Song info
281------------------------
282Song info starts at disk offset 0xee00h, or at
283sector 119 (the 120th sector on disk) (depending on
284info in superblock).
285
286Each song entry has a length of 2 sectors and is immediately
287followed by 5 sectors of file allocation info.
288
289Locate points/loops and track slip info is included in the song
290entries.
291
292Offset 00h-03h 32-bit number indicating no. of audio blocks in song
293Offset 04h-07h ?0
294Offset 08h-0bh 32-bit number related to audio track interlacing.
295
296 1/512th of the number of samples per interlace block
297 before the audio switches to the next track.
298
299 Value of this field equals Cluster size/(tracks*3).
300
301Offset 0ch-0fh 32-bit number related to audio track interlacing.
302
303 number of sectors per interlace block
304 before the audio switches to the next track.
305
306 Value of this field equals audio block size
307 /no. of tracks.
308 Default audio block size is defined in superblock
309 (0x480 sectors)
310
311 An audio block size of 0x480 and 2 tracks gives a
312 block size of 0x240h sectors or 0x48000 bytes
313 (=294912 bytes).
314
315Offset 10h-13h Status flags????????????????????
316 Offset 0x12h bit 0x10h -> write protect?????
317
318Offset 28h-2Fh First 8 bytes of song name.
319 (Maintained for compatibility
320 with FST before 1.10-
321 Obsoleted by long filenames
322 at offset 3b8h)
323
324Offset 30h ?
325
326Offset 31h Number of physical tracks used by song.
327
328 Note:
329 The HD24 has a high sample rate
330 mode (88200 and 96000 samples per
331 second, respectively).
332
333 In high sample rate mode, two
334 physical tracks are used for each
335 logical track.
336
337 That is, a 12-track song in high
338 sample rate mode will use 24 tracks
339 on the machine. The number 24 is
340 then what is indicated.
341
342 This allows interlacing samples between
343 tracks for compatibility with systems
344 running at half the sample rate.
345 In high sample rate mode, the track layout
346 is:
347 physical track 0-1 -> samples of logical track 1
348 physical track 2-3 -> samples of logical track 2
349 physical track 4-5 -> samples of logical track 3
350 .. and so on. Even numbered samples (0,....)
351 are on even numbered tracks.
352
353Offset 32h-33h Two more filename characters for short filename,
354 used in obsolete FST 1.0 standard.
355
356Offset 34h-36h Sample rate in samples/second
357
358 Typical values are:
359
360 00h ach 44h -> 44100 Samples/sec
361 00h bbh 80b -> 48000 Samples/sec
362 01h 58h 88h -> 88200 Samoles/sec
363 01h 77h 00h -> 96000 Samples/sec
364
365Offset 37h Bit depth (18h or 24 by default)
366
367offset 38h-3bh Unsigned 32-bit number containing
368 number of samples in song.
369
370 For high sample rates, 2 tracks
371 are used for each sample;
372 therefore, a song that according
373 to this 32-bit number contains 44100
374 samples has the same duration at both
375 44100 and 88200 kHz.
376
377offset 3ch Write protect byte.
378
379 This byte contains 8 bits (0-7, where
380 7 is the most significant bit and 0 the
381 least significant bit. In other words
382 bit 7 has value 128, bit 0 has value 1)
383
384 Bit 2 is on when song is write protected
385 (value of the byte is 0x4 then), off when
386 song is write enabled.
387
388offset 58h-B7h Track slip info for track 1-24
389
390 Track slip is measured in number of samples.
391 E.g. for a song recorded at 48 khz, a value
392 of 480 decimal (0x1e0) means 1/100 second
393 (10 ms) of track slip.
394 Track slip is stored as a signed 32-bit number.
395 Valid values for the HD24 are -170..170 msec
396
397Offset 0b8h-1e3h Locate point block
398
399Offset 3b8h-3e7h Full song name, max 64 bytes;
400 terminated by null byte when less
401 than 64 bytes
402
403Offset 400h-???? File allocation info (see below)
404
405Locate point block
406------------------
407The locate point block consists of 24 locate point entries.s
408
409Locate point entry
410------------------
411Each locate point entry has the following layout:
412Offset 0-3 32-bit time code
413 The time code represents the sample number
414 within the song.
415Offset 4-11 The 8-byte locate point name
416
417Locate point 0 indicates the relative time offset of the
418song. This is usually 0, but may be set to other values for
419tape transfers.
420
421The locate point is a 32-bit unsigned integer which contains the
422sample number within the song. In other words, in a 44.1 khz
423song, the locate point 0:0:1:0 (hours/minutes/seconds/frames)
424is encoded as the number 44100. Thus, the locate point furthest
425in the song is 2^32=4294967296 samples.
426This is enough for 44.1khz songs with a length of 27 hours.
427
428File allocation info
429====================
430The file allocation info consists of file allocation entries.
431Each file allocation entry has the following format:
432
433Offset 00h-03h Starting sector number for audio block
434Offset 04h-07h Number of audio blocks in allocation block
435
436In a valid song, the the 32-bit word on offset 0 of the song
437info equals the total sum of the number of audio blocks in the
438file allocation info.
439
440In my disk image, I see songs that had been previously deleted;
441the song length in audio blocks is zero for these. This also
442goes for songs that have no audio data yet.
443
444Audio data layout
445=================
446The audio data of a FST file system is stored in a raw, uncompressed
447format. Audio data that consists of multiple channels is interlaced
448blockwise (as opposed to sample-by-sample interlacing).
449
450The data is stored as 24-bit signed little endian integer data.
451
452The typical audio block size as indicated in the superblock is
4530x480 sectors. In stereo audio, each subblock is then 1/2 audio blocks
454or 0x240 sectors per channel.
455
456As the number of tracks increases, the block size per track decreases
457proportionally.
458
459The default audio block size of 0x480 sectors lets itself be divided
460into 2,4,6,8,12,16,24 tracks (with a sample size of 24 bit). Each channel
461then takes up 0x240, 0x120, 0xc0, 0x90, 0x60, 0x48, 0x30 sectors,
462respectively assuming 0x480 blocks per sector. In high sample rate
463modes, channels are paired to accomodate for the doubled sample rate.
464This is why in high sample rate mode a max of 12 channels are possible,
465while the maximum song length is still over 27 hours on 88.2 kHz.
466
467
468Not yet accounted for in this document
469======================================
470
471How the undo buffer is used (however, this is not relevant because the
472undo buffer is cleared after each power off. It might as well exist
473in RAM only).
474
475How pitch info is stored in the songs
476auto play
477auto rtn
478auto rec
479
480HD24tools extensions to FST
481===========================
482An extension is proposed where a song on a HD24 drive is used as data
483area, to store non-audio information associated with a song or project.
484This would allow HD24 owners to store track notes, mix settings,
485protools projects and so on along with their songs.
486
487A degree of compatibility with the HD24 is desired; although the HD24
488will not be able to use the information, it should also not corrupt it.
489
490The HD24 does not offer unique file names; moreover, the position of a
491file is not constant within the FS. As a result, songs have no unique
492identifier that allows other data to be associated with them.
493
494It is proposed to use bytes 0x3a0-0x3bf of each song entry as unique
495identifier. Testing shows that the HD24 recorder does not touch these
496bytes, even after a scandisk operation. Moreover, when a song is copied
497to another drive, these bytes are copied over as well.
498
499A single HD24 song would provide ample storage space for most purposes.
500Additionally, by using a single song only, the negative impact to the
501end user is minimal as no users have ever been registered to actually
502create 99 project of 99 songs. To prevent the HD24 from corrupting the
503contents of the song, it can be created as 0-track song; previous
504experiments have shown that the track count is flexible. Having a song
505marked as 0 track prevents the HD24 from arming tracks or playing back
506audio from the song, and will give a user some feedback about the nature
507of the song, without causing the HD24 to claim that the song is corrupt.
508A track count of 0 survives a scandisk command, and it seems that the
509HD24 permits copying such songs to other drives.
510
511A possible way to store data in the song is to have the data song
512contain a FAT file system. The advantage of the FAT file system is
513that it is well documented, and probably there will be library code
514available that will ease the implementation of an embedded FAT
515system on HD24 drives.
516
517The root directory of the file system shall contain a 'songdata'
518dir. This data directory shall contain a subdirectory named after the
519ID of each song. Of course the file names need to be long enough; if
520this is not possible, a map file may be created to contain mappings
521from song ID to songname subdirectory ID.
522
523Data placed in the appropriate songname directory is automatically
524associated with the song. Should we so desire, we can also create a
525'projdata' directory.
526
527By keeping the songdata directory structure flat, songs can be moved
528across projects without losing their associated files.
529
diff --git a/doc/COMPILING.txt b/doc/COMPILING.txt
new file mode 100644
index 0000000..f0abf5e
--- /dev/null
+++ b/doc/COMPILING.txt
@@ -0,0 +1,39 @@
1COMPILING HD24TOOLS
2
3Instructions for Linux (preferably Debian/Ubuntu based):
4
5Get the source code from svn on HD24tools.com
6
7sudo apt-get install fluid libfltk1.1 libfltk1.1-dev libsndfile1 libsndfile1-dev libportaudio0 libportaudio0-dev libjack0 libjack0.100.0-0 libjack0.100.0-0-dev libjack-dev libxft2 libxft-dev libxinerama libxinerama-dev
8
9Note: You may still need to install libflac.
10
11make clean
12./configure
13make
14
15mkdir ~/HD24tools
16cp hd24connect ~/HD24tools/
17cp hd24hexview ~/HD24tools/
18cp hd24info ~/HD24tools/
19cp hd24towav ~/HD24tools/
20cp hd24wavefix ~/HD24tools/
21ln -s /usr/lib/libsndfile.so.1 ~/HD24tools/
22ln -s /usr/lib/libportaudio.so ~/HD24tools/
23ln -s /usr/lib/libjack.so ~/HD24tools/
24
25For HD24tools to detect the drives (when being run as normal user),
26normal users need to have sufficient permissions to work with the
27drive device.
28
29To find out which drive device it is, run HD24connect as root,
30and select File->Recovery->Select device...
31
32This will show you the current device, which is the device
33that needs its permissions set.
34
35You can probably gain device permissions by adding your
36regular user to the proper group, making your user the
37owner of the device or by setting the device permissions
38in /etc/fstab.
39
diff --git a/doc/DEVELOPING.txt b/doc/DEVELOPING.txt
new file mode 100644
index 0000000..6c91747
--- /dev/null
+++ b/doc/DEVELOPING.txt
@@ -0,0 +1,270 @@
1Developing HD24tools
2====================
3
4To start on development of hd24tools, here are a few tips to get you started.
5
6Development environment
7=======================
8You will want libsndfile, libportaudio and the Fast Light Toolkit FLTK to be
9present on your system. On Linux you will also want the Jack Audio Connection
10Kit (optionally on Mac as well). The targeted compiler is gcc.
11
12On Windows, development is based on a MSYS/MinGW environment.
13
14On Mac, XCode is needed, as well as portaudio, libsndfile and FLTK.
15
16Configuring and building
17========================
18Configuration is auto-detected by running
19
20 ./configure
21
22Building is done with
23
24 make
25
26Installing is optional. You may want to run the following as root:
27
28 make install
29
30which will install common binaries to /usr/bin. More interestingly,
31you can run
32
33 make installer
34
35to create the installer for the current platform. Finally, with
36
37 make clean
38
39you can work from a clean configuration. The configure script also
40calls make clean.
41
42Cross-compiling
43===============
44Cross compiling is highly experimental and will probably fail for
45most purposes. On linux, you can say
46
47 ./configure os=win32
48
49which will attempt to create windows .exe files. However, until
50now only hd24hexview.exe has been successfully built on Linux.
51
52
53
54./configure
55make
56
57Setup
58=====
59During configuration, the set of libraries, make files etc to
60use is decided by the files in the setup directory. The file
61Makefile.in which is located there contains the release number
62which must be bumped up for every version. Unless you build
63official releases, please add your name to the release number
64or make your personal releases otherwise distinguishable from
65official releases.
66
67To perform library detection etc, there are files called
68Makefile.setup.<platform> in the setup directory. These are
69called with various targets to figure out if libraries exist.
70
71Unless porting to a new platform or adding external libraries,
72you will probably rarely need to change most of the setup
73scripts.
74
75File system documentation
76=========================
77Reverse-engineered information about the ADAT FST file system
78can be found in doc/ADATFS.txt. Probably this file contains
79enough info to not only allow reading ADAT drives but also to
80write them. The biggest obstacle in writing ADAT drives so
81far has been to get an accurate LBA sector count of non-
82formatted drives on all operating systems. Especially Windows
83seems to lack a reliable way to obtain this information.
84(Multiplying sectors/cylinders/heads isn't LBA accurate,
85any other way known to me is limited to a specific version
86of Windows). If you want to contribute to the ADATFS.txt
87file, figure out how the FST undo buffers work. To keep this
88software free, DO NOT obtain information from Alesis about
89FST which might pollute the project with non-free
90information.
91
92The HD24 library
93================
94Directory src/lib contains the HD24 library (and other
95library source code).
96
97common.cxx - some common string manipulation functions
98convertlib.cpp/.h - conversion between various data types
99countsectors.cpp - library to calculate drive size
100hd24connect.ico - HD24connect Icon for Windows
101hd24devicenamegenerator.cpp/.h -
102 Library to generate device names that could be
103 HD24 drives; contains alternatives for all
104 supported OS platforms
105hd24fs.cpp/.h
106 Library containing definition for HD24 file system
107 object.
108 Each file system contains drive info;
109 The drive info contains 1 or more projects;
110 Each project contains 0 or more songs;
111 Each song contains 25 locate points (START
112 +locate point 1-24) and track slip info for
113 each track.
114
115 Including hd24fs.h is sufficient to have access to
116 all of this.
117
118hd24project.cpp/.h
119 Library containing hd24 project decoding.
120
121hd24song.cpp/.h
122 Library containing hd24 song decoding;
123 this includes functionality to read audio, set
124 the song cursor, etc.
125
126hd24utils.cpp/.h
127 Library that contains useful routines, such as
128 printing the hd24 catalog, dumping a header,
129 saving a drive image etc. that do not belong in
130 the file system decoding library,
131 but that multiple programs might have a use for.
132
133nojack.cpp/.h
134 Dummy library to replace jack on windows and other
135 platforms in case it is not present.
136
137src/lib/FL/
138 Native OS file dialog support.
139
140INSTALLER GENERATOR
141===================
142
143The code for the installer generator is found in
144src/installer.
145
146Essentially, it takes the compiled binaries of hd24tools,
147and converts those to hexdumps in c-source (using an
148application called bin2c). This c source is then compiled
149and will be able to re-create the original binary
150files.
151
152While no complex registry magic is needed, this is
153sufficient for simple installations and probably less work
154to figure out than other solutions.
155
156This was originally intended to create install wizards for Mac,
157but ended up being used for Windows only. Mac users seem
158comfortable enough with the install-free .dmg images that they
159are presented with.
160
161The install wizard itself is basically implemented as a state
162machine.
163
164The installer for Linux installation could still be made a bit
165smoother, specifically in the libraries department- the right
166libraries are not always available at the right locations yet.
167
168THE ACTUAL HD24TOOLS
169====================
170
171Some tools only have a console/command line version. They are:
172
173hd24hexview a hex editor
174hd24wavefix a program that attempts to recover bit-distorted
175 audio to something remotely usable again
176hd24towav a program that converts raw 24 bit hd24 audio to
177 wav files
178syx2bin a program that converts the HD24 OS .syx files
179 to binary (not sure if the resulting binaries
180 are valid)
181hd24info a program that prints some info about the hd24
182 drives present in the system
183
184And finally, there is the graphical flagship program of the suite
185hd24connect. To start development, it would be recommended to
186understand the library, then the command line utilities first.
187
188The command line tools are in src/ whereas hd24connect is in
189src/frontend.
190
191Originally I intended hd24connect to have a frontend (GUI) and
192a backend. As it turned out, the whole thing ended up in the
193frontend. If you feel like creating a nice backend so that the
194frontend *really* *only* contains GUI stuff, feel free. Sorry.
195
196The entry point of hd24connect is src/frontend/hd24connect.cpp-
197this calls and opens the GUI.
198
199The main entrance for the GUI is in fluid file ui_hd24connect.fl
200(you *really* should use the 'fluid' user interface editor that
201comes with fltk to maintain the .fl files). Method make_window
202in class UserInterface starts it all.
203
204TEST SUITE
205==========
206There is a directory test/ which should at some point contain
207regression tests for hd24tools. To make it easier to perform
208such tests, it would need to be possible to control hd24tools
209entirely in batch-mode (using MIDI for this is may be a
210possibile way).
211
212DOCUMENTATION
213=============
214
215The .pdf documentation may be slightly outdated. If you wish
216to update it, you can do so with OpenOffice Writer.
217
218TASKS
219=====
220If you want to contribute, here are some things left to do:
221
222- Write support (realtime vs copy mode)
223
224 Save altered drive/project/song info
225
226 Write support can initially be tested on
227 drive image files.
228
229 Phase A1: Only overwriting existing audio, but
230 not allocating new space (copy mode)
231
232 Phase A2: Allocating new space (copy mode)
233
234 Phase B1: realtime write mode with JACK support
235
236- Wave preview
237
238 This would have to be awfully smart to be able to display
239 waves with zero active waiting time and without utilizing
240 peak files. Use information such as screen width reso-
241 lution to limit the amount of data that needs to be read
242 from disk. Probably adding a special read mode in the
243 library could help support this.
244
245- Figure out how to build (fat) Mac binaries with or without
246 Mac (but preferrably without requiring both intel and ppc
247 to build a release that works on either platform)
248
249- Figuring out a way to write wav header info/session
250 notes to HD24 songs, while maintaining HD24 compatibility
251
252- Adding MIDI support to the library (MMC, MTC)
253
254- Sync to real HD24 recorders?
255
256- Special HD24tools distro containing ReWire support to
257 allow streaming audio directly to protools/cubase?
258
259- Use real LRC to control HD24tools?
260
261- Figure out OS binary checksum algorithm
262
263- Create a test suite
264
265- Figure out how the HD24 performs Undo administration on
266 the file system level
267
268- Improve realtime read mode performance for audio streaming
269
270
diff --git a/doc/HARDWARE.txt b/doc/HARDWARE.txt
new file mode 100644
index 0000000..8d4809e
--- /dev/null
+++ b/doc/HARDWARE.txt
@@ -0,0 +1,34 @@
1Inside the HD24
2
3The HD24 is powered by a Motorola Coldfire
4
5MCF5206EFT54
6K36J
7QAJ0435)
8
9The Ethernet chip is a CrystalLan CS8900A-CQ3,
10a 10Base-T LAN chip.
11
12There is an empty, 26 pin port labelled 'Motorola BDM Port'.
13Motorola BDM stands for Motorola Background Debug Module,
14so we might speculate that this port allows us to perform
15debugging on the HD24 as it is running.
16
17There are to IC41LV16256 chips in the HD24: according to the
18data sheets, they are 256kx16 bit Dynamic RAM with EDO page mode,
19giving the HD24 a total of 1 megabyte of RAM.
20
21There is an ALTERA ACEX EP1K30QC208-2
22FPGA (Field Programmable Gate Array).
23
24There is a Texas Instruments AHCT16541
25AHCT16541 devices are noninverting 16-bit
26buffers composed of two 8-bit sections with
27separate output-enable signals. (possibly
28used for communication to displays?)
29
30Analog Devices ADSP 21065L KS-264
31A digital signal processor.
32
33
34
diff --git a/doc/LIVERECOVERY.txt b/doc/LIVERECOVERY.txt
new file mode 100644
index 0000000..94782a0
--- /dev/null
+++ b/doc/LIVERECOVERY.txt
@@ -0,0 +1,25 @@
1Figuring out on which sector the next recording should start
2(or where a crashed live recording starts)
3============================================================
41. Find the start offset of the drive usage table, e.g. 0xa00
52. Find the suspected start offset of the live recording
6 in said table. This is the offset of the first 32-bit word
7 that is 0.
8 For instance the found offset is 0xe74
93. This means the recording starts on cluster
10 0xe74-0xa00=0x474
114. The superblock states the number of audio blocks per cluster,
12 offset 0x14. For the sake of this example, lets assume 9
13 audio blocks per cluster. The size of each audio block is on
14 offset 0x10, usually 0x480.
155. The first audio sector is mentioned on the superblock on
16 offset 0x7e. In most cases it is 0x1397f6.
176. Each byte in the drive usage table represents 8 clusters.
187. The audio should then start on
19 0x1397f6 + (0x480*9*8*(0xe74-0xa00)) = sector 0x5b667f6.
20
21---------------
22The other way around- calculating offset from sector number:
23(0x02e427f6 - 0x1397f6) / 0x480 / clusters /8 + 0xa00
24
25
diff --git a/doc/MAILING.txt b/doc/MAILING.txt
new file mode 100644
index 0000000..20e9de3
--- /dev/null
+++ b/doc/MAILING.txt
@@ -0,0 +1,28 @@
1Subject: HD24tools 0.9.0beta for Win32 released
2Hello,
3
4HD24tools version 0.9.0beta has been made available for
5the following platforms:
6
7- Linux (i386)
8- Windows (All versions)
9
10Mac releases are expected to be released soon.
11
12The most important new features in this release are
13- Preliminary write support
14- New tabbed GUI
15- Several usability enhancements
16
17The release notes for this and previous release notes can be viewed on
18http://ringbreak.dnd.utwente.nl/~mrjb/hd24tools/RELEASE.txt
19
20As always, the release can be downloaded from:
21http://ringbreak.dnd.utwente.nl/~mrjb/hd24tools/download.html
22
23Should you encounter any problems with this release,
24please let me know.
25
26Best,
27Marc
28
diff --git a/doc/RELEASE.txt b/doc/RELEASE.txt
new file mode 100644
index 0000000..ac0d723
--- /dev/null
+++ b/doc/RELEASE.txt
@@ -0,0 +1,474 @@
1HD24Connect revision history and roadmap
2========================================
3
4Implemented features are set in the past tense. A version is complete when all
5planned versions are implemented. Until then, sub-versions are used, e.g.
60.3.1 already may have some (but not all) 0.4 features.
7
8This document ends with suggested features, but is in reverse chronological
9order otherwise, and as such starts with features planned for the next
10release.
11
12Current status is somewhere in the middle, search for the text
13'CURRENTLY IN PROGRESS' to find out what is being done right now.
14
15Version 1.1.0 => CURRENTLY IN PROGRESS
16
17- Added some unit tests to perform automated, scripted testing
18- Added frequency/gain display to mixer
19- Performed code cleanup:
20 - Moved recorder, mixer and HD24->PC file transfers
21 to their own modules
22 - permit various interfaces (X, Cocoa, Curses, etc)
23 - possibly permit recording macros?
24 - permit multi-window interface (show transport/time/mixer
25 simultaneously) and allow resizing those windows
26- Implement batch transports
27- Implement realtime recording
28- Auto-detect feedback loops!
29- Change to multi-window interface to allow viewing multiple tabs at once
30 (for example both recorder and mixer at same time)
31- Implement MIDI control/control surfaces
32 - Control other MIDI devices with HD24tools
33 - Control HD24tools with other MIDI devices
34- Implement LADSPA support for mixer FX
35 - Add default GUI for common effects, allow them
36 to be controlled through control surfaces.
37- Implement keyboardless operation
38- Add wave viewer for easier selection of export range
39- Add functionality to allow changing song naming convention for export
40- Simultaneous dual drive support. Benefits:
41 * allow copying songs between drives
42 * copying songs/projects from/to drive images
43- Add drive images that are found in drive image dir to
44 drive image dropdown to make it easier to switch between
45 real and virtual drives
46- Implement functionality to signal falling out of record
47 mode if needed (when drive is full, etc)
48- Create an interesting demo drive image to
49 allow people to play around with it
50 (low prio: people can download examples from raw-tracks.com
51 at a $5 fee)
52
53Version 1.0.0 => Will remain in alpha
54
55- Made source code available to the general public
56- Added recovery feature to deal with a specific class of
57 'unexpected end of song' error on fragmented drives
58- Added block checksum calculation to library
59- Implemented saving of changed project name/song name to disk
60- Added code for cluster allocation
61- Added code for converting orphan clusters to allocation entries
62- Compiling framework was changed to allow smoother Mac compiles
63- Added mixer tab with save/load mixer settings functionality
64- Finished up restructuring of mixer to make it work again
65- Added save functionality to allow renaming drive
66- Made detection of corrupted drives smoother to prevent need for
67 http://ringbreak.dnd.utwente.nl/~mrjb/hd24tools/drivenumber.html
68- Added Check for 'forbidden characters' in filenames
69 \ / : * ? " < > |
70 (HD24 accepts these but can have unpredictable effects on
71 OS side)
72- Added allocating functionality to allow lengthening songs
73 automatically during transfer
74- Altered layout of drive catalog to fit longer song names
75 and to have a bit larger margin on the left for printing
76- Added functionality to allow 1-click toggle between
77 sample rates of 44.1 <=> 48 kHz and 88.2 <=> 96 kHz
78 (toggling between lower/higher sample rates is not possible
79 without conversion as higher sample rates use 2 recording
80 tracks per channel).
81- Added dialog for simpler 'headerless' live recording recovery
82- Implemented initial headerless live recovery scheme
83- Made headerless live recording recovery read-only
84- Added functionality to create empty drive images
85- Created dialog for setting song parameters
86- Implemented Mixer JACK support
87- Implemented framework for smarter library loading.
88 This should allow Mac (and even Windows) users to have
89 JACK functionality, and will no longer require Mac
90 users to startup HD24connect by running an AppleScript.
91- ... and made library smart loading even smarter by letting
92 it look in the program directory first, the PATH dir next,
93 and all usual library directories next. This should result
94 in library loading that Just Works in most cases and
95 will allow JACK support on all platforms.
96- Wrote documentation explaining how to build HD24tools
97 from source (Linux, 64-bit Athlon)
98- Added functionality to create projects
99- Added functionality to create songs (incl. superblock
100 song count update)
101- Made sure changes in song/drive/project names also reflect
102 properly in FST 1.00 drives
103- Added functionality to automatically pre-record silence
104 in songs on creating them
105- Added functionality to update song usage list after
106 song creation
107- Automatically select song as 'default' after creation
108- Implemented reload of drive list/catalog/project list/song list
109 after major write operations
110- User interface settings reloaded as appropriate after writing
111 to drive
112- Added options dialog to allow (among other things) specifying
113 a filename pattern for file transfers to PC
114- Made write-protect checkbox work
115- Added drive format functionality
116- Added functionality to delete songs
117- Added functionality to delete projects
118- Made 'bypass' button for mixer work
119- Added timeout-style messages to alpha display
120- Implemented functionality to display song information
121 on alpha display
122- Implemented functionality for sorting songs inside a project.
123 This allows easily reordering songs by renaming them.
124- Implemented SMPTE timecode striping- for now limited to
125 30fps nondrop starting at 00:00:00.00.
126 May not work on sample rates other than 48kHz. In fact,
127 it may not work at all.
128- Made sure superblock is updated with number of free clusters
129 after song transfer to HD24 drive/creation of new song
130- Implemented write-protect to prevent writing to drives when
131 working with header files.
132- Implemented functionality to reduce number of sectors read
133 when transferring fewer tracks. The expected performance
134 win is not very big as the number of drive seeks is about
135 the same, but the weight of the added logic is minimal.
136 Perhaps on some systems the difference is noticable. YMMV.
137- Implemented .wav writing without libsndfile. If it is missing,
138 you'll still be able to transfer such files to your computer.
139- Made sure write functionality is disabled for drives found
140 not to be valid HD24 drives (due to corruption, or perhaps
141 they're simply OS drives which we DEFINITELY don't want to
142 overwrite)
143- Implemented locate point saving
144- Implemented (preliminary) transfer-time mixing of tracks
145- Made sure song/project are made default after selecting them
146- Fixed a non critical bug where closing the program during
147 playback caused a crash.
148
149TODO: Bugs to fix:
150
151- After quickformat of a drive, catalog and related screens are
152 not updated.
153
154TO DO: Testing and packaging:
155
156- Fixme: update all of drive info page on refresh
157 (What's missing?)
158- Make sure that 'new folder' button works properly on
159 all platforms! (Fixed on Windows, TO DO on mac)
160- Distribute Mac version as Universal Binary
161- Finally get .aif, .sd2 and .dig/.sd to work properly!
162- Check all FIXME and TODO comments in code
163- Get 16-bit export to work (low priority)
164- Documentation
165
166Version 0.9.0
167
168- Implemented tabbed interface
169- Added functionality to export drive images
170- Added time stamp to catalog
171- Added drive catalog display to drive inforrmation
172- Changed default time display to 30 frames per second instead of 1/100 sec
173
174- Added the 'Recorder' with various new features
175- Proper solo/mute buttons instead of solo/mute by channel selection
176- Track arm buttons
177- 24-channel display faithfully emulating what the HD24 would show
178- Peak modes: No peak hold, momentary peak hold, continuous peak hold
179- Added locate slider to rapidly jump to any point in the song
180- Added punch in/out locate points
181- Added visual clue to transport controls showing that clicking 'set'
182 can set locate points
183- Added input monitoring (mainly Linux)
184- Added dropdown to map stereo inputs to channel pairs in various ways
185- Fancy 7-segment LED display
186- Equally fancy info display
187- Fancy, bigger graphical buttons with LED for transport control
188- Fixed a clipping bug in portaudio playback (playback only)
189
190- Added signal detection to track selection in transfer tab
191- Added dropdown to allow a flexible custom size limit for exported files
192- Added dropdown to stamp songs with a different sample rate
193
194- Added tab for transfer back to HD24
195- Added functionality that permits selecting many files at once
196- Added functionality to automatically spread multi-track files
197 across several HD24 tracks
198- Added functionality to automatically mix multi-track files to mono
199- Added functionality to allow erasing tracks
200- Added functionality to allow moving tracks (including track action)
201 up or down
202- Added functionality to clear filenames from tracks
203- Added functionality to overwrite existing audio with audio from a file.
204 Many file formats are supported (subject to what is supported by
205 libsndfile).
206- SD2 file format support (does this work now?)
207- Create new folder from file browse dialog (does this work now?)
208
209
210Version 0.8.2
211
212- Hardened the software in some places to be more crash-resistant
213 in handling corrupt drives
214- Some compatibility enhancements
215- Fixed a bug in the calculation of the total number of bytes to export,
216 which caused the auto-split popup not to be displayed in some cases.
217
218Version 0.8.1
219
220- Fixed bug that caused auto-split popup to always appear for long recordings,
221 even if only a small fragment was being exported.
222
223Version 0.8.0
224
225- Printing disk contents on paper and file
226- Entirely replaced export engine for faster exports
227- Created OS native installers.
228- Allow transferring multiple songs at once (song choice 'All Songs')
229- Added possibility to export to stereo and multi-track files.
230
231Version 0.7
232
233- This never-released version adds high samplerate support.
234
235Version 0.6.2
236
237- Fixed a bug that caused the Windows version to lock up when loading a header file
238- Initial release for MacOS/X 10.4
239
240Version 0.6.1
241
242- Fixed a bug in the drive name generation in Windows
243
244Version 0.6
245
246- Initial Macintosh OS/X port. Still flaky due to interesting behavior of packages that HD24connect depends on.
247- Relabeled button "Transfer to PC" as "Transfer to Mac" for OS/X version.
248- Fixed bug that cleared surface of cancel button during transfers.
249- Added warning dialog to improve user friendliness when no HD24 drive is detected on program startup
250- Added menu option 'File/Detect HD24 drives' to allow re-scanning for drives after program startup.
251- Project directory browser now uses OS native file dialog.
252- Added menu option to allow creating header files from within hd24connect
253- Removed portaudio dependency (this has no visible impact).
254- Added Estimated Time of Arrival in transfers
255- Removed dependency on command line options to enable recovery features
256- Added application (desktop) icon for Windows
257- Allow exporting to more different file formats (currently WAV and AIFF)
258- Altered file naming for export
259- Cleaned up code that deals with drive name generation
260- Version control is now in place, allowing multiple people to work
261 on the project at the same time (Welcome, Randy!)
262
263Version 0.5
264
265- Added --force feature to allow using hd24 disks with invalid MBR.
266- Added --header feature which allows to use a fixed header file along with
267 a corrupt disk. This permits us to recover audio without need to modify
268 data on the corrupted disk.
269- Added portaudio playback. For the Windows version this means that audio
270 preview is now supported, while under Linux the Jack Audio Connection Kit
271 is no longer required for audio preview.
272- Fixed a bug in Linux audio preview. This minor bug affected exactly
273 1 user (me).
274- Added dialog to allow renaming drives, projects and songs (in memory only)
275- Altered project handling to more easily allow in-memory edits of projects
276
277Version 0.4
278
279- Fixed a minor bug with the file write caching.
280- Added a button to allow the user to interrupt a transfer.
281- Fixed flakyness in audio playback
282- Added dialog to allow manually setting locate points
283- Fix bug which causes windows version not to display song names
284- Added feature to allow setting loop start/end during playback
285- Implemented export to wav (for now, instead of raw) using libsndfile
286- Implemented basic loop mode for audio playback.
287
288Version 0.3
289
290- Added file write caching to speed up export under Windows.
291- Added direct playing under Linux (still flaky)
292- Altered library to resolve issue with STL string memory leaks
293
294Version 0.2
295
296- Added support for locate points.
297- Added backwards export.
298- Initial windows version.
299
300Version 0.1
301
302- First workable version.
303
304HD24hexview revision history and roadmap
305========================================
306
307Future
308
309- Verify/Fix any remaining issues with 4 GB limit on Windows
310- Correctly determine drive size
311- Allow multi-sector paste (from file).
312
313Version 1.4beta
314
315- Replaced code for windows drive size detection.
316
317Version 1.3beta
318
319- Added expert mode as safety switch to prevent accidentally writing to disk.
320- In expert mode, added a big fat warning for writing to the default boot
321 disk (/dev/hda or \\.\PHYSICALDRIVE0) and a (not so big & fat, but still)
322 warning for writing to other devices.
323
324Version 1.2beta
325
326- Added d-<hex> feature to dump sector <hex> counting from end of disk
327 This allows dumping the last sector from disk without having to figure
328 out the number of sectors based on brand and model of the disk.
329 Unfortunately, this does not work properly yet for Windows devices.
330
331Version 1.1beta
332
333- Fixed a bug in windows version that required output file to already exist
334 before writing
335- Added single-sector checksum (no multi-sector checksum yet)
336
337Version 1.0beta
338
339- Implemented compare
340- Implemented write offset
341
342Version 0.3
343
344- Implemented edit and write back of sectors
345- Implemented single-sector paste
346- Ported to Windows
347- Resolved a 4 GB issue with windows version
348- Allowed using files as devices
349
350Version 0.2
351
352- Implemented support for setting blocks
353- Resolved 4 gigabyte limitation for linux
354- Implemented scan
355- Implemented write to file
356
357Version 0.1
358- Implemented code to autodetect HD24 disks
359- Implemented feature to navigate disks with +/-/o
360
361========================================================
362Version x.x
363
364Spare ideas/suggested future features:
365
366- Allow exporting audio based on a 'guide track'. If a nonempty audio track has been exported, after which the disk has gotten corrupted, this audio track can be used to find back the other tracks without allocation information.
367
368 Will not be implemented anytime soon; this scenario is too
369 rare. Also, should recovery be needed, other ways exist to do so.
370
371- Allow the program to use installed audio encoders to
372 encode to mp3/flac/etc
373
374- Time line/draggable export locators
375
376 Proposed is a graphical display to allow
377 visually setting locate points for export.
378 Alternatively, a 'scrub editor' style display would be
379 workable.
380 While interesting, it would be rather time consuming
381 to build such a time line. For now, a draggable slider
382 is made available to ease the pain a bit.
383
384- Check available drive size before export
385
386 I'm not sure if I already implemented this. Obviously,
387 it is a required feature.
388
389- Allow transferring multiple projects at once
390 (project choice 'All projects')
391
392 Will probably be implemented at some point, but
393 custom song naming convention is then required first.
394
395- Allow automatic deletion of files when transfer is interrupted
396
397- Normalizing audio as it is being exported
398
399 This will require analyzing the entire export range
400 prior to export (possibly more, if the export is a
401 single song of an entire live performance; it is likely
402 that we'd want to normalize the whole performance
403 equally.
404
405- Allow exporting to different bit depths
406- MIDI control (both controlling HD24tools via MIDI or
407 let HD24tools control HD24 recorder via MIDI).
408
409 The benefit of allowing HD24tools control via MIDI
410 is that frequently requested functionality that the
411 HD24 does not support is a possibility; for instance,
412 the HD24 does not allow selecting songs via MIDI,
413 whereas such implementation in HD24tools would be
414 a fairly simple matter once it is MIDI enabled.
415 Someone also mentioned that possibily a recording
416 log could be kept by HD24tools when connected to
417 a HD24 via MIDI by simply keeping track of record
418 events. Unfortunately the HD24 does not send MIDI
419 for track record enable, even though it supports
420 track arming via MIDI (the good news is that some
421 MIDI functionality is supported even though the
422 HD24 itself does not send out MIDI for those actions).
423
424- Storing metadata on HD24 drives
425
426 There are some possibilities for this. One way is
427 to create a song contaning (for instance) a FAT
428 file system, and using some unused space in the
429 song entries to allow entries in that FAT file
430 system to uniquely point to them; this would allow
431 storing song-unique info (such as track data, etc)
432 in that file system.
433
434- Locate points in directory listing
435
436 This would make the catalog file a fair bit longer.
437 As such it would have to be an option that could
438 be turned on/off.
439
440- Virtual BRC application
441
442 This would be limited to whatever MMC supports.
443
444- Copying projects
445- Batch transfer
446- One click drive backup
447
448 These all come down to the same thing: find a
449 way to not require user intervention while
450 transferring large amounts of data.
451 Perhaps a 2-click drive backup (with the possibility
452 to edit the batch before export) is more useful than
453 a 1-click backup.
454 The main benefit (not having to wait actively while
455 audio is being transferred) is the same.
456
457- Calculate approx. occupied drive space per song, and add
458 to catalog.
459
460- Display currently selected song/project on other tabs as
461 well
462 - current song is now displayed on alpha display.
463
464- Allow different UIs (proposed is command line interface,
465 non-X interface, Cocoa interface, ...)
466
467- Control surface support, to allow using MIDI-enabled
468 consoles to control the HD24tools mixer/recorder
469
470- Add Vista tip to manual (regarding admin account for write
471 support)
472 Also add this info:
473 http://tech.groups.yahoo.com/group/hd24/message/12102
474
diff --git a/doc/SYXformat.txt b/doc/SYXformat.txt
new file mode 100644
index 0000000..9c02ccf
--- /dev/null
+++ b/doc/SYXformat.txt
@@ -0,0 +1,22 @@
1SYX file format
2===============
3The SYX file format packs every 7 8-bit bytes of a binary file
4into 8 7-bit bytes, which allows for a MIDI compatible file.
5These files can be converted to true binary files using the
6hd24syx2bin utility.
7
8Once converted, the format seems to be as follows:
9
10byte 0x00-0x07: string 'HD24CODE'
11byte 0x08-0x0b: unknown (checksum?)
12byte 0x0c-0x0f: version number string (e.g. "1.20")
13byte 0x10-0x13: 32-bit word, value 0
14byte 0x14-0x1b: Release date string (MM/DD/YY)
15byte 0x1c-0x1f: 32-bit word, value 0
16byte 0x20-0x27: Build time (hh:mm:ss)
17byte 0x28-0x2b: 32-bit word, value 0
18byte 0x2c-0x2f: binary file length in byte.
19 for version 1.20, file length is
20 712736 so bytes 0x2c-0x2f are
21 0xae020 or 0x00, 0x0a, 0xe0, 0x20
22
diff --git a/doc/TESTPLAN.txt b/doc/TESTPLAN.txt
new file mode 100644
index 0000000..ceb4849
--- /dev/null
+++ b/doc/TESTPLAN.txt
@@ -0,0 +1,130 @@
1Testplan for HD24tools
2
3Hexview
4- startup without HD24 drive connected
5- startup with HD24 connected
6- startup with --dev option (dev=drive image file, dev=device file, dev=normal file): use either clean image or image know to have problems (unexpected end
7of song, corrupt header, etc)
8- startup with --dev and --force
9- Specific to hexview: d-1 (sectorcount relative to end of disk)
10 How much time does the detection take under windows?
11
12HD24connect:
13- startup without HD24 drive connected
14- startup with 1 HD24 drive connected
15- startup with multiple HD24 drives connected
16- startup with --dev option (device node and image file, respectively)
17- ... ditto, AND with/without an HD24 drive connected
18- startup with both --dev en --force options
19- As above, but by selecting these options from the GUI
20- And again. Any irregularities?
21- Irregularities with drives/images containing:
22 0, 1, more projects? 99 projects?
23- Irregularities with projects containing
24 0, 1, more songs? 99 songs?
25- Irregularities when selecting songs with:
26 0 length?
27 0 tracks? (is this possible?)
28- Irregularities when selecting option '--All songs--' ?
29- Irregularities on renaming drive/project/song?
30- Does the 'new folder' button work while browsing the project directory?
31
32Exporting:
33- HD24connect should detect when the exportdirectory does not (or no longer)
34 exist when the export transfer is started.
35
36Special cases:
37- Exporting a song with zero length
38- Exporting 0 samples
39- Exporting 1 sample
40- Exporting > 2GigaSamples
41- Auto split enabled/disabled
42
43Test for all sample rates:
44- What name is being used (renamed or not?)
45- Full songs in all formats
46- Export all tracks
47- Export 0 tracks
48- Export only track 1, track 2, ... track N (n=number of tracks)
49- Songs > 2 GiB/track (to test automatic splitting)
50- Start locpoint=START, end locpoint=END
51- start locpoint=START, end locpoint=2 samples
52- start locpoint=START, end locpoint=10 sec
53- start locpoint=1 sec, end locpoint=10 sec
54- start locpoint=END, end locpoint=START
55- start locpoint=1 sample, end locpoint=END
56- start locpoint=1 sample, end locpoint=2 samples
57- start locpoint=1 sample, end locpoint=10 sec
58- start locpoint=1 sample, end locpoint=END
59- start locpoint=1 sec, end locpoint=END
60
61Select song 'All songs' on a drive not containing double songnames,
62export to an empty directory.
63- No questions are asked regarding overwriting files.
64- Nothing is mentioned about double song names (or prefixing song names).
65- HD24connect correctly detects if any songs with those prefixes already exist.
66- Are existing filenames properly detected when exporting large files (that
67 need splitting)? e.g. files with suffix _part1, _part2.
68
69TRANSPORT CONTROL/audio preview
70- To be tested on songs of either high or low sample rates
71- All possible state changes: stop->play, play->stop, etc.
72- Set locatepoints
73- Loop mode
74- Drag locate bar
75- FF past end of song possible? (by changing songs? by using JACK?)
76- REW to negative time code possible? (by using Jack?)
77- Change song during playback, including the possibility of changing song
78 at a time code not present in both songs
79- Export audio during playback could cause audio to sound choppy but the exported audio should be OK.
80
81RECOVERY FEATURES
82- Creating a drive image:
83 - What happens if there isn't enough drive space to hold the image?
84- Load created drive image and use it as HD24 drive
85- If this drive image is opened (File->open drive image), and we select
86 file->recovery->select device, the filename of the current drive image
87 should be reported as current device.
88- Switch device
89- Loading longliverec header: Can audio be exported correctly? (is it similar/
90 equal to the audio of the audio preview?
91- For both high and low sample rates?
92- Selecting a non-HD24 drive as drive image (for instance a random file,
93 or windos drive) should not cause HD24tools to crash during playback or
94 export.
95
96Other features
97- Exporting and printing file index should work with any number of projects and any number of songs per project. It is especially important to test large number of songs as only this will reveal memory leaks.
98
99TRANSFER TO HD24 DRIVE
100Tests to run that do not perform allocation:
101- Start transfer without files
102- With 1 file (in first slot)
103- With 1 file (in 2nd slot, in last slot) (using a clean image)
104- With 1 file (in 2nd slot, in last slot) (using an image with track 1 in use)
105- 16 track song/24 track song
106- With multiple files, less than the number of tracks
107- With multiple files, equal to the number of tracks
108- with files smaller than the song size
109- with files equal to the song size
110- with files larger than the song size
111- with multi channel files
112- with files that have a different sample rate
113- with files that have a different bit depth
114- with several files of various formats at once
115
116Tests that do perform allocation:
117- Start with an empty song
118- Transfer a file with 0 length to HD24
119- Transfer a file with >0 length to HD24
120- Transfer a file with even greater length to HD24
121- Create another song, transfer some audio to it.
122 Is start of song cluster word-aligned in usage table?
123- Extend the first song. Does this work right?
124 Is the continuation of the song word-aligned?
125- What happens if the file to transfer is longer than
126 the remaining amount of drive space?
127
128
129
130
diff --git a/doc/artwork/DMG_Background.png b/doc/artwork/DMG_Background.png
new file mode 100644
index 0000000..720305d
--- /dev/null
+++ b/doc/artwork/DMG_Background.png
Binary files differ
diff --git a/doc/artwork/DMG_Background.psd b/doc/artwork/DMG_Background.psd
new file mode 100644
index 0000000..6c648b2
--- /dev/null
+++ b/doc/artwork/DMG_Background.psd
Binary files differ
diff --git a/doc/artwork/HD24Connect.icns b/doc/artwork/HD24Connect.icns
new file mode 100644
index 0000000..17714bb
--- /dev/null
+++ b/doc/artwork/HD24Connect.icns
Binary files differ
diff --git a/doc/artwork/HD24_vipower.jpg b/doc/artwork/HD24_vipower.jpg
new file mode 100644
index 0000000..b667e9d
--- /dev/null
+++ b/doc/artwork/HD24_vipower.jpg
Binary files differ
diff --git a/doc/artwork/Icon.psd b/doc/artwork/Icon.psd
new file mode 100644
index 0000000..77f35a6
--- /dev/null
+++ b/doc/artwork/Icon.psd
Binary files differ
diff --git a/doc/artwork/hd24connect.jpg b/doc/artwork/hd24connect.jpg
new file mode 100644
index 0000000..e6d0695
--- /dev/null
+++ b/doc/artwork/hd24connect.jpg
Binary files differ
diff --git a/doc/artwork/hd24display.png b/doc/artwork/hd24display.png
new file mode 100644
index 0000000..c701008
--- /dev/null
+++ b/doc/artwork/hd24display.png
Binary files differ
diff --git a/doc/artwork/hd24pc.jpg b/doc/artwork/hd24pc.jpg
new file mode 100644
index 0000000..70b0278
--- /dev/null
+++ b/doc/artwork/hd24pc.jpg
Binary files differ
diff --git a/doc/hd24tools_manual.odt b/doc/hd24tools_manual.odt
new file mode 100644
index 0000000..691bd94
--- /dev/null
+++ b/doc/hd24tools_manual.odt
Binary files differ
diff --git a/doc/hd24tools_manual.pdf b/doc/hd24tools_manual.pdf
new file mode 100644
index 0000000..cbb32ff
--- /dev/null
+++ b/doc/hd24tools_manual.pdf
Binary files differ
diff --git a/images/longliverec.h24 b/images/longliverec.h24
new file mode 100644
index 0000000..e6fe746
--- /dev/null
+++ b/images/longliverec.h24
Binary files differ
diff --git a/images/unquickformat.h24 b/images/unquickformat.h24
new file mode 100644
index 0000000..1d6c130
--- /dev/null
+++ b/images/unquickformat.h24
Binary files differ
diff --git a/scripts/backupscript.txt b/scripts/backupscript.txt
new file mode 100644
index 0000000..7899c8c
--- /dev/null
+++ b/scripts/backupscript.txt
@@ -0,0 +1,5174 @@
1-0 Backup superblock 1
2d0
3bb
4be
5d-01
6p
7ws
8-0 Backup Drive info 1
9d01
10bb
11be
12d-02
13p
14ws
15-0 Backup undo (?) usage 1
16d02
17bb
18be
19d-05
20p
21ws
22d03
23bb
24be
25d-04
26p
27ws
28d04
29bb
30be
31d-03
32p
33ws
34-0 Backup drive usage table 1
35d05
36bb
37be
38d-14
39p
40ws
41d06
42bb
43be
44d-13
45p
46ws
47d07
48bb
49be
50d-12
51p
52ws
53d08
54bb
55be
56d-11
57p
58ws
59d09
60bb
61be
62d-10
63p
64ws
65d0A
66bb
67be
68d-0F
69p
70ws
71d0B
72bb
73be
74d-0E
75p
76ws
77d0C
78bb
79be
80d-0D
81p
82ws
83d0D
84bb
85be
86d-0C
87p
88ws
89d0E
90bb
91be
92d-0B
93p
94ws
95d0F
96bb
97be
98d-0A
99p
100ws
101d10
102bb
103be
104d-09
105p
106ws
107d11
108bb
109be
110d-08
111p
112ws
113d12
114bb
115be
116d-07
117p
118ws
119d13
120bb
121be
122d-06
123p
124ws
125-0 Backup project 1
126d14
127bb
128be
129d-15
130p
131ws
132-0 Backup project 2
133d15
134bb
135be
136d-16
137p
138ws
139-0 Backup project 3
140d16
141bb
142be
143d-17
144p
145ws
146-0 Backup project 4
147d17
148bb
149be
150d-18
151p
152ws
153-0 Backup project 5
154d18
155bb
156be
157d-19
158p
159ws
160-0 Backup project 6
161d19
162bb
163be
164d-1A
165p
166ws
167-0 Backup project 7
168d1A
169bb
170be
171d-1B
172p
173ws
174-0 Backup project 8
175d1B
176bb
177be
178d-1C
179p
180ws
181-0 Backup project 9
182d1C
183bb
184be
185d-1D
186p
187ws
188-0 Backup project 10
189d1D
190bb
191be
192d-1E
193p
194ws
195-0 Backup project 11
196d1E
197bb
198be
199d-1F
200p
201ws
202-0 Backup project 12
203d1F
204bb
205be
206d-20
207p
208ws
209-0 Backup project 13
210d20
211bb
212be
213d-21
214p
215ws
216-0 Backup project 14
217d21
218bb
219be
220d-22
221p
222ws
223-0 Backup project 15
224d22
225bb
226be
227d-23
228p
229ws
230-0 Backup project 16
231d23
232bb
233be
234d-24
235p
236ws
237-0 Backup project 17
238d24
239bb
240be
241d-25
242p
243ws
244-0 Backup project 18
245d25
246bb
247be
248d-26
249p
250ws
251-0 Backup project 19
252d26
253bb
254be
255d-27
256p
257ws
258-0 Backup project 20
259d27
260bb
261be
262d-28
263p
264ws
265-0 Backup project 21
266d28
267bb
268be
269d-29
270p
271ws
272-0 Backup project 22
273d29
274bb
275be
276d-2A
277p
278ws
279-0 Backup project 23
280d2A
281bb
282be
283d-2B
284p
285ws
286-0 Backup project 24
287d2B
288bb
289be
290d-2C
291p
292ws
293-0 Backup project 25
294d2C
295bb
296be
297d-2D
298p
299ws
300-0 Backup project 26
301d2D
302bb
303be
304d-2E
305p
306ws
307-0 Backup project 27
308d2E
309bb
310be
311d-2F
312p
313ws
314-0 Backup project 28
315d2F
316bb
317be
318d-30
319p
320ws
321-0 Backup project 29
322d30
323bb
324be
325d-31
326p
327ws
328-0 Backup project 30
329d31
330bb
331be
332d-32
333p
334ws
335-0 Backup project 31
336d32
337bb
338be
339d-33
340p
341ws
342-0 Backup project 32
343d33
344bb
345be
346d-34
347p
348ws
349-0 Backup project 33
350d34
351bb
352be
353d-35
354p
355ws
356-0 Backup project 34
357d35
358bb
359be
360d-36
361p
362ws
363-0 Backup project 35
364d36
365bb
366be
367d-37
368p
369ws
370-0 Backup project 36
371d37
372bb
373be
374d-38
375p
376ws
377-0 Backup project 37
378d38
379bb
380be
381d-39
382p
383ws
384-0 Backup project 38
385d39
386bb
387be
388d-3A
389p
390ws
391-0 Backup project 39
392d3A
393bb
394be
395d-3B
396p
397ws
398-0 Backup project 40
399d3B
400bb
401be
402d-3C
403p
404ws
405-0 Backup project 41
406d3C
407bb
408be
409d-3D
410p
411ws
412-0 Backup project 42
413d3D
414bb
415be
416d-3E
417p
418ws
419-0 Backup project 43
420d3E
421bb
422be
423d-3F
424p
425ws
426-0 Backup project 44
427d3F
428bb
429be
430d-40
431p
432ws
433-0 Backup project 45
434d40
435bb
436be
437d-41
438p
439ws
440-0 Backup project 46
441d41
442bb
443be
444d-42
445p
446ws
447-0 Backup project 47
448d42
449bb
450be
451d-43
452p
453ws
454-0 Backup project 48
455d43
456bb
457be
458d-44
459p
460ws
461-0 Backup project 49
462d44
463bb
464be
465d-45
466p
467ws
468-0 Backup project 50
469d45
470bb
471be
472d-46
473p
474ws
475-0 Backup project 51
476d46
477bb
478be
479d-47
480p
481ws
482-0 Backup project 52
483d47
484bb
485be
486d-48
487p
488ws
489-0 Backup project 53
490d48
491bb
492be
493d-49
494p
495ws
496-0 Backup project 54
497d49
498bb
499be
500d-4A
501p
502ws
503-0 Backup project 55
504d4A
505bb
506be
507d-4B
508p
509ws
510-0 Backup project 56
511d4B
512bb
513be
514d-4C
515p
516ws
517-0 Backup project 57
518d4C
519bb
520be
521d-4D
522p
523ws
524-0 Backup project 58
525d4D
526bb
527be
528d-4E
529p
530ws
531-0 Backup project 59
532d4E
533bb
534be
535d-4F
536p
537ws
538-0 Backup project 60
539d4F
540bb
541be
542d-50
543p
544ws
545-0 Backup project 61
546d50
547bb
548be
549d-51
550p
551ws
552-0 Backup project 62
553d51
554bb
555be
556d-52
557p
558ws
559-0 Backup project 63
560d52
561bb
562be
563d-53
564p
565ws
566-0 Backup project 64
567d53
568bb
569be
570d-54
571p
572ws
573-0 Backup project 65
574d54
575bb
576be
577d-55
578p
579ws
580-0 Backup project 66
581d55
582bb
583be
584d-56
585p
586ws
587-0 Backup project 67
588d56
589bb
590be
591d-57
592p
593ws
594-0 Backup project 68
595d57
596bb
597be
598d-58
599p
600ws
601-0 Backup project 69
602d58
603bb
604be
605d-59
606p
607ws
608-0 Backup project 70
609d59
610bb
611be
612d-5A
613p
614ws
615-0 Backup project 71
616d5A
617bb
618be
619d-5B
620p
621ws
622-0 Backup project 72
623d5B
624bb
625be
626d-5C
627p
628ws
629-0 Backup project 73
630d5C
631bb
632be
633d-5D
634p
635ws
636-0 Backup project 74
637d5D
638bb
639be
640d-5E
641p
642ws
643-0 Backup project 75
644d5E
645bb
646be
647d-5F
648p
649ws
650-0 Backup project 76
651d5F
652bb
653be
654d-60
655p
656ws
657-0 Backup project 77
658d60
659bb
660be
661d-61
662p
663ws
664-0 Backup project 78
665d61
666bb
667be
668d-62
669p
670ws
671-0 Backup project 79
672d62
673bb
674be
675d-63
676p
677ws
678-0 Backup project 80
679d63
680bb
681be
682d-64
683p
684ws
685-0 Backup project 81
686d64
687bb
688be
689d-65
690p
691ws
692-0 Backup project 82
693d65
694bb
695be
696d-66
697p
698ws
699-0 Backup project 83
700d66
701bb
702be
703d-67
704p
705ws
706-0 Backup project 84
707d67
708bb
709be
710d-68
711p
712ws
713-0 Backup project 85
714d68
715bb
716be
717d-69
718p
719ws
720-0 Backup project 86
721d69
722bb
723be
724d-6A
725p
726ws
727-0 Backup project 87
728d6A
729bb
730be
731d-6B
732p
733ws
734-0 Backup project 88
735d6B
736bb
737be
738d-6C
739p
740ws
741-0 Backup project 89
742d6C
743bb
744be
745d-6D
746p
747ws
748-0 Backup project 90
749d6D
750bb
751be
752d-6E
753p
754ws
755-0 Backup project 91
756d6E
757bb
758be
759d-6F
760p
761ws
762-0 Backup project 92
763d6F
764bb
765be
766d-70
767p
768ws
769-0 Backup project 93
770d70
771bb
772be
773d-71
774p
775ws
776-0 Backup project 94
777d71
778bb
779be
780d-72
781p
782ws
783-0 Backup project 95
784d72
785bb
786be
787d-73
788p
789ws
790-0 Backup project 96
791d73
792bb
793be
794d-74
795p
796ws
797-0 Backup project 97
798d74
799bb
800be
801d-75
802p
803ws
804-0 Backup project 98
805d75
806bb
807be
808d-76
809p
810ws
811-0 Backup project 99
812d76
813bb
814be
815d-77
816p
817ws
818-0 Backup song 1
819d77
820bb
821be
822d-79
823p
824ws
825d78
826bb
827be
828d-78
829p
830ws
831-0 Backup song alloc info 1
832d79
833bb
834be
835d-7E
836p
837ws
838d7A
839bb
840be
841d-7D
842p
843ws
844d7B
845bb
846be
847d-7C
848p
849ws
850d7C
851bb
852be
853d-7B
854p
855ws
856d7D
857bb
858be
859d-7A
860p
861ws
862-0 Backup song 2
863d7E
864bb
865be
866d-80
867p
868ws
869d7F
870bb
871be
872d-7F
873p
874ws
875-0 Backup song alloc info 2
876d80
877bb
878be
879d-85
880p
881ws
882d81
883bb
884be
885d-84
886p
887ws
888d82
889bb
890be
891d-83
892p
893ws
894d83
895bb
896be
897d-82
898p
899ws
900d84
901bb
902be
903d-81
904p
905ws
906-0 Backup song 3
907d85
908bb
909be
910d-87
911p
912ws
913d86
914bb
915be
916d-86
917p
918ws
919-0 Backup song alloc info 3
920d87
921bb
922be
923d-8C
924p
925ws
926d88
927bb
928be
929d-8B
930p
931ws
932d89
933bb
934be
935d-8A
936p
937ws
938d8A
939bb
940be
941d-89
942p
943ws
944d8B
945bb
946be
947d-88
948p
949ws
950-0 Backup song 4
951d8C
952bb
953be
954d-8E
955p
956ws
957d8D
958bb
959be
960d-8D
961p
962ws
963-0 Backup song alloc info 4
964d8E
965bb
966be
967d-93
968p
969ws
970d8F
971bb
972be
973d-92
974p
975ws
976d90
977bb
978be
979d-91
980p
981ws
982d91
983bb
984be
985d-90
986p
987ws
988d92
989bb
990be
991d-8F
992p
993ws
994-0 Backup song 5
995d93
996bb
997be
998d-95
999p
1000ws
1001d94
1002bb
1003be
1004d-94
1005p
1006ws
1007-0 Backup song alloc info 5
1008d95
1009bb
1010be
1011d-9A
1012p
1013ws
1014d96
1015bb
1016be
1017d-99
1018p
1019ws
1020d97
1021bb
1022be
1023d-98
1024p
1025ws
1026d98
1027bb
1028be
1029d-97
1030p
1031ws
1032d99
1033bb
1034be
1035d-96
1036p
1037ws
1038-0 Backup song 6
1039d9A
1040bb
1041be
1042d-9C
1043p
1044ws
1045d9B
1046bb
1047be
1048d-9B
1049p
1050ws
1051-0 Backup song alloc info 6
1052d9C
1053bb
1054be
1055d-A1
1056p
1057ws
1058d9D
1059bb
1060be
1061d-A0
1062p
1063ws
1064d9E
1065bb
1066be
1067d-9F
1068p
1069ws
1070d9F
1071bb
1072be
1073d-9E
1074p
1075ws
1076dA0
1077bb
1078be
1079d-9D
1080p
1081ws
1082-0 Backup song 7
1083dA1
1084bb
1085be
1086d-A3
1087p
1088ws
1089dA2
1090bb
1091be
1092d-A2
1093p
1094ws
1095-0 Backup song alloc info 7
1096dA3
1097bb
1098be
1099d-A8
1100p
1101ws
1102dA4
1103bb
1104be
1105d-A7
1106p
1107ws
1108dA5
1109bb
1110be
1111d-A6
1112p
1113ws
1114dA6
1115bb
1116be
1117d-A5
1118p
1119ws
1120dA7
1121bb
1122be
1123d-A4
1124p
1125ws
1126-0 Backup song 8
1127dA8
1128bb
1129be
1130d-AA
1131p
1132ws
1133dA9
1134bb
1135be
1136d-A9
1137p
1138ws
1139-0 Backup song alloc info 8
1140dAA
1141bb
1142be
1143d-AF
1144p
1145ws
1146dAB
1147bb
1148be
1149d-AE
1150p
1151ws
1152dAC
1153bb
1154be
1155d-AD
1156p
1157ws
1158dAD
1159bb
1160be
1161d-AC
1162p
1163ws
1164dAE
1165bb
1166be
1167d-AB
1168p
1169ws
1170-0 Backup song 9
1171dAF
1172bb
1173be
1174d-B1
1175p
1176ws
1177dB0
1178bb
1179be
1180d-B0
1181p
1182ws
1183-0 Backup song alloc info 9
1184dB1
1185bb
1186be
1187d-B6
1188p
1189ws
1190dB2
1191bb
1192be
1193d-B5
1194p
1195ws
1196dB3
1197bb
1198be
1199d-B4
1200p
1201ws
1202dB4
1203bb
1204be
1205d-B3
1206p
1207ws
1208dB5
1209bb
1210be
1211d-B2
1212p
1213ws
1214-0 Backup song 10
1215dB6
1216bb
1217be
1218d-B8
1219p
1220ws
1221dB7
1222bb
1223be
1224d-B7
1225p
1226ws
1227-0 Backup song alloc info 10
1228dB8
1229bb
1230be
1231d-BD
1232p
1233ws
1234dB9
1235bb
1236be
1237d-BC
1238p
1239ws
1240dBA
1241bb
1242be
1243d-BB
1244p
1245ws
1246dBB
1247bb
1248be
1249d-BA
1250p
1251ws
1252dBC
1253bb
1254be
1255d-B9
1256p
1257ws
1258-0 Backup song 11
1259dBD
1260bb
1261be
1262d-BF
1263p
1264ws
1265dBE
1266bb
1267be
1268d-BE
1269p
1270ws
1271-0 Backup song alloc info 11
1272dBF
1273bb
1274be
1275d-C4
1276p
1277ws
1278dC0
1279bb
1280be
1281d-C3
1282p
1283ws
1284dC1
1285bb
1286be
1287d-C2
1288p
1289ws
1290dC2
1291bb
1292be
1293d-C1
1294p
1295ws
1296dC3
1297bb
1298be
1299d-C0
1300p
1301ws
1302-0 Backup song 12
1303dC4
1304bb
1305be
1306d-C6
1307p
1308ws
1309dC5
1310bb
1311be
1312d-C5
1313p
1314ws
1315-0 Backup song alloc info 12
1316dC6
1317bb
1318be
1319d-CB
1320p
1321ws
1322dC7
1323bb
1324be
1325d-CA
1326p
1327ws
1328dC8
1329bb
1330be
1331d-C9
1332p
1333ws
1334dC9
1335bb
1336be
1337d-C8
1338p
1339ws
1340dCA
1341bb
1342be
1343d-C7
1344p
1345ws
1346-0 Backup song 13
1347dCB
1348bb
1349be
1350d-CD
1351p
1352ws
1353dCC
1354bb
1355be
1356d-CC
1357p
1358ws
1359-0 Backup song alloc info 13
1360dCD
1361bb
1362be
1363d-D2
1364p
1365ws
1366dCE
1367bb
1368be
1369d-D1
1370p
1371ws
1372dCF
1373bb
1374be
1375d-D0
1376p
1377ws
1378dD0
1379bb
1380be
1381d-CF
1382p
1383ws
1384dD1
1385bb
1386be
1387d-CE
1388p
1389ws
1390-0 Backup song 14
1391dD2
1392bb
1393be
1394d-D4
1395p
1396ws
1397dD3
1398bb
1399be
1400d-D3
1401p
1402ws
1403-0 Backup song alloc info 14
1404dD4
1405bb
1406be
1407d-D9
1408p
1409ws
1410dD5
1411bb
1412be
1413d-D8
1414p
1415ws
1416dD6
1417bb
1418be
1419d-D7
1420p
1421ws
1422dD7
1423bb
1424be
1425d-D6
1426p
1427ws
1428dD8
1429bb
1430be
1431d-D5
1432p
1433ws
1434-0 Backup song 15
1435dD9
1436bb
1437be
1438d-DB
1439p
1440ws
1441dDA
1442bb
1443be
1444d-DA
1445p
1446ws
1447-0 Backup song alloc info 15
1448dDB
1449bb
1450be
1451d-E0
1452p
1453ws
1454dDC
1455bb
1456be
1457d-DF
1458p
1459ws
1460dDD
1461bb
1462be
1463d-DE
1464p
1465ws
1466dDE
1467bb
1468be
1469d-DD
1470p
1471ws
1472dDF
1473bb
1474be
1475d-DC
1476p
1477ws
1478-0 Backup song 16
1479dE0
1480bb
1481be
1482d-E2
1483p
1484ws
1485dE1
1486bb
1487be
1488d-E1
1489p
1490ws
1491-0 Backup song alloc info 16
1492dE2
1493bb
1494be
1495d-E7
1496p
1497ws
1498dE3
1499bb
1500be
1501d-E6
1502p
1503ws
1504dE4
1505bb
1506be
1507d-E5
1508p
1509ws
1510dE5
1511bb
1512be
1513d-E4
1514p
1515ws
1516dE6
1517bb
1518be
1519d-E3
1520p
1521ws
1522-0 Backup song 17
1523dE7
1524bb
1525be
1526d-E9
1527p
1528ws
1529dE8
1530bb
1531be
1532d-E8
1533p
1534ws
1535-0 Backup song alloc info 17
1536dE9
1537bb
1538be
1539d-EE
1540p
1541ws
1542dEA
1543bb
1544be
1545d-ED
1546p
1547ws
1548dEB
1549bb
1550be
1551d-EC
1552p
1553ws
1554dEC
1555bb
1556be
1557d-EB
1558p
1559ws
1560dED
1561bb
1562be
1563d-EA
1564p
1565ws
1566-0 Backup song 18
1567dEE
1568bb
1569be
1570d-F0
1571p
1572ws
1573dEF
1574bb
1575be
1576d-EF
1577p
1578ws
1579-0 Backup song alloc info 18
1580dF0
1581bb
1582be
1583d-F5
1584p
1585ws
1586dF1
1587bb
1588be
1589d-F4
1590p
1591ws
1592dF2
1593bb
1594be
1595d-F3
1596p
1597ws
1598dF3
1599bb
1600be
1601d-F2
1602p
1603ws
1604dF4
1605bb
1606be
1607d-F1
1608p
1609ws
1610-0 Backup song 19
1611dF5
1612bb
1613be
1614d-F7
1615p
1616ws
1617dF6
1618bb
1619be
1620d-F6
1621p
1622ws
1623-0 Backup song alloc info 19
1624dF7
1625bb
1626be
1627d-FC
1628p
1629ws
1630dF8
1631bb
1632be
1633d-FB
1634p
1635ws
1636dF9
1637bb
1638be
1639d-FA
1640p
1641ws
1642dFA
1643bb
1644be
1645d-F9
1646p
1647ws
1648dFB
1649bb
1650be
1651d-F8
1652p
1653ws
1654-0 Backup song 20
1655dFC
1656bb
1657be
1658d-FE
1659p
1660ws
1661dFD
1662bb
1663be
1664d-FD
1665p
1666ws
1667-0 Backup song alloc info 20
1668dFE
1669bb
1670be
1671d-103
1672p
1673ws
1674dFF
1675bb
1676be
1677d-102
1678p
1679ws
1680d100
1681bb
1682be
1683d-101
1684p
1685ws
1686d101
1687bb
1688be
1689d-100
1690p
1691ws
1692d102
1693bb
1694be
1695d-FF
1696p
1697ws
1698-0 Backup song 21
1699d103
1700bb
1701be
1702d-105
1703p
1704ws
1705d104
1706bb
1707be
1708d-104
1709p
1710ws
1711-0 Backup song alloc info 21
1712d105
1713bb
1714be
1715d-10A
1716p
1717ws
1718d106
1719bb
1720be
1721d-109
1722p
1723ws
1724d107
1725bb
1726be
1727d-108
1728p
1729ws
1730d108
1731bb
1732be
1733d-107
1734p
1735ws
1736d109
1737bb
1738be
1739d-106
1740p
1741ws
1742-0 Backup song 22
1743d10A
1744bb
1745be
1746d-10C
1747p
1748ws
1749d10B
1750bb
1751be
1752d-10B
1753p
1754ws
1755-0 Backup song alloc info 22
1756d10C
1757bb
1758be
1759d-111
1760p
1761ws
1762d10D
1763bb
1764be
1765d-110
1766p
1767ws
1768d10E
1769bb
1770be
1771d-10F
1772p
1773ws
1774d10F
1775bb
1776be
1777d-10E
1778p
1779ws
1780d110
1781bb
1782be
1783d-10D
1784p
1785ws
1786-0 Backup song 23
1787d111
1788bb
1789be
1790d-113
1791p
1792ws
1793d112
1794bb
1795be
1796d-112
1797p
1798ws
1799-0 Backup song alloc info 23
1800d113
1801bb
1802be
1803d-118
1804p
1805ws
1806d114
1807bb
1808be
1809d-117
1810p
1811ws
1812d115
1813bb
1814be
1815d-116
1816p
1817ws
1818d116
1819bb
1820be
1821d-115
1822p
1823ws
1824d117
1825bb
1826be
1827d-114
1828p
1829ws
1830-0 Backup song 24
1831d118
1832bb
1833be
1834d-11A
1835p
1836ws
1837d119
1838bb
1839be
1840d-119
1841p
1842ws
1843-0 Backup song alloc info 24
1844d11A
1845bb
1846be
1847d-11F
1848p
1849ws
1850d11B
1851bb
1852be
1853d-11E
1854p
1855ws
1856d11C
1857bb
1858be
1859d-11D
1860p
1861ws
1862d11D
1863bb
1864be
1865d-11C
1866p
1867ws
1868d11E
1869bb
1870be
1871d-11B
1872p
1873ws
1874-0 Backup song 25
1875d11F
1876bb
1877be
1878d-121
1879p
1880ws
1881d120
1882bb
1883be
1884d-120
1885p
1886ws
1887-0 Backup song alloc info 25
1888d121
1889bb
1890be
1891d-126
1892p
1893ws
1894d122
1895bb
1896be
1897d-125
1898p
1899ws
1900d123
1901bb
1902be
1903d-124
1904p
1905ws
1906d124
1907bb
1908be
1909d-123
1910p
1911ws
1912d125
1913bb
1914be
1915d-122
1916p
1917ws
1918-0 Backup song 26
1919d126
1920bb
1921be
1922d-128
1923p
1924ws
1925d127
1926bb
1927be
1928d-127
1929p
1930ws
1931-0 Backup song alloc info 26
1932d128
1933bb
1934be
1935d-12D
1936p
1937ws
1938d129
1939bb
1940be
1941d-12C
1942p
1943ws
1944d12A
1945bb
1946be
1947d-12B
1948p
1949ws
1950d12B
1951bb
1952be
1953d-12A
1954p
1955ws
1956d12C
1957bb
1958be
1959d-129
1960p
1961ws
1962-0 Backup song 27
1963d12D
1964bb
1965be
1966d-12F
1967p
1968ws
1969d12E
1970bb
1971be
1972d-12E
1973p
1974ws
1975-0 Backup song alloc info 27
1976d12F
1977bb
1978be
1979d-134
1980p
1981ws
1982d130
1983bb
1984be
1985d-133
1986p
1987ws
1988d131
1989bb
1990be
1991d-132
1992p
1993ws
1994d132
1995bb
1996be
1997d-131
1998p
1999ws
2000d133
2001bb
2002be
2003d-130
2004p
2005ws
2006-0 Backup song 28
2007d134
2008bb
2009be
2010d-136
2011p
2012ws
2013d135
2014bb
2015be
2016d-135
2017p
2018ws
2019-0 Backup song alloc info 28
2020d136
2021bb
2022be
2023d-13B
2024p
2025ws
2026d137
2027bb
2028be
2029d-13A
2030p
2031ws
2032d138
2033bb
2034be
2035d-139
2036p
2037ws
2038d139
2039bb
2040be
2041d-138
2042p
2043ws
2044d13A
2045bb
2046be
2047d-137
2048p
2049ws
2050-0 Backup song 29
2051d13B
2052bb
2053be
2054d-13D
2055p
2056ws
2057d13C
2058bb
2059be
2060d-13C
2061p
2062ws
2063-0 Backup song alloc info 29
2064d13D
2065bb
2066be
2067d-142
2068p
2069ws
2070d13E
2071bb
2072be
2073d-141
2074p
2075ws
2076d13F
2077bb
2078be
2079d-140
2080p
2081ws
2082d140
2083bb
2084be
2085d-13F
2086p
2087ws
2088d141
2089bb
2090be
2091d-13E
2092p
2093ws
2094-0 Backup song 30
2095d142
2096bb
2097be
2098d-144
2099p
2100ws
2101d143
2102bb
2103be
2104d-143
2105p
2106ws
2107-0 Backup song alloc info 30
2108d144
2109bb
2110be
2111d-149
2112p
2113ws
2114d145
2115bb
2116be
2117d-148
2118p
2119ws
2120d146
2121bb
2122be
2123d-147
2124p
2125ws
2126d147
2127bb
2128be
2129d-146
2130p
2131ws
2132d148
2133bb
2134be
2135d-145
2136p
2137ws
2138-0 Backup song 31
2139d149
2140bb
2141be
2142d-14B
2143p
2144ws
2145d14A
2146bb
2147be
2148d-14A
2149p
2150ws
2151-0 Backup song alloc info 31
2152d14B
2153bb
2154be
2155d-150
2156p
2157ws
2158d14C
2159bb
2160be
2161d-14F
2162p
2163ws
2164d14D
2165bb
2166be
2167d-14E
2168p
2169ws
2170d14E
2171bb
2172be
2173d-14D
2174p
2175ws
2176d14F
2177bb
2178be
2179d-14C
2180p
2181ws
2182-0 Backup song 32
2183d150
2184bb
2185be
2186d-152
2187p
2188ws
2189d151
2190bb
2191be
2192d-151
2193p
2194ws
2195-0 Backup song alloc info 32
2196d152
2197bb
2198be
2199d-157
2200p
2201ws
2202d153
2203bb
2204be
2205d-156
2206p
2207ws
2208d154
2209bb
2210be
2211d-155
2212p
2213ws
2214d155
2215bb
2216be
2217d-154
2218p
2219ws
2220d156
2221bb
2222be
2223d-153
2224p
2225ws
2226-0 Backup song 33
2227d157
2228bb
2229be
2230d-159
2231p
2232ws
2233d158
2234bb
2235be
2236d-158
2237p
2238ws
2239-0 Backup song alloc info 33
2240d159
2241bb
2242be
2243d-15E
2244p
2245ws
2246d15A
2247bb
2248be
2249d-15D
2250p
2251ws
2252d15B
2253bb
2254be
2255d-15C
2256p
2257ws
2258d15C
2259bb
2260be
2261d-15B
2262p
2263ws
2264d15D
2265bb
2266be
2267d-15A
2268p
2269ws
2270-0 Backup song 34
2271d15E
2272bb
2273be
2274d-160
2275p
2276ws
2277d15F
2278bb
2279be
2280d-15F
2281p
2282ws
2283-0 Backup song alloc info 34
2284d160
2285bb
2286be
2287d-165
2288p
2289ws
2290d161
2291bb
2292be
2293d-164
2294p
2295ws
2296d162
2297bb
2298be
2299d-163
2300p
2301ws
2302d163
2303bb
2304be
2305d-162
2306p
2307ws
2308d164
2309bb
2310be
2311d-161
2312p
2313ws
2314-0 Backup song 35
2315d165
2316bb
2317be
2318d-167
2319p
2320ws
2321d166
2322bb
2323be
2324d-166
2325p
2326ws
2327-0 Backup song alloc info 35
2328d167
2329bb
2330be
2331d-16C
2332p
2333ws
2334d168
2335bb
2336be
2337d-16B
2338p
2339ws
2340d169
2341bb
2342be
2343d-16A
2344p
2345ws
2346d16A
2347bb
2348be
2349d-169
2350p
2351ws
2352d16B
2353bb
2354be
2355d-168
2356p
2357ws
2358-0 Backup song 36
2359d16C
2360bb
2361be
2362d-16E
2363p
2364ws
2365d16D
2366bb
2367be
2368d-16D
2369p
2370ws
2371-0 Backup song alloc info 36
2372d16E
2373bb
2374be
2375d-173
2376p
2377ws
2378d16F
2379bb
2380be
2381d-172
2382p
2383ws
2384d170
2385bb
2386be
2387d-171
2388p
2389ws
2390d171
2391bb
2392be
2393d-170
2394p
2395ws
2396d172
2397bb
2398be
2399d-16F
2400p
2401ws
2402-0 Backup song 37
2403d173
2404bb
2405be
2406d-175
2407p
2408ws
2409d174
2410bb
2411be
2412d-174
2413p
2414ws
2415-0 Backup song alloc info 37
2416d175
2417bb
2418be
2419d-17A
2420p
2421ws
2422d176
2423bb
2424be
2425d-179
2426p
2427ws
2428d177
2429bb
2430be
2431d-178
2432p
2433ws
2434d178
2435bb
2436be
2437d-177
2438p
2439ws
2440d179
2441bb
2442be
2443d-176
2444p
2445ws
2446-0 Backup song 38
2447d17A
2448bb
2449be
2450d-17C
2451p
2452ws
2453d17B
2454bb
2455be
2456d-17B
2457p
2458ws
2459-0 Backup song alloc info 38
2460d17C
2461bb
2462be
2463d-181
2464p
2465ws
2466d17D
2467bb
2468be
2469d-180
2470p
2471ws
2472d17E
2473bb
2474be
2475d-17F
2476p
2477ws
2478d17F
2479bb
2480be
2481d-17E
2482p
2483ws
2484d180
2485bb
2486be
2487d-17D
2488p
2489ws
2490-0 Backup song 39
2491d181
2492bb
2493be
2494d-183
2495p
2496ws
2497d182
2498bb
2499be
2500d-182
2501p
2502ws
2503-0 Backup song alloc info 39
2504d183
2505bb
2506be
2507d-188
2508p
2509ws
2510d184
2511bb
2512be
2513d-187
2514p
2515ws
2516d185
2517bb
2518be
2519d-186
2520p
2521ws
2522d186
2523bb
2524be
2525d-185
2526p
2527ws
2528d187
2529bb
2530be
2531d-184
2532p
2533ws
2534-0 Backup song 40
2535d188
2536bb
2537be
2538d-18A
2539p
2540ws
2541d189
2542bb
2543be
2544d-189
2545p
2546ws
2547-0 Backup song alloc info 40
2548d18A
2549bb
2550be
2551d-18F
2552p
2553ws
2554d18B
2555bb
2556be
2557d-18E
2558p
2559ws
2560d18C
2561bb
2562be
2563d-18D
2564p
2565ws
2566d18D
2567bb
2568be
2569d-18C
2570p
2571ws
2572d18E
2573bb
2574be
2575d-18B
2576p
2577ws
2578-0 Backup song 41
2579d18F
2580bb
2581be
2582d-191
2583p
2584ws
2585d190
2586bb
2587be
2588d-190
2589p
2590ws
2591-0 Backup song alloc info 41
2592d191
2593bb
2594be
2595d-196
2596p
2597ws
2598d192
2599bb
2600be
2601d-195
2602p
2603ws
2604d193
2605bb
2606be
2607d-194
2608p
2609ws
2610d194
2611bb
2612be
2613d-193
2614p
2615ws
2616d195
2617bb
2618be
2619d-192
2620p
2621ws
2622-0 Backup song 42
2623d196
2624bb
2625be
2626d-198
2627p
2628ws
2629d197
2630bb
2631be
2632d-197
2633p
2634ws
2635-0 Backup song alloc info 42
2636d198
2637bb
2638be
2639d-19D
2640p
2641ws
2642d199
2643bb
2644be
2645d-19C
2646p
2647ws
2648d19A
2649bb
2650be
2651d-19B
2652p
2653ws
2654d19B
2655bb
2656be
2657d-19A
2658p
2659ws
2660d19C
2661bb
2662be
2663d-199
2664p
2665ws
2666-0 Backup song 43
2667d19D
2668bb
2669be
2670d-19F
2671p
2672ws
2673d19E
2674bb
2675be
2676d-19E
2677p
2678ws
2679-0 Backup song alloc info 43
2680d19F
2681bb
2682be
2683d-1A4
2684p
2685ws
2686d1A0
2687bb
2688be
2689d-1A3
2690p
2691ws
2692d1A1
2693bb
2694be
2695d-1A2
2696p
2697ws
2698d1A2
2699bb
2700be
2701d-1A1
2702p
2703ws
2704d1A3
2705bb
2706be
2707d-1A0
2708p
2709ws
2710-0 Backup song 44
2711d1A4
2712bb
2713be
2714d-1A6
2715p
2716ws
2717d1A5
2718bb
2719be
2720d-1A5
2721p
2722ws
2723-0 Backup song alloc info 44
2724d1A6
2725bb
2726be
2727d-1AB
2728p
2729ws
2730d1A7
2731bb
2732be
2733d-1AA
2734p
2735ws
2736d1A8
2737bb
2738be
2739d-1A9
2740p
2741ws
2742d1A9
2743bb
2744be
2745d-1A8
2746p
2747ws
2748d1AA
2749bb
2750be
2751d-1A7
2752p
2753ws
2754-0 Backup song 45
2755d1AB
2756bb
2757be
2758d-1AD
2759p
2760ws
2761d1AC
2762bb
2763be
2764d-1AC
2765p
2766ws
2767-0 Backup song alloc info 45
2768d1AD
2769bb
2770be
2771d-1B2
2772p
2773ws
2774d1AE
2775bb
2776be
2777d-1B1
2778p
2779ws
2780d1AF
2781bb
2782be
2783d-1B0
2784p
2785ws
2786d1B0
2787bb
2788be
2789d-1AF
2790p
2791ws
2792d1B1
2793bb
2794be
2795d-1AE
2796p
2797ws
2798-0 Backup song 46
2799d1B2
2800bb
2801be
2802d-1B4
2803p
2804ws
2805d1B3
2806bb
2807be
2808d-1B3
2809p
2810ws
2811-0 Backup song alloc info 46
2812d1B4
2813bb
2814be
2815d-1B9
2816p
2817ws
2818d1B5
2819bb
2820be
2821d-1B8
2822p
2823ws
2824d1B6
2825bb
2826be
2827d-1B7
2828p
2829ws
2830d1B7
2831bb
2832be
2833d-1B6
2834p
2835ws
2836d1B8
2837bb
2838be
2839d-1B5
2840p
2841ws
2842-0 Backup song 47
2843d1B9
2844bb
2845be
2846d-1BB
2847p
2848ws
2849d1BA
2850bb
2851be
2852d-1BA
2853p
2854ws
2855-0 Backup song alloc info 47
2856d1BB
2857bb
2858be
2859d-1C0
2860p
2861ws
2862d1BC
2863bb
2864be
2865d-1BF
2866p
2867ws
2868d1BD
2869bb
2870be
2871d-1BE
2872p
2873ws
2874d1BE
2875bb
2876be
2877d-1BD
2878p
2879ws
2880d1BF
2881bb
2882be
2883d-1BC
2884p
2885ws
2886-0 Backup song 48
2887d1C0
2888bb
2889be
2890d-1C2
2891p
2892ws
2893d1C1
2894bb
2895be
2896d-1C1
2897p
2898ws
2899-0 Backup song alloc info 48
2900d1C2
2901bb
2902be
2903d-1C7
2904p
2905ws
2906d1C3
2907bb
2908be
2909d-1C6
2910p
2911ws
2912d1C4
2913bb
2914be
2915d-1C5
2916p
2917ws
2918d1C5
2919bb
2920be
2921d-1C4
2922p
2923ws
2924d1C6
2925bb
2926be
2927d-1C3
2928p
2929ws
2930-0 Backup song 49
2931d1C7
2932bb
2933be
2934d-1C9
2935p
2936ws
2937d1C8
2938bb
2939be
2940d-1C8
2941p
2942ws
2943-0 Backup song alloc info 49
2944d1C9
2945bb
2946be
2947d-1CE
2948p
2949ws
2950d1CA
2951bb
2952be
2953d-1CD
2954p
2955ws
2956d1CB
2957bb
2958be
2959d-1CC
2960p
2961ws
2962d1CC
2963bb
2964be
2965d-1CB
2966p
2967ws
2968d1CD
2969bb
2970be
2971d-1CA
2972p
2973ws
2974-0 Backup song 50
2975d1CE
2976bb
2977be
2978d-1D0
2979p
2980ws
2981d1CF
2982bb
2983be
2984d-1CF
2985p
2986ws
2987-0 Backup song alloc info 50
2988d1D0
2989bb
2990be
2991d-1D5
2992p
2993ws
2994d1D1
2995bb
2996be
2997d-1D4
2998p
2999ws
3000d1D2
3001bb
3002be
3003d-1D3
3004p
3005ws
3006d1D3
3007bb
3008be
3009d-1D2
3010p
3011ws
3012d1D4
3013bb
3014be
3015d-1D1
3016p
3017ws
3018-0 Backup song 51
3019d1D5
3020bb
3021be
3022d-1D7
3023p
3024ws
3025d1D6
3026bb
3027be
3028d-1D6
3029p
3030ws
3031-0 Backup song alloc info 51
3032d1D7
3033bb
3034be
3035d-1DC
3036p
3037ws
3038d1D8
3039bb
3040be
3041d-1DB
3042p
3043ws
3044d1D9
3045bb
3046be
3047d-1DA
3048p
3049ws
3050d1DA
3051bb
3052be
3053d-1D9
3054p
3055ws
3056d1DB
3057bb
3058be
3059d-1D8
3060p
3061ws
3062-0 Backup song 52
3063d1DC
3064bb
3065be
3066d-1DE
3067p
3068ws
3069d1DD
3070bb
3071be
3072d-1DD
3073p
3074ws
3075-0 Backup song alloc info 52
3076d1DE
3077bb
3078be
3079d-1E3
3080p
3081ws
3082d1DF
3083bb
3084be
3085d-1E2
3086p
3087ws
3088d1E0
3089bb
3090be
3091d-1E1
3092p
3093ws
3094d1E1
3095bb
3096be
3097d-1E0
3098p
3099ws
3100d1E2
3101bb
3102be
3103d-1DF
3104p
3105ws
3106-0 Backup song 53
3107d1E3
3108bb
3109be
3110d-1E5
3111p
3112ws
3113d1E4
3114bb
3115be
3116d-1E4
3117p
3118ws
3119-0 Backup song alloc info 53
3120d1E5
3121bb
3122be
3123d-1EA
3124p
3125ws
3126d1E6
3127bb
3128be
3129d-1E9
3130p
3131ws
3132d1E7
3133bb
3134be
3135d-1E8
3136p
3137ws
3138d1E8
3139bb
3140be
3141d-1E7
3142p
3143ws
3144d1E9
3145bb
3146be
3147d-1E6
3148p
3149ws
3150-0 Backup song 54
3151d1EA
3152bb
3153be
3154d-1EC
3155p
3156ws
3157d1EB
3158bb
3159be
3160d-1EB
3161p
3162ws
3163-0 Backup song alloc info 54
3164d1EC
3165bb
3166be
3167d-1F1
3168p
3169ws
3170d1ED
3171bb
3172be
3173d-1F0
3174p
3175ws
3176d1EE
3177bb
3178be
3179d-1EF
3180p
3181ws
3182d1EF
3183bb
3184be
3185d-1EE
3186p
3187ws
3188d1F0
3189bb
3190be
3191d-1ED
3192p
3193ws
3194-0 Backup song 55
3195d1F1
3196bb
3197be
3198d-1F3
3199p
3200ws
3201d1F2
3202bb
3203be
3204d-1F2
3205p
3206ws
3207-0 Backup song alloc info 55
3208d1F3
3209bb
3210be
3211d-1F8
3212p
3213ws
3214d1F4
3215bb
3216be
3217d-1F7
3218p
3219ws
3220d1F5
3221bb
3222be
3223d-1F6
3224p
3225ws
3226d1F6
3227bb
3228be
3229d-1F5
3230p
3231ws
3232d1F7
3233bb
3234be
3235d-1F4
3236p
3237ws
3238-0 Backup song 56
3239d1F8
3240bb
3241be
3242d-1FA
3243p
3244ws
3245d1F9
3246bb
3247be
3248d-1F9
3249p
3250ws
3251-0 Backup song alloc info 56
3252d1FA
3253bb
3254be
3255d-1FF
3256p
3257ws
3258d1FB
3259bb
3260be
3261d-1FE
3262p
3263ws
3264d1FC
3265bb
3266be
3267d-1FD
3268p
3269ws
3270d1FD
3271bb
3272be
3273d-1FC
3274p
3275ws
3276d1FE
3277bb
3278be
3279d-1FB
3280p
3281ws
3282-0 Backup song 57
3283d1FF
3284bb
3285be
3286d-201
3287p
3288ws
3289d200
3290bb
3291be
3292d-200
3293p
3294ws
3295-0 Backup song alloc info 57
3296d201
3297bb
3298be
3299d-206
3300p
3301ws
3302d202
3303bb
3304be
3305d-205
3306p
3307ws
3308d203
3309bb
3310be
3311d-204
3312p
3313ws
3314d204
3315bb
3316be
3317d-203
3318p
3319ws
3320d205
3321bb
3322be
3323d-202
3324p
3325ws
3326-0 Backup song 58
3327d206
3328bb
3329be
3330d-208
3331p
3332ws
3333d207
3334bb
3335be
3336d-207
3337p
3338ws
3339-0 Backup song alloc info 58
3340d208
3341bb
3342be
3343d-20D
3344p
3345ws
3346d209
3347bb
3348be
3349d-20C
3350p
3351ws
3352d20A
3353bb
3354be
3355d-20B
3356p
3357ws
3358d20B
3359bb
3360be
3361d-20A
3362p
3363ws
3364d20C
3365bb
3366be
3367d-209
3368p
3369ws
3370-0 Backup song 59
3371d20D
3372bb
3373be
3374d-20F
3375p
3376ws
3377d20E
3378bb
3379be
3380d-20E
3381p
3382ws
3383-0 Backup song alloc info 59
3384d20F
3385bb
3386be
3387d-214
3388p
3389ws
3390d210
3391bb
3392be
3393d-213
3394p
3395ws
3396d211
3397bb
3398be
3399d-212
3400p
3401ws
3402d212
3403bb
3404be
3405d-211
3406p
3407ws
3408d213
3409bb
3410be
3411d-210
3412p
3413ws
3414-0 Backup song 60
3415d214
3416bb
3417be
3418d-216
3419p
3420ws
3421d215
3422bb
3423be
3424d-215
3425p
3426ws
3427-0 Backup song alloc info 60
3428d216
3429bb
3430be
3431d-21B
3432p
3433ws
3434d217
3435bb
3436be
3437d-21A
3438p
3439ws
3440d218
3441bb
3442be
3443d-219
3444p
3445ws
3446d219
3447bb
3448be
3449d-218
3450p
3451ws
3452d21A
3453bb
3454be
3455d-217
3456p
3457ws
3458-0 Backup song 61
3459d21B
3460bb
3461be
3462d-21D
3463p
3464ws
3465d21C
3466bb
3467be
3468d-21C
3469p
3470ws
3471-0 Backup song alloc info 61
3472d21D
3473bb
3474be
3475d-222
3476p
3477ws
3478d21E
3479bb
3480be
3481d-221
3482p
3483ws
3484d21F
3485bb
3486be
3487d-220
3488p
3489ws
3490d220
3491bb
3492be
3493d-21F
3494p
3495ws
3496d221
3497bb
3498be
3499d-21E
3500p
3501ws
3502-0 Backup song 62
3503d222
3504bb
3505be
3506d-224
3507p
3508ws
3509d223
3510bb
3511be
3512d-223
3513p
3514ws
3515-0 Backup song alloc info 62
3516d224
3517bb
3518be
3519d-229
3520p
3521ws
3522d225
3523bb
3524be
3525d-228
3526p
3527ws
3528d226
3529bb
3530be
3531d-227
3532p
3533ws
3534d227
3535bb
3536be
3537d-226
3538p
3539ws
3540d228
3541bb
3542be
3543d-225
3544p
3545ws
3546-0 Backup song 63
3547d229
3548bb
3549be
3550d-22B
3551p
3552ws
3553d22A
3554bb
3555be
3556d-22A
3557p
3558ws
3559-0 Backup song alloc info 63
3560d22B
3561bb
3562be
3563d-230
3564p
3565ws
3566d22C
3567bb
3568be
3569d-22F
3570p
3571ws
3572d22D
3573bb
3574be
3575d-22E
3576p
3577ws
3578d22E
3579bb
3580be
3581d-22D
3582p
3583ws
3584d22F
3585bb
3586be
3587d-22C
3588p
3589ws
3590-0 Backup song 64
3591d230
3592bb
3593be
3594d-232
3595p
3596ws
3597d231
3598bb
3599be
3600d-231
3601p
3602ws
3603-0 Backup song alloc info 64
3604d232
3605bb
3606be
3607d-237
3608p
3609ws
3610d233
3611bb
3612be
3613d-236
3614p
3615ws
3616d234
3617bb
3618be
3619d-235
3620p
3621ws
3622d235
3623bb
3624be
3625d-234
3626p
3627ws
3628d236
3629bb
3630be
3631d-233
3632p
3633ws
3634-0 Backup song 65
3635d237
3636bb
3637be
3638d-239
3639p
3640ws
3641d238
3642bb
3643be
3644d-238
3645p
3646ws
3647-0 Backup song alloc info 65
3648d239
3649bb
3650be
3651d-23E
3652p
3653ws
3654d23A
3655bb
3656be
3657d-23D
3658p
3659ws
3660d23B
3661bb
3662be
3663d-23C
3664p
3665ws
3666d23C
3667bb
3668be
3669d-23B
3670p
3671ws
3672d23D
3673bb
3674be
3675d-23A
3676p
3677ws
3678-0 Backup song 66
3679d23E
3680bb
3681be
3682d-240
3683p
3684ws
3685d23F
3686bb
3687be
3688d-23F
3689p
3690ws
3691-0 Backup song alloc info 66
3692d240
3693bb
3694be
3695d-245
3696p
3697ws
3698d241
3699bb
3700be
3701d-244
3702p
3703ws
3704d242
3705bb
3706be
3707d-243
3708p
3709ws
3710d243
3711bb
3712be
3713d-242
3714p
3715ws
3716d244
3717bb
3718be
3719d-241
3720p
3721ws
3722-0 Backup song 67
3723d245
3724bb
3725be
3726d-247
3727p
3728ws
3729d246
3730bb
3731be
3732d-246
3733p
3734ws
3735-0 Backup song alloc info 67
3736d247
3737bb
3738be
3739d-24C
3740p
3741ws
3742d248
3743bb
3744be
3745d-24B
3746p
3747ws
3748d249
3749bb
3750be
3751d-24A
3752p
3753ws
3754d24A
3755bb
3756be
3757d-249
3758p
3759ws
3760d24B
3761bb
3762be
3763d-248
3764p
3765ws
3766-0 Backup song 68
3767d24C
3768bb
3769be
3770d-24E
3771p
3772ws
3773d24D
3774bb
3775be
3776d-24D
3777p
3778ws
3779-0 Backup song alloc info 68
3780d24E
3781bb
3782be
3783d-253
3784p
3785ws
3786d24F
3787bb
3788be
3789d-252
3790p
3791ws
3792d250
3793bb
3794be
3795d-251
3796p
3797ws
3798d251
3799bb
3800be
3801d-250
3802p
3803ws
3804d252
3805bb
3806be
3807d-24F
3808p
3809ws
3810-0 Backup song 69
3811d253
3812bb
3813be
3814d-255
3815p
3816ws
3817d254
3818bb
3819be
3820d-254
3821p
3822ws
3823-0 Backup song alloc info 69
3824d255
3825bb
3826be
3827d-25A
3828p
3829ws
3830d256
3831bb
3832be
3833d-259
3834p
3835ws
3836d257
3837bb
3838be
3839d-258
3840p
3841ws
3842d258
3843bb
3844be
3845d-257
3846p
3847ws
3848d259
3849bb
3850be
3851d-256
3852p
3853ws
3854-0 Backup song 70
3855d25A
3856bb
3857be
3858d-25C
3859p
3860ws
3861d25B
3862bb
3863be
3864d-25B
3865p
3866ws
3867-0 Backup song alloc info 70
3868d25C
3869bb
3870be
3871d-261
3872p
3873ws
3874d25D
3875bb
3876be
3877d-260
3878p
3879ws
3880d25E
3881bb
3882be
3883d-25F
3884p
3885ws
3886d25F
3887bb
3888be
3889d-25E
3890p
3891ws
3892d260
3893bb
3894be
3895d-25D
3896p
3897ws
3898-0 Backup song 71
3899d261
3900bb
3901be
3902d-263
3903p
3904ws
3905d262
3906bb
3907be
3908d-262
3909p
3910ws
3911-0 Backup song alloc info 71
3912d263
3913bb
3914be
3915d-268
3916p
3917ws
3918d264
3919bb
3920be
3921d-267
3922p
3923ws
3924d265
3925bb
3926be
3927d-266
3928p
3929ws
3930d266
3931bb
3932be
3933d-265
3934p
3935ws
3936d267
3937bb
3938be
3939d-264
3940p
3941ws
3942-0 Backup song 72
3943d268
3944bb
3945be
3946d-26A
3947p
3948ws
3949d269
3950bb
3951be
3952d-269
3953p
3954ws
3955-0 Backup song alloc info 72
3956d26A
3957bb
3958be
3959d-26F
3960p
3961ws
3962d26B
3963bb
3964be
3965d-26E
3966p
3967ws
3968d26C
3969bb
3970be
3971d-26D
3972p
3973ws
3974d26D
3975bb
3976be
3977d-26C
3978p
3979ws
3980d26E
3981bb
3982be
3983d-26B
3984p
3985ws
3986-0 Backup song 73
3987d26F
3988bb
3989be
3990d-271
3991p
3992ws
3993d270
3994bb
3995be
3996d-270
3997p
3998ws
3999-0 Backup song alloc info 73
4000d271
4001bb
4002be
4003d-276
4004p
4005ws
4006d272
4007bb
4008be
4009d-275
4010p
4011ws
4012d273
4013bb
4014be
4015d-274
4016p
4017ws
4018d274
4019bb
4020be
4021d-273
4022p
4023ws
4024d275
4025bb
4026be
4027d-272
4028p
4029ws
4030-0 Backup song 74
4031d276
4032bb
4033be
4034d-278
4035p
4036ws
4037d277
4038bb
4039be
4040d-277
4041p
4042ws
4043-0 Backup song alloc info 74
4044d278
4045bb
4046be
4047d-27D
4048p
4049ws
4050d279
4051bb
4052be
4053d-27C
4054p
4055ws
4056d27A
4057bb
4058be
4059d-27B
4060p
4061ws
4062d27B
4063bb
4064be
4065d-27A
4066p
4067ws
4068d27C
4069bb
4070be
4071d-279
4072p
4073ws
4074-0 Backup song 75
4075d27D
4076bb
4077be
4078d-27F
4079p
4080ws
4081d27E
4082bb
4083be
4084d-27E
4085p
4086ws
4087-0 Backup song alloc info 75
4088d27F
4089bb
4090be
4091d-284
4092p
4093ws
4094d280
4095bb
4096be
4097d-283
4098p
4099ws
4100d281
4101bb
4102be
4103d-282
4104p
4105ws
4106d282
4107bb
4108be
4109d-281
4110p
4111ws
4112d283
4113bb
4114be
4115d-280
4116p
4117ws
4118-0 Backup song 76
4119d284
4120bb
4121be
4122d-286
4123p
4124ws
4125d285
4126bb
4127be
4128d-285
4129p
4130ws
4131-0 Backup song alloc info 76
4132d286
4133bb
4134be
4135d-28B
4136p
4137ws
4138d287
4139bb
4140be
4141d-28A
4142p
4143ws
4144d288
4145bb
4146be
4147d-289
4148p
4149ws
4150d289
4151bb
4152be
4153d-288
4154p
4155ws
4156d28A
4157bb
4158be
4159d-287
4160p
4161ws
4162-0 Backup song 77
4163d28B
4164bb
4165be
4166d-28D
4167p
4168ws
4169d28C
4170bb
4171be
4172d-28C
4173p
4174ws
4175-0 Backup song alloc info 77
4176d28D
4177bb
4178be
4179d-292
4180p
4181ws
4182d28E
4183bb
4184be
4185d-291
4186p
4187ws
4188d28F
4189bb
4190be
4191d-290
4192p
4193ws
4194d290
4195bb
4196be
4197d-28F
4198p
4199ws
4200d291
4201bb
4202be
4203d-28E
4204p
4205ws
4206-0 Backup song 78
4207d292
4208bb
4209be
4210d-294
4211p
4212ws
4213d293
4214bb
4215be
4216d-293
4217p
4218ws
4219-0 Backup song alloc info 78
4220d294
4221bb
4222be
4223d-299
4224p
4225ws
4226d295
4227bb
4228be
4229d-298
4230p
4231ws
4232d296
4233bb
4234be
4235d-297
4236p
4237ws
4238d297
4239bb
4240be
4241d-296
4242p
4243ws
4244d298
4245bb
4246be
4247d-295
4248p
4249ws
4250-0 Backup song 79
4251d299
4252bb
4253be
4254d-29B
4255p
4256ws
4257d29A
4258bb
4259be
4260d-29A
4261p
4262ws
4263-0 Backup song alloc info 79
4264d29B
4265bb
4266be
4267d-2A0
4268p
4269ws
4270d29C
4271bb
4272be
4273d-29F
4274p
4275ws
4276d29D
4277bb
4278be
4279d-29E
4280p
4281ws
4282d29E
4283bb
4284be
4285d-29D
4286p
4287ws
4288d29F
4289bb
4290be
4291d-29C
4292p
4293ws
4294-0 Backup song 80
4295d2A0
4296bb
4297be
4298d-2A2
4299p
4300ws
4301d2A1
4302bb
4303be
4304d-2A1
4305p
4306ws
4307-0 Backup song alloc info 80
4308d2A2
4309bb
4310be
4311d-2A7
4312p
4313ws
4314d2A3
4315bb
4316be
4317d-2A6
4318p
4319ws
4320d2A4
4321bb
4322be
4323d-2A5
4324p
4325ws
4326d2A5
4327bb
4328be
4329d-2A4
4330p
4331ws
4332d2A6
4333bb
4334be
4335d-2A3
4336p
4337ws
4338-0 Backup song 81
4339d2A7
4340bb
4341be
4342d-2A9
4343p
4344ws
4345d2A8
4346bb
4347be
4348d-2A8
4349p
4350ws
4351-0 Backup song alloc info 81
4352d2A9
4353bb
4354be
4355d-2AE
4356p
4357ws
4358d2AA
4359bb
4360be
4361d-2AD
4362p
4363ws
4364d2AB
4365bb
4366be
4367d-2AC
4368p
4369ws
4370d2AC
4371bb
4372be
4373d-2AB
4374p
4375ws
4376d2AD
4377bb
4378be
4379d-2AA
4380p
4381ws
4382-0 Backup song 82
4383d2AE
4384bb
4385be
4386d-2B0
4387p
4388ws
4389d2AF
4390bb
4391be
4392d-2AF
4393p
4394ws
4395-0 Backup song alloc info 82
4396d2B0
4397bb
4398be
4399d-2B5
4400p
4401ws
4402d2B1
4403bb
4404be
4405d-2B4
4406p
4407ws
4408d2B2
4409bb
4410be
4411d-2B3
4412p
4413ws
4414d2B3
4415bb
4416be
4417d-2B2
4418p
4419ws
4420d2B4
4421bb
4422be
4423d-2B1
4424p
4425ws
4426-0 Backup song 83
4427d2B5
4428bb
4429be
4430d-2B7
4431p
4432ws
4433d2B6
4434bb
4435be
4436d-2B6
4437p
4438ws
4439-0 Backup song alloc info 83
4440d2B7
4441bb
4442be
4443d-2BC
4444p
4445ws
4446d2B8
4447bb
4448be
4449d-2BB
4450p
4451ws
4452d2B9
4453bb
4454be
4455d-2BA
4456p
4457ws
4458d2BA
4459bb
4460be
4461d-2B9
4462p
4463ws
4464d2BB
4465bb
4466be
4467d-2B8
4468p
4469ws
4470-0 Backup song 84
4471d2BC
4472bb
4473be
4474d-2BE
4475p
4476ws
4477d2BD
4478bb
4479be
4480d-2BD
4481p
4482ws
4483-0 Backup song alloc info 84
4484d2BE
4485bb
4486be
4487d-2C3
4488p
4489ws
4490d2BF
4491bb
4492be
4493d-2C2
4494p
4495ws
4496d2C0
4497bb
4498be
4499d-2C1
4500p
4501ws
4502d2C1
4503bb
4504be
4505d-2C0
4506p
4507ws
4508d2C2
4509bb
4510be
4511d-2BF
4512p
4513ws
4514-0 Backup song 85
4515d2C3
4516bb
4517be
4518d-2C5
4519p
4520ws
4521d2C4
4522bb
4523be
4524d-2C4
4525p
4526ws
4527-0 Backup song alloc info 85
4528d2C5
4529bb
4530be
4531d-2CA
4532p
4533ws
4534d2C6
4535bb
4536be
4537d-2C9
4538p
4539ws
4540d2C7
4541bb
4542be
4543d-2C8
4544p
4545ws
4546d2C8
4547bb
4548be
4549d-2C7
4550p
4551ws
4552d2C9
4553bb
4554be
4555d-2C6
4556p
4557ws
4558-0 Backup song 86
4559d2CA
4560bb
4561be
4562d-2CC
4563p
4564ws
4565d2CB
4566bb
4567be
4568d-2CB
4569p
4570ws
4571-0 Backup song alloc info 86
4572d2CC
4573bb
4574be
4575d-2D1
4576p
4577ws
4578d2CD
4579bb
4580be
4581d-2D0
4582p
4583ws
4584d2CE
4585bb
4586be
4587d-2CF
4588p
4589ws
4590d2CF
4591bb
4592be
4593d-2CE
4594p
4595ws
4596d2D0
4597bb
4598be
4599d-2CD
4600p
4601ws
4602-0 Backup song 87
4603d2D1
4604bb
4605be
4606d-2D3
4607p
4608ws
4609d2D2
4610bb
4611be
4612d-2D2
4613p
4614ws
4615-0 Backup song alloc info 87
4616d2D3
4617bb
4618be
4619d-2D8
4620p
4621ws
4622d2D4
4623bb
4624be
4625d-2D7
4626p
4627ws
4628d2D5
4629bb
4630be
4631d-2D6
4632p
4633ws
4634d2D6
4635bb
4636be
4637d-2D5
4638p
4639ws
4640d2D7
4641bb
4642be
4643d-2D4
4644p
4645ws
4646-0 Backup song 88
4647d2D8
4648bb
4649be
4650d-2DA
4651p
4652ws
4653d2D9
4654bb
4655be
4656d-2D9
4657p
4658ws
4659-0 Backup song alloc info 88
4660d2DA
4661bb
4662be
4663d-2DF
4664p
4665ws
4666d2DB
4667bb
4668be
4669d-2DE
4670p
4671ws
4672d2DC
4673bb
4674be
4675d-2DD
4676p
4677ws
4678d2DD
4679bb
4680be
4681d-2DC
4682p
4683ws
4684d2DE
4685bb
4686be
4687d-2DB
4688p
4689ws
4690-0 Backup song 89
4691d2DF
4692bb
4693be
4694d-2E1
4695p
4696ws
4697d2E0
4698bb
4699be
4700d-2E0
4701p
4702ws
4703-0 Backup song alloc info 89
4704d2E1
4705bb
4706be
4707d-2E6
4708p
4709ws
4710d2E2
4711bb
4712be
4713d-2E5
4714p
4715ws
4716d2E3
4717bb
4718be
4719d-2E4
4720p
4721ws
4722d2E4
4723bb
4724be
4725d-2E3
4726p
4727ws
4728d2E5
4729bb
4730be
4731d-2E2
4732p
4733ws
4734-0 Backup song 90
4735d2E6
4736bb
4737be
4738d-2E8
4739p
4740ws
4741d2E7
4742bb
4743be
4744d-2E7
4745p
4746ws
4747-0 Backup song alloc info 90
4748d2E8
4749bb
4750be
4751d-2ED
4752p
4753ws
4754d2E9
4755bb
4756be
4757d-2EC
4758p
4759ws
4760d2EA
4761bb
4762be
4763d-2EB
4764p
4765ws
4766d2EB
4767bb
4768be
4769d-2EA
4770p
4771ws
4772d2EC
4773bb
4774be
4775d-2E9
4776p
4777ws
4778-0 Backup song 91
4779d2ED
4780bb
4781be
4782d-2EF
4783p
4784ws
4785d2EE
4786bb
4787be
4788d-2EE
4789p
4790ws
4791-0 Backup song alloc info 91
4792d2EF
4793bb
4794be
4795d-2F4
4796p
4797ws
4798d2F0
4799bb
4800be
4801d-2F3
4802p
4803ws
4804d2F1
4805bb
4806be
4807d-2F2
4808p
4809ws
4810d2F2
4811bb
4812be
4813d-2F1
4814p
4815ws
4816d2F3
4817bb
4818be
4819d-2F0
4820p
4821ws
4822-0 Backup song 92
4823d2F4
4824bb
4825be
4826d-2F6
4827p
4828ws
4829d2F5
4830bb
4831be
4832d-2F5
4833p
4834ws
4835-0 Backup song alloc info 92
4836d2F6
4837bb
4838be
4839d-2FB
4840p
4841ws
4842d2F7
4843bb
4844be
4845d-2FA
4846p
4847ws
4848d2F8
4849bb
4850be
4851d-2F9
4852p
4853ws
4854d2F9
4855bb
4856be
4857d-2F8
4858p
4859ws
4860d2FA
4861bb
4862be
4863d-2F7
4864p
4865ws
4866-0 Backup song 93
4867d2FB
4868bb
4869be
4870d-2FD
4871p
4872ws
4873d2FC
4874bb
4875be
4876d-2FC
4877p
4878ws
4879-0 Backup song alloc info 93
4880d2FD
4881bb
4882be
4883d-302
4884p
4885ws
4886d2FE
4887bb
4888be
4889d-301
4890p
4891ws
4892d2FF
4893bb
4894be
4895d-300
4896p
4897ws
4898d300
4899bb
4900be
4901d-2FF
4902p
4903ws
4904d301
4905bb
4906be
4907d-2FE
4908p
4909ws
4910-0 Backup song 94
4911d302
4912bb
4913be
4914d-304
4915p
4916ws
4917d303
4918bb
4919be
4920d-303
4921p
4922ws
4923-0 Backup song alloc info 94
4924d304
4925bb
4926be
4927d-309
4928p
4929ws
4930d305
4931bb
4932be
4933d-308
4934p
4935ws
4936d306
4937bb
4938be
4939d-307
4940p
4941ws
4942d307
4943bb
4944be
4945d-306
4946p
4947ws
4948d308
4949bb
4950be
4951d-305
4952p
4953ws
4954-0 Backup song 95
4955d309
4956bb
4957be
4958d-30B
4959p
4960ws
4961d30A
4962bb
4963be
4964d-30A
4965p
4966ws
4967-0 Backup song alloc info 95
4968d30B
4969bb
4970be
4971d-310
4972p
4973ws
4974d30C
4975bb
4976be
4977d-30F
4978p
4979ws
4980d30D
4981bb
4982be
4983d-30E
4984p
4985ws
4986d30E
4987bb
4988be
4989d-30D
4990p
4991ws
4992d30F
4993bb
4994be
4995d-30C
4996p
4997ws
4998-0 Backup song 96
4999d310
5000bb
5001be
5002d-312
5003p
5004ws
5005d311
5006bb
5007be
5008d-311
5009p
5010ws
5011-0 Backup song alloc info 96
5012d312
5013bb
5014be
5015d-317
5016p
5017ws
5018d313
5019bb
5020be
5021d-316
5022p
5023ws
5024d314
5025bb
5026be
5027d-315
5028p
5029ws
5030d315
5031bb
5032be
5033d-314
5034p
5035ws
5036d316
5037bb
5038be
5039d-313
5040p
5041ws
5042-0 Backup song 97
5043d317
5044bb
5045be
5046d-319
5047p
5048ws
5049d318
5050bb
5051be
5052d-318
5053p
5054ws
5055-0 Backup song alloc info 97
5056d319
5057bb
5058be
5059d-31E
5060p
5061ws
5062d31A
5063bb
5064be
5065d-31D
5066p
5067ws
5068d31B
5069bb
5070be
5071d-31C
5072p
5073ws
5074d31C
5075bb
5076be
5077d-31B
5078p
5079ws
5080d31D
5081bb
5082be
5083d-31A
5084p
5085ws
5086-0 Backup song 98
5087d31E
5088bb
5089be
5090d-320
5091p
5092ws
5093d31F
5094bb
5095be
5096d-31F
5097p
5098ws
5099-0 Backup song alloc info 98
5100d320
5101bb
5102be
5103d-325
5104p
5105ws
5106d321
5107bb
5108be
5109d-324
5110p
5111ws
5112d322
5113bb
5114be
5115d-323
5116p
5117ws
5118d323
5119bb
5120be
5121d-322
5122p
5123ws
5124d324
5125bb
5126be
5127d-321
5128p
5129ws
5130-0 Backup song 99
5131d325
5132bb
5133be
5134d-327
5135p
5136ws
5137d326
5138bb
5139be
5140d-326
5141p
5142ws
5143-0 Backup song alloc info 99
5144d327
5145bb
5146be
5147d-32C
5148p
5149ws
5150d328
5151bb
5152be
5153d-32B
5154p
5155ws
5156d329
5157bb
5158be
5159d-32A
5160p
5161ws
5162d32A
5163bb
5164be
5165d-329
5166p
5167ws
5168d32B
5169bb
5170be
5171d-328
5172p
5173ws
5174q
diff --git a/scripts/decodemtc b/scripts/decodemtc
new file mode 100755
index 0000000..b190fb3
--- /dev/null
+++ b/scripts/decodemtc
@@ -0,0 +1,127 @@
1#!/usr/bin/perl -w --
2$|=1; # disable output buffering
3
4use strict;
5use Switch;
6use Time::HiRes qw(usleep ualarm gettimeofday tv_interval);
7open (MTCSOURCE, "amidi --dump --port=hw:1,0,0|");
8my $set=0;
9my $hour=0;
10my $min=0;
11my $sec=0;
12my $frame=0;
13my $tmptmphour=0;
14my $tmptmpmin=0;
15my $tmptmpsec=0;
16my $tmptmpframe=0;
17my $tmphour=0;
18my $tmpmin=0;
19my $tmpsec=0;
20my $tmpframe=0;
21my $qframe=-1;
22my $settmp=0;
23my $t0=[gettimeofday()];
24my $t1;
25my $elapsed;
26while (<MTCSOURCE>) {
27 chomp($_);
28 if (/F0 7F (.*) 06 44 06 01 (.*) F7/) {
29 my @tc=split(' ',substr($_,21,14));
30 $hour=hex("0x".$tc[0]) & 31;
31 $min=hex("0x".$tc[1]);
32 $sec=hex("0x".$tc[2]);
33 $frame=hex("0x".$tc[3]);
34 $qframe=hex("0x".$tc[4]);
35 printf "%02d:%02d:%02d.%02d/%02d (LOCATE) \r",$hour,$min,$sec,$frame,$qframe;
36 next;
37 }
38 if (/F1 (.*)/) {
39 $t1=[gettimeofday()];
40 $elapsed=tv_interval($t0,$t1);
41 if ($elapsed>.1) {
42 $set=0;
43 $tmptmphour=0;
44 $tmptmpmin=0;
45 $tmptmpsec=0;
46 $tmptmpframe=0;
47 $settmp=0;
48 $qframe=-1;
49 $tmphour=0;
50 $tmpmin=0;
51 $tmpsec=0;
52 $tmpframe=0;
53 $hour=0;
54 $min=0;
55 $sec=0;
56 $frame=0;
57
58 }
59 $t0=$t1;
60# print $_." | ";
61 my $nibble=hex ("0x".substr($1,1,1));
62 my $cmd=substr($1,0,1);
63 if ($set ==0) {
64 if ($cmd ne "0") {
65 print "skip\n";
66 next;
67 }
68 }
69 $settmp=0;
70 switch (0+substr($1,0,1)) {
71 case 0 {
72 $tmptmpframe=($tmptmpframe & 0xf0)|$nibble;
73 $set|=1;
74 }
75 case 1 {
76 $tmptmpframe=($tmptmpframe & 0x0f)|($nibble*16);
77 $set|=2;
78 $tmpframe=$tmptmpframe;
79 $settmp=1;
80 }
81 case 2 {
82 $set|=4;
83 $tmptmpsec=($tmptmpsec & 0xf0)|$nibble;
84 }
85 case 3 {
86 $set|=8;
87 $tmptmpsec=($tmptmpsec & 0x0f)|($nibble*16);
88 }
89 $tmpsec=$tmptmpsec;
90 case 4 {
91 $set|=16;
92 $tmptmpmin=($tmptmpmin & 0xf0)|$nibble;
93 }
94 case 5 {
95 $set|=32;
96 $tmptmpmin=($tmptmpmin & 0x0f)|($nibble*16);
97 $tmpmin=$tmptmpmin;
98 }
99 case 6 {
100 $set|=64;
101 $tmptmphour=($tmptmphour & 0xf0)|$nibble;
102 }
103 case 7 {
104 $set|=128;
105 $tmptmphour=($tmptmphour & 0x0f)|(($nibble*16)&1);
106 $tmphour=$tmptmphour;
107 }
108 }
109 $qframe++;
110 if ($qframe > 3) {
111 $qframe=0;
112 if ($settmp == 0) {
113 $tmpframe++;
114 }
115 $frame=$tmpframe;
116 $sec=$tmpsec;
117 $min=$tmpmin;
118 $hour=$tmphour;
119 }
120 if ($set==255) {
121 printf "%02d:%02d:%02d.%02d/%02d \r",$hour,$min,$sec,$frame,$qframe;
122 } else {
123 printf "%02d:%02d:%02d.%02d/%02d (no lock)\r",$hour,$min,$sec,$frame,$qframe;
124 }
125 }
126}
127close (MTCSOURCE);
diff --git a/scripts/encode_smpte.pl b/scripts/encode_smpte.pl
new file mode 100755
index 0000000..de8f427
--- /dev/null
+++ b/scripts/encode_smpte.pl
@@ -0,0 +1,181 @@
1#!/usr/bin/perl --
2#
3#http://en.wikipedia.org/wiki/SMPTE_time_code
4sub bitnum {
5 my ($val,$bit)=@_;
6 while (1==1) {
7 if ($bit<=0) {
8 return $val % 2;
9 }
10 $val=int($val/2);
11 $bit--;
12 }
13}
14my $lastframe=-1;
15my @smpteword;
16
17my $prevbitnum=-1;
18my $prevhalfbit=-1;
19my $prevoutval=0;
20sub smpte_modulate {
21 my ($currbitval,$bitnum,$halfbit)=@_;
22 if (($bitnum!=$prevbitnum) || (($halfbit!=$prevhalfbit) && ($currbitval==1)))
23 {
24 $prevoutval=1-$prevoutval;
25 }
26 $prevbitnum=$bitnum;
27 $prevhalfbit=$halfbit;
28 return $prevoutval;
29}
30
31sub smpte_timecodebit {
32 my ($insamplerate,$framerate,$nondrop,$insamnum)=@_;
33 my $samnum=$insamnum;
34 my $samplerate=$insamplerate;
35 if ($insamplerate!=48000)
36 {
37 $samplerate=48000;
38 $samnum=$insamnum*(48000/$insamplerate);
39 }
40 my $sampleinsecond=$samnum % $samplerate;
41 my $currentsecond=($samnum-$sampleinsecond)/$samplerate;
42 my $currenthour=int($currentsecond/3600);
43 $currentsecond-=3600*$currenthour;
44 my $currentminute=int($currentsecond/60);
45 $currentsecond-=60*$currentminute;
46 my $bitsperframe=80;
47 my $bitspersecond=$bitsperframe*$framerate;
48 my $samplesperbit=$samplerate/$bitspersecond;
49 my $samplesperframe=$samplerate/$framerate;
50 my $currentframe=int($sampleinsecond/$samplesperframe);
51 my $sampleinframe=$sampleinsecond-($currentframe*$samplesperframe);
52 my $bitinframe=int($sampleinframe/$samplesperbit);
53 my $subbit=int($sampleinframe-($bitinframe*$samplesperbit));
54 my $halfbit=($samplesperbit/2);
55
56 my $frameunits=($currentframe%10);
57 my $frametens=int(($currentframe-$frameunits)/10);
58
59 my $secondsunits=($currentsecond%10);
60 my $secondstems=int(($currentsecond-$secondunits)/10);
61
62 my $minuteunits=($currentminute%10);
63 my $minutetens=int(($currentminute-$minuteunits)/10);
64
65 my $hourunits=($currenthour%10);
66 my $hourtens=int(($currenthour-$hourunits)/10);
67
68 $smpteword[0]=bitnum($frameunits,0);
69 $smpteword[1]=bitnum($frameunits,1);
70 $smpteword[2]=bitnum($frameunits,2);
71 $smpteword[3]=bitnum($frameunits,3);
72 $smpteword[4]=0;
73 $smpteword[5]=0;
74 $smpteword[6]=0;
75 $smpteword[7]=0;
76 $smpteword[8]=bitnum($frametens,0);
77 $smpteword[9]=bitnum($frametens,1);
78 $smpteword[10]=0;
79 $smpteword[11]=0;
80 $smpteword[12]=0;
81 $smpteword[13]=0;
82 $smpteword[14]=0;
83 $smpteword[15]=0;
84 $smpteword[16]=bitnum($secondsunits,0);
85 $smpteword[17]=bitnum($secondsunits,1);
86 $smpteword[18]=bitnum($secondsunits,2);
87 $smpteword[19]=bitnum($secondsunits,3);
88 $smpteword[20]=0;
89 $smpteword[21]=0;
90 $smpteword[22]=0;
91 $smpteword[23]=0;
92 $smpteword[24]=bitnum($secondstens,0);
93 $smpteword[25]=bitnum($secondstens,1);
94 $smpteword[26]=bitnum($secondstens,2);
95 $smpteword[27]=0; #biphasemark, fill in later
96 $smpteword[28]=0;
97 $smpteword[29]=0;
98 $smpteword[30]=0;
99 $smpteword[31]=0;
100 $smpteword[32]=bitnum($minuteunits,0);
101 $smpteword[33]=bitnum($minuteunits,1);
102 $smpteword[34]=bitnum($minuteunits,2);
103 $smpteword[35]=bitnum($minuteunits,3);
104 $smpteword[36]=0;
105 $smpteword[37]=0;
106 $smpteword[38]=0;
107 $smpteword[39]=0;
108 $smpteword[40]=bitnum($minutetens,0);
109 $smpteword[41]=bitnum($minutetens,1);
110 $smpteword[42]=bitnum($minutetens,2);
111 $smpteword[43]=0; # binary group flag bit
112 $smpteword[44]=0;
113 $smpteword[45]=0;
114 $smpteword[46]=0;
115 $smpteword[47]=0;
116 $smpteword[48]=bitnum($hourunits,0);
117 $smpteword[49]=bitnum($hourunits,1);
118 $smpteword[50]=bitnum($hourunits,2);
119 $smpteword[51]=bitnum($hourunits,3);
120 $smpteword[52]=0;
121 $smpteword[53]=0;
122 $smpteword[54]=0;
123 $smpteword[55]=0;
124 $smpteword[56]=bitnum($hourtens,0);
125 $smpteword[57]=bitnum($hourtens,1);
126 $smpteword[58]=0; # reserved, must be 0
127 $smpteword[59]=0; # binary group flag bit
128 $smpteword[60]=0;
129 $smpteword[61]=0;
130 $smpteword[62]=0;
131 $smpteword[63]=0;
132
133 # sync word follows
134 $smpteword[64]=0;
135 $smpteword[65]=0;
136 $smpteword[66]=1;
137 $smpteword[67]=1;
138 $smpteword[68]=1;
139 $smpteword[69]=1;
140 $smpteword[70]=1;
141 $smpteword[71]=1;
142 $smpteword[72]=1;
143 $smpteword[73]=1;
144 $smpteword[74]=1;
145 $smpteword[75]=1;
146 $smpteword[76]=1;
147 $smpteword[77]=1;
148 $smpteword[78]=0;
149 $smpteword[79]=1;
150 my $parity=0;
151 for ($i=0;$i<=79;$i++) {
152 $parity+=$smpteword[$i];
153 }
154 $smpteword[27]=$parity & 1;
155
156 return $smpteword[$bitinframe];
157 # Enable this to also perform bit modulation:
158 # ###########################
159 if ($subbit<$halfbit) {
160 return smpte_modulate($smpteword[$bitinframe],$bitinframe,0);
161 }
162 return smpte_modulate($smpteword[$bitinframe],$bitinframe,1);
163 ##################################
164 # or only use this to return the raw SMPTE bits.
165}
166
167my $i;
168my $samplerate=48000;
169my $framerate=30;
170$startsam=0; #($samplerate/$framerate);
171my $nondrop=true;
172for ($samnum=$startsam;$samnum<1500000;$samnum+=10) {
173 $x=smpte_timecodebit($samplerate,$framerate,$nondrop,$samnum);
174 if ($x==0) {
175 print "0"; #chr(0);
176 } else {
177 print "1"; #chr(255);
178 }
179
180}
181
diff --git a/scripts/genbackupscript.pl b/scripts/genbackupscript.pl
new file mode 100755
index 0000000..9546c56
--- /dev/null
+++ b/scripts/genbackupscript.pl
@@ -0,0 +1,98 @@
1#!/usr/bin/perl --
2
3sub dec2hex {
4 # parameter passed to
5 # the subfunction
6 my $decnum = $_[0];
7 if ($decnum==0) {
8 return "0";
9 }
10 # the final hex number
11 my $hexnum;
12 my $tempval;
13 while ($decnum != 0) {
14 # get the remainder (modulus function)
15 # by dividing by 16
16 $tempval = $decnum % 16;
17 # convert to the appropriate letter
18 # if the value is greater than 9
19 if ($tempval > 9) {
20 $tempval = chr($tempval + 55);
21 }
22 # 'concatenate' the number to
23 # what we have so far in what will
24 # be the final variable
25 $hexnum = $tempval . $hexnum ;
26 # new actually divide by 16, and
27 # keep the integer value of the
28 # answer
29 $decnum = int($decnum / 16);
30 # if we cant divide by 16, this is the
31 # last step
32 if ($decnum < 16) {
33 # convert to letters again..
34 if ($decnum > 9) {
35 $decnum = chr($decnum + 55);
36 }
37
38 # add this onto the final answer..
39 # reset decnum variable to zero so loop
40 # will exit
41 $hexnum = $decnum . $hexnum;
42 $decnum = 0
43 }
44 }
45 return $hexnum;
46} # end sub
47
48sub writebackupblock ($$$$) {
49my $i;
50 my $sector=shift;
51 my $blocksize=shift;
52 my $currentcount=shift;
53 my $remark=shift;
54 print "-0 ".$remark." ".$currentcount."\n";
55 for ($i=1;$i<=$blocksize;$i++) {
56 print "d".dec2hex($sector+$i-1)."\n";
57 print "bb\nbe\n";
58 print "d-".dec2hex($sector+1+$blocksize-$i)."\n";
59 print "p\nws\n";
60 }
61}
62$sector=0;
63$blocksize=1;
64$count=1;
65writebackupblock($sector,$blocksize,$count,"Backup superblock");
66
67$sector+=$blocksize*$count;
68$blocksize=1;
69$count=1;
70writebackupblock ($sector,$blocksize,$count,"Backup Drive info");
71
72$sector+=$blocksize*$count;
73$blocksize=3;
74$count=1;
75writebackupblock ($sector,$blocksize,$count,"Backup undo (?) usage");
76
77$sector+=$blocksize*$count;
78$blocksize=15;
79$count=1;
80writebackupblock ($sector,$blocksize,$count,"Backup drive usage table");
81
82$sector+=$blocksize*$count;
83$blocksize=1;
84$count=99;
85for ($i=1;$i<=$count;$i++) {
86 writebackupblock ($sector+$i-1,$blocksize,$i,"Backup project ");
87}
88
89$sector+=$blocksize*$count;
90$count=99;
91for ($i=1;$i<=$count;$i++) {
92 $blocksize=2;
93 writebackupblock ($sector+(7*($i-1)),$blocksize,$i,"Backup song ");
94 $blocksize=5;
95 writebackupblock ($sector+(7*($i-1))+2,$blocksize,$i,"Backup song alloc info ");
96}
97print "q\n";
98
diff --git a/scripts/hd24arm1 b/scripts/hd24arm1
new file mode 100755
index 0000000..6df5cca
--- /dev/null
+++ b/scripts/hd24arm1
@@ -0,0 +1,2 @@
1#!/bin/sh
2amidi --send-hex="F0 7F 7F 06 40 04 4F 02 20 00 F7"
diff --git a/scripts/hd24arm1-16 b/scripts/hd24arm1-16
new file mode 100755
index 0000000..ddbdb14
--- /dev/null
+++ b/scripts/hd24arm1-16
@@ -0,0 +1,2 @@
1#!/bin/sh
2amidi --send-hex="F0 7F 7F 06 40 05 4F 03 60 7f 7f F7"
diff --git a/scripts/hd24arm1-24 b/scripts/hd24arm1-24
new file mode 100755
index 0000000..0b99ab1
--- /dev/null
+++ b/scripts/hd24arm1-24
@@ -0,0 +1,2 @@
1#!/bin/sh
2amidi --port=hw:1,0,0 --send-hex="F0 7F 7F 06 40 07 4F 05 60 7f 7f 7f 01 F7"
diff --git a/scripts/hd24arm2 b/scripts/hd24arm2
new file mode 100755
index 0000000..27c1f76
--- /dev/null
+++ b/scripts/hd24arm2
@@ -0,0 +1,2 @@
1#!/bin/sh
2amidi --send-hex="F0 7F 7F 06 40 04 4F 02 40 00 F7"
diff --git a/scripts/hd24getinfo b/scripts/hd24getinfo
new file mode 100755
index 0000000..769f205
--- /dev/null
+++ b/scripts/hd24getinfo
@@ -0,0 +1,2 @@
1#!/bin/sh
2amidi --send-hex="F0 7F 7F 06 40 04 21 02 20 00 F7"
diff --git a/scripts/hd24idreq b/scripts/hd24idreq
new file mode 100755
index 0000000..c34af04
--- /dev/null
+++ b/scripts/hd24idreq
@@ -0,0 +1,3 @@
1#!/bin/sh
2amidi --send-hex="f0 7f 7f 06 01 f7"
3
diff --git a/scripts/hd24mute1 b/scripts/hd24mute1
new file mode 100755
index 0000000..516f1e3
--- /dev/null
+++ b/scripts/hd24mute1
@@ -0,0 +1,2 @@
1#!/bin/sh
2amidi --send-hex="F0 7F 7F 06 40 04 62 02 20 00 F7"
diff --git a/scripts/hd24play b/scripts/hd24play
new file mode 100755
index 0000000..16ad717
--- /dev/null
+++ b/scripts/hd24play
@@ -0,0 +1,3 @@
1#!/bin/sh
2amidi --send-hex="f0 7f 7f 06 02 f7"
3
diff --git a/scripts/hd24stop b/scripts/hd24stop
new file mode 100755
index 0000000..c34af04
--- /dev/null
+++ b/scripts/hd24stop
@@ -0,0 +1,3 @@
1#!/bin/sh
2amidi --send-hex="f0 7f 7f 06 01 f7"
3
diff --git a/scripts/hd24unarmall b/scripts/hd24unarmall
new file mode 100755
index 0000000..532c276
--- /dev/null
+++ b/scripts/hd24unarmall
@@ -0,0 +1,2 @@
1#!/bin/sh
2amidi --port=hw:1,0,0 --send-hex="F0 7F 7F 06 40 02 4F 00 F7"
diff --git a/scripts/midi.c b/scripts/midi.c
new file mode 100644
index 0000000..97c66dc
--- /dev/null
+++ b/scripts/midi.c
@@ -0,0 +1,40 @@
1//
2// Programmer: Craig Stuart Sapp <craig@ccrma.stanford.edu>
3// Creation Date: Tue Dec 22 20:12:18 PST 1998
4// Last Modified: Tue Dec 22 20:12:23 PST 1998
5// Filename: insimple.c
6// Syntax: C; pthread
7// $Smake: gcc -O3 -Wall -o %b %f -static -lpthread && strip %b
8//
9
10#include <sys/soundcard.h>
11#include <fcntl.h>
12#include <unistd.h>
13#include <stdio.h>
14
15#define MIDI_DEVICE "/dev/sequencer"
16
17
18int main(void) {
19 unsigned char inpacket[4];
20
21 // first open the sequencer device for reading.
22 int seqfd = open(MIDI_DEVICE, O_RDONLY);
23 if (seqfd == -1) {
24 printf("Error: cannot open %s\n", MIDI_DEVICE);
25 exit(1);
26 }
27
28 // now just wait around for MIDI bytes to arrive and print them to screen.
29 while (1) {
30 read(seqfd, &inpacket, sizeof(inpacket));
31
32 // print the MIDI byte if this input packet contains one
33 if (inpacket[0] == SEQ_MIDIPUTC) {
34 printf("received MIDI byte: %d\n", inpacket[1]);
35 }
36 }
37
38 return 0;
39}
40
diff --git a/scripts/mtcspeak b/scripts/mtcspeak
new file mode 100755
index 0000000..6ea6c27
--- /dev/null
+++ b/scripts/mtcspeak
@@ -0,0 +1,34 @@
1#!/usr/bin/perl -w --
2$|=1; # disable output buffering
3use strict;
4open (MTCSOURCE, "amidi --dump --port=hw:1,0,0|");
5open (STDOUT, "|espeak");
6my $hour=0;
7my $min=0;
8my $sec=0;
9my $frame=0;
10my $qframe=-1;
11my $roundedframe;
12while (<MTCSOURCE>) {
13 chomp($_);
14 if (/F0 7F (.*) 06 44 06 01 (.*) F7/) {
15 my @tc=split(' ',substr($_,21,17));
16 $hour=hex("0x".$tc[0]) & 31;
17 $min=hex("0x".$tc[1]);
18 $sec=hex("0x".$tc[2]);
19 $frame=hex("0x".$tc[3]);
20 $qframe=hex("0x".$tc[4]);
21 $roundedframe=$frame;
22 if ($qframe>=50) {
23 $roundedframe++;
24 }
25 if ($hour>0) {
26 print "$hour hours $min minutes $sec seconds $roundedframe frames\r\n";
27 }
28 else
29 {
30 print "$min minutes $sec seconds $roundedframe frames\r\n";
31 }
32 }
33}
34close (MTCSOURCE);
diff --git a/scripts/off2sec.pl b/scripts/off2sec.pl
new file mode 100755
index 0000000..0751be5
--- /dev/null
+++ b/scripts/off2sec.pl
@@ -0,0 +1,19 @@
1#!/usr/bin/perl --
2# Given an offset of a byte number on disk,
3# this little script converts the given offset to the sector number
4# where the audio starts that is allocated by the given byte in the
5# usage table.
6# It is assumed that the drive usage table starts on offset 0xa00
7# (sector 5).
8# The blocks per cluster must be looked up in the boot record of the
9# drive before using this script; it varies based on drive capacity.
10my $blockspercluster=5;
11my $sectorsperblock=0x480;
12my $firstaudiosec=0x1397f6;
13my $usagetablestart=0xa00;
14my $recordingoffset=hex($ARGV[0]);
15my $bitsperbyte=8;
16my $startcluster=$recordingoffset-$usagetablestart;
17my $audiosec=$firstaudiosec+($sectorsperblock*$blockspercluster*$bitsperbyte*$startcluster);
18
19print sprintf("%x",$audiosec)."\n";
diff --git a/scripts/sec2off.pl b/scripts/sec2off.pl
new file mode 100755
index 0000000..6028cb0
--- /dev/null
+++ b/scripts/sec2off.pl
@@ -0,0 +1,17 @@
1#!/usr/bin/perl --
2# Given an audio sector number (based on alloc info of a song),
3# this script converts that sector number to the byte offset on
4# the drive where that sector number should be allocated.
5# This is useful in combination with hd24hexview.
6# Blocks per cluster must be looked up in the superblock of the drive;
7# it varies depending on drive capacity.
8my $blockspercluster=5;
9my $sectorsperblock=0x480;
10my $firstaudiosec=0x1397f6;
11my $usagetablestart=0xa00;
12my $audiosec=hex($ARGV[0]);
13my $bitsperbyte=8;
14
15my $offs=($audiosec-$firstaudiosec)/0x480/$blockspercluster/$bitsperbyte+$usagetablestart;
16
17print sprintf("%x",$offs)."\n";
diff --git a/scripts/showstoppedmtc b/scripts/showstoppedmtc
new file mode 100755
index 0000000..e1e42fe
--- /dev/null
+++ b/scripts/showstoppedmtc
@@ -0,0 +1,33 @@
1#!/usr/bin/perl -w --
2$|=1; # disable output buffering
3use strict;
4open (MTCSOURCE, "amidi --dump --port=hw:1,0,0|");
5my $hour=0;
6my $min=0;
7my $sec=0;
8my $frame=0;
9my $qframe=-1;
10while (<MTCSOURCE>) {
11 chomp($_);
12 if (/F0 7F (.*) 06 44 06 01 (.*) F7/) {
13 print $_;
14 my @tc=split(' ',substr($_,21,17));
15 $hour=hex("0x".$tc[0]) & 31;
16 $min=hex("0x".$tc[1]);
17 $sec=hex("0x".$tc[2]);
18 $frame=hex("0x".$tc[3]);
19 $qframe=hex("0x".$tc[4]);
20 $roundedframe=$frame;
21 if ($qframe>=50) {
22 $roundedframe++;
23 }
24 if ($hour>0) {
25 print "$hour hours $min minutes $sec seconds $roundedframe\r\n";
26 }
27 else
28 {
29 print "$min minutes $sec seconds $roundedframe\r\n";
30 }
31 }
32}
33close (MTCSOURCE);
diff --git a/scripts/sl2o.pl b/scripts/sl2o.pl
new file mode 100755
index 0000000..6047816
--- /dev/null
+++ b/scripts/sl2o.pl
@@ -0,0 +1,23 @@
1#!/usr/bin/perl --
2# sl2o -> converts Sectornumber and Length to Offset
3# Given a sector number and block count (as mentioned in an allocation
4# entry of a song), this little script tries to calculate which
5# range of byte offsets on the drive correspond with the usage
6# info of that allocation entry. This is useful in combination with
7# hd24hexview.
8# Blocks per cluster must be configured depending on the drive capacity.
9# Look up the correct number in the superblock of the drive.
10use POSIX floor;
11my $sectorsperblock=0x480;
12my $firstaudiosec=0x1397f6;
13my $usagetablestart=0xa00;
14my $blockspercluster=5;
15my $bitsperbyte=8;
16my $audiosec=hex($ARGV[0]);
17my $seclen=floor(hex($ARGV[1])/($blockspercluster*$bitsperbyte));
18
19
20my $offs=($audiosec-$firstaudiosec)/0x480/$blockspercluster/$bitsperbyte+$usagetablestart;
21
22print sprintf("%x",$offs)."-";
23print sprintf("%x",$offs+$seclen)."\n";
diff --git a/src/frontend/WidgetPDial.fl b/src/frontend/WidgetPDial.fl
new file mode 100644
index 0000000..5b7ec05
--- /dev/null
+++ b/src/frontend/WidgetPDial.fl
@@ -0,0 +1,131 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0105
3header_name {.h}
4code_name {.cc}
5decl {//Copyright (c) 2003-2005 Nasca Octavian Paul} {}
6
7decl {//License: GNU GPL version 2 or later} {}
8
9decl {\#include <FL/Fl_Dial.H>} {public
10}
11
12decl {\#include <FL/fl_draw.H>} {public
13}
14
15decl {\#include <stdio.h>} {public
16}
17
18decl {\#include <math.h>} {public
19}
20
21class WidgetPDial {: {public Fl_Dial}
22} {
23 Function {WidgetPDial(int x,int y, int w, int h, const char *label=0):Fl_Dial(x,y,w,h,label)} {} {
24 code {oldvalue=0.0;} {}
25 }
26 Function {handle(int event)} {return_type int
27 } {
28 code {double dragsize,v,min=minimum(),max=maximum();
29int my;
30
31switch (event){
32case FL_PUSH:oldvalue=value();
33case FL_DRAG:
34 my=-(Fl::event_y()-y()-h()/2);
35
36 dragsize=200.0;
37 if (Fl::event_state(FL_BUTTON1)==0) dragsize*=10;
38 v=oldvalue+my/dragsize*(max-min);
39 if (v<min) v=min;
40 else if (v>max) v=max;
41
42 //printf("%d %g %g\\n",my,v,oldvalue);
43 value(v);
44 value_damage();
45 if (this->when()!=0) do_callback();
46 return(1);
47 break;
48case FL_RELEASE:
49 if (this->when()==0) do_callback();
50 return(1);
51 break;
52};
53return(0);} {selected
54 }
55 }
56 Function {drawgradient(int cx,int cy,int sx,double m1,double m2)} {return_type void
57 } {
58 code {for (int i=(int)(m1*sx);i<(int)(m2*sx);i++){
59 double tmp=1.0-pow(i*1.0/sx,2.0);
60 pdialcolor(140+(int) (tmp*90),140+(int)(tmp*90),140+(int) (tmp*100));
61 fl_arc(cx+sx/2-i/2,cy+sx/2-i/2,i,i,0,360);
62};} {}
63 }
64 Function {draw()} {} {
65 code {int cx=x(),cy=y(),sx=w(),sy=h();
66
67
68//clears the button face
69pdialcolor(190,190,200);
70fl_pie(cx-1,cy-1,sx+2,sy+2,0,360);
71
72//Draws the button face (gradinet)
73drawgradient(cx,cy,sx,0.5,1.0);
74
75double val=(value()-minimum())/(maximum()-minimum());
76
77//draws the scale
78pdialcolor(220,220,250);
79double a1=angle1(),a2=angle2();
80for (int i=0;i<12;i++){
81 double a=-i/12.0*360.0-val*(a2-a1)-a1;
82 fl_pie(cx,cy,sx,sy,a+270-3,a+3+270);
83};
84
85drawgradient(cx,cy,sx,0.0,0.75);
86
87//draws the value
88double a=-(a2-a1)*val-a1;
89
90
91
92
93
94//draws the max and min points
95pdialcolor(0,100,200);
96int xp=(int)(cx+sx/2.0+sx/2.0*sin(angle1()/180.0*3.141592));
97int yp=(int)(cy+sy/2.0+sy/2.0*cos(angle1()/180.0*3.141592));
98fl_pie(xp-2,yp-2,4,4,0,360);
99
100xp=(int)(cx+sx/2.0+sx/2.0*sin(angle2()/180.0*3.141592));
101yp=(int)(cy+sy/2.0+sy/2.0*cos(angle2()/180.0*3.141592));
102fl_pie(xp-2,yp-2,4,4,0,360);
103
104
105
106
107
108fl_push_matrix();
109
110 fl_translate(cx+sx/2,cy+sy/2);
111 fl_rotate(a-90.0);
112
113 fl_translate(sx/2,0);
114
115
116 fl_begin_polygon();
117 pdialcolor(0,0,0);
118 fl_vertex(-10,-4);
119 fl_vertex(-10,4);
120 fl_vertex(0,0);
121 fl_end_polygon();
122
123
124fl_pop_matrix();} {}
125 }
126 Function {pdialcolor(int r,int g,int b)} {} {
127 code {if (active_r()) fl_color(r,g,b);
128 else fl_color(160-(160-r)/3,160-(160-b)/3,160-(160-b)/3);} {}
129 }
130 decl {double oldvalue;} {}
131}
diff --git a/src/frontend/dialog_choosedevice.fl b/src/frontend/dialog_choosedevice.fl
new file mode 100755
index 0000000..142b5f5
--- /dev/null
+++ b/src/frontend/dialog_choosedevice.fl
@@ -0,0 +1,99 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0109
3header_name {.h}
4code_name {.cxx}
5decl {\#include <hd24fs.h>} {public
6}
7
8decl {\#include <hd24devicenamegenerator.h>} {public
9}
10
11decl {\#include <vector>} {public
12}
13
14class dialog_choosedevice {open
15} {
16 decl {int buttonclicked;} {public
17 }
18 decl {int choice_startloc;} {public
19 }
20 decl {hd24fs* currfs;} {public
21 }
22 decl {int devnums[10000];} {}
23 decl {string* devicename;} {public
24 }
25 Function {fill_devices()} {open return_type void
26 } {
27 code {hd24devicenamegenerator* dng=new hd24devicenamegenerator();
28
29__uint32 totnames=dng->getnumberofnames();
30device->add("--Use other device--",0,NULL,(void*)this);
31int n=0;
32for (__uint32 i=0;i<totnames;i++)
33{
34 string* devname=dng->getdevicename(i);
35 if (currfs->isexistingdevice(devname))
36 {
37 device->add(devname->c_str(),0,NULL,(void*)this);
38 n++;
39 devnums[n]=i;
40 }
41 delete(devname);
42}
43device->value(1);} {}
44 }
45 Function {make_window(hd24fs* p_currfs)} {open
46 } {
47 Fl_Window {} {
48 label {Choose HD24 device} open selected
49 xywh {389 296 590 115} type Double color 52 labelsize 12
50 code0 {buttonclicked=0;}
51 code1 {currfs=p_currfs;}
52 code2 {currdev->value(currfs->getdevicename()->c_str());} modal visible
53 } {
54 Fl_Button button_ok {
55 label OK
56 callback {buttonclicked=1; //OK
57if (device->value()==0) {
58 devicename=new string(otherdevice->value());
59} else {
60 hd24devicenamegenerator* dng=new hd24devicenamegenerator();
61 devicename=dng->getdevicename((__uint32)devnums[device->value()]);
62 delete dng;
63}
64//choice_startloc=fromloc->value();
65//choice_endloc=toloc->value();
66Fl_Window * x = Fl::first_window();
67x->~Fl_Window();}
68 xywh {430 85 70 25}
69 }
70 Fl_Button button_cancel {
71 label Cancel
72 callback {buttonclicked=2; //Cancel
73Fl_Window * x = Fl::first_window();
74x->~Fl_Window();}
75 xywh {505 85 70 25}
76 }
77 Fl_Choice device {
78 label {Choose device:}
79 callback {if (device->value()!=0) {
80 otherdevice->deactivate();
81} else {
82 otherdevice->activate();
83 otherdevice->take_focus();
84}} open
85 xywh {115 30 460 20} down_box BORDER_BOX labelsize 12 textsize 12
86 code0 {fill_devices();}
87 } {}
88 Fl_Input otherdevice {
89 label {Other device:}
90 xywh {115 55 460 20} labelsize 12 textsize 12 deactivate
91 code0 {o->maximum_size(64);}
92 }
93 Fl_Output currdev {
94 label {Current device:}
95 xywh {115 5 240 20} box FLAT_BOX color 53 labelsize 12 textsize 12
96 }
97 }
98 }
99}
diff --git a/src/frontend/dialog_filesize.fl b/src/frontend/dialog_filesize.fl
new file mode 100755
index 0000000..df67208
--- /dev/null
+++ b/src/frontend/dialog_filesize.fl
@@ -0,0 +1,131 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0107
3header_name {.h}
4code_name {.cxx}
5decl {\#include <hd24fs.h>} {public
6}
7
8decl {\#include <FL/fl_ask.H>} {public
9}
10
11class dialog_filesize {open
12} {
13 decl {int buttonclicked;} {public
14 }
15 decl {__uint32 lastsector;} {public
16 }
17 Function {make_window()} {open
18 } {
19 Fl_Window filesizewindow {
20 label {Image size} open
21 xywh {351 357 340 105} type Double color 52 labelsize 12
22 code0 {buttonclicked=0;} modal visible
23 } {
24 Fl_Button button_ok {
25 label OK
26 callback {buttonclicked=1; //OK
27//char dest[66];
28//strncpy(&dest[0],currname->value(),64);
29//dest[64]='\\0';
30//itemname=new string(dest);
31__uint64 sizeval=strtol(filesize->value(),0,10);
32switch (sizeunit->value()) {
33 case 0:
34 sizeval*=2048;
35 break;
36 case 1:
37 sizeval*=1024*2048;
38 break;
39 default:
40 break;
41}
42sizeval--;
43if (sizeval>0xFFFFFFFF) {
44 sizeval=0xFFFFFFFF;
45}
46this->lastsector=(__uint32)(sizeval & 0xFFFFFFFF);
47Fl_Window * x = Fl::first_window();
48x->~Fl_Window();}
49 xywh {185 80 70 20} labelsize 12
50 }
51 Fl_Button button_cancel {
52 label Cancel
53 callback {buttonclicked=2; //Cancel
54Fl_Window * x = Fl::first_window();
55x->~Fl_Window();}
56 xywh {260 80 70 20} labelsize 12
57 }
58 Fl_Input filesize {
59 label {Enter size:}
60 xywh {120 55 120 20} labelsize 12 textsize 12
61 code0 {o->maximum_size(16);}
62 code1 {o->take_focus();}
63 }
64 Fl_Choice preset {
65 label {Select preset size} open selected
66 xywh {120 10 210 20} down_box BORDER_BOX labelsize 12 textsize 12
67 code0 {o->value(0);}
68 } {
69 MenuItem {} {
70 label {Specified below}
71 callback {sizeunit->activate();
72filesize->activate();}
73 xywh {0 0 34 21} labelsize 12
74 }
75 MenuItem {} {
76 label {DVD+R (Single layer)}
77 callback {sizeunit->value(2);
78filesize->value("9180416");
79sizeunit->deactivate();
80filesize->deactivate();}
81 xywh {10 10 34 21} labelsize 12
82 }
83 MenuItem {} {
84 label {DVD-R (Single layer)}
85 callback {sizeunit->value(2);
86filesize->value("9193984");
87sizeunit->deactivate();
88filesize->deactivate();}
89 xywh {20 20 34 21} labelsize 12
90 }
91 MenuItem {} {
92 label {DVD+R (Dual Layer)}
93 callback {sizeunit->value(2);
94filesize->value("16695296");
95sizeunit->deactivate();
96filesize->deactivate();}
97 xywh {20 20 34 21} labelsize 12
98 }
99 MenuItem {} {
100 label {DVD-R (Dual layer)}
101 callback {sizeunit->value(2);
102filesize->value("16686848");
103sizeunit->deactivate();
104filesize->deactivate();}
105 xywh {30 30 34 21} labelsize 12
106 }
107 }
108 Fl_Choice sizeunit {open
109 xywh {245 55 85 20} down_box BORDER_BOX labelsize 12
110 code0 {o->value(1);}
111 } {
112 MenuItem {} {
113 label MB
114 xywh {10 10 34 21}
115 }
116 MenuItem {} {
117 label GB
118 xywh {20 20 34 21}
119 }
120 MenuItem {} {
121 label Sectors
122 xywh {20 20 34 21}
123 }
124 }
125 Fl_Box {} {
126 label {- OR -}
127 xywh {85 33 35 17} labelsize 12
128 }
129 }
130 }
131}
diff --git a/src/frontend/dialog_fromto.fl b/src/frontend/dialog_fromto.fl
new file mode 100755
index 0000000..2c5ecb4
--- /dev/null
+++ b/src/frontend/dialog_fromto.fl
@@ -0,0 +1,50 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0107
3header_name {.h}
4code_name {.cxx}
5decl {\#include <hd24fs.h>} {public
6}
7
8class dialog_fromto {open
9} {
10 decl {int buttonclicked;} {public
11 }
12 decl {int choice_startloc;} {public
13 }
14 decl {int choice_endloc;} {public
15 }
16 Function {make_window(hd24song* currsong)} {open
17 } {
18 Fl_Window {} {
19 label {Set range} open selected
20 xywh {315 299 360 85} type Double color 52
21 code0 {buttonclicked=0;}
22 code1 {currsong=currsong;} modal visible
23 } {
24 Fl_Button button_ok {
25 label OK
26 callback {buttonclicked=1; //OK
27choice_startloc=fromloc->value();
28choice_endloc=toloc->value();
29Fl_Window * x = Fl::first_window();
30x->~Fl_Window();}
31 xywh {210 55 70 25}
32 }
33 Fl_Button button_cancel {
34 label Cancel
35 callback {buttonclicked=2; //Cancel
36Fl_Window * x = Fl::first_window();
37x->~Fl_Window();}
38 xywh {285 55 70 25}
39 }
40 Fl_Choice fromloc {
41 label {From location:} open
42 xywh {115 5 240 20} down_box BORDER_BOX labelsize 12 textsize 12
43 } {}
44 Fl_Choice toloc {
45 label {To location:} open
46 xywh {115 30 240 20} down_box BORDER_BOX labelsize 12 textsize 12
47 } {}
48 }
49 }
50}
diff --git a/src/frontend/dialog_newproject.fl b/src/frontend/dialog_newproject.fl
new file mode 100755
index 0000000..2de1335
--- /dev/null
+++ b/src/frontend/dialog_newproject.fl
@@ -0,0 +1,86 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0107
3header_name {.h}
4code_name {.cxx}
5decl {\#include <hd24fs.h>} {public
6}
7
8decl {\#include <convertlib.h>} {public
9}
10
11class dialog_newproject {open
12} {
13 decl {int buttonclicked;} {public
14 }
15 decl {char projectname[65];} {public
16 }
17 Function {make_window()} {open
18 } {
19 Fl_Window {} {
20 label {New project} open
21 xywh {247 417 500 85} type Double color 52
22 code0 {buttonclicked=0;} modal visible
23 } {
24 Fl_Button button_ok {
25 label OK
26 callback {
27for (int i=0;i<65;i++) {
28 projectname[i]=0;
29}
30strncpy(projectname,currname->value(),64);
31buttonclicked=1; //OK
32Fl_Window * x = Fl::first_window();
33x->~Fl_Window();} selected
34 xywh {345 60 70 20} labelsize 12
35 }
36 Fl_Button button_cancel {
37 label Cancel
38 callback {buttonclicked=2; //Cancel
39Fl_Window * x = Fl::first_window();
40x->~Fl_Window();}
41 xywh {420 60 70 20} labelsize 12
42 }
43 Fl_Input currname {
44 label {Project name:}
45 callback {char filteredname[65];
46int x=strlen(o->value());
47if (x>64) { x=64; }
48int src=0;
49int filtered=0;
50for (int i=0;i<x;i++) {
51 if (
52 (o->value()[i]=='\\\\')
53 || (o->value()[i]=='/')
54 || (o->value()[i]==':')
55 || (o->value()[i]=='*')
56 || (o->value()[i]=='?')
57 || (o->value()[i]=='"')
58 || (o->value()[i]=='<')
59 || (o->value()[i]=='>')
60 || (o->value()[i]=='\\\\')
61 || (o->value()[i]=='|'))
62 {
63 filtered=1;
64 continue;
65 }
66 filteredname[src]=o->value()[i];
67 src++;
68}
69filteredname[src]='\\0';
70if (filtered==1) {
71 int pos=o->position()-1;
72 if (pos<0) pos=0;
73 o->value(filteredname);
74 o->position(pos,pos);
75}}
76 xywh {100 35 390 20} labelsize 12 when 1 textsize 12
77 code0 {o->maximum_size(64);}
78 code1 {o->value("Proj Name"); o->take_focus();}
79 }
80 Fl_Box {} {
81 label {Please specify the name for the new project below:}
82 xywh {5 8 485 19} labelfont 1 labelsize 12 align 20
83 }
84 }
85 }
86}
diff --git a/src/frontend/dialog_newsong.fl b/src/frontend/dialog_newsong.fl
new file mode 100755
index 0000000..3974649
--- /dev/null
+++ b/src/frontend/dialog_newsong.fl
@@ -0,0 +1,352 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0107
3header_name {.h}
4code_name {.cxx}
5decl {\#include <hd24fs.h>} {public
6}
7
8decl {\#include <convertlib.h>} {public
9}
10
11class dialog_newsong {open
12} {
13 decl {int buttonclicked;} {public
14 }
15 decl {char songname[65];} {public
16 }
17 decl {unsigned long songlength_in_samples;} {public
18 }
19 decl {__uint32 samplerate;} {public
20 }
21 decl {__uint32 trackcount;} {public
22 }
23 decl {int mode;} {public
24 }
25 decl {int useasrange;} {public
26 }
27 decl {int locnum;} {}
28 decl {int subsecmax;} {}
29 Function {make_window()} {open
30 } {
31 Fl_Window {} {
32 label {New song} open
33 xywh {212 241 500 180} type Double color 52
34 code0 {buttonclicked=0; mode=2; songname[0]='\\0';}
35 code1 {subsecmax=29; samplerate=44100; trackcount=24;}
36 code2 {setuiloc(0);} modal visible
37 } {
38 Fl_Button button_ok {
39 label OK
40 callback {buttonclicked=1; //OK
41strncpy(songname,currname->value(),64);
42songlength_in_samples=getsonglen();
43Fl_Window * x = Fl::first_window();
44x->~Fl_Window();}
45 xywh {345 155 70 20} labelsize 12
46 }
47 Fl_Button button_cancel {
48 label Cancel
49 callback {buttonclicked=2; //Cancel
50useasrange=0;
51Fl_Window * x = Fl::first_window();
52x->~Fl_Window();}
53 xywh {420 155 70 20} labelsize 12
54 }
55 Fl_Input hr {
56 label {Length: }
57 callback {setuiloc(getsonglen());}
58 xywh {100 130 50 20} type Int labelsize 12 textsize 12
59 code0 {o->maximum_size(2);}
60 }
61 Fl_Input min {
62 label {:}
63 callback {setuiloc(getsonglen());}
64 xywh {160 130 45 20} type Int labelfont 1 labelsize 12 textsize 12
65 code0 {o->maximum_size(2);}
66 }
67 Fl_Input sec {
68 label {:}
69 callback {setuiloc(getsonglen());}
70 xywh {215 130 45 20} type Int labelfont 1 labelsize 12 textsize 12
71 code0 {o->maximum_size(2);}
72 }
73 Fl_Input subsec {
74 label {.}
75 callback {setuiloc(getsonglen());}
76 xywh {270 130 60 20} type Int labelfont 1 labelsize 12 textsize 12
77 code0 {o->maximum_size(5);}
78 }
79 Fl_Button button_mode {
80 label Frames
81 callback {setplchan();
82
83mode=(mode+1)%3;
84switch(mode) {
85 case 0:
86 {
87 o->label("Sec/100");
88 subsecmax=99;
89 break;
90 }
91 case 1:
92 {
93
94 if ((pchan /lchan)==2) {
95 o->label("2*Sams");
96 } else {
97 o->label("Samples");
98 }
99 subsecmax=samplerate/(pchan/lchan);
100 break;
101 }
102 case 2:
103 {
104 o->label("Frames");
105 subsecmax=29;
106 break;
107 }
108}
109setuiloc(songlength_in_samples);}
110 xywh {270 110 60 20} labelsize 12 align 18
111 }
112 Fl_Box {} {
113 label Hr
114 xywh {100 113 50 17} labelsize 12
115 }
116 Fl_Box {} {
117 label Min
118 xywh {160 113 45 17} labelsize 12
119 }
120 Fl_Box {} {
121 label Sec
122 xywh {215 113 45 17} labelsize 12
123 }
124 Fl_Input currname {
125 label {Song name:}
126 callback {char filteredname[65];
127int x=strlen(o->value());
128if (x>64) { x=64; }
129int src=0;
130int filtered=0;
131for (int i=0;i<x;i++) {
132 if (
133 (o->value()[i]=='\\\\')
134 || (o->value()[i]=='/')
135 || (o->value()[i]==':')
136 || (o->value()[i]=='*')
137 || (o->value()[i]=='?')
138 || (o->value()[i]=='"')
139 || (o->value()[i]=='<')
140 || (o->value()[i]=='>')
141 || (o->value()[i]=='\\\\')
142 || (o->value()[i]=='|'))
143 {
144 filtered=1;
145 continue;
146 }
147 filteredname[src]=o->value()[i];
148 src++;
149}
150filteredname[src]='\\0';
151if (filtered==1) {
152 int pos=o->position()-1;
153 if (pos<0) pos=0;
154 o->value(filteredname);
155 o->position(pos,pos);
156}}
157 xywh {100 35 390 20} labelsize 12 when 1 textsize 12
158 code0 {o->maximum_size(64);}
159 code1 {o->value("Song Name"); o->take_focus();}
160 }
161 Fl_Choice ratechoice {
162 label {Sample rate:} open
163 xywh {100 60 145 20} down_box BORDER_BOX labelsize 12 textsize 12
164 code0 {o->value(0);}
165 } {
166 MenuItem {} {
167 label {44100 Hz}
168 callback {samplerate=44100; setuiloc(getsonglen());}
169 xywh {35 35 36 21} labelsize 12
170 }
171 MenuItem {} {
172 label {48000 Hz}
173 callback {samplerate=48000;setuiloc(getsonglen());}
174 xywh {45 45 36 21} labelsize 12
175 }
176 MenuItem {} {
177 label {88200 Hz}
178 callback {samplerate=88200; setuiloc(getsonglen());
179if (numtracks->value()>7)
180{
181 numtracks->value(7);
182 trackcount=12;
183}}
184 xywh {55 55 36 21} labelsize 12
185 }
186 MenuItem {} {
187 label {96000 Hz}
188 callback {samplerate=96000; setuiloc(getsonglen());
189if (numtracks->value()>7)
190{
191 numtracks->value(7);
192 trackcount=12;
193}}
194 xywh {65 65 36 21} labelsize 12
195 }
196 }
197 Fl_Choice numtracks {
198 label {\# of Tracks:} open
199 xywh {100 85 145 20} down_box BORDER_BOX labelsize 12 textsize 12
200 code0 {o->value(10);}
201 } {
202 MenuItem {} {
203 label 1
204 callback {trackcount=1;}
205 xywh {45 45 36 21} labelsize 12
206 }
207 MenuItem {} {
208 label 2
209 callback {trackcount=2;}
210 xywh {55 55 36 21} labelsize 12
211 }
212 MenuItem {} {
213 label 3
214 callback {trackcount=3;}
215 xywh {65 65 36 21} labelsize 12
216 }
217 MenuItem {} {
218 label 4
219 callback {trackcount=4;}
220 xywh {75 75 36 21} labelsize 12
221 }
222 MenuItem {} {
223 label 6
224 callback {trackcount=6;}
225 xywh {85 85 36 21} labelsize 12
226 }
227 MenuItem {} {
228 label 8
229 callback {trackcount=8;}
230 xywh {95 95 36 21} labelsize 12
231 }
232 MenuItem {} {
233 label 9
234 callback {trackcount=9;}
235 xywh {105 105 36 21} labelsize 12
236 }
237 MenuItem {} {
238 label 12
239 callback {trackcount=12;}
240 xywh {105 105 36 21} labelsize 12
241 }
242 MenuItem {} {
243 label 16
244 callback {trackcount=16;
245if (samplerate>=88200)
246{
247 trackcount=12;
248 numtracks->value(7);
249}}
250 xywh {115 115 36 21} labelsize 12
251 }
252 MenuItem {} {
253 label 18
254 callback {trackcount=18;
255if (samplerate>=88200)
256{
257 trackcount=12;
258 numtracks->value(7);
259}}
260 xywh {125 125 36 21} labelsize 12
261 }
262 MenuItem {} {
263 label 24
264 callback {trackcount=24;
265if (samplerate>=88200)
266{
267 trackcount=12;
268 numtracks->value(7);
269}}
270 xywh {135 135 36 21} labelsize 12
271 }
272 }
273 Fl_Box {} {
274 label {Please specify the parameters for the new song below:}
275 xywh {5 8 485 19} labelfont 1 labelsize 12 align 20
276 }
277 }
278 }
279 Function {setuiloc(__uint32 offset)} {open return_type void
280 } {
281 code {setplchan();
282unsigned int chmult=(pchan/lchan);
283unsigned long realrate=samplerate/chmult;
284
285string* strhr=Convert::int2str(hd24song::display_hours(offset,realrate));
286hr->value(strhr->c_str());
287delete strhr;
288
289string* strmin=Convert::int2str(hd24song::display_minutes(offset,realrate));
290min->value(strmin->c_str());
291delete strmin;
292
293string* strsec=Convert::int2str(hd24song::display_seconds(offset,realrate));
294sec->value(strsec->c_str());
295delete strsec;
296
297string* strsubsec;
298
299long subseconds=hd24song::display_subseconds(offset,realrate);
300long subsecval;
301setplchan();
302
303switch(mode) {
304 case 0: subsecval=((subseconds*100)/ realrate ); break;
305 case 1: subsecval=(subseconds); break;
306 case 2: subsecval=((subseconds*30)/realrate ); break;
307 default: subsecval=0;
308}
309strsubsec=Convert::int2str(subsecval);
310subsec->value(strsubsec->c_str());
311delete strsubsec;} {}
312 }
313 Function {setplchan()} {open
314 } {
315 code {lchan = trackcount;
316if (this->samplerate>=88200) {
317 pchan=lchan*2;
318} else {
319 pchan=lchan;
320}} {}
321 }
322 decl {int pchan;} {}
323 decl {int lchan;} {}
324 Function {getsonglen()} {open return_type __uint32
325 } {
326 code {setplchan();
327unsigned int chmult=(pchan/lchan);
328unsigned long realrate=samplerate/chmult;
329
330long frames=0;
331switch(mode) {
332 case 0: frames=100; break;
333 case 1: frames=realrate; break;
334 case 2: frames=30; break;
335}
336
337__uint64 mylocpoint=((__uint64)3600* (__uint64)strtol( hr->value(),0,10) )
338 +((__uint64) 60* (__uint64)strtol(min->value(),0,10) )
339 +((__uint64) 1* (__uint64)strtol(sec->value(),0,10) )
340 ;
341
342mylocpoint=(__uint64)((__uint64)realrate*(__uint64)mylocpoint);
343
344mylocpoint+=(__uint64)(strtol(subsec->value(),0,10)*samplerate/(frames*chmult));
345
346if (mylocpoint>0xFFFFFFFF) {
347 mylocpoint=0xFFFFFFFF;
348}
349return (__uint32)mylocpoint;} {selected
350 }
351 }
352}
diff --git a/src/frontend/dialog_options.fl b/src/frontend/dialog_options.fl
new file mode 100755
index 0000000..39a3a54
--- /dev/null
+++ b/src/frontend/dialog_options.fl
@@ -0,0 +1,131 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0107
3header_name {.h}
4code_name {.cxx}
5decl {\#include <hd24fs.h>} {public
6}
7
8decl {\#include <FL/fl_ask.H>} {public
9}
10
11class dialog_options {open
12} {
13 decl {int buttonclicked;} {public
14 }
15 decl {hd24song* currsong;} {}
16 decl {string* itemname;} {public
17 }
18 Function {~dialog_options()} {open
19 } {
20 code {if (itemname!=NULL) delete itemname;} {}
21 }
22 decl {int locnum;} {}
23 Function {make_window()} {open
24 } {
25 Fl_Window optionswindow {
26 label options open
27 xywh {420 519 565 145} type Double color 52 hide
28 code0 {buttonclicked=0;} modal
29 } {
30 Fl_Tabs {} {open
31 xywh {0 0 565 145}
32 } {
33 Fl_Group {} {
34 label Catalog open
35 xywh {0 20 565 125} labelsize 12 hide
36 } {
37 Fl_Check_Button {} {
38 label {Include locate point information in drive catalog}
39 xywh {5 25 550 15} down_box DOWN_BOX labelsize 12 deactivate
40 }
41 Fl_Button button_catalogapply {
42 label Apply
43 callback {buttonclicked=1; //OK
44char dest[66];
45strncpy(&dest[0],currname->value(),64);
46dest[64]='\\0';
47itemname=new string(dest);
48Fl_Window * x = Fl::first_window();
49x->~Fl_Window();}
50 xywh {480 110 70 20} labelsize 12
51 }
52 Fl_Check_Button {} {
53 label {Keep catalog sorted alphabetically}
54 xywh {5 45 550 15} down_box DOWN_BOX labelsize 12 deactivate
55 }
56 }
57 Fl_Group {} {
58 label Transfers open
59 xywh {0 20 565 125} labelsize 12
60 } {
61 Fl_Button button_ok {
62 label Apply
63 callback {buttonclicked=1; //OK
64char dest[66];
65strncpy(&dest[0],currname->value(),64);
66dest[64]='\\0';
67itemname=new string(dest);
68Fl_Window * x = Fl::first_window();
69x->~Fl_Window();}
70 xywh {480 110 70 20} labelsize 12
71 }
72 Fl_Input currname {
73 label {Output file name:}
74 callback {char filteredname[65];
75int x=strlen(o->value());
76if (x>64) { x=64; }
77int src=0;
78int filtered=0;
79for (int i=0;i<x;i++) {
80 if (
81 (o->value()[i]=='\\\\')
82 || (o->value()[i]=='/')
83 || (o->value()[i]==':')
84 || (o->value()[i]=='*')
85 || (o->value()[i]=='?')
86 || (o->value()[i]=='"')
87 || (o->value()[i]=='<')
88 || (o->value()[i]=='>')
89 || (o->value()[i]=='\\\\')
90 || (o->value()[i]=='|'))
91 {
92 filtered=1;
93 continue;
94 }
95 filteredname[src]=o->value()[i];
96 src++;
97}
98filteredname[src]='\\0';
99if (filtered==1) {
100 int pos=o->position()-1;
101 if (pos<0) pos=0;
102 o->value(filteredname);
103 o->position(pos,pos);
104}}
105 xywh {120 25 435 20} labelsize 12 when 1 textsize 12
106 code0 {o->maximum_size(64);}
107 code1 {o->take_focus();}
108 }
109 Fl_Button button_transferhelp {
110 label Help
111 callback {fl_message("The following special sequences can be used:\\n"
112 "<drivename>\\t\\tThe volume label of the drive\\n"
113 "<projname>\\t\\tThe name of the project\\n"
114 "<songname>\\t\\tThe name of the song\\n"
115 "<projnum>\\t\\tThe sequence number of the project on disk\\n"
116 "<songnum>\\t\\tThe sequence number of the song within the project\\n"
117 "<tracknum>\\t\\tThe track number being transferred\\n"
118 "<tracknum+offset>\\tLikewise, prompt for offset before transfer\\n"
119 "<timestamp>\\t\\tCurrent date/time (YYYY-MM-DD HH:MI:SS)\\n"
120);} selected
121 xywh {405 110 70 20} labelsize 12
122 }
123 }
124 }
125 }
126 }
127 Function {dialog_options()} {open
128 } {
129 code {itemname=NULL;} {}
130 }
131}
diff --git a/src/frontend/dialog_rate.fl b/src/frontend/dialog_rate.fl
new file mode 100755
index 0000000..9f397bf
--- /dev/null
+++ b/src/frontend/dialog_rate.fl
@@ -0,0 +1,58 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0107
3header_name {.h}
4code_name {.cxx}
5decl {\#include <hd24fs.h>} {public
6}
7
8decl {\#include <FL/fl_ask.H>} {public
9}
10
11class dialog_rename {open
12} {
13 decl {int buttonclicked;} {public
14 }
15 decl {hd24song* currsong;} {}
16 decl {string* itemname;} {public
17 }
18 Function {~dialog_rename()} {open
19 } {
20 code {if (itemname!=NULL) delete itemname;} {}
21 }
22 decl {int locnum;} {}
23 Function {make_window(string* p_currname,string* p_title)} {open
24 } {
25 Fl_Window renamewindow {
26 label {Sample rate} open
27 xywh {277 310 490 75} type Double color 52
28 code0 {buttonclicked=0;}
29 code1 {currname->value(p_currname->c_str());}
30 code2 {o->label(p_title->c_str());} modal visible
31 } {
32 Fl_Button button_ok {
33 label OK
34 callback {buttonclicked=1; //OK
35char dest[66];
36strncpy(&dest[0],currname->value(),64);
37dest[64]='\\0';
38itemname=new string(dest);
39Fl_Window * x = Fl::first_window();
40x->~Fl_Window();}
41 xywh {330 40 70 25}
42 }
43 Fl_Button button_cancel {
44 label Cancel
45 callback {buttonclicked=2; //Cancel
46Fl_Window * x = Fl::first_window();
47x->~Fl_Window();}
48 xywh {405 40 70 25}
49 }
50 Fl_Input currname {
51 label {New rate:} selected
52 xywh {90 10 385 20} labelsize 12 textsize 12
53 code0 {o->maximum_size(64);}
54 code1 {o->take_focus();}
55 }
56 }
57 }
58}
diff --git a/src/frontend/dialog_rename.fl b/src/frontend/dialog_rename.fl
new file mode 100755
index 0000000..d7bd419
--- /dev/null
+++ b/src/frontend/dialog_rename.fl
@@ -0,0 +1,89 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0107
3header_name {.h}
4code_name {.cxx}
5decl {\#include <hd24fs.h>} {public
6}
7
8decl {\#include <FL/fl_ask.H>} {public
9}
10
11class dialog_rename {open
12} {
13 decl {int buttonclicked;} {public
14 }
15 decl {hd24song* currsong;} {}
16 decl {string* itemname;} {public
17 }
18 Function {~dialog_rename()} {open
19 } {
20 code {if (itemname!=NULL) delete itemname;} {}
21 }
22 decl {int locnum;} {}
23 Function {make_window(string* p_currname,string* p_title)} {open
24 } {
25 Fl_Window renamewindow {
26 label Rename open
27 xywh {111 127 490 75} type Double color 52
28 code0 {buttonclicked=0;}
29 code1 {currname->value(p_currname->c_str());}
30 code2 {o->label(p_title->c_str());} modal visible
31 } {
32 Fl_Button button_ok {
33 label OK
34 callback {buttonclicked=1; //OK
35char dest[66];
36strncpy(&dest[0],currname->value(),64);
37dest[64]='\\0';
38itemname=new string(dest);
39Fl_Window * x = Fl::first_window();
40x->~Fl_Window();}
41 xywh {330 40 70 25}
42 }
43 Fl_Button button_cancel {
44 label Cancel
45 callback {buttonclicked=2; //Cancel
46Fl_Window * x = Fl::first_window();
47x->~Fl_Window();}
48 xywh {405 40 70 25}
49 }
50 Fl_Input currname {
51 label {New Name:}
52 callback {char filteredname[65];
53int x=strlen(o->value());
54if (x>64) { x=64; }
55int src=0;
56int filtered=0;
57for (int i=0;i<x;i++) {
58 if (
59 (o->value()[i]=='\\\\')
60 || (o->value()[i]=='/')
61 || (o->value()[i]==':')
62 || (o->value()[i]=='*')
63 || (o->value()[i]=='?')
64 || (o->value()[i]=='"')
65 || (o->value()[i]=='<')
66 || (o->value()[i]=='>')
67 || (o->value()[i]=='\\\\')
68 || (o->value()[i]=='|'))
69 {
70 filtered=1;
71 continue;
72 }
73 filteredname[src]=o->value()[i];
74 src++;
75}
76filteredname[src]='\\0';
77if (filtered==1) {
78 int pos=o->position()-1;
79 if (pos<0) pos=0;
80 o->value(filteredname);
81 o->position(pos,pos);
82}} selected
83 xywh {90 10 385 20} labelsize 12 when 1 textsize 12
84 code0 {o->maximum_size(64);}
85 code1 {o->take_focus();}
86 }
87 }
88 }
89}
diff --git a/src/frontend/dialog_setlength.fl b/src/frontend/dialog_setlength.fl
new file mode 100755
index 0000000..1927f95
--- /dev/null
+++ b/src/frontend/dialog_setlength.fl
@@ -0,0 +1,204 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0107
3header_name {.h}
4code_name {.cxx}
5decl {\#include <hd24fs.h>} {public
6}
7
8decl {\#include <convertlib.h>} {public
9}
10
11class dialog_setlength {open
12} {
13 decl {int buttonclicked;} {public
14 }
15 decl {unsigned long locpoint;} {public
16 }
17 decl {int mode;} {public
18 }
19 decl {int useasrange;} {public
20 }
21 decl {hd24song* currsong;} {}
22 decl {int locnum;} {}
23 decl {int subsecmax;} {}
24 Function {make_window(hd24song* p_currsong,int p_locnum)} {open
25 } {
26 Fl_Window {} {
27 label {Set song length} open selected
28 xywh {160 246 455 300} type Double color 52
29 code0 {currsong=p_currsong; buttonclicked=0; mode=2;}
30 code1 {locpoint=currsong->songlength_in_samples();}
31 code2 {setuiloc(locpoint); subsecmax=29;}
32 code3 {p_locnum=p_locnum;} modal visible
33 } {
34 Fl_Button button_ok {
35 label OK
36 callback {buttonclicked=1; //OK
37Fl_Window * x = Fl::first_window();
38x->~Fl_Window();}
39 xywh {300 270 70 20} labelsize 12
40 }
41 Fl_Button button_cancel {
42 label Cancel
43 callback {buttonclicked=2; //Cancel
44useasrange=0;
45Fl_Window * x = Fl::first_window();
46x->~Fl_Window();}
47 xywh {375 270 70 20} labelsize 12
48 }
49 Fl_Input hr {
50 label {New song length: }
51 callback {unsigned int chmult=(currsong->physical_channels()/currsong->logical_channels());
52unsigned long realrate=currsong->samplerate()/chmult;
53
54locpoint-=(unsigned long)(3600*realrate*(currsong->display_hours(locpoint)));
55locpoint+=(unsigned long)(3600*realrate*(strtol(hr->value(),0,10)));
56setuiloc(locpoint);}
57 xywh {150 65 50 20} type Int labelsize 12 textsize 12
58 code0 {o->maximum_size(2);}
59 }
60 Fl_Input min {
61 label {:}
62 callback {unsigned int chmult=(currsong->physical_channels()/currsong->logical_channels());
63unsigned long realrate=currsong->samplerate()/chmult;
64
65locpoint-=(unsigned long)(60*realrate*(currsong->display_minutes(locpoint)));
66locpoint+=(unsigned long)(60*realrate*(strtol(min->value(),0,10)));
67setuiloc(locpoint);}
68 xywh {210 65 45 20} type Int labelfont 1 labelsize 12 textsize 12
69 code0 {o->maximum_size(2);}
70 }
71 Fl_Input sec {
72 label {:}
73 callback {unsigned int chmult=(currsong->physical_channels()/currsong->logical_channels());
74unsigned long realrate=currsong->samplerate()/chmult;
75
76locpoint-=(unsigned long)(realrate*(currsong->display_seconds(locpoint)));
77locpoint+=(unsigned long)(realrate*(strtol(sec->value(),0,10)));
78setuiloc(locpoint);}
79 xywh {265 65 45 20} type Int labelfont 1 labelsize 12 textsize 12
80 code0 {o->maximum_size(2);}
81 }
82 Fl_Input subsec {
83 label {.}
84 callback {if (strtol(subsec->value(),0,10)>subsecmax) {
85 string* strmax=Convert::int2str(subsecmax);
86 subsec->value(strmax->c_str());
87 delete strmax;
88
89}
90
91unsigned int chmult=(currsong->physical_channels()/currsong->logical_channels());
92unsigned long realrate=currsong->samplerate()/chmult;
93
94long subseconds=currsong->display_subseconds(locpoint);
95
96locpoint-=subseconds;
97
98long frames=0;
99switch(mode) {
100 case 0: frames=100; break;
101 case 1: frames=realrate; break;
102 case 2: frames=30; break;
103}
104locpoint+=(unsigned long)(strtol(subsec->value(),0,10)*currsong->samplerate()/(frames*chmult));
105setuiloc(locpoint);}
106 xywh {320 65 60 20} type Int labelfont 1 labelsize 12 textsize 12
107 code0 {o->maximum_size(5);}
108 }
109 Fl_Button button_mode {
110 label Frames
111 callback {mode=(mode+1)%3;
112switch(mode) {
113 case 0:
114 {
115 o->label("Sec/100");
116 subsecmax=99;
117 break;
118 }
119 case 1:
120 {
121
122 if ((currsong->physical_channels()/currsong->logical_channels())==2) {
123 o->label("2*Sams");
124 } else {
125 o->label("Samples");
126 }
127 subsecmax=currsong->samplerate()/(currsong->physical_channels()/currsong->logical_channels());
128 break;
129 }
130 case 2:
131 {
132 o->label("Frames");
133 subsecmax=29;
134 break;
135 }
136}
137setuiloc(locpoint);}
138 xywh {320 45 60 20} labelsize 12 align 18
139 }
140 Fl_Box {} {
141 label Hr
142 xywh {150 48 50 17} labelsize 12
143 }
144 Fl_Box {} {
145 label Min
146 xywh {210 48 45 17} labelsize 12
147 }
148 Fl_Box {} {
149 label Sec
150 xywh {265 48 45 17} labelsize 12
151 }
152 Fl_Box {} {
153 label {Set the approximate song length here. Round up when unsure.}
154 xywh {5 5 440 30} labelsize 12 align 20
155 }
156 Fl_Box {} {
157 label {Note: This operation will requires about 40 MB of free space to write
158recovery information to a header file on your computer.
159
160This operation WILL NOT write to your HD24 drive, and as such should
161be completely safe, while permitting you to save your missing audio.
162Once this operation is complete, you should TRANSFER ALL AUDIO
163that you want to keep from the HD24 drive and then re-format it,
164before recording any more audio to it.
165
166Cancel this dialog if you're not in need of a recovery.}
167 xywh {5 100 440 160} labelsize 12 align 21
168 }
169 }
170 }
171 Function {setuiloc(unsigned long offset)} {open return_type void
172 } {
173 code {unsigned long maxoffset=0xFFFFFFFF;
174if (offset>maxoffset) {
175 offset=maxoffset;
176 locpoint=offset;
177}
178string* strhr=Convert::int2str(currsong->display_hours(offset));
179hr->value(strhr->c_str());
180delete strhr;
181
182string* strmin=Convert::int2str(currsong->display_minutes(offset));
183min->value(strmin->c_str());
184delete strmin;
185
186string* strsec=Convert::int2str(currsong->display_seconds(offset));
187sec->value(strsec->c_str());
188delete strsec;
189
190string* strsubsec;
191
192long subseconds=currsong->display_subseconds(offset);
193long subsecval;
194switch(mode) {
195 case 0: subsecval=((subseconds*100)/ ( currsong->samplerate()/ (currsong->physical_channels()/currsong->logical_channels()) ) ); break;
196 case 1: subsecval=(subseconds); break;
197 case 2: subsecval=((subseconds*30)/( currsong->samplerate()/ (currsong->physical_channels()/currsong->logical_channels()) ) ); ; break;
198 default: subsecval=0;
199}
200strsubsec=Convert::int2str(subsecval);
201subsec->value(strsubsec->c_str());
202delete strsubsec;} {}
203 }
204}
diff --git a/src/frontend/dialog_setlocate.fl b/src/frontend/dialog_setlocate.fl
new file mode 100755
index 0000000..30de1a6
--- /dev/null
+++ b/src/frontend/dialog_setlocate.fl
@@ -0,0 +1,209 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0107
3header_name {.h}
4code_name {.cxx}
5decl {\#include <hd24fs.h>} {public
6}
7
8decl {\#include <convertlib.h>} {public
9}
10
11class dialog_setlocate {open
12} {
13 decl {int buttonclicked;} {public
14 }
15 decl {unsigned long locpoint;} {public
16 }
17 decl {int mode;} {public
18 }
19 decl {int useasrange;} {public
20 }
21 decl {hd24song* currsong;} {}
22 decl {int locnum;} {}
23 decl {int subsecmax;} {}
24 Function {make_window(hd24song* p_currsong,int p_locnum)} {open
25 } {
26 Fl_Window {} {
27 label {Edit locate point} open
28 xywh {160 247 385 100} type Double color 52
29 code0 {currsong=p_currsong; buttonclicked=0; mode=2; locnum=p_locnum;}
30 code1 {locpoint=currsong->getlocatepos(locnum); locname->value(currsong->getlocatename(locnum)->c_str());}
31 code2 {setuiloc(currsong->getlocatepos(locnum)); subsecmax=29;}
32 code3 {if ((locnum!=1) && (locnum!=2)) { setasrange->hide(); }; if (locnum==1) { setasrange->label("Set as start of export range"); } if (locnum==2) { setasrange->label("Set as end of export range"); }} modal visible
33 } {
34 Fl_Button button_ok {
35 label OK
36 callback {buttonclicked=1; //OK
37char dest[10];
38strncpy(&dest[0],locname->value(),8);
39dest[9]='\\0';
40string* newname=new string(dest);
41currsong->setlocatename(locnum,*newname);
42currsong->setlocatepos(locnum,locpoint);
43useasrange=setasrange->value();
44delete newname;
45Fl_Window * x = Fl::first_window();
46x->~Fl_Window();}
47 xywh {235 75 70 20} labelsize 12
48 }
49 Fl_Button button_cancel {
50 label Cancel
51 callback {buttonclicked=2; //Cancel
52useasrange=0;
53Fl_Window * x = Fl::first_window();
54x->~Fl_Window();}
55 xywh {310 75 70 20} labelsize 12
56 }
57 Fl_Input hr {
58 label {New locate point:}
59 callback {unsigned int chmult=(currsong->physical_channels()/currsong->logical_channels());
60unsigned long realrate=currsong->samplerate()/chmult;
61
62locpoint-=(unsigned long)(3600*realrate*(currsong->display_hours(locpoint)));
63locpoint+=(unsigned long)(3600*realrate*(strtol(hr->value(),0,10)));
64setuiloc(locpoint);}
65 xywh {150 45 50 20} type Int labelsize 12 textsize 12
66 code0 {o->maximum_size(2);}
67 }
68 Fl_Input min {
69 label {:}
70 callback {unsigned int chmult=(currsong->physical_channels()/currsong->logical_channels());
71unsigned long realrate=currsong->samplerate()/chmult;
72
73locpoint-=(unsigned long)(60*realrate*(currsong->display_minutes(locpoint)));
74locpoint+=(unsigned long)(60*realrate*(strtol(min->value(),0,10)));
75setuiloc(locpoint);}
76 xywh {210 45 45 20} type Int labelfont 1 labelsize 12 textsize 12
77 code0 {o->maximum_size(2);}
78 }
79 Fl_Input sec {
80 label {:}
81 callback {unsigned int chmult=(currsong->physical_channels()/currsong->logical_channels());
82unsigned long realrate=currsong->samplerate()/chmult;
83
84locpoint-=(unsigned long)(realrate*(currsong->display_seconds(locpoint)));
85locpoint+=(unsigned long)(realrate*(strtol(sec->value(),0,10)));
86setuiloc(locpoint);}
87 xywh {265 45 45 20} type Int labelfont 1 labelsize 12 textsize 12
88 code0 {o->maximum_size(2);}
89 }
90 Fl_Input subsec {
91 label {.}
92 callback {if (strtol(subsec->value(),0,10)>subsecmax) {
93 string* strmax=Convert::int2str(subsecmax);
94 subsec->value(strmax->c_str());
95 delete strmax;
96
97}
98
99unsigned int chmult=(currsong->physical_channels()/currsong->logical_channels());
100unsigned long realrate=currsong->samplerate()/chmult;
101
102long subseconds=currsong->display_subseconds(locpoint);
103
104locpoint-=subseconds;
105
106long frames=0;
107switch(mode) {
108 case 0: frames=100; break;
109 case 1: frames=realrate; break;
110 case 2: frames=30; break;
111}
112locpoint+=(unsigned long)(strtol(subsec->value(),0,10)*currsong->samplerate()/(frames*chmult));
113setuiloc(locpoint);}
114 xywh {320 45 60 20} type Int labelfont 1 labelsize 12 textsize 12
115 code0 {o->maximum_size(5);}
116 }
117 Fl_Button button_mode {
118 label Frames
119 callback {mode=(mode+1)%3;
120switch(mode) {
121 case 0:
122 {
123 o->label("Sec/100");
124 subsecmax=99;
125 break;
126 }
127 case 1:
128 {
129
130 if ((currsong->physical_channels()/currsong->logical_channels())==2) {
131 o->label("2*Sams");
132 } else {
133 o->label("Samples");
134 }
135 subsecmax=currsong->samplerate()/(currsong->physical_channels()/currsong->logical_channels());
136 break;
137 }
138 case 2:
139 {
140 o->label("Frames");
141 subsecmax=29;
142 break;
143 }
144}
145setuiloc(locpoint);}
146 xywh {320 25 60 20} labelsize 12 align 18
147 }
148 Fl_Input locname {
149 label {Location Name:}
150 callback {char templabel[10];
151strncpy(&templabel[0],o->value(),8);
152templabel[8]='\\0';
153o->value(templabel);}
154 xywh {150 5 115 20} labelsize 12 textsize 12
155 code0 {o->maximum_size(8);}
156 }
157 Fl_Check_Button setasrange {
158 label {Set as start of export range}
159 xywh {25 75 205 20} down_box DOWN_BOX value 1 labelsize 12
160 }
161 Fl_Box {} {
162 label Hr
163 xywh {150 28 50 17} labelsize 12
164 }
165 Fl_Box {} {
166 label Min
167 xywh {210 28 45 17} labelsize 12
168 }
169 Fl_Box {} {
170 label Sec
171 xywh {265 28 45 17} labelsize 12
172 }
173 }
174 }
175 Function {setuiloc(unsigned long offset)} {open return_type void
176 } {
177 code {unsigned long maxoffset=currsong->getlocatepos(25);
178if (offset>maxoffset) {
179 offset=maxoffset;
180 locpoint=offset;
181}
182string* strhr=Convert::int2str(currsong->display_hours(offset));
183hr->value(strhr->c_str());
184delete strhr;
185
186string* strmin=Convert::int2str(currsong->display_minutes(offset));
187min->value(strmin->c_str());
188delete strmin;
189
190string* strsec=Convert::int2str(currsong->display_seconds(offset));
191sec->value(strsec->c_str());
192delete strsec;
193
194string* strsubsec;
195
196long subseconds=currsong->display_subseconds(offset);
197long subsecval;
198switch(mode) {
199 case 0: subsecval=((subseconds*100)/ ( currsong->samplerate()/ (currsong->physical_channels()/currsong->logical_channels()) ) ); break;
200 case 1: subsecval=(subseconds); break;
201 case 2: subsecval=((subseconds*30)/( currsong->samplerate()/ (currsong->physical_channels()/currsong->logical_channels()) ) ); ; break;
202 default: subsecval=0;
203}
204strsubsec=Convert::int2str(subsecval);
205subsec->value(strsubsec->c_str());
206delete strsubsec;} {selected
207 }
208 }
209}
diff --git a/src/frontend/hd24connect.cpp b/src/frontend/hd24connect.cpp
new file mode 100755
index 0000000..b31b758
--- /dev/null
+++ b/src/frontend/hd24connect.cpp
@@ -0,0 +1,326 @@
1#define MAINDEBUG 0
2#include <FL/Fl.H>
3#include <FL/Fl_Window.H>
4#include <FL/Fl_Box.H>
5#include "ui_hd24connect.h"
6#include <hd24fs.h>
7#include <hd24utils.h>
8#include <FL/x.H> //dave
9#ifdef LINUX
10#include <X11/xpm.h> //dave
11#endif
12#include "images/hd24connect_64x64.xpm" //dave
13#include <iostream>
14#include <string>
15#include <stdlib.h>
16#include <hd24utils.h>
17#ifndef MAX_PATH
18#define MAX_PATH 127
19#endif
20
21#ifdef WINDOWS
22#include <windows.h>
23#define IDI_ICON1 101
24#endif
25string device;
26string headerfilename;
27int force;
28int maintmode;
29int wavefixmode;
30int testmode;
31#ifdef LINUX
32#define TIMEOUT 0.03
33#endif
34#define ARGDEV "--dev="
35#define ARGHEADER "--header="
36#define ARGFORCE "--force"
37#define ARGMAINT "--maint"
38#define ARGWAVEFIX "--wavefix"
39#define ARGTEST "--test"
40
41#include "selftest.cpp"
42
43int parsecommandline(int argc, char ** argv)
44{
45 int invalid=0;
46 force=0;
47 maintmode=0;
48 wavefixmode=0;
49 testmode=0;
50 device="";
51 for (int c=1;c<argc;c++) {
52
53 string arg=argv[c];
54 if (arg.substr(0,1)=="-") {
55 if (arg.substr(1,1)!="-") {
56 continue; // skip single-dash arguments
57 // for instance to skip -display
58 // and to skip macOS process number
59 }
60 }
61 if (arg.substr(0,strlen(ARGTEST))==ARGTEST) {
62 testmode=1;
63 continue;
64 }
65 if (arg.substr(0,strlen(ARGDEV))==ARGDEV) {
66 device=arg.substr(strlen(ARGDEV));
67 continue;
68 }
69 if (arg.substr(0,strlen(ARGMAINT))==ARGMAINT) {
70 maintmode=1;
71#if (MAINDEBUG==1)
72 cout << "Running in maintenance mode." << endl;
73#endif
74 continue;
75 }
76 if (arg.substr(0,strlen(ARGWAVEFIX))==ARGWAVEFIX) {
77 wavefixmode=1;
78#if (MAINDEBUG==1)
79 cout << "Running in wavefix mode." << endl;
80#endif
81 continue;
82 }
83 if (arg.substr(0,strlen(ARGHEADER))==ARGHEADER) {
84 headerfilename=arg.substr(strlen(ARGHEADER));
85 continue;
86 }
87 if (arg.substr(0,strlen(ARGFORCE))==(ARGFORCE)) {
88 force=1;
89 continue;
90 }
91#ifdef DARWIN
92 // on MacOS ignore all crap on the command line
93 // (system adds process ID info etc)
94 continue;
95#endif
96
97#if (MAINDEBUG==1)
98 cout << "Invalid argument: " << arg << endl;
99#endif
100 invalid=1;
101 }
102 return invalid;
103}
104
105int isabsolutepath(const char* pathname) {
106 if (pathname[0]=='/') return (1==1);
107 if (pathname[0]=='\\') return (1==1);
108 if (pathname[1]==':') return (1==1);
109 return (1==0);
110}
111
112void getprogdir(const char* currpath,const char* callpath,char* result) {
113 if (isabsolutepath(callpath)) {
114 strncpy(result,callpath,strlen(callpath)+1);
115 return;
116 }
117 strcat(result,currpath);
118#ifdef WINDOWS
119 strcat(result,"\\\0");
120#else
121 strcat(result,"/\0");
122#endif
123
124 if (strcmp(callpath,"./")!=0) {
125 strcat(result,callpath);
126 }
127 return;
128}
129
130
131int main(int argc, char **argv) {
132
133 int result=0;
134
135 /* First, the program will figure out its own
136 absolute program path. This will be used
137 for loading libraries after program startup,
138 rather than having hard dependencies *during*. */
139 char* currentworkingdir=(char*)malloc(2048);
140#if (MAINDEBUG==1)
141 cout << "Welcome to HD24connect" << endl;
142#endif
143 string currname=argv[0];
144 string rawname="";
145#if (MAINDEBUG==1)
146 cout << "Currname=" << currname << endl;
147#endif
148 do {
149 string lastchar="";
150 lastchar+=currname.substr(currname.length()-1,1);
151 if ((lastchar=="/") || (lastchar=="\\")) {
152 break;
153 }
154 rawname=currname.substr(currname.length()-1,1)+rawname;
155 currname=currname.substr(0,currname.length()-1);
156
157 if (currname=="") break;
158 } while (1==1);
159 // currname=path given on commandline
160
161 char cwd[2048];
162 char* mycwd=getcwd(&cwd[0],2048);
163 mycwd=&cwd[0];
164#if (MAINDEBUG==1)
165 cout << "cwd=" << cwd << endl;
166#endif
167 char absprogpath[2048];
168 char fullname[2048];
169 absprogpath[0]='\0';
170 getprogdir(&cwd[0],currname.c_str(),&absprogpath[0]);
171
172#if (MAINDEBUG==1)
173 cout << "absprogpath=" << absprogpath << endl;
174#endif
175 free(currentworkingdir);
176
177 /*
178 * Either absprogpath now contains absolute program path
179 * (if called from current path or by specifying path)
180 * or we need to traverse the OS PATH.
181 */
182 strncpy(fullname,absprogpath,2048);
183 strcat(fullname,rawname.c_str());
184#if (MAINDEBUG==1)
185 cout << "fullname=" << fullname << endl;
186#endif
187 if (!(hd24utils::fileExists(fullname))) {
188 /* File according to full name does not exist. */
189#if (MAINDEBUG==1)
190 cout << "rawname=" << rawname << ", path=" << getenv("PATH") << endl;
191#endif
192 hd24utils::findfile(&rawname[0],getenv("PATH"),&absprogpath[0]);
193 if (strlen(absprogpath)==0) {
194 cout << "Cannot find executable. "<< endl;
195 return 0;
196 }
197 }
198 // The final word on which path contains the exe is absprogpath.
199#if (MAINDEBUG==1)
200 cout << "The final word on where the exe is, is: " << absprogpath << endl;
201 cout << "main debugmode enabled." << endl;
202 cout << " Sizeof float=" << sizeof(float) << endl;
203#endif
204 char initial_path[MAX_PATH];
205 mycwd=getcwd(initial_path,MAX_PATH);
206 // This prints the path+filename to ourselves:
207 // If we run from current dir, argv is just filename;
208 // otherwise missing part of path+filename.
209 // So initial path+filename always renders the complete path.
210 int invalid=parsecommandline(argc,argv);
211 if (invalid!=0) {
212 return invalid;
213 }
214 //force=0;
215
216 hd24fs* sysob=NULL;
217 if (testmode==1)
218 {
219#ifdef LINUX
220 fl_open_display();
221#endif
222 HD24UserInterface ui(argc,argv,absprogpath);
223 // testmode active- run self test.
224 result=runselftest(&ui);
225 cout << "Selftest run complete - Thank you for using HD24connect." << endl;
226 ui.finish();
227 return result;
228 }
229
230 string* imagedir=hd24utils::getlastdir("driveimagedir");
231#if (MAINDEBUG==1)
232 cout << "imagedir="<<*imagedir<< endl;
233#endif
234 if (device=="") {
235 sysob=new hd24fs(imagedir->c_str(),hd24fs::MODE_RDWR);
236 } else {
237 cout << "Trying to use " << device << " as hd24 device." << endl;
238 sysob=new hd24fs(imagedir->c_str(),hd24fs::MODE_RDWR,&device,(force==1));
239 if (!(sysob->isOpen()))
240 {
241 if (!force) {
242 cout << "Cannot open hd24 device" << endl;
243 delete sysob;
244 return 1;
245 }
246 }
247 }
248 delete imagedir;
249 if (headerfilename!="")
250 {
251 if (!(sysob->useheaderfile(headerfilename)))
252 {
253 cout << "Couldn't load header file "<<headerfilename << endl;
254 };
255 }
256#if (MAINDEBUG==1)
257 cout << "mdb(2)" << endl;
258#endif
259// Fl::scheme("gtk+");
260#ifdef LINUX
261 fl_open_display();
262#endif
263 HD24UserInterface ui(argc,argv,absprogpath);
264#if (MAINDEBUG==1)
265 cout << "mdb(3b)" << endl;
266#endif
267 sysob->setmaintenancemode(maintmode);
268 sysob->setwavefixmode(wavefixmode);
269#if (MAINDEBUG==1)
270 cout << "mdb(3c)" << endl;
271#endif
272 Fl_Window *window = ui.make_window(sysob);
273#if (MAINDEBUG==1)
274 cout << "mdb(3d)" << endl;
275#endif
276#ifdef WINDOWS
277
278 window->icon((char *)LoadIcon(fl_display,MAKEINTRESOURCE(IDI_ICON1)));
279#endif
280 window->end();
281 window->show(); //argc, argv);
282
283#ifdef LINUX //dave
284 Pixmap p, mask;
285 XpmCreatePixmapFromData(fl_display,DefaultRootWindow(fl_display),(char **)hd24connect_xpm, &p, &mask, NULL);
286
287/*
288FLTK support for transparent background is broken. So instead of this:
289window->icon((char *)p);
290We will write the following: */
291XWMHints *hints=NULL;
292hints = XGetWMHints(fl_display, fl_xid(window));
293hints->icon_pixmap = p;
294hints->icon_mask = mask;
295hints->flags = IconPixmapHint | IconMaskHint;
296XSetWMHints(fl_display, fl_xid(window), hints);
297/* -- end of transparency fix */
298#endif
299#if (MAINDEBUG==1)
300 cout << "mdb(3)" << endl;
301#endif
302#if (MAINDEBUG==1)
303 cout << "mdb(4)" << endl;
304#endif
305 if (!(sysob->isOpen()))
306 {
307 window->deactivate();
308 fl_message("No valid HD24 drive is connected to the system.\nUse the File menu to resolve this problem.");
309 window->activate();
310 }
311 // run normally.
312 result= Fl::run();
313 ui.control->ready(0);
314#ifndef WINDOWS
315 cout << "Thank you for using HD24connect." << endl;
316#endif
317// ui.finish();
318
319#ifdef hints
320 if (hints!=NULL)
321 {
322 delete hints;
323 }
324#endif
325 return result;
326}
diff --git a/src/frontend/hd24connect.ico b/src/frontend/hd24connect.ico
new file mode 100644
index 0000000..72a6e89
--- /dev/null
+++ b/src/frontend/hd24connect.ico
Binary files differ
diff --git a/src/frontend/images/7seg_0.gif b/src/frontend/images/7seg_0.gif
new file mode 100644
index 0000000..58e66fe
--- /dev/null
+++ b/src/frontend/images/7seg_0.gif
Binary files differ
diff --git a/src/frontend/images/7seg_1.gif b/src/frontend/images/7seg_1.gif
new file mode 100644
index 0000000..07c0b19
--- /dev/null
+++ b/src/frontend/images/7seg_1.gif
Binary files differ
diff --git a/src/frontend/images/7seg_2.gif b/src/frontend/images/7seg_2.gif
new file mode 100644
index 0000000..6b8061c
--- /dev/null
+++ b/src/frontend/images/7seg_2.gif
Binary files differ
diff --git a/src/frontend/images/7seg_3.gif b/src/frontend/images/7seg_3.gif
new file mode 100644
index 0000000..60556e5
--- /dev/null
+++ b/src/frontend/images/7seg_3.gif
Binary files differ
diff --git a/src/frontend/images/7seg_4.gif b/src/frontend/images/7seg_4.gif
new file mode 100644
index 0000000..c3e1e96
--- /dev/null
+++ b/src/frontend/images/7seg_4.gif
Binary files differ
diff --git a/src/frontend/images/7seg_5.gif b/src/frontend/images/7seg_5.gif
new file mode 100644
index 0000000..927bf60
--- /dev/null
+++ b/src/frontend/images/7seg_5.gif
Binary files differ
diff --git a/src/frontend/images/7seg_6.gif b/src/frontend/images/7seg_6.gif
new file mode 100644
index 0000000..5dbf489
--- /dev/null
+++ b/src/frontend/images/7seg_6.gif
Binary files differ
diff --git a/src/frontend/images/7seg_7.gif b/src/frontend/images/7seg_7.gif
new file mode 100644
index 0000000..f7e215b
--- /dev/null
+++ b/src/frontend/images/7seg_7.gif
Binary files differ
diff --git a/src/frontend/images/7seg_8.gif b/src/frontend/images/7seg_8.gif
new file mode 100644
index 0000000..4fd1568
--- /dev/null
+++ b/src/frontend/images/7seg_8.gif
Binary files differ
diff --git a/src/frontend/images/7seg_9.gif b/src/frontend/images/7seg_9.gif
new file mode 100644
index 0000000..42cefe9
--- /dev/null
+++ b/src/frontend/images/7seg_9.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix.gif b/src/frontend/images/HD24_matrix.gif
new file mode 100644
index 0000000..33dfe22
--- /dev/null
+++ b/src/frontend/images/HD24_matrix.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_100.gif b/src/frontend/images/HD24_matrix_100.gif
new file mode 100644
index 0000000..89fa45a
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_100.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_101.gif b/src/frontend/images/HD24_matrix_101.gif
new file mode 100644
index 0000000..b8bf231
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_101.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_102.gif b/src/frontend/images/HD24_matrix_102.gif
new file mode 100644
index 0000000..94412f4
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_102.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_103.gif b/src/frontend/images/HD24_matrix_103.gif
new file mode 100644
index 0000000..3e281a7
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_103.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_104.gif b/src/frontend/images/HD24_matrix_104.gif
new file mode 100644
index 0000000..c037ce9
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_104.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_105.gif b/src/frontend/images/HD24_matrix_105.gif
new file mode 100644
index 0000000..bddeb44
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_105.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_106.gif b/src/frontend/images/HD24_matrix_106.gif
new file mode 100644
index 0000000..90c3f05
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_106.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_107.gif b/src/frontend/images/HD24_matrix_107.gif
new file mode 100644
index 0000000..e4d1fc8
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_107.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_108.gif b/src/frontend/images/HD24_matrix_108.gif
new file mode 100644
index 0000000..cd3f56b
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_108.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_109.gif b/src/frontend/images/HD24_matrix_109.gif
new file mode 100644
index 0000000..84c3aeb
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_109.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_110.gif b/src/frontend/images/HD24_matrix_110.gif
new file mode 100644
index 0000000..a900e54
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_110.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_111.gif b/src/frontend/images/HD24_matrix_111.gif
new file mode 100644
index 0000000..97e9c1c
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_111.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_112.gif b/src/frontend/images/HD24_matrix_112.gif
new file mode 100644
index 0000000..2a15b94
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_112.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_113.gif b/src/frontend/images/HD24_matrix_113.gif
new file mode 100644
index 0000000..2dced00
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_113.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_114.gif b/src/frontend/images/HD24_matrix_114.gif
new file mode 100644
index 0000000..4a09605
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_114.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_115.gif b/src/frontend/images/HD24_matrix_115.gif
new file mode 100644
index 0000000..3fd5273
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_115.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_116.gif b/src/frontend/images/HD24_matrix_116.gif
new file mode 100644
index 0000000..d8e539d
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_116.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_117.gif b/src/frontend/images/HD24_matrix_117.gif
new file mode 100644
index 0000000..778df49
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_117.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_118.gif b/src/frontend/images/HD24_matrix_118.gif
new file mode 100644
index 0000000..3363a9d
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_118.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_119.gif b/src/frontend/images/HD24_matrix_119.gif
new file mode 100644
index 0000000..4ea9b64
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_119.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_120.gif b/src/frontend/images/HD24_matrix_120.gif
new file mode 100644
index 0000000..08dd4b9
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_120.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_121.gif b/src/frontend/images/HD24_matrix_121.gif
new file mode 100644
index 0000000..0a7d586
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_121.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_122.gif b/src/frontend/images/HD24_matrix_122.gif
new file mode 100644
index 0000000..3c1ff79
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_122.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_123.gif b/src/frontend/images/HD24_matrix_123.gif
new file mode 100644
index 0000000..991c59c
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_123.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_124.gif b/src/frontend/images/HD24_matrix_124.gif
new file mode 100644
index 0000000..991c59c
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_124.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_125.gif b/src/frontend/images/HD24_matrix_125.gif
new file mode 100644
index 0000000..991c59c
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_125.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_126.gif b/src/frontend/images/HD24_matrix_126.gif
new file mode 100644
index 0000000..991c59c
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_126.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_127.gif b/src/frontend/images/HD24_matrix_127.gif
new file mode 100644
index 0000000..991c59c
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_127.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_32.gif b/src/frontend/images/HD24_matrix_32.gif
new file mode 100644
index 0000000..63304b1
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_32.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_33.gif b/src/frontend/images/HD24_matrix_33.gif
new file mode 100644
index 0000000..0437f42
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_33.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_34.gif b/src/frontend/images/HD24_matrix_34.gif
new file mode 100644
index 0000000..d7aa4e1
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_34.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_35.gif b/src/frontend/images/HD24_matrix_35.gif
new file mode 100644
index 0000000..a73ab5f
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_35.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_36.gif b/src/frontend/images/HD24_matrix_36.gif
new file mode 100644
index 0000000..f741bb0
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_36.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_37.gif b/src/frontend/images/HD24_matrix_37.gif
new file mode 100644
index 0000000..b335468
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_37.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_38.gif b/src/frontend/images/HD24_matrix_38.gif
new file mode 100644
index 0000000..a41c62b
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_38.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_39.gif b/src/frontend/images/HD24_matrix_39.gif
new file mode 100644
index 0000000..4cb9ff7
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_39.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_40.gif b/src/frontend/images/HD24_matrix_40.gif
new file mode 100644
index 0000000..e65298d
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_40.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_41.gif b/src/frontend/images/HD24_matrix_41.gif
new file mode 100644
index 0000000..b33b736
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_41.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_42.gif b/src/frontend/images/HD24_matrix_42.gif
new file mode 100644
index 0000000..5dc29ea
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_42.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_43.gif b/src/frontend/images/HD24_matrix_43.gif
new file mode 100644
index 0000000..23b4d9a
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_43.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_44.gif b/src/frontend/images/HD24_matrix_44.gif
new file mode 100644
index 0000000..3813d69
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_44.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_45.gif b/src/frontend/images/HD24_matrix_45.gif
new file mode 100644
index 0000000..0ab8c42
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_45.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_46.gif b/src/frontend/images/HD24_matrix_46.gif
new file mode 100644
index 0000000..902ec61
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_46.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_47.gif b/src/frontend/images/HD24_matrix_47.gif
new file mode 100644
index 0000000..d40524a
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_47.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_48.gif b/src/frontend/images/HD24_matrix_48.gif
new file mode 100644
index 0000000..28e1580
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_48.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_49.gif b/src/frontend/images/HD24_matrix_49.gif
new file mode 100644
index 0000000..8583186
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_49.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_50.gif b/src/frontend/images/HD24_matrix_50.gif
new file mode 100644
index 0000000..2cc053f
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_50.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_51.gif b/src/frontend/images/HD24_matrix_51.gif
new file mode 100644
index 0000000..d528bea
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_51.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_52.gif b/src/frontend/images/HD24_matrix_52.gif
new file mode 100644
index 0000000..c133802
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_52.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_53.gif b/src/frontend/images/HD24_matrix_53.gif
new file mode 100644
index 0000000..3b63434
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_53.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_54.gif b/src/frontend/images/HD24_matrix_54.gif
new file mode 100644
index 0000000..52a912a
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_54.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_55.gif b/src/frontend/images/HD24_matrix_55.gif
new file mode 100644
index 0000000..913fa29
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_55.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_56.gif b/src/frontend/images/HD24_matrix_56.gif
new file mode 100644
index 0000000..d84897c
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_56.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_57.gif b/src/frontend/images/HD24_matrix_57.gif
new file mode 100644
index 0000000..03fa842
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_57.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_58.gif b/src/frontend/images/HD24_matrix_58.gif
new file mode 100644
index 0000000..2205a71
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_58.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_59.gif b/src/frontend/images/HD24_matrix_59.gif
new file mode 100644
index 0000000..55a05e5
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_59.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_60.gif b/src/frontend/images/HD24_matrix_60.gif
new file mode 100644
index 0000000..6717578
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_60.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_61.gif b/src/frontend/images/HD24_matrix_61.gif
new file mode 100644
index 0000000..d2d4337
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_61.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_62.gif b/src/frontend/images/HD24_matrix_62.gif
new file mode 100644
index 0000000..4dd41f8
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_62.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_63.gif b/src/frontend/images/HD24_matrix_63.gif
new file mode 100644
index 0000000..7437751
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_63.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_64.gif b/src/frontend/images/HD24_matrix_64.gif
new file mode 100644
index 0000000..991c59c
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_64.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_65.gif b/src/frontend/images/HD24_matrix_65.gif
new file mode 100644
index 0000000..3751e69
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_65.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_66.gif b/src/frontend/images/HD24_matrix_66.gif
new file mode 100644
index 0000000..757dc9b
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_66.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_67.gif b/src/frontend/images/HD24_matrix_67.gif
new file mode 100644
index 0000000..c3448a5
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_67.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_68.gif b/src/frontend/images/HD24_matrix_68.gif
new file mode 100644
index 0000000..9f43eba
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_68.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_69.gif b/src/frontend/images/HD24_matrix_69.gif
new file mode 100644
index 0000000..5a972dc
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_69.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_70.gif b/src/frontend/images/HD24_matrix_70.gif
new file mode 100644
index 0000000..659ee77
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_70.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_71.gif b/src/frontend/images/HD24_matrix_71.gif
new file mode 100644
index 0000000..b8d498a
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_71.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_72.gif b/src/frontend/images/HD24_matrix_72.gif
new file mode 100644
index 0000000..9f4e79d
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_72.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_73.gif b/src/frontend/images/HD24_matrix_73.gif
new file mode 100644
index 0000000..7049d5b
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_73.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_74.gif b/src/frontend/images/HD24_matrix_74.gif
new file mode 100644
index 0000000..2d22554
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_74.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_75.gif b/src/frontend/images/HD24_matrix_75.gif
new file mode 100644
index 0000000..4c75258
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_75.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_76.gif b/src/frontend/images/HD24_matrix_76.gif
new file mode 100644
index 0000000..3fb4747
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_76.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_77.gif b/src/frontend/images/HD24_matrix_77.gif
new file mode 100644
index 0000000..43f8fac
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_77.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_78.gif b/src/frontend/images/HD24_matrix_78.gif
new file mode 100644
index 0000000..3b37dc3
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_78.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_79.gif b/src/frontend/images/HD24_matrix_79.gif
new file mode 100644
index 0000000..8be50ea
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_79.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_80.gif b/src/frontend/images/HD24_matrix_80.gif
new file mode 100644
index 0000000..e9dda05
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_80.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_81.gif b/src/frontend/images/HD24_matrix_81.gif
new file mode 100644
index 0000000..2e3e5b0
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_81.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_82.gif b/src/frontend/images/HD24_matrix_82.gif
new file mode 100644
index 0000000..a209e00
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_82.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_83.gif b/src/frontend/images/HD24_matrix_83.gif
new file mode 100644
index 0000000..37bed7f
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_83.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_84.gif b/src/frontend/images/HD24_matrix_84.gif
new file mode 100644
index 0000000..2bea274
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_84.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_85.gif b/src/frontend/images/HD24_matrix_85.gif
new file mode 100644
index 0000000..f02f416
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_85.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_86.gif b/src/frontend/images/HD24_matrix_86.gif
new file mode 100644
index 0000000..b9642bc
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_86.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_87.gif b/src/frontend/images/HD24_matrix_87.gif
new file mode 100644
index 0000000..c9c2813
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_87.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_88.gif b/src/frontend/images/HD24_matrix_88.gif
new file mode 100644
index 0000000..93d7d19
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_88.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_89.gif b/src/frontend/images/HD24_matrix_89.gif
new file mode 100644
index 0000000..e9bfb57
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_89.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_90.gif b/src/frontend/images/HD24_matrix_90.gif
new file mode 100644
index 0000000..f106d72
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_90.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_91.gif b/src/frontend/images/HD24_matrix_91.gif
new file mode 100644
index 0000000..991c59c
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_91.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_92.gif b/src/frontend/images/HD24_matrix_92.gif
new file mode 100644
index 0000000..991c59c
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_92.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_93.gif b/src/frontend/images/HD24_matrix_93.gif
new file mode 100644
index 0000000..991c59c
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_93.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_94.gif b/src/frontend/images/HD24_matrix_94.gif
new file mode 100644
index 0000000..991c59c
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_94.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_95.gif b/src/frontend/images/HD24_matrix_95.gif
new file mode 100644
index 0000000..991c59c
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_95.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_96.gif b/src/frontend/images/HD24_matrix_96.gif
new file mode 100644
index 0000000..991c59c
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_96.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_97.gif b/src/frontend/images/HD24_matrix_97.gif
new file mode 100644
index 0000000..a0fbde3
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_97.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_98.gif b/src/frontend/images/HD24_matrix_98.gif
new file mode 100644
index 0000000..89c3f8a
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_98.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_99.gif b/src/frontend/images/HD24_matrix_99.gif
new file mode 100644
index 0000000..1596771
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_99.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_arrowleft.gif b/src/frontend/images/HD24_matrix_arrowleft.gif
new file mode 100644
index 0000000..0950acb
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_arrowleft.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_arrowright.gif b/src/frontend/images/HD24_matrix_arrowright.gif
new file mode 100644
index 0000000..60101ec
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_arrowright.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_realsize.gif b/src/frontend/images/HD24_matrix_realsize.gif
new file mode 100644
index 0000000..991c59c
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_realsize.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_writeenabled.gif b/src/frontend/images/HD24_matrix_writeenabled.gif
new file mode 100644
index 0000000..19b59d3
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_writeenabled.gif
Binary files differ
diff --git a/src/frontend/images/HD24_matrix_writeprotected.gif b/src/frontend/images/HD24_matrix_writeprotected.gif
new file mode 100644
index 0000000..14ef331
--- /dev/null
+++ b/src/frontend/images/HD24_matrix_writeprotected.gif
Binary files differ
diff --git a/src/frontend/images/aqua.bmp b/src/frontend/images/aqua.bmp
new file mode 100644
index 0000000..3ad5445
--- /dev/null
+++ b/src/frontend/images/aqua.bmp
Binary files differ
diff --git a/src/frontend/images/aqua.rar b/src/frontend/images/aqua.rar
new file mode 100644
index 0000000..63e877e
--- /dev/null
+++ b/src/frontend/images/aqua.rar
Binary files differ
diff --git a/src/frontend/images/aquabutton_down.gif b/src/frontend/images/aquabutton_down.gif
new file mode 100644
index 0000000..ecf4092
--- /dev/null
+++ b/src/frontend/images/aquabutton_down.gif
Binary files differ
diff --git a/src/frontend/images/aquabutton_up.gif b/src/frontend/images/aquabutton_up.gif
new file mode 100644
index 0000000..2b12ec2
--- /dev/null
+++ b/src/frontend/images/aquabutton_up.gif
Binary files differ
diff --git a/src/frontend/images/button.gif b/src/frontend/images/button.gif
new file mode 100644
index 0000000..070d82b
--- /dev/null
+++ b/src/frontend/images/button.gif
Binary files differ
diff --git a/src/frontend/images/button.xcf b/src/frontend/images/button.xcf
new file mode 100644
index 0000000..d80fd3c
--- /dev/null
+++ b/src/frontend/images/button.xcf
Binary files differ
diff --git a/src/frontend/images/button_ffwd.gif b/src/frontend/images/button_ffwd.gif
new file mode 100644
index 0000000..f09258e
--- /dev/null
+++ b/src/frontend/images/button_ffwd.gif
Binary files differ
diff --git a/src/frontend/images/button_ffwd_dn.gif b/src/frontend/images/button_ffwd_dn.gif
new file mode 100644
index 0000000..2c18d91
--- /dev/null
+++ b/src/frontend/images/button_ffwd_dn.gif
Binary files differ
diff --git a/src/frontend/images/button_lrc.gif b/src/frontend/images/button_lrc.gif
new file mode 100644
index 0000000..f2ab406
--- /dev/null
+++ b/src/frontend/images/button_lrc.gif
Binary files differ
diff --git a/src/frontend/images/button_lrc_dn.gif b/src/frontend/images/button_lrc_dn.gif
new file mode 100644
index 0000000..dcf5cad
--- /dev/null
+++ b/src/frontend/images/button_lrc_dn.gif
Binary files differ
diff --git a/src/frontend/images/button_lrc_led.gif b/src/frontend/images/button_lrc_led.gif
new file mode 100644
index 0000000..7c84600
--- /dev/null
+++ b/src/frontend/images/button_lrc_led.gif
Binary files differ
diff --git a/src/frontend/images/button_lrc_led_dn.gif b/src/frontend/images/button_lrc_led_dn.gif
new file mode 100644
index 0000000..2cec7c7
--- /dev/null
+++ b/src/frontend/images/button_lrc_led_dn.gif
Binary files differ
diff --git a/src/frontend/images/button_lrc_led_on.gif b/src/frontend/images/button_lrc_led_on.gif
new file mode 100644
index 0000000..b149d30
--- /dev/null
+++ b/src/frontend/images/button_lrc_led_on.gif
Binary files differ
diff --git a/src/frontend/images/button_lrc_led_on_dn.gif b/src/frontend/images/button_lrc_led_on_dn.gif
new file mode 100644
index 0000000..e2f9143
--- /dev/null
+++ b/src/frontend/images/button_lrc_led_on_dn.gif
Binary files differ
diff --git a/src/frontend/images/button_mute.gif b/src/frontend/images/button_mute.gif
new file mode 100644
index 0000000..b29e443
--- /dev/null
+++ b/src/frontend/images/button_mute.gif
Binary files differ
diff --git a/src/frontend/images/button_mute_dn.gif b/src/frontend/images/button_mute_dn.gif
new file mode 100644
index 0000000..4f44a69
--- /dev/null
+++ b/src/frontend/images/button_mute_dn.gif
Binary files differ
diff --git a/src/frontend/images/button_play.gif b/src/frontend/images/button_play.gif
new file mode 100644
index 0000000..5e26985
--- /dev/null
+++ b/src/frontend/images/button_play.gif
Binary files differ
diff --git a/src/frontend/images/button_play_dn.gif b/src/frontend/images/button_play_dn.gif
new file mode 100644
index 0000000..1dad7fe
--- /dev/null
+++ b/src/frontend/images/button_play_dn.gif
Binary files differ
diff --git a/src/frontend/images/button_rec.gif b/src/frontend/images/button_rec.gif
new file mode 100644
index 0000000..af2ad76
--- /dev/null
+++ b/src/frontend/images/button_rec.gif
Binary files differ
diff --git a/src/frontend/images/button_rec_dn.gif b/src/frontend/images/button_rec_dn.gif
new file mode 100644
index 0000000..9293d04
--- /dev/null
+++ b/src/frontend/images/button_rec_dn.gif
Binary files differ
diff --git a/src/frontend/images/button_rew.gif b/src/frontend/images/button_rew.gif
new file mode 100644
index 0000000..1dd8501
--- /dev/null
+++ b/src/frontend/images/button_rew.gif
Binary files differ
diff --git a/src/frontend/images/button_rew_dn.gif b/src/frontend/images/button_rew_dn.gif
new file mode 100644
index 0000000..e00f65f
--- /dev/null
+++ b/src/frontend/images/button_rew_dn.gif
Binary files differ
diff --git a/src/frontend/images/button_small.gif b/src/frontend/images/button_small.gif
new file mode 100644
index 0000000..762af63
--- /dev/null
+++ b/src/frontend/images/button_small.gif
Binary files differ
diff --git a/src/frontend/images/button_small_dn.gif b/src/frontend/images/button_small_dn.gif
new file mode 100644
index 0000000..0f96f67
--- /dev/null
+++ b/src/frontend/images/button_small_dn.gif
Binary files differ
diff --git a/src/frontend/images/button_solo.gif b/src/frontend/images/button_solo.gif
new file mode 100644
index 0000000..f70004e
--- /dev/null
+++ b/src/frontend/images/button_solo.gif
Binary files differ
diff --git a/src/frontend/images/button_solo_dn.gif b/src/frontend/images/button_solo_dn.gif
new file mode 100644
index 0000000..847d366
--- /dev/null
+++ b/src/frontend/images/button_solo_dn.gif
Binary files differ
diff --git a/src/frontend/images/button_stop.gif b/src/frontend/images/button_stop.gif
new file mode 100644
index 0000000..06b5581
--- /dev/null
+++ b/src/frontend/images/button_stop.gif
Binary files differ
diff --git a/src/frontend/images/button_stop_dn.gif b/src/frontend/images/button_stop_dn.gif
new file mode 100644
index 0000000..b526b8a
--- /dev/null
+++ b/src/frontend/images/button_stop_dn.gif
Binary files differ
diff --git a/src/frontend/images/button_stop_uplit.gif b/src/frontend/images/button_stop_uplit.gif
new file mode 100644
index 0000000..1b84f7e
--- /dev/null
+++ b/src/frontend/images/button_stop_uplit.gif
Binary files differ
diff --git a/src/frontend/images/ch21.gif b/src/frontend/images/ch21.gif
new file mode 100644
index 0000000..2aece61
--- /dev/null
+++ b/src/frontend/images/ch21.gif
Binary files differ
diff --git a/src/frontend/images/ch21.png b/src/frontend/images/ch21.png
new file mode 100644
index 0000000..b564294
--- /dev/null
+++ b/src/frontend/images/ch21.png
Binary files differ
diff --git a/src/frontend/images/down.gif b/src/frontend/images/down.gif
new file mode 100644
index 0000000..6320f2a
--- /dev/null
+++ b/src/frontend/images/down.gif
Binary files differ
diff --git a/src/frontend/images/fader.gif b/src/frontend/images/fader.gif
new file mode 100644
index 0000000..5ee05a2
--- /dev/null
+++ b/src/frontend/images/fader.gif
Binary files differ
diff --git a/src/frontend/images/ffwd.gif b/src/frontend/images/ffwd.gif
new file mode 100755
index 0000000..8029722
--- /dev/null
+++ b/src/frontend/images/ffwd.gif
Binary files differ
diff --git a/src/frontend/images/hd24connect.png b/src/frontend/images/hd24connect.png
new file mode 100755
index 0000000..4ad7bc6
--- /dev/null
+++ b/src/frontend/images/hd24connect.png
Binary files differ
diff --git a/src/frontend/images/hd24connect.xpm b/src/frontend/images/hd24connect.xpm
new file mode 100644
index 0000000..c3a2b33
--- /dev/null
+++ b/src/frontend/images/hd24connect.xpm
@@ -0,0 +1,38 @@
1/* XPM */
2const char * hd24connect_xpm[] = {
3"32 32 3 1",
4" c None",
5". c #FFFFFF",
6"+ c #000000",
7"....... .................. ",
8".+++++. .+++++.+++++++++++.. ",
9".+++++. .+++++..++++++++++++. ",
10".+++++.....+++++...++++++++++++.",
11".+++++++++++++++............+++.",
12".+++++++++++++++.++++.......+++.",
13".+++++.....+++++.++++++++++++++.",
14".+++++. .+++++.+++++++++++++. ",
15".+++++. .+++++.+++++++++++.. ",
16"....... ...... ........... ",
17" ",
18" ",
19" ",
20" ............ ... ..... ",
21" .++++++++++++. .+++. .+++++.",
22".++++++++++++++. .++++. .+++++.",
23" .........+++++. .+++.....+++++.",
24" .+++++++++++++..++++++++++++++.",
25".+++++++++++++. .++++++++++++++.",
26".+++++..........+++++++++++++++.",
27".++++++++++++++...........+++++.",
28" .+++++++++++++. .+++++.",
29" ............. .......",
30" ",
31" ",
32"................................",
33"..++.+++.+..+.+..+.+++..++.+++++",
34".+...+.+.++.+.++.+.+...+.....+..",
35".+...+.+.+.++.+.++.++..+.....+..",
36".+...+.+.+..+.+..+.+...+.....+..",
37"..++.+++.+..+.+..+.+++..++...+..",
38"................................"};
diff --git a/src/frontend/images/hd24connect_64x64.xpm b/src/frontend/images/hd24connect_64x64.xpm
new file mode 100644
index 0000000..d087646
--- /dev/null
+++ b/src/frontend/images/hd24connect_64x64.xpm
@@ -0,0 +1,355 @@
1/* XPM */
2const char * hd24connect_xpm[] = {
3"64 64 288 2",
4" c None",
5". c #3B412D",
6"+ c #343913",
7"@ c #272E1D",
8"# c #0C161A",
9"$ c #10191D",
10"% c #303437",
11"& c #323A3E",
12"* c #1C1C1C",
13"= c #000000",
14"- c #42161A",
15"; c #121415",
16"> c #4B1215",
17", c #0F1011",
18"' c #0C0D0E",
19") c #070708",
20"! c #040506",
21"~ c #08090A",
22"{ c #0A0C0C",
23"] c #020203",
24"^ c #060809",
25"/ c #FAFAFA",
26"( c #FEFEFE",
27"_ c #C5C7C8",
28": c #6D6E6F",
29"< c #4D4F50",
30"[ c #828384",
31"} c #FCFDFD",
32"| c #F0F2F2",
33"1 c #CCCFD0",
34"2 c #8E9091",
35"3 c #292A2A",
36"4 c #222222",
37"5 c #FBFBFC",
38"6 c #FFFFFF",
39"7 c #C6C8C8",
40"8 c #6E6F70",
41"9 c #4E4F50",
42"0 c #252626",
43"a c #D1D2D3",
44"b c #F7F7F7",
45"c c #444546",
46"d c #16191B",
47"e c #222728",
48"f c #1D2122",
49"g c #040505",
50"h c #393A3B",
51"i c #656767",
52"j c #7B7C7D",
53"k c #858686",
54"l c #868686",
55"m c #888989",
56"n c #F7F8F8",
57"o c #A8AAAA",
58"p c #050606",
59"q c #EEF0F0",
60"r c #AEAEAE",
61"s c #C8CACB",
62"t c #080A0A",
63"u c #737475",
64"v c #070808",
65"w c #0D0E10",
66"x c #030404",
67"y c #010101",
68"z c #141516",
69"A c #131516",
70"B c #FCFCFC",
71"C c #868889",
72"D c #FAFAFB",
73"E c #383B3C",
74"F c #090A0A",
75"G c #262829",
76"H c #898A8B",
77"I c #393C3C",
78"J c #28292A",
79"K c #E4E5E5",
80"L c #848586",
81"M c #BFC1C1",
82"N c #050506",
83"O c #2B3235",
84"P c #212629",
85"Q c #262A2D",
86"R c #161617",
87"S c #7A7C7D",
88"T c #060606",
89"U c #424546",
90"V c #101212",
91"W c #EFF1F1",
92"X c #352427",
93"Y c #F9FAFA",
94"Z c #F8F8F8",
95"` c #868888",
96" . c #020202",
97".. c #ECEDEE",
98"+. c #949696",
99"@. c #0A0B0B",
100"#. c #232323",
101"$. c #727374",
102"%. c #747575",
103"&. c #5A5C5C",
104"*. c #38393A",
105"=. c #727373",
106"-. c #212223",
107";. c #3E3F40",
108">. c #707172",
109",. c #5C5C5D",
110"'. c #353637",
111"). c #464A4B",
112"!. c #202223",
113"~. c #343637",
114"{. c #191A1B",
115"]. c #423135",
116"^. c #1C1D1E",
117"/. c #1A1D1E",
118"(. c #3C3F41",
119"_. c #212A2D",
120":. c #414146",
121"<. c #35312B",
122"[. c #282E20",
123"}. c #2F2B26",
124"|. c #394246",
125"1. c #333739",
126"2. c #373539",
127"3. c #3D4044",
128"4. c #151A19",
129"5. c #161819",
130"6. c #020303",
131"7. c #44171A",
132"8. c #24292C",
133"9. c #1F2427",
134"0. c #151819",
135"a. c #4A4E50",
136"b. c #252728",
137"c. c #040606",
138"d. c #0A0A0B",
139"e. c #0A0B0C",
140"f. c #0D0E0E",
141"g. c #030304",
142"h. c #000101",
143"i. c #343434",
144"j. c #242526",
145"k. c #989A9B",
146"l. c #D4D6D7",
147"m. c #EDEEEE",
148"n. c #F2F3F3",
149"o. c #F3F4F4",
150"p. c #E9EAEB",
151"q. c #CCCECF",
152"r. c #949697",
153"s. c #363738",
154"t. c #040404",
155"u. c #212424",
156"v. c #F1F2F2",
157"w. c #E8EAEA",
158"x. c #BEC0C2",
159"y. c #101010",
160"z. c #050607",
161"A. c #C6C9CA",
162"B. c #DADADB",
163"C. c #797B7C",
164"D. c #272829",
165"E. c #DEDFDF",
166"F. c #0A0A0A",
167"G. c #2D3033",
168"H. c #F4F4F5",
169"I. c #D0D2D3",
170"J. c #121313",
171"K. c #949596",
172"L. c #D5D6D7",
173"M. c #F5F6F6",
174"N. c #101112",
175"O. c #AEB0B1",
176"P. c #595A5C",
177"Q. c #343739",
178"R. c #303537",
179"S. c #131414",
180"T. c #9B9D9E",
181"U. c #FAFCFC",
182"V. c #161618",
183"W. c #3C3E3E",
184"X. c #C1C2C3",
185"Y. c #F0F1F2",
186"Z. c #A0A2A4",
187"`. c #B0B1B2",
188" + c #434646",
189".+ c #121314",
190"++ c #EFF0F1",
191"@+ c #030303",
192"#+ c #454647",
193"$+ c #959798",
194"%+ c #E6E7E8",
195"&+ c #F2F4F4",
196"*+ c #FAFBFB",
197"=+ c #E7E8E9",
198"-+ c #2A2C2D",
199";+ c #ADAFB0",
200">+ c #FEFEFF",
201",+ c #FDFEFE",
202"'+ c #C8C9CA",
203")+ c #151616",
204"!+ c #C7C8C9",
205"~+ c #D1D2D2",
206"{+ c #999A9A",
207"]+ c #98999A",
208"^+ c #87898A",
209"/+ c #656667",
210"(+ c #2C2D2E",
211"_+ c #333435",
212":+ c #646666",
213"<+ c #818282",
214"[+ c #8F9192",
215"}+ c #939495",
216"|+ c #959697",
217"1+ c #F8F9F9",
218"2+ c #242626",
219"3+ c #8C8D8E",
220"4+ c #8F9091",
221"5+ c #0B0C0C",
222"6+ c #2C3032",
223"7+ c #1D1F20",
224"8+ c #131415",
225"9+ c #F4F4F4",
226"0+ c #ECEEEE",
227"a+ c #E8EAEB",
228"b+ c #161818",
229"c+ c #1E1F20",
230"d+ c #2F2F2F",
231"e+ c #545556",
232"f+ c #D0D1D2",
233"g+ c #161718",
234"h+ c #252627",
235"i+ c #545656",
236"j+ c #727474",
237"k+ c #838484",
238"l+ c #7A7C7C",
239"m+ c #6B6D6D",
240"n+ c #2B2E31",
241"o+ c #060707",
242"p+ c #2A2E32",
243"q+ c #1F2426",
244"r+ c #212425",
245"s+ c #101213",
246"t+ c #0E1010",
247"u+ c #222425",
248"v+ c #303233",
249"w+ c #585D5E",
250"x+ c #2C2C2C",
251"y+ c #0B0B0B",
252"z+ c #262626",
253"A+ c #242424",
254"B+ c #202020",
255"C+ c #191919",
256"D+ c #303030",
257"E+ c #1B1B1B",
258"F+ c #212121",
259"G+ c #171717",
260"H+ c #292929",
261"I+ c #080808",
262"J+ c #090909",
263"K+ c #0E0E0E",
264"L+ c #070707",
265"M+ c #050505",
266"N+ c #121212",
267"O+ c #272727",
268"P+ c #3D3D3D",
269"Q+ c #282828",
270"R+ c #0D0D0D",
271"S+ c #181818",
272"T+ c #252525",
273"U+ c #323232",
274"V+ c #2E2E2E",
275"W+ c #3C3C3C",
276"X+ c #1F1F1F",
277"Y+ c #111111",
278"Z+ c #2B2B2B",
279"`+ c #1E1E1E",
280" @ c #141414",
281".@ c #626262",
282"+@ c #161616",
283"@@ c #5E5E5E",
284"#@ c #414141",
285"$@ c #131313",
286"%@ c #1A1A1A",
287"&@ c #0F0F0F",
288"*@ c #393939",
289"=@ c #383838",
290"-@ c #565656",
291";@ c #3A3A3A",
292" ",
293" ",
294" ",
295" ",
296" ",
297" ",
298" ",
299" ",
300". + + + + + + + + + + + + + + + + + + @ # # # # # # # # # # # $ + + + + + + + + + + + + + + + % & ",
301"* = = = = = = = = = = = - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ; > ",
302"* = = , , , , , , ' = = - = = ) , , , , , , ! = = = ~ , , , , , , , , , , , , , , , , , , , , , { ] = = = = , ",
303"* = ^ / ( ( ( ( ( _ = = - = = : ( ( ( ( ( ( < = = = [ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( } | 1 2 3 = = 4 ",
304"* = ^ 5 6 6 6 6 6 7 = = - = = 8 6 6 6 6 6 6 9 = = = 0 a 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 b c = = ",
305"* = ^ 5 6 6 6 6 6 7 = = d e e e e e e e f = = 8 6 6 6 6 6 6 9 = = = = g h i j k l l l l l l l l l l l l l l m n 6 6 6 6 6 o = = ",
306"* = ^ 5 6 6 6 6 6 7 = = = = = = = = = = = = = 8 6 6 6 6 6 6 9 = = = = = = = = = = = = = = = = = = = = = = = p q 6 6 6 6 6 r = = ",
307"* = ^ 5 6 6 6 6 6 s t t t t t t t t t t t t t u 6 6 6 6 6 6 9 = = = v w w w w w w x = y ; z z z z z z A x = p q 6 6 6 6 6 r = = ",
308"* = ^ 5 6 6 6 6 6 ( / / / / / / / / / / / / / B 6 6 6 6 6 6 9 = = = C D D D D D D E = F G = p q 6 6 6 6 6 r = = ",
309"* = ^ 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 9 = = = H 6 6 6 6 6 6 I = F J = p q 6 6 6 6 6 r = = ",
310"* = ^ 5 6 6 6 6 6 K L L L L L L L L L L L L L M 6 6 6 6 6 6 9 = = = H 6 6 6 6 6 6 I = N O P P P P P P Q R = p q 6 6 6 6 6 r = = ",
311"* = ^ 5 6 6 6 6 6 7 = = = = = = = = = = = = = S 6 6 6 6 6 6 9 = = = H 6 6 6 6 6 6 I = = = = = = = = = = = = p q 6 6 6 6 6 r = = ",
312"* = ^ 5 6 6 6 6 6 7 = = T ' ' ' ' ' ' ' ~ = = S 6 6 6 6 6 6 9 = = = H 6 6 6 6 6 6 U ' ' ' ' ' ' ' ' ' ' ' ' V W 6 6 6 6 6 r = = ",
313"* = ^ 5 6 6 6 6 6 7 = = X = = S 6 6 6 6 6 6 9 = = = H 6 6 6 6 6 6 Y Z Z Z Z Z Z Z Z Z Z Z Z Z ( 6 6 6 6 6 ` = .",
314"* = ^ 5 6 6 6 6 6 7 = = - = = S 6 6 6 6 6 6 9 = = = H 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 ..+.@.= #.",
315"* = x $.%.%.%.%.%.&.= = - = = *.%.%.%.%.%.=.-.= = = ;.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.>.,.'.F = = .).",
316"* = = = = = = = = = = = - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = !. ",
317"~.{.{.{.{.{.{.{.{.{.{.{.]. {.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.^./.(._. ",
318" ",
319" :.<.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.}.|. 1.1.1.1.1.2.3. 1.1.1.1.1.1.1.1.1.1.1. ",
320" 4.5. .= = = = = = = = = = = = = = = = = = = = = = 6.5.7. 8.= = = = = = = = = p 9. 0.= = = = = = = = = = = a. ",
321" b.= = = = c.d.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.e.F x = = = = f. g = g.e.e.e.v x = = = h. 0.= = e.e.e.e.e.e.~ = = a. ",
322"i.= = j.k.l.m.n.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.o.n.p.q.r.s.= = t.u.= = C o.o.o.v.w.x.y.= z. 0.= T w.o.o.o.o.o.A.= = a. ",
323" .= N B.6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 / C.= = = = D.o.6 6 6 6 6 E.F.= G. 0.= T H.6 6 6 6 6 I.= = a. ",
324"= = J.K.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.+.L.6 6 6 6 6 M.N.= = y O.6 6 6 6 6 ( P.= = Q.R.R.R.R.R.S.= T H.6 6 6 6 6 I.= = a. ",
325"= = = = = = = = = = = = = = = = = = = = = = = T.6 6 6 6 6 U.V.= = W.} 6 6 6 6 6 X.g.= = = = = = = = = = T Y.6 6 6 6 6 I.= = a. ",
326"= = = = = = = x e.f.f.f.f.f.f.f.f.f.f.f.f.f.f.Z.6 6 6 6 6 U.V.= y `.6 6 6 6 6 B +f.f.f.f.f.f.f.f.f.f.f..+++6 6 6 6 6 I.= = a. ",
327"= = = @+#+$+s %+| &+&+&+&+&+&+&+&+&+&+&+&+&+&+*+6 6 6 6 6 =+e.= -+B 6 6 6 6 6 ( o.&+&+&+&+&+&+&+&+&+&+&+o.( 6 6 6 6 6 I.= = a. ",
328"= = ] ;+>+6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 ,+'+W.= = )+!+( 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 I.= = a. ",
329"= = !.( 6 6 6 6 6 ~+{+{+{+{+{+{+{+{+{+{+{+{+{+{+]+^+/+(+@+= = = = g _+:+<+[+}+}+}+}+}+}+}+}+}+}+}+}+}+}+|+1+6 6 6 6 6 I.= = a. ",
330"= = 2+( 6 6 6 6 6 3+= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = p q 6 6 6 6 6 I.= = a. ",
331"= = 2+( 6 6 6 6 6 4+v v v v v v v v v v v v v v v v v v v v y = 5+6+7+8+5+p ! ! ! ! ! ! ! ! ! ! ! ! y = p q 6 6 6 6 6 I.= = a. ",
332"= = , 9+6 6 6 6 6 b 0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+a+z = b+ c+= p q 6 6 6 6 6 I.= = a. ",
333"d+= = e+f+} 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 U.V.= b+ -.= p q 6 6 6 6 6 I.= = a. ",
334" g+= = ] h+i+j+<+k+k+k+k+k+k+k+k+k+k+k+k+k+k+k+k+k+k+k+k+<+5+= b+ -.= @+l+k+k+k+k+k+m+= = a. ",
335" n+o+= = = = = = = = = = = = = = = = = = = = = = = = = = = = b+ -.= = = = = = = = = = = a. ",
336" p+q+r+s+y.t+t+t+t+t+t+t+t+t+t+t+t+t+t+t+t+t+t+t+t+t+t+t+u+ v+t+t+t+t+t+t+t+t+t+t+t+w+ ",
337" ",
338" ",
339" ",
340" x+y+z+ A+B+C+d+ D+E+F+G+ ",
341" H+= y I+J+= K+= L+L+= y+ = = M+ = N+ = = K+ = O+ = = = = = = K+T = J+T .P+ = = = = = = = = ",
342" Q+= R+ S+= T+ U+= y. = = = z+ = N+ = = = V+ = O+ = R+ M+y W+ y.= = ",
343" X+= H+ = I+ K+= = = X+T = N+ = t.E+Y+ = O+ = K+ Z+= `+ F.= = ",
344" t.= = @ `+= = = .@T +@ = N+ = T @@y #@ = O+ = = = = = = $@= +@ F.= = ",
345" y+= = %@ O+= = = H+t.B+= N+ = T #.y+F+= O+ = T = = = Y+= U+ F.= = ",
346" U+= x+ . . M+= = = L+L+= N+ = T .L+= O+ = &@ *@= y. F.= = ",
347" @+ .Z+ 4 4 = X+ O+= H+ = = =@= = N+ = T +@= = O+ = L+ C+= O+ * -@ F.= = ",
348" N+= = = T `+ .= = .R+ = = y+= N+ = T @+= O+ = = = = = `+ H+ .= = .;@ N+T F. ",
349" ",
350" ",
351" ",
352" ",
353" ",
354" ",
355" "};
diff --git a/src/frontend/images/led1.gif b/src/frontend/images/led1.gif
new file mode 100644
index 0000000..0d12d05
--- /dev/null
+++ b/src/frontend/images/led1.gif
Binary files differ
diff --git a/src/frontend/images/led10.gif b/src/frontend/images/led10.gif
new file mode 100644
index 0000000..608f51c
--- /dev/null
+++ b/src/frontend/images/led10.gif
Binary files differ
diff --git a/src/frontend/images/led2.gif b/src/frontend/images/led2.gif
new file mode 100644
index 0000000..cdda56d
--- /dev/null
+++ b/src/frontend/images/led2.gif
Binary files differ
diff --git a/src/frontend/images/led3.gif b/src/frontend/images/led3.gif
new file mode 100644
index 0000000..1bf0030
--- /dev/null
+++ b/src/frontend/images/led3.gif
Binary files differ
diff --git a/src/frontend/images/led4.gif b/src/frontend/images/led4.gif
new file mode 100644
index 0000000..683243e
--- /dev/null
+++ b/src/frontend/images/led4.gif
Binary files differ
diff --git a/src/frontend/images/led5.gif b/src/frontend/images/led5.gif
new file mode 100644
index 0000000..efbb09b
--- /dev/null
+++ b/src/frontend/images/led5.gif
Binary files differ
diff --git a/src/frontend/images/led6.gif b/src/frontend/images/led6.gif
new file mode 100644
index 0000000..98a8f8d
--- /dev/null
+++ b/src/frontend/images/led6.gif
Binary files differ
diff --git a/src/frontend/images/led7.gif b/src/frontend/images/led7.gif
new file mode 100644
index 0000000..85cebc2
--- /dev/null
+++ b/src/frontend/images/led7.gif
Binary files differ
diff --git a/src/frontend/images/led8.gif b/src/frontend/images/led8.gif
new file mode 100644
index 0000000..1e8e1db
--- /dev/null
+++ b/src/frontend/images/led8.gif
Binary files differ
diff --git a/src/frontend/images/led9.gif b/src/frontend/images/led9.gif
new file mode 100644
index 0000000..c5f9522
--- /dev/null
+++ b/src/frontend/images/led9.gif
Binary files differ
diff --git a/src/frontend/images/leds_3.gif b/src/frontend/images/leds_3.gif
new file mode 100644
index 0000000..2ff9fcd
--- /dev/null
+++ b/src/frontend/images/leds_3.gif
Binary files differ
diff --git a/src/frontend/images/leds_32.gif b/src/frontend/images/leds_32.gif
new file mode 100644
index 0000000..2ff9fcd
--- /dev/null
+++ b/src/frontend/images/leds_32.gif
Binary files differ
diff --git a/src/frontend/images/loop.gif b/src/frontend/images/loop.gif
new file mode 100755
index 0000000..cd13fb0
--- /dev/null
+++ b/src/frontend/images/loop.gif
Binary files differ
diff --git a/src/frontend/images/nextcue.gif b/src/frontend/images/nextcue.gif
new file mode 100755
index 0000000..497a8ed
--- /dev/null
+++ b/src/frontend/images/nextcue.gif
Binary files differ
diff --git a/src/frontend/images/play.gif b/src/frontend/images/play.gif
new file mode 100755
index 0000000..b773559
--- /dev/null
+++ b/src/frontend/images/play.gif
Binary files differ
diff --git a/src/frontend/images/prevcue.gif b/src/frontend/images/prevcue.gif
new file mode 100755
index 0000000..0d553c9
--- /dev/null
+++ b/src/frontend/images/prevcue.gif
Binary files differ
diff --git a/src/frontend/images/rec.gif b/src/frontend/images/rec.gif
new file mode 100755
index 0000000..b0926f8
--- /dev/null
+++ b/src/frontend/images/rec.gif
Binary files differ
diff --git a/src/frontend/images/rew.gif b/src/frontend/images/rew.gif
new file mode 100755
index 0000000..790b225
--- /dev/null
+++ b/src/frontend/images/rew.gif
Binary files differ
diff --git a/src/frontend/images/rewindtozero.gif b/src/frontend/images/rewindtozero.gif
new file mode 100755
index 0000000..aff7b12
--- /dev/null
+++ b/src/frontend/images/rewindtozero.gif
Binary files differ
diff --git a/src/frontend/images/stop.gif b/src/frontend/images/stop.gif
new file mode 100755
index 0000000..610c64a
--- /dev/null
+++ b/src/frontend/images/stop.gif
Binary files differ
diff --git a/src/frontend/images/up.gif b/src/frontend/images/up.gif
new file mode 100644
index 0000000..8af2173
--- /dev/null
+++ b/src/frontend/images/up.gif
Binary files differ
diff --git a/src/frontend/images/wave.gif b/src/frontend/images/wave.gif
new file mode 100755
index 0000000..00d9c7e
--- /dev/null
+++ b/src/frontend/images/wave.gif
Binary files differ
diff --git a/src/frontend/images/xpbutton_dn.gif b/src/frontend/images/xpbutton_dn.gif
new file mode 100644
index 0000000..c3d211a
--- /dev/null
+++ b/src/frontend/images/xpbutton_dn.gif
Binary files differ
diff --git a/src/frontend/images/xpbutton_up.gif b/src/frontend/images/xpbutton_up.gif
new file mode 100644
index 0000000..5248a0d
--- /dev/null
+++ b/src/frontend/images/xpbutton_up.gif
Binary files differ
diff --git a/src/frontend/images/xpbutton_uplit.gif b/src/frontend/images/xpbutton_uplit.gif
new file mode 100644
index 0000000..831f171
--- /dev/null
+++ b/src/frontend/images/xpbutton_uplit.gif
Binary files differ
diff --git a/src/frontend/resource.rc b/src/frontend/resource.rc
new file mode 100644
index 0000000..28e2b35
--- /dev/null
+++ b/src/frontend/resource.rc
@@ -0,0 +1,2 @@
1#define IDI_ICON1 101
2IDI_ICON1 ICON DISCARDABLE "src/frontend/hd24connect.ico"
diff --git a/src/frontend/selftest.cpp b/src/frontend/selftest.cpp
new file mode 100644
index 0000000..2f3f65a
--- /dev/null
+++ b/src/frontend/selftest.cpp
@@ -0,0 +1,646 @@
1#include <FL/forms.H>
2hd24fs* testfs;
3
4void createimage_callback(void* y)
5{
6 cout << "." << endl;
7 Fl::add_timeout(1.0,createimage_callback,y);
8 return;
9}
10int passcount;
11int failcount;
12#define MINSECTORS 1353964
13
14//#define BITBIGGER (MINSECTORS+10000)
15/* this gives for a bit over 5 minutes at 48k, 24 tracks: */
16#define BITBIGGER (MINSECTORS+2073600)
17
18/* constant is for pretty demo image. */
19void pass()
20{
21 passcount++;
22 cout << "......................................................PASS" << endl;
23}
24void fail()
25{
26 failcount++;
27 cout << "......................................................FAIL" << endl;
28}
29void fail(const char* reason)
30{
31 failcount++;
32 cout << "......................................................FAIL" << endl;
33 cout << "Reason: "<<reason << endl;
34}
35void test_createimage()
36{
37 cout << "Test if creating too small drive images is prevented... " << endl;
38
39 __uint32 lastsector=MINSECTORS-1;
40
41 string* strtest=new string("testimage.h24");
42 char message[2048];
43 message[0]='\0';
44 Fl::add_timeout(1.0,createimage_callback,&message[0]);
45 int result=hd24utils::newdriveimage(strtest,lastsector,&message[0],NULL);
46 delete strtest;
47 Fl::remove_timeout(&createimage_callback);
48 if (result!=-1) fail(); else pass();
49 ////////////////////////////////////////////////////
50 cout << "-----------------------------------------------" << endl;
51 cout << "Create minimum size empty drive image... please wait" << endl;
52 lastsector=MINSECTORS;
53
54 strtest=new string("testimage.h24");
55 result=hd24utils::newdriveimage(strtest,lastsector,&message[0],NULL);
56
57 cout << "Image create messages=" << message << endl;
58 if (result==0) pass(); else fail();
59 // Check expected drive image contents.
60 hd24fs* testfs=new hd24fs((const char*)NULL,hd24fs::MODE_RDWR,strtest,false);
61 /* we calculate free space based on 1 channel because it is much
62 more sensitive than free space based on 24 channels */
63 string* freespace=testfs->freespace(48000,1);
64
65 cout << "Free space on drive: " << *freespace << endl;
66 delete testfs;
67 //////////////////////////////////////////////////////
68 cout << "-----------------------------------------------" << endl;
69 cout << "Creating somewhat larger size empty drive image... please wait" << endl;
70 lastsector=BITBIGGER;
71
72 string* strtest2=new string("testimage2.h24");
73 result=hd24utils::newdriveimage(strtest2,lastsector,&message[0],NULL);
74
75 cout << "Image create messages=" << message << endl;
76 if (result==0) pass(); else fail();
77 // Check expected drive image contents.
78 hd24fs* testfs2=new hd24fs((const char*)NULL,hd24fs::MODE_RDWR,strtest2,false);
79 string* freespace2=testfs2->freespace(48000,1);
80 cout << "Free space on drive: " << *freespace2 << endl;
81 if (strcmp(freespace->c_str(),freespace2->c_str())==0)
82 {
83 fail("Images were supposed to have different sizes");
84 } else {
85 pass();
86 }
87 delete testfs2;
88 delete freespace2;
89 delete strtest2;
90//*/
91 delete freespace;
92 delete strtest;
93 return;
94}
95
96void test_useimage()
97{
98 char failmsg[64];
99 cout << "Try to use empty drive image... " << endl;
100 //false=force?
101 string* strtest=new string("testimage2.h24");
102 testfs=new hd24fs((const char*)NULL,hd24fs::MODE_RDWR,strtest,false);
103 delete strtest;
104 strtest=NULL;
105
106 // Let's see if all is as expected.
107 if (!(testfs->isOpen())) fail(); else pass();
108 string* freespace=testfs->freespace(48000,24);
109 cout << "Free space on drive: " << *freespace << endl;
110 delete freespace;
111 hd24raw* rawfs=new hd24raw(testfs);
112 /*
113 These functions are only available through raw FS
114 */
115 int songsondisk=rawfs->songsondisk();
116 cout << "Songs on disk=" << songsondisk << endl;
117 if (songsondisk!=0) fail(); else pass();
118
119 __uint32 lastsector=rawfs->getlastsectornum();
120 __uint32 expectedlastsector=BITBIGGER;
121 cout << "Last sectornum of drive image="<< lastsector << endl;
122
123
124 if (lastsector!=expectedlastsector)
125 {
126 sprintf(failmsg,"Expected last sector was %ld but found %ld",expectedlastsector,lastsector);
127 fail(failmsg);
128 }
129 else
130 {
131 pass();
132 }
133
134 string* devname=testfs->getdevicename();
135 cout <<"Device name="<<*devname<<endl;
136 if (*devname=="")
137 {
138 fail("Device name should always exist");
139 } else pass();
140
141 string* volname=testfs->volumename();
142 cout <<"Volume name="<<*volname <<endl;
143 if (*volname=="") fail("Volume name of freshly formatted drive must be nonempty"); else pass();
144
145 // set volume name, commit, then test if change OK
146 __uint32 projcount=testfs->projectcount();
147 cout <<"Project count="<<projcount << endl;
148 if (projcount!=1) fail("Newly formatted image must have exactly 1 project."); else pass();
149 hd24project* currproj=NULL;
150 if (projcount>0)
151 {
152 currproj=testfs->getproject(0); // must error
153 cout << "Check protection against getting project 0" << endl;
154 if (currproj!=NULL) fail(); else pass();
155
156 delete currproj;
157 currproj=testfs->getproject(1); // must not error
158 cout << "Check zero songcount for supposedly empty project" << endl;
159 __uint32 songcount=currproj->songcount();
160 if (songcount!=0) fail(); else pass();
161
162 cout << "Check getting nonexisting/invalid project numbers" << endl;
163 int failed=0;
164 for (int i=2; i<=100; i++)
165 {
166 currproj=testfs->getproject(i); // must not error but must return null
167 if (currproj!=NULL)
168 {
169 failed=1;
170 }
171 }
172 if (failed!=0) fail(); else pass();
173 }
174
175 cout << "set volume name in drive image" << endl;
176 testfs->setvolumename("myvol"); // only in memory!!!
177 // check if volume name has been set (in memory)
178 cout << "reading back volume name to see if set was successful" << endl;
179
180 volname=testfs->volumename();
181 if (*volname!="myvol") fail(); else pass();
182
183 cout << "set longer name in drive image" << endl;
184 testfs->setvolumename("mylongervolumename"); // only in memory!!!
185 volname=testfs->volumename();
186 if (*volname!="mylongervolumename") fail(); else pass();
187
188 cout << "Test truncating too long volume name in drive image" << endl;
189 testfs->setvolumename("myoverlylongvolumenamethemaximumissixtyfourcharactersbutwemakeitlongeranyway"); // only in memory!!!
190 volname=testfs->volumename();
191 if (strlen(volname->c_str())!=64) fail(); else pass();
192 cout << "Try to clear volume name" <<endl;
193 testfs->setvolumename("");
194 volname=testfs->volumename();
195 if (strlen(volname->c_str())!=0) fail(); else pass();
196 cout << "Setting volume name " << endl;
197 testfs->setvolumename("MyVolume");
198 cout << "and commiting for later readback." << endl;
199 testfs->savedriveinfo(); // auto-commit
200 cout << "Commit done." << endl;
201 return;
202}
203
204void test_commit()
205{
206 string* strtest=new string("testimage2.h24");
207
208 cout << "Delete testfs..." << endl;
209 delete testfs;
210 testfs=NULL;
211
212 pass();
213
214 testfs=new hd24fs((const char*)NULL,hd24fs::MODE_RDWR,strtest,false);
215 delete strtest;
216 cout << "Reading back volume name" << endl;
217 string* volname=testfs->volumename();
218 cout << "Read back " << *volname << endl;
219 if (*volname!="MyVolume") fail(); else pass();
220
221 // after commit, drive size must be preserved.
222 hd24raw* rawfs=new hd24raw(testfs);
223 __uint32 lastsector=rawfs->getlastsectornum();
224 __uint32 expectedlastsector=BITBIGGER;
225 cout << "Test if image has remained same size: "<< lastsector << endl;
226 if (lastsector!=expectedlastsector) fail(); else pass();
227
228
229 testfs->setvolumename("Drive Name");
230 testfs->savedriveinfo(); // commit tested before-assume it succeeds.
231}
232
233void test_project()
234{
235 string* strtest=new string("testimage2.h24");
236
237 cout << "Delete testfs..." << endl;
238 delete testfs;
239 testfs=NULL;
240
241 pass();
242
243 testfs=new hd24fs((const char*)NULL,hd24fs::MODE_RDWR,strtest,false);
244 delete strtest;
245 hd24raw* rawfs=new hd24raw(testfs);
246 cout << "Checking current project count... (should be 1): ";
247 int pcount=testfs->projectcount();
248 cout << pcount << endl;
249 if (pcount==1) pass(); else fail("Project count of formatted drive should be 1");
250
251 cout << "Try to get project id 0 (should not be possible)" << endl;
252 hd24project* proj=testfs->getproject(0);
253 if (proj==NULL) pass(); else
254 {
255 delete proj;
256 proj=NULL;
257 fail("Project IDs should be 1 based but are not!");
258 }
259
260 cout << "Try to get project id 1 (first and only project on drive" << endl;
261 proj=testfs->getproject(1);
262 if (proj==NULL) fail("Cannot get only project on drive"); else
263 {
264 delete proj;
265 proj=NULL;
266 pass();
267 }
268 cout << "Try to get any but the first project on the drive" << endl;
269 cout << "(using legal project numbers and one too high number)" << endl;
270 int projsgot=0;
271 int i=0;
272 for (i=2; i<=100; i++)
273 {
274 if (proj!=NULL)
275 {
276 delete proj;
277 proj=NULL;
278 }
279 proj=testfs->getproject(i);
280 if (proj!=NULL)
281 {
282 projsgot++;
283 fail("Managed to get project number:");
284 cout << i << endl;
285 delete proj;
286 proj=NULL;
287 }
288 }
289 if (proj!=NULL)
290 {
291 delete proj;
292 proj=NULL;
293 }
294
295 if (projsgot==0) pass();
296
297 cout << "Try if only project on drive is protected from deleting" << endl;
298 testfs->deleteproject(1);
299 pcount=testfs->projectcount();
300 cout << pcount << endl;
301 if (pcount==1) pass(); else fail("Only project on drive should not be deletable");
302
303 cout << "Try to create a project..." << endl;
304 hd24project* newproj=testfs->createproject("selftest project 1");
305 if (newproj==NULL)
306 {
307 fail("Creating project failed");
308 } else {
309 pass();
310 }
311 delete newproj; // we won't be using this object anymore.
312
313 cout << "Make sure project creation updates project count..." << endl;
314 pcount=testfs->projectcount();
315 if (pcount==2) pass(); else fail("Project count should have been 2 at this stage.");
316 cout << "Trying to delete newly created project..." << endl;
317 testfs->deleteproject(2);
318 pcount=testfs->projectcount();
319 if (pcount==1) pass(); else fail("Deletion successful");
320
321 cout << "Trying to create 98 new projects (should be possible)..." << endl;
322 char projname[64];
323 int failedcreate=0;
324 for (i=0;i<98;i++)
325 {
326 cout << "project=" << i << endl;
327 sprintf(projname,"selftest project %d",i+2);
328 hd24project* newproj=testfs->createproject(projname);
329 pcount=testfs->projectcount();
330 if (pcount!=(i+2))
331 {
332 sprintf(projname,"could not create project %d",i);
333 fail(projname);
334 failedcreate=1;
335 break;
336 };
337 delete newproj;
338 }
339 if (failedcreate==0)
340 {
341 pass();
342 }
343 cout << "Checking if project count is 99 as expected " << endl;
344 pcount=testfs->projectcount();
345 if (pcount==99) pass(); else fail("Nope.");
346
347 cout << "Trying if creating more projects than allowed is prevented" << endl;
348 newproj=NULL;
349 newproj=testfs->createproject(projname);
350 if (newproj!=NULL)
351 {
352 fail("Project object was returned!");
353 } else {
354 pass();
355 }
356
357 pcount=testfs->projectcount();
358 cout << "Verifying project count to still be 99" <<endl;
359 if (pcount==99) pass(); else fail("Project count unduely updated.");
360
361 cout << "Deleting last 50 projects" << endl;
362 /* this should leave 49 projects in place. */
363 for (i=1;i<60;i++)
364 {
365 testfs->deleteproject(50);
366 }
367 pcount=testfs->projectcount();
368 if (pcount==49) pass(); else fail("Incorrect project count.");
369 cout << "Creating 50th project again" << i << endl;
370 sprintf(projname,"selftest project %d",i+2);
371 if (newproj!=NULL) delete newproj;
372
373 newproj=testfs->createproject(projname);
374 pcount=testfs->projectcount();
375 cout << "Expecting project count to be 50 now..." << endl;
376 if (pcount!=50) fail("Incorrect project count"); else pass();
377
378 cout << "Checking project sector of first project (must be 0x14 or 20)" << endl;
379 __uint32 projsec= rawfs->getprojectsectornum(1);
380 cout << "Proj sector=" << projsec << endl;
381 if (projsec!=0x14) fail("Incorrect sector"); else pass();
382
383 cout << "Deleting first project (to empty a slot)" << endl;
384 pcount=testfs->projectcount();
385 cout << "project count BEFORE=" <<pcount <<endl;
386
387 testfs->deleteproject(1);
388 int pcount2=testfs->projectcount();
389 cout << "Project count AFTER=" <<pcount2 << endl;
390 if (pcount2!=(pcount-1)) fail("Expected project count to be 49."); else pass();
391 projsec= rawfs->getprojectsectornum(1);
392 cout << "Second project should originally have been on 0x15,"<<endl;
393 cout << "expecting first project to start on that sector now..." <<endl;
394 cout << "(in reality it is on " << projsec << ")" << endl;
395 if (projsec!=0x15) fail("Incorrect sector"); else pass();
396 /* now create a new project-- this project must be on sector 0x14
397 again */
398 cout << "Creating new project - it should overwrite the first project block" << endl;
399 newproj=testfs->createproject(projname);
400 pcount=testfs->projectcount();
401 cout << "Expecting project count of 50 again, in reality it is " << pcount << endl;
402 if (pcount!=50) fail("Incorrect project count"); else pass();
403 __sint32 projid=newproj->projectid();
404 cout << "Project id=" << projid << endl;
405 if (projid!=50) {
406 fail("Unexpected project id");
407 }
408 projsec=rawfs->getprojectsectornum(projid);
409 cout << "Expecting project sector of project " << projid << " to be 0x14," ;
410 cout << " in reality it is " << projsec << endl;
411
412 if (projsec!=0x14) fail("Incorrect sector"); else pass();
413
414 newproj->projectname("Changed Name");
415 string* projcname=newproj->projectname();
416 if (*projcname!="Changed Name") fail("Project name change unsuccessful"); else pass();
417 delete projcname;
418 newproj->save();
419 delete rawfs;
420}
421
422
423void test_proj2()
424{
425 int pcount;
426 string* strtest=new string("testimage2.h24");
427
428 cout << "Delete testfs..." << endl;
429 delete testfs;
430 testfs=NULL;
431
432 pass();
433
434 testfs=new hd24fs((const char*)NULL,hd24fs::MODE_RDWR,strtest,false);
435 delete strtest;
436 cout << "Checking current project count... (should be 50): ";
437
438 pcount=testfs->projectcount();
439 cout << "Expecting project count of 50 again, in reality it is " << pcount << endl;
440 if (pcount!=50) fail("Incorrect project count"); else pass();
441 cout << "Getting existing project no. 50..." << endl;
442 hd24project* currproj=testfs->getproject(50);
443 if (currproj==NULL) { fail("Cannot get project"); } else {pass();}
444 cout << "Getting project name: ";
445 string* pname=currproj->projectname();
446 cout << *pname << endl;
447 if (*pname!="Changed Name") fail("Project name change unsuccessful"); else pass();
448
449// delete rawfs;
450
451}
452
453void test_song()
454{
455 string* strtest=new string("testimage2.h24");
456
457 cout << "Delete testfs..." << endl;
458 delete testfs;
459 testfs=NULL;
460
461 pass();
462
463 testfs=new hd24fs((const char*)NULL,hd24fs::MODE_RDWR,strtest,false);
464 delete strtest;
465
466 // Check on-disk songcount
467 hd24raw* rawfs=new hd24raw(testfs);
468 int songcount=rawfs->songsondisk();
469 cout << "Checking if song count is still zero as it should be "<<endl;
470 if (songcount!=0)
471 {
472 fail("Song count of newly formatted drive should be 0.");
473 } else {
474 pass();
475 }
476
477 delete rawfs;
478
479}
480
481void test_demoimage()
482{
483 string* strtest=new string("testimage2.h24");
484
485 cout << "Delete testfs..." << endl;
486 delete testfs;
487 testfs=NULL;
488
489 pass();
490
491 testfs=new hd24fs((const char*)NULL,hd24fs::MODE_RDWR,strtest,false);
492 delete strtest;
493
494 testfs->setvolumename("Sizeable Hard Drive"); // only in memory!!!
495 testfs->commit();
496
497 string* volname=testfs->volumename();
498 if (*volname!="Sizeable Hard Drive") fail(); else pass();
499 delete volname;
500
501 cout << "Checking FS version..." << endl;
502 string* version=testfs->version();
503 if (*version!="1.10") fail("Unexpected FS version (expectation was 1.10)"); else pass();
504 delete version;
505
506 cout << "Checking max. project count (99 expected)..." << endl;
507 __uint32 maxprojcount=testfs->maxprojects();
508 if (maxprojcount!=99) fail("Unexpected max project count"); else pass();
509
510 cout << "Checking block size..." << endl;
511 if (testfs->getblocksizeinsectors() != 0x480) fail("Unexpected block size"); else pass();
512
513 // delete all but last project
514 while (testfs->projectcount()>1)
515 {
516 // leave only last project
517 testfs->deleteproject(2);
518 }
519
520 // now up the total project count to 42
521 char projname[64];
522 int i=1;
523 hd24project* newproj=NULL;
524 while (testfs->projectcount()!=42)
525 {
526 i++;
527 sprintf(projname,"selftest project %d",i+2);
528 int prevprojcount=testfs->projectcount();
529 newproj=testfs->createproject(projname);
530 int newprojcount=testfs->projectcount();
531 if (newprojcount==prevprojcount)
532 {
533 fail("Failed to create project.");
534 break;
535 }
536 if (newproj!=NULL)
537 {
538 delete newproj;
539 newproj=NULL;
540 }
541
542 }
543 if (newproj!=NULL)
544 {
545 delete newproj; // we won't be using this object anymore.
546 newproj=NULL;
547 }
548
549 // rename project now.
550 hd24project* currproj;
551 currproj=testfs->getproject(15); // must error
552 testfs->lastprojectid(15);
553 currproj->projectname("Client X");
554 currproj->save();
555 volname=testfs->volumename();
556 cout <<"Volume name="<<*volname <<endl;
557 testfs->commit();
558 delete currproj;
559 currproj=NULL;
560 currproj=testfs->getproject(15);
561 cout << "Test if project name change with commit works..." << endl;
562 cout << "Projname is supposed to be 'Client X', and is: ";
563 string* sprojname=currproj->projectname();
564 cout << *sprojname << endl;
565 if (*sprojname!="Client X") fail("project name change failed."); else pass();
566 delete sprojname;
567 cout << "Testing if song count is zero..." << endl;
568 if (currproj->songcount()==0) pass(); else fail("Should have been 0");
569
570 // Now it's time to create some songs.
571 for (i=0;i<12;i++)
572 {
573 hd24song* currsong=currproj->createsong("A Huge Hit",24,48000);
574 currsong->save();
575 delete currsong;
576 }
577 currproj->lastsongid(8);
578 currproj->save();
579 testfs->commit();
580 hd24song* currsong=currproj->getsong(currproj->lastsongid());
581 cout << "Renaming song..." << endl;
582 currsong->songname("A Huge Hit (final take)");
583 currsong->save();
584 testfs->commit();
585 delete currsong;
586 currsong=NULL;
587 currsong=currproj->getsong(currproj->lastsongid());
588 cout << "Checking if song ID is equal to last set..." << endl;
589 if (currsong->songid()==8) pass(); else fail("Incorrect songid.");
590 string* freespacebefore=testfs->freespace(48000,24);
591 cout << "Lengthening song..." << endl;
592 __uint32 desiredlen=10416000; //00:03:37.00
593 __uint32 newlen=currsong->songlength_in_samples(desiredlen);
594 if (newlen!=desiredlen)
595 {
596 fail("Song lengthening failed.");
597 cout << "Length in samples is " << newlen
598 << "instead of " << desiredlen << endl;
599 } else pass();
600
601 currsong->setwriteprotected(true);
602 currsong->save();
603 testfs->commit();
604 cout << "Free space on drive before lengthening: " << *freespacebefore << endl;
605 string* freespace=testfs->freespace(48000,24);
606 cout << "Free space on drive after lengthening: " << *freespace << endl;
607 delete freespace;
608}
609
610int runselftest(HD24UserInterface* ui)
611{
612 cout << "=======TESTMODE ACTIVATED=======" << endl;
613 passcount=0;
614 failcount=0;
615 test_createimage();
616 test_useimage();
617 test_commit();
618 test_project();
619 test_proj2();
620
621 test_song();
622 test_demoimage(); // create an interesting looking demo drive image
623
624
625 cout << "Create 1 project, 99 projects, try 100th project" << endl;
626
627 cout << "Create 1..99 songs" << endl;
628
629 cout << "rename projects, rename songs" << endl;
630
631 cout << "Delete 1.99 projects/songs" << endl;
632
633 cout << "Record audio to songs" << endl;
634
635 // Proceed to test gui.
636
637 Fl_Window* window=ui->make_window(testfs);
638 window->end();
639 window->show();
640 fl_message("Proceeding to test GUI.");
641 cout << "====================== TEST COMPLETE ===================" << endl;
642 cout << "PASS: " << passcount << endl;
643 cout << "FAIL: " << failcount << endl;
644 cout << "========================================================" << endl;
645 return 0;
646}
diff --git a/src/frontend/ui_hd24connect.fl b/src/frontend/ui_hd24connect.fl
new file mode 100755
index 0000000..eae32ad
--- /dev/null
+++ b/src/frontend/ui_hd24connect.fl
@@ -0,0 +1,4597 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0109
3header_name {.h}
4code_name {.cxx}
5decl {class HD24TrackChannel;} {public
6}
7
8decl {class TrackInfo;} {public
9}
10
11decl {class HD24UserInterface;} {public
12}
13
14decl {class MixerUI;} {public
15}
16
17decl {class RecorderUI;} {public
18}
19
20decl {class PortAudioWrapper;} {public
21}
22
23decl {class JackWrapper;} {public
24}
25
26decl {class hd24transferengine;} {public
27}
28
29decl {\#define HD24DEBUG 0} {public
30}
31
32decl {\#define BLINKRATE 25} {public
33}
34
35decl {\#define PA_FRAMESPERBUF 512} {public
36}
37
38decl {\#define MAXCHANNELS 24} {public
39}
40
41decl {\#define UIREFRESH 1 /* 1=best, 10=1/10 refresh rate */} {public
42}
43
44decl {\#define HD24MODE hd24fs::MODE_RDWR} {public
45}
46
47decl {\#define TIMEOUT 0.03} {public
48}
49
50decl {\#define SPLITFILESIZE_BYTES ((__uint64)(1024*1024*1024))} {public
51}
52
53decl {\#include <config.h>} {public
54}
55
56decl {\#include <string>} {public
57}
58
59decl {\#include <vector>} {public
60}
61
62decl {\#include <portwin.h>} {public
63}
64
65decl {\#include <soundlibs.h> /* portaudio, libjack */} {public
66}
67
68decl {\#include <iostream>} {public
69}
70
71decl {\#include <FL/FLTKstuff.H>} {public
72}
73
74decl {\#include <FL/Fl_Menu_Bar.H>} {public
75}
76
77decl {\#include <FL/Fl_File_Chooser.H>} {public
78}
79
80decl {\#include <FL/filename.H>} {public
81}
82
83decl {\#include <xplat_dlfcn.h>} {public
84}
85
86decl {\#include <sndfile.h>} {public
87}
88
89decl {\#include <convertlib.h>} {public
90}
91
92decl {\#include <memutils.h>} {public
93}
94
95decl {\#include <hd24fs.h>} {public
96}
97
98decl {\#include <hd24utils.h>} {public
99}
100
101decl {\#include <hd24transferengine.h>} {public
102}
103
104decl {\#include <smpte.h>} {public
105}
106
107decl {\#include <WidgetPDial.h>} {public
108}
109
110decl {\#include <dialog_newproject.h>} {public
111}
112
113decl {\#include <dialog_newsong.h>} {public
114}
115
116decl {\#include <dialog_setlocate.h>} {public
117}
118
119decl {\#include <dialog_filesize.h>} {public
120}
121
122decl {\#include <dialog_setlength.h>} {public
123}
124
125decl {\#include <dialog_fromto.h>} {public
126}
127
128decl {\#include <dialog_rename.h>} {public
129}
130
131decl {\#include <dialog_options.h>} {public
132}
133
134decl {\#include <dialog_choosedevice.h>} {public
135}
136
137decl {\#include <ui_help_about.h>} {public
138}
139
140decl {\#include <ui_mixer.h>} {public
141}
142
143decl {\#include <time.h>} {public
144}
145
146decl {\#include <math.h>} {public
147}
148
149decl {\#include <ui_hd24trackchannel.h>} {public
150}
151
152decl {\#include <ui_recorder.h>} {public
153}
154
155decl {class HD24UserInterface;} {public
156}
157
158decl {class HD24control;} {public
159}
160
161decl {class SoundFileWrapper;} {public
162}
163
164class HD24data {} {
165 decl {HD24UserInterface* parentui;} {}
166 decl {friend class HD24control;} {}
167 decl {int ready;} {public
168 }
169}
170
171class HD24control {} {
172 decl {HD24data* data;} {}
173 Function {parentui(HD24UserInterface* p_parentui)} {open
174 } {
175 code {data->parentui=p_parentui;} {}
176 }
177 Function {parentui()} {open return_type {HD24UserInterface*}
178 } {
179 code {return data->parentui;} {}
180 }
181 Function {HD24control()} {open
182 } {
183 code {data=new HD24data();} {}
184 }
185 Function {~HD24control()} {open
186 } {
187 code {delete data;} {}
188 }
189 Function {ready()} {open return_type int
190 } {
191 code {return data->ready;} {}
192 }
193 Function {ready(int p_ready)} {open return_type void
194 } {
195 code {data->ready=p_ready;} {}
196 }
197}
198
199decl {\#include <hd24sndfile.h>} {public
200}
201
202class HD24UserInterface {open
203} {
204 decl {hd24transferengine* transeng;} {}
205 decl {HD24control* control;} {public
206 }
207 decl {PortAudioWrapper* portaudio;} {public
208 }
209 decl {SoundFileWrapper* soundfile;} {public
210 }
211 decl {JackWrapper* libjack;} {public
212 }
213 decl {int busy;} {public
214 }
215 decl {hd24fs* defaulthd24;} {}
216 decl {hd24fs* currenthd24;} {public
217 }
218 decl {int trackselected[24];} {public
219 }
220 decl {hd24project* currproj;} {public
221 }
222 decl {hd24song* currsong;} {public
223 }
224 decl {Fl_Check_Button* track[24];} {public
225 }
226 decl {int tracksave[24]; /* to keep track[24] settings */} {public
227 }
228 decl {vector<string> format_outputextension;} {public
229 }
230 decl {vector<string> format_shortdesc;} {public
231 }
232 Function {deactivate_ui()} {open return_type void
233 } {
234 code {drivename->deactivate();
235rename_drive->deactivate();
236projectname->deactivate();
237rename_project->deactivate();
238songname->deactivate();
239songinfogroup->deactivate();
240tabDrive->deactivate();
241rename_song->deactivate();
242locatepoints->deactivate();
243fromto->deactivate();
244transfercanvas->deactivate();
245menufile->deactivate();
246tabRecorder->deactivate();
247tabMixer->deactivate();
248menuhelp->deactivate();} {}
249 }
250 Function {disable_program_controls()} {return_type void
251 } {
252 code {drivename->deactivate();
253rename_drive->deactivate();
254projectname->deactivate();
255rename_project->deactivate();
256songname->deactivate();
257rename_song->deactivate();
258transfercanvas->deactivate();
259locatepoints->deactivate();
260fromto->deactivate();
261button_golocatepoint->deactivate();
262recorder->control->disable();} {}
263 }
264 Function {activate_ui()} {open return_type void
265 } {
266 code {drivename->activate();
267transfercanvas->activate();
268tabRecorder->activate();
269projectname->activate();
270songname->activate();
271songinfogroup->activate();
272tabDrive->activate();
273tabMixer->activate();
274locatepoints->activate();
275fromto->activate();
276menufile->activate();
277menuhelp->activate();} {}
278 }
279 Function {addsongtodropdown(int i)} {} {
280 code {\#if (HD24DEBUG==1)
281 cout << "addsongtodropdown " << i << endl;
282 cout << "set song" << endl;
283\#endif
284 hd24song* song=currproj->getsong(i);
285\#if (HD24DEBUG==1)
286 cout << "song is set" << endl;
287\#endif
288 string* strsongname=Convert::int2str(i);
289 *strsongname+=": ";
290 string* actualname=song->songname();
291 *strsongname+=*actualname;
292 delete actualname;
293
294\#if (HD24DEBUG==1)
295 cout << "song is set2" << endl;
296\#endif
297 songname->add(strsongname->c_str(),0,(void (*)(Fl_Widget*,void*))(&(songname_cb)),(void*)this);
298\#if (HD24DEBUG==1)
299 cout << "song is set3" << endl;
300\#endif
301 delete song;
302 delete(strsongname);} {}
303 }
304 Function {populate_projectlist(int projectid)} {return_type void
305 } {
306 code {/* Set project info */
307int i;
308\#if (HD24DEBUG==1)
309 cout << "clear project list" << endl;
310\#endif
311for (i=0;i<=100;i++) {
312 projectname->remove(0);
313}
314int numprojs=0;
315if (currenthd24==NULL) {
316 return;
317}
318numprojs=currenthd24->projectcount();
319for (i=1; i<=numprojs; i++) {
320 hd24project* currproj=currenthd24->getproject(i);
321 string* projname1=Convert::int2str(i);
322 *projname1+=": ";
323 string* currpname=currproj->projectname();
324 *projname1+=*currpname;
325 projectname->add(projname1->c_str(),0,(void (*)(Fl_Widget*,void*))(&(projectname_cb)),(void*)this);
326 delete(currpname);
327 delete(projname1);
328 delete currproj;
329}
330
331select_project(projectid);} {}
332 }
333 Function {populate_songlist(int songid)} {open return_type void
334 } {
335 code {int i;
336int numsongs=currproj->songcount();
337\#if (HD24DEBUG==1)
338 cout << "populate_songlist" << endl;
339\#endif
340if (numsongs==0)
341{
342\#if (HD24DEBUG==1)
343 cout << "no songs" << endl;
344\#endif
345 for (i=0;i<=100;i++) {
346 songname->remove(0);
347 }
348 songname->add("-- Empty project --",0,NULL,(void*)this);
349 songname->value(0);
350 refresh(songname);
351 return;
352}
353songname->activate();
354\#if (HD24DEBUG==1)
355 cout << "clear songlist" << endl;
356\#endif
357for (i=0;i<=100;i++) {
358 songname->remove(0);
359}
360
361songname->add("-- All songs --",0,(void (*)(Fl_Widget*,void*))(&(songname_cb)),(void*)this);
362
363\#if (HD24DEBUG==1)
364 cout << "Add songs to dropdown" << endl;
365\#endif
366for (i=1; i<=numsongs; i++) {
367 addsongtodropdown(i);
368}
369control->ready(1);
370this->busy=0;
371
372\#if (HD24DEBUG==1)
373 cout << "about to select last used song" << endl;
374\#endif
375signed long lastsong=currproj->lastsongid();
376if (lastsong<1) {
377 lastsong=0;
378}
379\#if (HD24DEBUG==1)
380 cout << "got last song id:" << lastsong << endl;
381\#endif
382if (lastsong==0) {
383 songname->value(0);
384 songname->redraw();
385 return;
386}
387select_song(lastsong);
388songname->redraw();} {}
389 }
390 Function {populate_drivelist(int driveid)} {open return_type void
391 } {
392 code {// when another drive has been selected, init dropdown lists.
393for (unsigned int q=0;q<=99;q++) {
394 drivename->remove(0);
395}
396// find out how many ADAT drives are detected.
397unsigned int devcount=defaulthd24->hd24devicecount();
398\#if (HD24DEBUG==1)
399 cout << "devcount=" << devcount << endl;
400\#endif
401unsigned int usedevcount=devcount;
402if (devcount==0) usedevcount=1; // we are using a file image.
403for (unsigned int devnum=0;devnum<usedevcount;devnum++)
404{
405\#if (HD24DEBUG==1)
406cout << "devnum" << devnum << endl;
407\#endif
408 // currhd24 is not a spelling error. it is for local use.
409 string* idir=hd24utils::getlastdir("driveimagedir");
410 hd24fs* currhd24 = new hd24fs(idir->c_str(),defaulthd24->mode(),devnum);
411 delete idir;
412 if (!(currhd24->isOpen())) {
413 if (!(defaulthd24->isOpen())) {
414 disable_program_controls();
415 }
416 }
417\#if (HD24DEBUG==1)
418cout << "newfs" << devnum << endl;
419\#endif
420
421 string* drivename1=Convert::int2str(devnum+1);
422
423 *drivename1+=": ";
424 string* volname;
425
426\#if (HD24DEBUG==1)
427cout << "getvolname" << devnum << endl;
428\#endif
429
430 if (devcount!=usedevcount)
431 {
432 volname=currenthd24->volumename();
433 } else {
434 volname=currhd24->volumename();
435 }
436
437\#if (HD24DEBUG==1)
438cout << "gotvolname" << devnum << endl;
439\#endif
440
441 *drivename1+=*volname;
442 // NULL=callback
443 drivename->add(drivename1->c_str(),0,(void (*)(Fl_Widget*,void*))(&(drivename_cb)),(void*)this);
444 delete(currhd24);
445 delete(volname);
446 delete(drivename1);
447}
448
449/* Set drive info */
450\#if (HD24DEBUG==1)
451cout << "set drivename dropdown value to " << driveid << endl;
452\#endif
453drivename->value(driveid);} {}
454 }
455 Function {populate_locatepoints(hd24song* locsong,Fl_Choice* lpoints)} {open return_type int
456 } {
457 code {int i;
458int numpoints=0;
459if (locsong!=NULL)
460{
461 numpoints=locsong->locatepointcount();
462}
463
464\#if (HD24DEBUG==1)
465 cout << "populate_lpoints" << endl;
466\#endif
467if (numpoints==0)
468{
469\#if (HD24DEBUG==1)
470 cout << "no locate points." << endl;
471\#endif
472 for (i=0;i<=99;i++) {
473 lpoints->remove(0);
474 }
475 lpoints->deactivate();
476 refresh(lpoints);
477 return numpoints;
478}
479lpoints->activate();
480\#if (HD24DEBUG==1)
481 cout << "clear lpoints" << endl;
482\#endif
483for (i=0;i<=99;i++) {
484 lpoints->remove(0);
485}
486for (i=0; i<numpoints+1; i++) {
487 // locatepoint (max+1) is a virtual locate point 'END'.
488\#if (HD24DEBUG==1)
489 cout << "set locate point" << endl;
490\#endif
491 __uint32 locatepos=locsong->getlocatepos(i);
492\#if (HD24DEBUG==1)
493 cout << "locate pos "<<i<<" is " << locatepos << endl;
494\#endif
495 string* locname1;
496 if ((i==0)||(i==numpoints)) {
497 locname1=locsong->getlocatename(i);
498
499 if ((locname1->length())>0) {
500 while (locname1->substr(0,1)==" ") {
501 *locname1=locname1->substr(1,locname1->length()-1);
502 }
503 while (locname1->substr(locname1->length()-1,1)==" ") {
504 *locname1=locname1->substr(0,locname1->length()-1);
505 }
506 } else {
507 *locname1+="START";
508 }
509 *locname1+=": ";
510 if (i==numpoints) {
511 *locname1+="+";
512 }
513 string* dur=locsong->display_duration(locatepos);
514 *locname1+=*dur;
515 delete (dur);
516 } else {
517 locname1=Convert::int2str(i,2,"0");
518 *locname1+=": +";
519 string* dur=locsong->display_duration(locatepos);
520 *locname1+=*dur;
521 delete (dur);
522 *locname1+=" ";
523 string* lni=locsong->getlocatename(i);
524 *locname1+=*lni;
525 delete(lni);
526 }
527
528\#if (HD24DEBUG==1)
529 cout << "add lpoints" << endl;
530\#endif
531 lpoints->add(locname1->c_str(),0,NULL,(void*)this);
532 delete locname1;
533 lpoints->redraw();
534\#if (HD24DEBUG==1)
535 cout << "added lpoints" << endl;
536\#endif
537}
538
539button_setlocatepoint->activate();
540lpoints->value(0);
541this->setlocbuttonlabel(0);
542return numpoints;} {}
543 }
544 Function {init_vars()} {open return_type void
545 } {
546 code {\#if (HD24DEBUG == 1)
547cout << "init_vars" << endl;
548\#endif
549//jackclient=NULL;
550//jackmtsample=NULL;
551currsong=NULL;
552currproj=NULL;
553//portaudiostream=NULL;
554//inputParameters=new PaStreamParameters;
555//outputParameters=new PaStreamParameters;
556//portaudiooffset=0;
557//pa_streamtime=0;
558//portaudio_initialized=0;
559//portaudio_mustloop=0;
560//portaudio_looppos=0;
561mustdisplaytimer=true;
562mustdispsavemessage=false;
563closingdown=false;
564savemessage[0]='\\0';
565refreshingui=0;
566//loopmode=0;
567//dispwritecountdown=0;
568init_gui(0);
569Fl::add_timeout(TIMEOUT,poll_callback,this);} {}
570 }
571 Function {ui_refresh(const char* orig)} {open
572 } {
573 code {/* to prevent re-refresh by selecting current project
574 which will select a song which will refresh the current
575 ui again...(in case of corrupt 'unexpected end of song'
576 songs): */
577if (refreshingui>1) return;
578refreshingui++;
579
580// init dropdown lists.
581\#if (HD24DEBUG==1)
582cout << "==TRIGGER GUI REFRESH FROM "<<orig << "==" << endl;
583cout << "going to clear dropdown lists" << endl;
584\#endif
585for (unsigned int q=0;q<=99;q++) {
586 projectname->remove(0);
587 songname->remove(0);
588}
589int devid=0;
590if ((currenthd24!=NULL)&&(currenthd24!=defaulthd24))
591{
592 devid=currenthd24->getdeviceid();
593 if (devid<0)
594 {
595 devid=0;
596 }
597}
598\#if (HD24DEBUG==1)
599cout << "going to populate drive list (" << devid << ")" << endl;
600\#endif
601
602populate_drivelist(devid);
603
604// following uses fsys (the default drive)
605\#if (HD24DEBUG==1)
606cout << "get projcount then?" << endl;
607\#endif
608string* nump=Convert::int2str(currenthd24->projectcount());
609\#if (HD24DEBUG==1)
610cout << "got projcount=" << *nump << endl;
611\#endif
612number_of_projects->value(nump->c_str());
613delete (nump);
614\#if (HD24DEBUG==1)
615cout << "last project id=" << currenthd24->lastprojectid() << endl;
616\#endif
617
618populate_projectlist(currenthd24->lastprojectid());
619
620
621string* cat=new string("");
622if (hd24utils::gencatalog(this->currenthd24,cat)==0) {
623 this->catalogbuffer->remove(0,this->catalogbuffer->length()-1);
624 this->catalogbuffer->append(cat->c_str());
625
626// if (this->catalog->buffer()!=NULL) {
627// free(this->catalog->buffer());
628// }
629// this->catalog->buffer(cat->c_str());
630}
631delete(cat);
632\#if (HD24DEBUG==1)
633cout << "get version" << endl;
634\#endif
635string* version1=currenthd24->version();
636\#if (HD24DEBUG==1)
637cout << "got version" << endl;
638\#endif
639fsversion->value(version1->c_str());
640delete(version1);
641
642calcspace();
643Fl::add_timeout(TIMEOUT,poll_callback,this);
644
645refreshingui--;} {}
646 }
647 Function {init_gui(int drive)} {open return_type void
648 } {
649 code {// int drive is for multi drive support.
650
651// deselect all tracks on ' copy to hd24 tab'
652for (unsigned int i=1; i<=MAXCHANNELS; i++) {
653 trackselected[i-1]=0;
654}
655// Neither jack or portaudio were found by configure.
656// This means no sound is available, so hide the transport controls.
657recorder->control->disable();
658recorder->control->audio->mixer(this->mixer->control);
659
660\#if (HD24DEBUG==1)
661 cout << "init_gui" << endl;
662\#endif
663Fl::remove_timeout(poll_callback);
664ui_refresh("init gui");
665Fl::add_timeout(TIMEOUT,poll_callback,this);
666
667populate_formats();
668\#if (HD24DEBUG==1)
669 cout << "formats populated" << endl;
670\#endif
671fromtime->value("START");
672totime->value("END");
673refresh(fromtime);
674refresh(totime);
675\#if (HD24DEBUG==1)
676 cout << "init gui complete" << endl;
677\#endif
678
679calcspace();
680showprogtitle();
681
682
683setstatus("Ready.");} {}
684 }
685 Function {drivename_cb(Fl_Widget* w, void* data)} {return_type {static void}
686 } {
687 code {\#if (HD24DEBUG==1)
688 cout << "drivename_cb" << endl;
689\#endif
690HD24UserInterface *o=(HD24UserInterface *)data;
691o->drivename_callback(w,data);} {}
692 }
693 Function {drivename_callback(Fl_Widget* w, void* data)} {return_type void
694 } {
695 code {\#if (HD24DEBUG==1)
696 cout << "drivename_callback" << endl;
697\#endif
698int choicemade=((Fl_Choice*)(w))->value();
699\#if (HD24DEBUG==1)
700cout << "chose drive " << choicemade+1 << endl;
701\#endif
702
703
704string* idir=hd24utils::getlastdir("driveimagedir");
705hd24fs* newcurrenthd=new hd24fs(idir->c_str(),defaulthd24->mode(),choicemade);
706delete idir;
707currenthd24=newcurrenthd;
708
709init_gui(choicemade);} {}
710 }
711 Function {trackaction_callback(Fl_Widget* w, void* data)} {return_type void
712 } {
713 code {\#if (HD24DEBUG==1)
714 cout << "trackaction_callback" << endl;
715\#endif
716int choicemade=((Fl_Choice*)(w))->value();
717if (choicemade==0) {
718 ((Fl_Choice*)(w))->color(1);
719} else {
720 ((Fl_Choice*)(w))->color(7);
721}
722\#if (HD24DEBUG==1)
723cout << "chose item " << choicemade << endl;
724\#endif} {}
725 }
726 Function {projectname_cb(Fl_Widget* w, void* data)} {return_type {static void}
727 } {
728 code {\#if (HD24DEBUG==1)
729 cout << "projectname_cb" << endl;
730\#endif
731HD24UserInterface *o=(HD24UserInterface *)data;
732o->projectname_callback(w,data);} {}
733 }
734 Function {projectname_callback(Fl_Widget* w, void* data)} {return_type void
735 } {
736 code {\#if (HD24DEBUG==1)
737 cout << "projectname_callback" << endl;
738\#endif
739int choicemade=((Fl_Choice*)(w))->value();
740select_project(choicemade+1);} {}
741 }
742 Function {songname_cb(Fl_Widget* w, void* data)} {open return_type {static void}
743 } {
744 code {\#if (HD24DEBUG == 1 )
745 cout << "songname_cb" << endl;
746\#endif
747HD24UserInterface *o=(HD24UserInterface *)data;
748o->songname_callback(w,data);} {}
749 }
750 Function {songname_callback(Fl_Widget* w, void* data)} {open return_type void
751 } {
752 code {\#if (HD24DEBUG==1)
753 cout << "songname_callback" << endl;
754\#endif
755int choicemade=((Fl_Choice*)(w))->value();
756if (currproj!=NULL) delete currproj;
757currproj=currenthd24->getproject(projectname->value()+1);
758//songname->value(choicemade); // should not be needed
759select_song(choicemade); // song id=choicemade} {}
760 }
761 Function {refresh(Fl_Widget * w)} {open return_type void
762 } {
763 code {w->deactivate();
764w->activate();} {}
765 }
766 decl {time_t starttime,endtime} {}
767 Function {calcspace()} {return_type void
768 } {
769 code {__uint32 rate;
770__uint32 tracks;
771
772switch (atrate->value()) {
773 case 0: rate=44100; break;
774 case 1: rate=48000; break;
775 case 2: rate=88200; break;
776 case 3: rate=96000; break;
777 default: return;
778}
779switch (attracks->value()) {
780 case 0: tracks=2; break;
781 case 1: tracks=6; break;
782 case 2: tracks=8; break;
783 case 3: tracks=12; break;
784 case 4: tracks=16; break;
785 case 5: tracks=24; break;
786 default: return;
787}
788string* strfree=currenthd24->freespace(rate,tracks);
789freespace->value(strfree->c_str());
790delete (strfree);} {}
791 }
792 Function {transferstatus(void* ui,const char* message,double pct)} {open return_type {static void}
793 } {
794 code {if (ui==NULL) return;
795((HD24UserInterface*)ui)->statusmsg->value(message);
796((HD24UserInterface*)ui)->fl_check();} {}
797 }
798 Function {setstatus(string message)} {open return_type void
799 } {
800 code {statusmsg->value(message.c_str());
801fl_check();} {}
802 }
803 decl {/* ===File transfer stuff ===================================================== */} {}
804 decl {Fl_Widget* trackaction[24];} {public
805 }
806 decl {int transfer_cancel;} {public
807 }
808 decl {Fl_Output* filename[24];} {public
809 }
810 Function {savemessage_callback(void* user)} {open return_type {static void}
811 } {
812 code {HD24UserInterface* mythis=(HD24UserInterface*)user;
813string* stat=new string(mythis->savemessage);
814mythis->setstatus(*stat);
815//mythis->uicanvas->redraw();
816mythis->statusbar->damage();
817mythis->statusbar->redraw();
818
819delete (stat);
820if (mythis->mustdispsavemessage) {
821Fl::repeat_timeout(.25,savemessage_callback,user);
822}} {}
823 }
824 Function {countfiletracks(const char* filename)} {open return_type int
825 } {
826 code {SF_INFO sfinfo;
827SNDFILE* infile=NULL;
828if (strlen(filename)==0)
829{
830 return 0;
831}
832infile=soundfile->sf_open(filename,SFM_READ,&sfinfo);
833if (!infile)
834{
835 return 0;
836}
837int numchans=sfinfo.channels;
838soundfile->sf_close(infile);
839return numchans;} {}
840 }
841 decl {char savemessage[300];} {public
842 }
843 Function {populate_trackaction(HD24UserInterface* ui,Fl_Widget* o,int tracknum)} {open return_type void
844 } {
845 code {if (tracknum<1) {
846return;
847}
848if (tracknum>24) {
849 return;
850}
851
852trackaction[tracknum-1]=o;
853
854((Fl_Choice*)o)->clear();
855((Fl_Choice*)o)->add("Erase",0,(void (*)(Fl_Widget*,void*))(&(trackaction_cb)),(void*)this);
856((Fl_Choice*)o)->add("SMPTE",0,(void (*)(Fl_Widget*,void*))(&(trackaction_cb)),(void*)this);
857((Fl_Choice*)o)->add("Mono",0,(void (*)(Fl_Widget*,void*))(&(trackaction_cb)),(void*)this);
858// count number of tracks in file given by filename
859// when >1, for each track add a line.
860int numtracks=countfiletracks(filename[tracknum-1]->value());
861if (numtracks>1) {
862 for (int i=1; i<=numtracks; i++) {
863 string strtrack="Tr.";
864 string* strnum=Convert::int2str(i);
865 strtrack+=*strnum;
866 ((Fl_Choice*)o)->add(strtrack.c_str(),0,(void (*)(Fl_Widget*,void*))(&(trackaction_cb)),(void*)this);
867 delete strnum;
868 }
869}
870((Fl_Choice*)o)->value(2); // default 0=erase, 1=SMPTE, 2=mono
871((Fl_Choice*)o)->redraw();
872fl_check();} {}
873 }
874 Function {populate_trackactionbyfile(__uint32 slotnum,int trackchoice)} {open return_type void
875 } {
876 code {if (slotnum<0) return;
877if (slotnum>23) return;
878
879Fl_Choice* o=(Fl_Choice*)trackaction[slotnum];
880if (o==NULL) return;
881for (unsigned int i=0;i<128;i++) { o->remove(0); }
882o->add("Erase",0,(void (*)(Fl_Widget*,void*))(&(trackaction_cb)),(void*)this);
883o->add("SMPTE",0,(void (*)(Fl_Widget*,void*))(&(trackaction_cb)),(void*)this);
884o->add("Mono",0,(void (*)(Fl_Widget*,void*))(&(trackaction_cb)),(void*)this);
885// count number of tracks in file given by filename
886// when >1, for each track add a line.
887int numtracks=countfiletracks(filename[slotnum]->value());
888if (numtracks>1) {
889 for (int i=1; i<=numtracks; i++) {
890 string strtrack="Tr.";
891 string* strnum=Convert::int2str(i);
892 strtrack+=*strnum;
893 o->add(strtrack.c_str(),0,(void (*)(Fl_Widget*,void*))(&(trackaction_cb)),(void*)this);
894 delete strnum;
895 }
896}
897o->value(trackchoice);
898trackaction_callback(o,NULL);
899o->redraw();
900
901fl_check();} {}
902 }
903 Function {moveselected(__sint32 direction)} {open return_type void
904 } {
905 code {__uint32 firsttrack=0;
906__uint32 lasttrack=0;
907if (currsong==NULL)
908{
909 return;
910}
911if (direction==-1)
912{
913 firsttrack=1;
914 lasttrack=currsong->logical_channels();
915 if (trackselected[0]==1)
916 {
917 // move up, but first track is selected
918 // and already upper choice- cannot move up
919 return;
920 }
921}
922else
923{
924 if (direction==1)
925 {
926 lasttrack=1;
927 firsttrack=currsong->logical_channels();
928
929 if (trackselected[currsong->logical_channels()-1]==1)
930 {
931 return;
932 }
933 }
934}
935// we need to move stuff.
936if (firsttrack==0) return; // direction==0, don't move.
937
938__uint32 tracknum=firsttrack;
939while (tracknum!=lasttrack)
940{
941 if (trackselected[tracknum-1]!=trackselected[tracknum-1-direction])
942 {
943 int dummy=trackselected[tracknum-1];
944 string* trackval=new string(filename[tracknum-1]->value());
945
946 trackselected[tracknum-1]=trackselected[tracknum-1-direction];
947 trackselected[tracknum-1-direction]=dummy;
948
949 int a=((Fl_Choice*)(trackaction[tracknum-1]))->value();
950 int b=((Fl_Choice*)(trackaction[tracknum-1-direction]))->value();
951
952 filename[tracknum-1]->value(filename[tracknum-1-direction]->value());
953 filename[tracknum-1-direction]->value(trackval->c_str());
954
955 populate_trackactionbyfile(tracknum-1,b);
956 populate_trackactionbyfile(tracknum-1-direction,a);
957
958 delete trackval;
959 }
960 tracknum-=direction;
961}
962
963redrawtracks();} {}
964 }
965 Function {trackaction_cb(Fl_Widget* w, void* data)} {open return_type {static void}
966 } {
967 code {\#if (HD24DEBUG==1)
968 cout << "trackaction_cb" << endl;
969\#endif
970HD24UserInterface *o=(HD24UserInterface *)data;
971o->trackaction_callback(w,data);} {}
972 }
973 Function {redrawtracks()} {open return_type void
974 } {
975 code {bool track_active;
976if (currsong==NULL) {
977 return;
978}
979
980for (unsigned int tracknum=1;tracknum<=MAXCHANNELS;tracknum++)
981{
982 if (currsong->logical_channels()>=tracknum) {
983 track_active=true;
984 filename[tracknum-1]->activate();
985 } else {
986 track_active=false;
987 ((Fl_Output*)filename[tracknum-1])->color(7);
988 filename[tracknum-1]->deactivate();
989 }
990
991 if (track_active) {
992 if (trackselected[tracknum-1]==1) {
993 ((Fl_Output*)filename[tracknum-1])->color(3);
994 } else {
995 ((Fl_Output*)filename[tracknum-1])->color(7);
996 }
997 }
998
999 ((Fl_Output*)filename[tracknum-1])->redraw();
1000}} {}
1001 }
1002 decl {/* ===UI stuff ===================================================== */} {}
1003 Function {populate_formats()} {open return_type void
1004 } {
1005 code {\#if (HD24DEBUG==1)
1006 cout << "populate_formats" << endl;
1007\#endif
1008
1009for (int i=0;i<transeng->supportedformatcount();i++)
1010{
1011 fileformat->add(transeng->getformatdesc(i),0,NULL,(void*)this);
1012}
1013fileformat->value(0);} {}
1014 }
1015 Function {selectfilename(int tracknum)} {return_type void
1016 } {
1017 code {this->trackselected[tracknum-1]=1-this->trackselected[tracknum-1];
1018if (this->trackselected[tracknum-1]==1) {
1019 this->filename[tracknum-1]->color(3);
1020} else {
1021 this->filename[tracknum-1]->color(7);
1022}
1023this->filename[tracknum-1]->redraw();} {}
1024 }
1025 Function {select_project(int projectid)} {open return_type void
1026 } {
1027 code {if (currproj!=NULL) {
1028 if (currsong!=NULL)
1029 {
1030 hd24song* tmpsong=currsong;
1031 currsong=NULL;
1032 delete tmpsong;
1033 }
1034 hd24project* tmpproj=currproj;
1035 currproj=NULL;
1036 delete tmpproj;
1037}
1038currproj=currenthd24->getproject(projectid);
1039\#if (HD24DEBUG==1)
1040 cout << "select_project \#" << projectid << endl;
1041\#endif
1042currenthd24->lastprojectid(projectid);
1043projectname->value(projectid-1); /* project id is 1-based */
1044int currsongcount=0;
1045if (currproj==NULL)
1046{
1047 delete_project->deactivate();
1048}
1049else
1050{
1051 delete_project->activate();
1052 currsongcount=currproj->songcount();
1053}
1054
1055if (currsongcount==0)
1056{
1057 number_of_songs->value("0");
1058 populate_songlist(0); // shows -- EMPTY PROJECT --
1059 select_song(0);
1060 return;
1061}
1062
1063// currproj is defined at this point.
1064
1065string* nums=Convert::int2str(currproj->songcount());
1066number_of_songs->value(nums->c_str());
1067\#if (HD24DEBUG==1)
1068 cout << "number of songs=" << currproj->songcount() << endl;
1069\#endif
1070delete(nums);
1071
1072int lastsongid=currproj->lastsongid();
1073\#if (HD24DEBUG==1)
1074 cout << "lastsongid=" << lastsongid << endl;
1075\#endif
1076populate_songlist(lastsongid);} {}
1077 }
1078 Function {select_song(int songid)} {open return_type void
1079 } {
1080 code {unsigned int i;
1081button_setlocatepoint->deactivate();
1082\#if (HD24DEBUG==1)
1083cout << "select_song \#" << songid << endl;
1084\#endif
1085
1086
1087
1088if (songid==0) {
1089
1090 // This represents the choice "all songs"
1091 if (currsong!=NULL) {
1092 hd24song* tmpsong=currsong;
1093 currsong=NULL;
1094 delete tmpsong;
1095 }
1096 transfersource->value("(All songs in the current project)");
1097 if (number_of_tracks==NULL)
1098 {
1099 return; // ui not yet initialized?
1100 }
1101 tab_tohd24->deactivate();
1102 rename_song->deactivate();
1103 delete_song->deactivate();
1104 number_of_tracks->value("");
1105 number_of_tracks->deactivate();
1106 sample_rate->value("");
1107 sample_rate->deactivate();
1108 bitdepth->value("");
1109 bitdepth->deactivate();
1110 duration->value("");
1111 duration->deactivate();
1112 //refresh (songname);
1113 for (i=0; i<MAXCHANNELS;i++) {
1114 track[i]->deactivate();
1115 track[i]->value(1);
1116 track[i]->show();
1117 }
1118 button_setlocatepoint->deactivate();
1119 button_golocatepoint->deactivate();
1120 button_invert_tracks->deactivate();
1121 choice_startloc=0; // use default
1122 // disable locatepoint dropdown:
1123 choice_endloc=populate_locatepoints(currsong,locatepoints);
1124 choice_endloc=0;
1125 update_fromto();
1126 fromto->deactivate();
1127 refresh (tab_tohd24);
1128 return;
1129
1130} else {
1131\#if (HD24DEBUG==1)
1132cout << "activate buttons" << endl;
1133\#endif
1134 delete_song->activate();
1135 rename_song->activate();
1136 tab_tohd24->activate();
1137 button_golocatepoint->activate();
1138 button_setlocatepoint->activate();
1139 button_invert_tracks->activate();
1140 rename_song->activate();
1141 sample_rate->activate();
1142 bitdepth->activate();
1143 duration->activate();
1144 refresh (rename_song);
1145 refresh (number_of_tracks);
1146 refresh (sample_rate);
1147 refresh (bitdepth);
1148 refresh (duration);
1149 refresh (tab_tohd24);
1150\#if (HD24DEBUG==1)
1151cout << "deselect old song" << endl;
1152\#endif
1153 if (currsong!=NULL) {
1154 recorder->control->song(NULL); /* tell recorder that the song is gone */
1155 delete currsong;
1156 currsong=NULL;
1157 }
1158\#if (HD24DEBUG==1)
1159cout << "currprojgetsong" << endl;
1160\#endif
1161 currsong=currproj->getsong(songid);
1162 currproj->lastsongid(songid);
1163 if (currsong->has_unexpected_end()) {
1164 if (currsong->is_fixable_unexpected_end()) {
1165 song_messages->value("Unexpected end of song.\\nTrying to find the rest of the audio...");
1166// currenthd24->dumpclusterusage2(currenthd24->findorphanclusters());
1167 unsigned char* orphans=currenthd24->findorphanclusters();
1168 if (orphans != NULL) {
1169 currsong->appendorphanclusters(orphans,true /*allowsongresize*/);
1170 song_messages->value(
1171 "Unexpected end of song. I think I found back the rest of it.\\n"
1172 "However, you really should backup all audio and reformat this drive.");
1173 if (currenthd24->getmaintenancemode()==1) {
1174 if (confirm("Song was recovered. Do you wish to save the changes?\\nAnswer Yes only if you have verified that the audio is OK)")) {
1175 currsong->save();
1176 }
1177 }
1178 }
1179 }
1180 else
1181 {
1182 ui_refresh("selectsong");
1183 song_messages->value("Unexpected end of song.\\nHD24tools can not automatically fix this specific occurence.");
1184 }
1185 } else {
1186 song_messages->value("No messages.");
1187 }
1188}
1189
1190
1191\#if (HD24DEBUG==1)
1192cout << "songname->value" << endl;
1193\#endif
1194
1195songname->value(songid); // entry 0=all songs, 1=song id 1
1196string* dummy=currsong->songname();
1197transfersource->value(dummy->c_str());
1198
1199/* This should al be done by the recorder....
1200string disp="S";
1201string* idstr=Convert::int2str(songid,2,"0");
1202disp+=*idstr;
1203delete idstr;
1204disp+=":\\"";
1205string* dummy=currsong->songname();
1206transfersource->value(dummy->c_str());
1207string* dummy2=Convert::readstring((unsigned char*)dummy->c_str(),0,10);
1208string* dummy3=Convert::readstring((unsigned char*)dummy->c_str(),0,11);
1209
1210disp+=*dummy2;
1211delete dummy;
1212delete dummy2;
1213if (dummy3->length()>10)
1214{
1215disp+="\\4"; // arrow right
1216} else {
1217disp+="\\"";
1218}
1219delete dummy3;
1220string* disp2=Convert::padright(disp,16," ");
1221
1222string* dur=currsong->display_duration();
1223
1224*disp2+=dur->substr(0,8);
1225*disp2+=":";
1226*disp2+=dur->substr(9,2);
1227*disp2+=" ";
1228if (currsong->iswriteprotected())
1229{
1230*disp2+="\\1";
1231} else {
1232*disp2+="\\2";
1233}
1234string* strtracksb=Convert::int2str(currsong->logical_channels(),2,"0");
1235*disp2+=*strtracksb;
1236delete strtracksb;
1237*disp2+="t";
1238
1239recorder->control->dispwrite(0,disp2->c_str());
1240delete disp2;
1241 ............. until this point */
1242recorder->control->song(currsong); /* load song into recorder */
1243
1244redrawtracks(); // enable/disable tracks for export to HD24
1245string* strtracks=Convert::int2str(currsong->logical_channels());
1246number_of_tracks->value(strtracks->c_str());
1247number_of_tracks->activate();
1248delete (strtracks);
1249string* samrat=Convert::int2str(currsong->samplerate());
1250sample_rate->value(samrat->c_str());
1251sample_rate->activate();
1252delete samrat;
1253if (mixer!=NULL) {
1254 mixer->control->samplerate(this->samplerate());
1255}
1256
1257string* bitd=Convert::int2str(currsong->bitdepth());
1258bitdepth->value(bitd->c_str());
1259bitdepth->activate();
1260delete(bitd);
1261
1262string* dur=currsong->display_duration();
1263duration->value(dur->c_str());
1264duration->activate();
1265delete(dur);
1266
1267if (currsong->iswriteprotected()) {
1268 writeprotected->value(1);
1269} else {
1270 writeprotected->value(0);
1271}
1272
1273refresh (songname);
1274refresh (number_of_tracks);
1275refresh (sample_rate);
1276refresh (bitdepth);
1277refresh (duration);
1278refresh (writeprotected);// writeprotected->deactivate();
1279
1280for (i=0; i<currsong->logical_channels();i++) {
1281 track[i]->activate();
1282 track[i]->show();
1283 trackled[i]->show();
1284}
1285for (i=currsong->logical_channels();i<MAXCHANNELS;i++) {
1286 track[i]->deactivate();
1287 track[i]->hide();
1288 trackled[i]->hide();
1289}
1290
1291choice_startloc=0; // use default
1292choice_endloc=populate_locatepoints(currsong,locatepoints);
1293button_golocatepoint->activate();
1294if (choice_endloc>0) {
1295 fromto->activate();
1296}
1297update_fromto();} {}
1298 }
1299 decl {int choice_startloc;} {}
1300 decl {int choice_endloc;} {}
1301 decl {bool mustdispsavemessage;} {public
1302 }
1303 decl {int loopmode;} {public
1304 }
1305 decl {int uiredrawcount; /* to limit refreshing UI */} {public
1306 }
1307 Function {update_fromto()} {return_type void
1308 } {
1309 code {if (currsong==NULL)
1310{
1311fromtime->value("START");
1312totime->value("END");
1313return;
1314}
1315string* dummy1=currsong->getlocatename(choice_startloc);
1316string* dummy2=currsong->getlocatename(choice_endloc);
1317string* strfrom=Convert::trim(dummy1);
1318string* strto=Convert::trim(dummy2);
1319
1320
1321fromtime->value(strfrom->c_str());
1322totime->value(strto->c_str());
1323delete(dummy1);
1324delete(dummy2);
1325delete (strfrom);
1326delete (strto);} {}
1327 }
1328 Function {make_window(hd24fs* p_fsys) /* <------------------------------------------- */} {open
1329 } {
1330 Fl_Window {} {
1331 label HD24connect open
1332 xywh {485 44 605 530} type Double color 52 align 5
1333 code0 {defaulthd24=p_fsys;}
1334 code1 {currenthd24=p_fsys; // current and default to allow multi drive support}
1335 code2 {init_vars();} visible
1336 } {
1337 Fl_Group {} {open
1338 xywh {-5 0 1720 540}
1339 } {
1340 Fl_Group menucanvas {open
1341 xywh {0 0 640 24}
1342 } {
1343 Fl_Menu_Bar {} {open
1344 xywh {0 0 640 24} color 52
1345 } {
1346 Submenu menufile {
1347 label {&File} open
1348 xywh {0 0 100 20} labelsize 12
1349 } {
1350 MenuItem {} {
1351 label {&Detect HD24 drives}
1352 callback {if (currenthd24!=NULL) {
1353 delete currenthd24;
1354 currenthd24=NULL;
1355}
1356
1357string* idir=hd24utils::getlastdir("driveimagedir");
1358currenthd24=new hd24fs(idir->c_str(),hd24fs::MODE_RDWR);
1359delete idir;
1360defaulthd24=currenthd24;
1361if (!(currenthd24->isOpen()))
1362{
1363 fl_message("Sorry, during detection no valid HD24 drive was found connected to the system.\\nPlease switch on and connect the drive, or try another File menu option.");
1364}
1365ui_restart();}
1366 xywh {0 0 34 21} labelsize 12 divider
1367 }
1368 MenuItem {} {
1369 label {&Open drive image...}
1370 callback {string* driveimgdir=hd24utils::getlastdir("driveimagedir");
1371
1372Fl_Native_File_Chooser chooser;
1373chooser.directory(driveimgdir->c_str());
1374delete driveimgdir;
1375chooser.title("Select HD24 drive image\\0");
1376chooser.type(Fl_Native_File_Chooser::BROWSE_FILE);
1377chooser.filter("Drive Images\\t*.{img,bin,h24,hd24}\\0");
1378//chooser.preview(0);
1379switch (chooser.show()) {
1380 case -1: break; //error
1381 case 1: break; //cancel
1382 default:
1383 if (chooser.filename()) {
1384 string* cfilename=new string(chooser.filename());
1385
1386 //cout << "filename = " << *strfile << endl;
1387 string* fpath=new string("");
1388 *fpath+=cfilename->substr(0,strlen(cfilename->c_str())-strlen(fl_filename_name(cfilename->c_str())));
1389 hd24utils::setlastdir("driveimagedir",fpath->c_str());
1390
1391 hd24fs* sysob=new hd24fs(fpath->c_str(),hd24fs::MODE_RDWR,cfilename,false);
1392 delete cfilename;
1393 if (currenthd24!=NULL)
1394 {
1395 currenthd24->~hd24fs();
1396 }
1397 if (defaulthd24!=NULL)
1398 {
1399 if (defaulthd24!=currenthd24)
1400 {
1401 defaulthd24->~hd24fs();
1402 }
1403 }
1404 currenthd24=sysob;
1405 defaulthd24=sysob;
1406
1407 if (!(currenthd24->isOpen()))
1408 {
1409 bool choice=confirm(
1410 "File does not appear to be a valid HD24 device image.\\nDo you want to try using it anyway?\\nWarning: Choosing 'Yes' may result in\\ncrashes and other unpredictable behavior."
1411 );
1412
1413 if (choice) {
1414 if (sysob!=NULL) {
1415 delete (sysob);
1416 }
1417 bool wantheader=confirm("Do you want to load a header file?");
1418
1419 cfilename=new string(chooser.filename());
1420 string* idir=hd24utils::getlastdir("driveimagedir");
1421 sysob=new hd24fs(idir->c_str(),hd24fs::MODE_RDWR,cfilename,true); //force
1422 delete idir;
1423 delete cfilename;
1424 if (currenthd24!=NULL)
1425 {
1426 currenthd24->~hd24fs();
1427 }
1428 if (defaulthd24!=NULL)
1429 {
1430 if (defaulthd24!=currenthd24)
1431 {
1432 defaulthd24->~hd24fs();
1433 }
1434
1435 }
1436
1437 currenthd24=sysob;
1438 defaulthd24=sysob;
1439 if (currenthd24->isOpen()) {
1440 if (wantheader) {
1441 loadheaderfile();
1442 }
1443 ui_restart();
1444 return;
1445 }
1446 fl_message("Cannot open HD24 device image.");
1447 }
1448
1449 return;
1450 }
1451 ui_restart();
1452 }
1453 break;
1454}}
1455 xywh {0 0 34 21} labelsize 12
1456 }
1457 MenuItem {} {
1458 label {&Save drive image...}
1459 callback {string* driveimgdir=new string("");
1460*driveimgdir+=*hd24utils::getlastdir("driveimagedir");
1461
1462Fl_Native_File_Chooser chooser;
1463chooser.filter("Drive Images\\t*.{img,bin,h24,hd24}\\0");
1464chooser.title("Export full drive image file");
1465chooser.directory(driveimgdir->c_str());
1466chooser.options(Fl_Native_File_Chooser::NEW_FOLDER);
1467chooser.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
1468
1469switch (chooser.show()) {
1470 case -1: break; //error
1471 case 1: break; //cancel
1472 default:
1473 // save header to chooser.filename()
1474
1475 bool bFileexists=hd24utils::fileExists(chooser.filename());
1476 if (bFileexists) {
1477 bool choice=confirm(
1478 "A file with this name already exists. Do you wish to overwrite it?"
1479 );
1480 if (!(choice)) return;
1481 }
1482 string* strfile=new string(chooser.filename());
1483 //cout << "filename = " << *strfile << endl;
1484 string* fpath=new string("");
1485 *fpath+=strfile->substr(0,strlen(strfile->c_str())-strlen(fl_filename_name(strfile->c_str())));
1486 hd24utils::setlastdir("driveimagedir",fpath->c_str());
1487 this->transfer_cancel=0;
1488 this->mustdispsavemessage=true;
1489 Fl::add_timeout(.25,savemessage_callback,this);
1490 int result=hd24utils::savedriveimage(currenthd24,strfile,&this->savemessage[0],&this->transfer_cancel);
1491 delete strfile;
1492 if (result==0) {
1493 fl_message("Drive image created successfully.");
1494 setstatus("Done.");
1495 } else {
1496 fl_message("Could not write drive image to file. Access denied? Disk full?");
1497 }
1498 this->mustdispsavemessage=false;
1499 break;
1500}
1501delete driveimgdir;}
1502 xywh {10 10 34 21} labelsize 12
1503 }
1504 Submenu {} {
1505 label {&Catalog} open
1506 xywh {0 0 70 21} labelsize 12
1507 } {
1508 MenuItem {} {
1509 label {&Export catalog...}
1510 callback {string* catdir=new string("");
1511*catdir+=*hd24utils::getlastdir("catalogdir");
1512
1513Fl_Native_File_Chooser chooser;
1514chooser.filter("Text files\\t*.txt");
1515chooser.title("Export disk catalog to file");
1516chooser.directory(catdir->c_str());
1517chooser.options(Fl_Native_File_Chooser::NEW_FOLDER);
1518chooser.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
1519
1520switch (chooser.show()) {
1521 case -1: break; //error
1522 case 1: break; //cancel
1523 default:
1524 // save header to chooser.filename()
1525
1526 bool bFileexists=hd24utils::fileExists(chooser.filename());
1527 if (bFileexists) {
1528 bool choice=confirm(
1529 "A file with this name already exists. Do you wish to overwrite it?"
1530 );
1531 if (!(choice)) return;
1532 }
1533 string* strfile=new string(chooser.filename());
1534 //cout << "filename = " << *strfile << endl;
1535 string* fpath=new string("");
1536 *fpath+=strfile->substr(0,strlen(strfile->c_str())-strlen(fl_filename_name(strfile->c_str())));
1537 hd24utils::setlastdir("catalogdir",fpath->c_str());
1538 string* anyerrors=hd24utils::savecatalog(currenthd24,strfile);
1539 delete strfile;
1540 if (anyerrors==NULL) {
1541 fl_message("Catalog file created successfully.");
1542 } else {
1543 delete anyerrors;
1544 fl_message("Could not write catalog file. Access denied? Disk full?");
1545 }
1546 break;
1547}
1548delete catdir;}
1549 tooltip {Save the disk directory to a printable text file} xywh {40 40 34 21} labelsize 12
1550 }
1551 MenuItem {} {
1552 label {&Print catalog}
1553 callback {string* result=hd24utils::printcatalog(currenthd24);
1554if (result!=NULL)
1555{
1556 if (strlen(result->c_str())!=0)
1557 {
1558 fl_message("%s",result->c_str());
1559 }
1560}
1561delete result;}
1562 tooltip {Save the disk directory to a printable text file} xywh {30 30 34 21} labelsize 12 divider
1563 }
1564 }
1565 Submenu {} {
1566 label {&Mixer} open
1567 xywh {10 10 70 21} labelsize 12
1568 } {
1569 MenuItem {} {
1570 label {&Save mixer settings to file,,,}
1571 callback {mixer->savetofile();}
1572 tooltip {Save the current mixer settings to a file} xywh {50 50 34 21} labelsize 12
1573 }
1574 MenuItem {} {
1575 label {&Load mixer settings from file...}
1576 callback {mixer->loadfromfile();}
1577 tooltip {Recall mixer settings from a previously saved mix} xywh {60 60 34 21} labelsize 12 divider
1578 }
1579 MenuItem {} {
1580 label {&Save mixer settings to HD24 drive,,,}
1581 tooltip {Save the current mix onto the HD24 drive} xywh {60 60 34 21} labelsize 12 deactivate
1582 }
1583 MenuItem {} {
1584 label {&Load mixer settings from HD24 drive...}
1585 tooltip {Recall mixer settings from a mix previously saved to the current HD24 drive} xywh {70 70 34 21} labelsize 12 deactivate
1586 }
1587 }
1588 Submenu {} {
1589 label {&Recovery} open
1590 xywh {0 0 70 21} labelsize 12 divider
1591 } {
1592 MenuItem {} {
1593 label {&Select device...}
1594 callback {dialog_choosedevice* chooser=new dialog_choosedevice();
1595Fl_Double_Window* w=chooser->make_window(currenthd24);
1596w->end();
1597w->show();
1598while (w->visible()) {
1599Fl::wait();
1600}
1601string* cfilename;
1602hd24fs* sysob;
1603string* idir=NULL;
1604switch (chooser->buttonclicked) {
1605 case 1:
1606 // OK
1607 cfilename=new string(chooser->devicename->c_str());
1608 idir=hd24utils::getlastdir("driveimagedir");
1609 sysob=new hd24fs(idir->c_str(),hd24fs::MODE_RDWR,cfilename,false);
1610 delete idir; idir=NULL;
1611
1612 currenthd24=sysob;
1613 defaulthd24=sysob;
1614
1615 if (!(currenthd24->isOpen()))
1616 {
1617 bool choice=confirm(
1618 "Device does not appear to be a valid HD24 device.\\nDo you want to try using it anyway?\\nWarning: Choosing 'Yes' may result in\\ncrashes and other unpredictable behavior."
1619 );
1620
1621 if (choice) {
1622 if (sysob!=NULL) {
1623 delete (sysob);
1624 }
1625 string* idir=hd24utils::getlastdir("driveimagedir");
1626 sysob=new hd24fs(idir->c_str(),hd24fs::MODE_RDWR,cfilename,true); //force
1627 delete idir;
1628 currenthd24=sysob;
1629 defaulthd24=sysob;
1630 int tryheader=0;
1631 if (currenthd24->isOpen()) {
1632 tryheader=1;
1633 bool wantheader=confirm("Do you want to load a header file?");
1634 if (wantheader) {
1635 loadheaderfile();
1636 }
1637
1638 ui_restart();
1639 delete cfilename;
1640 return;
1641 }
1642 if (tryheader==1) {
1643 fl_message("Cannot open HD24 device.");
1644 } else {
1645 fl_message("Cannot open HD24 device. Access denied?");
1646 }
1647 }
1648 delete cfilename;
1649 break;
1650 }
1651 ui_restart();
1652 delete cfilename;
1653 break;
1654 case 2:
1655 // cancel
1656 break;
1657 default:
1658 // unknown
1659 break;
1660}
1661delete chooser;}
1662 xywh {5 5 34 21} labelsize 12
1663 }
1664 MenuItem {} {
1665 label {Load &header file...}
1666 callback {loadheaderfile();}
1667 xywh {5 5 34 21} labelsize 12
1668 }
1669 MenuItem {} {
1670 label {&Create header file...}
1671 callback {string* headerdir=new string("");
1672*headerdir+=*hd24utils::getlastdir("headerdir");
1673
1674Fl_Native_File_Chooser chooser;
1675chooser.filter("Header files (*.h24)\\t");
1676chooser.title("Create header file");
1677chooser.options(Fl_Native_File_Chooser::NEW_FOLDER);
1678chooser.directory(headerdir->c_str());
1679chooser.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
1680
1681switch (chooser.show()) {
1682 case -1: break; //error
1683 case 1: break; //cancel
1684 default:
1685 // save header to chooser.filename()
1686 bool bFileexists=hd24utils::fileExists(chooser.filename());
1687 if (bFileexists) {
1688 bool choice=confirm(
1689 "A file with this name already exists. Do you wish to overwrite it?"
1690 );
1691 if (!(choice)) return;
1692 }
1693 string* strfile=new string(chooser.filename());
1694 string* fpath=new string("");
1695 *fpath+=strfile->substr(0,strlen(strfile->c_str())-strlen(fl_filename_name(strfile->c_str())));
1696 hd24utils::setlastdir("headerdir",fpath->c_str());
1697
1698 int result=hd24utils::saveheader(currenthd24,strfile);
1699 delete strfile;
1700 if (result==0) {
1701 fl_message("Header file created successfully.");
1702 } else {
1703 fl_message("Could not write header file. Access denied? Disk full?");
1704 }
1705 break;
1706}}
1707 xywh {15 15 34 21} labelsize 12
1708 }
1709 MenuItem {} {
1710 label {Recover song from &power failure}
1711 callback {if (currsong==NULL) {
1712 fl_message("First select the song to recover.");
1713 return;
1714}
1715
1716dialog_setlength* ui_setlength;
1717ui_setlength=new dialog_setlength;
1718int currlocchoice=locatepoints->value();
1719Fl_Window *win=ui_setlength->make_window(currsong,currlocchoice);
1720win->end();
1721win->show();
1722
1723while (win->visible()) { Fl::wait(); }
1724
1725if (ui_setlength->buttonclicked==1) {
1726 // TODO:
1727 // - create header file
1728 // getuserdatapath.
1729 //
1730
1731 char userdatapath[FL_PATH_MAX];
1732 Fl_Preferences* prefs=new Fl_Preferences(Fl_Preferences::USER,"HD24","HD24connect");
1733 prefs->getUserdataPath(userdatapath,FL_PATH_MAX);
1734 delete prefs;
1735 string* headerfilename=new string(userdatapath);
1736
1737 // add OS directory slash if forgotten
1738\#ifdef WINDOWS
1739\#define OSSLASH '\\\\'
1740\#else
1741\#define OSSLASH '/'
1742\#endif
1743const char* x=headerfilename->c_str();
1744int q=strlen(x);
1745if (q>0)
1746{
1747 if (x[q-1]!=OSSLASH)
1748 {
1749 *headerfilename+=OSSLASH;
1750 }
1751}
1752*headerfilename+="livefix.h24";
1753
1754 int createtempheaderresult=hd24utils::savedrivesectors(currenthd24,headerfilename,0,0x10c76,NULL,NULL);
1755
1756 if (createtempheaderresult!=0)
1757 {
1758 delete headerfilename;
1759 fl_message("Couldn't create a temporary header file, cannot continue. Sorry.");
1760 return;
1761 }
1762 // header was created successfully.
1763 currenthd24->useheaderfile(*headerfilename);
1764 //cout << "Userdatapath="<<userdatapath << endl;
1765
1766 // - use header file
1767 // - this makes sure any writes go to header file
1768
1769 bool clearnew=false;
1770 currsong->songlength_in_samples(ui_setlength->locpoint,clearnew);
1771 currsong->save();
1772 ui_refresh("liverec");
1773}
1774delete ui_setlength;}
1775 xywh {10 10 36 21} labelsize 12
1776 }
1777 }
1778 MenuItem {} {
1779 label {E&xit}
1780 callback {/* Find current window */
1781this->finish();
1782
1783Fl_Window * x=Fl::first_window();
1784x->~Fl_Window();
1785delete x;
1786x=NULL;}
1787 xywh {0 0 100 20} labelsize 12
1788 }
1789 }
1790 Submenu menutools {
1791 label {&Tools} open
1792 xywh {10 10 100 20} labelsize 12
1793 } {
1794 Submenu {} {
1795 label {Alter &order of songs in project} open
1796 xywh {20 20 100 20} labelsize 12 divider
1797 } {
1798 MenuItem {} {
1799 label {Sort &Alphabetically}
1800 callback {if (this->currproj==NULL)
1801{
1802 fl_message("Cannot sort project- no project selected.");
1803 return;
1804}
1805this->currproj->sort();
1806this->currproj->save();
1807this->ui_refresh("sort");}
1808 xywh {30 30 34 21} labelsize 12
1809 }
1810 }
1811 MenuItem {} {
1812 label {&Options...}
1813 callback {dialog_options* ui_options;
1814ui_options=new dialog_options;
1815Fl_Window *win=ui_options->make_window();
1816win->end();
1817win->show();
1818
1819while (win->visible()) { Fl::wait(); }
1820
1821delete ui_options;}
1822 xywh {30 30 34 21} labelsize 12
1823 }
1824 }
1825 Submenu menuhelp {
1826 label {&Help} open
1827 xywh {0 0 100 20} labelsize 12
1828 } {
1829 MenuItem {} {
1830 label {&About}
1831 callback {UserInterface_HelpAbout* ui_help_about;
1832ui_help_about=new UserInterface_HelpAbout;
1833
1834Fl_Window *helpaboutdialog=ui_help_about->make_window();
1835helpaboutdialog->end();
1836helpaboutdialog->show();
1837
1838while (helpaboutdialog->visible()) { Fl::wait(); }}
1839 xywh {0 0 100 20} labelsize 12
1840 }
1841 MenuItem {} {
1842 label {System &Info}
1843 callback {string info="HD24connect system info\\n";
1844info+="JACK: ";
1845if (libjack->libloaded) {
1846 info+="Loaded";
1847} else {
1848 info+="Not present";
1849}
1850info+="\\n";
1851
1852info+="LIBSNDFILE: ";
1853if (soundfile->libloaded) {
1854 info+="Loaded";
1855} else {
1856 info+="Not present";
1857}
1858info+="\\n";
1859
1860
1861info+="PORTAUDIO: ";
1862if (portaudio->libloaded) {
1863 info+="Loaded";
1864} else {
1865 info+="Not present";
1866}
1867info+="\\n";
1868
1869
1870fl_message("%s",info.c_str());}
1871 xywh {20 20 100 20} labelsize 12
1872 }
1873 MenuItem {} {
1874 label {Report a &Bug}
1875 callback {string bug="No warranty of any kind is given on this program.\\n\\n";
1876bug+="However, if you find any defects or faults in it, they\\n";
1877bug+="will most likely be fixed with high priority in the next\\n";
1878bug+="release, as long as the author is aware of them.\\n\\n";
1879bug+="Should you find any defects, please email the author at\\n";
1880bug+="the following e-mail address:\\n\\n";
1881bug+="mrjb@@dnd.utwente.nl.\\n\\n";
1882bug+="Make sure to include 'hd24' in the subject line.";
1883fl_message("%s",bug.c_str());}
1884 xywh {0 0 100 20} labelsize 12
1885 }
1886 MenuItem {} {
1887 label {Request a &Feature}
1888 callback {string bug="If you would like a specific feature to be added, please\\n";
1889bug+="please email your request to the author at the following \\n";
1890bug+="e-mail address:\\n\\n";
1891bug+="mrjb@@dnd.utwente.nl.\\n\\n";
1892bug+="Make sure to include 'hd24 feature request' in the subject line.\\n";
1893bug+="You can increase the priority of the request by donating.";
1894fl_message("%s",bug.c_str());}
1895 xywh {10 10 100 20} labelsize 12
1896 }
1897 MenuItem {} {
1898 label {&Credits}
1899 callback {string thanks="Extra Special thanks go out to: \\n\\n";
1900thanks+="Randy Bryant for trusting me to use his Mac\\n";
1901thanks+="Mike Crute for hosting and builder support\\n";
1902thanks+="Cabbage for building various Mac package installers\\n";
1903thanks+="Edward van Westerlaak for Windows and Mac/OSX beta testing, hardware support and suggestions\\n";
1904thanks+="Erik de Castro Lopo and other contributors for libsndfile\\n";
1905thanks+="Ross Bencina, Phil Burk, Bjorn Roche and other contributors for the portaudio library\\n";
1906thanks+="Bill Spitzak and others for the Fast Light Toolkit\\n";
1907thanks+="Sveinn Kjartansson for providing the means for high sample rate support\\n\\n";
1908thanks+="Special thanks go out to the Yahoo Groups HD24 community\\n";
1909thanks+="for additional beta testing, suggestions and general encouragement.\\n\\n";
1910fl_message("%s",thanks.c_str());}
1911 xywh {10 10 100 20} labelsize 12
1912 }
1913 }
1914 }
1915 }
1916 Fl_Group uicanvas {open
1917 xywh {-5 0 1720 540} resizable
1918 } {
1919 Fl_Group transfercanvas {
1920 label Transfer
1921 xywh {10 360 590 150} box UP_BOX color 52 labelfont 1 labelsize 12 align 5
1922 } {}
1923 Fl_Group statusbar {
1924 xywh {-5 510 725 20} box DOWN_BOX color 23
1925 } {
1926 Fl_Output backgroundbox {
1927 xywh {0 510 605 20} color 52 labelsize 12 textsize 12
1928 }
1929 Fl_Button stop_transfer {
1930 label Cancel
1931 callback {transfer_cancel=1;
1932stop_transfer->hide();}
1933 xywh {525 510 80 20} labelsize 12 align 16
1934 code0 {o->hide();}
1935 }
1936 Fl_Output statusmsg {
1937 xywh {0 510 525 20} color 52 labelsize 12 textsize 12
1938 }
1939 }
1940 Fl_Tabs Tabs {
1941 callback {this->readmixer();
1942this->mixer->damage();
1943if (o->value()==tabRecorder)
1944{
1945 if (recorder->button_play->value()==0)
1946 {
1947 showprogtitle();
1948 }
1949}} open
1950 xywh {-5 25 1600 485}
1951 code0 {o->value(tabDrive);}
1952 } {
1953 Fl_Group tabDrive {
1954 label Drive open
1955 xywh {0 45 605 465} box UP_BOX color 52 labelfont 1 labelsize 12 align 5 hide
1956 } {
1957 Fl_Choice drivename {
1958 label {Drive name:}
1959 xywh {155 80 440 20} down_box BORDER_BOX labelsize 12 textsize 12
1960 } {}
1961 Fl_Output fsversion {
1962 label {FS version:}
1963 xywh {305 105 50 20} labelsize 12 textsize 12
1964 code0 {o->clear_visible_focus();}
1965 }
1966 Fl_Output number_of_projects {
1967 label {Number of projects:}
1968 xywh {155 105 70 20} labelsize 12 textsize 12
1969 code0 {o->clear_visible_focus();}
1970 }
1971 Fl_Button rename_drive {
1972 label {Rename...}
1973 callback {if (currenthd24==NULL) return;
1974dialog_rename* ui_rename;
1975ui_rename=new dialog_rename();
1976string* currname=currenthd24->volumename();
1977string* strname=new string("Rename project");
1978Fl_Window* win=ui_rename->make_window(currname,strname);
1979if (strname!=NULL)
1980{
1981 delete strname;
1982}
1983if (currname!=NULL)
1984{
1985 delete currname;
1986}
1987win->end();
1988win->show();
1989
1990while (win->visible()) { Fl::wait(); }
1991if (ui_rename->buttonclicked==1)
1992{
1993 // OK clicked
1994 if (confirm("Do you wish to write the changes to disk?")) {
1995 currenthd24->setvolumename(*(ui_rename->itemname));
1996 currenthd24->savedriveinfo();
1997 populate_drivelist(1+drivename->value());
1998 drivename->redraw();
1999 }
2000}
2001delete ui_rename;
2002ui_refresh("ren proj");}
2003 xywh {510 105 85 20} labelsize 12 align 16
2004 }
2005 Fl_Output freespace {
2006 label {Free space preview:}
2007 xywh {155 130 140 20} labelsize 12 textsize 12
2008 code0 {o->clear_visible_focus();}
2009 }
2010 Fl_Choice atrate {
2011 label {at }
2012 callback {calcspace();} open
2013 xywh {320 130 85 20} down_box BORDER_BOX labelsize 12 textsize 12
2014 code0 {o->value(0);}
2015 } {
2016 MenuItem {} {
2017 label 44100
2018 xywh {5 5 100 20} value 1 labelsize 12
2019 }
2020 MenuItem {} {
2021 label 48000
2022 xywh {15 15 100 20} value 1 labelsize 12
2023 }
2024 MenuItem {} {
2025 label 88200
2026 xywh {25 25 100 20} value 1 labelsize 12
2027 }
2028 MenuItem {} {
2029 label 96000
2030 xywh {35 35 100 20} value 1 labelsize 12
2031 }
2032 }
2033 Fl_Choice attracks {
2034 label {Hz, }
2035 callback {calcspace();} open
2036 xywh {435 130 75 20} down_box BORDER_BOX labelsize 12 textsize 12
2037 code0 {o->value(5);}
2038 } {
2039 MenuItem {} {
2040 label 2
2041 xywh {15 15 100 20} value 1 labelsize 12
2042 }
2043 MenuItem {} {
2044 label 6
2045 xywh {25 25 100 20} value 1 labelsize 12
2046 }
2047 MenuItem {} {
2048 label 8
2049 xywh {35 35 100 20} value 1 labelsize 12
2050 }
2051 MenuItem {} {
2052 label 12
2053 xywh {45 45 100 20} value 1 labelsize 12
2054 }
2055 MenuItem {} {
2056 label 16
2057 xywh {55 55 100 20} value 1 labelsize 12
2058 }
2059 MenuItem {} {
2060 label 24
2061 xywh {65 65 100 20} value 1 labelsize 12
2062 }
2063 }
2064 Fl_Box {} {
2065 label tracks
2066 xywh {510 130 55 20} labelsize 12 align 20
2067 }
2068 Fl_Group {} {open
2069 xywh {25 70 15 15}
2070 } {}
2071 Fl_Box {} {
2072 label {Drive information}
2073 xywh {0 58 5 17} labelfont 1 labelsize 12 align 8
2074 }
2075 Fl_Text_Display catalog {
2076 label {Drive contents}
2077 xywh {5 190 595 310} box DOWN_BOX labelfont 1 labelsize 12 align 5 textfont 4 textsize 12
2078 code0 {if (catalogbuffer==NULL) catalogbuffer=new Fl_Text_Buffer(); string* cat=new string("\\n"); catalogbuffer->append(cat->c_str()); delete cat;}
2079 code1 {o->buffer(catalogbuffer); o->scrollbar_align(FL_ALIGN_RIGHT);}
2080 }
2081 Fl_Button format_driveimage {
2082 label Format
2083 callback {bool wantformat=confirm("This will COMPLETELY ERASE\\nALL projects and songs on this drive.\\nAre you SURE you want to format the current drive?\\n");
2084if (!wantformat) return;
2085// Okay, user is absolutely sure.
2086currenthd24->write_enable();
2087currenthd24->quickformat(NULL);
2088// there's no point in re-enabling write
2089// protection again now, is there?
2090ui_refresh("format");
2091setstatus("Format complete.");
2092return;}
2093 xywh {455 105 55 20} labelsize 12 align 16
2094 }
2095 Fl_Button create_driveimage {
2096 label {New Image...}
2097 callback {dialog_filesize* ui_filesize;
2098ui_filesize=new dialog_filesize();
2099Fl_Window *win=ui_filesize->make_window();
2100win->end();
2101win->show();
2102
2103while (win->visible()) { Fl::wait(); }
2104__uint32 lastsector=0;
2105
2106if (ui_filesize->buttonclicked!=1)
2107{
2108 delete ui_filesize;
2109 return;
2110}
2111
2112lastsector=ui_filesize->lastsector;
2113delete ui_filesize;
2114
2115string* driveimgdir=new string("");
2116*driveimgdir+=*hd24utils::getlastdir("driveimagedir");
2117
2118Fl_Native_File_Chooser chooser;
2119chooser.filter("Drive Images\\t*.{img,bin,h24,hd24}\\0");
2120chooser.title("Create empty drive image in file");
2121chooser.directory(driveimgdir->c_str());
2122chooser.options(Fl_Native_File_Chooser::NEW_FOLDER);
2123chooser.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
2124
2125switch (chooser.show()) {
2126 case -1: break; //error
2127 case 1: break; //cancel
2128 default:
2129 // save header to chooser.filename()
2130
2131 bool bFileexists=hd24utils::fileExists(chooser.filename());
2132 if (bFileexists) {
2133 bool choice=confirm(
2134 "A file with this name already exists. Do you wish to overwrite it?"
2135 );
2136 if (!(choice)) return;
2137 }
2138 string* strfile=new string(chooser.filename());
2139 //cout << "filename = " << *strfile << endl;
2140 string* fpath=new string("");
2141 *fpath+=strfile->substr(0,strlen(strfile->c_str())-strlen(fl_filename_name(strfile->c_str())));
2142 hd24utils::setlastdir("driveimagedir",fpath->c_str());
2143 this->transfer_cancel=0;
2144 this->mustdispsavemessage=true;
2145 Fl::add_timeout(.25,savemessage_callback,this);
2146// __uint32 lastsector=2097151; // 1 GiB
2147 int result=hd24utils::newdriveimage(strfile,lastsector,&this->savemessage[0],&this->transfer_cancel);
2148
2149 this->mustdispsavemessage=false;
2150 setstatus("Done.");
2151 if (result==0) {
2152 setstatus("Done.");
2153 int wantopen=confirm("Drive image created successfully.\\nDo you want to open it now?");
2154 if (wantopen==1)
2155 {
2156 string* idir=hd24utils::getlastdir("driveimagedir");
2157 hd24fs* sysob=new hd24fs(idir->c_str(),hd24fs::MODE_RDWR,strfile,false);
2158 delete idir;
2159 if (currenthd24!=NULL)
2160 {
2161 currenthd24->~hd24fs();
2162 }
2163 if (defaulthd24!=NULL)
2164 {
2165 if (defaulthd24!=currenthd24)
2166 {
2167 defaulthd24->~hd24fs();
2168 }
2169
2170 }
2171 currenthd24=sysob;
2172 defaulthd24=sysob;
2173 }
2174
2175 } else {
2176 fl_message("Could not write drive image to file. Access denied? Disk full?");
2177 }
2178 delete strfile;
2179 break;
2180}
2181setstatus("Done.");
2182ui_refresh("newdriveimage");
2183delete driveimgdir;}
2184 xywh {360 105 95 20} labelsize 12 align 16
2185 }
2186 Fl_Box {} {
2187 label {Songs marked * are write-protected.}
2188 xywh {235 175 365 15} labelfont 2 labelsize 12 align 24
2189 }
2190 }
2191 Fl_Group songinfogroup {
2192 label {Project/Song}
2193 xywh {0 50 605 460} box UP_BOX color 52 labelfont 1 labelsize 12 align 5 hide
2194 } {
2195 Fl_Choice songname {
2196 label {Song name:} open
2197 xywh {155 155 440 20} down_box BORDER_BOX labelsize 12 textsize 12
2198 } {}
2199 Fl_Output number_of_tracks {
2200 label {Number of tracks:}
2201 xywh {155 180 90 20} labelsize 12 textsize 12
2202 code0 {o->clear_visible_focus();}
2203 }
2204 Fl_Output sample_rate {
2205 label {Sample rate:}
2206 callback {if (currsong==NULL) return;
2207bool confirmrate=false;
2208if (strcmp(o->value(),"44100")==0) {
2209 o->value("48000");
2210 currsong->samplerate(48000);
2211 if (mixer!=NULL) mixer->control->samplerate(48000);
2212 confirmrate=confirm("Re-stamp song as 48000Hz on disk?");
2213} else {
2214 if (strcmp(o->value(),"48000")==0) {
2215 o->value("44100");
2216 currsong->samplerate(44100);
2217 if (mixer!=NULL) mixer->control->samplerate(44100);
2218 confirmrate=confirm("Re-stamp song as 44100Hz on disk?");
2219 }
2220}
2221if (strcmp(o->value(),"88200")==0) {
2222 o->value("96000");
2223 currsong->samplerate(96000);
2224 if (mixer!=NULL) mixer->control->samplerate(48000);
2225 confirmrate=confirm("Re-stamp song as 96000Hz on disk?");
2226} else {
2227 if (strcmp(o->value(),"96000")==0) {
2228 o->value("88200");
2229 if (mixer!=NULL) mixer->control->samplerate(44100);
2230 confirmrate=confirm("Re-stamp song as 88200Hz on disk?");
2231 }
2232}
2233
2234 if (confirmrate) {
2235// currsong->songname(*(ui_rename->itemname));
2236 currsong->save();
2237 populate_songlist(songname->value());
2238 } else {
2239
2240
2241
2242if (strcmp(o->value(),"44100")==0) {
2243 o->value("48000");
2244 currsong->samplerate(48000);
2245 if (mixer!=NULL) mixer->control->samplerate(48000);
2246} else {
2247 if (strcmp(o->value(),"48000")==0) {
2248 o->value("44100");
2249 currsong->samplerate(44100);
2250 if (mixer!=NULL) mixer->control->samplerate(44100);
2251 }
2252}
2253if (strcmp(o->value(),"88200")==0) {
2254 o->value("96000");
2255 currsong->samplerate(96000);
2256 if (mixer!=NULL) mixer->control->samplerate(48000);
2257} else {
2258 if (strcmp(o->value(),"96000")==0) {
2259 o->value("88200");
2260 currsong->samplerate(88200);
2261 if (mixer!=NULL) mixer->control->samplerate(44100);
2262 }
2263}
2264
2265
2266 }
2267ui_refresh("stamprate");}
2268 xywh {155 230 90 20} labelsize 12 textsize 12
2269 code0 {o->clear_visible_focus();}
2270 }
2271 Fl_Output bitdepth {
2272 label {Bit depth:}
2273 xywh {155 255 90 20} labelsize 12 textsize 12
2274 code0 {o->clear_visible_focus();}
2275 }
2276 Fl_Output duration {
2277 label {Duration:}
2278 xywh {155 205 90 20} labelsize 12 textsize 12
2279 code0 {o->clear_visible_focus();}
2280 }
2281 Fl_Button rename_song {
2282 label {Rename...}
2283 callback {if (currsong==NULL) return;
2284dialog_rename* ui_rename;
2285ui_rename=new dialog_rename();
2286string* currname=currsong->songname();
2287string* strsong=new string("Rename song");
2288Fl_Window* win=ui_rename->make_window(currname,strsong);
2289delete strsong;
2290win->end();
2291win->show();
2292
2293while (win->visible()) { Fl::wait(); }
2294if (ui_rename->buttonclicked==1)
2295{
2296 // OK clicked
2297 if (confirm("Do you wish to write the changes to disk?")) {
2298 currsong->songname(*(ui_rename->itemname));
2299 currsong->save();
2300 populate_songlist(songname->value());
2301 }
2302}
2303
2304delete ui_rename;
2305ui_refresh("rename song");}
2306 xywh {510 180 85 20} labelsize 12 align 16
2307 }
2308 Fl_Choice locatepoints {
2309 label {Locate points:}
2310 callback {setlocbuttonlabel(locatepoints->value());
2311if ((locatepoints->value())==25) {
2312button_setlocatepoint->deactivate();
2313} else {
2314button_setlocatepoint->activate();
2315}} open
2316 xywh {155 280 215 20} down_box BORDER_BOX labelsize 12 textsize 12 deactivate
2317 } {}
2318 Fl_Button button_setlocatepoint {
2319 label {Edit...}
2320 callback {if (currsong==NULL) return;
2321dialog_setlocate* ui_setlocate;
2322ui_setlocate=new dialog_setlocate;
2323int currlocchoice=locatepoints->value();
2324Fl_Window *win=ui_setlocate->make_window(currsong,locatepoints->value());
2325win->end();
2326win->show();
2327
2328while (win->visible()) { Fl::wait(); }
2329
2330/* Dialog has closed, read the results */
2331
2332populate_locatepoints(currsong,locatepoints);
2333locatepoints->value(currlocchoice);
2334
2335if (ui_setlocate->useasrange==1) {
2336 if (currlocchoice==1)
2337 {
2338 choice_startloc=1;
2339 }
2340 if (currlocchoice==2)
2341 {
2342 choice_endloc=2;
2343 }
2344}
2345currsong->save();
2346
2347update_fromto();
2348delete ui_setlocate;}
2349 xywh {370 280 60 20} labelsize 12 align 16 deactivate
2350 }
2351 Fl_Check_Button writeprotected {
2352 label {Write protected}
2353 callback {if (currsong==NULL) return;
2354bool confirmprot=false;
2355if (o->value()==0) {
2356 currsong->setwriteprotected(false);
2357 confirmprot=confirm("Write-enable song on disk?");
2358} else {
2359 if (o->value()==1) {
2360 currsong->setwriteprotected(true);
2361 confirmprot=confirm("Write-protect song on disk?");
2362 }
2363}
2364
2365if (confirmprot) {
2366 currsong->save();
2367 populate_songlist(songname->value());
2368} else {
2369 if (o->value()==0) {
2370 o->value(1);
2371 } else {
2372 o->value(0);
2373 }
2374}
2375ui_refresh("writeprot");}
2376 xywh {155 300 20 25} down_box DOWN_BOX labelsize 12 align 8
2377 }
2378 Fl_Button button_golocatepoint {
2379 label Go
2380 callback {if (currsong==NULL) return;
2381if (recorder==NULL) return;
2382recorder->control->hd24_transport_goloc(currsong->getlocatepos(locatepoints->value()));}
2383 xywh {435 280 155 20} labelsize 12 align 16
2384 }
2385 Fl_Output number_of_songs {
2386 label {Number of songs:}
2387 xywh {155 105 85 20} labelsize 12 textsize 12
2388 code0 {o->clear_visible_focus();}
2389 }
2390 Fl_Choice projectname {
2391 label {Project name:} open
2392 xywh {155 80 440 20} down_box BORDER_BOX labelsize 12 textsize 12
2393 } {}
2394 Fl_Button rename_project {
2395 label {Rename...}
2396 callback {if (currproj==NULL) return;
2397dialog_rename* ui_rename;
2398ui_rename=new dialog_rename();
2399
2400string* currname=currproj->projectname();
2401string* strproject=new string("Rename project");
2402Fl_Window* win=ui_rename->make_window(currname,strproject);
2403if (strproject!=NULL)
2404{
2405 delete strproject;
2406}
2407win->end();
2408win->show();
2409
2410while (win->visible()) { Fl::wait(); }
2411if (ui_rename->buttonclicked==1)
2412{
2413 // OK clicked
2414 if (confirm("Do you wish to write the changes to disk?")) {
2415 currproj->projectname(*(ui_rename->itemname));
2416 currproj->save();
2417 populate_projectlist(1+projectname->value());
2418 }
2419
2420
2421
2422
2423}
2424delete ui_rename;
2425ui_refresh("ren proj 2");}
2426 xywh {510 105 85 20} labelsize 12 align 16
2427 }
2428 Fl_Box {} {
2429 label {Project information}
2430 xywh {0 58 5 17} labelfont 1 labelsize 12 align 8
2431 }
2432 Fl_Box {} {
2433 label {Song information}
2434 xywh {0 138 5 17} labelfont 1 labelsize 12 align 8
2435 }
2436 Fl_Output song_messages_label {
2437 label {Recovery messages:}
2438 xywh {155 325 10 20} type Multiline labelsize 12 textsize 12
2439 code0 {o->clear_visible_focus();}
2440 }
2441 Fl_Output song_messages {
2442 xywh {155 325 440 40} type Multiline labelsize 12 textsize 12
2443 code0 {o->clear_visible_focus();}
2444 }
2445 Fl_Button delete_project {
2446 label Delete
2447 callback {bool wantdel=confirm("Are you sure you want to delete this project, all songs in it and their recorded audio?\\nThis operation cannot be undone!");
2448if (!wantdel) return;
2449__sint32 projtodel=currproj->projectid();
2450__uint32 result=currenthd24->deleteproject(projtodel);
2451result++; result--; // ignore for now
2452ui_refresh("del proj");}
2453 xywh {455 105 55 20} labelsize 12 align 16
2454 }
2455 Fl_Button delete_song {
2456 label Delete
2457 callback {if (currproj==NULL) return;
2458if (currsong==NULL) return;
2459
2460bool wantdel=confirm("Are you sure you want to delete this song and its recorded audio?\\nThis operation cannot be undone!");
2461if (!wantdel) return;
2462__uint32 songtodel=currsong->songid();
2463__uint32 result=currproj->deletesong(songtodel);
2464result++; result--; //ignore for now
2465ui_refresh("del song");}
2466 xywh {455 180 55 20} labelsize 12 align 16
2467 }
2468 Fl_Button create_project {
2469 label {New Project...}
2470 callback {if (currenthd24==NULL) {
2471 fl_message("No drive is currently selected.");
2472 return;
2473}
2474
2475if (currenthd24->projectcount() == currenthd24->maxprojects())
2476{
2477 fl_message("Cannot create project.\\nThe maximum number of projects is already in use!");
2478 return;
2479}
2480// - check if current project is NULL
2481// - check if there's song space left in it
2482dialog_newproject* ui_newproject;
2483ui_newproject=new dialog_newproject();
2484Fl_Window *win=ui_newproject->make_window();
2485win->end();
2486win->show();
2487
2488while (win->visible()) { Fl::wait(); }
2489
2490if (ui_newproject->buttonclicked!=1)
2491{
2492 delete ui_newproject;
2493 return;
2494}
2495char projname[65];
2496for (int i=0;i<65;i++) {
2497 projname[i]=0;
2498}
2499hd24project* newproj=currenthd24->createproject(
2500(const char*)strncpy(projname,ui_newproject->projectname,64)
2501);
2502if (newproj==NULL)
2503{
2504 fl_message("Could not create the project. Access denied?");
2505 delete ui_newproject;
2506 return;
2507}
2508
2509//if (ui_newsong->buttonclicked==1) {
2510// lastsector=ui_filesize->lastsector;
2511//}
2512ui_refresh("createproj");
2513delete ui_newproject;}
2514 xywh {360 105 95 20} labelsize 12 align 16
2515 }
2516 Fl_Button create_song {
2517 label {New Song...}
2518 callback {if (currenthd24==NULL) {
2519 fl_message("No drive is currently selected.");
2520 return;
2521}
2522
2523if (currproj==NULL) {
2524 fl_message("No project is currently selected.");
2525 return;
2526}
2527
2528if (currproj->songcount() == currproj->maxsongs())
2529{
2530 fl_message("Cannot create song.\\nThe maximum number of songs is already in use!");
2531 return;
2532}
2533savemessage[0]='\\0';
2534transfer_cancel=0;
2535
2536this->mustdispsavemessage=true;
2537Fl::add_timeout(0,savemessage_callback,this);
2538
2539dialog_newsong* ui_newsong;
2540ui_newsong=new dialog_newsong();
2541Fl_Window *win=ui_newsong->make_window();
2542win->end();
2543win->show();
2544
2545
2546
2547while (win->visible()) { Fl::wait(); }
2548
2549
2550
2551//__uint32 lastsector=0;
2552
2553if (ui_newsong->buttonclicked!=1)
2554{
2555 mustdispsavemessage=false;
2556 transfer_cancel=1;
2557 delete ui_newsong;
2558 return;
2559}
2560
2561char songname[65];
2562for (int i=0;i<65;i++) {
2563 songname[i]=0;
2564}
2565hd24song* newsong=currproj->createsong(
2566(const char*)strncpy(songname,ui_newsong->songname,64),ui_newsong->trackcount,ui_newsong->samplerate
2567);
2568
2569
2570if (newsong==NULL)
2571{
2572 fl_message("Could not create the song. Access denied?");
2573 mustdispsavemessage=false;
2574 transfer_cancel=1;
2575 delete ui_newsong;
2576 return;
2577}
2578__uint32 samlen=ui_newsong->songlength_in_samples;
2579win->~Fl_Window();
2580delete ui_newsong;
2581// optionally, lengthen song to specified size.
2582if (samlen>0) {
2583 setstatus("Lengthening song... ");
2584
2585
2586\#if (HD24DEBUG==1)
2587 cout << "about to start lengthening song to maxlen=" << samlen << endl;
2588\#endif
2589 bool clearnew=true; // clear lengthened part
2590
2591 __uint32 translen=newsong->songlength_in_samples(samlen,clearnew,&this->savemessage[0],&this->transfer_cancel,Fl::check);
2592
2593
2594\#if (HD24DEBUG==1)
2595 cout << "verifying actual song length " << endl;
2596 cout << "new len=" << translen << endl;
2597\#endif
2598 if (translen!=samlen)
2599 {
2600\#if (HD24DEBUG==1)
2601
2602 cout << "new len<> maxlen so not enough space." << endl;
2603\#endif
2604 if (transfer_cancel==0)
2605 {
2606 fl_message("Not enough space on HD24 drive.");
2607 } else
2608 {
2609 fl_message("Song lengthening cancelled by user.");
2610 }
2611 return;
2612 }
2613 newsong->save();
2614
2615\#if (HD24DEBUG==1)
2616cout << "translen is now " << translen << endl;
2617\#endif
2618}
2619stop_transfer->hide();
2620this->mustdispsavemessage=false;
2621delete newsong; // ui refresh will pick it up as currsong.
2622ui_refresh("newsong");
2623setstatus("Ready.");
2624return;}
2625 xywh {360 180 95 20} labelsize 12 align 16
2626 }
2627 Fl_Box {} {
2628 label Hz
2629 xywh {245 230 19 20} labelsize 12 align 20
2630 }
2631 Fl_Box {} {
2632 label {hours:minutes:seconds.frames}
2633 xywh {245 205 195 20} labelsize 12 align 20
2634 }
2635 }
2636 Fl_Group tabRecorder {
2637 label Recorder open
2638 xywh {-5 46 620 464} color 52 labelfont 1 labelsize 12 hide
2639 } {
2640 Fl_Group recorder {open
2641 xywh {-5 49 610 457} color 53 selection_color 53 align 0
2642 code0 {o->set_ui(this);}
2643 code1 {o->control->audiolib(AUDIOLIB_PORTAUDIO,(void*)(this->portaudio));}
2644 code2 {o->control->audiolib(AUDIOLIB_JACK,(void*)(this->libjack));}
2645 code3 {o->control->audiolib(AUDIOLIB_SNDFILE,(void*)(this->soundfile));}
2646 class RecorderUI
2647 } {}
2648 }
2649 Fl_Group tabMixer {
2650 label Mixer open
2651 xywh {0 45 605 463} color 52 labelfont 1 labelsize 12 hide
2652 } {
2653 Fl_Group mixer {open
2654 xywh {0 49 605 456} color 53 selection_color 53 align 0
2655 code0 {o->set_ui(this);}
2656 class MixerUI
2657 } {}
2658 }
2659 Fl_Group tabCopyToPC {
2660 label {Copy to PC} open
2661 xywh {5 50 600 455} color 52 labelfont 1 labelsize 12 hide
2662 } {
2663 Fl_Check_Button {} {
2664 xywh {85 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2665 code0 {track[0]=o;}
2666 }
2667 Fl_Check_Button {} {
2668 xywh {105 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2669 code0 {track[1]=o;}
2670 }
2671 Fl_Check_Button {} {
2672 xywh {125 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2673 code0 {track[2]=o;}
2674 }
2675 Fl_Check_Button {} {
2676 xywh {145 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2677 code0 {track[3]=o;}
2678 }
2679 Fl_Check_Button {} {
2680 xywh {165 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2681 code0 {track[4]=o;}
2682 }
2683 Fl_Check_Button {} {
2684 xywh {185 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2685 code0 {track[5]=o;}
2686 }
2687 Fl_Check_Button {} {
2688 xywh {205 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2689 code0 {track[6]=o;}
2690 }
2691 Fl_Check_Button {} {
2692 xywh {225 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2693 code0 {track[7]=o;}
2694 }
2695 Fl_Check_Button {} {
2696 xywh {255 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2697 code0 {track[8]=o;}
2698 }
2699 Fl_Check_Button {} {
2700 xywh {275 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2701 code0 {track[9]=o;}
2702 }
2703 Fl_Check_Button {} {
2704 xywh {295 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2705 code0 {track[10]=o;}
2706 }
2707 Fl_Check_Button {} {
2708 xywh {315 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2709 code0 {track[11]=o;}
2710 }
2711 Fl_Check_Button {} {
2712 xywh {335 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2713 code0 {track[12]=o;}
2714 }
2715 Fl_Check_Button {} {
2716 xywh {355 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2717 code0 {track[13]=o;}
2718 }
2719 Fl_Check_Button {} {
2720 xywh {375 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2721 code0 {track[14]=o;}
2722 }
2723 Fl_Check_Button {} {
2724 xywh {395 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2725 code0 {track[15]=o;}
2726 }
2727 Fl_Check_Button {} {
2728 xywh {425 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2729 code0 {track[16]=o;}
2730 }
2731 Fl_Check_Button {} {
2732 xywh {445 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2733 code0 {track[17]=o;}
2734 }
2735 Fl_Check_Button {} {
2736 xywh {465 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2737 code0 {track[18]=o;}
2738 }
2739 Fl_Check_Button {} {
2740 xywh {485 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2741 code0 {track[19]=o;}
2742 }
2743 Fl_Check_Button {} {
2744 xywh {505 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2745 code0 {track[20]=o;}
2746 }
2747 Fl_Check_Button {} {
2748 xywh {525 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2749 code0 {track[21]=o;}
2750 }
2751 Fl_Check_Button {} {
2752 xywh {545 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2753 code0 {track[22]=o;}
2754 }
2755 Fl_Check_Button {} {
2756 xywh {565 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1
2757 code0 {track[23]=o;}
2758 }
2759 Fl_Box {} {
2760 label {Tracks:}
2761 xywh {15 79 70 16} box FLAT_BOX color 52 labelsize 12 align 20
2762 }
2763 Fl_Button button_invert_tracks {
2764 label Invert
2765 callback {int i;
2766for (i=0; i<MAXCHANNELS; i++) {
2767 track[i]->value(1-track[i]->value());
2768}}
2769 xywh {15 92 65 20} labelsize 12 align 16
2770 }
2771 Fl_Box led1 {
2772 label 01
2773 xywh {85 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2774 code0 {this->trackled[0]=o;}
2775 }
2776 Fl_Box led2 {
2777 label 02
2778 xywh {105 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2779 code0 {this->trackled[1]=o;}
2780 }
2781 Fl_Box led3 {
2782 label 03
2783 xywh {125 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2784 code0 {this->trackled[2]=o;}
2785 }
2786 Fl_Box led4 {
2787 label 04
2788 xywh {145 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2789 code0 {this->trackled[3]=o;}
2790 }
2791 Fl_Box led5 {
2792 label 05
2793 xywh {165 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2794 code0 {this->trackled[4]=o;}
2795 }
2796 Fl_Box led6 {
2797 label 06
2798 xywh {185 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2799 code0 {this->trackled[5]=o;}
2800 }
2801 Fl_Box led7 {
2802 label 07
2803 xywh {205 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2804 code0 {this->trackled[6]=o;}
2805 }
2806 Fl_Box led8 {
2807 label 08
2808 xywh {225 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2809 code0 {this->trackled[7]=o;}
2810 }
2811 Fl_Box led9 {
2812 label 09
2813 xywh {255 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2814 code0 {this->trackled[8]=o;}
2815 }
2816 Fl_Box led10 {
2817 label 10
2818 xywh {275 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2819 code0 {this->trackled[9]=o;}
2820 }
2821 Fl_Box led11 {
2822 label 11
2823 xywh {295 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2824 code0 {this->trackled[10]=o;}
2825 }
2826 Fl_Box led12 {
2827 label 12
2828 xywh {315 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2829 code0 {this->trackled[11]=o;}
2830 }
2831 Fl_Box led13 {
2832 label 13
2833 xywh {335 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2834 code0 {this->trackled[12]=o;}
2835 }
2836 Fl_Box led14 {
2837 label 14
2838 xywh {355 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2839 code0 {this->trackled[13]=o;}
2840 }
2841 Fl_Box led15 {
2842 label 15
2843 xywh {375 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2844 code0 {this->trackled[14]=o;}
2845 }
2846 Fl_Box led16 {
2847 label 16
2848 xywh {395 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2849 code0 {this->trackled[15]=o;}
2850 }
2851 Fl_Box led17 {
2852 label 17
2853 xywh {424 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2854 code0 {this->trackled[16]=o;}
2855 }
2856 Fl_Box led18 {
2857 label 18
2858 xywh {444 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2859 code0 {this->trackled[17]=o;}
2860 }
2861 Fl_Box led19 {
2862 label 19
2863 xywh {464 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2864 code0 {this->trackled[18]=o;}
2865 }
2866 Fl_Box led20 {
2867 label 20
2868 xywh {484 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2869 code0 {this->trackled[19]=o;}
2870 }
2871 Fl_Box led21 {
2872 label 21
2873 xywh {504 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2874 code0 {this->trackled[20]=o;}
2875 }
2876 Fl_Box led22 {
2877 label 22
2878 xywh {524 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2879 code0 {this->trackled[21]=o;}
2880 }
2881 Fl_Box led23 {
2882 label 23
2883 xywh {544 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2884 code0 {this->trackled[22]=o;}
2885 }
2886 Fl_Box led24 {
2887 label 24
2888 xywh {564 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12
2889 code0 {this->trackled[23]=o;}
2890 }
2891 Fl_Button button_transfertopc {
2892 label Transfer
2893 callback {recorder->control->button_stop_call();
2894mustdisplaytimer=false;
2895__sint64 bytestransferred=0;
2896transeng->sizelimit(strtoll(sizelimit->value(),0,10));
2897
2898int bytespersam;
2899int wantsplit=0;
2900__uint32 numsongs=1;
2901double dif;
2902__sint64 totbytestotransfer=0;
2903
2904bool needoverwrite=false;
2905bool isproblem=false;
2906__uint32 channelstotransfer=0;
2907
2908__uint32 i=0;
2909
2910transfer_cancel=0;
2911
2912if (currproj==NULL)
2913{
2914\#if (HD24DEBUG==1)
2915 cout << "No current project." << endl;
2916\#endif
2917 return;
2918}
2919
2920/* TODO: DISABLE/ENABLE JACK BEFORE/AFTER TRANSFER */
2921//jack_client_t* saveclient=jackclient;
2922//jackclient=NULL;
2923/* TODO: DISABLE/ENABLE JACK BEFORE/AFTER TRANSFER */
2924
2925if (!(hd24utils::dirExists(projectdir->value())))
2926{
2927 fl_message("Project directory no longer exists.\\nPlease select another directory and try again.");
2928 //jackclient=saveclient;
2929\#if (HD24DEBUG==1)
2930 cout << "project dir no longer exists, transfer cancelled." << endl;
2931\#endif
2932
2933 return;
2934}
2935transeng->setstatusfunction=HD24UserInterface::transferstatus;
2936transeng->projectdir(projectdir->value());
2937transeng->set_ui((void*)this);
2938transeng->mixer(this->mixer->control);
2939transeng->soundfile=soundfile;
2940bool channelwarning=false;
2941int currfileformat=0;
2942bool multisong=false;
2943if (currsong==NULL)
2944{
2945 multisong=true;
2946}
2947else
2948{
2949 // count channels to transfer
2950 __uint32 channels=currsong->logical_channels();
2951 for (unsigned int handle=0;handle<channels;handle++)
2952 {
2953 if (track[handle]->value()!=0)
2954 {
2955 channelstotransfer++;
2956 transeng->trackselected(handle,true);
2957 }
2958 else
2959 {
2960 transeng->trackselected(handle,false);
2961 }
2962 }
2963
2964 transeng->mixleft( (transfersource_mixleft->value())==1);
2965 transeng->mixright( (transfersource_mixright->value()) ==1);
2966
2967 currfileformat=fileformat->value();
2968
2969 transeng->selectedformat(currfileformat);
2970
2971 if (transeng->format_outputchannels(currfileformat)>1)
2972 {
2973 if ((channelstotransfer%(transeng->format_outputchannels(currfileformat)))!=0)
2974 {
2975 channelwarning=true;
2976 }
2977 }
2978
2979}
2980
2981if (multisong)
2982{
2983 numsongs=currproj->songcount();
2984}
2985if (channelwarning)
2986{
2987 string multiple="Number of channels to export must be a multiple of ";
2988 string* mynum=Convert::int2str(transeng->format_outputchannels(currfileformat));
2989 multiple+=*mynum;
2990 if (transeng->format_outputchannels(currfileformat)==2)
2991 {
2992 multiple+="\\nto export to stereo pairs.";
2993 } else {
2994 multiple+="\\nfor export to groups of ";
2995 multiple+=*mynum;
2996 multiple+=" channels.";
2997 }
2998 fl_message("%s",multiple.c_str());
2999 delete mynum;
3000/* TODO: DISABLE/ENABLE JACK BEFORE/AFTER TRANSFER */
3001// jackclient=saveclient;
3002
3003
3004 return;
3005
3006}
3007if (numsongs==0)
3008{
3009\#if (HD24DEBUG==1)
3010 cout << "multisong transfer: no songs in current project." << endl;
3011\#endif
3012 fl_message("Nothing to do!");
3013/* TODO: DISABLE/ENABLE JACK BEFORE/AFTER TRANSFER */
3014// jackclient=saveclient;
3015
3016 return;
3017}
3018int havedoublesongname=0;
3019if (multisong && (numsongs>1))
3020{
3021 // check if any song names are duplicated
3022 hd24song* s1=NULL;
3023 hd24song* s2=NULL;
3024 for (unsigned i=1; i<numsongs; i++)
3025 {
3026 if (s1!=NULL) {
3027 delete s1;
3028 s1=NULL;
3029 }
3030 s1=currproj->getsong(i);
3031 string* songname1=s1->songname();
3032 for (unsigned int j=i+1; j<=numsongs; j++) {
3033 if (s2!=NULL) {
3034 delete s2;
3035 s2=NULL;
3036 }
3037 s2=currproj->getsong(j);
3038 string* songname2=s2->songname();
3039 if (*songname1==*songname2) {
3040 havedoublesongname=1;
3041 }
3042 delete songname2;
3043 if (havedoublesongname==1) break;
3044 }
3045 delete songname1;
3046 if (havedoublesongname==1) break;
3047 }
3048 if (s1!=NULL) {
3049 delete s1;
3050 s1=NULL;
3051 }
3052 if (s2!=NULL) {
3053 delete s2;
3054 s2=NULL;
3055 }
3056}
3057if (havedoublesongname==1)
3058{
3059 if (!confirm(
3060 "Duplicate song names were detected. If you continue, \\n"
3061 "exported songs will be prefixed with the song number. \\n\\n"
3062 "If you prefer to name the songs before export, you will\\n"
3063 "want to stop now.\\n\\n"
3064 "Do you wish to continue?"
3065 )
3066 ) {
3067/* TODO: DISABLE/ENABLE JACK BEFORE/AFTER TRANSFER */
3068// jackclient=saveclient;
3069 return;
3070 };
3071}
3072// preparation for the transfers
3073for (i=1; i<=numsongs; i++)
3074{
3075 if (multisong)
3076 {
3077 if (currsong!=NULL) {
3078 delete currsong;
3079 currsong=NULL;
3080 }
3081 currsong=currproj->getsong(i);
3082 if (currsong!=NULL)
3083 {
3084 channelstotransfer=currsong->logical_channels();
3085 choice_startloc=0;
3086 choice_endloc=currsong->locatepointcount();
3087 }
3088 }
3089\#if (HD24DEBUG==1)
3090 cout << "channels to transfer=" << channelstotransfer << endl;
3091\#endif
3092 __uint64 bytestotransfer_perchannel=0;
3093 __uint64 bytestotransfer_thissong=0;
3094 transeng->sourcesong(currsong);
3095 if (currsong!=NULL)
3096 {
3097 bytespersam=(currsong->bitdepth())/8;
3098 // for kb/sec calculation
3099 // because of this, double at higher sample rates
3100
3101 __uint32 samstotrans_thissong;
3102 if (multisong)
3103 {
3104 samstotrans_thissong=currsong->songlength_in_samples();
3105 transeng->startoffset(0);
3106 transeng->endoffset(currsong->songlength_in_samples());
3107 }
3108 else
3109 {
3110 __uint32 startoffset=0;
3111 __uint32 endoffset=0;
3112
3113 if (choice_startloc!=0) {
3114 startoffset=currsong->getlocatepos(choice_startloc);
3115 }
3116 if (choice_endloc!=0)
3117 {
3118 endoffset=currsong->getlocatepos(choice_endloc);
3119 }
3120 transeng->startoffset(startoffset);
3121 transeng->endoffset(endoffset);
3122 if (endoffset>startoffset)
3123 {
3124 samstotrans_thissong=endoffset-startoffset;
3125 }
3126 else
3127 {
3128 samstotrans_thissong=startoffset-endoffset;
3129 }
3130 }
3131\#if (HD24DEBUG==1)
3132 cout << "sams to transfer for this song=" << samstotrans_thissong << endl ;
3133\#endif
3134 if (samstotrans_thissong==0xFFFFFFFF)
3135 {
3136 bool wanttransfer=confirm(
3137 "You are trying to transfer the maximum song size possible\\n"
3138 "(more than twenty hours or 300 Gigabytes of audio). \\n\\n"
3139 "HD24tools will gladly try to perform this transfer for you,\\n"
3140 "but it will take VERY LONG, and is probably not very helpful\\n"
3141 "to you.\\n\\n"
3142 "If you are currently trying to recover audio, you probably\\n"
3143 "forgot to set the export range (with the 'Range...' button\\n"
3144 "above). It is highly recommended to listen to your audio\\n"
3145 "and set two locate points before setting the export range.\\n\\n"
3146 "Do you want to perform this long and possibly useless\\n"
3147 "transfer anyway?");
3148 if (!(wanttransfer)) return;
3149 }
3150
3151 bytestotransfer_perchannel=(__sint64)((__sint64)samstotrans_thissong*(__sint64)bytespersam);
3152
3153 // hi-samplerate correction:
3154 bytestotransfer_perchannel*=(currsong->physical_channels()/currsong->logical_channels());
3155 bytestotransfer_thissong=(channelstotransfer*bytestotransfer_perchannel);
3156
3157 totbytestotransfer+=bytestotransfer_thissong;
3158
3159 if (!(needoverwrite))
3160 {
3161 needoverwrite=anyfilesexist(currsong);
3162 }
3163 }
3164
3165
3166 /* The above number equals 2 giga/4, to bypass format limitations.
3167 For 24-bit samples 2 giga/3 would suffice but some space could
3168 be needed by headers etc. */
3169 __uint64 MAXBYTES=transeng->sizelimit();
3170 // max number of samples per giga is half for high samplerate files
3171 if (multisong)
3172 {
3173 delete currsong;
3174 currsong=NULL;
3175 }
3176\#if (HD24DEBUG==1)
3177 cout << "Maxbytes per channel=" << MAXBYTES ;
3178 cout << "bytes per channel=" << bytestotransfer_perchannel << endl;
3179\#endif
3180 if (bytestotransfer_perchannel>MAXBYTES)
3181 {
3182 if (wantsplit!=1)
3183 {
3184/*
3185 int choice=fl_choice(
3186 "Exported audio files may be too large to play or edit. \\nDo you want to export the file as multiple smaller chunks?",
3187 "Yes","No","Cancel"
3188 );
3189 if (choice==2)
3190 {
3191\#if (HD24DEBUG==1)
3192 cout << "user cancelled too large file transfer" << endl;
3193\#endif
3194 //jackclient=saveclient;
3195 return; // cancelled
3196 }
3197 if (choice==0)
3198 {
3199 wantsplit=1;
3200 }
3201*/
3202 if (autosplit->value()==1) {
3203 wantsplit=1;
3204 }
3205 }
3206 }
3207}
3208if (multisong)
3209{
3210 if (currsong!=NULL) {
3211 delete currsong;
3212 currsong=NULL;
3213 }
3214}
3215
3216// do we need to overwrite any files? Are we allowed to?
3217if (needoverwrite)
3218{
3219 isproblem=(!(confirm("One or more output files already exist. Do you want to overwrite them?")));
3220}
3221
3222if (isproblem)
3223{
3224\#if (HD24DEBUG==1)
3225 cout << "user does not wish to perform needed overwrite." << endl;
3226\#endif
3227/* TODO: DISABLE/ENABLE JACK BEFORE/AFTER TRANSFER */
3228// jackclient=saveclient;
3229 return;
3230}
3231
3232// needed to check for dir to make sure about existence of output files
3233// but the previous question may have given the user the time to mess up.
3234// check the dir again :)
3235
3236if (!(hd24utils::dirExists(projectdir->value())))
3237{
3238 fl_message("Project directory no longer exists.\\nPlease select another directory and try again.");
3239/* TODO: DISABLE/ENABLE JACK BEFORE/AFTER TRANSFER */
3240// jackclient=saveclient;
3241\#if (HD24DEBUG==1)
3242 cout << "project directory deleted" << endl;
3243\#endif
3244 return;
3245}
3246\#if (HD24DEBUG==1)
3247 cout << "by calc, tot bytes to transfer=" << totbytestotransfer << endl;
3248\#endif
3249
3250deactivate_ui();
3251setstatus("Transferring audio to PC... 0%");
3252time (&starttime);
3253int somethingwrong=0;
3254for (i=1; i<=numsongs; i++)
3255{
3256\#if (HD24DEBUG==1)
3257 cout << "set song" << endl;
3258\#endif
3259 if (transfer_cancel!=0)
3260 {
3261\#if (HD24DEBUG==1)
3262 cout << "transfer cancelled by user." << endl;
3263\#endif
3264 break;
3265 }
3266
3267 if (multisong)
3268 {
3269 if (currsong!=NULL) {
3270 delete currsong;
3271 currsong=NULL;
3272 }
3273 currsong=currproj->getsong(i);
3274 }
3275 transeng->sourcesong(currsong);
3276 if (currsong==NULL)
3277 {
3278\#if (HD24DEBUG==1)
3279 cout << "currsong=null, nothing to transfer" << endl;
3280\#endif
3281 continue;
3282 }
3283\#if (HD24DEBUG==1)
3284 cout << "calling ftransfer with ";
3285 cout << "sonnum=" << i;
3286 cout << ", numsongs=" << numsongs;
3287 cout << ", totlen(bytes)=" << totbytestotransfer;
3288 cout << ", bytestransferred=" << bytestransferred;
3289 cout << ", wantsplit=" << wantsplit << endl;
3290\#endif
3291
3292 transeng->prepare_transfer_to_pc(i,numsongs,totbytestotransfer,bytestransferred,wantsplit,(havedoublesongname==1)?(i):(0));
3293 __sint64 currtransferred=transeng->transfer_to_pc();
3294 if (currtransferred==0)
3295 {
3296 somethingwrong=1;
3297 break;
3298 }
3299 bytestransferred+=currtransferred;
3300
3301 if (multisong)
3302 {
3303 delete currsong;
3304 currsong=NULL;
3305 }
3306
3307}
3308
3309
3310if (multisong)
3311{
3312 if (currsong!=NULL)
3313 {
3314 delete currsong;
3315 currsong=NULL;
3316 }
3317}
3318
3319/* TODO: DISABLE/ENABLE JACK BEFORE/AFTER TRANSFER */
3320//jackclient=saveclient;
3321if (somethingwrong==1)
3322{
3323 activate_ui();
3324 if (transeng->lasterror()!=NULL)
3325 {
3326
3327 setstatus(transeng->lasterror()->c_str());
3328 }
3329 else
3330 {
3331 setstatus((const char*)&"Unexpected error transferring files.");
3332 }
3333 stop_transfer->hide();
3334 return;
3335}
3336
3337time (&endtime);
3338dif=difftime(endtime,starttime);
3339//__uint32 subsecs=(__uint32)(100*(dif-floor(dif)));
3340dif=floor(dif);
3341__uint32 minutes=((__uint32)dif-((__uint32)dif%60))/60;
3342__uint32 seconds=((__uint32)dif%60);
3343
3344string minsec="Ready. Transfer time: ";
3345if (transfer_cancel==1)
3346{
3347 minsec="Transfer cancelled. Elapsed transfer time: ";
3348}
3349transfer_cancel=0;
3350string* strmins=Convert::int2str(minutes,2,"0");
3351minsec+=*strmins;
3352delete (strmins);
3353minsec+=":";
3354string* strsecs=Convert::int2str(seconds,2,"0");
3355minsec+=*strsecs;
3356delete(strsecs);
3357
3358if (dif>=1)
3359{
3360 __uint32 kbps=(__uint32)(((bytestransferred)/1024)/dif);
3361
3362 minsec+=" (";
3363 string* strkbps=Convert::int2str(kbps);
3364 minsec+=*strkbps;
3365 minsec+=" kB/sec)";
3366 delete(strkbps);
3367}
3368activate_ui();
3369setstatus(minsec.c_str());
3370stop_transfer->hide();}
3371 xywh {530 480 70 20} labelsize 12 align 16
3372 code0 {o->label("Transfer");}
3373 }
3374 Fl_Button {} {
3375 label {Browse...}
3376 callback {Fl_Native_File_Chooser chooser;
3377chooser.title("Select project directory");
3378chooser.type(Fl_Native_File_Chooser::BROWSE_DIRECTORY);
3379chooser.options(Fl_Native_File_Chooser::NEW_FOLDER);
3380chooser.filter("");
3381
3382string currdir="";
3383currdir+=projectdir->value();
3384
3385chooser.directory(currdir.c_str());
3386switch (chooser.show()) {
3387 case -1: break; //error
3388 case 1: break; //cancel
3389 default:
3390 if (chooser.filename()) {
3391 projectdir->value(chooser.filename());
3392 hd24utils::setlastdir("projdir",chooser.filename());
3393 }
3394
3395 break;
3396}}
3397 xywh {505 175 85 20} labelsize 12 align 16
3398 }
3399 Fl_Input projectdir {
3400 label {Project dir:}
3401 callback {/* callback when release: add a
3402 (back)slash to the end of the
3403 pathname if one is not present. */
3404
3405\#ifdef WINDOWS
3406\#define MYSLASH '\\\\'
3407\#else
3408\#define MYSLASH '/'
3409\#endif
3410char* x=(char*)projectdir->value();
3411if (strlen(x)==0) {
3412 x[0]=MYSLASH;
3413 x[1]=0;
3414} else {
3415 int q=strlen(x);
3416 if (x[q-1]!=MYSLASH) {
3417 x[q]=MYSLASH;
3418 x[q+1]=0;
3419 }
3420}
3421projectdir->value(x);
3422hd24utils::setlastdir("projdir",projectdir->value());}
3423 xywh {85 175 415 20} labelsize 12 textsize 12
3424 code0 {getlastprojdir(o);}
3425 code1 {/*o->clear_visible_focus();*/}
3426 }
3427 Fl_Output fromtime {
3428 label {From:}
3429 xywh {265 115 105 20} labelsize 12 textsize 12
3430 code0 {o->clear_visible_focus();}
3431 }
3432 Fl_Output totime {
3433 label {To:}
3434 xywh {395 115 105 20} labelsize 12 textsize 12
3435 code0 {o->clear_visible_focus();}
3436 }
3437 Fl_Button fromto {
3438 label {Range...}
3439 callback {if (currsong==NULL) return;
3440dialog_fromto* ui_fromto;
3441ui_fromto=new dialog_fromto;
3442
3443Fl_Window *win=ui_fromto->make_window(currsong);
3444populate_locatepoints(currsong,ui_fromto->fromloc);
3445populate_locatepoints(currsong,ui_fromto->toloc);
3446ui_fromto->fromloc->value(choice_startloc);
3447ui_fromto->toloc->value(choice_endloc);
3448win->end();
3449win->show();
3450
3451while (win->visible()) { Fl::wait(); }
3452
3453/* Dialog has closed, read the results */
3454//if (ui_fromto->buttonclicked==0)
3455//{ fl_message("No OK nor Cancel clicked"); }
3456if (ui_fromto->buttonclicked==1)
3457{
3458 // OK clicked
3459 choice_startloc=ui_fromto->choice_startloc;
3460 choice_endloc=ui_fromto->choice_endloc;
3461 update_fromto();
3462}
3463//if (ui_fromto->buttonclicked==2)
3464//{ fl_message("Cancel clicked"); }
3465delete ui_fromto;}
3466 xywh {505 115 85 20} labelsize 12 align 16
3467 }
3468 Fl_Choice fileformat {
3469 label {File format:} open
3470 xywh {85 200 160 20} down_box BORDER_BOX labelsize 12 textsize 12
3471 } {}
3472 Fl_Check_Button autosplit {
3473 label {Automatically limit size of exported files}
3474 callback {if (autosplit->value()==1) {
3475 sizelimitdropdown->activate();
3476
3477 if (sizelimitdropdown->value()==6) {
3478 sizelimit->activate();
3479 } else {
3480 sizelimit->deactivate();
3481 }
3482} else {
3483 sizelimitdropdown->deactivate();
3484 sizelimit->deactivate();
3485}}
3486 xywh {10 265 20 20} box FLAT_BOX down_box DOWN_BOX value 1 color 52 labelsize 12 align 8
3487 }
3488 Fl_Input sizelimit {
3489 label bytes
3490 xywh {425 290 120 20} labelsize 12 align 8 textsize 12
3491 code0 {long long x=1073741824LL; string* sval=Convert::int64tostr(x); o->value(sval->c_str()); delete sval; o->deactivate();}
3492 code1 {o->maximum_size(17);}
3493 }
3494 Fl_Box {} {
3495 label {Transfer target:}
3496 xywh {10 153 305 17} box FLAT_BOX color 52 labelfont 1 labelsize 12 align 20
3497 }
3498 Fl_Box {} {
3499 label {Transfer options:}
3500 xywh {10 243 305 17} box FLAT_BOX color 52 labelfont 1 labelsize 12 align 20
3501 }
3502 Fl_Box {} {
3503 label {Note: The actual file size will be a rough approximation of the requested split size.}
3504 xywh {30 318 550 17} box FLAT_BOX color 52 labelfont 2 labelsize 12 align 20
3505 }
3506 Fl_Check_Button customrate {
3507 label {Stamp files with a custom sample rate}
3508 callback {if (customrate->value()==1) {
3509 ratechoice->activate();
3510 if (ratechoice->value()==4) {
3511 stamprate->activate();
3512 } else {
3513 stamprate->deactivate();
3514 }
3515} else {
3516 ratechoice->deactivate();
3517 stamprate->deactivate();
3518}}
3519 xywh {10 345 20 20} box FLAT_BOX down_box DOWN_BOX color 52 labelsize 12 align 8
3520 }
3521 Fl_Choice ratechoice {
3522 label {Sample rate:} open
3523 xywh {105 370 295 20} down_box BORDER_BOX labelsize 12 textsize 12 deactivate
3524 code0 {o->value(1);}
3525 } {
3526 MenuItem {} {
3527 label {44100 Hz}
3528 callback {long long x=44100LL;
3529string* sval=Convert::int64tostr(x);
3530stamprate->value(sval->c_str());
3531delete sval;
3532stamprate->deactivate();}
3533 xywh {25 25 36 21} labelsize 12
3534 }
3535 MenuItem {} {
3536 label {48000 Hz}
3537 callback {long long x=48000LL;
3538string* sval=Convert::int64tostr(x);
3539stamprate->value(sval->c_str());
3540delete sval;
3541stamprate->deactivate();}
3542 xywh {35 35 36 21} labelsize 12
3543 }
3544 MenuItem {} {
3545 label {88200 Hz}
3546 callback {long long x=88200LL;
3547string* sval=Convert::int64tostr(x);
3548stamprate->value(sval->c_str());
3549delete sval;
3550stamprate->deactivate();}
3551 xywh {45 45 36 21} labelsize 12
3552 }
3553 MenuItem {} {
3554 label {96000 Hz}
3555 callback {long long x=96000LL;
3556string* sval=Convert::int64tostr(x);
3557stamprate->value(sval->c_str());
3558delete sval;
3559stamprate->deactivate();}
3560 xywh {55 55 36 21} labelsize 12
3561 }
3562 MenuItem {} {
3563 label {User defined, specify -->}
3564 callback {stamprate->activate();}
3565 xywh {85 85 36 21} labelsize 12
3566 }
3567 }
3568 Fl_Input stamprate {
3569 label Hz
3570 xywh {425 370 120 20} labelsize 12 align 8 textsize 12 deactivate
3571 code0 {long long x=48000; string* sval=Convert::int64tostr(x); o->value(sval->c_str()); delete sval; o->deactivate();}
3572 code1 {o->maximum_size(5);}
3573 }
3574 Fl_Choice sizelimitdropdown {
3575 label {Split every:} open
3576 tooltip 1 xywh {105 290 295 20} down_box BORDER_BOX labelsize 12 textsize 12
3577 code0 {o->value(2);}
3578 } {
3579 MenuItem {} {
3580 label {650 MB (74 minute CD)}
3581 callback {long long x=650000000LL;
3582string* sval=Convert::int64tostr(x);
3583sizelimit->value(sval->c_str());
3584delete sval;
3585sizelimit->deactivate();}
3586 xywh {20 20 36 21} labelsize 12
3587 }
3588 MenuItem {} {
3589 label {700 MB (80 minute CD)}
3590 callback {long long x=700000000LL;
3591string* sval=Convert::int64tostr(x);
3592sizelimit->value(sval->c_str());
3593delete sval;
3594sizelimit->deactivate();}
3595 xywh {30 30 36 21} labelsize 12
3596 }
3597 MenuItem {} {
3598 label {1 GiB (Recommended for wave editors)}
3599 callback {long long x=1073741824LL;
3600string* sval=Convert::int64tostr(x);
3601sizelimit->value(sval->c_str());
3602delete sval;
3603sizelimit->deactivate();}
3604 xywh {40 40 36 21} labelsize 12
3605 }
3606 MenuItem {} {
3607 label {2 GiB (Max. legal WAV size)}
3608 callback {long long x=2147483648LL;
3609string* sval=Convert::int64tostr(x);
3610sizelimit->value(sval->c_str());
3611delete sval;
3612sizelimit->deactivate();}
3613 xywh {50 50 36 21} labelsize 12
3614 }
3615 MenuItem {} {
3616 label {4 GiB (Max. 32-bit limit)}
3617 callback {long long x=4294967296LL;
3618string* sval=Convert::int64tostr(x);
3619sizelimit->value(sval->c_str());
3620delete sval;
3621sizelimit->deactivate();}
3622 xywh {60 60 36 21} labelsize 12
3623 }
3624 MenuItem {} {
3625 label {4.7 GB (DVD size)}
3626 callback {long long x=4700000000LL;
3627string* sval=Convert::int64tostr(x);
3628sizelimit->value(sval->c_str());
3629delete sval;
3630sizelimit->deactivate();}
3631 xywh {70 70 36 21} labelsize 12
3632 }
3633 MenuItem {} {
3634 label {User defined, specify -->}
3635 callback {sizelimit->activate();}
3636 xywh {80 80 36 21} labelsize 12
3637 }
3638 }
3639 Fl_Check_Button transfersource_mixleft {
3640 label {Mixer Left}
3641 callback {saverestoretrackselection(o);}
3642 xywh {85 115 20 20} down_box DOWN_BOX labelsize 12 align 4
3643 }
3644 Fl_Check_Button transfersource_mixright {
3645 label Right
3646 callback {saverestoretrackselection(o);}
3647 xywh {105 115 20 20} down_box DOWN_BOX labelsize 12 align 8
3648 }
3649 Fl_Group batch_stuff {
3650 label {batch stuff } open
3651 xywh {5 390 600 115} align 16 hide deactivate
3652 } {
3653 Fl_Box {} {
3654 label {Batch transfer list:}
3655 xywh {10 393 305 17} box FLAT_BOX color 52 labelfont 1 labelsize 12 align 20 deactivate
3656 }
3657 Fl_Output transfer_list {
3658 xywh {10 410 515 90} type Multiline labelsize 12 textsize 12 deactivate
3659 code0 {o->clear_visible_focus();}
3660 }
3661 Fl_Button button_addtobatch {
3662 label {To Batch}
3663 xywh {530 410 70 20} labelsize 12 align 16 deactivate
3664 }
3665 Fl_Button button_removefrombatch {
3666 label Remove
3667 xywh {530 430 70 20} labelsize 12 align 16 deactivate
3668 }
3669 }
3670 Fl_Output transfersource {
3671 label {Transfer source:}
3672 xywh {127 57 458 20} box NO_BOX labelfont 1 labelsize 12 textsize 12
3673 }
3674 Fl_Button {} {
3675 label {?}
3676 callback {fl_message("This option allows you to limit the size of exported files. \\n"
3677"In the dropdown box, the following units are used:\\n\\n"
3678"MB - Megabyte, 1000x1000 bytes\\n"
3679"GB - Gigabyte, 1000x1000x1000 bytes\\n"
3680"GiB - Binary Gigabyte or Gibibyte, 1024x1024x1024 bytes\\n\\n"
3681"In any situation, the actual byte count is displayed on the right.");}
3682 tooltip {Click here for an explanation about file splitting.} xywh {400 290 20 20} box FLAT_BOX down_box FLAT_BOX color 15 selection_color 15 labelfont 1 labelsize 11 labelcolor 7
3683 }
3684 Fl_Button {} {
3685 label {?}
3686 callback {fl_message("Stamping files with another sample rates allows you \\n"
3687"to export files with a sample rate that differs from the sample \\n"
3688"rate at which the song was recorded. When using this option, \\n"
3689"note that no resampling takes place; both the pitch and playback \\n"
3690"speed will change compared to the original sample rate. ");}
3691 tooltip {Click here for an explanation about sample rate stamping} xywh {400 370 20 20} box FLAT_BOX down_box FLAT_BOX color 15 selection_color 15 labelfont 1 labelsize 11 labelcolor 7
3692 }
3693 }
3694 Fl_Group tab_tohd24 {
3695 label {Copy to HD24} open
3696 xywh {0 45 605 461} color 52 labelfont 1 labelsize 12
3697 } {
3698 Fl_Button button_transfertohd24 {
3699 label Transfer
3700 callback {recorder->control->button_stop_call(); //stop transport
3701bool have_smpte=false;
3702if (currproj==NULL)
3703{
3704 fl_message("No project selected, nothing to do!\\nSelect a project on the Project/Song tab and try again.");
3705 return;
3706}
3707if (currsong==NULL)
3708{
3709 fl_message("No song selected, nothing to do!\\nSelect a song on the Project/Song tab and try again.");
3710 return;
3711}
3712
3713int havefiles=0;
3714for (unsigned int ch=1;ch<=currsong->logical_channels();ch++) {
3715
3716 if (strlen(filename[ch-1]->value())>0) {
3717 // track has a file selected
3718 havefiles=1;
3719 currsong->trackarmed(ch,true);
3720 continue;
3721 }
3722 int action=((Fl_Choice*)(trackaction[ch-1]))->value();
3723 if (action==0) { /* 0=ERASE */
3724 // track action says 'erase'
3725 havefiles=1;
3726 currsong->trackarmed(ch,true);
3727 continue;
3728 }
3729 if (action==1) { /* 1=SMPTE */
3730 // track action says 'stripe with SMPTE/LTC'
3731 havefiles=1;
3732 have_smpte=true;
3733 currsong->trackarmed(ch,true);
3734 continue;
3735 }
3736 // no file, no timecode stripe and no erase, keep track.
3737 currsong->trackarmed(ch,false);
3738
3739}
3740if (havefiles==0) {
3741 fl_message(
3742 "To transfer files to the HD24, load one or more files.\\n"
3743 "Each file will be assigned to an empty track slot.\\n\\n"
3744 "Before transferring, you will be able to rearrange the\\n"
3745 "order of the tracks by clicking on one or more tracks\\n"
3746 "and clicking the up or down arrow buttons.\\n\\n"
3747 "When a track slot is empty, the existing track will be\\n"
3748 "preserved, unless 'Erase' or 'SMPTE' is selected on \\n"
3749 "the right of the track.\\n\\n"
3750 "When a file to transfer contains multiple tracks, you\\n"
3751 "can choose to mixdown the file to mono (the default), \\n"
3752 "or you can select the track that you want to transfer \\n"
3753 "to the HD24 drive."
3754 );
3755 for (unsigned int ch=1;ch<=currsong->logical_channels();ch++) {
3756 currsong->trackarmed(ch,false);
3757 }
3758 return;
3759}
3760if (currsong->iswriteprotected())
3761{
3762 fl_message("The song is write protected.");
3763 for (unsigned int ch=1;ch<=currsong->logical_channels();ch++) {
3764 currsong->trackarmed(ch,false);
3765 }
3766 return;
3767}
3768// ask ARE YOU SURE????
3769bool sure=confirm("Are you sure you want to overwrite the existing audio?");
3770if (!sure) return;
3771
3772// check if all files still exist
3773
3774int filemissing=0;
3775for (unsigned int misscheck=1;misscheck<=currsong->logical_channels();misscheck++) {
3776 if (strlen(filename[misscheck-1]->value())==0) continue;
3777 if (!(hd24utils::fileExists(filename[misscheck-1]->value())))
3778 {
3779 filemissing=1;
3780 break;
3781 }
3782}
3783
3784if (filemissing==1) {
3785 fl_message("One or more files no longer exist. \\nPlease clear and reload the files, then try again.");
3786 return;
3787}
3788// end of checking if all files still exist
3789transeng->targetsong(currsong);
3790transeng->soundfile=soundfile;
3791for (unsigned int filenum=1;filenum<=currsong->logical_channels();filenum++)
3792{
3793 transeng->sourcefilename(filenum,filename[filenum-1]->value());
3794 transeng->trackaction(filenum,((Fl_Choice*)(trackaction[filenum-1]))->value());
3795}
3796transeng->transfer_to_hd24();
3797stop_transfer->hide();
3798if (transeng->lasterror()!=NULL)
3799{
3800 if (transeng->lasterror()->c_str()!=NULL)
3801 {
3802 setstatus(transeng->lasterror()->c_str());
3803 }
3804 else
3805 {
3806 setstatus("Done. No error messages.");
3807 }
3808} else {
3809 setstatus("Done.");
3810}
3811ui_refresh("tohd24_done");
3812activate_ui();
3813fl_check();} selected
3814 xywh {530 480 70 20} labelsize 12
3815 }
3816 Fl_Output filename1 {
3817 label {01 }
3818 callback {selectfilename(1);}
3819 xywh {40 50 430 19} labelfont 1 labelsize 12 textsize 12
3820 code0 {filename[0]=o;}
3821 }
3822 Fl_Output filename2 {
3823 label {02 }
3824 callback {selectfilename(2);}
3825 xywh {40 69 430 19} labelfont 1 labelsize 12 textsize 12
3826 code0 {filename[1]=o;}
3827 }
3828 Fl_Output filename3 {
3829 label {03 }
3830 callback {selectfilename(3);}
3831 xywh {40 88 430 19} labelfont 1 labelsize 12 textsize 12
3832 code0 {filename[2]=o;}
3833 }
3834 Fl_Output filename4 {
3835 label {04 }
3836 callback {selectfilename(4);}
3837 xywh {40 107 430 19} labelfont 1 labelsize 12 textsize 12
3838 code0 {filename[3]=o;}
3839 }
3840 Fl_Output filename5 {
3841 label {05 }
3842 callback {selectfilename(5);}
3843 xywh {40 126 430 19} labelfont 1 labelsize 12 textsize 12
3844 code0 {filename[4]=o;}
3845 }
3846 Fl_Output filename6 {
3847 label {06 }
3848 callback {selectfilename(6);}
3849 xywh {40 145 430 19} labelfont 1 labelsize 12 textsize 12
3850 code0 {filename[5]=o;}
3851 }
3852 Fl_Output filename7 {
3853 label {07 }
3854 callback {selectfilename(7);}
3855 xywh {40 164 430 19} labelfont 1 labelsize 12 textsize 12
3856 code0 {filename[6]=o;}
3857 }
3858 Fl_Output filename8 {
3859 label {08 }
3860 callback {selectfilename(8);}
3861 xywh {40 183 430 19} labelfont 1 labelsize 12 textsize 12
3862 code0 {filename[7]=o;}
3863 }
3864 Fl_Output filename9 {
3865 label {09 }
3866 callback {selectfilename(9);}
3867 xywh {40 202 430 19} labelfont 1 labelsize 12 textsize 12
3868 code0 {filename[8]=o;}
3869 }
3870 Fl_Output filename10 {
3871 label {10 }
3872 callback {selectfilename(10);}
3873 xywh {40 221 430 19} labelfont 1 labelsize 12 textsize 12
3874 code0 {filename[9]=o;}
3875 }
3876 Fl_Output filename11 {
3877 label {11 }
3878 callback {selectfilename(11);}
3879 xywh {40 240 430 19} labelfont 1 labelsize 12 textsize 12
3880 code0 {filename[10]=o;}
3881 }
3882 Fl_Output filename12 {
3883 label {12 }
3884 callback {selectfilename(12);}
3885 xywh {40 259 430 19} labelfont 1 labelsize 12 textsize 12
3886 code0 {filename[11]=o;}
3887 }
3888 Fl_Output filename13 {
3889 label {13 }
3890 callback {selectfilename(13);}
3891 xywh {40 278 430 19} labelfont 1 labelsize 12 textsize 12
3892 code0 {filename[12]=o;}
3893 }
3894 Fl_Output filename14 {
3895 label {14 }
3896 callback {selectfilename(14);}
3897 xywh {40 297 430 19} labelfont 1 labelsize 12 textsize 12
3898 code0 {filename[13]=o;}
3899 }
3900 Fl_Output filename15 {
3901 label {15 }
3902 callback {selectfilename(15);}
3903 xywh {40 316 430 19} labelfont 1 labelsize 12 textsize 12
3904 code0 {filename[14]=o;}
3905 }
3906 Fl_Output filename16 {
3907 label {16 }
3908 callback {selectfilename(16);}
3909 xywh {40 335 430 19} labelfont 1 labelsize 12 textsize 12
3910 code0 {filename[15]=o;}
3911 }
3912 Fl_Output filename17 {
3913 label {17 }
3914 callback {selectfilename(17);}
3915 xywh {40 354 430 19} labelfont 1 labelsize 12 textsize 12
3916 code0 {filename[16]=o;}
3917 }
3918 Fl_Output filename18 {
3919 label {18 }
3920 callback {selectfilename(18);}
3921 xywh {40 373 430 19} labelfont 1 labelsize 12 textsize 12
3922 code0 {filename[17]=o;}
3923 }
3924 Fl_Output filename19 {
3925 label {19 }
3926 callback {selectfilename(19);}
3927 xywh {40 392 430 19} labelfont 1 labelsize 12 textsize 12
3928 code0 {filename[18]=o;}
3929 }
3930 Fl_Output filename20 {
3931 label {20 }
3932 callback {selectfilename(20);}
3933 xywh {40 411 430 19} labelfont 1 labelsize 12 textsize 12
3934 code0 {filename[19]=o;}
3935 }
3936 Fl_Output filename21 {
3937 label {21 }
3938 callback {selectfilename(21);}
3939 xywh {40 430 430 19} labelfont 1 labelsize 12 textsize 12
3940 code0 {filename[20]=o;}
3941 }
3942 Fl_Output filename22 {
3943 label {22 }
3944 callback {selectfilename(22);}
3945 xywh {40 449 430 19} labelfont 1 labelsize 12 textsize 12
3946 code0 {filename[21]=o;}
3947 }
3948 Fl_Output filename23 {
3949 label {23 }
3950 callback {selectfilename(23);}
3951 xywh {40 468 430 19} labelfont 1 labelsize 12 textsize 12
3952 code0 {filename[22]=o;}
3953 }
3954 Fl_Output filename24 {
3955 label {24 }
3956 callback {selectfilename(24);}
3957 xywh {40 487 430 19} labelfont 1 labelsize 12 textsize 12
3958 code0 {filename[23]=o;}
3959 }
3960 Fl_Repeat_Button button_moveup {
3961 callback {moveselected(-1);}
3962 image {images/up.gif} xywh {530 255 70 20} labelsize 12 align 17
3963 }
3964 Fl_Repeat_Button button_movedown {
3965 callback {moveselected(1);}
3966 image {images/down.gif} xywh {530 275 70 20} labelsize 12
3967 }
3968 Fl_Button button_load {
3969 label {Load...}
3970 callback {if (currsong == NULL) {
3971 fl_message("No song selected.\\nSelect a song on the Project/Song tab and try again.");
3972 return;
3973 return;
3974}
3975string* audiofiledir=hd24utils::getlastdir("audiofiledir");
3976
3977Fl_Native_File_Chooser chooser;
3978chooser.directory(audiofiledir->c_str());
3979delete audiofiledir;
3980chooser.title("Select the files to transfer:\\0");
3981chooser.type(Fl_Native_File_Chooser::BROWSE_MULTI_FILE);
3982chooser.filter("Audio files\\t*.{wav,aif}\\0");
3983//chooser.preview(0);
3984int tosplitornottosplit=0;
3985
3986switch (chooser.show()) {
3987 case -1: break; //error
3988 case 1: break; //cancel
3989 default:
3990 if (chooser.filename()) {
3991 string* cfilename=new string(chooser.filename());
3992
3993 string* fpath=new string("");
3994 *fpath+=cfilename->substr(0,strlen(cfilename->c_str())-strlen(fl_filename_name(cfilename->c_str())));
3995 hd24utils::setlastdir("audiofiledir",fpath->c_str());
3996 delete cfilename;
3997 for (int n = 0; n < chooser.count(); n++ ) {
3998 string* cfilename=new string(chooser.filename(n));
3999 int currfiletracks=countfiletracks(cfilename->c_str());
4000 int totfiletracks=currfiletracks;
4001 int haveslot=0;
4002 while (currfiletracks>0) {
4003 if (totfiletracks>1) {
4004 if (tosplitornottosplit==0) {
4005 bool wantsplit=
4006 confirm("One or more selected files have more than 1 track. Do you wish to split them up?");
4007 if (!wantsplit) {
4008 tosplitornottosplit=1;
4009 } else {
4010 tosplitornottosplit=2;
4011 }
4012 }
4013 }
4014
4015 haveslot=0;
4016 for (unsigned int freeslot=0;freeslot<currsong->logical_channels();freeslot++) {
4017 if (strlen(filename[freeslot]->value())==0) {
4018 haveslot=1;
4019 filename[freeslot]->value(chooser.filename(n));
4020// cout << "Clear slot " << freeslot << endl;
4021 ((Fl_Choice*)(trackaction[freeslot]))->clear();
4022 if (tosplitornottosplit>1) {
4023 populate_trackactionbyfile(freeslot,3+(totfiletracks-currfiletracks));
4024 } else {
4025 populate_trackactionbyfile(freeslot,2);
4026 }
4027 break;
4028 }
4029 }
4030 if (haveslot==0) {
4031 break;
4032 }
4033 if (tosplitornottosplit==1) {
4034 currfiletracks=0;
4035 } else {
4036 currfiletracks--;
4037 }
4038 }
4039 delete cfilename;
4040 if (haveslot==0) {
4041 fl_message("One or more files could not be assigned to a track slot.\\n"
4042 "Please clear one or more track slots and try again.");
4043 break;
4044 }
4045 }
4046 }
4047}}
4048 xywh {530 50 70 20} labelsize 12
4049 }
4050 Fl_Button button_clear {
4051 label Clear
4052 callback {for (unsigned int i=0;i<MAXCHANNELS;i++) {
4053 if (trackselected[i]==1) {
4054 filename[i]->value("");
4055 trackselected[i]=0;
4056
4057 }
4058};
4059redrawtracks();}
4060 xywh {530 70 70 20} labelsize 12
4061 }
4062 Fl_Choice trackaction1 {open
4063 xywh {470 50 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4064 code0 {this->populate_trackaction(this,o,1);}
4065 } {}
4066 Fl_Choice trackaction2 {open
4067 xywh {470 69 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4068 code0 {this->populate_trackaction(this,o,2);}
4069 } {}
4070 Fl_Choice trackaction3 {open
4071 xywh {470 88 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4072 code0 {this->populate_trackaction(this,o,3);}
4073 } {}
4074 Fl_Choice trackaction4 {open
4075 xywh {470 107 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4076 code0 {this->populate_trackaction(this,o,4);}
4077 } {}
4078 Fl_Choice trackaction5 {open
4079 xywh {470 126 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4080 code0 {this->populate_trackaction(this,o,5);}
4081 } {}
4082 Fl_Choice trackaction6 {open
4083 xywh {470 145 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4084 code0 {this->populate_trackaction(this,o,6);}
4085 } {}
4086 Fl_Choice trackaction7 {open
4087 xywh {470 164 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4088 code0 {this->populate_trackaction(this,o,7);}
4089 } {}
4090 Fl_Choice trackaction8 {open
4091 xywh {470 183 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4092 code0 {this->populate_trackaction(this,o,8);}
4093 } {}
4094 Fl_Choice trackaction9 {open
4095 xywh {470 202 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4096 code0 {this->populate_trackaction(this,o,9);}
4097 } {}
4098 Fl_Choice trackaction10 {open
4099 xywh {470 221 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4100 code0 {this->populate_trackaction(this,o,10);}
4101 } {}
4102 Fl_Choice trackaction11 {open
4103 xywh {470 240 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4104 code0 {this->populate_trackaction(this,o,11);}
4105 } {}
4106 Fl_Choice trackaction12 {open
4107 xywh {470 259 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4108 code0 {this->populate_trackaction(this,o,12);}
4109 } {}
4110 Fl_Choice trackaction13 {open
4111 xywh {470 278 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4112 code0 {this->populate_trackaction(this,o,13);}
4113 } {}
4114 Fl_Choice trackaction14 {open
4115 xywh {470 297 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4116 code0 {this->populate_trackaction(this,o,14);}
4117 } {}
4118 Fl_Choice trackaction15 {open
4119 xywh {470 316 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4120 code0 {this->populate_trackaction(this,o,15);}
4121 } {}
4122 Fl_Choice trackaction16 {open
4123 xywh {470 335 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4124 code0 {this->populate_trackaction(this,o,16);}
4125 } {}
4126 Fl_Choice trackaction17 {open
4127 xywh {470 354 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4128 code0 {this->populate_trackaction(this,o,17);}
4129 } {}
4130 Fl_Choice trackaction18 {open
4131 xywh {470 373 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4132 code0 {this->populate_trackaction(this,o,18);}
4133 } {}
4134 Fl_Choice trackaction19 {open
4135 xywh {470 392 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4136 code0 {this->populate_trackaction(this,o,19);}
4137 } {}
4138 Fl_Choice trackaction20 {open
4139 xywh {470 411 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4140 code0 {this->populate_trackaction(this,o,20);}
4141 } {}
4142 Fl_Choice trackaction21 {open
4143 xywh {470 430 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4144 code0 {this->populate_trackaction(this,o,21);}
4145 } {}
4146 Fl_Choice trackaction22 {open
4147 xywh {470 449 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4148 code0 {this->populate_trackaction(this,o,22);}
4149 } {}
4150 Fl_Choice trackaction23 {open
4151 xywh {470 468 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4152 code0 {this->populate_trackaction(this,o,23);}
4153 } {}
4154 Fl_Choice trackaction24 {open
4155 xywh {470 487 55 19} down_box BORDER_BOX labelsize 11 textsize 11
4156 code0 {this->populate_trackaction(this,o,24);}
4157 } {}
4158 Fl_Button button_transfertohd24help {
4159 label Help
4160 callback {fl_message(
4161 "To transfer files to the HD24, load one or more files.\\n"
4162 "Each file will be assigned to an empty track slot.\\n\\n"
4163 "Before transferring, you will be able to rearrange the\\n"
4164 "order of the tracks by clicking on one or more tracks\\n"
4165 "and clicking the up or down arrow buttons.\\n\\n"
4166 "When a track slot is empty, the existing track will be\\n"
4167 "preserved, unless 'Erase' or 'SMPTE' is selected on \\n"
4168 "the right of the track.\\n\\n"
4169 "When a file to transfer contains multiple tracks, you\\n"
4170 "can choose to mixdown the file to mono (the default), \\n"
4171 "or you can select the track that you want to transfer \\n"
4172 "to the HD24 drive."
4173 );}
4174 xywh {530 455 70 20} labelsize 12
4175 }
4176 }
4177 }
4178 Fl_Group uicanvas_futureversions {open
4179 xywh {5 10 1710 530} hide resizable
4180 } {
4181 Fl_Tabs Future_Tabs {open
4182 xywh {10 35 1595 485}
4183 } {
4184 Fl_Group tab_wave {
4185 label Wave open
4186 xywh {15 60 595 455} color 52 labelfont 1 labelsize 12 deactivate
4187 code0 {o->hide();}
4188 } {
4189 Fl_Box {} {
4190 label {A future version of HD24connect may display a wave form here.
4191Initially, the purpose of this wave form would be to make it
4192easier to select an export range.}
4193 xywh {15 68 460 222} align 21
4194 }
4195 }
4196 Fl_Group tab_data {
4197 label Data open
4198 xywh {15 60 595 455} color 52 labelfont 1 labelsize 12 hide deactivate
4199 code0 {o->hide();}
4200 } {
4201 Fl_Box {} {
4202 label {A future version of HD24connect may display a list of data files here.
4203Specifically, this would be a list of files associated with the current
4204project and/or song. To make this possible, a single song on the
4205HD24 drive may be sacrificed as data area. This tab would then contain
4206functionality to import/export/list those files, as well as functionality to
4207create a data area on the drive.
4208Without data area on the HD24 drive itself, songs may still be given a
4209unique identifier to allow, for instance, automatically associating a mix
4210on the DAW computer with a song. }
4211 xywh {15 63 505 222} align 21
4212 }
4213 }
4214 }
4215 }
4216 }
4217 }
4218 }
4219 }
4220 Function {make_cli(hd24fs* p_fsys)} {return_type void
4221 } {
4222 code {// make_cli: stands for make commandline interface
4223// (intended to allow batch processing and regression testing)
4224// both current and default to allow multi drive support
4225defaulthd24=p_fsys;
4226currenthd24=p_fsys;} {}
4227 }
4228 decl {/* ===RECORDER UI stuff ===================================================== */} {}
4229 Function {readmixer()} {open return_type void
4230 } {
4231 code {// set solo status of channel to value
4232/*
4233for (unsigned int i=0;i<MAXCHANNELS;i++) {
4234 solobutton[i]->value(mixer->mixerchannel[i]->control->solo());
4235 solobutton[i]->redraw();
4236 mutebutton[i]->value(mixer->mixerchannel[i]->control->mute());
4237 mutebutton[i]->redraw();
4238}
4239*/} {}
4240 }
4241 decl {/* === UTILS ===================================================== */} {}
4242 Function {getlastprojdir(Fl_Input* o)} {return_type void
4243 } {
4244 code {string* projdir=hd24utils::getlastdir("projdir");
4245o->value(projdir->c_str());
4246delete projdir;} {}
4247 }
4248 Function {ui_restart()} {open
4249 } {
4250 code {//if (isportaudioinitialized()) {
4251// portaudio_transport_stop();
4252//}
4253if (recorder!=NULL) {
4254 if (recorder->control!=NULL) {
4255 recorder->control->button_stop_call();
4256 }
4257}
4258Fl::remove_timeout(poll_callback);
4259
4260recorder->~RecorderUI();
4261delete recorder;
4262
4263Fl_Window * winx=Fl::first_window();
4264if (currproj!=NULL)
4265{
4266 delete currproj;
4267 currproj=NULL;
4268}
4269
4270if (currsong!=NULL)
4271{
4272 delete currsong;
4273 currsong=NULL;
4274}
4275
4276Fl_Window * winy=make_window(currenthd24);
4277
4278winy->position(winx->x(),winx->y());
4279winy->end();
4280winy->show();
4281\#ifdef LINUX
4282XSetWMHints(fl_display, fl_xid(winy), XGetWMHints(fl_display, fl_xid(winx)));
4283\#endif
4284winx->~Fl_Window();
4285delete winx;
4286winx=NULL;
4287//if (jackmtsample!=NULL)
4288//{
4289// free(jackmtsample);
4290//}} {}
4291 }
4292 Function {loadheaderfile()} {} {
4293 code {Fl_Native_File_Chooser chooser;
4294chooser.title("Select header file\\0");
4295chooser.filter("Drive Images\\t*.{img,bin,h24,hd24}\\0");
4296chooser.type(Fl_Native_File_Chooser::BROWSE_FILE);
4297
4298string* headerdir=hd24utils::getlastdir("headerdir");
4299chooser.directory(headerdir->c_str());
4300delete headerdir;
4301switch (chooser.show()) {
4302 case -1: break; //error
4303 case 1: break; //cancel
4304 default:
4305 if (chooser.filename()) {
4306 if (!(currenthd24->useheaderfile (chooser.filename()))) {
4307 fl_message("Couldn't load headerfile. Possible causes: \\n- Most likely you haven't selected a device or drive image yet.\\n- Maybe you have no read access to the file.");
4308 return;
4309 }
4310 string* strfile=new string(chooser.filename());
4311 string* fpath=new string("");
4312 *fpath+=strfile->substr(0,strlen(strfile->c_str())-strlen(fl_filename_name(strfile->c_str())));
4313 hd24utils::setlastdir("headerdir",fpath->c_str());
4314 ui_restart();
4315 return;
4316 }
4317 break;
4318}} {}
4319 }
4320 Function {anyfilesexist(hd24song* thesong)} {return_type bool
4321 } {
4322 code {bool anyexist=false;
4323
4324struct stat fi;
4325__uint32 channels=thesong->logical_channels();
4326for (unsigned int q=0; q<100; q++)
4327{
4328 for (unsigned int handle=0;handle<channels;handle++)
4329 {
4330 if (track[handle]->value()==0) {
4331 // channel not selected for export
4332 continue;
4333 }
4334 string* fname=transeng->generate_filename(handle,0,q);
4335\#if (HD24DEBUG==1)
4336 cout << "check if file exists:" << *fname << endl;
4337\#endif
4338 if ((stat (fname->c_str(), &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0)) {
4339 anyexist=true;
4340\#if (HD24DEBUG==1)
4341 cout << "yes, exists" << *fname << endl;
4342\#endif
4343 delete fname;
4344 break;
4345 }
4346
4347 fname=transeng->generate_filename(handle,1,q);
4348\#if (HD24DEBUG==1)
4349 cout << "check if file exists:" << *fname << endl;
4350\#endif
4351 if ((stat (fname->c_str(), &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0)) {
4352 anyexist=true;
4353\#if (HD24DEBUG==1)
4354 cout << "yes, exists" << *fname << endl;
4355\#endif
4356 delete fname;
4357 break;
4358 }
4359\#if (HD24DEBUG==1)
4360 cout << "no, doesnt exist" << endl;
4361\#endif
4362
4363 delete fname;
4364 }
4365 if (anyexist==true) break;
4366}
4367return anyexist;} {}
4368 }
4369 Function {fl_check()} {open return_type void
4370 } {
4371 code {refresh(stop_transfer);
4372refresh(statusmsg);
4373Fl::check();} {}
4374 }
4375 decl {bool mustdisplaytimer;} {public
4376 }
4377 decl {bool polling;} {public
4378 }
4379 decl {Fl_Text_Buffer* catalogbuffer;} {public
4380 }
4381 Function {HD24UserInterface(int argc,char** argv,char* absprogpath)} {open
4382 } {
4383 code {control=new HD24control();
4384control->parentui(this);
4385control->ready(0);
4386/*currpeakmode=0;
4387for (unsigned int i=0;i<MAXCHANNELS;i++) { trackpeak[i]=0; } */
4388catalogbuffer=NULL;
4389portaudio=new PortAudioWrapper(absprogpath);
4390soundfile=new SoundFileWrapper(absprogpath);
4391libjack=new JackWrapper(absprogpath);
4392this->recorder=NULL; // will be initialized by make_window code
4393this->transeng=new hd24transferengine();} {}
4394 }
4395 Function {~HD24UserInterface()} {open
4396 } {
4397 code {if (control!=NULL) delete control;
4398if (portaudio!=NULL) delete portaudio;
4399if (soundfile!=NULL) delete soundfile;
4400if (libjack!=NULL) delete libjack;
4401if (currsong!=NULL) delete currsong;
4402if (currproj!=NULL) delete currproj;
4403if (currenthd24==defaulthd24)
4404{
4405 if (currenthd24!=NULL) delete currenthd24;
4406} else {
4407 if (currenthd24!=NULL) delete currenthd24;
4408 if (defaulthd24!=NULL) delete defaulthd24;
4409}
4410if (transeng!=NULL)
4411{
4412 delete transeng;
4413 transeng=NULL;
4414}} {}
4415 }
4416 Function {confirm(const char* question)} {open return_type bool
4417 } {
4418 code {int result=fl_choice("%s","No","Yes",NULL,question);
4419if (result==1) {
4420 return true;
4421}
4422return false;} {}
4423 }
4424 Function {samplerate()} {open return_type __uint32
4425 } {
4426 code {// returns current samplerate of the UI, used by mixer
4427if (currsong==NULL) return 44100;
4428return currsong->samplerate();} {}
4429 }
4430 decl {friend class ScrubWheel;} {}
4431 decl {int refreshingui;} {}
4432 Function {saverestoretrackselection(Fl_Check_Button* o)} {open return_type void
4433 } {
4434 code {int i;
4435if (o->value()==1)
4436{
4437 if (
4438 (transfersource_mixleft->value()
4439 +transfersource_mixright->value())
4440 ==1)
4441 {
4442 // save selected tracks
4443 // disable track selection
4444 // (repopulate formats list/file name/whatever?)
4445 for (i=0;i<MAXCHANNELS;i++)
4446 {
4447 tracksave[i]=track[i]->value();
4448 track[i]->value(1);
4449 track[i]->deactivate();
4450 button_invert_tracks->deactivate();
4451 }
4452 fileformat->deactivate();
4453 return;
4454 }
4455}
4456
4457if (o->value()==0)
4458{
4459 if (
4460 (transfersource_mixleft->value()
4461 +transfersource_mixright->value())
4462 ==0)
4463 {
4464 // restore tracks
4465 // enable track selection
4466 for (i=0;i<MAXCHANNELS;i++)
4467 {
4468 track[i]->value(tracksave[i]);
4469 track[i]->activate();
4470 button_invert_tracks->activate();
4471
4472 }
4473 fileformat->activate();
4474 }
4475}} {}
4476 }
4477 Function {showprogtitle()} {open return_type void
4478 } {
4479 code {recorder->control->dispwrite(0,"HD24connect "
4480 "HD24VERSION ",3000);} {}
4481 }
4482 decl {bool closingdown;} {public
4483 }
4484 Function {finish()} {open return_type void
4485 } {
4486 code {this->control->ready(0);
4487this->closingdown=true;
4488this->recorder->finish();} {}
4489 }
4490 Function {poll_callback(void* user)} {open return_type {static void}
4491 } {
4492 code {HD24UserInterface* mythis=(HD24UserInterface*)user;
4493//RecorderUI* mythis=(RecorderUI*)user;
4494\#if (HD24DEBUG==1)
4495 //cout << "poll_callback" << endl;
4496\#endif
4497if (mythis->control->ready()!=1) { return; }
4498
4499
4500if (mythis->busy!=1) {
4501 mythis->busy=1;
4502 hd24song* mycurrsong=mythis->currsong;
4503
4504 if (mythis->recorder->control->song()!=mythis->currsong)
4505 {
4506 mythis->recorder->control->song(mythis->currsong); /* tell recorder that the song is gone */
4507 }
4508
4509 if (mycurrsong!=NULL) {
4510 mycurrsong->bufferpoll();
4511 }
4512
4513
4514 mythis->uiredrawcount=(mythis->uiredrawcount+1)%UIREFRESH;
4515 if (mythis->uiredrawcount==0) {
4516
4517 for (unsigned int i=0;i<MAXCHANNELS;i++) {
4518// if (mythis->Tabs->value()==mythis->tabCopyToPC) {
4519// if (mythis->trackpeak[i]>.01) {
4520// if (mythis->trackpeak[i]>.9)
4521// {
4522// mythis->trackled[i]->color(1);
4523// mythis->trackled[i]->redraw();
4524// } else {
4525// if (mythis->trackpeak[i]>.7) {
4526// mythis->trackled[i]->color(3);
4527// mythis->trackled[i]->redraw();
4528// } else {
4529// mythis->trackled[i]->color(2);
4530// mythis->trackled[i]->redraw();
4531// }
4532// }
4533// } else {
4534// mythis->trackled[i]->color(52);
4535// mythis->trackled[i]->redraw();
4536// }
4537// }
4538 }
4539
4540 if (mythis->Tabs->value()==mythis->tabMixer) {
4541// mythis->mixer->redraw();
4542 mythis->mixer->control->updatemeters();
4543 }
4544 if (mythis->Tabs->value()==mythis->tabRecorder) {
4545// mythis->mixer->redraw();
4546// mythis->recorder->control->updatemeters();
4547 }
4548 // Fl check??
4549 }
4550}
4551if (mythis->recorder!=NULL) {
4552 RecorderUI::poll_callback(mythis->recorder);
4553}
4554mythis->busy=0;
4555Fl::add_timeout(TIMEOUT,poll_callback,user);} {}
4556 }
4557 decl {Fl_Box* trackled[24];} {public
4558 }
4559 Function {setlocbuttonlabel(int i)} {open return_type void
4560 } {
4561 code {hd24song* locsong=this->currsong;
4562int numpoints=0;
4563if (locsong!=NULL)
4564{
4565 numpoints=locsong->locatepointcount();
4566}
4567__uint32 locatepos=locsong->getlocatepos(i);
4568string* locname1=new string("");
4569 if (!(((i==0)||(i==numpoints)))) {
4570 *locname1+="+";
4571 string* dur=locsong->display_duration(locatepos);
4572 *locname1+=*dur;
4573 delete (dur);
4574 } else {
4575 if (i!=0)
4576 {
4577 *locname1+="+";
4578 string* dur=locsong->display_duration(locatepos);
4579 *locname1+=*dur;
4580 delete (dur);
4581 } else {
4582 *locname1+="START";
4583 }
4584 }
4585
4586 *locname1="Seek to "+*locname1;
4587 int l=strlen(locname1->c_str());
4588 for (i=0;i<l;i++) {
4589 locbuttonlabel[i]=locname1->c_str()[i];
4590 locbuttonlabel[i+1]=(char)0;
4591 }
4592
4593 button_golocatepoint->label(&(this->locbuttonlabel[0]));
4594 delete locname1;} {}
4595 }
4596 decl {char locbuttonlabel[64];} {}
4597}
diff --git a/src/frontend/ui_hd24connect.txt b/src/frontend/ui_hd24connect.txt
new file mode 100644
index 0000000..e25538a
--- /dev/null
+++ b/src/frontend/ui_hd24connect.txt
@@ -0,0 +1,387 @@
1# generated by Fast Light User Interface Designer (fluid) version 1.0107
21
3-60
4REC
5INP
6-48
7-36
8-24
9-15
10-9
11-6
12-3
13-1
14CLIP
15HD24connect
16&File
17&Detect HD24 drives
18&Open drive image...
19&Save drive image...
20&Export catalog...
21Save the disk directory to a printable text file
22&Print catalog
23Save the disk directory to a printable text file
24&Recovery
25&Select device...
26Load &header file...
27&Create header file...
28Recover song from &power failure
29E&xit
30&Help
31&About
32Report a &Bug...
33Request a &Feature...
34&Credits
35Transfer
36Cancel
37Drive
38Drive name:
39FS version:
40Number of projects:
41Rename...
42Free space preview:
43at
4444100
4548000
4688200
4796000
48Hz,
492
506
518
5212
5316
5424
55tracks
56Drive information
57Drive contents
58Project/Song
59Song name:
60Number of tracks:
61Sample rate:
62Bit depth:
63Duration:
64Rename...
65Locate points:
66Edit...
67Write protected
68Go
69Number of songs:
70Project name:
71Rename...
72Project information
73Song information
74Recorder
75Play
76Play
77Play
78Play
79Play
80arm
81arm
82Play
83Play
84Play
85Play
86Play
87Play
88Play
89Play
90Play
91Play
92Play
93Play
94Play
95Play
96Play
97Play
98SET LOC
99Set Locate
100AUTO LOOP
101Auto Loop
102Rewind
103F Fwd
104Stop
105Play
106LOOP START
107Loop Start
108LOOP END
109Loop End
110LOC 0
111Locate 0
112Record
113arm
114arm
115arm
116arm
117arm
118arm
119arm
120arm
121arm
122arm
123arm
124arm
125arm
126arm
127arm
128arm
129arm
130arm
131arm
132arm
133arm
134arm
135arm
136arm
137Arm tracks
138S
139Solo
140M
141Mute
142H
143M
144S
145F
146AUTO
147PLAY
148RTN
149REC
150REHEARSE
151PITCH
152REHEARSE
153Set Locate
154PUNCH IN
155Set Locate
156PUNCH OUT
157Set Locate
158Peak\012mode
159arm
160Peak\012clear
161arm
162Auto\012input
163arm
164All\012input
165arm
166Stereo input mapping
167Normal
168Swap Left and Right
169Mix to mono
170Use Left only
171Use Right only
172Mixer
173Solo
174Mute
175S
176Solo
177M
178Mute
179MONO
180MAIN
1811
1822
1833
1844
1855
1866
1877
1888
1899
19010
19111
19212
19313
19414
19515
19616
19717
19818
19919
20020
20121
20222
20323
20424
205Copy to PC
206Tracks:
207Invert
20801
20902
21003
21104
21205
21306
21407
21508
21609
21710
21811
21912
22013
22114
22215
22316
22417
22518
22619
22720
22821
22922
23023
23124
232Transfer
233Browse...
234Project dir:
235From:
236To:
237Range...
238Export file format:
239Automatically limit size of exported files
240When exporting multiple songs at once, prefix file names with song number
241only if multiple songs have the same song name
242Transfer source:
243Transfer target:
244Transfer options:
245bytes
246Note: The actual file size will be a rough approximation of the requested split size.
247Stamp files with a custom sample rate
248Sample rate:
24944100 Hz
25048000 Hz
25188200 Hz
25296000 Hz
253User defined, specify -->
254Hz
255Split every:
256650 MB (74 minute CD)
257700 MB (80 minute CD)
2581 GiB (Recommended for wave editors)
2592 GiB (Max. legal WAV size)
2604 GiB (Max. 32-bit limit)
2614.7 GB (DVD size)
262User defined, specify -->
263Copy to HD24
264Transfer
26501
26602
26703
26804
26905
27006
27107
27208
27309
27410
27511
27612
27713
27814
27915
28016
28117
28218
28319
28420
28521
28622
28723
28824
289Load...
290Clear
291font
292label
293label
294label
295label
296label
297label
298label
299label
300label
301label
302label
303label
304label
305label
306label
307label
308label
309label
310label
311label
312label
313label
314label
315label
316label
317label
318label
319label
320label
321label
322label
323label
324label
325label
326label
327label
328label
329label
330label
331label
332label
333label
334label
335label
336label
337label
338label
339label
340label
341label
342label
343label
344label
345label
346label
347label
348label
349label
350label
351label
352label
353label
354label
355label
356label
357label
358label
359label
360label
361label
362label
363label
364label
365label
366label
367label
368label
369label
370label
371label
372label
373label
374label
375label
376label
377label
378label
379label
380label
381label
382label
383label
384label
385label
386label
387label
diff --git a/src/frontend/ui_hd24trackchannel.fl b/src/frontend/ui_hd24trackchannel.fl
new file mode 100644
index 0000000..748313e
--- /dev/null
+++ b/src/frontend/ui_hd24trackchannel.fl
@@ -0,0 +1,322 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0107
3header_name {.h}
4code_name {.cxx}
5decl {\#include <config.h>} {public
6}
7
8decl {\#include <FL/FLTKstuff.H>} {public
9}
10
11decl {\#include <ui_hd24connect.h>} {public
12}
13
14class HD24TrackChannel {open : {public Fl_Group}
15} {
16 decl {\#define PEAKMODE_NOHOLD 0} {public
17 }
18 decl {\#define PEAKMODE_TEMPHOLD 1} {public
19 }
20 decl {\#define PEAKMODE_CONTHOLD 2} {public
21 }
22 decl {\#define PEAKMODE_MAXHOLD 33} {public
23 }
24 decl {int mode;} {}
25 decl {int maxledslit; /* for peak hold */} {public
26 }
27 decl {int holdtime;} {public
28 }
29 decl {RecorderUI* ui;} {selected
30 }
31 decl {Fl_Box* levelled[10];} {public
32 }
33 decl {Fl_Window* win;} {}
34 decl {unsigned int channel;} {}
35 Function {make_window()} {open
36 } {
37 Fl_Window ledchannel {open
38 xywh {20 74 20 120} type Double color 0 labelcolor 7
39 code0 {o->position(parent()->x(),parent()->y());}
40 class Fl_Group visible
41 } {
42 Fl_Box tracknum {
43 label 1
44 xywh {3 76 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 10 labelcolor 6 align 2
45 }
46 Fl_Box led1 {
47 xywh {3 76 12 6} box FLAT_BOX color 6 labelfont 1 labelsize 10 labelcolor 6 align 2 hide
48 code0 {levelled[0]=led1;}
49 }
50 Fl_Box recled {
51 xywh {3 96 12 6} box FLAT_BOX color 1 labelfont 1 labelsize 10 labelcolor 1 align 2 hide
52 }
53 Fl_Box inputled {
54 xywh {3 104 12 6} box FLAT_BOX color 6 labelfont 1 labelsize 10 labelcolor 6 align 2 hide
55 }
56 Fl_Box led2 {
57 xywh {3 68 12 6} box FLAT_BOX color 6 labelfont 1 labelsize 10 labelcolor 6 align 2 hide
58 code0 {levelled[1]=led2;}
59 }
60 Fl_Box led3 {
61 xywh {3 60 12 6} box FLAT_BOX color 6 labelfont 1 labelsize 10 labelcolor 6 align 2 hide
62 code0 {levelled[2]=led3;}
63 }
64 Fl_Box led4 {
65 xywh {3 52 12 6} box FLAT_BOX color 6 labelfont 1 labelsize 10 labelcolor 6 align 2 hide
66 code0 {levelled[3]=led4;}
67 }
68 Fl_Box led5 {
69 xywh {3 44 12 6} box FLAT_BOX color 6 labelfont 1 labelsize 10 labelcolor 6 align 2 hide
70 code0 {levelled[4]=led5;}
71 }
72 Fl_Box led6 {
73 xywh {3 36 12 6} box FLAT_BOX color 6 labelfont 1 labelsize 10 labelcolor 6 align 2 hide
74 code0 {levelled[5]=led6;}
75 }
76 Fl_Box led7 {
77 xywh {3 28 12 6} box FLAT_BOX color 93 labelfont 1 labelsize 10 labelcolor 93 align 2 hide
78 code0 {levelled[6]=led7;}
79 }
80 Fl_Box led8 {
81 xywh {3 20 12 6} box FLAT_BOX color 93 labelfont 1 labelsize 10 labelcolor 93 align 2 hide
82 code0 {levelled[7]=led8;}
83 }
84 Fl_Box led9 {
85 xywh {3 12 12 6} box FLAT_BOX color 93 labelfont 1 labelsize 10 labelcolor 93 align 2 hide
86 code0 {levelled[8]=led9;}
87 }
88 Fl_Box led10 {
89 xywh {3 4 12 6} box FLAT_BOX color 1 labelfont 1 labelsize 10 labelcolor 1 align 2 hide
90 code0 {levelled[9]=led10;}
91 }
92 }
93 }
94 Function {setval(float levelval)} {open
95 } {
96 code {int lednum=0;
97double myval=(double)levelval;
98
99// reset peaks if desired
100switch (mode) {
101 case PEAKMODE_NOHOLD: this->peakreset(); break;
102 case PEAKMODE_TEMPHOLD:
103 if (this->holdtime>PEAKMODE_MAXHOLD) {
104 peakreset();
105 } else {
106 this->holdtime++;
107 }
108 break;
109 case PEAKMODE_CONTHOLD:
110 break;
111 default:
112 this->mode=PEAKMODE_NOHOLD;
113 peakreset();
114 break;
115}
116
117int ledslit=0;
118
119if (myval>= ledlimit[lednum]) { ledslit=1; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); }
120if (myval>= ledlimit[lednum]) { ledslit=2; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); }
121if (myval>= ledlimit[lednum]) { ledslit=3; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); }
122if (myval>= ledlimit[lednum]) { ledslit=4; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); }
123if (myval>= ledlimit[lednum]) { ledslit=5; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); }
124if (myval>= ledlimit[lednum]) { ledslit=6; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); }
125if (myval>= ledlimit[lednum]) { ledslit=7; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); }
126if (myval>= ledlimit[lednum]) { ledslit=8; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); }
127if (myval>= ledlimit[lednum]) { ledslit=9; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); }
128if (myval>= ledlimit[lednum]) { ledslit=10; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); }
129
130if (ledslit >this->maxledslit ) {
131 this->maxledslit=ledslit;
132 this->holdtime=0;
133} else {
134 if ((this->maxledslit)>0) {
135 this->levelled[maxledslit-1]->show();
136 }
137}
138
139checkblink();} {}
140 }
141 Function {init_window()} {open return_type void
142 } {
143 code {this->mode=PEAKMODE_NOHOLD;
144this->win=(Fl_Window*)make_window();
145this->ui=NULL;
146this->channel=0;
147this->maxledslit=0;
148this->holdtime=0;
149this->ledlimit[0]=(double)pow(10,(double)((double)-30/(double)10)); // -30 dB
150this->ledlimit[1]=(double)pow(10,(double)((double)-24/(double)10)); // -24 dB
151this->ledlimit[2]=(double)pow(10,(double)((double)-18/(double)10));
152this->ledlimit[3]=(double)pow(10,(double)((double)-12/(double)10)); //...
153this->ledlimit[4]=(double)pow(10,(double)((double)-7.5/(double)10));
154this->ledlimit[5]=(double)pow(10,(double)((double)-4.5/(double)10));
155this->ledlimit[6]=(double)pow(10,(double)((double)-3/(double)10));
156this->ledlimit[7]=(double)pow(10,(double)((double)-1.5/(double)10));
157this->ledlimit[8]=(double)pow(10,(double)((double)-.5/(double)10));
158this->ledlimit[9]=(double)pow(10,(double)((double)0/(double)10)); // -0 dB
159
160this->setval(0);
161
162return;} {}
163 }
164 Function {HD24TrackChannel(int a,int b,int c,int d,const char* e):Fl_Group(a,b,c,d,e)} {open
165 } {
166 code {init_window();} {}
167 }
168 Function {HD24TrackChannel(int a,int b,int c,int d):Fl_Group(a,b,c,d,NULL)} {open
169 } {
170 code {init_window();} {}
171 }
172 Function {setchnum(__uint32 i)} {open
173 } {
174 code {/* As copy_label does not work on older versions of fltk,
175 the label now persists within the object but outside this
176 function. This solves the problem that is nowadays addressed
177 by copy_label, but without requiring an up-to-date version
178 of FLTK (1.1.6 or later). */
179channel=i;
180snprintf(&labeltext[0],8,"%ld",i);
181this->tracknum->label(labeltext);} {}
182 }
183 Function {setui(RecorderUI* p_ui)} {open
184 } {
185 code {this->ui=p_ui;} {}
186 }
187 Function {checkblink()} {open
188 } {
189 code {if (ui==NULL) return;
190/*
191TODO: Make available
192if (ui->currenthd24==NULL) return;
193*/
194if (channel==0) return;
195
196
197bool showinputled=false;
198/*
199if (ui->currenthd24->isallinput()) {
200 if (ui->control->song()==NULL) {
201 // no song, show all input leds
202 showinputled=true;
203 } else {
204 // song selected, only show as many
205 // input leds as channels in the song
206 if (channel<=ui->control->song()->logical_channels()) {
207 showinputled=ui->control->song()->istrackmonitoringinput(channel);
208 }
209 }
210} else {
211*/
212 if (ui->control->song()!=NULL) {
213 showinputled=ui->control->song()->istrackmonitoringinput(channel);
214 }
215/*
216}
217*/
218
219if (ui->control->song()!=NULL) {
220if (ui->control->song()->logical_channels()<channel) {
221 this->recled->hide();
222} else {
223 if (ui->control->song()->trackarmed(channel)) {
224 if (ui->blinkcounter<8) {
225 this->recled->hide();
226 } else {
227 this->recled->show();
228 }
229 } else {
230 this->recled->hide();
231 }
232}
233}
234if (showinputled) {
235 this->inputled->show();
236} else {
237 this->inputled->hide();
238}
239
240return;} {}
241 }
242 decl {double ledlimit[10];} {}
243 Function {peakreset()} {return_type void
244 } {
245 code {maxledslit=0;
246holdtime=0;} {}
247 }
248 Function {peakmode(int p_peakmode)} {return_type void
249 } {
250 code {this->mode=p_peakmode;
251peakreset();} {}
252 }
253 decl {char labeltext[10];} {}
254}
255
256class TrackInfo {: {public Fl_Group}
257} {
258 Function {make_window()} {} {
259 Fl_Window ledchannel {
260 xywh {5 69 20 120} type Double color 0 labelcolor 7 align 16 hide
261 code0 {o->position(parent()->x(),parent()->y());}
262 class Fl_Group
263 } {
264 Fl_Box led1 {
265 label {-60}
266 xywh {3 76 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 6 align 16
267 }
268 Fl_Box recled {
269 label REC
270 xywh {3 96 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 1 align 16
271 }
272 Fl_Box inputled {
273 label INP
274 xywh {3 104 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 6 align 16
275 }
276 Fl_Box led2 {
277 label {-48}
278 xywh {3 68 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 6 align 16
279 }
280 Fl_Box led3 {
281 label {-36}
282 xywh {3 60 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 6 align 16
283 }
284 Fl_Box led4 {
285 label {-24}
286 xywh {3 52 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 6 align 16
287 }
288 Fl_Box led5 {
289 label {-15}
290 xywh {3 44 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 1 align 16
291 }
292 Fl_Box led6 {
293 label {-9}
294 xywh {3 36 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 6 align 16
295 }
296 Fl_Box led7 {
297 label {-6}
298 xywh {3 28 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 93 align 16
299 }
300 Fl_Box led8 {
301 label {-3}
302 xywh {3 20 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 93 align 16
303 }
304 Fl_Box led9 {
305 label {-1}
306 xywh {3 12 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 93 align 16
307 }
308 Fl_Box led10 {
309 label CLIP
310 xywh {0 4 22 6} box FLAT_BOX color 0 labelfont 1 labelsize 8 labelcolor 1 align 16
311 }
312 }
313 }
314 Function {TrackInfo(int a,int b,int c,int d,const char* e):Fl_Group(a,b,c,d,e)} {open
315 } {
316 code {make_window();} {}
317 }
318 Function {TrackInfo(int a,int b,int c,int d):Fl_Group(a,b,c,d,NULL)} {open
319 } {
320 code {make_window();} {}
321 }
322}
diff --git a/src/frontend/ui_help_about.fl b/src/frontend/ui_help_about.fl
new file mode 100755
index 0000000..2bd0a3b
--- /dev/null
+++ b/src/frontend/ui_help_about.fl
@@ -0,0 +1,68 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0107
3header_name {.h}
4code_name {.cxx}
5class UserInterface_HelpAbout {open
6} {
7 Function {make_window()} {open
8 } {
9 Fl_Window {} {
10 label {About HD24connect} open
11 xywh {567 209 340 350} type Double color 52 modal visible
12 } {
13 Fl_Box {} {
14 xywh {10 10 320 305} box DOWN_BOX color 7
15 }
16 Fl_Box {} {
17 image {images/hd24connect.png} xywh {45 25 250 77}
18 }
19 Fl_Button {} {
20 label OK
21 callback {/* Find the window regardless of its class name */
22Fl_Window * x=Fl::first_window();
23x->~Fl_Window();}
24 xywh {125 320 90 25} labelsize 12
25 }
26 Fl_Box {} {
27 label {HD24connect version HD24VERSION}
28 xywh {45 110 250 20} labelsize 12
29 }
30 Fl_Box {} {
31 label {This program was written as an independent effort,}
32 xywh {15 130 305 20} labelsize 11
33 }
34 Fl_Box {} {
35 label {and is neither endorsed by nor affiliated with Alesis.}
36 xywh {15 145 305 20} labelsize 11
37 }
38 Fl_Box {} {
39 label {No warranty of any kind is given or implied.} selected
40 xywh {15 175 305 20} labelsize 11
41 }
42 Fl_Box {} {
43 label {Share and enjoy!}
44 xywh {10 290 310 20} labelsize 11
45 }
46 Fl_Box {} {
47 label {Use at your own risk.}
48 xywh {15 190 305 20} labelsize 11
49 }
50 Fl_Box {} {
51 label {If you find this program useful, please make a }
52 xywh {15 215 305 20} labelsize 11
53 }
54 Fl_Box {} {
55 label {donation to the author. See }
56 xywh {15 230 305 20} labelsize 11
57 }
58 Fl_Box {} {
59 label {http://ringbreak.dnd.utwente.nl/~mrjb/hd24tools/}
60 xywh {15 245 305 20} labelsize 11
61 }
62 Fl_Box {} {
63 label {Feel free to request additional features.}
64 xywh {15 260 305 20} labelsize 11
65 }
66 }
67 }
68}
diff --git a/src/frontend/ui_mixer.fl b/src/frontend/ui_mixer.fl
new file mode 100644
index 0000000..11dee83
--- /dev/null
+++ b/src/frontend/ui_mixer.fl
@@ -0,0 +1,2225 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0109
3header_name {.h}
4code_name {.cxx}
5decl {\#define MAXSAMRATE 48000} {public
6}
7
8decl {\#define maxfilterunits 200} {public
9}
10
11decl {\#define maxreverbunits 20} {public
12}
13
14decl {\#define maxreverbseconds 1} {public
15}
16
17decl {\#define eqperchan 4} {public
18}
19
20decl {\#define Pi2 (2*3.1415926535897)} {public
21}
22
23decl {\#include <config.h>} {public
24}
25
26decl {\#include <string>} {public
27}
28
29decl {\#include <vector>} {public
30}
31
32decl {\#include <soundlibs.h>} {public
33}
34
35decl {\#include <iostream>} {public
36}
37
38decl {\#include <fstream>} {public
39}
40
41decl {\#include <FL/FLTKstuff.H>} {public
42}
43
44decl {\#include <FL/filename.H>} {public
45}
46
47decl {\#include <convertlib.h>} {public
48}
49
50decl {\#include <WidgetPDial.h>} {public
51}
52
53decl {\#include <time.h>} {public
54}
55
56decl {\#include <math.h>} {public
57}
58
59decl {\#include <ui_hd24connect.h>} {public
60}
61
62class stereosample {open
63} {
64 decl {float left;} {public
65 }
66 decl {float right;} {public
67 }
68}
69
70decl {class MixerChannelControl;} {public
71}
72
73decl {class MixerChannelUI;} {public
74}
75
76decl {class MixerChannelData;} {public
77}
78
79decl {class MasterChannelUI;} {public
80}
81
82decl {class MasterChannelControl;} {public
83}
84
85decl {class MixerControl;} {public
86}
87
88decl {class MixerChannelUI;} {public
89}
90
91class MixerLevelMeterData {} {
92 decl {\#define PEAKMODE_NOHOLD 0} {public
93 }
94 decl {\#define PEAKMODE_TEMPHOLD 1} {public
95 }
96 decl {\#define PEAKMODE_CONTHOLD 2} {public
97 }
98 decl {\#define PEAKMODE_MAXHOLD 33} {public
99 }
100 decl {int mode;} {public
101 }
102 decl {double dB;} {public
103 }
104 decl {double peakvalue; /* for peak hold */} {public
105 }
106 decl {double metervalue;} {public
107 }
108 decl {int holdtime;} {public
109 }
110 decl {int dBrange;} {public
111 }
112}
113
114class MixerLevelMeterControl {} {
115 decl {MixerLevelMeterData* data;} {}
116 Function {MixerLevelMeterControl()} {open
117 } {
118 code {data=new MixerLevelMeterData;
119init();} {}
120 }
121 Function {~MixerLevelMeterControl()} {open
122 } {
123 code {delete data;} {}
124 }
125 Function {setvalue(double levelval)} {open
126 } {
127 code {data->dB=20*log10(levelval);
128return;
129
130// reset peaks if desired
131switch (data->mode) {
132 case PEAKMODE_NOHOLD: this->peakreset(); break;
133 case PEAKMODE_TEMPHOLD:
134 if (data->holdtime>PEAKMODE_MAXHOLD) {
135 peakreset();
136 } else {
137 data->holdtime++;
138 }
139 break;
140 case PEAKMODE_CONTHOLD:
141 break;
142 default:
143 data->mode=PEAKMODE_NOHOLD;
144 peakreset();
145 break;
146}
147
148if (levelval>data->metervalue) {
149 data->peakvalue=data->metervalue;
150 data->holdtime=0;
151}} {}
152 }
153 Function {peakmode(int p_peakmode)} {open return_type void
154 } {
155 code {data->mode=p_peakmode;
156peakreset();} {}
157 }
158 Function {peakreset()} {open return_type void
159 } {
160 code {data->peakvalue=0;
161data->holdtime=0;} {}
162 }
163 Function {init()} {open return_type void
164 } {
165 code {data->peakvalue=0;
166data->holdtime=0;
167
168data->dBrange=60;
169this->setvalue(0);
170return;} {}
171 }
172 Function {getpctvalue()} {open return_type float
173 } {
174 code {float pct=100-(100*(-(data->dB)/(data->dBrange)));
175
176if (pct<0) { pct=0; }
177if (pct>100) { pct=100; }
178
179return pct;} {}
180 }
181}
182
183class MixerLevelMeterUI {: {public Fl_Group}
184} {
185 decl {MixerLevelMeterControl* control;} {public
186 }
187 Function {MixerLevelMeterUI(int a,int b,int c,int d,const char* e):Fl_Group(a,b,c,d,e)} {} {
188 code {init_ui();} {}
189 }
190 Function {MixerLevelMeterUI(int a,int b,int c,int d):Fl_Group(a,b,c,d,NULL)} {} {
191 code {init_ui();} {}
192 }
193 Function {init_ui()} {open private
194 } {
195 code {this->control=new MixerLevelMeterControl();} {}
196 }
197 Function {draw()} {open
198 } {
199 code {float pct=(control->getpctvalue())/100;
200
201int zro=y();
202int bot=zro+128;
203int myx=x();
204int top=bot- ((int)( pct*128));
205
206 fl_color(fl_rgb_color(0,255,0));
207 fl_line(myx,top,myx,bot);
208 myx++;
209 fl_line(myx,top,myx,bot);
210 myx--;
211
212 fl_color(fl_rgb_color(0,0,0));
213 fl_line(myx,zro,myx,top);
214 myx++;
215 fl_line(myx,zro,myx,top);
216
217return;} {}
218 }
219 Function {~MixerLevelMeterUI()} {open
220 } {
221 code {delete control;} {}
222 }
223}
224
225class MixerChannelData {open
226} {
227 decl {int bypass; /* 1 to bypass all mixing */} {public
228 }
229 decl {friend class MixerChannelUI;} {}
230 decl {friend class MixerChannelControl;} {}
231 decl {MixerChannelUI* parentui;} {}
232 decl {double trackpeak;} {public
233 }
234 decl {int enable_eq; /* overall eq settings */} {public
235 }
236 decl {int enable_pan; /* overall eq settings */} {public
237 }
238 decl {int eq_on[eqperchan];} {public
239 }
240 decl {double eq_gain[eqperchan];} {public
241 }
242 decl {double eq_freq[eqperchan];} {public
243 }
244 decl {double eq_Q[eqperchan];} {public
245 }
246 decl {double eq_type[eqperchan];} {public
247 }
248 decl {double fadermult;} {public
249 }
250 decl {double faderval;} {public
251 }
252 decl {double panvalue;} {public
253 }
254 decl {float* delaybuffer;} {}
255 decl {long delaybuffersize;} {public
256 }
257 decl {long delaybuffersam;} {public
258 }
259 decl {int solo;} {}
260 decl {int mute;} {}
261 decl {int ch_number;} {}
262 decl {char strchnum[4];} {}
263 decl {float* sample;} {public
264 }
265 decl {int mixmono;} {}
266 decl {MixerControl* parentmixercontrol;} {}
267 decl {__uint32 samplerate;} {public
268 }
269 decl {int selected;} {}
270 decl {int ringbufpos[maxreverbunits];} {}
271}
272
273class MixerChannelControl {open
274} {
275 decl {friend class MixerChannelUI;} {}
276 decl {friend class MixerChannelData;} {}
277 decl {MixerChannelData* data;} {public
278 }
279 Function {init()} {open return_type void
280 } {
281 code {data->bypass=0;
282data->trackpeak=0;
283data->enable_eq=1;
284data->enable_pan=1;
285data->solo=0;
286data->mute=0;
287data->sample=(float *)malloc(24000*sizeof(float));
288data->eq_gain[0]=0;
289data->eq_gain[1]=0;
290data->eq_gain[2]=0;
291data->eq_gain[3]=0;
292data->eq_Q[0]=1;
293data->eq_Q[1]=1;
294data->eq_Q[2]=1;
295data->eq_Q[3]=1;
296data->eq_on[0]=1;
297data->eq_on[1]=1;
298data->eq_on[2]=1;
299data->eq_on[3]=1;
300data->eq_freq[0]=100;
301data->eq_freq[1]=600;
302data->eq_freq[2]=1600;
303data->eq_freq[3]=6000;
304data->samplerate=44100; // TODO: set to proper val
305data->faderval=90;
306data->fadermult=1;
307data->panvalue=0;
308
309
310data->delaybuffersize=maxreverbunits*maxreverbseconds*MAXSAMRATE;
311data->delaybuffer=(float *)malloc(sizeof(float)*(data->delaybuffersize));
312if (data->delaybuffer==NULL) cout << " out of mem L" << endl;
313data->delaybuffersam=data->delaybuffersize;
314for (int i=0;i<data->delaybuffersize;i++)
315{
316 data->delaybuffer[i]=0;
317}
318data->ringbufpos[0]=881;
319data->ringbufpos[1]=883;
320data->ringbufpos[2]=887;
321data->ringbufpos[3]=907;
322data->ringbufpos[4]=911;
323data->ringbufpos[5]=919;
324data->ringbufpos[6]=929;
325data->ringbufpos[7]=937;
326data->ringbufpos[8]=941;
327data->ringbufpos[9]=947;
328data->ringbufpos[10]=953;
329data->ringbufpos[11]=967;
330data->ringbufpos[12]=971;
331data->ringbufpos[13]=977;
332data->ringbufpos[14]=983;
333data->ringbufpos[15]=991;
334data->ringbufpos[16]=997;
335data->ringbufpos[17]=1009;
336data->ringbufpos[18]=1013;
337data->ringbufpos[19]=1019;
338
339return;} {}
340 }
341 Function {MixerChannelControl()} {open
342 } {
343 code {data=new MixerChannelData();
344init();} {}
345 }
346 Function {~MixerChannelControl()} {open
347 } {
348 code {free (data->sample);
349data->sample=NULL;
350free (data->delaybuffer);
351data->delaybuffer=NULL;
352delete data;
353data=NULL;} {}
354 }
355 Function {fadervalue(const double p_val)} {} {
356 code {double lin;
357if (p_val == 0) {
358 lin=0;
359} else {
360 lin=pow(10,(p_val-90)/60);
361}
362data->fadermult=lin;
363data->faderval=p_val;
364data->parentui->fader->value(p_val);
365data->parentui->redraw();} {}
366 }
367 Function {fadervalue()} {open return_type double
368 } {
369 code {return data->faderval;} {}
370 }
371 Function {updatemeters()} {open return_type void
372 } {
373 code {// update and redraw meterlevels object
374this->parentui()->mixled->control->setvalue(data->trackpeak);
375this->parentui()->mixled->redraw();
376// then, reset peak value
377trackpeak(0);} {}
378 }
379 Function {solo(int p_val)} {open return_type void
380 } {
381 code {data->solo=p_val;
382data->parentui->mixsolo->value(p_val);
383data->parentui->mixsolo->damage();
384data->parentui->mixsolo->redraw();
385if (p_val==1)
386{
387this->parentmixercontrol()->selectedchannel(this->channel_number()-1);
388}} {}
389 }
390 Function {mute(int p_val)} {open return_type void
391 } {
392 code {data->mute=p_val;
393data->parentui->mixmute->value(p_val);
394data->parentui->mixmute->damage();
395data->parentui->mixmute->redraw();
396//if (ui!=NULL) {
397// ui->readmixer();
398//}} {}
399 }
400 Function {solo()} {open return_type int
401 } {
402 code {return data->solo;} {}
403 }
404 Function {mute()} {open return_type int
405 } {
406 code {return data->mute;} {}
407 }
408 Function {issolo()} {open return_type int
409 } {
410 code {return data->solo;} {}
411 }
412 Function {ismute()} {open return_type int
413 } {
414 code {return data->mute;} {}
415 }
416 Function {getfadermult()} {open return_type double
417 } {
418 code {return data->fadermult;} {}
419 }
420 Function {trackpeak()} {open return_type double
421 } {
422 code {return data->trackpeak;} {}
423 }
424 Function {trackpeak(double peakval)} {open return_type void
425 } {
426 code {data->trackpeak=peakval;} {}
427 }
428 Function {channel_number(int ch)} {open return_type void
429 } {
430 code {data->ch_number=ch;
431snprintf(data->strchnum,3,"%d",ch);
432data->parentui->mixmute->label(data->strchnum);} {}
433 }
434 Function {channel_number()} {open return_type int
435 } {
436 code {return data->ch_number;} {}
437 }
438 Function {parentmixercontrol(MixerControl* p_parentmixercontrol)} {open return_type void
439 } {
440 code {data->parentmixercontrol=p_parentmixercontrol;} {}
441 }
442 Function {parentui(MixerChannelUI* p_parentui)} {open return_type void
443 } {
444 code {data->parentui=p_parentui;} {}
445 }
446 Function {parentui()} {open return_type {MixerChannelUI*}
447 } {
448 code {return data->parentui;} {}
449 }
450 Function {parentmixercontrol()} {open return_type {MixerControl*}
451 } {
452 code {return data->parentmixercontrol;} {}
453 }
454 Function {panvalue(const double p_val)} {open
455 } {
456 code {data->panvalue=p_val;
457data->parentui->mixpan->value(p_val);
458data->parentui->mixpan->damage();
459data->parentui->mixpan->redraw();} {}
460 }
461 Function {panvalue()} {open return_type double
462 } {
463 code {return data->panvalue;} {}
464 }
465 Function {sample(int framenum,float samval)} {open
466 } {
467 code {if (data==NULL) return;
468if ((data->sample)==NULL) return;
469data->sample[framenum]=samval;
470/*float q=1;
471if (samval<0) {
472 q=-1;
473}
474if ((samval*q) > data->trackpeak) {
475 data->trackpeak=samval*q;
476}*/} {}
477 }
478 Function {sample(int framenum)} {return_type float
479 } {
480 code {return data->sample[framenum];} {}
481 }
482 Function {getsample(stereosample* sam,int framenum)} {open return_type void
483 } {
484 code {float monosam=data->sample[framenum];
485
486if (data->bypass==1)
487{
488 /* Bypass all mixer functions, just return the sample */
489 sam->left=monosam/2;
490 sam->right=monosam/2;
491 return;
492}
493
494float panval;
495if (data->enable_eq==1) {
496 int Q=1;
497 // FilterCell(unsigned long Unit, double Input, double Frequency, double Q, double Gain, unsigned long Type)
498 if (eq_on(0)==1 && (eq_gain(0)!=0)) monosam=FilterCell(0,monosam,eq_freq(0),Q,eq_gain(0),7);
499 if (eq_on(1)==1 && (eq_gain(1)!=0)) monosam=FilterCell(1,monosam,eq_freq(1),Q,eq_gain(1),7);
500 if (eq_on(2)==1 && (eq_gain(2)!=0)) monosam=FilterCell(2,monosam,eq_freq(2),Q,eq_gain(2),7);
501 if (eq_on(3)==1 && (eq_gain(3)!=0)) monosam=FilterCell(3,monosam,eq_freq(3),Q,eq_gain(3),7);
502}
503
504monosam*=getfadermult();
505
506sam->left=monosam;
507sam->right=monosam;
508
509if (data->enable_pan==1)
510{
511 panval=panvalue();
512} else {
513 panval=0;
514}
515
516float pctright=(panval+127)/254;
517float pctleft=1-pctright;
518sam->left*=pctleft;
519sam->right*=pctright;
520
521float subsamval=fabs(monosam);
522if (subsamval > trackpeak()) {
523 trackpeak(subsamval);
524}
525
526return;} {}
527 }
528 Function {channelselect(int select)} {return_type void
529 } {
530 code {data->selected=select;
531parentui()->mixchsel->value(select);
532parentui()->mixchsel->redraw();} {}
533 }
534 Function {FilterCell(unsigned long Unit, double Input, double Frequency, double Q, double Gain, unsigned long Type)} {return_type double
535 } {
536 code {__uint32 SampleRate=data->samplerate;
537
538/* --------------------------------------------------------------- */
539 double Output,S,omega,A,sn,cs,alpha,beta,temp1,temp2,temp3,temp4;
540 Output=Input;
541
542/* -- check if frequency, Q, gain or type has changed.. and, if so, update coefficients */
543 if ( ( Frequency != filter_f[Unit] ) || ( Gain != filter_g[Unit] ) || ( Q != filter_q[Unit] ) || ( Type != filter_t[Unit] ) ) {
544 filter_f[Unit] = Frequency; filter_q[Unit] = Q; filter_g[Unit] = Gain; filter_t[Unit] = Type; /* remember last frequency, q, gain and type */
545 switch (Type) {
546 case 0: /* no filtering */
547 filter_b0[Unit] = pow( 10.0, Gain / 20.0 ); /* convert from dB to linear */
548 break;
549 case 1: /* lowpass */
550 Gain = pow( 10.0, Gain / 20.0 ); /* convert from dB to linear */
551 omega = ( Pi2 * Frequency ) / SampleRate;
552 sn = sin( omega ); cs = cos( omega );
553 alpha = sn / ( 2.0 * Q );
554 filter_a0[Unit] = 1.0 / ( 1.0 + alpha );
555 filter_a1[Unit] = ( -2.0 * cs ) * filter_a0[Unit];
556 filter_a2[Unit] = ( 1.0 - alpha ) * filter_a0[Unit];
557 filter_b1[Unit] = ( 1.0 - cs ) * filter_a0[Unit] * Gain;
558 filter_b0[Unit] = filter_b1[Unit] * 0.5;
559 break;
560 case 2: /* highpass */
561 Gain = pow( 10.0, Gain / 20.0 ); /* convert from dB to linear */
562 omega = ( Pi2 * Frequency ) / SampleRate;
563 sn = sin( omega ); cs = cos( omega );
564 alpha = sn / ( 2.0 * Q );
565 filter_a0[Unit] = 1.0 / ( 1.0 + alpha );
566 filter_a1[Unit] = ( -2.0 * cs ) * filter_a0[Unit];
567 filter_a2[Unit] = ( 1.0 - alpha ) * filter_a0[Unit];
568 filter_b1[Unit] = -( 1.0 + cs ) * filter_a0[Unit] * Gain;
569 filter_b0[Unit] = -filter_b1[Unit] * 0.5;
570 break;
571 case 3: /* bandpass */
572 Gain = pow( 10.0, Gain / 20.0 ); /* convert from dB to linear */
573 omega = ( Pi2 * Frequency ) / SampleRate;
574 sn = sin( omega ); cs = cos( omega );
575 alpha = sn / ( 2.0 * Q );
576 filter_a0[Unit] = 1.0 / ( 1.0 + alpha );
577 filter_a1[Unit] = ( -2.0 * cs ) * filter_a0[Unit];
578 filter_a2[Unit] = ( 1.0 - alpha ) * filter_a0[Unit];
579 filter_b0[Unit] = alpha * filter_a0[Unit] * Gain;
580 break;
581 case 4: /* notch */
582 Gain = pow( 10.0, Gain / 20.0 ); /* convert from dB to linear */
583 omega = ( Pi2 * Frequency ) / SampleRate;
584 sn = sin( omega ); cs = cos( omega );
585 alpha = sn / ( 2.0 * Q );
586 filter_a0[Unit] = 1.0 / ( 1.0 + alpha );
587 filter_a1[Unit] = ( -2.0 * cs ) * filter_a0[Unit];
588 filter_a2[Unit] = ( 1.0 - alpha ) * filter_a0[Unit];
589 filter_b0[Unit] = filter_a0[Unit] * Gain;
590 filter_b1[Unit] = filter_a1[Unit] * Gain;
591 break;
592 case 5: /* lowshelf */
593 /* "shelf slope" 1.0 = max slope, because neither Q nor bandwidth is used in */
594 /* those filters (note: true only for lowshelf and highshelf, not peaking). */
595 S = 1.0; /* used only by lowshelf and highshelf */
596 A = pow( 10.0 , ( Gain / 40.0 ) ); /* Gain is expressed in dB */
597 omega = ( Pi2 * Frequency ) / SampleRate;
598 sn = sin( omega ); cs = cos( omega );
599 temp1 = A + 1.0; temp2 = A - 1.0; temp3 = temp1 * cs; temp4 = temp2 * cs;
600 beta = sn * sqrt( ( A * A + 1.0 ) / S - temp2 * temp2 );
601 filter_a0[Unit] = 1.0 / ( temp1 + temp4 + beta );
602 filter_a1[Unit] = ( -2.0 * ( temp2 + temp3 ) ) * filter_a0[Unit];
603 filter_a2[Unit] = ( temp1 + temp4 - beta ) * filter_a0[Unit];
604 filter_b0[Unit] = ( A * ( temp1 - temp4 + beta ) ) * filter_a0[Unit];
605 filter_b1[Unit] = ( 2.0 * A * ( temp2 - temp3 ) ) * filter_a0[Unit];
606 filter_b2[Unit] = ( A * ( temp1 - temp4 - beta ) ) * filter_a0[Unit];
607 break;
608 case 6: /* highshelf */
609 /* "shelf slope" 1.0 = max slope, because neither Q nor bandwidth is used in */
610 /* those filters (note: true only for lowshelf and highshelf, not peaking). */
611 S = 1.0; /* used only by lowshelf and highshelf */
612 A = pow( 10.0, ( Gain / 40.0 ) ); /* Gain is expressed in dB */
613 omega = ( Pi2 * Frequency ) / SampleRate;
614 sn = sin( omega ); cs = cos( omega );
615 temp1 = A + 1.0; temp2 = A - 1.0; temp3 = temp1 * cs; temp4 = temp2 * cs;
616 beta = sn * sqrt( ( A * A + 1.0 ) / S - temp2 * temp2 );
617 filter_a0[Unit] = 1.0 / ( temp1 - temp4 + beta );
618 filter_a1[Unit] = ( 2.0 * ( temp2 - temp3 ) ) * filter_a0[Unit];
619 filter_a2[Unit] = ( temp1 - temp4 - beta ) * filter_a0[Unit];
620 filter_b0[Unit] = ( A * ( temp1 + temp4 + beta ) ) * filter_a0[Unit];
621 filter_b1[Unit] = ( -2.0 * A * ( temp2 + temp3 ) ) * filter_a0[Unit];
622 filter_b2[Unit] = ( A * ( temp1 + temp4 - beta ) ) * filter_a0[Unit];
623 break;
624 case 7: /* peaking */
625 A = pow( 10.0, ( Gain / 40.0 ) ); /* Gain is expressed in dB */
626 omega = ( Pi2 * Frequency ) / SampleRate;
627 sn = sin( omega ); cs = cos( omega );
628 alpha = sn / ( 2.0 * Q );
629 temp1 = alpha * A;
630 temp2 = alpha / A;
631 filter_a0[Unit] = 1.0 / ( 1.0 + temp2 );
632 filter_a1[Unit] = ( -2.0 * cs ) * filter_a0[Unit];
633 filter_a2[Unit] = ( 1.0 - temp2 ) * filter_a0[Unit];
634 filter_b0[Unit] = ( 1.0 + temp1 ) * filter_a0[Unit];
635 filter_b2[Unit] = ( 1.0 - temp1 ) * filter_a0[Unit];
636 break;
637 }
638 }
639/* -- filter loop: if you don't change the parameters of the filter dynamically, ~only this code will be executed. */
640 switch (Type) {
641 case 0: /* no filtering */
642 Output = filter_b0[Unit]*Input;
643 break;
644 case 1: /* lowpass */
645 case 2: /* highpass */
646 Output = filter_b0[Unit]*Input
647 + filter_b1[Unit]*filter_i1[Unit]
648 + filter_b0[Unit]*filter_i2[Unit]
649 - filter_a1[Unit]*filter_o1[Unit]
650 - filter_a2[Unit]*filter_o2[Unit];
651 break;
652 case 3: /* bandpass */
653 Output = filter_b0[Unit]*Input
654 - filter_b0[Unit]*filter_i2[Unit]
655 - filter_a1[Unit]*filter_o1[Unit]
656 - filter_a2[Unit]*filter_o2[Unit];
657 break;
658 case 4: /* notch */
659 Output = filter_b0[Unit]*Input
660 + filter_b1[Unit]*filter_i1[Unit]
661 + filter_b0[Unit]*filter_i2[Unit]
662 - filter_a1[Unit]*filter_o1[Unit]
663 - filter_a2[Unit]*filter_o2[Unit];
664 break;
665 case 5: /* low shelving */
666 case 6: /* high shelving */
667 Output = filter_b0[Unit]*Input
668 + filter_b1[Unit]*filter_i1[Unit]
669 + filter_b2[Unit]*filter_i2[Unit]
670 - filter_a1[Unit]*filter_o1[Unit]
671 - filter_a2[Unit]*filter_o2[Unit];
672 break;
673 case 7: /* peaking */
674 Output = filter_b0[Unit]*Input
675 + filter_a1[Unit]*filter_i1[Unit]
676 + filter_b2[Unit]*filter_i2[Unit]
677 - filter_a1[Unit]*filter_o1[Unit]
678 - filter_a2[Unit]*filter_o2[Unit];
679 break;
680 }
681 filter_o2[Unit]=filter_o1[Unit];
682 filter_o1[Unit]=Output;
683 filter_i2[Unit]=filter_i1[Unit];
684 filter_i1[Unit]=Input; /* update variables for recursion */
685
686 return(Output);} {}
687 }
688 Function {eq_gain(int whicheq,double gain)} {open return_type void
689 } {
690 code {if (whicheq>4) return;
691if (whicheq<0) return;
692data->eq_gain[whicheq]=gain;
693
694
695//cout << "set freq to "<<freq <<" for (base0)ch "<<channel_number()-1 << endl;
696WidgetPDial* gainwidget=NULL;
697Fl_Output* dispwidget=NULL;
698switch (whicheq) {
699 case 0:
700 {
701 gainwidget=parentmixercontrol()->parentui()->gain1;
702 dispwidget=parentmixercontrol()->parentui()->dispgain1;
703 break;
704 }
705 case 1:
706 {
707 gainwidget=parentmixercontrol()->parentui()->gain2;
708 dispwidget=parentmixercontrol()->parentui()->dispgain2;
709 break;
710 }
711 case 2:
712 {
713 gainwidget=parentmixercontrol()->parentui()->gain3;
714 dispwidget=parentmixercontrol()->parentui()->dispgain3;
715 break;
716 }
717 case 3:
718 {
719 gainwidget=parentmixercontrol()->parentui()->gain4;
720 dispwidget=parentmixercontrol()->parentui()->dispgain4;
721 break;
722 }
723}
724if (dispwidget!=NULL)
725{
726 string* sval=Convert::int64tostr((__sint64)gain);
727 dispwidget->value(sval->c_str());
728 delete sval;
729 dispwidget->redraw();
730}
731if (gainwidget!=NULL)
732{
733 gainwidget->value(gain);
734 gainwidget->redraw();
735}} {}
736 }
737 Function {eq_gain(int whicheq)} {open return_type double
738 } {
739 code {if (whicheq>4) return 0;
740if (whicheq<0) return 0;
741return data->eq_gain[whicheq];} {}
742 }
743 Function {eq_freq(int whicheq,double freq)} {open return_type void
744 } {
745 code {if (whicheq>4) return;
746if (whicheq<0) return;
747data->eq_freq[whicheq]=freq;
748//cout << "set freq to "<<freq <<" for (base0)ch "<<channel_number()-1 << endl;
749WidgetPDial* freqwidget=NULL;
750Fl_Output* dispwidget=NULL;
751switch (whicheq) {
752 case 0:
753 {
754 freqwidget=parentmixercontrol()->parentui()->freq1;
755 dispwidget=parentmixercontrol()->parentui()->dispfreq1;
756 break;
757 }
758 case 1:
759 {
760 freqwidget=parentmixercontrol()->parentui()->freq2;
761 dispwidget=parentmixercontrol()->parentui()->dispfreq2;
762 break;
763 }
764 case 2:
765 {
766 freqwidget=parentmixercontrol()->parentui()->freq3;
767 dispwidget=parentmixercontrol()->parentui()->dispfreq3;
768 break;
769 }
770 case 3:
771 {
772 freqwidget=parentmixercontrol()->parentui()->freq4;
773 dispwidget=parentmixercontrol()->parentui()->dispfreq4;
774 break;
775 }
776}
777if (dispwidget!=NULL)
778{
779 string* sval=Convert::int64tostr((__sint64)freq);
780 dispwidget->value(sval->c_str());
781 delete sval;
782 dispwidget->redraw();
783}
784if (freqwidget!=NULL)
785{
786 freqwidget->value(freq);
787 freqwidget->redraw();
788}} {}
789 }
790 Function {eq_freq(int whicheq)} {return_type double
791 } {
792 code {if (whicheq>4) return 0;
793if (whicheq<0) return 0;
794return data->eq_freq[whicheq];} {}
795 }
796 Function {eq_on(int whicheq,int onoff)} {return_type void
797 } {
798 code {if (whicheq>4) return;
799if (whicheq<0) return;
800data->eq_on[whicheq]=onoff;
801
802switch (whicheq) {
803 case 0: parentmixercontrol()->parentui()->eqon1->value(onoff); break;
804 case 1: parentmixercontrol()->parentui()->eqon2->value(onoff); break;
805 case 2: parentmixercontrol()->parentui()->eqon3->value(onoff); break;
806 case 3: parentmixercontrol()->parentui()->eqon4->value(onoff); break;
807}
808parentmixercontrol()->parentui()->eqon1->redraw();
809parentmixercontrol()->parentui()->eqon2->redraw();
810parentmixercontrol()->parentui()->eqon3->redraw();
811parentmixercontrol()->parentui()->eqon4->redraw();} {}
812 }
813 Function {eq_on(int whicheq)} {return_type int
814 } {
815 code {if (whicheq>4) return 0;
816if (whicheq<0) return 0;
817return data->eq_on[whicheq];} {}
818 }
819 Function {eq_Q(int whicheq,double Q)} {return_type void
820 } {
821 code {if (whicheq>4) return;
822if (whicheq<0) return;
823data->eq_Q[whicheq]=Q;
824//cout << "set freq to "<<freq <<" for (base0)ch "<<channel_number()-1 << endl;
825
826//switch (whicheq) {
827// case 0: parentmixercontrol()->parentui()->Q1->value(freq); break;
828// case 1: parentmixercontrol()->parentui()->Q2->value(freq); break;
829// case 2: parentmixercontrol()->parentui()->Q3->value(freq); break;
830// case 3: parentmixercontrol()->parentui()->Q4->value(freq); break;
831//}
832//parentmixercontrol()->parentui()->freq1->redraw();
833//parentmixercontrol()->parentui()->freq2->redraw();
834//parentmixercontrol()->parentui()->freq3->redraw();
835//parentmixercontrol()->parentui()->freq4->redraw();} {}
836 }
837 Function {eq_Q(int whicheq)} {return_type double
838 } {
839 code {if (whicheq>4) return 0;
840if (whicheq<0) return 0;
841return data->eq_Q[whicheq];} {}
842 }
843 decl {double filter_i1[eqperchan]; /* temporary variables */} {}
844 decl {double filter_i2[eqperchan];} {}
845 decl {double filter_o1[eqperchan];} {}
846 decl {double filter_o2[eqperchan];} {}
847 decl {double filter_a0[eqperchan]; /*coefficients */} {}
848 decl {double filter_a1[eqperchan];} {}
849 decl {double filter_a2[eqperchan];} {}
850 decl {double filter_b0[eqperchan]; /*coefficients */} {}
851 decl {double filter_b1[eqperchan];} {}
852 decl {double filter_b2[eqperchan];} {}
853 decl {double filter_f[eqperchan]; /* last freq used */} {}
854 decl {double filter_q[eqperchan]; /* last Q used */} {}
855 decl {double filter_g[eqperchan]; /* last gain used */} {}
856 decl {unsigned long filter_t[eqperchan]; /* last T used */} {}
857 Function {pan_enabled(int yesno)} {open return_type void
858 } {
859 code {data->enable_pan=yesno;} {}
860 }
861 Function {pan_enabled()} {open return_type int
862 } {
863 code {return data->enable_pan;} {}
864 }
865 Function {eq_enabled(int yesno)} {return_type void
866 } {
867 code {data->enable_eq=yesno;} {}
868 }
869 Function {eq_enabled()} {open return_type int
870 } {
871 code {return data->enable_eq;} {}
872 }
873 Function {bypass(int yesno)} {open return_type void
874 } {
875 code {data->bypass=yesno;} {}
876 }
877 Function {bypass()} {open return_type int
878 } {
879 code {return data->bypass;} {}
880 }
881 Function {samplerate(__uint32 p_samplerate)} {open return_type void
882 } {
883 code {data->samplerate=p_samplerate;} {}
884 }
885 Function {samplerate()} {open return_type __uint32
886 } {
887 code {return data->samplerate;} {}
888 }
889}
890
891class MixerChannelUI {open : {public Fl_Group}
892} {
893 decl {MixerChannelControl* control;} {public
894 }
895 Function {MixerChannelUI(int a,int b,int c,int d,const char* e):Fl_Group(a,b,c,d,e)} {open
896 } {
897 code {init_ui();} {}
898 }
899 Function {MixerChannelUI(int a,int b,int c,int d):Fl_Group(a,b,c,d,NULL)} {open
900 } {
901 code {init_ui();} {}
902 }
903 Function {init_ui()} {open private
904 } {
905 code {this->control=new MixerChannelControl();
906this->control->parentui(this);
907make_window();} {}
908 }
909 Function {make_window()} {open
910 } {
911 Fl_Window channelstrip {open
912 xywh {698 377 20 235} type Double
913 code0 {o->position(this->x(),this->y());}
914 class Fl_Group visible
915 } {
916 Fl_Group resources {open
917 xywh {80 62 150 98} hide deactivate
918 } {
919 Fl_Button button_mute_up {
920 tooltip Play image {images/button_mute.gif} xywh {80 62 5 13} labelsize 11 align 16 deactivate
921 }
922 Fl_Button button_mute_dn {
923 tooltip Play image {images/button_mute_dn.gif} xywh {85 62 35 13} labelsize 11 align 16 deactivate
924 }
925 Fl_Button button_solo_up {
926 tooltip Play image {images/button_solo.gif} xywh {80 62 5 13} labelsize 11 align 16 deactivate
927 }
928 Fl_Button button_solo_dn {
929 tooltip Play image {images/button_solo_dn.gif} xywh {85 62 45 13} labelsize 11 align 16 deactivate
930 }
931 }
932 Fl_Button mixmute {
933 label 1
934 callback {//mute(0,o->value());
935this->control->mute(o->value());}
936 tooltip Mute xywh {0 65 20 15} selection_color 1 labelfont 1 labelsize 10 align 2
937 code0 {o->up_image(button_mute_up->image()); o->down_image(button_mute_dn->image());}
938 class Fl_Image_Toggle_Button
939 }
940 Fl_Button mixsolo {
941 callback {this->control->solo(o->value());}
942 tooltip Solo xywh {0 45 20 15} selection_color 2
943 code0 {o->up_image(button_solo_up->image()); o->down_image(button_solo_dn->image());}
944 class Fl_Image_Toggle_Button
945 }
946 Fl_Dial mixpan {
947 callback {control->panvalue(o->value());}
948 xywh {0 25 20 20} minimum -127 maximum 127 step 1
949 class WidgetPDial
950 }
951 Fl_Round_Button mixchsel {
952 callback {this->control->parentmixercontrol()->selectedchannel(this->control->channel_number()-1);}
953 xywh {0 0 15 20} down_box ROUND_DOWN_BOX align 2
954 }
955 Fl_Group mixled {open
956 xywh {18 93 4 132}
957 class MixerLevelMeterUI
958 } {}
959 Fl_Slider fader {
960 callback {control->fadervalue(o->value());}
961 image {images/fader.gif} xywh {0 92 18 128} type {Vert Knob} color 8 labelfont 1 labelsize 10 align 0 minimum 127 maximum 0 step 1 value 90
962 code0 {o->clear_visible_focus();}
963 }
964 }
965 }
966 Function {~MixerChannelUI()} {open
967 } {
968 code {delete control;} {}
969 }
970}
971
972class MasterChannelData {open
973} {
974 decl {friend class MasterChannelUI;} {}
975 decl {friend class MasterChannelControl;} {}
976 decl {MasterChannelUI* parentui;} {}
977 decl {double trackpeak[2];} {public
978 }
979 decl {int eq_on[eqperchan];} {public
980 }
981 decl {double eq_gain[eqperchan];} {public
982 }
983 decl {double eq_freq[eqperchan];} {public
984 }
985 decl {double eq_Q[eqperchan];} {public
986 }
987 decl {double eq_type[eqperchan];} {public
988 }
989 decl {double fadermult[2];} {public
990 }
991 decl {double fadervalue;} {public
992 }
993 decl {double panvalue;} {public
994 }
995 decl {float* delaybuffer;} {}
996 decl {long delaybuffersize;} {public
997 }
998 decl {long delaybuffersam;} {public
999 }
1000 decl {int solo;} {}
1001 decl {int mute;} {}
1002 decl {int ch_number;} {}
1003 decl {char strchnum[4];} {}
1004 decl {float* sample;} {public
1005 }
1006 decl {int mixmono;} {}
1007}
1008
1009class MasterChannelControl {open
1010} {
1011 decl {friend class MasterChannelUI;} {}
1012 Function {init()} {open return_type void
1013 } {
1014 code {data->solo=0;
1015data->mute=0;
1016data->mixmono=0;
1017data->sample=(float *)malloc(24000*sizeof(float));
1018data->trackpeak[0]=0;
1019data->trackpeak[1]=0;
1020data->fadermult[0]=1;
1021data->fadermult[1]=1;
1022data->panvalue=0;
1023data->fadervalue=90;
1024return;} {}
1025 }
1026 decl {MasterChannelData* data;} {}
1027 Function {MasterChannelControl()} {open
1028 } {
1029 code {data=new MasterChannelData;
1030init();} {}
1031 }
1032 Function {~MasterChannelControl()} {open
1033 } {
1034 code {free (data->sample);
1035delete data;} {}
1036 }
1037 Function {fadervalue(const double p_val)} {open
1038 } {
1039 code {double lin;
1040if (p_val == 0) {
1041 lin=0;
1042} else {
1043 lin=pow(10,(p_val-90)/60);
1044}
1045data->fadermult[0]=lin;
1046data->fadermult[1]=lin;
1047data->fadervalue=p_val;
1048data->parentui->redraw();
1049//faderarray[channel]=lin;
1050//mixmute[channel]->draw();
1051//mixfader[channel]->draw();
1052//mixled[channel]->draw();
1053//masterled[0]->draw();
1054//masterled[1]->draw();
1055//this->redraw();*/} {}
1056 }
1057 Function {fadervalue()} {open return_type double
1058 } {
1059 code {return data->fadervalue;} {}
1060 }
1061 Function {updatemeters()} {open return_type void
1062 } {
1063 code {// update and redraw meterlevels object
1064this->parentui()->mixledleft->control->setvalue(data->trackpeak[0]);
1065this->parentui()->mixledright->control->setvalue(data->trackpeak[1]);
1066
1067this->parentui()->mixledleft->redraw();
1068this->parentui()->mixledright->redraw();
1069// then, reset peak value
1070trackpeak(0,0);
1071trackpeak(1,0);} {}
1072 }
1073 Function {trackpeak(int lr)} {open return_type double
1074 } {
1075 code {return data->trackpeak[lr];} {}
1076 }
1077 Function {trackpeak(int lr,double peakval)} {open return_type void
1078 } {
1079 code {data->trackpeak[lr]=peakval;} {}
1080 }
1081 Function {parentui(MasterChannelUI* p_parentui)} {open return_type void
1082 } {
1083 code {data->parentui=p_parentui;} {}
1084 }
1085 Function {parentui()} {open return_type {MasterChannelUI*}
1086 } {
1087 code {return data->parentui;} {}
1088 }
1089 Function {sample(int framenum,float samval)} {open
1090 } {
1091 code {data->sample[framenum]=samval;
1092/*float q=1;
1093if (samval<0) {
1094 q=-1;
1095}
1096if ((samval*q) > data->trackpeak) {
1097 data->trackpeak=samval*q;
1098}*/} {}
1099 }
1100 Function {sample(int framenum)} {open return_type float
1101 } {
1102 code {return data->sample[framenum];} {}
1103 }
1104 Function {getfadermult(int lr)} {open return_type double
1105 } {
1106 code {return data->fadermult[lr];} {}
1107 }
1108 Function {mixmono(int inval)} {open return_type void
1109 } {
1110 code {data->mixmono=inval;
1111parentui()->mix_mono->value(inval);
1112parentui()->mix_mono->redraw();} {}
1113 }
1114 Function {mixmono()} {open return_type int
1115 } {
1116 code {return data->mixmono;} {}
1117 }
1118}
1119
1120class MasterChannelUI {open : {public Fl_Group}
1121} {
1122 decl {MasterChannelControl* control;} {public
1123 }
1124 Function {MasterChannelUI(int a,int b,int c,int d,const char* e):Fl_Group(a,b,c,d,e)} {open
1125 } {
1126 code {init_ui();} {}
1127 }
1128 Function {MasterChannelUI(int a,int b,int c,int d):Fl_Group(a,b,c,d,NULL)} {open
1129 } {
1130 code {init_ui();} {}
1131 }
1132 Function {init_ui()} {open private
1133 } {
1134 code {this->control=new MasterChannelControl();
1135this->control->parentui(this);
1136make_window();} {}
1137 }
1138 Function {make_window()} {open
1139 } {
1140 Fl_Window channelstrip {open
1141 xywh {889 373 30 235} type Double
1142 code0 {o->position(this->x(),this->y());}
1143 class Fl_Group visible
1144 } {
1145 Fl_Group mixledleft {open
1146 xywh {2 92 4 132}
1147 class MixerLevelMeterUI
1148 } {}
1149 Fl_Group mixledright {open
1150 xywh {24 92 4 132}
1151 class MixerLevelMeterUI
1152 } {}
1153 Fl_Slider fader {
1154 callback {control->fadervalue(o->value());}
1155 image {images/fader.gif} xywh {6 92 18 128} type {Vert Knob} color 8 labelfont 1 labelsize 10 align 0 minimum 127 maximum 0 step 1 value 90
1156 code0 {o->clear_visible_focus();}
1157 }
1158 Fl_Button mix_mono {
1159 label MONO
1160 callback {control->mixmono(o->value());}
1161 xywh {0 68 30 15} type Toggle selection_color 3 labelsize 8
1162 code0 {o->clear_visible_focus();}
1163 }
1164 }
1165 }
1166 Function {~MasterChannelUI()} {open
1167 } {
1168 code {delete control;} {}
1169 }
1170}
1171
1172class MixerData {open
1173} {
1174 decl {MixerUI* parentui;} {}
1175 decl {friend class MixerControl;} {}
1176 decl {int eqon;} {}
1177 decl {float* mixermasterout;} {public
1178 }
1179 decl {double trackpeak[2];} {public
1180 }
1181 decl {double fadermult[2];} {public
1182 }
1183 decl {__uint32 samplerate;} {public
1184 }
1185 decl {int selectedchannel;} {public
1186 }
1187 decl {double fadervalue;} {public
1188 }
1189 decl {__uint32 delaybuffersam;} {public
1190 }
1191 decl {int bypass;} {}
1192}
1193
1194class MixerControl {open
1195} {
1196 decl {friend class MixerUI;} {}
1197 decl {MixerData* data;} {}
1198 Function {mix(int frames) /* <----------------------------------*/} {open
1199 } {
1200 code {int solo=0;
1201int trackon[24]; // 0=mute, 1=normal, 2=solo
1202MixerChannelControl* trackctl[24];
1203for (int tracknum=0;tracknum<24;tracknum++) {
1204 trackctl[tracknum]=parentui()->mixerchannel[tracknum]->control;
1205 trackon[tracknum]=1; // normal
1206 MixerChannelControl* track=trackctl[tracknum];
1207 if (track->issolo()!=0) {
1208 solo=1;
1209 trackon[tracknum]++;
1210 }
1211 if (track->ismute()!=0) {
1212 trackon[tracknum]--;
1213 }
1214 track->eq_enabled(data->eqon);
1215 track->pan_enabled(1-(parentui()->fader_master->control->mixmono()));
1216 track->bypass(data->bypass);
1217}
1218
1219stereosample sam;
1220for (int i=0;i<frames;i++) {
1221 float outleft=0;
1222 float outright=0;
1223
1224
1225 for (int j=0;j<24 /* tracks */;j++) {
1226 if (!(trackon[j]>solo)) continue;
1227 MixerChannelControl* track=trackctl[j];
1228
1229 track->getsample(&sam,i);
1230
1231 outleft+=sam.left;
1232 outright+=sam.right;
1233 }
1234 outleft*=parentui()->fader_master->control->getfadermult(0);
1235 outright*=parentui()->fader_master->control->getfadermult(1);
1236
1237 /* clipping */
1238 if (outleft>1) {
1239 outleft=1; }
1240 else {
1241 if (outleft<-1) outleft=-1;
1242 }
1243 if (outright>1) {
1244 outright=1;
1245 } else {
1246 if (outright<-1) outright=-1;
1247 }
1248
1249
1250 if (fabs(outleft) > parentui()->fader_master->control->trackpeak(0)) {
1251 parentui()->fader_master->control->trackpeak(0,fabs(outleft));
1252 }
1253 if (fabs(outright) > parentui()->fader_master->control->trackpeak(1)) {
1254 parentui()->fader_master->control->trackpeak(1,fabs(outright));
1255 }
1256
1257 /* / tape saturation emulation
1258 if (parentui()->tapesaton->value()==1)
1259 {
1260 int tapewidth=100;
1261 float myleft=0;
1262 float myright=0;
1263 for (int tapepos=0;tapepos<tapewidth;tapepos++)
1264 {
1265 float maxleft=.3+( ((rand()%32767)-16384)/(16384*5) );
1266 float maxright=.3+( ((rand()%32767)-16384)/(16384*5) );
1267 if (outleft>maxleft) {
1268 myleft+=maxleft;
1269 } else {
1270 myleft+=outleft;
1271 }
1272 if (outright>maxright) {
1273 myright+=maxright;
1274 } else {
1275 myright+=outright;
1276 }
1277 }
1278 outleft=myleft/tapewidth;
1279 outright=myright/tapewidth;
1280 } */
1281 data->mixermasterout[i*25+0]=outleft;
1282 data->mixermasterout[i*25+1]=outright;
1283}} {}
1284 }
1285 Function {init()} {open return_type void
1286 } {
1287 code {data->eqon=1;
1288data->mixermasterout=(float *)malloc(512000*sizeof(float));
1289data->parentui=NULL;
1290data->selectedchannel=0;
1291data->bypass=1;
1292
1293return;} {}
1294 }
1295 Function {MixerControl()} {} {
1296 code {data=new MixerData();
1297data->parentui=NULL;
1298data->samplerate=0;
1299init();} {}
1300 }
1301 Function {~MixerControl()} {} {
1302 code {free (data->mixermasterout);
1303
1304//delaybuffersize=maxreverbunits*maxreverbseconds*MAXSAMRATE;
1305//delaybuffer=(float *)malloc(sizeof(float)*delaybuffersize);
1306//if (delaybuffer==NULL) cout << " out of mem L" << endl;
1307//delaybuffersam=delaybuffersize;
1308//for (int i=0;i<delaybuffersize;i++)
1309//{
1310// delaybuffer[i]=0;
1311//}
1312delete data;} {}
1313 }
1314 Function {parentui(MixerUI* p_parentui)} {return_type void
1315 } {
1316 code {data->parentui=p_parentui;} {}
1317 }
1318 Function {parentui()} {return_type {MixerUI*}
1319 } {
1320 code {return data->parentui;} {}
1321 }
1322 Function {fadervalue(const double p_val)} {} {
1323 code {double lin;
1324if (p_val == 0) {
1325 lin=0;
1326} else {
1327 lin=pow(10,(p_val-90)/60);
1328}
1329data->fadermult[0]=lin;
1330data->fadermult[1]=lin;
1331data->fadervalue=p_val;
1332//faderarray[channel]=lin;
1333//mixmute[channel]->draw();
1334//mixfader[channel]->draw();
1335//mixled[channel]->draw();
1336//masterled[0]->draw();
1337//masterled[1]->draw();
1338parentui()->fader_master->fader->value(p_val);
1339parentui()->fader_master->redraw(); //this->redraw();*/} {}
1340 }
1341 Function {fadervalue()} {return_type double
1342 } {
1343 code {return data->fadervalue;} {}
1344 }
1345 Function {trackpeak(int lr)} {return_type double
1346 } {
1347 code {return data->trackpeak[lr];} {}
1348 }
1349 Function {trackpeak(int lr,double peakval)} {return_type void
1350 } {
1351 code {data->trackpeak[lr]=peakval;} {}
1352 }
1353 Function {masterout(int tracknum,int framenum)} {return_type float
1354 } {
1355 code {return data->mixermasterout[framenum*25+tracknum];} {}
1356 }
1357 Function {lin2dB(double lin)} {return_type double
1358 } {
1359 code {return log10(lin)*20.0;} {}
1360 }
1361 Function {dB2lin(double dB)} {return_type double
1362 } {
1363 code {return pow(10.0,dB/20.0);} {}
1364 }
1365 Function {selectedchannel(int channel_base0)} {return_type void
1366 } {
1367 code {data->selectedchannel=channel_base0;
1368for (int i=0;i<24;i++) {
1369 if (channel_base0!=i) {
1370 this->parentui()->mixerchannel[i]->control->channelselect(0);
1371 } else {
1372 this->parentui()->mixerchannel[i]->control->channelselect(1);
1373 }
1374}
1375MixerChannelControl* mixcontrol=this->parentui()->mixerchannel[channel_base0]->control;
1376
1377// reloading controls with their own value causes a redraw.
1378mixcontrol->eq_gain(0,mixcontrol->eq_gain(0));
1379mixcontrol->eq_gain(1,mixcontrol->eq_gain(1));
1380mixcontrol->eq_gain(2,mixcontrol->eq_gain(2));
1381mixcontrol->eq_gain(3,mixcontrol->eq_gain(3));
1382
1383mixcontrol->eq_freq(0,mixcontrol->eq_freq(0));
1384mixcontrol->eq_freq(1,mixcontrol->eq_freq(1));
1385mixcontrol->eq_freq(2,mixcontrol->eq_freq(2));
1386mixcontrol->eq_freq(3,mixcontrol->eq_freq(3));
1387
1388mixcontrol->eq_on(0,mixcontrol->eq_on(0));
1389mixcontrol->eq_on(1,mixcontrol->eq_on(1));
1390mixcontrol->eq_on(2,mixcontrol->eq_on(2));
1391mixcontrol->eq_on(3,mixcontrol->eq_on(3));} {}
1392 }
1393 Function {selectedchannel()} {return_type int
1394 } {
1395 code {return data->selectedchannel;} {}
1396 }
1397 Function {savemix(string* strfile)} {return_type {string*}
1398 } {
1399 code {fstream to_out(strfile->c_str(),ios::out);
1400if (to_out==NULL) {
1401 string *error=new string("");
1402 *error+="Cannot open mix file for writing.";
1403 return error;
1404}
1405
1406for (int i=0;i<24;i++) {
1407 MixerChannelControl* track=parentui()->mixerchannel[i]->control;
1408 to_out << "[Track="<<i+1<<"]" <<endl;
1409 to_out << "solo=" << track->solo() << endl;
1410 to_out << "mute=" << track->mute() << endl;
1411 to_out << "fader=" << track->fadervalue() << endl;
1412 to_out << "pan=" << track->panvalue() << endl;
1413
1414 for (int j=0;j<eqperchan;j++) {
1415 to_out << "eq_on[" << j << "]=" << track->eq_on(j) << endl;
1416 to_out << "eq_freq[" << j << "]=" << track->eq_freq(j) << endl;
1417 to_out << "eq_gain[" << j << "]=" << track->eq_gain(j) << endl;
1418 to_out << "eq_Q[" << j << "]=" << track->eq_Q(j) << endl;
1419
1420 }
1421}
1422to_out << "[Master]" << endl;
1423to_out << "eqon=" << eq_on() << endl;
1424to_out << "mono=" << parentui()->fader_master->control->mixmono() << endl;
1425to_out << "fader=" << parentui()->fader_master->control->fadervalue()<< endl;
1426
1427to_out.flush();
1428to_out.close();
1429return NULL;} {}
1430 }
1431 Function {savetrackmix(string* strfile,int base0track)} {return_type {string*}
1432 } {
1433 code {fstream to_out(strfile->c_str(),ios::out);
1434if (to_out==NULL) {
1435 string *error=new string("");
1436 *error+="Cannot open mix file for writing.";
1437 return error;
1438}
1439
1440int i=base0track;
1441
1442 MixerChannelControl* track=parentui()->mixerchannel[i]->control;
1443 to_out << "[Track="<<i+1<<"]" <<endl;
1444 to_out << "solo=" << track->solo() << endl;
1445 to_out << "mute=" << track->mute() << endl;
1446 to_out << "fader=" << track->fadervalue() << endl;
1447 to_out << "pan=" << track->panvalue() << endl;
1448
1449 for (int j=0;j<eqperchan;j++) {
1450 to_out << "eq_on[" << j << "]=" << track->eq_on(j) << endl;
1451 to_out << "eq_freq[" << j << "]=" << track->eq_freq(j) << endl;
1452 to_out << "eq_gain[" << j << "]=" << track->eq_gain(j) << endl;
1453 to_out << "eq_Q[" << j << "]=" << track->eq_Q(j) << endl;
1454
1455 }
1456
1457to_out.flush();
1458to_out.close();
1459return NULL;} {}
1460 }
1461 Function {loadmix(string* strfile)} {return_type {string*}
1462 } {
1463 code {fstream from_in(strfile->c_str(),ios::in);
1464if (from_in==NULL) {
1465 string *error=new string("");
1466 *error+="Cannot open mix file for writing.";
1467 return error;
1468}
1469string line;
1470int savechan=selectedchannel();
1471bool master=false;
1472while (!(from_in.eof()))
1473{
1474 getline(from_in,line);
1475 if (line=="") continue;
1476 if (line.substr(0,7)=="[Track=") {
1477 master=false;
1478 int ch=Convert::str2long(line.substr(7,2));
1479 this->selectedchannel(ch-1);
1480 continue;
1481 }
1482 MixerChannelControl* track=parentui()->mixerchannel[selectedchannel()]->control;
1483 if (line.substr(0,8)=="[Master]") {
1484 master=true;
1485 continue;
1486 }
1487 if (master) {
1488 if (line.substr(0,5)=="mono=") {
1489 parentui()->fader_master->control->mixmono(Convert::str2long(line.substr(5,1)));
1490 continue;
1491 }
1492 if (line.substr(0,5)=="eqon=") {
1493 this->eq_on(Convert::str2long(line.substr(5,1)));
1494 continue;
1495 }
1496 }
1497 if (line.substr(0,5)=="solo=") {
1498// mixsolo[this->selectedchannel]->value(Convert::str2long(line.substr(5,1)));
1499 track->solo(Convert::str2long(line.substr(5,1)));
1500 continue;
1501 }
1502 if (line.substr(0,5)=="mute=") {
1503// mixmute[this->selectedchannel]->value(Convert::str2long(line.substr(5,1)));
1504 track->mute(Convert::str2long(line.substr(5,1)));
1505 continue;
1506 }
1507 if (line.substr(0,4)=="pan=") {
1508 track->panvalue(Convert::str2dbl(line.substr(4,10)));
1509 continue;
1510 }
1511 if ((line.substr(0,8)=="eq_freq[")
1512 &&(line.substr(9,2)=="]="))
1513 {
1514 int whicheq=Convert::str2long(line.substr(8,1));
1515 double freq=Convert::str2dbl(line.substr(11,10));
1516 track->eq_freq(whicheq,freq);
1517 continue;
1518
1519 }
1520 if ((line.substr(0,8)=="eq_gain[")
1521 &&(line.substr(9,2)=="]="))
1522 {
1523 int whicheq=Convert::str2long(line.substr(8,1));
1524 double gain=Convert::str2dbl(line.substr(11,10));
1525 track->eq_gain(whicheq,gain);
1526 continue;
1527
1528 }
1529 if ((line.substr(0,5)=="eq_Q[")
1530 &&(line.substr(6,2)=="]="))
1531 {
1532 int whicheq=Convert::str2long(line.substr(5,1));
1533 double Q=Convert::str2dbl(line.substr(8,10));
1534 track->eq_Q(whicheq,Q);
1535 continue;
1536 }
1537 if ((line.substr(0,6)=="eq_on[")
1538 &&(line.substr(7,2)=="]="))
1539 {
1540 int whicheq=Convert::str2long(line.substr(6,1));
1541 int onoff=Convert::str2long(line.substr(9,10));
1542 track->eq_on(whicheq,onoff);
1543 continue;
1544 }
1545 if (line.substr(0,6)=="fader=") {
1546 if (master) {
1547 this->fadervalue(Convert::str2dbl(line.substr(6,10)));
1548 }
1549 else
1550 {
1551 track->fadervalue(Convert::str2dbl(line.substr(6,10)));
1552
1553 }
1554
1555 continue;
1556 }
1557
1558 cout << "Unknown setting, ignoring: " << line << endl;
1559}
1560this->selectedchannel(savechan);
1561from_in.close();
1562
1563return NULL;} {}
1564 }
1565 Function {loadtrackmix(string* strfile,int base0track)} {open return_type {string*}
1566 } {
1567 code {fstream from_in(strfile->c_str(),ios::in);
1568if (from_in==NULL) {
1569 string *error=new string("");
1570 *error+="Cannot open mix file for writing.";
1571 return error;
1572}
1573string line;
1574int savechan=base0track;
1575while (!(from_in.eof()))
1576{
1577 getline(from_in,line);
1578 if (line=="") continue;
1579 if (line.substr(0,7)=="[Track=") {
1580 continue;
1581 }
1582 MixerChannelControl* track=parentui()->mixerchannel[selectedchannel()]->control;
1583 if (line.substr(0,5)=="solo=") {
1584// mixsolo[this->selectedchannel]->value(Convert::str2long(line.substr(5,1)));
1585 track->solo(Convert::str2long(line.substr(5,1)));
1586 continue;
1587 }
1588 if (line.substr(0,5)=="mute=") {
1589// mixmute[this->selectedchannel]->value(Convert::str2long(line.substr(5,1)));
1590 track->mute(Convert::str2long(line.substr(5,1)));
1591 continue;
1592 }
1593 if (line.substr(0,4)=="pan=") {
1594 track->panvalue(Convert::str2dbl(line.substr(4,10)));
1595 continue;
1596 }
1597 if ((line.substr(0,8)=="eq_freq[")
1598 &&(line.substr(9,2)=="]="))
1599 {
1600 int whicheq=Convert::str2long(line.substr(8,1));
1601 double freq=Convert::str2dbl(line.substr(11,10));
1602 track->eq_freq(whicheq,freq);
1603 continue;
1604
1605 }
1606 if ((line.substr(0,8)=="eq_gain[")
1607 &&(line.substr(9,2)=="]="))
1608 {
1609 int whicheq=Convert::str2long(line.substr(8,1));
1610 double gain=Convert::str2dbl(line.substr(11,10));
1611 track->eq_gain(whicheq,gain);
1612 continue;
1613
1614 }
1615 if ((line.substr(0,5)=="eq_Q[")
1616 &&(line.substr(6,2)=="]="))
1617 {
1618 int whicheq=Convert::str2long(line.substr(5,1));
1619 double Q=Convert::str2dbl(line.substr(8,10));
1620 track->eq_Q(whicheq,Q);
1621 continue;
1622 }
1623 if ((line.substr(0,6)=="eq_on[")
1624 &&(line.substr(7,2)=="]="))
1625 {
1626 int whicheq=Convert::str2long(line.substr(6,1));
1627 int onoff=Convert::str2long(line.substr(9,10));
1628 track->eq_on(whicheq,onoff);
1629 continue;
1630 }
1631 if (line.substr(0,6)=="fader=") {
1632 track->fadervalue(Convert::str2dbl(line.substr(6,10)));
1633 continue;
1634 }
1635
1636 cout << "Unknown setting, ignoring: " << line << endl;
1637}
1638this->selectedchannel(savechan);
1639from_in.close();
1640
1641return NULL;} {}
1642 }
1643 Function {updatemeters()} {open
1644 } {
1645 code {MixerUI* pui=this->parentui();
1646if (pui==NULL) return;
1647for (int tracknum=0;tracknum<24;tracknum++) {
1648 pui->mixerchannel[tracknum]->control->updatemeters();
1649}
1650// update and redraw meterlevels object
1651pui->fader_master->control->updatemeters();} {}
1652 }
1653 Function {samplerate(__uint32 p_samplerate)} {open return_type void
1654 } {
1655 code {data->samplerate=p_samplerate;
1656
1657MixerUI* pui=this->parentui();
1658if (pui==NULL) return;
1659for (int tracknum=0;tracknum<24;tracknum++) {
1660 pui->mixerchannel[tracknum]->control->samplerate(p_samplerate);
1661}} {}
1662 }
1663 Function {samplerate()} {open return_type __uint32
1664 } {
1665 code {return data->samplerate;} {}
1666 }
1667 Function {eq_on(int onoff)} {return_type void
1668 } {
1669 code {data->eqon=onoff;
1670parentui()->eqon->value(onoff);
1671parentui()->eqon->redraw();} {}
1672 }
1673 Function {eq_on()} {open return_type int
1674 } {
1675 code {return data->eqon;} {}
1676 }
1677 Function {bypass()} {return_type int
1678 } {
1679 code {return data->bypass;} {}
1680 }
1681 Function {bypass(int onoff)} {return_type void
1682 } {
1683 code {data->bypass=onoff;
1684parentui()->bypass->value(onoff);
1685parentui()->bypass->redraw();} {}
1686 }
1687}
1688
1689class MixerUI {open : {public Fl_Group}
1690} {
1691 decl {MixerControl* control;} {public
1692 }
1693 decl {MixerChannelUI* mixerchannel[24];} {public
1694 }
1695 decl {/* ===MIXER UI stuff ===================================================== */} {}
1696 decl {HD24UserInterface* ui;} {}
1697 decl {Fl_Window* window} {}
1698 Function {make_window() /*<-----------------------------------*/} {open
1699 } {
1700 Fl_Window mixgroup {open
1701 xywh {41 257 605 460} type Double
1702 code0 {o->position(this->x(),this->y());}
1703 class Fl_Group visible
1704 } {
1705 Fl_Group resources {open
1706 xywh {70 52 150 98} hide deactivate
1707 } {
1708 Fl_Button button_small_up {
1709 tooltip arm image {images/button_small.gif} xywh {75 52 145 13} deactivate
1710 }
1711 Fl_Button button_small_dn {
1712 tooltip arm image {images/button_small_dn.gif} xywh {70 52 5 13} deactivate
1713 }
1714 }
1715 Fl_Group mixergroup {open
1716 xywh {-9 0 643 463}
1717 code0 {init_gui();}
1718 } {
1719 Fl_Box {} {
1720 xywh {-9 354 625 109} box BORDER_BOX
1721 }
1722 Fl_Box {} {
1723 label S
1724 tooltip Solo xywh {5 269 10 14} color 1 selection_color 1 labelfont 1 labelsize 12
1725 }
1726 Fl_Box {} {
1727 label M
1728 tooltip Mute xywh {5 286 10 14} color 1 selection_color 1 labelfont 1 labelsize 12
1729 }
1730 Fl_Group channelgroup {open selected
1731 xywh {0 210 584 250} deactivate
1732 } {
1733 Fl_Group mixerchannel1 {open
1734 xywh {17 221 20 231} box BORDER_BOX color 7
1735 code0 {mixerchannel[0]=o;}
1736 class MixerChannelUI
1737 } {}
1738 Fl_Group mixerchannel2 {open
1739 xywh {37 221 20 231} box BORDER_BOX color 7
1740 code0 {mixerchannel[1]=o;}
1741 class MixerChannelUI
1742 } {}
1743 Fl_Group mixerchannel3 {open
1744 xywh {57 221 20 231} box BORDER_BOX color 7
1745 code0 {mixerchannel[2]=o;}
1746 class MixerChannelUI
1747 } {}
1748 Fl_Group mixerchannel4 {open
1749 xywh {77 221 20 231} box BORDER_BOX color 7
1750 code0 {mixerchannel[3]=o;}
1751 class MixerChannelUI
1752 } {}
1753 Fl_Group mixerchannel5 {open
1754 xywh {97 221 20 231} box BORDER_BOX color 7
1755 code0 {mixerchannel[4]=o;}
1756 class MixerChannelUI
1757 } {}
1758 Fl_Group mixerchannel6 {open
1759 xywh {117 221 20 231} box BORDER_BOX color 7
1760 code0 {mixerchannel[5]=o;}
1761 class MixerChannelUI
1762 } {}
1763 Fl_Group mixerchannel7 {open
1764 xywh {137 221 20 231} box BORDER_BOX color 7
1765 code0 {mixerchannel[6]=o;}
1766 class MixerChannelUI
1767 } {}
1768 Fl_Group mixerchannel8 {open
1769 xywh {157 221 20 231} box BORDER_BOX color 7
1770 code0 {mixerchannel[7]=o;}
1771 class MixerChannelUI
1772 } {}
1773 Fl_Group mixerchannel9 {open
1774 xywh {177 221 20 231} box BORDER_BOX color 7
1775 code0 {mixerchannel[8]=o;}
1776 class MixerChannelUI
1777 } {}
1778 Fl_Group mixerchannel10 {open
1779 xywh {197 221 20 231} box BORDER_BOX color 7
1780 code0 {mixerchannel[9]=o;}
1781 class MixerChannelUI
1782 } {}
1783 Fl_Group mixerchannel11 {open
1784 xywh {217 221 20 231} box BORDER_BOX color 7
1785 code0 {mixerchannel[10]=o;}
1786 class MixerChannelUI
1787 } {}
1788 Fl_Group mixerchannel12 {open
1789 xywh {237 221 20 231} box BORDER_BOX color 7
1790 code0 {mixerchannel[11]=o;}
1791 class MixerChannelUI
1792 } {}
1793 Fl_Group mixerchannel13 {open
1794 xywh {257 221 20 231} box BORDER_BOX color 7
1795 code0 {mixerchannel[12]=o;}
1796 class MixerChannelUI
1797 } {}
1798 Fl_Group mixerchannel14 {open
1799 xywh {277 221 20 231} box BORDER_BOX color 7
1800 code0 {mixerchannel[13]=o;}
1801 class MixerChannelUI
1802 } {}
1803 Fl_Group mixerchannel15 {open
1804 xywh {297 221 20 231} box BORDER_BOX color 7
1805 code0 {mixerchannel[14]=o;}
1806 class MixerChannelUI
1807 } {}
1808 Fl_Group mixerchannel16 {open
1809 xywh {317 221 20 231} box BORDER_BOX color 7
1810 code0 {mixerchannel[15]=o;}
1811 class MixerChannelUI
1812 } {}
1813 Fl_Group mixerchannel17 {open
1814 xywh {337 221 20 231} box BORDER_BOX color 7
1815 code0 {mixerchannel[16]=o;}
1816 class MixerChannelUI
1817 } {}
1818 Fl_Group mixerchannel18 {open
1819 xywh {357 221 20 231} box BORDER_BOX color 7
1820 code0 {mixerchannel[17]=o;}
1821 class MixerChannelUI
1822 } {}
1823 Fl_Group mixerchannel19 {open
1824 xywh {377 221 20 231} box BORDER_BOX color 7
1825 code0 {mixerchannel[18]=o;}
1826 class MixerChannelUI
1827 } {}
1828 Fl_Group mixerchannel20 {open
1829 xywh {397 221 20 231} box BORDER_BOX color 7
1830 code0 {mixerchannel[19]=o;}
1831 class MixerChannelUI
1832 } {}
1833 Fl_Group mixerchannel21 {open
1834 xywh {417 221 20 231} box BORDER_BOX color 7
1835 code0 {mixerchannel[20]=o;}
1836 class MixerChannelUI
1837 } {}
1838 Fl_Group mixerchannel22 {open
1839 xywh {437 221 20 231} box BORDER_BOX color 7
1840 code0 {mixerchannel[21]=o;}
1841 class MixerChannelUI
1842 } {}
1843 Fl_Group mixerchannel23 {open
1844 xywh {457 221 20 231} box BORDER_BOX color 7
1845 code0 {mixerchannel[22]=o;}
1846 class MixerChannelUI
1847 } {}
1848 Fl_Group mixerchannel24 {open
1849 xywh {477 221 20 231} box BORDER_BOX color 7
1850 code0 {mixerchannel[23]=o;}
1851 class MixerChannelUI
1852 } {}
1853 }
1854 Fl_Tabs {} {open
1855 xywh {10 25 435 195}
1856 } {
1857 Fl_Group eqgroup {
1858 label EQ open
1859 xywh {10 45 435 175} labelfont 1 labelsize 10 deactivate
1860 } {
1861 Fl_Dial gain1 {
1862 callback {mixerchannel[control->selectedchannel()]->control->eq_gain(0,o->value());}
1863 xywh {20 159 30 30} minimum -20 maximum 20 step 10
1864 class WidgetPDial
1865 }
1866 Fl_Dial gain2 {
1867 callback {mixerchannel[control->selectedchannel()]->control->eq_gain(1,o->value());}
1868 xywh {65 159 30 30} minimum -20 maximum 20 step 10
1869 class WidgetPDial
1870 }
1871 Fl_Dial gain3 {
1872 callback {mixerchannel[control->selectedchannel()]->control->eq_gain(2,o->value());}
1873 xywh {110 159 30 30} minimum -20 maximum 20 step 10
1874 class WidgetPDial
1875 }
1876 Fl_Dial gain4 {
1877 label GAIN
1878 callback {mixerchannel[control->selectedchannel()]->control->eq_gain(3,o->value());}
1879 xywh {155 159 30 30} labelfont 1 labelsize 12 align 8 minimum -20 maximum 20 step 10
1880 class WidgetPDial
1881 }
1882 Fl_Dial freq1 {
1883 callback {mixerchannel[control->selectedchannel()]->control->eq_freq(0,o->value());}
1884 xywh {20 125 30 30} minimum 20 maximum 200 step 10 value 100
1885 class WidgetPDial
1886 }
1887 Fl_Dial freq2 {
1888 callback {mixerchannel[control->selectedchannel()]->control->eq_freq(1,o->value());}
1889 xywh {65 125 30 30} minimum 150 maximum 1000 step 20 value 600
1890 class WidgetPDial
1891 }
1892 Fl_Dial freq3 {
1893 callback {mixerchannel[control->selectedchannel()]->control->eq_freq(2,o->value());}
1894 xywh {110 125 30 30} minimum 800 maximum 3000 step 10 value 1600
1895 class WidgetPDial
1896 }
1897 Fl_Dial freq4 {
1898 label FREQ
1899 callback {mixerchannel[control->selectedchannel()]->control->eq_freq(3,o->value());}
1900 xywh {155 125 30 30} labelfont 1 labelsize 12 align 8 minimum 3000 maximum 12000 step 1 value 6000
1901 class WidgetPDial
1902 }
1903 Fl_Check_Button eqon1 {
1904 label { Low}
1905 callback {mixerchannel[control->selectedchannel()]->control->eq_on(0,o->value());}
1906 xywh {15 95 20 15} down_box DOWN_BOX value 1 labelsize 12 align 5
1907 }
1908 Fl_Check_Button eqon2 {
1909 label {Lo/Mid}
1910 callback {mixerchannel[control->selectedchannel()]->control->eq_on(1,o->value());}
1911 xywh {60 95 20 15} down_box DOWN_BOX value 1 labelsize 12 align 5
1912 }
1913 Fl_Check_Button eqon3 {
1914 label {Hi/Mid}
1915 callback {mixerchannel[control->selectedchannel()]->control->eq_on(2,o->value());}
1916 xywh {105 95 20 15} down_box DOWN_BOX value 1 labelsize 12 align 5
1917 }
1918 Fl_Check_Button eqon4 {
1919 label High
1920 callback {mixerchannel[control->selectedchannel()]->control->eq_on(3,o->value());}
1921 xywh {150 95 20 15} down_box DOWN_BOX value 1 labelsize 12 align 5
1922 }
1923 Fl_Check_Button eqon {
1924 label {Enable equalizer (all channels)}
1925 callback {control->eq_on(o->value());}
1926 xywh {15 50 205 20} down_box DOWN_BOX value 1 labelsize 12
1927 }
1928 Fl_Check_Button reverbon {
1929 label {Reverb (not yet available)}
1930 callback {//mixerchannel[control->selectedchannel()]->control->reverb_on(o->value());}
1931 xywh {240 95 175 15} down_box DOWN_BOX value 1 labelsize 12 deactivate
1932 }
1933 Fl_Check_Button tapesaton {
1934 label {Tape emulation}
1935 callback {//mixerchannel[control->selectedchannel()]->control->reverb_on(o->value());}
1936 xywh {240 80 175 15} down_box DOWN_BOX value 1 labelsize 12 deactivate
1937 }
1938 Fl_Output dispgain1 {
1939 xywh {15 190 40 15} box FLAT_BOX color 53 labelsize 10 align 0 textsize 10
1940 }
1941 Fl_Output dispgain2 {
1942 xywh {60 190 40 15} box FLAT_BOX color 53 labelsize 10 align 0 textsize 10
1943 }
1944 Fl_Output dispgain3 {
1945 xywh {105 190 40 15} box FLAT_BOX color 53 labelsize 10 align 0 textsize 10
1946 }
1947 Fl_Output dispgain4 {
1948 xywh {150 190 40 15} box FLAT_BOX color 53 labelsize 10 align 0 textsize 10
1949 }
1950 Fl_Output dispfreq1 {
1951 xywh {15 109 40 15} box FLAT_BOX color 53 labelsize 10 align 0 textsize 10
1952 }
1953 Fl_Output dispfreq2 {
1954 xywh {60 109 40 15} box FLAT_BOX color 53 labelsize 10 align 0 textsize 10
1955 }
1956 Fl_Output dispfreq3 {
1957 xywh {105 109 40 15} box FLAT_BOX color 53 labelsize 10 align 0 textsize 10
1958 }
1959 Fl_Output dispfreq4 {
1960 xywh {150 109 40 15} box FLAT_BOX color 53 labelsize 10 align 0 textsize 10
1961 }
1962 }
1963 Fl_Tabs {} {
1964 label AUX
1965 xywh {10 45 330 175} labelfont 1 labelsize 10 hide
1966 } {}
1967 }
1968 Fl_Button bypass {
1969 label {Bypass Mixer}
1970 callback {control->bypass(o->value());
1971
1972switch (o->value())
1973{
1974 case 0:
1975 eqgroup->activate();
1976 channelgroup->activate();
1977 break;
1978 case 1:
1979 eqgroup->deactivate();
1980 channelgroup->deactivate();
1981 break;
1982
1983}}
1984 tooltip Solo xywh {10 0 90 20} type Toggle value 1 selection_color 1 labelsize 12
1985 }
1986 Fl_Group fader_master {open
1987 xywh {574 221 20 231} box BORDER_BOX color 7
1988 class MasterChannelUI
1989 } {}
1990 }
1991 }
1992 }
1993 Function {MixerUI(int a,int b,int c,int d):Fl_Group(a,b,c,d,NULL)} {open
1994 } {
1995 code {control=new MixerControl();
1996control->parentui(this);
1997this->window=(Fl_Window*)(this->make_window());} {}
1998 }
1999 Function {~MixerUI()} {open
2000 } {
2001 code {delete control;} {}
2002 }
2003 Function {init_gui()} {open
2004 } {
2005 code {int starty=(mixerchannel[0]->y());
2006int startx=(mixerchannel[0]->x());
2007fader_master->clear_visible_focus();
2008for (int i=1;i<=24;i++)
2009{
2010 if (i==1) {
2011 mixerchannel[i-1]->control->channelselect(1);
2012 }
2013 mixerchannel[i-1]->position(startx+((i-1)*23),starty);
2014// mixerchannel[i-1]->size(mixerchannel[0]->w(),mixerchannel[0]->h());
2015 mixerchannel[i-1]->clear_visible_focus();
2016 mixerchannel[i-1]->control->channel_number(i);
2017
2018 mixerchannel[i-1]->control->parentmixercontrol(this->control);
2019
2020 // set values on freq/gain displays:
2021 mixerchannel[i-1]->control->eq_freq(0,mixerchannel[i-1]->control->eq_freq(0));
2022 mixerchannel[i-1]->control->eq_freq(1,mixerchannel[i-1]->control->eq_freq(1));
2023 mixerchannel[i-1]->control->eq_freq(2,mixerchannel[i-1]->control->eq_freq(2));
2024 mixerchannel[i-1]->control->eq_freq(3,mixerchannel[i-1]->control->eq_freq(3));
2025
2026 mixerchannel[i-1]->control->eq_gain(0,mixerchannel[i-1]->control->eq_gain(0));
2027 mixerchannel[i-1]->control->eq_gain(1,mixerchannel[i-1]->control->eq_gain(1));
2028 mixerchannel[i-1]->control->eq_gain(2,mixerchannel[i-1]->control->eq_gain(2));
2029 mixerchannel[i-1]->control->eq_gain(3,mixerchannel[i-1]->control->eq_gain(3));
2030
2031
2032// eq_freq[(i-1)*eqperchan+0]=100;
2033// eq_freq[(i-1)*eqperchan+1]=600;
2034// eq_freq[(i-1)*eqperchan+2]=1600;
2035// eq_freq[(i-1)*eqperchan+3]=6000;
2036// eq_on[(i-1)*eqperchan+0]=eqon1->value();
2037// eq_on[(i-1)*eqperchan+1]=eqon2->value();
2038// eq_on[(i-1)*eqperchan+2]=eqon3->value();
2039// eq_on[(i-1)*eqperchan+3]=eqon4->value();
2040// for (int j=0;j<4;j++) {
2041// eq_gain[(i-1)*eqperchan+j]=0;
2042//
2043// eq_Q[(i-1)*eqperchan+j]=1;
2044// eq_type[(i-1)*eqperchan+j]=7;
2045// }
2046 mixerchannel[i-1]->clear_visible_focus();
2047// mixsolo[i-1]->position(8+(startx)+((i-1)*23),mixsolo[i-1]->y());
2048// mixsolo[i-1]->size(mixsolo[0]->w(),mixsolo[0]->h());
2049// mixsolo[i-1]->up_image(mixsolo[0]->up_image());
2050// mixsolo[i-1]->down_image(mixsolo[0]->down_image());
2051
2052// mixmute[i-1]->position(mixsolo[i-1]->x(),mixmute[i-1]->y());
2053// mixmute[i-1]->size(mixmute[0]->w(),mixmute[0]->h());
2054// mixmute[i-1]->up_image(mixmute[0]->up_image());
2055// mixmute[i-1]->down_image(mixmute[0]->down_image());
2056
2057// mixfader[i-1]->position(mixsolo[i-1]->x(),mixfader[i-1]->y());
2058// mixfader[i-1]->size(mixfader[0]->w(),mixfader[0]->h());
2059
2060// mixchsel[i-1]->position(mixsolo[i-1]->x(),mixchsel[i-1]->y());
2061// mixpan[i-1]->position(mixsolo[i-1]->x(),mixpan[i-1]->y());
2062// mixled[i-1]->position(mixfader[i-1]->x()+17,mixfader[0]->y());
2063 mixerchannel[i-1]->control->fadervalue(90);
2064}
2065
2066//masterled[0]->position(fader_master->x()-2,fader_master->y());
2067//masterled[1]->position(fader_master->x()+17,fader_master->y());
2068fader_master->control->fadervalue(90);
2069//this->selectedchannel(0);} {}
2070 }
2071 Function {set_ui(HD24UserInterface* p_ui)} {open return_type void
2072 } {
2073 code {this->ui=p_ui;} {}
2074 }
2075 Function {loadfromfile()} {open return_type void
2076 } {
2077 code {string* mixdir=hd24utils::getlastdir("mixdir");
2078
2079Fl_Native_File_Chooser chooser;
2080chooser.directory(mixdir->c_str());
2081delete mixdir;
2082
2083chooser.title("Select a mix to load\\0");
2084chooser.type(Fl_Native_File_Chooser::BROWSE_FILE);
2085chooser.filter("Mixer settings\\t*.{mix}\\0");
2086//chooser.preview(0);
2087switch (chooser.show()) {
2088 case -1: break; //error
2089 case 1: break; //cancel
2090 default:
2091 if (chooser.filename()) {
2092 string* cfilename=new string(chooser.filename());
2093
2094 //cout << "filename = " << *strfile << endl;
2095 string* fpath=new string("");
2096 *fpath+=cfilename->substr(0,strlen(cfilename->c_str())-strlen(fl_filename_name(cfilename->c_str())));
2097 hd24utils::setlastdir("mixdir",fpath->c_str());
2098 control->loadmix(cfilename);
2099 delete fpath;
2100 delete cfilename;
2101 }
2102 break;
2103}} {}
2104 }
2105 Function {savetofile()} {open return_type void
2106 } {
2107 code {string* mixdir=new string("");
2108*mixdir+=*(hd24utils::getlastdir("mixdir"));
2109
2110Fl_Native_File_Chooser chooser;
2111chooser.filter("Mix files\\t*.mix");
2112chooser.title("Save mixer settings to file");
2113chooser.directory(mixdir->c_str());
2114chooser.options(Fl_Native_File_Chooser::NEW_FOLDER);
2115chooser.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
2116
2117switch (chooser.show()) {
2118 case -1: break; //error
2119 case 1: break; //cancel
2120 default:
2121 // save header to chooser.filename()
2122
2123 bool bFileexists=false;
2124 if (bFileexists) {
2125 bool choice=ui->confirm(
2126 "A file with this name already exists. Do you wish to overwrite it?"
2127 );
2128 if (!(choice)) return;
2129 }
2130 string* strfile=new string(chooser.filename());
2131 //cout << "filename = " << *strfile << endl;
2132 string* fpath=new string("");
2133 *fpath+=strfile->substr(0,strlen(strfile->c_str())-strlen(fl_filename_name(strfile->c_str())));
2134 hd24utils::setlastdir("mixdir",fpath->c_str());
2135
2136 string* anyerrors=control->savemix(strfile);
2137
2138 delete strfile;
2139 delete fpath;
2140 if (anyerrors==NULL) {
2141 fl_message("Mix file saved successfully.");
2142 } else {
2143 delete anyerrors;
2144 fl_message("Could not write mix file. Access denied? Disk full?");
2145 }
2146 break;
2147}
2148delete mixdir;} {}
2149 }
2150 Function {loadtrackmixfromfile()} {open return_type void
2151 } {
2152 code {string* mixdir=hd24utils::getlastdir("mixdir");
2153
2154Fl_Native_File_Chooser chooser;
2155chooser.directory(mixdir->c_str());
2156delete mixdir;
2157
2158chooser.title("Select a mix to load\\0");
2159chooser.type(Fl_Native_File_Chooser::BROWSE_FILE);
2160chooser.filter("Mixer settings\\t*.{mix}\\0");
2161//chooser.preview(0);
2162switch (chooser.show()) {
2163 case -1: break; //error
2164 case 1: break; //cancel
2165 default:
2166 if (chooser.filename()) {
2167 string* cfilename=new string(chooser.filename());
2168
2169 //cout << "filename = " << *strfile << endl;
2170 string* fpath=new string("");
2171 *fpath+=cfilename->substr(0,strlen(cfilename->c_str())-strlen(fl_filename_name(cfilename->c_str())));
2172 hd24utils::setlastdir("mixdir",fpath->c_str());
2173 control->loadtrackmix(cfilename,control->selectedchannel());
2174 delete fpath;
2175 delete cfilename;
2176 }
2177 break;
2178}} {}
2179 }
2180 Function {savetrackmixtofile()} {open return_type void
2181 } {
2182 code {string* mixdir=new string("");
2183*mixdir+=*(hd24utils::getlastdir("mixdir"));
2184
2185Fl_Native_File_Chooser chooser;
2186chooser.filter("Mix files\\t*.mix");
2187chooser.title("Save mixer settings to file");
2188chooser.directory(mixdir->c_str());
2189chooser.options(Fl_Native_File_Chooser::NEW_FOLDER);
2190chooser.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);
2191
2192switch (chooser.show()) {
2193 case -1: break; //error
2194 case 1: break; //cancel
2195 default:
2196 // save header to chooser.filename()
2197
2198 bool bFileexists=false;
2199 if (bFileexists) {
2200 bool choice=ui->confirm(
2201 "A file with this name already exists. Do you wish to overwrite it?"
2202 );
2203 if (!(choice)) return;
2204 }
2205 string* strfile=new string(chooser.filename());
2206 //cout << "filename = " << *strfile << endl;
2207 string* fpath=new string("");
2208 *fpath+=strfile->substr(0,strlen(strfile->c_str())-strlen(fl_filename_name(strfile->c_str())));
2209 hd24utils::setlastdir("mixdir",fpath->c_str());
2210
2211 string* anyerrors=control->savetrackmix(strfile,control->selectedchannel());
2212
2213 delete strfile;
2214 if (anyerrors==NULL) {
2215 fl_message("Mix file saved successfully.");
2216 } else {
2217 delete anyerrors;
2218 fl_message("Could not write mix file. Access denied? Disk full?");
2219 }
2220 delete fpath;
2221 break;
2222}
2223delete mixdir;} {}
2224 }
2225}
diff --git a/src/frontend/ui_recorder.fl b/src/frontend/ui_recorder.fl
new file mode 100644
index 0000000..f650f5f
--- /dev/null
+++ b/src/frontend/ui_recorder.fl
@@ -0,0 +1,3639 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0109
3header_name {.h}
4code_name {.cxx}
5decl {\#define RECORDERDEBUG 0} {public
6}
7
8decl {\#define MAXSAMRATE 48000} {public
9}
10
11decl {\#define AUDIOLIB_PORTAUDIO 1} {public
12}
13
14decl {\#define AUDIOLIB_JACK 2} {public
15}
16
17decl {\#define AUDIOLIB_SNDFILE 3} {public
18}
19
20decl {\#define Pi2 (2*3.1415926535897)} {public
21}
22
23decl {\#include <config.h>} {public
24}
25
26decl {\#include <string>} {public
27}
28
29decl {\#include <vector>} {public
30}
31
32decl {\#include <soundlibs.h>} {public
33}
34
35decl {\#include <iostream>} {public
36}
37
38decl {\#include <fstream>} {public
39}
40
41decl {\#include <FL/FLTKstuff.H>} {public
42}
43
44decl {\#include <FL/filename.H>} {public
45}
46
47decl {\#include <convertlib.h>} {public
48}
49
50decl {\#include <time.h>} {public
51}
52
53decl {\#include <math.h>} {public
54}
55
56decl {\#include <hd24fs.h>} {public
57}
58
59decl {\#include <ui_hd24connect.h>} {public
60}
61
62decl {\#include <ui_mixer.h>} {public
63}
64
65decl {class MixerControl;} {public
66}
67
68decl {\#include <sharedlibs.h>} {public
69}
70
71decl {class RecorderChannelData;} {public
72}
73
74decl {class RecorderChannelControl;} {public
75}
76
77decl {class RecorderChannelUI;} {public
78}
79
80decl {class RecorderData;} {public
81}
82
83decl {class RecorderControl;} {public
84}
85
86decl {class RecorderUI;} {public
87}
88
89class ScrubWheel {: {public Fl_Roller}
90} {
91 decl {int myval;} {}
92 decl {RecorderUI* ui;} {}
93 decl {int lastx;} {}
94 Function {handle(int e)} {open return_type int
95 } {
96 code {/*char *fltk_eventnames[] =
97{
98 "FL_NO_EVENT",
99 "FL_PUSH",
100 "FL_RELEASE",
101 "FL_ENTER",
102 "FL_LEAVE",
103 "FL_DRAG",
104 "FL_FOCUS",
105 "FL_UNFOCUS",
106 "FL_KEYDOWN",
107 "FL_KEYUP",
108 "FL_CLOSE",
109 "FL_MOVE",
110 "FL_SHORTCUT",
111 "FL_DEACTIVATE",
112 "FL_ACTIVATE",
113 "FL_HIDE",
114 "FL_SHOW",
115 "FL_PASTE",
116 "FL_SELECTIONCLEAR",
117 "FL_MOUSEWHEEL",
118 "FL_DND_ENTER",
119 "FL_DND_DRAG",
120 "FL_DND_LEAVE",
121 "FL_DND_RELEASE",
122};
123
124*/
125if (e==FL_DRAG) {
126 myval=Fl::event_x()-lastx;
127 RecorderControl::button_scrub_call(myval,this->ui->control);
128}
129lastx=Fl::event_x();
130return 1;} {}
131 }
132 Function {ScrubWheel(int a,int b,int c,int d,const char* e):Fl_Roller(a,b,c,d,e)} {open
133 } {
134 code {myval=0;} {}
135 }
136 Function {draw()} {open
137 } {
138 code {//draw goes here
139return Fl_Roller::draw();} {}
140 }
141 Function {value()} {open return_type int
142 } {
143 code {return this->myval;} {}
144 }
145 Function {value(int newval)} {open return_type int
146 } {
147 code {int oldval=this->myval;
148this->myval=newval; // not very useful but whatever
149return oldval;} {}
150 }
151 Function {setui(RecorderUI* p_ui)} {open
152 } {
153 code {this->ui=p_ui;} {}
154 }
155}
156
157class AudioSystem {open
158} {
159 decl {AudioStorage* tape;} {}
160 decl {__uint32 samrate;} {public
161 }
162 decl {bool closingdown;} {public
163 }
164 decl {MixerControl* mixercontrol;} {}
165 decl {RecorderControl* recorder;} {}
166 decl {PortAudioWrapper* portaudio;} {public
167 }
168 decl {SoundFileWrapper* soundfile;} {public
169 }
170 decl {JackWrapper* libjack;} {}
171 decl {PaStreamParameters* inputParameters;} {}
172 decl {PaStreamParameters* outputParameters;} {}
173 decl {PaStream* portaudiostream;} {}
174 decl {jack_client_t *jackclient;} {}
175 decl {__uint32 jackrate;} {}
176 decl {__uint32 portaudiooffset;} {public
177 }
178 decl {int as_initialized;} {}
179 decl {int portaudio_initialized;} {}
180 decl {int jack_initialized;} {}
181 decl {int as_looppos;} {}
182 decl {bool as_mustloop;} {}
183 decl {jack_port_t *output_port[24];} {}
184 decl {jack_port_t *output_master[2];} {}
185 decl {jack_port_t *input_port[24];} {}
186 decl {long* mtsample;} {}
187 decl {bool havestreamtime;} {}
188 decl {__sint64 streamtime;} {public
189 }
190 Function {AudioSystem(RecorderControl* rec)} {open
191 } {
192 code {\#if (RECORDERDEBUG==1)
193cout << "AudioSystem::AudioSystem()" << endl;
194\#endif
195initvars(rec);} {}
196 }
197 Function {initvars(RecorderControl* rec)} {open return_type void
198 } {
199 code {this->tape=NULL;
200this->samrate=0;
201this->closingdown=false;
202this->mixercontrol=NULL;
203this->recorder=rec;
204this->portaudio=NULL;
205this->soundfile=NULL;
206this->libjack=NULL;
207this->jackclient=NULL;
208this->portaudiostream=NULL;
209this->portaudio_initialized=0;
210this->as_initialized=false;
211this->jack_initialized=false;
212this->as_looppos=0;
213this->as_mustloop=false;
214this->inputParameters=NULL;
215this->outputParameters=NULL;
216this->inputParameters=new PaStreamParameters;
217this->outputParameters=new PaStreamParameters;
218this->mtsample=NULL;
219for (int i=0;i<24;i++) {
220 this->output_port[i]=NULL;
221 this->input_port[i]=NULL;
222}
223this->output_master[0]=NULL;
224this->output_master[1]=NULL;
225this->havestreamtime=false;} {}
226 }
227 Function {currentlocation(__uint32 newpos)} {open return_type void
228 } {
229 code {if (tape==NULL) return;
230tape->currentlocation(newpos);} {}
231 }
232 Function {currentlocation()} {return_type __uint32
233 } {
234 code {if (tape==NULL) return 0;
235return tape->currentlocation();} {}
236 }
237 Function {jack_process(jack_nframes_t nframes, void *arg)} {open private return_type {static int}
238 } {
239 code {\#ifndef LIBJACK
240\#if (RECORDERDEBUG==1)
241cout << "no libjack" << endl;
242\#endif
243\#endif
244
245\#ifdef LIBJACK
246
247RecorderControl* recordercontrol=(RecorderControl*)arg;
248
249if (recordercontrol==NULL) {
250 cout << "no control" << endl;
251 return 0;
252}
253AudioSystem* audio=recordercontrol->audio;
254if (audio==NULL)
255{
256 cout << "no audiosys" << endl;
257 return 0;
258}
259if ((audio->libjack)==NULL)
260{
261\#if (RECORDERDEBUG==1)
262cout << "no libjack" << endl;
263\#endif
264 return 0;
265}
266
267if (!(audio->libjack->libloaded))
268{
269 cout << "no jacklib" << endl;
270 return 0;
271}
272
273RecorderControl* mythis=recordercontrol;
274//RecorderUI* mythis=recordercontrol; //(RecorderUI*)arg;
275//AudioSystem* audio=mythis->control->audio;
276
277
278jack_client_t* currjackclient=audio->jackclient;
279if (currjackclient==NULL) return 0;
280MixerControl* mixer=audio->mixer();
281if (mixer==NULL) return 0;
282jack_position_t current;
283jack_transport_state_t transport_state=audio->libjack->jack_transport_query(currjackclient,&current);
284
285hd24song* mysong=(hd24song*)audio->tape;
286if (mysong==NULL) return 0; /* nothing to do! */
287
288hd24fs* myfs=mysong->fs();
289
290__sint64 frame_time = (__sint64)(audio->libjack->jack_get_current_transport_frame(currjackclient));
291
292MixerChannelControl* mixerchannel[24];
293
294
295for (unsigned int tracknum=0;tracknum<MAXCHANNELS;tracknum++)
296{
297 mixerchannel[tracknum]=mixer->parentui()->mixerchannel[tracknum]->control;
298}
299
300unsigned int i;
301__sint64 intsamval=0;
302mysong->golocatepos(frame_time);
303int jumpedloop=0;
304if (transport_state!=JackTransportStopped)
305{
306 __sint64 frpos=frame_time;
307 __sint64 posoffset=0;
308 for (i=0;i<nframes;i++)
309 {
310 if ( mythis->loopmode()==1 )
311 {
312 posoffset++;
313 if ((frpos+i)==(__sint64)(mysong->getlocatepos(hd24song::LOCATEPOS_LOOPEND)))
314 {
315 frpos=mysong->getlocatepos(hd24song::LOCATEPOS_LOOPSTART);
316 mysong->golocatepos(frpos);
317 posoffset=0;
318 jumpedloop=1;
319 }
320 }
321
322 mysong->getmultitracksample(
323 (long*)((&audio->mtsample[i*25])),
324 hd24song::READMODE_REALTIME
325 );
326 }
327 if (jumpedloop==1)
328 {
329 audio->hd24_transport_locate((__sint64)(frpos+posoffset));
330 }
331}
332
333for (unsigned int tracknum=0;tracknum<MAXCHANNELS;tracknum++)
334{
335 jack_default_audio_sample_t *out =
336 (jack_default_audio_sample_t *)(audio->libjack->jack_port_get_buffer (audio->output_port[tracknum], nframes));
337 jack_default_audio_sample_t *in =
338 (jack_default_audio_sample_t *)(audio->libjack->jack_port_get_buffer (audio->input_port[tracknum], nframes));
339 for (i=0;i<nframes;i++)
340 {
341 if (transport_state!=JackTransportStopped) {
342 long* xb=(long*)(&(audio->mtsample[i*25+tracknum]));
343 intsamval=xb[0];
344 intsamval=((intsamval>>16)+((intsamval%256)<<16)+(intsamval & 0xff00));
345 if (intsamval>=(1<<23)) {
346 intsamval-=(1<<24);
347 }
348 double samval=(intsamval/(double)0x800000);
349 out[i]=samval; // send pre-fader, pre-mixer channel output to JACK
350 } else {
351 out[i]=0;
352 }
353
354 mixerchannel[tracknum]->sample(i,out[i]);
355
356 // ... except if we are monitoring input, in which case regular reading etc is
357 // still going on, but we will just copy the incoming signal to the output:
358 // (with the possible exception of tracks being recorded but that's for later)
359 if (myfs->isallinput()) {
360 out[i]=in[i];
361 }
362
363 if (fabs(out[i]) > mythis->data->trackpeak[i]) {
364 mythis->data->trackpeak[tracknum]=fabs(out[i]);
365 }
366 }
367}
368mixer->mix(nframes);
369jack_default_audio_sample_t *masterL =
370(jack_default_audio_sample_t *)(audio->libjack->jack_port_get_buffer (audio->output_master[0], nframes));
371jack_default_audio_sample_t *masterR =
372(jack_default_audio_sample_t *)(audio->libjack->jack_port_get_buffer (audio->output_master[1], nframes));
373if ((masterL!=NULL)&&(masterR!=NULL)) {
374 for (i=0;i<nframes;i++)
375 {
376 masterL[i] = mixer->masterout(0,i); // left
377 masterR[i] = mixer->masterout(1,i); // right
378 }
379}
380\#endif
381
382return 0;} {}
383 }
384 Function {jack_shutdown(void *arg)} {private return_type {static void}
385 } {
386 code {\#ifdef LIBJACK
387AudioSystem* audio=(AudioSystem*)arg;
388if (audio->jackclient==NULL) {
389 return;
390}
391if (audio->mtsample!=NULL) {
392 memutils::myfree("jack_shutdown",audio->mtsample);
393 audio->mtsample=NULL;
394}
395audio->jackclient=NULL;
396return;
397\#endif} {}
398 }
399 Function {jackinit()} {open private return_type void
400 } {
401 code {if (portaudio_initialized==1)
402{
403\#if (RECORDERDEBUG==1)
404 cout << "not initializing jack because portaudio is active" << endl;
405\#endif
406 return;
407}
408if (!(libjack->libloaded))
409{
410\#if (RECORDERDEBUG==1)
411 cout << "not initializing jack because its lib is not loaded" << endl;
412\#endif
413 return;
414}
415if (this->closingdown) {
416 if (jackclient!=NULL)
417 {
418 jack_shutdown(this);
419 }
420 jackclient=NULL;
421 return;
422}
423\#ifdef LIBJACK
424//button_setlocate->value(0);
425//highlight_setbuttons(0); // value of setlocate button
426//mustdisplaytimer=true;
427if (jackclient==NULL) {
428 jackclient = libjack->jack_client_new("HD24connect");
429
430 if (jackclient == NULL) {
431 // error: jack open failed.
432\#if (RECORDERDEBUG==1)
433 cout << "error: jack open failed." << endl;
434\#endif
435 return;
436 }
437 mtsample=(long *)memutils::mymalloc("jackinit",512000,1);
438
439 libjack->jack_set_process_callback (
440 jackclient,
441 (int (*)(jack_nframes_t, void*))jack_process,
442 recorder); // was: this (=audiosystem)
443 libjack->jack_on_shutdown (jackclient, jack_shutdown, this);
444 jackrate=libjack->jack_get_sample_rate (jackclient);
445 int i;
446 for (i=1;i<=MAXCHANNELS;i++) {
447 string portnameout="output";
448 string portnamein="input";
449
450 string* tracknum=Convert::int2str(i);
451 portnameout+=*tracknum;
452 portnamein+=*tracknum;
453 delete(tracknum);
454
455 output_port[i-1]=libjack->jack_port_register (jackclient, portnameout.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
456 input_port[i-1]=libjack->jack_port_register (jackclient, portnamein.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
457 }
458 string portnameout="master_out_L";
459 output_master[0]=libjack->jack_port_register (jackclient, portnameout.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
460 portnameout="master_out_R";
461 output_master[1]=libjack->jack_port_register (jackclient, portnameout.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
462 if (libjack->jack_activate(jackclient)) {
463\#if (RECORDERDEBUG==1)
464 cout << "cannot activate jack client" << endl;
465\#endif
466 };
467}
468\#endif} {}
469 }
470 Function {isjackinitialized()} {open private return_type bool
471 } {
472 code {if (this->jackclient!=NULL)
473{
474 return true;
475}
476return false;} {}
477 }
478 Function {portaudioinit()} {open private return_type void
479 } {
480 code {\#ifndef LIBPORTAUDIO
481return;
482\#endif
483\#ifdef LIBPORTAUDIO
484//if (currsong==NULL) return;
485//\#if (RECORDERDEBUG==1)
486//cout << "Init portaudio" << endl;
487//\#endif
488//mustdisplaytimer=true;
489PaError err;
490err=(*(portaudio->Pa_Initialize))();
491if (err!=paNoError) {
492 this->portaudiostream=NULL;
493 (*(portaudio->Pa_Terminate))(); return;
494\#if (RECORDERDEBUG==1)
495cout << "Error during init portaudio" << endl;
496\#endif
497}
498this->mustloop(false);
499this->as_looppos=0;
500this->portaudio_initialized=1;
501this->as_initialized=1;
502\#endif} {}
503 }
504 Function {isportaudioinitialized()} {open private return_type bool
505 } {
506 code {if (!(portaudio->libloaded)) {
507return false;
508}
509if (portaudiostream!=NULL) {
510 return true;
511}
512if (portaudio_initialized!=0) {
513 return true;
514}
515return false;} {}
516 }
517 Function {portaudio_process(const void *inputBuffer, void *outputBuffer, __uint32 nframes, const PaStreamCallbackTimeInfo* timeinfo,PaStreamCallbackFlags, void *userData)} {open private return_type {static int}
518 } {
519 code {RecorderControl* recordercontrol=(RecorderControl*)userData;
520
521if (recordercontrol==NULL) {
522 cout << "no control" << endl;
523 return 0;
524}
525AudioSystem* audio=recordercontrol->audio;
526if (audio==NULL)
527{
528 cout << "no audiosys" << endl;
529 return 0;
530}
531if (audio->portaudio==NULL)
532{
533 cout << "no portaudio" << endl;
534 return 0;
535}
536if (!(audio->portaudio->libloaded))
537{
538 cout << "no palib" << endl;
539 return 0;
540}
541if (!audio->havestreamtime)
542{
543 audio->streamtime=0;
544 audio->havestreamtime=true;
545}
546
547float samleft=0;
548float samright=0;
549
550//hd24fs* myfs=mythis->currenthd24;
551
552PaStream* curr_pa_stream=audio->portaudiostream;
553
554if (curr_pa_stream==NULL)
555{
556 cout << "no stream" << endl;
557 return paContinue;
558}
559if ((audio->mtsample)==NULL)
560{
561 cout << "no sample" << endl;
562 return paContinue;
563}
564
565// TODO: connect audio system to mixer
566MixerControl* mixer=audio->mixer();
567if (mixer==NULL)
568{
569 cout << "no mixer" << endl;
570 return paContinue;
571}
572
573if (audio->mustloop())
574{
575 cout << "must loop" << endl;
576 return paContinue;
577}
578
579hd24song* mysong=recordercontrol->song();
580if (mysong == NULL)
581{
582 cout << "no song" << endl;
583 return 0;//nothing to do!
584}
585
586unsigned int tottracks=(unsigned int)mysong->logical_channels();
587
588/* frame time indicates how long the stream has been playing
589 and is reset to 0 after pressing stop/play.
590 To compensate for this, we must add our portaudio-offset,
591 the offset of the songcursor when we pressed 'play'.
592 We then record the absolute stream time in pa_streamtime. */
593__sint64 frame_time = audio->streamtime;
594frame_time+=audio->portaudiooffset;
595//audio->streamtime=frame_time;
596audio->streamtime+=nframes;
597MixerChannelControl* mixerchannel[24];
598
599unsigned int i;
600__sint64 intsamval=0;
601
602mysong->golocatepos(frame_time);
603int loopmode=recordercontrol->loopmode();
604int jumpedloop=0;
605
606 __sint64 frpos=frame_time;
607 __sint64 posoffset=0;
608 for (i=0;i<nframes;i++)
609 {
610 if ( loopmode==1 )
611 {
612 posoffset++;
613 if ((frpos+i)==(__sint64)(mysong->getlocatepos(hd24song::LOCATEPOS_LOOPEND)))
614 {
615 frpos=mysong->getlocatepos(hd24song::LOCATEPOS_LOOPSTART);
616 mysong->golocatepos(frpos);
617 posoffset=0;
618 jumpedloop=1;
619 }
620 }
621
622 mysong->getmultitracksample(
623 (long*)((&audio->mtsample[i*25])),
624 hd24song::READMODE_REALTIME
625 );
626 // if sample rate is high speed, skip next sample.
627 if ((mysong->physical_channels()/mysong->logical_channels())==2)
628 {
629 mysong->getmultitracksample(
630 (long*)((&audio->mtsample[i*25])),
631 hd24song::READMODE_REALTIME
632 );
633 }
634 }
635 if (jumpedloop==1)
636 {
637 audio->as_looppos=frpos+posoffset;
638 audio->mustloop(true);
639 }
640
641
642
643 for (unsigned int tracknum=0;tracknum<MAXCHANNELS;tracknum++)
644 {
645 mixerchannel[tracknum]=mixer->parentui()->mixerchannel[tracknum]->control;
646 }
647
648 for (unsigned int tracknum=0;tracknum<tottracks;tracknum++)
649 {
650 recordercontrol->data->trackpeak[tracknum]=0;
651 }
652
653
654 for (i=0;i<nframes;i++)
655 {
656 double samvaltot=0;
657 if (inputBuffer!=NULL) {
658 samleft=((float*)inputBuffer)[i*2];
659 samright=((float*)inputBuffer)[i*2+1];
660 } else {
661 samleft=0;
662 samright=0;
663 }
664 // depending on input mode, mix these to mono, set right to be equal to
665 // left, swap them or set left to be equal to right.
666 float subsamval;
667 for (unsigned int tracknum=0;tracknum<tottracks;tracknum++)
668 {
669 long* xb=(long*)(&(audio->mtsample[i*25+tracknum]));
670 intsamval=xb[0];
671 intsamval=((intsamval>>16)+((intsamval%256)<<16)+(intsamval & 0xff00));
672 if (intsamval>=(1<<23)) {
673 intsamval-=(1<<24);
674 }
675
676
677 if (mysong->istrackmonitoringinput(tracknum+1))
678 {
679 subsamval=((tracknum%2)==0)?(samleft):(samright);
680 }
681 else
682 {
683 subsamval=(intsamval/(double)0x800000);
684 }
685 samvaltot+=subsamval;
686 if (fabs(subsamval) > recordercontrol->data->trackpeak[tracknum]) {
687 recordercontrol->data->trackpeak[tracknum]=fabs(subsamval);
688 }
689
690 mixerchannel[tracknum]->sample(i,subsamval);
691
692 }
693 if (tottracks<24) {
694 for (unsigned int tracknum=tottracks;tracknum<MAXCHANNELS;tracknum++) {
695 mixerchannel[tracknum]->sample(i,0);
696 }
697 }
698 /*
699 if (outputBuffer!=NULL) {
700 ((float*)outputBuffer)[i*2] = samval; // left
701 ((float*)outputBuffer)[i*2+1] = samval; // right
702 }*/
703
704 }
705 mixer->mix(nframes);
706
707 if (outputBuffer!=NULL) {
708
709 for (i=0;i<nframes;i++)
710 {
711 ((float*)outputBuffer)[i*2] = mixer->masterout(0,i); // left
712 ((float*)outputBuffer)[i*2+1] = mixer->masterout(1,i); // right
713 }
714 }
715
716// cout << mythis->trackpeak[0] << endl;
717
718return 0;} {}
719 }
720 Function {portaudio_transport_start()} {open private return_type void
721 } {
722 code {if (!(portaudio->libloaded)) {
723return;
724}
725
726\#if (RECORDERDEBUG==1)
727cout << "portaudio transport start" << endl;
728\#endif
729if (!isportaudioinitialized())
730{
731 PaError err=(*(portaudio->Pa_Initialize))();
732 if (err != paNoError)
733 {
734\#if (RECORDERDEBUG==1)
735 cout << "Cannot initialize portaudio- exiting." << endl;
736\#endif
737
738 }
739}
740if (isportaudioinitialized() && (portaudiostream!=NULL)) {
741\#if (RECORDERDEBUG==1)
742cout << "already have stream- done starting" << endl;
743\#endif
744 return;
745}
746this->mustloop(false);
747
748this->as_looppos=0;
749PaDeviceIndex indev=(*(portaudio->Pa_GetDefaultInputDevice))();
750PaDeviceIndex outdev=(*(portaudio->Pa_GetDefaultOutputDevice))();
751cout << "default input device="<<indev<< endl;
752cout << "default output device="<<outdev<<endl;
753
754if (inputParameters!=NULL)
755{
756 memset(inputParameters,'\\0',sizeof(*inputParameters));
757}
758
759inputParameters->channelCount=2;
760inputParameters->sampleFormat=paFloat32;
761inputParameters->device=indev;
762inputParameters->suggestedLatency = (*(portaudio->Pa_GetDeviceInfo))( inputParameters->device )->defaultLowInputLatency;
763inputParameters->hostApiSpecificStreamInfo = NULL;
764\#if (RECORDERDEBUG==1)
765cout << "Input params set" << endl;
766cout << "Device=" << indev << endl;
767cout << "Channelcount=" << inputParameters->channelCount << endl;
768cout << "sampleFormat=" << inputParameters->sampleFormat << endl;
769cout << "suggestedlatency=" << inputParameters->suggestedLatency << endl;
770
771\#endif
772if (outputParameters!=NULL)
773{
774 memset(outputParameters,'\\0',sizeof(*outputParameters));
775}
776
777outputParameters->channelCount=2;
778outputParameters->sampleFormat=paFloat32;
779outputParameters->device=outdev;
780outputParameters->suggestedLatency = (*(portaudio->Pa_GetDeviceInfo))( outputParameters->device )->defaultLowOutputLatency;
781outputParameters->hostApiSpecificStreamInfo = NULL;
782\#if (RECORDERDEBUG==1)
783cout << "Output params set" << endl;
784\#endif
785cout << "Device=" << outdev << endl;
786cout << "Channelcount=" << outputParameters->channelCount << endl;
787cout << "sampleFormat=" << outputParameters->sampleFormat << endl;
788cout << "suggestedlatency=" << outputParameters->suggestedLatency << endl;
789
790if (mtsample==NULL)
791{
792 mtsample=(long *)memutils::mymalloc("portaudio_transport_start",512000,sizeof(long));
793}
794
795double playbackrate=this->samplerate();
796cout << "trying samrate="<<samrate<<endl;
797cout << "framesperbuf=" << PA_FRAMESPERBUF << endl;
798
799PaError err=(*(portaudio->Pa_OpenStream))(
800 &portaudiostream,
801 NULL,/*this->inputParameters,*/
802 this->outputParameters,
803 playbackrate,
804 PA_FRAMESPERBUF, /* frames per buffer */
805 paClipOff | paDitherOff,
806 portaudio_process,
807 (void*)recorder);
808this->havestreamtime=false;
809this->streamtime=0;
810
811if (err!=paNoError) {
812\#if (RECORDERDEBUG==1)
813cout << "Error opening stream" << endl;
814cout << portaudio->Pa_GetErrorText(err) << endl;
815cout << "playbackrate=" << playbackrate << endl;
816\#endif
817 (*(portaudio->Pa_Terminate))();
818 return;
819}
820\#if (RECORDERDEBUG==1)
821cout << "Stream opened, going to start it now..." << endl;
822\#endif
823err=(*(portaudio->Pa_StartStream))(portaudiostream);
824if (err!=paNoError) {
825\#if (RECORDERDEBUG==1)
826cout << "Error starting stream" << endl;
827cout << portaudio->Pa_GetErrorText(err) << endl;
828\#endif
829 (*(portaudio->Pa_Terminate))();
830 return;
831}
832\#if (RECORDERDEBUG==1)
833cout << "Stream started" << endl;
834\#endif
835
836
837return;} {}
838 }
839 Function {stopPAstream()} {open private return_type void
840 } {
841 code {// only to be called by portaudio_transport_stop
842if (portaudiostream==NULL) return;
843PaStream* pstream=portaudiostream;
844portaudiostream=NULL;
845
846PaError err = (*(portaudio->Pa_StopStream))( pstream );
847
848if (err!=paNoError) {
849 cout << portaudio->Pa_GetErrorText(err) << endl;
850}
851
852err = (*(portaudio->Pa_CloseStream))( pstream );
853
854if (err!=paNoError) {
855 cout << portaudio->Pa_GetErrorText(err) << endl;
856}
857
858(*(portaudio->Pa_Terminate))();} {}
859 }
860 Function {portaudio_transport_stop()} {open private return_type void
861 } {
862 code {if (portaudio==NULL) return;
863if (!(portaudio->libloaded)) return;
864
865\#if (RECORDERDEBUG==1)
866cout << "portaudio transport stop" << endl;
867\#endif
868// TODO: only stop stream if not monitoring input.
869stopPAstream();
870portaudio_initialized=0;
871portaudiostream=NULL;
872portaudiooffset+=streamtime;
873cout << "portaudiooffset at stop=" << portaudiooffset << endl;
874if (mtsample!=NULL)
875{
876 memutils::myfree("portaudio_transport_stop",mtsample);
877 mtsample=NULL;
878}} {}
879 }
880 Function {hd24_transport_goloc(__uint32 frames)} {open return_type void
881 } {
882 code {if (libjack!=NULL)
883{
884 if (libjack->libloaded) {
885 if (portaudio_initialized!=1) {
886
887 jackinit();
888 if (jackclient!=NULL) {
889 hd24_transport_locate((__sint64)frames);
890 return;
891 }
892 }
893 }
894}
895
896if (portaudio!=NULL)
897{
898 if (portaudio->libloaded)
899 {
900 hd24_transport_locate((__sint64)frames);
901 return;
902 }
903}} {}
904 }
905 Function {hd24_transport_locate(__sint64 i)} {open return_type void
906 } {
907 code {cout << "Request to transport locate to " << i << endl;
908if (i<0) i=0;
909if (libjack!=NULL)
910{
911 if (libjack->libloaded) {
912 cout << "try jackinit" << endl;
913 jackinit();
914 if (jackclient!=NULL) {
915 libjack->jack_transport_locate(jackclient,i);
916 return;
917 }
918 }
919 cout << "Jack locate attempt inconclusive, will try portaudio if available" << endl;
920}
921
922if (portaudio!=NULL)
923{
924 if (portaudio->libloaded) {
925 cout << "will have to do portaudio locate." << endl;
926 bool streamwasinitialized=true;
927 if (!(isportaudioinitialized()))
928 {
929 cout << "No previous stream, init a new one "<< endl;
930 streamwasinitialized=false;
931 if (tape==NULL)
932 {
933 return;
934 }
935
936 tape->currentlocation((i < 0) ? 0 : i);
937 cout << "set location to " << i << endl;
938 portaudiooffset=i; // still ok even without active stream
939 streamtime=i;
940 cout << "set portaudiooffset, streamtime to " << i << endl;
941 return; // <-- see if this does the trick- no previous
942 // stream, no new one.
943 }
944
945 PaError err;
946 if (portaudiostream!=NULL)
947 {
948 cout << "Still have a stream that needs stopping first." << endl;
949 err = (*(portaudio->Pa_StopStream))( portaudiostream );
950 if (err!=paNoError)
951 {
952 // maybe another program owns the stream.
953 cout << portaudio->Pa_GetErrorText(err) << endl;
954 }
955
956 PaStream* oldportaudiostream=portaudiostream;
957 portaudiostream=NULL;
958 err = (*(portaudio->Pa_CloseStream))( oldportaudiostream );
959 }
960
961 portaudiooffset=i; // still ok even without active stream
962 streamtime=i; // old portaudio V18 legacy
963
964 bool streamnolongerinitialized=false;
965 if (!(isportaudioinitialized()))
966 {
967 if (streamwasinitialized)
968 {
969 streamnolongerinitialized=true;
970 }
971 }
972
973 if (streamnolongerinitialized)
974 {
975 /* if closing stream means no longer initialized,
976 do not open another because we are not playing back
977 anything at the moment. */
978 return;
979 }
980 cout << "open a fresh stream" << endl;
981
982 PaDeviceIndex indev=(*(portaudio->Pa_GetDefaultInputDevice))();
983 PaDeviceIndex outdev=(*(portaudio->Pa_GetDefaultOutputDevice))();
984 if (inputParameters!=NULL)
985 {
986 memset(inputParameters,'\\0',sizeof(*inputParameters));
987
988 this->inputParameters->device=indev;
989 this->inputParameters->channelCount=2;
990 this->inputParameters->sampleFormat=paFloat32;
991 void* devinfo=(void*)(*(portaudio->Pa_GetDeviceInfo))( inputParameters->device );
992 if (devinfo!=NULL)
993 {
994 this->inputParameters->suggestedLatency = (*(portaudio->Pa_GetDeviceInfo))( inputParameters->device )->defaultLowInputLatency;
995 }
996 this->inputParameters->hostApiSpecificStreamInfo = NULL;
997 }
998 if (outputParameters!=NULL)
999 {
1000 memset(outputParameters,'\\0',sizeof(*outputParameters));
1001 this->outputParameters->device=outdev;
1002 this->outputParameters->channelCount=2;
1003 this->outputParameters->sampleFormat=paFloat32;
1004 void* devinfo=(void*)(*(portaudio->Pa_GetDeviceInfo))( outputParameters->device );
1005 if (devinfo!=NULL)
1006 {
1007 this->outputParameters->suggestedLatency = (*(portaudio->Pa_GetDeviceInfo))( outputParameters->device )->defaultLowOutputLatency;
1008 }
1009 this->outputParameters->hostApiSpecificStreamInfo = NULL;
1010 }
1011
1012 double samrate=this->samplerate();
1013 cout << " sample rate for new stream is " << samrate << endl;
1014 if (samrate==0)
1015 {
1016 return;
1017 }
1018
1019 err=(*(portaudio->Pa_OpenStream))(
1020 &portaudiostream,
1021 NULL,/*this->inputParameters,*/
1022 this->outputParameters,
1023 samrate,
1024 PA_FRAMESPERBUF, /* frames per buffer */
1025 paClipOff | paDitherOff,
1026 portaudio_process,
1027 this->recorder);
1028 this->havestreamtime=false;
1029 this->streamtime=0;
1030
1031 if (err!=paNoError) {
1032 cout << portaudio->Pa_GetErrorText(err) << endl;
1033 }
1034 if (err!=paNoError) { (*( portaudio->Pa_Terminate))(); return; }
1035
1036
1037 err=(*(portaudio->Pa_StartStream))(portaudiostream);
1038 if (err!=paNoError) {
1039 cout << portaudio->Pa_GetErrorText(err) << endl;
1040 }
1041 cout << "stream appears to have started successfully" << endl;
1042
1043 return;
1044 }
1045}} {}
1046 }
1047 Function {hd24_transport_locate(__uint32 i)} {open return_type void
1048 } {
1049 code {this->hd24_transport_locate((__sint64)i);} {}
1050 }
1051 Function {hd24_transport_start()} {open return_type void
1052 } {
1053 code {if (libjack!=NULL)
1054{
1055 if (libjack->libloaded) {
1056 jackinit();
1057 if (jackclient!=NULL) {
1058 libjack->jack_transport_start(jackclient);
1059 return;
1060 }
1061 }
1062}
1063
1064if (portaudio!=NULL)
1065{
1066 if (portaudio->libloaded)
1067 {
1068 if (!(isportaudioinitialized()))
1069 {
1070 portaudioinit();
1071 }
1072 if (isportaudioinitialized())
1073 {
1074 portaudio_transport_start();
1075 return;
1076 }
1077 }
1078}} {}
1079 }
1080 Function {hd24_transport_stop()} {open return_type void
1081 } {
1082 code {if (recorder!=NULL)
1083{
1084 recorder->resetpeaks();
1085}
1086
1087if (libjack!=NULL)
1088{
1089 if (libjack->libloaded)
1090 {
1091 jackinit();
1092 if (jackclient!=NULL)
1093 {
1094 libjack->jack_transport_stop(jackclient);
1095 return;
1096 }
1097 }
1098}
1099
1100if (portaudio!=NULL)
1101{
1102 if (portaudio->libloaded)
1103 {
1104 if (!(isportaudioinitialized()))
1105 {
1106 portaudioinit();
1107 }
1108 if (isportaudioinitialized())
1109 {
1110 portaudio_transport_stop();
1111 return;
1112 }
1113 }
1114}} {}
1115 }
1116 Function {hd24_transport_ffwd(long int frames)} {open return_type void
1117 } {
1118 code {if (portaudio_initialized!=1)
1119{
1120 if (libjack!=NULL)
1121 {
1122 if (libjack->libloaded)
1123 {
1124 jackinit();
1125 if (jackclient!=NULL)
1126 {
1127 __sint64 frame_time = /* currentlocation() */
1128 (__sint64)(libjack->jack_get_current_transport_frame(jackclient));
1129 hd24_transport_locate((__sint64)(frame_time+frames));
1130 return;
1131 }
1132 }
1133 }
1134}
1135
1136if (portaudio!=NULL)
1137{
1138 if (portaudio->libloaded)
1139 {
1140 __sint64 frame_time=currentlocation();
1141 hd24_transport_locate((__sint64)(frame_time+frames));
1142
1143//string* dur=currsong->display_cursor();
1144//setstatus(*dur);
1145//delete (dur);
1146
1147 return;
1148 }
1149}} {}
1150 }
1151 Function {hd24_transport_rew(long int frames)} {open return_type void
1152 } {
1153 code {if (libjack!=NULL)
1154{
1155 if (libjack->libloaded)
1156 {
1157 if (portaudio_initialized!=1)
1158 {
1159 jackinit();
1160 if (jackclient!=NULL)
1161 {
1162 __sint64 frame_time =
1163 (__sint64)(libjack->jack_get_current_transport_frame(jackclient));
1164 if (frames>frame_time) {
1165 hd24_transport_locate((__sint64)0);
1166 } else {
1167 hd24_transport_locate((__sint64)(frame_time-frames));
1168 }
1169 return;
1170 }
1171 }
1172 }
1173}
1174
1175if (portaudio!=NULL)
1176{
1177 if (portaudio->libloaded) {
1178
1179 __sint64 frame_time=currentlocation();
1180 if (frames>frame_time) {
1181 hd24_transport_locate((__sint64)0);
1182 } else {
1183 hd24_transport_locate((__sint64)(frame_time-frames));
1184 }
1185
1186 hd24_transport_locate((__sint64)(frame_time-frames));
1187
1188 return;
1189 }
1190}} {}
1191 }
1192 Function {isinitialized()} {return_type bool
1193 } {
1194 code {if (this->isportaudioinitialized())
1195{
1196 return true;
1197}
1198if (this->isjackinitialized())
1199{
1200 return true;
1201}
1202return false;} {}
1203 }
1204 Function {mustloop()} {return_type bool
1205 } {
1206 code {return this->as_mustloop;} {}
1207 }
1208 Function {mustloop(bool yesno)} {return_type void
1209 } {
1210 code {this->as_mustloop=yesno;} {}
1211 }
1212 Function {samplerate()} {return_type __uint32
1213 } {
1214 code {return this->samrate;
1215/*(double)(currsong->samplerate()/(currsong->physical_channels()/currsong->logical_channels())); */} {}
1216 }
1217 Function {samplerate(__uint32 newrate)} {return_type void
1218 } {
1219 code {this->samrate=newrate;} {}
1220 }
1221 Function {looppos()} {return_type __uint32
1222 } {
1223 code {return this->as_looppos;} {}
1224 }
1225 Function {looppos(__uint32 newpos)} {return_type void
1226 } {
1227 code {this->as_looppos=newpos;} {}
1228 }
1229 Function {locatepoint(int locpointnum,__uint32 locatepos)} {return_type void
1230 } {
1231 code {if (tape==NULL) return;
1232tape->setlocatepos(locpointnum,locatepos);} {}
1233 }
1234 Function {locatepoint(int locpointnum)} {return_type __uint32
1235 } {
1236 code {if (tape==NULL) return 0;
1237return tape->getlocatepos(locpointnum);} {}
1238 }
1239 Function {audiolib(int whichlib,void* libptr)} {open return_type void
1240 } {
1241 code {if (whichlib==AUDIOLIB_PORTAUDIO)
1242{
1243 this->portaudio=(PortAudioWrapper*)libptr;
1244\#if (RECORDERDEBUG==1)
1245cout << "set portaudio lib to " << libptr << endl;
1246\#endif
1247 return;
1248}
1249if (whichlib==AUDIOLIB_JACK)
1250{
1251 this->libjack=(JackWrapper*)libptr;
1252\#if (RECORDERDEBUG==1)
1253cout << "set jack lib to " << libptr << endl;
1254\#endif
1255 return;
1256}
1257if (whichlib==AUDIOLIB_SNDFILE)
1258{
1259 this->soundfile=(SoundFileWrapper*)libptr;
1260\#if (RECORDERDEBUG==1)
1261cout << "set soundfile lib to " << libptr << endl;
1262\#endif
1263}} {}
1264 }
1265 Function {audiolib(int whichlib)} {open return_type {void*}
1266 } {
1267 code {if (whichlib==AUDIOLIB_PORTAUDIO)
1268{
1269 return (void*)portaudio;
1270}
1271if (whichlib==AUDIOLIB_JACK)
1272{
1273 return (void*)libjack;
1274}
1275if (whichlib==AUDIOLIB_SNDFILE)
1276{
1277 return (void*)soundfile;
1278}
1279return NULL;} {}
1280 }
1281 Function {~AudioSystem()} {open
1282 } {
1283 code {if (inputParameters!=NULL)
1284{
1285 delete inputParameters;
1286 inputParameters=NULL;
1287}
1288if (outputParameters!=NULL)
1289{
1290 delete outputParameters;
1291 outputParameters=NULL;
1292}
1293\#if (RECORDERDEBUG==1)
1294cout << "AudioSystem::~AudioSystem()" << endl;
1295\#endif} {}
1296 }
1297 Function {audiostore(AudioStorage* store)} {open return_type void
1298 } {
1299 code {this->tape=store;
1300if (store!=NULL)
1301{
1302 this->samrate=store->samplerate();
1303}} {}
1304 }
1305 Function {audiostore()} {open return_type {AudioStorage*}
1306 } {
1307 code {return tape;} {}
1308 }
1309 Function {mixer(MixerControl* p_mixer)} {open return_type void
1310 } {
1311 code {this->mixercontrol=p_mixer;} {}
1312 }
1313 Function {mixer()} {open return_type {MixerControl*}
1314 } {
1315 code {return this->mixercontrol;} {}
1316 }
1317}
1318
1319class RecorderData {open
1320} {
1321 decl {int loopmode;} {public
1322 }
1323 decl {float trackpeak[24];} {public
1324 }
1325}
1326
1327class RecorderControl {open
1328} {
1329 decl {RecorderData* data;} {public
1330 }
1331 decl {RecorderUI* ui;} {public
1332 }
1333 decl {AudioSystem* audio;} {public
1334 }
1335 Function {RecorderControl()} {open
1336 } {
1337 code {this->data=new RecorderData();
1338init();} {}
1339 }
1340 Function {~RecorderControl()} {open
1341 } {
1342 code {if (this->data!=NULL)
1343{
1344 delete this->data;
1345}} {}
1346 }
1347 Function {init()} {open return_type void
1348 } {
1349 code {this->ui=NULL;
1350this->audio=new AudioSystem(this);
1351data->loopmode=0;} {}
1352 }
1353 Function {ready()} {open return_type int
1354 } {
1355 code {return 1;} {}
1356 }
1357 Function {parentui()} {open return_type {RecorderUI*}
1358 } {
1359 code {return this->ui;} {}
1360 }
1361 Function {parentui(RecorderUI* p_ui)} {open return_type void
1362 } {
1363 code {this->ui=p_ui;} {}
1364 }
1365 Function {loopmode()} {open return_type int
1366 } {
1367 code {return data->loopmode;} {}
1368 }
1369 Function {loopmode(int p_loopmode)} {return_type void
1370 } {
1371 code {data->loopmode=p_loopmode;
1372if (ui!=NULL)
1373{
1374 ui->button_loopmode->value(p_loopmode);
1375 ui->button_loopmode->redraw();
1376}} {}
1377 }
1378 Function {button_scrub_call(int amount,RecorderControl* mycontrol)} {open return_type {static void}
1379 } {
1380 code {if (mycontrol->audio==NULL) return;
1381// we could get the current transport pos here; ....
1382if (amount>0) {
1383mycontrol->audio->hd24_transport_ffwd((__uint32)(300*amount));
1384} else {
1385mycontrol->audio->hd24_transport_rew((__uint32)(-300*amount));
1386}
1387// ... then the new transport pos here; read the snippet
1388// of audio that is spanned by the difference, stretch
1389// it to the audio buffer size, then play it.
1390// Alternatively, a visual-only representation could be fine.} {}
1391 }
1392 Function {button_rew_call()} {open return_type void
1393 } {
1394 code {if (this->audio==NULL) return;
1395this->audio->hd24_transport_rew(5*this->audio->samplerate());} {}
1396 }
1397 Function {button_ffwd_call()} {open return_type void
1398 } {
1399 code {if (this->audio==NULL) return;
1400this->audio->hd24_transport_ffwd(5*this->audio->samplerate());} {}
1401 }
1402 Function {button_stop_call()} {open return_type void
1403 } {
1404 code {if (this->audio==NULL) return;
1405//this->currenthd24->settransportstatus(hd24fs::TRANSPORTSTATUS_STOP);
1406//TODO: The above is for monitoring purposes
1407this->audio->hd24_transport_stop();
1408if (ui==NULL) return;
1409
1410ui->button_light((void*)(ui->button_stop),1);
1411//button_stop->up_image(button_stop_uplit->image());
1412ui->button_up((void*)(ui->button_play));
1413ui->button_up((void*)(ui->button_rec));} {}
1414 }
1415 Function {button_play_call()} {open return_type void
1416 } {
1417 code {if (this->audio==NULL) return;
1418//if (button_rec->value()==1) {
1419// this->currenthd24->settransportstatus(hd24fs::TRANSPORTSTATUS_REC);
1420// TODO: The above is for monitoring purposes
1421//} else {
1422// this->currenthd24->settransportstatus(hd24fs::TRANSPORTSTATUS_PLAY);
1423// TODO: The above is for monitoring purposes
1424//}
1425this->audio->hd24_transport_start();
1426
1427ui->button_light(ui->button_stop,0);
1428
1429if (ui->button_play->value()==1)
1430{
1431 ui->button_up(ui->button_rec);
1432}
1433ui->button_down(ui->button_play);} {}
1434 }
1435 Function {button_rec_call()} {open return_type void
1436 } {
1437 code {/* ui->button_rec->redraw();
1438if (currsong==NULL) return;
1439if (currenthd24==NULL) return;
1440
1441if (this->currenthd24->gettransportstatus()==hd24fs::TRANSPORTSTATUS_STOP) {
1442 return;
1443}
1444
1445if (ui->button_rec->value()==1) {
1446 this->currenthd24->settransportstatus(hd24fs::TRANSPORTSTATUS_REC);
1447} else {
1448 this->currenthd24->settransportstatus(hd24fs::TRANSPORTSTATUS_PLAY);
1449}
1450
1451this->audio->hd24_transport_stop();
1452//button_play->value(0); */} {}
1453 }
1454 Function {solo(int channel,int val)} {} {
1455 code {// set solo status of channel to value
1456//mixer->mixerchannel[channel]->control->solo(val);} {}
1457 }
1458 Function {mute(int channel,int val)} {} {
1459 code {// set mute status of channel to value
1460//mixer->mixerchannel[channel]->control->mute(val);} {}
1461 }
1462 Function {resetpeaks()} {open return_type void
1463 } {
1464 code {for (int i=0;i<24;i++)
1465{
1466 data->trackpeak[i]=0;
1467}} {}
1468 }
1469 Function {highlight_setbuttons(int value)} {open return_type void
1470 } {
1471 code {ui->highlight_setbuttons(value);} {}
1472 }
1473 Function {hd24_transport_goloc(__uint32 frames)} {open return_type void
1474 } {
1475 code {if (audio==NULL)
1476{
1477 return;
1478}
1479audio->hd24_transport_goloc(frames);} {}
1480 }
1481 Function {button_rehearse_call()} {return_type void
1482 } {
1483 code {return;} {}
1484 }
1485 Function {handlelocatebutton(__uint32 locpoint)} {return_type void
1486 } {
1487 code {// either set or jumpto locate point
1488
1489if (ui->button_setlocate->value()==1)
1490{
1491 // set locate point
1492 ui->button_setlocate->value(0);
1493 highlight_setbuttons(ui->button_setlocate->value());
1494 // set loop start to current song cursor
1495 if (audio==NULL) return;
1496 audio->locatepoint(locpoint,audio->currentlocation());
1497// ui->populate_locatepoints(currsong,ui->locatepoints);
1498} else {
1499 // jump to locate point
1500 if (audio==NULL) return;
1501 audio->hd24_transport_locate((__sint64)(audio->locatepoint(locpoint)));
1502}} {}
1503 }
1504 Function {disable()} {} {
1505 code {/* Disable the recorder */
1506//fl_message("TODO: recordercontrol::disable()");
1507if ((this->ui)==NULL) return;
1508this->ui->deactivate();} {}
1509 }
1510 Function {enable()} {} {
1511 code {/* Disable the recorder */
1512//fl_message("TODO: recordercontrol::enable()");
1513if ((this->ui)==NULL) return;
1514this->ui->activate();} {}
1515 }
1516 decl {int dispwritecountdown;} {public
1517 }
1518 Function {dispwrite(unsigned int line,const char* message)} {return_type void
1519 } {
1520 code {ui->dispwrite(line,message);} {}
1521 }
1522 Function {dispwrite(unsigned int line,const char* message,__uint32 timeout_msec)} {return_type void
1523 } {
1524 code {ui->dispwrite(line,message,timeout_msec);} {}
1525 }
1526 Function {audiolib(int whichlib,void* libptr)} {open return_type void
1527 } {
1528 code {if (audio==NULL) return;
1529audio->audiolib(whichlib,libptr);} {}
1530 }
1531 Function {song(hd24song* store)} {open return_type void
1532 } {
1533 code {audio->audiostore((AudioStorage*)store);
1534if (store!=NULL)
1535{
1536 this->enable();
1537} else {
1538 this->disable();
1539}
1540if (store==NULL)
1541{
1542 string* disp=new string(" No Song "
1543 " Selected ");
1544 dispwrite(0,disp->c_str());
1545 delete disp;
1546}
1547else
1548{
1549
1550 string disp="S";
1551 string* idstr=Convert::int2str(store->songid(),2,"0");
1552 disp+=*idstr;
1553 delete idstr;
1554 disp+=":\\"";
1555 string* dummy=store->songname();
1556 //transfersource->value(dummy->c_str());
1557 string* dummy2=Convert::readstring((unsigned char*)dummy->c_str(),0,10);
1558 string* dummy3=Convert::readstring((unsigned char*)dummy->c_str(),0,11);
1559
1560 disp+=*dummy2;
1561 delete dummy;
1562 delete dummy2;
1563 if (dummy3->length()>10)
1564 {
1565 disp+="\\4"; // arrow right
1566 } else {
1567 disp+="\\"";
1568 }
1569 delete dummy3;
1570 string* disp2=Convert::padright(disp,16," ");
1571
1572 string* dur=store->display_duration();
1573
1574 *disp2+=dur->substr(0,8);
1575 *disp2+=":";
1576 *disp2+=dur->substr(9,2);
1577 *disp2+=" ";
1578 delete dur;
1579
1580 if (store->iswriteprotected())
1581 {
1582 *disp2+="\\1";
1583 } else {
1584 *disp2+="\\2";
1585 }
1586 string* strtracksb=Convert::int2str(store->logical_channels(),2,"0");
1587 *disp2+=*strtracksb;
1588 delete strtracksb;
1589 *disp2+="t";
1590
1591 dispwrite(0,disp2->c_str());
1592 delete disp2;
1593
1594}} {selected
1595 }
1596 }
1597 Function {song()} {open return_type {hd24song*}
1598 } {
1599 code {return (hd24song*)audio->audiostore();} {}
1600 }
1601 Function {toggletrackarmed(__uint32 base1tracknum)} {open return_type void
1602 } {
1603 code {AudioStorage* astore=(hd24song*)(this->audio->audiostore());
1604astore->trackarmed(base1tracknum,!astore->trackarmed(base1tracknum));} {}
1605 }
1606}
1607
1608class RecorderUI {: {public Fl_Group}
1609} {
1610 decl {RecorderControl* control;} {public
1611 }
1612 Function {RecorderUI(int a,int b,int c,int d):Fl_Group(a,b,c,d,NULL)} {open
1613 } {
1614 code {this->control=new RecorderControl();
1615control->parentui(this);
1616this->window=(Fl_Window*)(this->make_window());
1617this->init_gui();} {}
1618 }
1619 Function {~RecorderUI()} {open
1620 } {
1621 code {delete control;} {}
1622 }
1623 Function {init_gui()} {open
1624 } {
1625 code {// position vu meters on recorder tab
1626int startx=trackchan[0]->x();
1627int starty=trackchan[0]->y();
1628for (unsigned int i=1; i<=MAXCHANNELS; i++) {
1629 int coloff=((i-((i-1)%8))-1)/8;
1630 trackchan[i-1]->setui(this);
1631 trackchan[i-1]->position(7+(18*coloff)+(startx)+((i-1)*23),starty+10);
1632 trackchan[i-1]->setchnum(i);
1633
1634 solobutton[i-1]->position(8+(15*coloff)+(startx)+((i-1)*23),solobutton[i-1]->y());
1635 solobutton[i-1]->size(solobutton[0]->w(),solobutton[0]->h());
1636 solobutton[i-1]->up_image(solobutton[0]->up_image());
1637 solobutton[i-1]->down_image(solobutton[0]->down_image());
1638 mutebutton[i-1]->up_image(mutebutton[0]->up_image());
1639 mutebutton[i-1]->down_image(mutebutton[0]->down_image());
1640 mutebutton[i-1]->position(solobutton[i-1]->x(),mutebutton[i-1]->y());
1641 mutebutton[i-1]->size(mutebutton[0]->w(),mutebutton[0]->h());
1642
1643 armbutton[i-1]->position(solobutton[i-1]->x(),armbutton[i-1]->y());
1644 if (i!=1) {
1645 armbutton[i-1]->size(armbutton[0]->w(),armbutton[0]->h());
1646 armbutton[i-1]->up_image(armbutton[0]->up_image());
1647 armbutton[i-1]->down_image(armbutton[0]->down_image());
1648 }
1649
1650}
1651
1652
1653trackinfo[0]->position(8*23+15,starty+10);
1654trackinfo[1]->position(16*23+33,starty+10);} {}
1655 }
1656 Function {set_ui(HD24UserInterface* p_ui)} {open return_type void
1657 } {
1658 code {this->ui=p_ui;} {}
1659 }
1660 decl {bool mustdisplaytimer;} {public
1661 }
1662 decl {int loopmode;} {public
1663 }
1664 decl {RecorderChannelUI* recorderchannel[24];} {public
1665 }
1666 decl {/* ==== RECORDER UI STUFF ====================*/} {}
1667 decl {HD24UserInterface* ui;} {}
1668 decl {//hd24fs* currenthd24;} {public
1669 }
1670 decl {//hd24song* currsong;} {public
1671 }
1672 decl {Fl_Window* window} {}
1673 decl {int currpeakmode;} {public
1674 }
1675 decl {Fl_Box* dispcell[16][2];} {public
1676 }
1677 decl {Fl_Box* i7seg[10];} {public
1678 }
1679 decl {Fl_Box* dispfont[256];} {public
1680 }
1681 decl {int slidermoved;} {public
1682 }
1683 decl {Fl_Image_Button* armbutton[24];} {public
1684 }
1685 decl {Fl_Image_Toggle_Button* mutebutton[24];} {public
1686 }
1687 decl {Fl_Image_Toggle_Button* solobutton[24];} {public
1688 }
1689 decl {int blinkcounter; /* For blinking record enable leds of level meters etc */} {public
1690 }
1691 decl {HD24TrackChannel* trackchan[24];} {public
1692 }
1693 decl {TrackInfo* trackinfo[24];} {public
1694 }
1695 decl {char olddisp[32];} {}
1696 Function {dispwrite_raw(unsigned int line,const char* message,bool savedisp)} {private return_type void
1697 } {
1698 code {unsigned int max=strlen(message);
1699// allowed lines on display: 0 and 1
1700if (line>1) { return; }
1701
1702if (max>(16*(2-line))) {
1703 // maximum 16 chars if we start on line 1 (second line)
1704 // 32 chars if we start on line 0 (first line).
1705 max=(16*(2-line));
1706}
1707
1708for (unsigned int i=0;i<max;i++) {
1709 if (i==16) { line++; }
1710 unsigned int currchar=(unsigned int)((unsigned char)(message[i]));
1711 if (savedisp)
1712 {
1713 olddisp[(i%16)+(16*line)]=currchar;
1714 }
1715 this->dispcell[i%16][line]->image(dispfont[currchar]->image());
1716 this->dispcell[i%16][line]->redraw();
1717
1718}
1719fl_check();} {}
1720 }
1721 decl {int dispwritecountdown;} {public
1722 }
1723 Function {dispwrite(unsigned int line,const char* message)} {return_type void
1724 } {
1725 code {dispwrite_raw(line,message,true);
1726dispwritecountdown=0;} {}
1727 }
1728 Function {disprestore()} {return_type void
1729 } {
1730 code {dispwrite_raw(0,&olddisp[0],false);
1731dispwritecountdown=0;} {}
1732 }
1733 Function {dispwrite(unsigned int line,const char* message,__uint32 timeout_msec)} {return_type void
1734 } {
1735 code {dispwrite_raw(line,message,false);
1736 dispwritecountdown=(int)(1000*TIMEOUT);} {}
1737 }
1738 Function {readmixer()} {open return_type void
1739 } {
1740 code {// set solo status of channel to value
1741/*
1742for (unsigned int i=0;i<MAXCHANNELS;i++) {
1743 solobutton[i]->value(mixer->mixerchannel[i]->control->solo());
1744 solobutton[i]->redraw();
1745 mutebutton[i]->value(mixer->mixerchannel[i]->control->mute());
1746 mutebutton[i]->redraw();
1747}
1748*/} {}
1749 }
1750 Function {make_window() /*<-----------------------------------*/} {open
1751 } {
1752 Fl_Window recordergroup {open
1753 xywh {378 259 615 440} type Double
1754 code0 {o->position(this->x(),this->y());}
1755 class Fl_Group visible
1756 } {
1757 Fl_Group resources {open
1758 xywh {25 62 560 423} hide deactivate
1759 } {
1760 Fl_Button button_play_up {
1761 tooltip Play image {images/button_play.gif} xywh {25 75 50 30} labelsize 11 align 16 deactivate
1762 }
1763 Fl_Button button_play_dn {
1764 tooltip Play image {images/button_play_dn.gif} xywh {75 75 50 30} labelsize 11 align 16 deactivate
1765 }
1766 Fl_Button button_stop_dn {
1767 tooltip Play image {images/button_stop_dn.gif} xywh {295 445 50 30} labelsize 11 align 16 deactivate
1768 }
1769 Fl_Button button_stop_up {
1770 tooltip Play image {images/button_stop.gif} xywh {345 445 50 30} labelsize 11 align 16 deactivate
1771 }
1772 Fl_Button button_stop_uplit {
1773 tooltip Play image {images/button_stop_uplit.gif} xywh {355 455 50 30} labelsize 11 align 16 deactivate
1774 }
1775 Fl_Button button_small_up {
1776 tooltip arm image {images/button_small.gif} xywh {565 195 20 15} deactivate
1777 }
1778 Fl_Button button_small_dn {
1779 tooltip arm image {images/button_small_dn.gif} xywh {60 215 20 15} deactivate
1780 }
1781 Fl_Button button_rew_up {
1782 tooltip Play image {images/button_rew.gif} xywh {35 85 50 30} labelsize 11 align 16 deactivate
1783 }
1784 Fl_Button button_rew_dn {
1785 tooltip Play image {images/button_rew_dn.gif} xywh {85 85 50 30} labelsize 11 align 16 deactivate
1786 }
1787 Fl_Button button_ffwd_up {
1788 tooltip Play image {images/button_ffwd.gif} xywh {45 95 50 30} labelsize 11 align 16 deactivate
1789 }
1790 Fl_Button button_ffwd_dn {
1791 tooltip Play image {images/button_ffwd_dn.gif} xywh {95 95 50 30} labelsize 11 align 16 deactivate
1792 }
1793 Fl_Button button_rec_up {
1794 tooltip Play image {images/button_rec.gif} xywh {55 105 50 30} labelsize 11 align 16 deactivate
1795 }
1796 Fl_Button button_rec_dn {
1797 tooltip Play image {images/button_rec_dn.gif} xywh {105 105 50 30} labelsize 11 align 16 deactivate
1798 }
1799 Fl_Button button_mute_up {
1800 tooltip Play image {images/button_mute.gif} xywh {65 115 50 30} labelsize 11 align 16 deactivate
1801 }
1802 Fl_Button button_mute_dn {
1803 tooltip Play image {images/button_mute_dn.gif} xywh {115 115 50 30} labelsize 11 align 16 deactivate
1804 }
1805 Fl_Button button_solo_up {
1806 tooltip Play image {images/button_solo.gif} xywh {75 125 50 30} labelsize 11 align 16 deactivate
1807 }
1808 Fl_Button button_solo_dn {
1809 tooltip Play image {images/button_solo_dn.gif} xywh {125 125 50 30} labelsize 11 align 16 deactivate
1810 }
1811 Fl_Button button_lrc_led_up {
1812 tooltip Play image {images/button_lrc_led.gif} xywh {85 135 50 30} labelsize 11 align 16 deactivate
1813 }
1814 Fl_Button button_lrc_led_dn {
1815 tooltip Play image {images/button_lrc_led_dn.gif} xywh {135 135 50 30} labelsize 11 align 16 deactivate
1816 }
1817 Fl_Button button_lrc_led_on_up {
1818 tooltip Play image {images/button_lrc_led_on.gif} xywh {85 135 50 30} labelsize 11 align 16 deactivate
1819 }
1820 Fl_Button button_lrc_led_on_dn {
1821 tooltip Play image {images/button_lrc_led_on_dn.gif} xywh {135 135 50 30} labelsize 11 align 16 deactivate
1822 }
1823 Fl_Button button_lrc_up {
1824 tooltip Play image {images/button_lrc.gif} xywh {85 135 50 30} labelsize 11 align 16 deactivate
1825 }
1826 Fl_Button button_lrc_dn {
1827 tooltip Play image {images/button_lrc_dn.gif} xywh {135 135 50 30} labelsize 11 align 16 deactivate
1828 }
1829 Fl_Box i7seg0 {
1830 image {images/7seg_0.gif} xywh {325 276 20 34} hide
1831 code0 {i7seg[0]=o;}
1832 }
1833 Fl_Box i7seg1 {
1834 image {images/7seg_1.gif} xywh {325 276 20 34} hide
1835 code0 {i7seg[1]=o;}
1836 }
1837 Fl_Box i7seg2 {
1838 image {images/7seg_2.gif} xywh {325 276 20 34} hide
1839 code0 {i7seg[2]=o;}
1840 }
1841 Fl_Box i7seg3 {
1842 image {images/7seg_3.gif} xywh {325 276 20 34} hide
1843 code0 {i7seg[3]=o;}
1844 }
1845 Fl_Box i7seg4 {
1846 image {images/7seg_4.gif} xywh {325 276 20 34} hide
1847 code0 {i7seg[4]=o;}
1848 }
1849 Fl_Box i7seg5 {
1850 image {images/7seg_5.gif} xywh {325 276 20 34} hide
1851 code0 {i7seg[5]=o;}
1852 }
1853 Fl_Box i7seg6 {
1854 image {images/7seg_6.gif} xywh {325 276 20 34} hide
1855 code0 {i7seg[6]=o;}
1856 }
1857 Fl_Box i7seg7 {
1858 image {images/7seg_7.gif} xywh {325 276 20 34} hide
1859 code0 {i7seg[7]=o;}
1860 }
1861 Fl_Box i7seg8 {
1862 image {images/7seg_8.gif} xywh {325 276 20 34} hide
1863 code0 {i7seg[8]=o;}
1864 }
1865 Fl_Box i7seg9 {
1866 image {images/7seg_9.gif} xywh {325 276 20 34} hide
1867 code0 {i7seg[9]=o;}
1868 }
1869 Fl_Group dispfontgroup {
1870 label font open
1871 xywh {565 28 70 52} hide deactivate
1872 } {
1873 Fl_Box {} {
1874 label label
1875 image {images/HD24_matrix_32.gif} xywh {580 43 35 17} hide
1876 code0 {this->dispfont[32]=o;}
1877 }
1878 Fl_Box {} {
1879 label label
1880 image {images/HD24_matrix_33.gif} xywh {580 43 35 17} hide
1881 code0 {this->dispfont[33]=o;}
1882 }
1883 Fl_Box {} {
1884 label label
1885 image {images/HD24_matrix_34.gif} xywh {580 43 35 17} hide
1886 code0 {this->dispfont[34]=o;}
1887 }
1888 Fl_Box {} {
1889 label label
1890 image {images/HD24_matrix_35.gif} xywh {580 43 35 17} hide
1891 code0 {this->dispfont[35]=o;}
1892 }
1893 Fl_Box {} {
1894 label label
1895 image {images/HD24_matrix_36.gif} xywh {580 43 35 17} hide
1896 code0 {this->dispfont[36]=o;}
1897 }
1898 Fl_Box {} {
1899 label label
1900 image {images/HD24_matrix_37.gif} xywh {580 43 35 17} hide
1901 code0 {this->dispfont[37]=o;}
1902 }
1903 Fl_Box {} {
1904 label label
1905 image {images/HD24_matrix_38.gif} xywh {580 43 35 17} hide
1906 code0 {this->dispfont[38]=o;}
1907 }
1908 Fl_Box {} {
1909 label label
1910 image {images/HD24_matrix_39.gif} xywh {580 43 35 17} hide
1911 code0 {this->dispfont[39]=o;}
1912 }
1913 Fl_Box {} {
1914 label label
1915 image {images/HD24_matrix_40.gif} xywh {580 43 35 17} hide
1916 code0 {this->dispfont[40]=o;}
1917 }
1918 Fl_Box {} {
1919 label label
1920 image {images/HD24_matrix_41.gif} xywh {580 43 35 17} hide
1921 code0 {this->dispfont[41]=o;}
1922 }
1923 Fl_Box {} {
1924 label label
1925 image {images/HD24_matrix_42.gif} xywh {580 43 35 17} hide
1926 code0 {this->dispfont[42]=o;}
1927 }
1928 Fl_Box {} {
1929 label label
1930 image {images/HD24_matrix_43.gif} xywh {580 43 35 17} hide
1931 code0 {this->dispfont[43]=o;}
1932 }
1933 Fl_Box {} {
1934 label label
1935 image {images/HD24_matrix_44.gif} xywh {580 43 35 17} hide
1936 code0 {this->dispfont[44]=o;}
1937 }
1938 Fl_Box {} {
1939 label label
1940 image {images/HD24_matrix_45.gif} xywh {580 43 35 17} hide
1941 code0 {this->dispfont[45]=o;}
1942 }
1943 Fl_Box {} {
1944 label label
1945 image {images/HD24_matrix_46.gif} xywh {580 43 35 17} hide
1946 code0 {this->dispfont[46]=o;}
1947 }
1948 Fl_Box {} {
1949 label label
1950 image {images/HD24_matrix_47.gif} xywh {580 43 35 17} hide
1951 code0 {this->dispfont[47]=o;}
1952 }
1953 Fl_Box {} {
1954 label label
1955 image {images/HD24_matrix_48.gif} xywh {580 43 35 17} hide
1956 code0 {this->dispfont[48]=o;}
1957 }
1958 Fl_Box {} {
1959 label label
1960 image {images/HD24_matrix_49.gif} xywh {580 43 35 17} hide
1961 code0 {this->dispfont[49]=o;}
1962 }
1963 Fl_Box {} {
1964 label label
1965 image {images/HD24_matrix_50.gif} xywh {580 43 35 17} hide
1966 code0 {this->dispfont[50]=o;}
1967 }
1968 Fl_Box {} {
1969 label label
1970 image {images/HD24_matrix_51.gif} xywh {580 43 35 17} hide
1971 code0 {this->dispfont[51]=o;}
1972 }
1973 Fl_Box {} {
1974 label label
1975 image {images/HD24_matrix_52.gif} xywh {580 43 35 17} hide
1976 code0 {this->dispfont[52]=o;}
1977 }
1978 Fl_Box {} {
1979 label label
1980 image {images/HD24_matrix_53.gif} xywh {580 43 35 17} hide
1981 code0 {this->dispfont[53]=o;}
1982 }
1983 Fl_Box {} {
1984 label label
1985 image {images/HD24_matrix_54.gif} xywh {580 43 35 17} hide
1986 code0 {this->dispfont[54]=o;}
1987 }
1988 Fl_Box {} {
1989 label label
1990 image {images/HD24_matrix_55.gif} xywh {580 43 35 17} hide
1991 code0 {this->dispfont[55]=o;}
1992 }
1993 Fl_Box {} {
1994 label label
1995 image {images/HD24_matrix_56.gif} xywh {580 43 35 17} hide
1996 code0 {this->dispfont[56]=o;}
1997 }
1998 Fl_Box {} {
1999 label label
2000 image {images/HD24_matrix_57.gif} xywh {580 43 35 17} hide
2001 code0 {this->dispfont[57]=o;}
2002 }
2003 Fl_Box {} {
2004 label label
2005 image {images/HD24_matrix_58.gif} xywh {580 43 35 17} hide
2006 code0 {this->dispfont[58]=o;}
2007 }
2008 Fl_Box {} {
2009 label label
2010 image {images/HD24_matrix_59.gif} xywh {580 43 35 17} hide
2011 code0 {this->dispfont[59]=o;}
2012 }
2013 Fl_Box {} {
2014 label label
2015 image {images/HD24_matrix_60.gif} xywh {580 43 35 17} hide
2016 code0 {this->dispfont[60]=o;}
2017 }
2018 Fl_Box {} {
2019 label label
2020 image {images/HD24_matrix_61.gif} xywh {580 43 35 17} hide
2021 code0 {this->dispfont[61]=o;}
2022 }
2023 Fl_Box {} {
2024 label label
2025 image {images/HD24_matrix_62.gif} xywh {580 43 35 17} hide
2026 code0 {this->dispfont[62]=o;}
2027 }
2028 Fl_Box {} {
2029 label label
2030 image {images/HD24_matrix_63.gif} xywh {580 43 35 17} hide
2031 code0 {this->dispfont[63]=o;}
2032 }
2033 Fl_Box {} {
2034 label label
2035 image {images/HD24_matrix_64.gif} xywh {580 43 35 17} hide
2036 code0 {this->dispfont[64]=o;}
2037 }
2038 Fl_Box {} {
2039 label A
2040 image {images/HD24_matrix_65.gif} xywh {580 43 35 17} hide
2041 code0 {this->dispfont[65]=o;}
2042 }
2043 Fl_Box {} {
2044 label B
2045 image {images/HD24_matrix_66.gif} xywh {580 43 35 17} hide
2046 code0 {this->dispfont[66]=o;}
2047 }
2048 Fl_Box {} {
2049 label C
2050 image {images/HD24_matrix_67.gif} xywh {580 43 35 17} hide
2051 code0 {this->dispfont[67]=o;}
2052 }
2053 Fl_Box {} {
2054 label D
2055 image {images/HD24_matrix_68.gif} xywh {580 43 35 17} hide
2056 code0 {this->dispfont[68]=o;}
2057 }
2058 Fl_Box {} {
2059 label E
2060 image {images/HD24_matrix_69.gif} xywh {580 43 35 17} hide
2061 code0 {this->dispfont[69]=o;}
2062 }
2063 Fl_Box {} {
2064 label F
2065 image {images/HD24_matrix_70.gif} xywh {580 43 35 17} hide
2066 code0 {this->dispfont[70]=o;}
2067 }
2068 Fl_Box {} {
2069 label G
2070 image {images/HD24_matrix_71.gif} xywh {580 43 35 17} hide
2071 code0 {this->dispfont[71]=o;}
2072 }
2073 Fl_Box {} {
2074 label H
2075 image {images/HD24_matrix_72.gif} xywh {580 43 35 17} hide
2076 code0 {this->dispfont[72]=o;}
2077 }
2078 Fl_Box {} {
2079 label I
2080 image {images/HD24_matrix_73.gif} xywh {580 43 35 17} hide
2081 code0 {this->dispfont[73]=o;}
2082 }
2083 Fl_Box {} {
2084 label J
2085 image {images/HD24_matrix_74.gif} xywh {580 43 35 17} hide
2086 code0 {this->dispfont[74]=o;}
2087 }
2088 Fl_Box {} {
2089 label K
2090 image {images/HD24_matrix_75.gif} xywh {580 43 35 17} hide
2091 code0 {this->dispfont[75]=o;}
2092 }
2093 Fl_Box {} {
2094 label L
2095 image {images/HD24_matrix_76.gif} xywh {580 43 35 17} hide
2096 code0 {this->dispfont[76]=o;}
2097 }
2098 Fl_Box {} {
2099 label M
2100 image {images/HD24_matrix_77.gif} xywh {580 43 35 17} hide
2101 code0 {this->dispfont[77]=o;}
2102 }
2103 Fl_Box {} {
2104 label N
2105 image {images/HD24_matrix_78.gif} xywh {580 43 35 17} hide
2106 code0 {this->dispfont[78]=o;}
2107 }
2108 Fl_Box {} {
2109 label O
2110 image {images/HD24_matrix_79.gif} xywh {580 43 35 17} hide
2111 code0 {this->dispfont[79]=o;}
2112 }
2113 Fl_Box {} {
2114 label P
2115 image {images/HD24_matrix_80.gif} xywh {580 43 35 17} hide
2116 code0 {this->dispfont[80]=o;}
2117 }
2118 Fl_Box {} {
2119 label Q
2120 image {images/HD24_matrix_81.gif} xywh {580 43 35 17} hide
2121 code0 {this->dispfont[81]=o;}
2122 }
2123 Fl_Box {} {
2124 label R
2125 image {images/HD24_matrix_82.gif} xywh {580 43 35 17} hide
2126 code0 {this->dispfont[82]=o;}
2127 }
2128 Fl_Box {} {
2129 label S
2130 image {images/HD24_matrix_83.gif} xywh {580 43 35 17} hide
2131 code0 {this->dispfont[83]=o;}
2132 }
2133 Fl_Box {} {
2134 label T
2135 image {images/HD24_matrix_84.gif} xywh {580 43 35 17} hide
2136 code0 {this->dispfont[84]=o;}
2137 }
2138 Fl_Box {} {
2139 label U
2140 image {images/HD24_matrix_85.gif} xywh {580 43 35 17} hide
2141 code0 {this->dispfont[85]=o;}
2142 }
2143 Fl_Box {} {
2144 label V
2145 image {images/HD24_matrix_86.gif} xywh {580 43 35 17} hide
2146 code0 {this->dispfont[86]=o;}
2147 }
2148 Fl_Box {} {
2149 label W
2150 image {images/HD24_matrix_87.gif} xywh {580 43 35 17} hide
2151 code0 {this->dispfont[87]=o;}
2152 }
2153 Fl_Box {} {
2154 label X
2155 image {images/HD24_matrix_88.gif} xywh {580 43 35 17} hide
2156 code0 {this->dispfont[88]=o;}
2157 }
2158 Fl_Box {} {
2159 label Y
2160 image {images/HD24_matrix_89.gif} xywh {580 43 35 17} hide
2161 code0 {this->dispfont[89]=o;}
2162 }
2163 Fl_Box {} {
2164 label Z
2165 image {images/HD24_matrix_90.gif} xywh {580 43 35 17} hide
2166 code0 {this->dispfont[90]=o;}
2167 }
2168 Fl_Box {} {
2169 label label
2170 image {images/HD24_matrix_91.gif} xywh {580 43 35 17} hide
2171 code0 {this->dispfont[91]=o;}
2172 }
2173 Fl_Box {} {
2174 label label
2175 image {images/HD24_matrix_92.gif} xywh {580 43 35 17} hide
2176 code0 {this->dispfont[92]=o;}
2177 }
2178 Fl_Box {} {
2179 label label
2180 image {images/HD24_matrix_93.gif} xywh {580 43 35 17} hide
2181 code0 {this->dispfont[93]=o;}
2182 }
2183 Fl_Box {} {
2184 label label
2185 image {images/HD24_matrix_94.gif} xywh {580 43 35 17} hide
2186 code0 {this->dispfont[94]=o;}
2187 }
2188 Fl_Box {} {
2189 label label
2190 image {images/HD24_matrix_95.gif} xywh {580 43 35 17} hide
2191 code0 {this->dispfont[95]=o;}
2192 }
2193 Fl_Box {} {
2194 label label
2195 image {images/HD24_matrix_96.gif} xywh {580 43 35 17} hide
2196 code0 {this->dispfont[96]=o;}
2197 }
2198 Fl_Box {} {
2199 label label
2200 image {images/HD24_matrix_97.gif} xywh {580 43 35 17} hide
2201 code0 {this->dispfont[97]=o;}
2202 }
2203 Fl_Box {} {
2204 label label
2205 image {images/HD24_matrix_98.gif} xywh {580 43 35 17} hide
2206 code0 {this->dispfont[98]=o;}
2207 }
2208 Fl_Box {} {
2209 label label
2210 image {images/HD24_matrix_99.gif} xywh {580 43 35 17} hide
2211 code0 {this->dispfont[99]=o;}
2212 }
2213 Fl_Box {} {
2214 label label
2215 image {images/HD24_matrix_100.gif} xywh {580 43 35 17} hide
2216 code0 {this->dispfont[100]=o;}
2217 }
2218 Fl_Box {} {
2219 label label
2220 image {images/HD24_matrix_101.gif} xywh {580 43 35 17} hide
2221 code0 {this->dispfont[101]=o;}
2222 }
2223 Fl_Box {} {
2224 label label
2225 image {images/HD24_matrix_102.gif} xywh {580 43 35 17} hide
2226 code0 {this->dispfont[102]=o;}
2227 }
2228 Fl_Box {} {
2229 label label
2230 image {images/HD24_matrix_103.gif} xywh {580 43 35 17} hide
2231 code0 {this->dispfont[103]=o;}
2232 }
2233 Fl_Box {} {
2234 label label
2235 image {images/HD24_matrix_104.gif} xywh {580 43 35 17} hide
2236 code0 {this->dispfont[104]=o;}
2237 }
2238 Fl_Box {} {
2239 label label
2240 image {images/HD24_matrix_105.gif} xywh {580 43 35 17} hide
2241 code0 {this->dispfont[105]=o;}
2242 }
2243 Fl_Box {} {
2244 label label
2245 image {images/HD24_matrix_106.gif} xywh {580 43 35 17} hide
2246 code0 {this->dispfont[106]=o;}
2247 }
2248 Fl_Box {} {
2249 label label
2250 image {images/HD24_matrix_107.gif} xywh {580 43 35 17} hide
2251 code0 {this->dispfont[107]=o;}
2252 }
2253 Fl_Box {} {
2254 label label
2255 image {images/HD24_matrix_108.gif} xywh {580 43 35 17} hide
2256 code0 {this->dispfont[108]=o;}
2257 }
2258 Fl_Box {} {
2259 label label
2260 image {images/HD24_matrix_109.gif} xywh {580 43 35 17} hide
2261 code0 {this->dispfont[109]=o;}
2262 }
2263 Fl_Box {} {
2264 label label
2265 image {images/HD24_matrix_110.gif} xywh {580 43 35 17} hide
2266 code0 {this->dispfont[110]=o;}
2267 }
2268 Fl_Box {} {
2269 label label
2270 image {images/HD24_matrix_111.gif} xywh {580 43 35 17} hide
2271 code0 {this->dispfont[111]=o;}
2272 }
2273 Fl_Box {} {
2274 label label
2275 image {images/HD24_matrix_112.gif} xywh {580 43 35 17} hide
2276 code0 {this->dispfont[112]=o;}
2277 }
2278 Fl_Box {} {
2279 label label
2280 image {images/HD24_matrix_113.gif} xywh {580 43 35 17} hide
2281 code0 {this->dispfont[113]=o;}
2282 }
2283 Fl_Box {} {
2284 label label
2285 image {images/HD24_matrix_114.gif} xywh {580 43 35 17} hide
2286 code0 {this->dispfont[114]=o;}
2287 }
2288 Fl_Box {} {
2289 label label
2290 image {images/HD24_matrix_115.gif} xywh {580 43 35 17} hide
2291 code0 {this->dispfont[115]=o;}
2292 }
2293 Fl_Box {} {
2294 label label
2295 image {images/HD24_matrix_116.gif} xywh {580 43 35 17} hide
2296 code0 {this->dispfont[116]=o;}
2297 }
2298 Fl_Box {} {
2299 label label
2300 image {images/HD24_matrix_117.gif} xywh {580 43 35 17} hide
2301 code0 {this->dispfont[117]=o;}
2302 }
2303 Fl_Box {} {
2304 label label
2305 image {images/HD24_matrix_118.gif} xywh {580 43 35 17} hide
2306 code0 {this->dispfont[118]=o;}
2307 }
2308 Fl_Box {} {
2309 label label
2310 image {images/HD24_matrix_119.gif} xywh {580 43 35 17} hide
2311 code0 {this->dispfont[119]=o;}
2312 }
2313 Fl_Box {} {
2314 label label
2315 image {images/HD24_matrix_120.gif} xywh {580 43 35 17} hide
2316 code0 {this->dispfont[120]=o;}
2317 }
2318 Fl_Box {} {
2319 label label
2320 image {images/HD24_matrix_121.gif} xywh {580 43 35 17} hide
2321 code0 {this->dispfont[121]=o;}
2322 }
2323 Fl_Box {} {
2324 label label
2325 image {images/HD24_matrix_122.gif} xywh {580 43 35 17} hide
2326 code0 {this->dispfont[122]=o;}
2327 }
2328 Fl_Box {} {
2329 label label
2330 image {images/HD24_matrix_123.gif} xywh {580 43 35 17} hide
2331 code0 {this->dispfont[123]=o;}
2332 }
2333 Fl_Box {} {
2334 label label
2335 image {images/HD24_matrix_124.gif} xywh {580 43 35 17} hide
2336 code0 {this->dispfont[124]=o;}
2337 }
2338 Fl_Box {} {
2339 label label
2340 image {images/HD24_matrix_125.gif} xywh {580 43 35 17} hide
2341 code0 {this->dispfont[125]=o;}
2342 }
2343 Fl_Box {} {
2344 label label
2345 image {images/HD24_matrix_126.gif} xywh {580 43 35 17} hide
2346 code0 {this->dispfont[126]=o;}
2347 }
2348 Fl_Box {} {
2349 label label
2350 image {images/HD24_matrix_127.gif} xywh {580 43 35 17} hide
2351 code0 {this->dispfont[127]=o;}
2352 }
2353 Fl_Box {} {
2354 label writeprotect
2355 image {images/HD24_matrix_writeprotected.gif} xywh {590 53 35 17} hide
2356 code0 {this->dispfont[1]=o;}
2357 }
2358 Fl_Box {} {
2359 label writeenable
2360 image {images/HD24_matrix_writeenabled.gif} xywh {600 63 35 17} hide
2361 code0 {this->dispfont[2]=o;}
2362 }
2363 Fl_Box {} {
2364 label {arrow left}
2365 image {images/HD24_matrix_arrowleft.gif} xywh {600 63 35 17} hide
2366 code0 {this->dispfont[3]=o;}
2367 }
2368 Fl_Box {} {
2369 label {arrow right}
2370 image {images/HD24_matrix_arrowright.gif} xywh {610 73 35 17} hide
2371 code0 {this->dispfont[4]=o;}
2372 }
2373 }
2374 }
2375 Fl_Slider locationslider {
2376 callback {hd24song* currsong=(hd24song*)(this->control->song());
2377if (currsong==NULL) return;
2378this->slidermoved=3;
2379long long newpos=(long long)currsong->songlength_in_samples();
2380newpos*=(int)(o->value());
2381newpos=(__uint32)(newpos/1000);
2382control->hd24_transport_goloc(newpos);}
2383 xywh {10 208 595 17} type Horizontal selection_color 41 labelsize 12 align 4 maximum 1000 step 1
2384 code0 {this->slidermoved=0;}
2385 }
2386 Fl_Box {} {
2387 xywh {305 226 300 149} box DOWN_BOX color 8
2388 }
2389 Fl_Button button_setlocate {
2390 label {SET LOC}
2391 callback {control->highlight_setbuttons(o->value());}
2392 tooltip {Set Locate} xywh {420 290 50 20} type Toggle box FLAT_BOX down_box FLAT_BOX color 16 selection_color 18 labelfont 1 labelsize 9 labelcolor 7 align 5
2393 code0 {o->up_image(button_lrc_up->image()); o->down_image(button_lrc_dn->image());}
2394 class Fl_Image_Toggle_Button
2395 }
2396 Fl_Button button_loopmode {
2397 label {AUTO LOOP}
2398 callback {control->loopmode(button_loopmode->value());}
2399 tooltip {Auto Loop} xywh {310 250 50 20} type Toggle box FLAT_BOX down_box FLAT_BOX color 16 selection_color 18 labelfont 1 labelsize 9 labelcolor 7 align 5
2400 code0 {o->up_image(button_lrc_up->image()); o->down_image(button_lrc_dn->image());}
2401 class Fl_Image_Toggle_Button
2402 }
2403 Fl_Repeat_Button button_rew {
2404 callback {control->button_rew_call();}
2405 tooltip Rewind image {images/button_rew.gif} xywh {310 330 50 30} box FLAT_BOX labelsize 11 align 16
2406 code0 {o->up_image(o->image()); o->down_image(button_rew_dn->image()); o->image(NULL);}
2407 class Fl_Image_Repeat_Button
2408 }
2409 Fl_Repeat_Button button_ffwd {
2410 callback {control->button_ffwd_call();}
2411 tooltip {F Fwd} image {images/button_ffwd.gif} xywh {370 330 50 30} box FLAT_BOX labelsize 11 align 16
2412 code0 {o->up_image(o->image()); o->down_image(button_ffwd_dn->image()); o->image(NULL);}
2413 class Fl_Image_Repeat_Button
2414 }
2415 Fl_Button button_stop {
2416 callback {if (control!=NULL) control->button_stop_call();}
2417 tooltip Stop image {images/button_stop_uplit.gif} xywh {430 330 50 30} box FLAT_BOX labelsize 11 align 16
2418 code0 {//o->up_image(button_stop_uplit->image()); o->down_image(button_stop_dn->image());}
2419 code1 {o->up_image(o->image()); o->down_image(button_stop_dn->image()); o->image(NULL);}
2420 class Fl_Image_Button
2421 }
2422 Fl_Button button_play {
2423 callback {control->button_play_call();}
2424 tooltip Play image {images/button_play.gif} xywh {490 330 50 30} box FLAT_BOX labelsize 11 align 16
2425 code0 {o->up_image(o->image()); o->down_image(button_play_dn->image()); o->image(NULL);}
2426 class Fl_Image_Button
2427 }
2428 Fl_Box {} {
2429 xywh {475 231 127 84} box BORDER_BOX color 0
2430 }
2431 Fl_Button button_loopstart {
2432 label {LOOP START}
2433 callback {control->handlelocatebutton(hd24song::LOCATEPOS_LOOPSTART);}
2434 tooltip {Loop Start} xywh {485 250 50 20} box FLAT_BOX down_box FLAT_BOX color 16 selection_color 18 labelfont 1 labelsize 9 labelcolor 7 align 1
2435 code0 {hlbuttons_defaultcolor=o->color(); o->up_image(button_lrc_led_up->image()); o->down_image(button_lrc_led_dn->image());}
2436 class Fl_Image_Button
2437 }
2438 Fl_Button button_loopend {
2439 label {LOOP END}
2440 callback {control->handlelocatebutton(hd24song::LOCATEPOS_LOOPEND);}
2441 tooltip {Loop End} xywh {550 250 50 20} box FLAT_BOX down_box FLAT_BOX color 16 selection_color 18 labelfont 1 labelsize 9 labelcolor 7 align 9
2442 code0 {o->up_image(button_lrc_led_up->image()); o->down_image(button_lrc_led_dn->image());}
2443 class Fl_Image_Button
2444 }
2445 Fl_Button button_locate0 {
2446 label {LOC 0}
2447 callback {control->audio->hd24_transport_locate((__sint64)0);}
2448 tooltip {Locate 0} xywh {420 250 50 20} box FLAT_BOX color 16 selection_color 18 labelfont 1 labelsize 9 labelcolor 7 align 5
2449 code0 {o->up_image(button_lrc_up->image()); o->down_image(button_lrc_dn->image());}
2450 class Fl_Image_Button
2451 }
2452 Fl_Button button_rec {
2453 callback {control->button_rec_call();}
2454 tooltip Record image {images/button_rec.gif} xywh {550 330 50 30} type Toggle box FLAT_BOX labelsize 11
2455 code0 {o->up_image(o->image()); o->down_image(button_rec_dn->image()); o->image(NULL);}
2456 class Fl_Image_Toggle_Button
2457 }
2458 Fl_Group channelcanvas {open
2459 xywh {10 15 595 140} box DOWN_BOX color 0
2460 } {
2461 Fl_Group tc1 {open
2462 xywh {15 15 15 135}
2463 code0 {trackchan[0]=o;}
2464 class HD24TrackChannel
2465 } {}
2466 Fl_Group tc2 {open
2467 xywh {15 15 15 135}
2468 code0 {trackchan[1]=o;}
2469 class HD24TrackChannel
2470 } {}
2471 Fl_Group tc3 {open
2472 xywh {15 15 15 135}
2473 code0 {trackchan[2]=o;}
2474 class HD24TrackChannel
2475 } {}
2476 Fl_Group tc4 {open
2477 xywh {15 15 15 135}
2478 code0 {trackchan[3]=o;}
2479 class HD24TrackChannel
2480 } {}
2481 Fl_Group tc5 {open
2482 xywh {15 15 15 135}
2483 code0 {trackchan[4]=o;}
2484 class HD24TrackChannel
2485 } {}
2486 Fl_Group tc6 {open
2487 xywh {15 15 15 135}
2488 code0 {trackchan[5]=o;}
2489 class HD24TrackChannel
2490 } {}
2491 Fl_Group tc7 {open
2492 xywh {15 15 15 135}
2493 code0 {trackchan[6]=o;}
2494 class HD24TrackChannel
2495 } {}
2496 Fl_Group tc8 {open
2497 xywh {15 15 15 135}
2498 code0 {trackchan[7]=o;}
2499 class HD24TrackChannel
2500 } {}
2501 Fl_Group trackinfo1 {open
2502 xywh {15 15 15 135}
2503 code0 {trackinfo[0]=trackinfo1;}
2504 class TrackInfo
2505 } {}
2506 Fl_Group tc9 {open
2507 xywh {15 15 15 135}
2508 code0 {trackchan[8]=o;}
2509 class HD24TrackChannel
2510 } {}
2511 Fl_Group tc10 {open
2512 xywh {15 15 15 135}
2513 code0 {trackchan[9]=o;}
2514 class HD24TrackChannel
2515 } {}
2516 Fl_Group tc11 {open
2517 xywh {15 15 15 135}
2518 code0 {trackchan[10]=o;}
2519 class HD24TrackChannel
2520 } {}
2521 Fl_Group tc12 {open
2522 xywh {15 15 15 135}
2523 code0 {trackchan[11]=o;}
2524 class HD24TrackChannel
2525 } {}
2526 Fl_Group tc13 {open
2527 xywh {15 15 15 135}
2528 code0 {trackchan[12]=o;}
2529 class HD24TrackChannel
2530 } {}
2531 Fl_Group tc14 {open
2532 xywh {15 15 15 135}
2533 code0 {trackchan[13]=o;}
2534 class HD24TrackChannel
2535 } {}
2536 Fl_Group tc15 {open
2537 xywh {15 15 15 135}
2538 code0 {trackchan[14]=o;}
2539 class HD24TrackChannel
2540 } {}
2541 Fl_Group tc16 {open
2542 xywh {15 15 15 135}
2543 code0 {trackchan[15]=o;}
2544 class HD24TrackChannel
2545 } {}
2546 Fl_Group trackinfo2 {open
2547 xywh {15 15 15 135}
2548 code0 {trackinfo[1]=trackinfo2;}
2549 class TrackInfo
2550 } {}
2551 Fl_Group tc17 {open
2552 xywh {15 15 15 135}
2553 code0 {trackchan[16]=o;}
2554 class HD24TrackChannel
2555 } {}
2556 Fl_Group tc18 {open
2557 xywh {15 15 15 135}
2558 code0 {trackchan[17]=o;}
2559 class HD24TrackChannel
2560 } {}
2561 Fl_Group tc19 {open
2562 xywh {15 15 15 135}
2563 code0 {trackchan[18]=o;}
2564 class HD24TrackChannel
2565 } {}
2566 Fl_Group tc20 {open
2567 xywh {15 15 15 135}
2568 code0 {trackchan[19]=o;}
2569 class HD24TrackChannel
2570 } {}
2571 Fl_Group tc21 {open
2572 xywh {15 15 15 135}
2573 code0 {trackchan[20]=o;}
2574 class HD24TrackChannel
2575 } {}
2576 Fl_Group tc22 {open
2577 xywh {15 15 15 135}
2578 code0 {trackchan[21]=o;}
2579 class HD24TrackChannel
2580 } {}
2581 Fl_Group tc23 {open
2582 xywh {15 15 15 135}
2583 code0 {trackchan[22]=o;}
2584 class HD24TrackChannel
2585 } {}
2586 Fl_Group tc24 {open
2587 xywh {15 15 15 135}
2588 code0 {trackchan[23]=o;}
2589 class HD24TrackChannel
2590 } {}
2591 Fl_Group {} {open
2592 xywh {35 40 15 15}
2593 } {}
2594 }
2595 Fl_Button arm1 {
2596 callback {this->control->toggletrackarmed(1);}
2597 tooltip arm xywh {40 155 20 15} labelsize 8 labelcolor 7
2598 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[0]=o;}
2599 class Fl_Image_Button
2600 }
2601 Fl_Button arm2 {
2602 callback {this->control->toggletrackarmed(2);}
2603 tooltip arm xywh {60 155 15 15}
2604 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[1]=o;}
2605 class Fl_Image_Button
2606 }
2607 Fl_Button arm3 {
2608 callback {this->control->toggletrackarmed(3);}
2609 tooltip arm xywh {75 155 15 15}
2610 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[2]=o;}
2611 class Fl_Image_Button
2612 }
2613 Fl_Button arm4 {
2614 callback {this->control->toggletrackarmed(4);}
2615 tooltip arm xywh {90 155 15 15}
2616 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[3]=o;}
2617 class Fl_Image_Button
2618 }
2619 Fl_Button arm5 {
2620 callback {this->control->toggletrackarmed(5);}
2621 tooltip arm xywh {105 155 15 15}
2622 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[4]=o;}
2623 class Fl_Image_Button
2624 }
2625 Fl_Button arm6 {
2626 callback {this->control->toggletrackarmed(6);}
2627 tooltip arm xywh {120 155 15 15}
2628 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[5]=o;}
2629 class Fl_Image_Button
2630 }
2631 Fl_Button arm7 {
2632 callback {this->control->toggletrackarmed(7);}
2633 tooltip arm xywh {135 155 15 15}
2634 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[6]=o;}
2635 class Fl_Image_Button
2636 }
2637 Fl_Button arm8 {
2638 callback {this->control->toggletrackarmed(8);}
2639 tooltip arm xywh {150 155 15 15}
2640 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[7]=o;}
2641 class Fl_Image_Button
2642 }
2643 Fl_Button arm9 {
2644 callback {this->control->toggletrackarmed(9);}
2645 tooltip arm xywh {235 155 15 15}
2646 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[8]=o;}
2647 class Fl_Image_Button
2648 }
2649 Fl_Button arm10 {
2650 callback {this->control->toggletrackarmed(10);}
2651 tooltip arm xywh {250 155 15 15}
2652 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[9]=o;}
2653 class Fl_Image_Button
2654 }
2655 Fl_Button arm11 {
2656 callback {this->control->toggletrackarmed(11);}
2657 tooltip arm xywh {265 155 15 15}
2658 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[10]=o;}
2659 class Fl_Image_Button
2660 }
2661 Fl_Button arm12 {
2662 callback {this->control->toggletrackarmed(12);}
2663 tooltip arm xywh {280 155 15 15}
2664 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[11]=o;}
2665 class Fl_Image_Button
2666 }
2667 Fl_Button arm13 {
2668 callback {this->control->toggletrackarmed(13);}
2669 tooltip arm xywh {295 155 15 15}
2670 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[12]=o;}
2671 class Fl_Image_Button
2672 }
2673 Fl_Button arm14 {
2674 callback {this->control->toggletrackarmed(14);}
2675 tooltip arm xywh {310 155 15 15}
2676 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[13]=o;}
2677 class Fl_Image_Button
2678 }
2679 Fl_Button arm15 {
2680 callback {this->control->toggletrackarmed(15);}
2681 tooltip arm xywh {325 155 15 15}
2682 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[14]=o;}
2683 class Fl_Image_Button
2684 }
2685 Fl_Button arm16 {
2686 callback {this->control->toggletrackarmed(16);}
2687 tooltip arm xywh {340 155 15 15}
2688 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[15]=o;}
2689 class Fl_Image_Button
2690 }
2691 Fl_Button arm17 {
2692 callback {this->control->toggletrackarmed(17);}
2693 tooltip arm xywh {430 155 15 15}
2694 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[16]=o;}
2695 class Fl_Image_Button
2696 }
2697 Fl_Button arm18 {
2698 callback {this->control->toggletrackarmed(18);}
2699 tooltip arm xywh {445 155 15 15}
2700 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[17]=o;}
2701 class Fl_Image_Button
2702 }
2703 Fl_Button arm19 {
2704 callback {this->control->toggletrackarmed(19);}
2705 tooltip arm xywh {460 155 15 15}
2706 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[18]=o;}
2707 class Fl_Image_Button
2708 }
2709 Fl_Button arm20 {
2710 callback {this->control->toggletrackarmed(20);}
2711 tooltip arm xywh {475 155 15 15}
2712 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[19]=o;}
2713 class Fl_Image_Button
2714 }
2715 Fl_Button arm21 {
2716 callback {this->control->toggletrackarmed(21);}
2717 tooltip arm xywh {490 155 15 15}
2718 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[20]=o;}
2719 class Fl_Image_Button
2720 }
2721 Fl_Button arm22 {
2722 callback {this->control->toggletrackarmed(22);}
2723 tooltip arm xywh {505 155 15 15}
2724 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[21]=o;}
2725 class Fl_Image_Button
2726 }
2727 Fl_Button arm23 {
2728 callback {this->control->toggletrackarmed(23);}
2729 tooltip arm xywh {520 155 15 15}
2730 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[22]=o;}
2731 class Fl_Image_Button
2732 }
2733 Fl_Button arm24 {
2734 callback {this->control->toggletrackarmed(24);}
2735 tooltip arm xywh {535 155 15 15}
2736 code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[23]=o;}
2737 class Fl_Image_Button
2738 }
2739 Fl_Button solo1 {
2740 callback {control->solo(0,o->value());}
2741 xywh {40 175 20 15} selection_color 2
2742 code0 {o->up_image(button_solo_up->image()); o->down_image(button_solo_dn->image()); solobutton[0]=o;}
2743 class Fl_Image_Toggle_Button
2744 }
2745 Fl_Button solo2 {
2746 callback {control->solo(1,o->value());}
2747 xywh {60 175 15 15} selection_color 2
2748 code0 {solobutton[1]=o;}
2749 class Fl_Image_Toggle_Button
2750 }
2751 Fl_Button solo3 {
2752 callback {control->solo(2,o->value());}
2753 xywh {75 175 15 15} selection_color 2
2754 code0 {solobutton[2]=o;}
2755 class Fl_Image_Toggle_Button
2756 }
2757 Fl_Button solo4 {
2758 callback {control->solo(3,o->value());}
2759 xywh {90 175 15 15} selection_color 2
2760 code0 {solobutton[3]=o;}
2761 class Fl_Image_Toggle_Button
2762 }
2763 Fl_Button solo5 {
2764 callback {control->solo(4,o->value());}
2765 xywh {105 175 15 15} selection_color 2
2766 code0 {solobutton[4]=o;}
2767 class Fl_Image_Toggle_Button
2768 }
2769 Fl_Button solo6 {
2770 callback {control->solo(5,o->value());}
2771 xywh {120 175 15 15} selection_color 2
2772 code0 {solobutton[5]=o;}
2773 class Fl_Image_Toggle_Button
2774 }
2775 Fl_Button solo7 {
2776 callback {control->solo(6,o->value());}
2777 xywh {135 175 15 15} selection_color 2
2778 code0 {solobutton[6]=o;}
2779 class Fl_Image_Toggle_Button
2780 }
2781 Fl_Button solo8 {
2782 callback {control->solo(7,o->value());}
2783 xywh {150 175 15 15} selection_color 2
2784 code0 {solobutton[7]=o;}
2785 class Fl_Image_Toggle_Button
2786 }
2787 Fl_Button solo9 {
2788 callback {control->solo(8,o->value());}
2789 xywh {235 175 15 15} selection_color 2
2790 code0 {solobutton[8]=o;}
2791 class Fl_Image_Toggle_Button
2792 }
2793 Fl_Button solo10 {
2794 callback {control->solo(9,o->value());}
2795 xywh {250 175 15 15} selection_color 2
2796 code0 {solobutton[9]=o;}
2797 class Fl_Image_Toggle_Button
2798 }
2799 Fl_Button solo11 {
2800 callback {control->solo(10,o->value());}
2801 xywh {265 175 15 15} selection_color 2
2802 code0 {solobutton[10]=o;}
2803 class Fl_Image_Toggle_Button
2804 }
2805 Fl_Button solo12 {
2806 callback {control->solo(11,o->value());}
2807 xywh {280 175 15 15} selection_color 2
2808 code0 {solobutton[11]=o;}
2809 class Fl_Image_Toggle_Button
2810 }
2811 Fl_Button solo13 {
2812 callback {control->solo(12,o->value());}
2813 xywh {295 175 15 15} selection_color 2
2814 code0 {solobutton[12]=o;}
2815 class Fl_Image_Toggle_Button
2816 }
2817 Fl_Button solo14 {
2818 callback {control->solo(13,o->value());}
2819 xywh {310 175 15 15} selection_color 2
2820 code0 {solobutton[13]=o;}
2821 class Fl_Image_Toggle_Button
2822 }
2823 Fl_Button solo15 {
2824 callback {control->solo(14,o->value());}
2825 xywh {325 175 15 15} selection_color 2
2826 code0 {solobutton[14]=o;}
2827 class Fl_Image_Toggle_Button
2828 }
2829 Fl_Button solo16 {
2830 callback {control->solo(15,o->value());}
2831 xywh {340 175 15 15} selection_color 2
2832 code0 {solobutton[15]=o;}
2833 class Fl_Image_Toggle_Button
2834 }
2835 Fl_Button solo17 {
2836 callback {control->solo(16,o->value());}
2837 xywh {430 175 15 15} selection_color 2
2838 code0 {solobutton[16]=o;}
2839 class Fl_Image_Toggle_Button
2840 }
2841 Fl_Button solo18 {
2842 callback {control->solo(17,o->value());}
2843 xywh {445 175 15 15} selection_color 2
2844 code0 {solobutton[17]=o;}
2845 class Fl_Image_Toggle_Button
2846 }
2847 Fl_Button solo19 {
2848 callback {control->solo(18,o->value());}
2849 xywh {460 175 15 15} selection_color 2
2850 code0 {solobutton[18]=o;}
2851 class Fl_Image_Toggle_Button
2852 }
2853 Fl_Button solo20 {
2854 callback {control->solo(19,o->value());}
2855 xywh {475 175 15 15} selection_color 2
2856 code0 {solobutton[19]=o;}
2857 class Fl_Image_Toggle_Button
2858 }
2859 Fl_Button solo21 {
2860 callback {control->solo(20,o->value());}
2861 xywh {490 175 15 15} selection_color 2
2862 code0 {solobutton[20]=o;}
2863 class Fl_Image_Toggle_Button
2864 }
2865 Fl_Button solo22 {
2866 callback {control->solo(21,o->value());}
2867 xywh {505 175 15 15} selection_color 2
2868 code0 {solobutton[21]=o;}
2869 class Fl_Image_Toggle_Button
2870 }
2871 Fl_Button solo23 {
2872 callback {control->solo(22,o->value());}
2873 xywh {520 175 15 15} selection_color 2
2874 code0 {solobutton[22]=o;}
2875 class Fl_Image_Toggle_Button
2876 }
2877 Fl_Button solo24 {
2878 callback {control->solo(23,o->value());}
2879 xywh {535 175 15 15} selection_color 2
2880 code0 {solobutton[23]=o;}
2881 class Fl_Image_Toggle_Button
2882 }
2883 Fl_Button mute1 {
2884 callback {control->mute(0,o->value());}
2885 xywh {40 192 20 15} selection_color 1
2886 code0 {o->up_image(button_mute_up->image()); o->down_image(button_mute_dn->image()); mutebutton[0]=o;}
2887 class Fl_Image_Toggle_Button
2888 }
2889 Fl_Button mute2 {
2890 callback {control->mute(1,o->value());}
2891 xywh {60 192 15 15} selection_color 1
2892 code0 {mutebutton[1]=o;}
2893 class Fl_Image_Toggle_Button
2894 }
2895 Fl_Button mute3 {
2896 callback {control->mute(2,o->value());}
2897 xywh {75 192 15 15} selection_color 1
2898 code0 {mutebutton[2]=o;}
2899 class Fl_Image_Toggle_Button
2900 }
2901 Fl_Button mute4 {
2902 callback {control->mute(3,o->value());}
2903 xywh {90 192 15 15} selection_color 1
2904 code0 {mutebutton[3]=o;}
2905 class Fl_Image_Toggle_Button
2906 }
2907 Fl_Button mute5 {
2908 callback {control->mute(4,o->value());}
2909 xywh {105 192 15 15} selection_color 1
2910 code0 {mutebutton[4]=o;}
2911 class Fl_Image_Toggle_Button
2912 }
2913 Fl_Button mute6 {
2914 callback {control->mute(5,o->value());}
2915 xywh {120 192 15 15} selection_color 1
2916 code0 {mutebutton[5]=o;}
2917 class Fl_Image_Toggle_Button
2918 }
2919 Fl_Button mute7 {
2920 callback {control->mute(6,o->value());}
2921 xywh {135 192 15 15} selection_color 1
2922 code0 {mutebutton[6]=o;}
2923 class Fl_Image_Toggle_Button
2924 }
2925 Fl_Button mute8 {
2926 callback {control->mute(7,o->value());}
2927 xywh {150 192 15 15} selection_color 1
2928 code0 {mutebutton[7]=o;}
2929 class Fl_Image_Toggle_Button
2930 }
2931 Fl_Button mute9 {
2932 callback {control->mute(8,o->value());}
2933 xywh {235 192 15 15} selection_color 1
2934 code0 {mutebutton[8]=o;}
2935 class Fl_Image_Toggle_Button
2936 }
2937 Fl_Button mute10 {
2938 callback {control->mute(9,o->value());}
2939 xywh {250 192 15 15} selection_color 1
2940 code0 {mutebutton[9]=o;}
2941 class Fl_Image_Toggle_Button
2942 }
2943 Fl_Button mute11 {
2944 callback {control->mute(10,o->value());}
2945 xywh {265 192 15 15} selection_color 1
2946 code0 {mutebutton[10]=o;}
2947 class Fl_Image_Toggle_Button
2948 }
2949 Fl_Button mute12 {
2950 callback {control->mute(11,o->value());}
2951 xywh {280 192 15 15} selection_color 1
2952 code0 {mutebutton[11]=o;}
2953 class Fl_Image_Toggle_Button
2954 }
2955 Fl_Button mute13 {
2956 callback {control->mute(12,o->value());}
2957 xywh {295 192 15 15} selection_color 1
2958 code0 {mutebutton[12]=o;}
2959 class Fl_Image_Toggle_Button
2960 }
2961 Fl_Button mute14 {
2962 callback {control->mute(13,o->value());}
2963 xywh {310 192 15 15} selection_color 1
2964 code0 {mutebutton[13]=o;}
2965 class Fl_Image_Toggle_Button
2966 }
2967 Fl_Button mute15 {
2968 callback {control->mute(14,o->value());}
2969 xywh {325 192 15 15} selection_color 1
2970 code0 {mutebutton[14]=o;}
2971 class Fl_Image_Toggle_Button
2972 }
2973 Fl_Button mute16 {
2974 callback {control->mute(15,o->value());}
2975 xywh {340 192 15 15} selection_color 1
2976 code0 {mutebutton[15]=o;}
2977 class Fl_Image_Toggle_Button
2978 }
2979 Fl_Button mute17 {
2980 callback {control->mute(16,o->value());}
2981 xywh {430 192 15 15} selection_color 1
2982 code0 {mutebutton[16]=o;}
2983 class Fl_Image_Toggle_Button
2984 }
2985 Fl_Button mute18 {
2986 callback {control->mute(17,o->value());}
2987 xywh {445 192 15 15} selection_color 1
2988 code0 {mutebutton[17]=o;}
2989 class Fl_Image_Toggle_Button
2990 }
2991 Fl_Button mute19 {
2992 callback {control->mute(18,o->value());}
2993 xywh {460 192 15 15} selection_color 1
2994 code0 {mutebutton[18]=o;}
2995 class Fl_Image_Toggle_Button
2996 }
2997 Fl_Button mute20 {
2998 callback {control->mute(19,o->value());}
2999 xywh {475 192 15 15} selection_color 1
3000 code0 {mutebutton[19]=o;}
3001 class Fl_Image_Toggle_Button
3002 }
3003 Fl_Button mute21 {
3004 callback {control->mute(20,o->value());}
3005 xywh {490 192 15 15} selection_color 1
3006 code0 {mutebutton[20]=o;}
3007 class Fl_Image_Toggle_Button
3008 }
3009 Fl_Button mute22 {
3010 callback {control->mute(21,o->value());}
3011 xywh {505 192 15 15} selection_color 1
3012 code0 {mutebutton[21]=o;}
3013 class Fl_Image_Toggle_Button
3014 }
3015 Fl_Button mute23 {
3016 callback {control->mute(22,o->value());}
3017 xywh {520 192 15 15} selection_color 1
3018 code0 {mutebutton[22]=o;}
3019 class Fl_Image_Toggle_Button
3020 }
3021 Fl_Button mute24 {
3022 callback {control->mute(23,o->value());}
3023 xywh {535 192 15 15} selection_color 1
3024 code0 {mutebutton[23]=o;}
3025 class Fl_Image_Toggle_Button
3026 }
3027 Fl_Box arm_unarm_all {
3028 callback {hd24song* currsong=this->control->song();
3029if (currsong==NULL) return;
3030
3031bool alltracksarmed=true;
3032for (unsigned int i=1;i<=currsong->logical_channels();i++) {
3033 if (!currsong->trackarmed(i)) {
3034 alltracksarmed=false;
3035 break;
3036 }
3037}
3038bool mustarm=false;
3039if (!alltracksarmed) {
3040 mustarm=true;
3041}
3042for (unsigned int i=1;i<=currsong->logical_channels();i++) {
3043 currsong->trackarmed(i,mustarm);
3044}}
3045 tooltip {Arm tracks} xywh {10 156 10 10} box OVAL_BOX color 1 selection_color 1
3046 class Fl_Button
3047 }
3048 Fl_Box {} {
3049 label S
3050 tooltip Solo xywh {10 176 15 14} color 1 selection_color 1 labelfont 1 labelsize 12
3051 }
3052 Fl_Box {} {
3053 label M
3054 tooltip Mute xywh {10 191 15 14} color 1 selection_color 1 labelfont 1 labelsize 12
3055 }
3056 Fl_Group infodisplay {open
3057 xywh {10 225 295 150} box DOWN_BOX color 0
3058 } {
3059 Fl_Box ho1 {
3060 image {images/7seg_8.gif} xywh {12 234 16 26}
3061 code0 {o->image(i7seg0->image()); o->redraw();}
3062 }
3063 Fl_Box ho2 {
3064 image {images/7seg_8.gif} xywh {27 234 16 26}
3065 code0 {o->image(i7seg0->image()); o->redraw();}
3066 }
3067 Fl_Box mi1 {
3068 image {images/7seg_8.gif} xywh {55 234 16 26}
3069 code0 {o->image(i7seg0->image()); o->redraw();}
3070 }
3071 Fl_Box mi2 {
3072 image {images/7seg_8.gif} xywh {70 234 16 26}
3073 code0 {o->image(i7seg0->image()); o->redraw();}
3074 }
3075 Fl_Box se1 {
3076 image {images/7seg_8.gif} xywh {98 234 16 26}
3077 code0 {o->image(i7seg0->image()); o->redraw();}
3078 }
3079 Fl_Box se2 {
3080 image {images/7seg_8.gif} xywh {113 234 16 26}
3081 code0 {o->image(i7seg0->image()); o->redraw();}
3082 }
3083 Fl_Box fr1 {
3084 image {images/7seg_8.gif} xywh {141 234 16 26}
3085 code0 {o->image(i7seg0->image()); o->redraw();}
3086 }
3087 Fl_Box fr2 {
3088 image {images/7seg_8.gif} xywh {156 234 16 26}
3089 code0 {o->image(i7seg0->image()); o->redraw();}
3090 }
3091 Fl_Box {} {
3092 label H
3093 xywh {42 247 12 14} labelfont 3 labelsize 11 labelcolor 6
3094 }
3095 Fl_Box {} {
3096 label M
3097 xywh {85 247 12 14} labelfont 3 labelsize 11 labelcolor 6
3098 }
3099 Fl_Box {} {
3100 label S
3101 xywh {128 247 12 14} labelfont 3 labelsize 11 labelcolor 6
3102 }
3103 Fl_Box {} {
3104 label F
3105 xywh {171 247 12 14} labelfont 3 labelsize 11 labelcolor 6
3106 }
3107 Fl_Box l1c0 {
3108 image {images/HD24_matrix_realsize.gif} xywh {13 274 20 26}
3109 code0 {this->dispcell[0][0]=o;}
3110 }
3111 Fl_Box l1c1 {
3112 image {images/HD24_matrix_realsize.gif} xywh {31 274 20 26}
3113 code0 {this->dispcell[1][0]=o;}
3114 }
3115 Fl_Box l1c2 {
3116 image {images/HD24_matrix_realsize.gif} xywh {49 274 20 26}
3117 code0 {this->dispcell[2][0]=o;}
3118 }
3119 Fl_Box l1c3 {
3120 image {images/HD24_matrix_realsize.gif} xywh {67 274 20 26}
3121 code0 {this->dispcell[3][0]=o;}
3122 }
3123 Fl_Box l1c4 {
3124 image {images/HD24_matrix_realsize.gif} xywh {85 274 20 26}
3125 code0 {this->dispcell[4][0]=o;}
3126 }
3127 Fl_Box l1c5 {
3128 image {images/HD24_matrix_realsize.gif} xywh {103 274 20 26}
3129 code0 {this->dispcell[5][0]=o;}
3130 }
3131 Fl_Box l1c6 {
3132 image {images/HD24_matrix_realsize.gif} xywh {121 274 20 26}
3133 code0 {this->dispcell[6][0]=o;}
3134 }
3135 Fl_Box l1c7 {
3136 image {images/HD24_matrix_realsize.gif} xywh {139 274 20 26}
3137 code0 {this->dispcell[7][0]=o;}
3138 }
3139 Fl_Box l1c8 {
3140 image {images/HD24_matrix_realsize.gif} xywh {157 274 20 26}
3141 code0 {this->dispcell[8][0]=o;}
3142 }
3143 Fl_Box l1c9 {
3144 image {images/HD24_matrix_realsize.gif} xywh {175 274 20 26}
3145 code0 {this->dispcell[9][0]=o;}
3146 }
3147 Fl_Box l1ca {
3148 image {images/HD24_matrix_realsize.gif} xywh {193 274 20 26}
3149 code0 {this->dispcell[10][0]=o;}
3150 }
3151 Fl_Box l1cb {
3152 image {images/HD24_matrix_realsize.gif} xywh {211 274 20 26}
3153 code0 {this->dispcell[11][0]=o;}
3154 }
3155 Fl_Box l1cc {
3156 image {images/HD24_matrix_realsize.gif} xywh {229 274 20 26}
3157 code0 {this->dispcell[12][0]=o;}
3158 }
3159 Fl_Box l1cd {
3160 image {images/HD24_matrix_realsize.gif} xywh {247 274 20 26}
3161 code0 {this->dispcell[13][0]=o;}
3162 }
3163 Fl_Box l1ce {
3164 image {images/HD24_matrix_realsize.gif} xywh {265 274 20 26}
3165 code0 {this->dispcell[14][0]=o;}
3166 }
3167 Fl_Box l1cf {
3168 image {images/HD24_matrix_realsize.gif} xywh {283 274 20 26}
3169 code0 {this->dispcell[15][0]=o;}
3170 }
3171 Fl_Box l2c0 {
3172 image {images/HD24_matrix_realsize.gif} xywh {12 304 20 26}
3173 code0 {this->dispcell[0][1]=o;}
3174 }
3175 Fl_Box l2c1 {
3176 image {images/HD24_matrix_realsize.gif} xywh {30 304 20 26}
3177 code0 {this->dispcell[1][1]=o;}
3178 }
3179 Fl_Box l2c2 {
3180 image {images/HD24_matrix_realsize.gif} xywh {48 304 20 26}
3181 code0 {this->dispcell[2][1]=o;}
3182 }
3183 Fl_Box l2c3 {
3184 image {images/HD24_matrix_realsize.gif} xywh {66 304 20 26}
3185 code0 {this->dispcell[3][1]=o;}
3186 }
3187 Fl_Box l2c4 {
3188 image {images/HD24_matrix_realsize.gif} xywh {84 304 20 26}
3189 code0 {this->dispcell[4][1]=o;}
3190 }
3191 Fl_Box l2c5 {
3192 image {images/HD24_matrix_realsize.gif} xywh {102 304 20 26}
3193 code0 {this->dispcell[5][1]=o;}
3194 }
3195 Fl_Box l2c6 {
3196 image {images/HD24_matrix_realsize.gif} xywh {120 304 20 26}
3197 code0 {this->dispcell[6][1]=o;}
3198 }
3199 Fl_Box l2c7 {
3200 image {images/HD24_matrix_realsize.gif} xywh {138 304 20 26}
3201 code0 {this->dispcell[7][1]=o;}
3202 }
3203 Fl_Box l2c8 {
3204 image {images/HD24_matrix_realsize.gif} xywh {156 304 20 26}
3205 code0 {this->dispcell[8][1]=o;}
3206 }
3207 Fl_Box l2c9 {
3208 image {images/HD24_matrix_realsize.gif} xywh {174 304 20 26}
3209 code0 {this->dispcell[9][1]=o;}
3210 }
3211 Fl_Box l2ca {
3212 image {images/HD24_matrix_realsize.gif} xywh {192 304 20 26}
3213 code0 {this->dispcell[10][1]=o;}
3214 }
3215 Fl_Box l2cb {
3216 image {images/HD24_matrix_realsize.gif} xywh {210 304 20 26}
3217 code0 {this->dispcell[11][1]=o;}
3218 }
3219 Fl_Box l2cc {
3220 image {images/HD24_matrix_realsize.gif} xywh {228 304 20 26}
3221 code0 {this->dispcell[12][1]=o;}
3222 }
3223 Fl_Box l2cd {
3224 image {images/HD24_matrix_realsize.gif} xywh {246 304 20 26}
3225 code0 {this->dispcell[13][1]=o;}
3226 }
3227 Fl_Box l2ce {
3228 image {images/HD24_matrix_realsize.gif} xywh {264 304 20 26}
3229 code0 {this->dispcell[14][1]=o;}
3230 }
3231 Fl_Box l2cf {
3232 image {images/HD24_matrix_realsize.gif} xywh {282 304 20 26}
3233 code0 {this->dispcell[15][1]=o;}
3234 }
3235 Fl_Box autoanythingled {
3236 label AUTO
3237 xywh {193 233 65 8} box FLAT_BOX color 93 labelfont 1 labelsize 8 hide
3238 }
3239 Fl_Box autoplayled {
3240 label PLAY
3241 xywh {215 242 24 8} box FLAT_BOX color 93 labelfont 1 labelsize 8 hide
3242 }
3243 Fl_Box autortnled {
3244 label RTN
3245 xywh {240 242 18 8} box FLAT_BOX color 93 labelfont 1 labelsize 8 hide
3246 }
3247 Fl_Box autorecled {
3248 label REC
3249 xywh {193 242 21 8} box FLAT_BOX color 1 labelfont 1 labelsize 8 align 16 hide
3250 }
3251 Fl_Box rehearseled {
3252 label REHEARSE
3253 xywh {193 251 65 8} box FLAT_BOX color 1 labelfont 1 labelsize 8
3254 }
3255 Fl_Box pitchled {
3256 label PITCH
3257 xywh {260 242 40 8} box FLAT_BOX color 6 labelfont 1 labelsize 8 hide
3258 }
3259 }
3260 Fl_Button button_rehearse {
3261 label REHEARSE
3262 callback {control->button_rehearse_call();}
3263 tooltip {Set Locate} xywh {310 290 50 20} type Toggle box FLAT_BOX down_box FLAT_BOX color 47 selection_color 18 labelfont 1 labelsize 9 labelcolor 7 align 5 deactivate
3264 code0 {o->up_image(button_lrc_up->image()); o->down_image(button_lrc_dn->image());}
3265 class Fl_Image_Toggle_Button
3266 }
3267 Fl_Button button_punchin {
3268 label {PUNCH IN}
3269 callback {control->handlelocatebutton(hd24song::LOCATEPOS_PUNCHIN);}
3270 tooltip {Set Locate} xywh {485 290 50 20} box FLAT_BOX down_box FLAT_BOX color 47 selection_color 18 labelfont 1 labelsize 9 labelcolor 7 align 1
3271 code0 {o->up_image(button_lrc_led_up->image()); o->down_image(button_lrc_led_dn->image());}
3272 class Fl_Image_Button
3273 }
3274 Fl_Button button_punchout {
3275 label {PUNCH OUT}
3276 callback {control->handlelocatebutton(hd24song::LOCATEPOS_PUNCHOUT);}
3277 tooltip {Set Locate} xywh {550 290 50 20} box FLAT_BOX down_box FLAT_BOX color 47 selection_color 18 labelfont 1 labelsize 9 labelcolor 7 align 9
3278 code0 {o->up_image(button_lrc_led_up->image()); o->down_image(button_lrc_led_dn->image());}
3279 class Fl_Image_Button
3280 }
3281 Fl_Button button_peakmode {
3282 label {Peak
3283mode}
3284 callback {this->currpeakmode=((this->currpeakmode)+1)%3;
3285
3286for (unsigned int i=0;i<MAXCHANNELS;i++) {
3287 this->trackchan[i]->peakmode(this->currpeakmode);
3288}
3289switch (this->currpeakmode)
3290{
3291 case 0: // "No" "Peak Hold"
3292 dispwrite(0," No "
3293 " Peak Hold ",2000);
3294 break;
3295 case 1: // "Momentary" "Peak Hold"
3296 dispwrite(0," Momentary "
3297 " Peak Hold ",2000);
3298 break;
3299 case 2: // "Continuous" "Peak Hold"
3300 dispwrite(0," Continuous "
3301 " Peak Hold ",2000);
3302 break;
3303 default:
3304 // ???????
3305 break;
3306}}
3307 tooltip arm xywh {10 375 50 30} color 8 selection_color 8 labelfont 1 labelsize 10 labelcolor 7
3308 code0 {o->clear_visible_focus();}
3309 class Fl_Button
3310 }
3311 Fl_Button button_peakclear {
3312 label {Peak
3313clear}
3314 callback {this->currpeakmode=((this->currpeakmode)+1)%3;
3315
3316for (unsigned int i=0;i<MAXCHANNELS;i++) {
3317 this->trackchan[i]->peakreset();
3318}}
3319 tooltip arm xywh {60 375 50 30} color 8 selection_color 8 labelfont 1 labelsize 10 labelcolor 7
3320 code0 {o->clear_visible_focus();}
3321 class Fl_Button
3322 }
3323 Fl_Button button_autoinput {
3324 label {Auto
3325input}
3326 callback {/*
3327if (currenthd24==NULL) return;
3328if (button_autoinput->value()==1) {
3329 currenthd24->setautoinput(true);
3330} else {
3331 currenthd24->setautoinput(false);
3332}
3333*/}
3334 tooltip arm xywh {110 375 45 30} type Toggle color 8 selection_color 59 labelfont 1 labelsize 10 labelcolor 7
3335 code0 {o->clear_visible_focus();}
3336 class Fl_Button
3337 }
3338 Fl_Button button_allinput {
3339 label {All
3340input}
3341 callback {/*
3342if (currenthd24==NULL) return;
3343if (button_allinput->value()==0) {
3344 currenthd24->setallinput(false);
3345} else {
3346 currenthd24->setallinput(true);
3347}
3348*/}
3349 tooltip arm xywh {155 375 45 30} type Toggle color 8 selection_color 59 labelfont 1 labelsize 10 labelcolor 7
3350 code0 {o->clear_visible_focus();}
3351 class Fl_Button
3352 }
3353 Fl_Choice stereoinmap {
3354 label {Stereo input mapping} open
3355 xywh {463 390 140 20} down_box BORDER_BOX labelsize 12 align 5 textsize 12 deactivate
3356 } {
3357 MenuItem {} {
3358 label Normal
3359 xywh {5 5 36 21} labelsize 12
3360 }
3361 MenuItem {} {
3362 label {Swap Left and Right}
3363 xywh {15 15 36 21} labelsize 12
3364 }
3365 MenuItem {} {
3366 label {Mix to mono}
3367 xywh {15 15 36 21} labelsize 12
3368 }
3369 MenuItem {} {
3370 label {Use Left only}
3371 xywh {25 25 36 21} labelsize 12
3372 }
3373 MenuItem {} {
3374 label {Use Right only}
3375 xywh {35 35 36 21} labelsize 12
3376 }
3377 }
3378 Fl_Roller {} {
3379 label {Drag to Jog}
3380 callback {// scrubwheel calls button_scrub_call()}
3381 xywh {310 390 110 20} type Horizontal labelsize 12 align 1 minimum -1 step 2
3382 code0 {o->setui(this);}
3383 class ScrubWheel
3384 }
3385 }
3386 }
3387 decl {/* === Audio/transport ===================================================== */} {}
3388 decl {int hlbuttons_defaultcolor;} {public
3389 }
3390 Function {highlight_setbuttons(int value)} {open return_type void
3391 } {
3392 code {if (value==1) {
3393 if (button_loopstart!=NULL) {
3394 button_loopstart->up_image(button_lrc_led_on_up->image());
3395 button_loopstart->down_image(button_lrc_led_on_dn->image());
3396 }
3397 if (button_loopend!=NULL) {
3398 button_loopend->up_image(button_lrc_led_on_up->image());
3399 button_loopend->down_image(button_lrc_led_on_dn->image());
3400 }
3401 if (button_punchin!=NULL) {
3402 button_punchin->up_image(button_lrc_led_on_up->image());
3403 button_punchin->down_image(button_lrc_led_on_dn->image());
3404 }
3405 if (button_punchout!=NULL) {
3406 button_punchout->up_image(button_lrc_led_on_up->image());
3407 button_punchout->down_image(button_lrc_led_on_dn->image());
3408 }
3409} else {
3410 button_loopstart->up_image(button_lrc_led_up->image());
3411 button_loopstart->down_image(button_lrc_led_dn->image());
3412 button_loopend->up_image(button_lrc_led_up->image());
3413 button_loopend->down_image(button_lrc_led_dn->image());
3414 button_punchin->up_image(button_lrc_led_up->image());
3415 button_punchin->down_image(button_lrc_led_dn->image());
3416 button_punchout->up_image(button_lrc_led_up->image());
3417 button_punchout->down_image(button_lrc_led_dn->image());
3418}
3419 if (button_punchout!=NULL) { button_punchout->redraw(); }
3420 if (button_punchin!=NULL) { button_punchin->redraw(); }
3421 if (button_loopstart!=NULL) { button_loopstart->redraw(); }
3422 if (button_loopend!=NULL) { button_loopend->redraw();}} {}
3423 }
3424 Function {poll_callback(void* user)} {open return_type {static void}
3425 } {
3426 code {//HD24UserInterface* mythis=(HD24UserInterface*)user;
3427RecorderUI* mythis=(RecorderUI*)user;
3428int visible=0;
3429 if (mythis->recordergroup->visible())
3430 {
3431 visible=1;
3432 } else {
3433 visible=0;
3434 }
3435
3436
3437if (mythis->control->ready()!=1) { return; }
3438
3439if (mythis->dispwritecountdown>0)
3440{
3441 mythis->dispwritecountdown--;
3442 if (mythis->dispwritecountdown==0) {
3443 mythis->disprestore();
3444 }
3445}
3446
3447if (mythis->busy!=1) {
3448 mythis->busy=1;
3449 mythis->blinkcounter=(mythis->blinkcounter+1)%BLINKRATE;
3450
3451 if (visible==1) {
3452 for (unsigned int i=0;i<MAXCHANNELS;i++) {
3453 mythis->trackchan[i]->setval(mythis->control->data->trackpeak[i]);
3454 }
3455
3456 Fl_Image* oldimg;
3457 Fl_Image* newimg=NULL;
3458
3459 string* dur=NULL;
3460 hd24song* mycurrsong=mythis->control->song();
3461 if (mycurrsong!=NULL) {
3462 dur=mycurrsong->display_cursor();
3463 } else {
3464 dur=new string("00:00:00.00");
3465 }
3466
3467
3468 oldimg=mythis->ho1->image();
3469 mythis->ho1->image(mythis->i7seg[dur->c_str()[0]-'0']->image());
3470 if (newimg!=oldimg) mythis->ho1->redraw();
3471
3472 oldimg=mythis->ho2->image();
3473 mythis->ho2->image(mythis->i7seg[dur->c_str()[1]-'0']->image());
3474 if (newimg!=oldimg) mythis->ho2->redraw();
3475
3476 oldimg=mythis->mi1->image();
3477 mythis->mi1->image(mythis->i7seg[dur->c_str()[3]-'0']->image());
3478 if (newimg!=oldimg) mythis->mi1->redraw();
3479
3480 oldimg=mythis->mi2->image();
3481 mythis->mi2->image(mythis->i7seg[dur->c_str()[4]-'0']->image());
3482 if (newimg!=oldimg) mythis->mi2->redraw();
3483
3484 oldimg=mythis->se1->image();
3485 mythis->se1->image(mythis->i7seg[dur->c_str()[6]-'0']->image());
3486 if (newimg!=oldimg) mythis->se1->redraw();
3487
3488 oldimg=mythis->se2->image();
3489 mythis->se2->image(mythis->i7seg[dur->c_str()[7]-'0']->image());
3490 if (newimg!=oldimg) mythis->se2->redraw();
3491 oldimg=mythis->fr1->image();
3492 mythis->fr1->image(mythis->i7seg[dur->c_str()[9]-'0']->image());
3493 if (newimg!=oldimg) mythis->fr1->redraw();
3494
3495 oldimg=mythis->fr2->image();
3496 mythis->fr2->image(mythis->i7seg[dur->c_str()[10]-'0']->image());
3497 if (newimg!=oldimg) mythis->fr2->redraw();
3498 if ((mythis->mustdisplaytimer) && (mycurrsong !=NULL))
3499 {
3500
3501 // mythis->setstatus(*dur);
3502 __uint32 currloc=mycurrsong->cursorpos();
3503 if (mycurrsong->songlength_in_samples() >0) {
3504 currloc=mycurrsong->cursorpos()/(mycurrsong->songlength_in_samples()/1000);
3505 } else {
3506 currloc=0;
3507 }
3508 if (mythis->slidermoved!=0) {
3509 mythis->slidermoved--;
3510 } else {
3511 mythis->locationslider->value(currloc);
3512 }
3513 }
3514 delete (dur);
3515 }
3516
3517}
3518mythis->busy=0;
3519//Fl::add_timeout(TIMEOUT,poll_callback,user);
3520
3521AudioSystem* audio=mythis->control->audio;
3522
3523if (!audio->isinitialized()) return;
3524if (!audio->mustloop()) return;
3525audio->hd24_transport_locate((__sint64)(audio->looppos()));
3526audio->mustloop(false);
3527audio->looppos(0);} {}
3528 }
3529 Function {fl_check()} {open return_type void
3530 } {
3531 code {Fl::check();} {}
3532 }
3533 decl {int busy;} {public
3534 }
3535 decl {friend class ScrubWheel;} {}
3536 decl {int uiredrawcount; /* to limit refreshing UI */} {public
3537 }
3538 Function {finish()} {open return_type void
3539 } {
3540 code {if (this==NULL) return;
3541
3542this->control->button_stop_call();} {}
3543 }
3544 Function {button_light(void* button,bool lit)} {open return_type void
3545 } {
3546 code {if (button==NULL) return;
3547if (((Fl_Image_Button*)button)==button_stop)
3548{
3549 if (lit==1)
3550 {
3551 button_stop->up_image(button_stop_uplit->image());
3552 button_stop->down_image(button_stop_dn->image());
3553 }
3554 else
3555 {
3556 button_stop->up_image(button_stop_up->image());
3557 button_stop->down_image(button_stop_dn->image());
3558 }
3559 button_stop->redraw();
3560 return;
3561}} {}
3562 }
3563 Function {button_up(void* button)} {open return_type void
3564 } {
3565 code {if (button==NULL)
3566{
3567 return;
3568}
3569
3570if ((void*)button==(void*)button_stop)
3571{
3572 button_stop->value(0);
3573 button_stop->redraw();
3574 return;
3575}
3576if ((void*)button==(void*)button_play)
3577{
3578 button_play->value(0);
3579 button_play->redraw();
3580 return;
3581}
3582if ((void*)button==(void*)button_rec)
3583{
3584 button_rec->value(0);
3585 button_rec->redraw();
3586 return;
3587}
3588if ((void*)button==(void*)button_rew)
3589{
3590 button_rew->value(0);
3591 button_rew->redraw();
3592 return;
3593}
3594if ((void*)button==(void*)button_ffwd)
3595{
3596 button_ffwd->value(0);
3597 button_ffwd->redraw();
3598 return;
3599}} {}
3600 }
3601 Function {button_down(void* button)} {open return_type void
3602 } {
3603 code {if (button==NULL)
3604{
3605 return;
3606}
3607
3608if ((void*)button==(void*)button_stop)
3609{
3610 button_stop->value(1);
3611 button_stop->redraw();
3612 return;
3613}
3614if ((void*)button==(void*)button_play)
3615{
3616 button_play->value(1);
3617 button_play->redraw();
3618 return;
3619}
3620if ((void*)button==(void*)button_rec)
3621{
3622 button_rec->value(1);
3623 button_rec->redraw();
3624 return;
3625}
3626if ((void*)button==(void*)button_rew)
3627{
3628 button_rew->value(1);
3629 button_rew->redraw();
3630 return;
3631}
3632if ((void*)button==(void*)button_ffwd)
3633{
3634 button_ffwd->value(1);
3635 button_ffwd->redraw();
3636 return;
3637}} {}
3638 }
3639}
diff --git a/src/hd24hexview.cpp b/src/hd24hexview.cpp
new file mode 100755
index 0000000..8ee4751
--- /dev/null
+++ b/src/hd24hexview.cpp
@@ -0,0 +1,923 @@
1#include <iostream>
2#include <algorithm>
3#include <cctype>
4#include <string>
5#include <sys/types.h>
6#include <sys/stat.h>
7#include <fcntl.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include "config.h"
11#include "hd24fs.h"
12#include "convertlib.h"
13
14#define VERSION "1.3 beta"
15#define _LARGE_FILES
16#define _FILE_OFFSET_BITS 64
17#define FILE_OFFSET_BITS 64
18#define LARGE_FILES
19#define LARGEFILE64_SOURCE
20#define SECTORSIZE 512
21#define ARGHEADER "--header="
22
23#ifdef DARWIN
24# define open64 open
25# define lseek64 lseek
26# define pread64 pread
27# define creat64 creat
28# define pwrite64 pwrite
29#endif
30
31#ifndef WINDOWS
32# include <unistd.h>
33#endif
34
35string device;
36string headerfilename;
37__uint64 writeoffset;
38int force;
39int expertmode;
40int graphmode;
41int enable_graphmode;
42int disable_graphmode;
43
44// Check if a file exists
45bool fileexists (string* fname)
46{
47 struct stat fi;
48
49 if ((stat(fname->c_str(), &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0)) {
50 return true;
51 }
52
53 return false;
54}
55
56// Check if file handle is invalid
57bool isinvalidhandle(FSHANDLE handle)
58{
59#ifdef WINDOWS
60 if (handle == FSHANDLE_INVALID) {
61 return true;
62 }
63#else
64 if (handle == 0 || handle == FSHANDLE_INVALID) {
65 return true;
66 }
67#endif
68 return false;
69}
70
71// Output a message for expert only features
72void expertmodemessage(string feature)
73{
74 cout << feature <<" is only allowed in expert mode." << endl;
75}
76
77// Seek to a position in the drive
78void hd24seek(FSHANDLE devhd24, __uint64 seekpos)
79{
80#ifdef WINDOWS
81 LARGE_INTEGER li;
82 li.HighPart = seekpos >> 32;
83 li.LowPart = seekpos % ((__uint64) 1 << 32);
84 SetFilePointerEx(devhd24, li, NULL, FILE_BEGIN);
85#else
86 lseek64(devhd24, seekpos, 0);
87#endif
88 return;
89}
90
91// Calculate a 32-bit checksum for a block
92long unsigned int calcblockchecksum(hd24raw* rawdevice, unsigned long firstsector, unsigned long endsector)
93{
94 long unsigned int checksum32 = 0;
95 unsigned char origblock[5120];
96
97 for (unsigned long k = firstsector; k < endsector; k++)
98 {
99 rawdevice->readsectors(k, origblock, 1);
100
101 for (unsigned long i = 0; i < SECTORSIZE; i += 4)
102 {
103 unsigned long num = Convert::getint32(origblock, i);
104 int byte1 = num % 256;
105 int byte2 = (num >> 8) % 256;
106 int byte3 = (num >> 16) % 256;
107 int byte4 = (num >> 24) % 256;
108 num = byte4 + (byte3 << 8) + (byte2 << 16) + (byte1 << 24);
109 checksum32 += num;
110 }
111 }
112
113 return checksum32;
114}
115
116// Write to a sector
117long writesectors(FSHANDLE devhd24, unsigned long sectornum, unsigned char * buffer, int sectors)
118{
119 int WRITESIZE = SECTORSIZE * sectors; // allows searching across sector boundaries
120 hd24seek(devhd24, (__uint64) sectornum * 512);
121
122#ifdef WINDOWS
123 DWORD dummy;
124 long bytes = 0;
125
126 if (WriteFile(devhd24, buffer, WRITESIZE, &dummy, NULL)) {
127 bytes = WRITESIZE;
128 };
129#else
130 long bytes = pwrite64(devhd24, buffer, WRITESIZE, (__uint64) sectornum * 512);
131#endif
132
133 return bytes;
134}
135
136void writetofile(hd24raw* rawdevice,string filename, long firstsector,long endsector)
137{
138 int i;
139 unsigned char bootblock[5120];
140#if defined(LINUX) || defined(DARWIN)
141 FSHANDLE handle=creat64(filename.c_str(),O_WRONLY);
142#endif
143#ifdef WINDOWS
144 FSHANDLE handle=CreateFile(filename.c_str(),GENERIC_WRITE|GENERIC_READ,
145 FILE_SHARE_READ|FILE_SHARE_WRITE,
146 NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
147 if (isinvalidhandle(handle)) {
148 handle=CreateFile(filename.c_str(),GENERIC_WRITE|GENERIC_READ,
149 FILE_SHARE_READ|FILE_SHARE_WRITE,
150 NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
151 }
152
153#endif
154 if (isinvalidhandle(handle)) {
155 cout << "Cannot open file "<<filename <<" for writing. Access denied?" << endl;
156 return;
157 }
158 cout << "Write range from offset "<< *Convert::int64tohex((__uint64)firstsector*512)<< " to offset " << *Convert::int64tohex((__uint64)endsector*512-1) << endl;
159 for (i=firstsector;i<endsector;i++) {
160 rawdevice->readsectors(i,bootblock,1);
161#if defined(LINUX) || defined(DARWIN)
162 __uint64 targetoff=i;
163 targetoff-=firstsector;
164 targetoff+=writeoffset;
165 targetoff*=512;
166 ssize_t byteswritten=pwrite64(handle,bootblock,512,targetoff);
167#endif
168#ifdef WINDOWS
169 //DWORD dummy;
170 //long bytes=0;
171 __uint64 targetoff=i;
172 targetoff-=firstsector;
173 targetoff+=writeoffset;
174 __uint64 byteswritten=writesectors(handle,targetoff,bootblock,1);
175#endif
176 if (byteswritten==0) {
177 cout << "Wrote 0 bytes to file. Access denied?" << endl;
178#if defined(LINUX) || defined(DARWIN)
179 close (handle);
180#endif
181#ifdef WNDOWS
182 CloseHandle(handle);
183#endif
184 return;
185 }
186 if ((i%1000)==0) {
187 string* x=Convert::int64tohex((__uint64)i*0x200);
188 cout << "Write offset " << *x << "\r";
189 if (x!=NULL) { delete x; x=NULL; }
190 }
191 }
192#if defined(LINUX) || defined(DARWIN)
193 close (handle);
194#endif
195#ifdef WINDOWS
196 CloseHandle(handle);
197#endif
198 return;
199}
200
201string getbinstr(string tofind)
202{
203 if (tofind.substr(0,1)=="'") {
204 // find literal string
205 tofind=tofind.substr(1,tofind.length()-2);
206 cout << "Find string " << tofind << endl;
207 } else {
208 string binstr="";
209 string tmp="";
210 tofind+=" ";
211 unsigned int i;
212 for (i=0;i<tofind.length();i++) {
213 string onechar=tofind.substr(i,1);
214 if (onechar!=" ") {
215 if (!Convert::isnibble(onechar)) {
216 cout << "Error: not a valid hex string" << endl;
217 return "";
218 }
219 tmp+=onechar;
220 } else {
221 if (tmp!="") {
222 binstr+=Convert::hex2byte(tmp);
223 }
224 tmp="";
225 }
226 }
227 tofind=binstr;
228 cout << "looking for " << binstr << endl;
229 }
230 return *(new string(tofind));
231}
232
233long movebytes(unsigned char* bootblock,string editstr)
234{
235 string strfrompos="";
236 string strmovelen="";
237 string strtopos="";
238 while (
239 (editstr.substr(0,1)!=" ")
240 &&(editstr.substr(0,1)!="l")
241 &&(editstr.substr(0,1)!="L")
242 &&(editstr!=""))
243 {
244 strfrompos+=editstr.substr(0,1);
245 editstr=editstr.substr(1,editstr.length()-1);
246 }
247 if (
248 (editstr.substr(0,1)=="l")
249 ||(editstr.substr(0,1)=="L"))
250 {
251 editstr=editstr.substr(1,editstr.length()-1);
252
253 while (
254 (editstr.substr(0,1)!=" ")
255 &&(editstr!=""))
256 {
257 strmovelen+=editstr.substr(0,1);
258 editstr=editstr.substr(1,editstr.length()-1);
259 }
260 } else {
261 cout << "Syntax: m<from>L<len> <target>" << endl;
262 return 0;
263 }
264
265 if (
266 (editstr.substr(0,1)==" ")
267 )
268 {
269 editstr=editstr.substr(1,editstr.length()-1);
270
271 while (
272 (editstr.substr(0,1)!=" ")
273 &&(editstr!=""))
274 {
275 strtopos+=editstr.substr(0,1);
276 editstr=editstr.substr(1,editstr.length()-1);
277 }
278 } else {
279 cout << "Syntax: m<from>L<len> <target>" << endl;
280 return 0;
281 }
282 cout << " strfrompos=" << strfrompos << endl;
283 cout << " strmovelen=" << strmovelen << endl;
284 cout << " strtopos=" << strtopos << endl;
285
286 long frompos=(Convert::hex2long(strfrompos)%SECTORSIZE);
287 long movelen=(Convert::hex2long(strmovelen)%SECTORSIZE);
288 long topos=(Convert::hex2long(strtopos)%SECTORSIZE);
289 cout << " pos=" << frompos << endl;
290 cout << " movelen=" << movelen << endl;
291 cout << " movepos=" << topos << endl;
292 void* x=malloc(movelen);
293 memcpy(x,bootblock+frompos,movelen);
294 memcpy(bootblock+topos,x,movelen);
295 free (x);
296 return 0;
297}
298
299long editbytes(unsigned char* bootblock,string editstr)
300{
301 string strpos="";
302 while ((editstr.substr(0,1)!=" ") &&(editstr!="")) {
303 strpos+=editstr.substr(0,1);
304 editstr=editstr.substr(1,editstr.length()-1);
305 }
306 if (editstr!="") {
307 editstr=editstr.substr(1,editstr.length()-1);
308 }
309 string binstr=getbinstr(editstr);
310 long pos=(Convert::hex2long(strpos)%SECTORSIZE);
311 cout << "binstr=" << binstr << " " << pos << endl;
312 memcpy(bootblock+pos,binstr.c_str(),binstr.length());
313 return 0;
314}
315
316void compareblock(hd24raw* rawdevice,unsigned long firstsector,unsigned long endsector,long current)
317{
318 unsigned int i;
319 unsigned int j;
320 unsigned int k;
321 unsigned char origblock[5120];
322 unsigned char destblock[5120];
323 string* startoff=Convert::int64tohex((__uint64)firstsector*512);
324 string* endoff=Convert::int64tohex((__uint64)endsector*512-1);
325 cout << "Compare range from offset "<< *startoff << " to offset " << *endoff <<endl;
326 delete startoff; startoff=NULL;
327 delete endoff; endoff=NULL;
328 int anydifs=0;
329 for (k=firstsector; k<endsector; k++)
330 {
331 rawdevice->readsectors(k,origblock,1);
332 rawdevice->readsectors(k-firstsector+current,destblock,1);
333 for (i=0;i<SECTORSIZE;i+=16) {
334 string strline1="";
335 string strline2="";
336 int havedifs=0;
337 long offset=k*512;
338 string* result1=Convert::int32tohex(offset+i);
339 strline1+= *result1+" ";
340 offset=current*512;
341 delete result1; result1=NULL;
342 string* result2=Convert::int32tohex(offset+i);
343 strline2+= *result2+" ";
344 delete result2; result2=NULL;
345 for (j=0;j<16;j++)
346 {
347 if (origblock[i+j]!=destblock[i+j])
348 {
349 string* result=Convert::byte2hex(origblock[i+j]);
350 strline1+= *result;
351 delete result; result=NULL;
352 havedifs=1;
353 } else {
354 strline1+=" ";
355 }
356 string *result= Convert::byte2hex(destblock[i+j]) ;
357 strline2+= *result;
358 delete result; result=NULL;
359 if (j==7) {
360 strline1+= "-" ;
361 strline2+= "-" ;
362 } else {
363 strline1+= " " ;
364 strline2+= " " ;
365 }
366 }
367 strline1+= " ";
368 strline2+= " ";
369 for (j=0;j<16;j++) {
370 strline1+= Convert::safebyte(origblock[i+j]);
371 if (origblock[i+j]!=destblock[i+j]) {
372 strline2+= Convert::safebyte(destblock[i+j]);
373 } else {
374 strline2+=" ";
375 }
376 }
377 if (havedifs==1) {
378 anydifs=1;
379 cout << strline1 << endl;
380 cout << strline2 << endl;
381 }
382 }
383 }
384 if (anydifs==0) {
385 cout << "Blocks are equal." << endl;
386 }
387}
388
389long scanforblock(hd24raw* rawdevice,string tofind,unsigned long firstsector,unsigned long endsector,long current)
390{
391 unsigned int i;
392 unsigned char bootblock[5120];
393 tofind=getbinstr(tofind);
394 if (tofind=="") return current;
395
396 /* Now that we know what to look for, let us try to find the string.
397 * Note that we can search across sector boundaries because we read
398 * 2 sectors at a time.
399 */
400 string* startoff= Convert::int64tohex((__uint64)firstsector*512);
401 string* endoff=Convert::int64tohex((__uint64)endsector*512-1);
402 cout << "Scan range from offset "<< *startoff << " to offset " << *endoff << endl;
403 delete startoff; startoff=NULL;
404 delete endoff; endoff=NULL;
405 for (i=firstsector; i<endsector; i++) {
406 rawdevice->readsectors(i,bootblock,2);
407 if ((i%0x1000)==0) {
408 string* curroff=Convert::int64tohex((__uint64)i*0x200);
409 cout << "Scan offset " << *curroff << "\r";
410 delete curroff; curroff=NULL;
411 }
412 /* check if string found. */
413 int j=0;
414 for (j=0;j<512;j++) {
415
416 if (memcmp((const void *)&bootblock[j],(const void *)tofind.c_str(),(size_t)tofind.length())==0) {
417 string* foundoff=Convert::int64tohex((__uint64)i*512+j);
418 cout << endl << "Found on offset " << *foundoff << endl;
419 delete foundoff; foundoff=NULL;
420 return i;
421 }
422 }
423 }
424 cout << endl << "Not found." << endl;
425 return current;
426}
427
428void fstfix(unsigned char * bootblock,int fixsize)
429{
430 for (int i=0;i<fixsize;i+=4)
431 {
432 unsigned char a=bootblock[i];
433 unsigned char b=bootblock[i+1];
434 unsigned char c=bootblock[i+2];
435 unsigned char d=bootblock[i+3];
436 bootblock[i]=d;
437 bootblock[i+1]=c;
438 bootblock[i+2]=b;
439 bootblock[i+3]=a;
440 }
441}
442
443int parsecommandline(int argc, char ** argv)
444{
445 int invalid=0;
446 force=0;
447 expertmode=0;
448 device="";
449 headerfilename="";
450 for (int c=1;c<argc;c++) {
451 string arg=argv[c];
452 if (arg.substr(0,2)!="--") {
453 if (fileexists(&arg)) {
454 device=arg;
455 force=1;
456 continue;
457 }
458 }
459 if (arg.substr(0,strlen("--dev="))=="--dev=") {
460 device=arg.substr(strlen("--dev="));
461 continue;
462 }
463 if (arg.substr(0,strlen("--expert"))=="--expert") {
464 expertmode=1;
465 continue;
466 }
467 if (arg.substr(0,strlen(ARGHEADER))==ARGHEADER) {
468 headerfilename=arg.substr(strlen(ARGHEADER));
469 continue;
470 }
471
472 if (arg.substr(0,strlen("--force"))=="--force") {
473 force=1;
474 continue;
475 }
476 cout << "Invalid argument: " << arg << endl;
477 invalid=1;
478 }
479 return invalid;
480}
481
482int main (int argc,char ** argv)
483{
484 int invalid=parsecommandline(argc,argv);
485 if (invalid!=0) {
486 return invalid;
487 }
488
489 hd24fs* fsys = NULL;
490 if (device=="") {
491 fsys=new hd24fs((const char*)NULL,hd24fs::MODE_RDWR);
492 } else {
493 cout << "Trying to use " << device << " as hd24 device." << endl;
494 fsys=new hd24fs((const char*)NULL,hd24fs::MODE_RDWR,&device,(force==1));
495 }
496
497 hd24raw* rawdevice = NULL;
498
499 rawdevice=new hd24raw(fsys); //1==1 is true -> no translate
500 if (!fsys->isOpen()) {
501 cout << "Cannot open hd24 device." << endl;
502 delete fsys; fsys=NULL;
503 if (rawdevice!=NULL)
504 {
505 delete rawdevice;
506 rawdevice=NULL;
507 }
508 return 1;
509 }
510 if (headerfilename!="")
511 {
512 if (!(fsys->useheaderfile(headerfilename)))
513 {
514 cout << "Couldn't load header file "<<headerfilename << endl;
515 delete fsys; fsys=NULL;
516 return 1;
517 };
518 }
519 //delete fsys; //not yet, rawdevice is using this
520 cout << "Using device " << *fsys->getdevicename() << endl;
521 /* Initialization */
522 unsigned char bootblock[5120];
523 unsigned long sectornum=0;
524 int nodump=0;
525 int noread=0;
526 int writesec=0;
527 unsigned long blockstart=0;
528 unsigned long blockend=0;
529 writeoffset=0;
530 unsigned long checksum=0;
531 string userinput;
532 string lastsearch="";
533 if (expertmode==1) {
534 cout << "Expert mode enabled. " << endl;
535 cout << "Warning! Disk writes are enabled." << endl;
536 cout << "You now have the capability to destroy." << endl;
537 cout << "Proceed with extreme caution!" << endl;
538 }
539
540try{
541 /* try block is intended to make sure hd24 device is closed on exit*/
542 string filename="outfile.dmp";
543
544 do {
545 int i;
546 int j;
547 if (enable_graphmode==1)
548 {
549 cout << "Enabling graph mode." << endl;
550 graphmode=1;
551 enable_graphmode=0;
552 }
553 if (disable_graphmode==1) {
554 cout << "Disabling graph mode." << endl;
555 graphmode=0;
556 disable_graphmode=0;
557 }
558 if (writesec==1) {
559 rawdevice->writesectors(sectornum,bootblock,1);
560 writesec=0;
561 }
562 if (noread==0) {
563 rawdevice->readsectors(sectornum,bootblock,1);
564 }
565 noread=0;
566 long offset=sectornum*512;
567 if (nodump==0) {
568 cout << "Sector " << *Convert::int32tohex((long)sectornum) << endl;
569
570 for (i=0;i<SECTORSIZE;i+=16) {
571 string* dummy=Convert::int32tohex(offset+i);
572 cout << *dummy << " ";
573 delete dummy; dummy=NULL;
574 for (j=0;j<16;j++) {
575 string* dummy= Convert::byte2hex(bootblock[i+j]);
576 cout << *dummy;
577 if (j==7) {
578 cout << "-" ;
579 } else {
580 cout << " " ;
581 }
582 delete dummy; dummy=NULL;
583 }
584 cout << " ";
585 for (j=0;j<16;j++) {
586 cout << Convert::safebyte(bootblock[i+j]);
587 }
588 cout << "" << endl;
589 }
590 }
591 nodump=0;
592 cout << "-";
593 char inputbuf[1025];
594 cin.getline(inputbuf,1024);
595 userinput="";
596 userinput+=inputbuf;
597 if (userinput=="") {
598 continue;
599 }
600 while (
601 (userinput.substr(userinput.length()-1,1)==" ")
602 ||(userinput.substr(userinput.length()-1,1)=="\n")
603 ||(userinput.substr(userinput.length()-1,1)=="\r")
604 )
605 {
606 userinput=userinput.substr(0,userinput.length()-1);
607 }
608 if (userinput=="+") {
609 sectornum++;
610 continue;
611 }
612 if (userinput=="gon") {
613 if (graphmode==0) {
614 enable_graphmode=1;
615 }
616 continue;
617 }
618 if ((userinput=="goff")||(userinput=="gof")) {
619 if (graphmode==1) {
620 disable_graphmode=1;
621 }
622 continue;
623 }
624 if (userinput=="wo") {
625 writeoffset=0;
626 cout << "Writeoffset cleared." << endl;
627 nodump=1; // inhibit viewing the sector after this command.
628 continue;
629 }
630 if (userinput.substr(0,2)=="wo") {
631 writeoffset=Convert::hex2long(userinput.substr(2,userinput.length()-2));
632 string* convwrite=Convert::int32tohex(writeoffset);
633 cout << "Writeoffset set to " << *convwrite << " sectors." << endl;
634 delete convwrite; convwrite=NULL;
635 nodump=1; // inhibit viewing the sector after this command.
636 continue;
637 }
638 if (userinput.substr(0,1)=="+") {
639 long sectoadd=Convert::hex2long(userinput.substr(1,userinput.length()-1));
640 sectornum+=sectoadd;
641 continue;
642 }
643 if (userinput=="-") {
644 if (sectornum>0)
645 {
646 sectornum--;
647 } else {
648 sectornum=0;
649 }
650 continue;
651 }
652 if (userinput.substr(0,1)=="-") {
653 long sectoadd=Convert::hex2long(userinput.substr(1,userinput.length()-1));
654 if ((__uint32)sectoadd>(__uint32)sectornum)
655 {
656 sectornum=0;
657 } else {
658 sectornum-=sectoadd;
659 }
660 continue;
661 }
662 if (userinput==".") {
663 noread=1;
664 continue;
665 }
666 if ((userinput.substr(0,1)=="?")||(userinput=="help")) {
667 cout << "Help for hd24hexview " << VERSION << endl;
668 cout << "==============================" << endl;
669 cout << "General:" <<endl;
670 cout << " q quit" << endl;
671 cout << " ? shows this help" << endl;
672 cout << endl;
673 cout << "Navigation:" << endl;
674 cout << " + dump next sector" << endl;
675 cout << " +<n> increment n sectors, then dump sector"<<endl;
676 cout << " - dump prev sector" << endl;
677 cout << " -<n> decrement n sectors, then dump sector"<<endl;
678 cout << " . re-display current sector" << endl;
679 cout << " d<hex> dump sector <hex>" << endl;
680 cout << " d-<hex> dump sector totalnumberofsectors-<hex>" << endl;
681 cout << " d re-read current sector from disk" << endl;
682 cout << " m<from>l<hexlen> <to>" << endl;
683 cout << " move <hexlen> bytes from offset <from> to <to>" << endl;
684 cout << " o<hex> dump sector that contains offset <hex>" << endl;
685 cout << " s x y.. scan marked block for byte sequence x y ..." << endl;
686 cout << " s'...' scan marked block for exact string" << endl;
687 cout << " e<p> xx edit byte sequence at pos p to xxxx " << endl;
688 cout << " e<p> 'x' edit pos p to string 'x'" << endl;
689 cout << endl;
690 cout << "Block commands:" << endl;
691 cout << " bb mark start of sector as block beginning" << endl;
692 cout << " be mark end of sector as block end" << endl;
693 cout << " bc block clear" << endl;
694 cout << " diff compare marked block with current" << endl;
695 cout << " p paste first sector of marked block to current sector" << endl;
696 cout << endl;
697 cout << "File commands:" << endl;
698 cout << " n<xx> set filename to xx" << endl;
699 cout << " n clear filename" << endl;
700 cout << " w write marked block to named file/device" << endl;
701 cout << " wo clear sector write offset for file/device write" << endl;
702 cout << " wo<xx> set write offset to xx sectors" << endl;
703 cout << " ws write back current edited sector to disk" << endl;
704 cout << "HD24 specific features:" << endl;
705 cout << " fix reverse byte ordering of 32 bit words" << endl;
706 cout << " for better human readability" << endl;
707 cout << " cs Calc checksum of selected block" << endl;
708 cout << " scs Set zero checksum of selected block" << endl;
709
710 nodump=1; // inhibit viewing the sector after this command.
711 continue;
712 }
713 if (userinput.substr(0,2)=="bc") {
714 blockstart=0;
715 blockend=0;
716 cout << "Block selection cleared." << endl;
717 nodump=1; // inhibit viewing the sector after this command.
718 continue;
719 }
720 if (userinput.substr(0,2)=="bb") {
721 cout << "Block start set." << endl;
722 nodump=1; // inhibit viewing the sector after this command.
723 blockstart=sectornum;
724 continue;
725 }
726 if (userinput.substr(0,2)=="be") {
727 cout << "Block end set." << endl;
728 /* dump is startsector..endsector,
729 * excl. end sector. number of bytes to dump=
730 * (blockend-blockstart)*512
731 */
732 nodump=1; // inhibit viewing the sector after this command.
733 blockend=sectornum+1;
734 continue;
735 }
736 if (userinput.substr(0,2)=="cs") {
737 checksum=calcblockchecksum(rawdevice,blockstart,blockend);
738 cout << "Block checksum is " << checksum << endl;
739 nodump=1;
740 noread=1;
741 continue;
742 }
743 if (userinput.substr(0,3)=="scs") {
744 if (blockend-1!=sectornum) {
745 cout << "Current sector must be block end." << endl;
746 nodump=1;
747 noread=1;
748 continue;
749 }
750 unsigned long checksum=calcblockchecksum(rawdevice,blockstart,blockend);
751 unsigned long oldchecksum=0;
752 oldchecksum+=((unsigned char)(bootblock[511])); oldchecksum=oldchecksum <<8;
753 oldchecksum+=((unsigned char)(bootblock[510])); oldchecksum=oldchecksum <<8;
754 oldchecksum+=((unsigned char)(bootblock[509])); oldchecksum=oldchecksum <<8;
755 oldchecksum+=((unsigned char)(bootblock[508]));
756 oldchecksum-=checksum;
757 bootblock[508]=oldchecksum%256; oldchecksum=oldchecksum >> 8;
758 bootblock[509]=oldchecksum%256; oldchecksum=oldchecksum >> 8;
759 bootblock[510]=oldchecksum%256; oldchecksum=oldchecksum >> 8;
760 bootblock[511]=oldchecksum%256; oldchecksum=oldchecksum >> 8;
761
762 noread=1;
763 continue;
764 }
765 if (userinput.substr(0,4)=="diff") {
766 nodump=1; // inhibit viewing the sector after this command.
767 if (blockend==blockstart) {
768 cout << "Please set block start/end first." << endl;
769 continue;
770 }
771 compareblock(rawdevice,blockstart,blockend,sectornum);
772 continue;
773 }
774 if (userinput.substr(0,1)=="s") {
775 if (userinput=="s") {
776 userinput+=lastsearch;
777 } else {
778 lastsearch=userinput.substr(1,userinput.length()-1);
779 }
780 if (blockend==blockstart) {
781 sectornum=scanforblock(rawdevice,lastsearch,0,0xffffffff,sectornum);
782 } else {
783 sectornum=scanforblock(rawdevice,lastsearch,blockstart,blockend,sectornum);
784 }
785 continue;
786 }
787 if (userinput=="version") {
788 cout << VERSION << endl;
789 nodump=1; // inhibit viewing the sector after this command.
790 noread=1;
791 continue;
792 }
793 if (userinput.substr(0,1)=="p") {
794 //paste
795 if (blockend==blockstart) {
796 nodump=1;
797 cout << "Mark a block first." << endl;
798 continue;
799 }
800 rawdevice->readsectors(blockstart,bootblock,1);
801 noread=1;
802 continue;
803 }
804 if (userinput.substr(0,1)=="e") {
805 string editstr=userinput.substr(1,userinput.length()-1);
806 editbytes(bootblock,editstr);
807 noread=1;
808 continue;
809 }
810 if (userinput.substr(0,1)=="m") {
811 string editstr=userinput.substr(1,userinput.length()-1);
812 movebytes(bootblock,editstr);
813 noread=1;
814 continue;
815 }
816 if (userinput=="d") {
817 continue;
818 }
819
820 if (userinput.substr(0,2)=="d-") {
821 // if we have 10 sectors (0..9), last one is d-1=sector 9
822 // so sector num is total number of secs - negnum
823 sectornum=rawdevice->getlastsectornum()-Convert::hex2long(userinput.substr(2,userinput.length()-2))+1;
824 continue;
825 }
826
827 if (userinput.substr(0,1)=="d") {
828 sectornum=Convert::hex2long(userinput.substr(1,userinput.length()-1));
829 continue;
830 }
831 if (userinput.substr(0,1)=="o") {
832 long offset=Convert::hex2long(userinput.substr(1,userinput.length()-1));
833 offset-=(offset%512);
834 sectornum=offset/512;
835 }
836 if (userinput=="fix") {
837 fstfix(bootblock,512);
838 noread=1;
839 continue;
840 }
841 if (userinput.substr(0,1)=="n") {
842 int dangerousname=0;
843 if (userinput.substr(1,4)=="\\\\.\\") {
844 dangerousname=1;
845 }
846 if (userinput.substr(1,5)=="/dev/") {
847 dangerousname=1;
848 }
849 if (userinput.substr(1,4)=="//./") {
850 dangerousname=1;
851 }
852 if (dangerousname==1) {
853 if (expertmode==0) {
854 expertmodemessage("Writing to devices");
855 } else {
856 filename=userinput.substr(1,userinput.length()-1);
857 cout << "OK, setting output file to device " << filename << endl;
858 cout << "Please take your time to make sure this is really the correct drive."<<endl;
859 string strlower=filename;
860 int (*pf)(int)=tolower;
861 std::transform (strlower.begin(),strlower.end(),strlower.begin(),pf);
862 if (
863 (strlower=="\\\\.\\physicaldrive0")
864 || (strlower=="/dev/hda"))
865 {
866 cout << "CAREFUL!!! " << strlower << " is probably your main system disk!" << endl;
867 cout << "If you continue you might mess up your computer!!!" << endl;
868 cout << "I will not stop you from doing this, so " << endl;
869 cout << "MAKE SURE THIS IS REALLY THE DRIVE YOU WANT TO WRITE TO!" << endl;
870 cout << "UNLESS ABSOLUTELY SURE, STOP WHAT YOU ARE DOING RIGHT NOW!" << endl;
871 }
872 }
873 } else {
874 filename=userinput.substr(1,userinput.length()-1);
875 }
876 nodump=1; // inhibit viewing the sector after this command.
877 if (filename=="") {
878 string filename="outfile.dmp";
879 }
880 cout << "Current output filename is " << filename << endl;
881
882 continue;
883 }
884 if (userinput=="w") {
885 cout << "Writing " << blockend-blockstart << " sectors to " << filename << endl;
886 writetofile(rawdevice,filename,blockstart,blockend);
887 nodump=1; // inhibit viewing the sector after this command.
888 cout << "Done." << endl;
889 continue;
890 }
891 if (userinput=="ws") {
892 if (expertmode==1) {
893 writesec=1;
894 } else {
895 noread=1;
896 expertmodemessage("Writing sectors");
897 nodump=1;
898 }
899 }
900 if (userinput=="freesec") {
901 nodump=1;
902 cout << "Sector " << *Convert::int32tohex((long)rawdevice->getnextfreesector(0xFFFFFFFF)) << endl;
903 cout << rawdevice->getnextfreesector(0xFFFFFFFF) << endl;
904 }
905 if (userinput=="commit") {
906 if (expertmode==1) {
907 cout << "Commit FS to disk." << endl;
908 fsys->commit();
909 }
910 }
911 } while (userinput!="q");
912
913} catch (string e) {
914 cout << "Exiting because of an unexpected error." << endl;
915 delete rawdevice; rawdevice=NULL;
916 delete fsys; fsys=NULL;
917 return 1;
918}
919 delete rawdevice; rawdevice=NULL;
920 delete fsys; fsys=NULL;
921 return 0;
922}
923
diff --git a/src/hd24info.cpp b/src/hd24info.cpp
new file mode 100755
index 0000000..bcc834b
--- /dev/null
+++ b/src/hd24info.cpp
@@ -0,0 +1,111 @@
1#include <iostream>
2#include <string>
3#include <convertlib.h>
4#include <hd24fs.h>
5
6using namespace std;
7
8void showsongs(hd24project* currentproj)
9{
10 int numsongs = currentproj->songcount();
11
12 cout << "======================================================================" << endl;
13
14 if (numsongs == 0)
15 {
16 cout << " There are no songs in this project." << endl;
17 }
18
19 for (int i = 1; i <= numsongs; i++)
20 {
21 hd24song currsong = *(currentproj->getsong(i));
22 string* songname1 = new string("");
23 cout << " ";
24
25 if (i < 10)
26 {
27 cout << " ";
28 }
29
30 cout << i << ": ";
31
32 string* currsname = currsong.songname();
33 *songname1 += *currsname;
34
35 cout << *(Convert::padright(*songname1, 20, " "));
36 cout << *(currsong.display_duration()) << ", ";
37
38 string* chans = Convert::int2str(currsong.logical_channels());
39 chans = Convert::padleft(*chans,2," ");
40
41 cout << *chans << "ch. " << currsong.samplerate() << " Hz ";
42
43 delete(currsname);
44 delete(songname1);
45
46 cout << endl;
47 }
48}
49
50void showprojects(hd24fs* currenthd24)
51{
52 int numprojs = currenthd24->projectcount();
53
54 for (int i = 1; i <= numprojs; i++)
55 {
56 hd24project currproj = *(currenthd24->getproject(i));
57 string* projname1 = new string("");
58 string* currpname = currproj.projectname();
59 *projname1 += *currpname;
60
61 cout << "======================================================================" << endl << "Project " << i << ": ";
62 cout << *projname1 << endl;
63
64 showsongs (&currproj);
65
66 delete(currpname);
67 delete(projname1);
68 }
69}
70
71int main()
72{
73 hd24fs* fsysp=new hd24fs((const char*)NULL);
74 hd24fs fsys=*fsysp;
75 string* volname;
76
77 if (!fsys.isOpen())
78 {
79 cout << "Cannot open hd24 device." << endl;
80 return 1;
81 }
82
83 int devcount = fsys.hd24devicecount();
84
85 if (devcount > 1)
86 {
87 cout << "Number of hd24 devices found: " << fsys.hd24devicecount() << endl;
88 }
89
90 for (int i = 0; i < devcount; i++)
91 {
92 hd24fs* currhd24 = new hd24fs((const char*)NULL,fsys.mode(), i);
93
94 if (devcount > 1)
95 {
96 cout << "Showing info for device #" << i << endl;
97 }
98
99 volname = currhd24->volumename();
100 string vname = "";
101 vname += *volname;
102 cout << "Volume name : " << vname<<endl;
103 delete volname;
104
105 cout << "Number of projects : " << currhd24->projectcount() << endl;
106 showprojects(currhd24);
107 delete currhd24;
108 }
109
110 return 0;
111}
diff --git a/src/hd24syx2bin.cpp b/src/hd24syx2bin.cpp
new file mode 100644
index 0000000..1ccc501
--- /dev/null
+++ b/src/hd24syx2bin.cpp
@@ -0,0 +1,113 @@
1//syx2bin.cpp
2//converts an alesis hd24 .syx OS file to binary
3using namespace std;
4#include <iostream>
5#define SKIPCHARS 9
6
7int main(int argc, char *argv[])
8{
9
10 FILE *pInfile;
11 FILE *pOutfile;
12 char *pInfilename, *pOutfilename;
13 int loop;
14 int msbits;
15
16 if(argc < 3)
17 {
18 fprintf(stderr, "Usage : %s infile outfile\n",argv[0]);
19 exit(1);
20 }
21
22 pInfilename = argv[1];
23 pOutfilename = argv[2];
24
25 pInfile = fopen(pInfilename, "rb");
26 if(!pInfile)
27 {
28 fprintf(stderr, "ERROR : couldn't open %s for reading\n", pInfilename);
29 exit(1);
30 }
31 pOutfile = fopen(pOutfilename, "wb");
32 if(!pOutfile)
33 {
34 fprintf(stderr, "ERROR : couldn't open %s for writing\n", pOutfilename);
35 fclose(pInfile); //close open infile
36 exit(1);
37 }
38
39 //skip F0 and 5 byte header
40 for(loop = 0; loop < SKIPCHARS; loop++)
41 {
42 fgetc(pInfile);
43 }
44
45// msbits = fgetc(pInfile);
46 unsigned char b[8];
47 unsigned char header[64];
48 int whichbyte=3;
49int headerbyte=0;
50 unsigned int checksum=0;
51 int filesize=0;
52 int written=0;
53 while((msbits != EOF) && (msbits != 0xF7)) //get most significant bits byte
54 {
55 int i;
56 int j;
57 j=10;
58
59 for (i=0;i<8;i++) {
60 b[i]=fgetc(pInfile);
61 if (b[i]==0xF7) {
62 msbits=0xF7;
63 j=i;
64 }
65 }
66 // convert 8->7 bytes
67 unsigned char bits=b[0];
68 int max=8;
69 if (j<max) { max=j; }
70 for (i=1;i<max;i++) {
71#ifdef LSB
72 int onebit=(bits & 1) <<7;
73 b[i]|=onebit;
74 bits = (bits>>1);
75#else
76 int onebit=(bits << 1) & 0x80;
77 b[i]|=onebit;
78 bits = (bits << 1);
79#endif
80 fputc((unsigned char) b[i], pOutfile);
81 written++;
82 if (headerbyte<64) {
83 header[headerbyte]=b[i];
84 headerbyte++;
85 }
86 else
87 {
88 if (filesize==0) {
89 int x1=(int)((unsigned char)header[47]);
90 int x2=(int)((unsigned char)header[46]);
91 int x3=(int)((unsigned char)header[45]);
92 int x4=(int)((unsigned char)header[44]);
93 filesize=x1+(256*x2)+(256*256*x3)+(256*256*256*x4);
94 }
95 }
96 whichbyte=(whichbyte+1)%4;
97 checksum=(checksum+b[i] ) % 256;
98//((unsigned char)(b[i]) << (8*(whichbyte))) ;
99 if (filesize!=0) {
100 if (written>=filesize) break;
101 }
102 }
103 if (filesize!=0) {
104 if (written>=filesize) break;
105 }
106
107 }
108 printf("Checksum=%x\n",checksum);
109 fclose(pInfile);
110 fclose(pOutfile);
111 return 0;
112}
113
diff --git a/src/hd24towav.cpp b/src/hd24towav.cpp
new file mode 100755
index 0000000..7d654ef
--- /dev/null
+++ b/src/hd24towav.cpp
@@ -0,0 +1,233 @@
1#ifdef WINDOWS
2namespace std {}
3#endif
4using namespace std;
5#include <string>
6#include <iostream>
7#include "convertlib.h"
8/*
9** Copyright (C) 2001-2005 Erik de Castro Lopo <erikd@mega-nerd.com>
10**
11** This program is free software; you can redistribute it and/or modify
12** it under the terms of the GNU General Public License as published by
13** the Free Software Foundation; either version 2 of the License, or
14** (at your option) any later version.
15**
16** This program is distributed in the hope that it will be useful,
17** but WITHOUT ANY WARRANTY; without even the implied warranty of
18** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19** GNU General Public License for more details.
20**
21** You should have received a copy of the GNU General Public License
22** along with this program; if not, write to the Free Software
23** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24*/
25
26#include <stdio.h>
27
28/* Include this header file to use functions from libsndfile. */
29#include <sndfile.h>
30
31/* This will be the length of the buffer used to hold.frames while
32** we process them.
33*/
34#define BUFFER_LEN 1024
35
36/* libsndfile can handle more than 6 channels but we'll restrict it to 6. */
37#define MAX_CHANNELS 6
38string inputfilename;
39string outputfilename;
40string format;
41long rate;
42long bits;
43int convertfile(string inputfilename) {
44/* This is a buffer of double precision floating point values
45 * which will hold our data while we process it.
46 */
47 format="wav";
48 cout << "Converting " << inputfilename << endl;
49 if (rate==0) {
50 if (
51 (inputfilename.find("44k1",0) != string::npos)
52 ||(inputfilename.find("44K1",0) != string::npos)
53 ||(inputfilename.find("44100",0) != string::npos)
54 ) {
55 rate=44100;
56 }
57 if (
58 (inputfilename.find("48k",0) != string::npos)
59 ||(inputfilename.find("48K",0) != string::npos)
60 ||(inputfilename.find("48000",0) != string::npos)
61 ) {
62 rate=48000;
63 }
64 if (
65 (inputfilename.find("88k2",0) != string::npos)
66 ||(inputfilename.find("88K2",0) != string::npos)
67 ||(inputfilename.find("88200",0) != string::npos)
68 ) {
69 rate=88200;
70 }
71 if (
72 (inputfilename.find("96k",0) != string::npos)
73 ||(inputfilename.find("96K",0) != string::npos)
74 ||(inputfilename.find("96000",0) != string::npos)
75 ) {
76 rate=96000;
77 }
78 }
79 bits=24;
80 static int data [BUFFER_LEN] ;
81
82 /* A SNDFILE is very much like a FILE in the Standard C library. The
83 ** sf_open function return an SNDFILE* pointer when they sucessfully
84 ** open the specified file.
85 */
86 SNDFILE *infile, *outfile ;
87
88 /* A pointer to an SF_INFO stutct is passed to sf_open.
89 ** On read, the library fills this struct with information about the file.
90 ** On write, the struct must be filled in before calling sf_open.
91 */
92 SF_INFO sfinfoin ;
93 SF_INFO sfinfoout;
94 int readcount ;
95 if (inputfilename=="") {
96 cout << "Must specify --input filename" << endl;
97 return 1;
98 }
99 if (outputfilename=="") {
100 outputfilename=inputfilename;
101 string ext="";
102 if (format=="wav") {
103 ext=".wav";
104 }
105 if (outputfilename.substr(outputfilename.length()-4,4)==".raw") {
106 outputfilename=outputfilename.substr(0,outputfilename.length()-4)+ext;
107 }
108 if (outputfilename=="") {
109 cout << "Must specify --output filename" << endl;
110 return 1;
111 }
112 }
113 const char *infilename = inputfilename.c_str();
114 const char *outfilename = outputfilename.c_str();
115
116 /* Here's where we open the input file. We pass sf_open the file name and
117 ** a pointer to an SF_INFO struct.
118 ** On successful open, sf_open returns a SNDFILE* pointer which is used
119 ** for all subsequent operations on that file.
120 ** If an error occurs during sf_open, the function returns a NULL pointer.
121 **
122 ** If you are trying to open a raw headerless file you will need to set the
123 ** format and channels fields of sfinfo before calling sf_open(). For
124 ** instance to open a raw 16 bit stereo PCM file you would need the following
125 ** two lines:
126 **
127 ** sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16 ;
128 ** sfinfo.channels = 2 ;
129 */
130 sfinfoin.format = SF_FORMAT_RAW | SF_FORMAT_PCM_24|SF_ENDIAN_BIG ;
131 sfinfoin.channels = 1 ;
132
133 if (format=="wav") {
134 sfinfoout.format = SF_FORMAT_WAV ;
135 }
136 if (bits==16) {
137 sfinfoout.format|=SF_FORMAT_PCM_16;
138 }
139 if (bits==24) {
140 sfinfoout.format|=SF_FORMAT_PCM_24;
141 }
142
143 sfinfoout.samplerate=rate;
144 sfinfoout.channels = 1 ;
145 if (! (infile = sf_open (infilename, SFM_READ, &sfinfoin)))
146 { /* Open failed so print an error message. */
147 printf ("Not able to open input file %s.\n", infilename) ;
148 /* Print the error message from libsndfile. */
149 puts (sf_strerror (NULL)) ;
150 return 1 ;
151 } ;
152
153 /* Open the output file. */
154 if (! (outfile = sf_open (outfilename, SFM_WRITE, &sfinfoout)))
155 { printf ("Not able to open output file %s.\n", outfilename) ;
156 puts (sf_strerror (NULL)) ;
157 return 1 ;
158 } ;
159
160 /* While there are.frames in the input file, read them, process
161 ** them and write them to the output file.
162 */
163 while ((readcount = sf_read_int (infile, data, BUFFER_LEN)))
164 {
165 sf_write_int (outfile, data, readcount) ;
166 } ;
167
168 /* Close input and output files. */
169 sf_close (infile) ;
170 sf_close (outfile) ;
171 return 0;
172}
173
174int parsecommandline(int argc, char **argv)
175{
176 int invalid = 0;
177
178 for (int c = 1; c < argc; c++) {
179 string arg = argv[c];
180
181 if (arg.substr(0, 1) != "-") {
182 inputfilename = arg;
183 outputfilename = "";
184 convertfile(inputfilename);
185 continue;
186 }
187
188 if (arg.substr(0,strlen("--input=")) == "--input=") {
189 inputfilename = arg.substr(strlen("--input="));
190 continue;
191 }
192
193 if (arg.substr(0,strlen("--output=")) == "--output=") {
194 outputfilename = arg.substr(strlen("--output="));
195 continue;
196 }
197
198 if (arg.substr(0,strlen("--rate=")) == "--rate=") {
199 rate = Convert::str2long(arg.substr(strlen("--rate=")));
200 continue;
201 }
202
203 if (arg.substr(0,strlen("--bits=")) == "--bits=") {
204 bits = Convert::str2long(arg.substr(strlen("--bits=")));
205 continue;
206 }
207
208 cout << "Invalid argument: " << arg << endl;
209 invalid = 1;
210 }
211 return invalid;
212}
213
214int main (int argc, char **argv)
215{
216 rate = 0;
217 int invalid = parsecommandline(argc, argv);
218
219 if (invalid!=0) {
220 return invalid;
221 }
222
223 return 0 ;
224} /* main */
225
226
227/*
228** Do not edit or modify anything in this comment block.
229** The arch-tag line is a file identity tag for the GNU Arch
230** revision control system.
231**
232** arch-tag: de9fdd1e-b807-41ef-9d51-075ba383e536
233*/
diff --git a/src/hd24wavefix.cpp b/src/hd24wavefix.cpp
new file mode 100755
index 0000000..c7ab2f0
--- /dev/null
+++ b/src/hd24wavefix.cpp
@@ -0,0 +1,207 @@
1#include "config.h"
2#include <iostream>
3#include <algorithm>
4#include <cctype>
5#include <string>
6#include "hd24fs.h"
7#include <sys/types.h>
8#include <sys/stat.h>
9#include <fcntl.h>
10#ifndef WINDOWS
11#include <unistd.h>
12#endif
13#include <stdio.h>
14#include <stdlib.h>
15#include <iostream>
16#include "convertlib.h"
17#define HEADERSIZE 44
18#define SAMPLES_IN_HALF_BUF 1024*1024
19#define SAMPLES_IN_FULL_BUF 2*SAMPLES_IN_HALF_BUF
20#define BYTES_PER_SAM 3
21#define BYTES_IN_HALF_BUF BYTES_PER_SAM*SAMPLES_IN_HALF_BUF
22#define BYTES_IN_FULL_BUF BYTES_PER_SAM*SAMPLES_IN_FULL_BUF
23char audiobuf[BYTES_IN_FULL_BUF];
24char fixbuf[BYTES_IN_HALF_BUF];
25string inputfile;
26string outputfile;
27int simple=0;
28FILE* infile;
29FILE* outfile;
30__uint64 writeoffset;
31
32void clearaudiobuf()
33{
34 int i;
35 for (i=0;i<BYTES_IN_FULL_BUF;i++) {
36 audiobuf[i]=0;
37 }
38}
39void shiftaudiobuf()
40{
41 int i;
42 for (i=0;i<BYTES_IN_HALF_BUF;i++) {
43 audiobuf[i]=audiobuf[i+BYTES_IN_HALF_BUF];
44 audiobuf[i+BYTES_IN_HALF_BUF]=0;
45 }
46}
47int getsam(int samnum)
48{
49 int samval=audiobuf[samnum+BYTES_IN_HALF_BUF]
50 +(audiobuf[samnum+BYTES_IN_HALF_BUF]*256)
51 +(audiobuf[samnum+BYTES_IN_HALF_BUF]*256*256);
52 return samval;
53}
54int tosigned(int samval) {
55 if (samval>=(1<<23)) {
56 samval-=(1<<24);
57 }
58 return samval;
59}
60int topos(int samval) {
61 return samval+(1<<23);
62}
63bool fileexists (string* fname) {
64 struct stat fi;
65 if ((stat (fname->c_str(), &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0)) {
66 return true;
67 }
68 return false;
69}
70void hd24seek(FSHANDLE devhd24,__uint64 seekpos)
71{
72#if defined(LINUX) || defined(DARWIN)
73 lseek(devhd24,seekpos,0);
74// lseek64(devhd24,seekpos,0);
75#endif
76#ifdef WINDOWS
77 LARGE_INTEGER li;
78 li.HighPart=seekpos>>32;
79 li.LowPart=seekpos%((__uint64)1<<32);
80 SetFilePointerEx(devhd24,li,NULL,FILE_BEGIN);
81#endif
82 return;
83}
84
85int parsecommandline(int argc, char ** argv)
86{
87 int invalid=0;
88 inputfile="";
89 outputfile="";
90 for (int c=1;c<argc;c++) {
91 string arg=argv[c];
92 if (arg.substr(0,strlen("--input="))=="--input=") {
93 inputfile=arg.substr(strlen("--input="));
94 continue;
95 }
96 if (arg.substr(0,strlen("--output="))=="--output=") {
97 outputfile=arg.substr(strlen("--output="));
98 continue;
99 }
100 if (arg.substr(0,strlen("--simple"))=="--simple") {
101 simple=1;
102 continue;
103 }
104 cout << "Invalid argument: " << arg << endl;
105 invalid=1;
106 }
107 return invalid;
108}
109void findmask(FILE* infile)
110{
111 fseek(infile,HEADERSIZE,SEEK_SET);
112 return;
113}
114void copyheader(FILE* infile,FILE* outfile)
115{
116 char buffer[HEADERSIZE];
117 fseek(infile,0,SEEK_SET);
118 int readcount=fread((void*)&buffer[0],1,HEADERSIZE,infile);
119 if (readcount>0) {
120 int writecount=fwrite((const void*)&buffer[0],1,HEADERSIZE,outfile);
121 if (writecount==0) {
122 cout << "Cannot write output file" << endl;
123 }
124 }
125 return;
126}
127void copyaudio(FILE* infile,FILE* outfile) {
128 int readcount;
129 do {
130 shiftaudiobuf();
131 readcount=fread((void*)&audiobuf[BYTES_IN_HALF_BUF],1,BYTES_IN_HALF_BUF,infile);
132 for (int i=0; i<SAMPLES_IN_HALF_BUF-1;i+=2) {
133 int q0=3;
134 int q1=0;
135 if (audiobuf[BYTES_IN_HALF_BUF+i*3+q0+2-6]==audiobuf[BYTES_IN_HALF_BUF+i*3+q1+2]) {
136 audiobuf[BYTES_IN_HALF_BUF+i*3+q0+2]=audiobuf[BYTES_IN_HALF_BUF+i*3+q1+2];
137 } else {
138 audiobuf[BYTES_IN_HALF_BUF+i*3+q0+0]=audiobuf[BYTES_IN_HALF_BUF+i*3+q1+0];
139 audiobuf[BYTES_IN_HALF_BUF+i*3+q0+1]=audiobuf[BYTES_IN_HALF_BUF+i*3+q1+1];
140 audiobuf[BYTES_IN_HALF_BUF+i*3+q0+2]=audiobuf[BYTES_IN_HALF_BUF+i*3+q1+2];
141 }
142 }
143 if (readcount>0) {
144 int writecount=fwrite(
145 (void*)&audiobuf[BYTES_IN_HALF_BUF],1,readcount,outfile);
146 if (writecount==0) {
147 cout << "Cannot write output file" << endl;
148 }
149 }
150
151 }
152 while (readcount>0);
153 return;
154}
155void simplecopyaudio(FILE* infile,FILE* outfile)
156{
157 int readcount;
158 do {
159 readcount=fread((void*)&audiobuf[BYTES_IN_HALF_BUF],1,BYTES_IN_HALF_BUF,infile);
160 for (int i=0; i<SAMPLES_IN_HALF_BUF-1;i+=2) {
161 int q0=3;
162 int q1=0;
163 audiobuf[BYTES_IN_HALF_BUF+i*3+q0+0]=audiobuf[BYTES_IN_HALF_BUF+i*3+q1+0];
164 audiobuf[BYTES_IN_HALF_BUF+i*3+q0+1]=audiobuf[BYTES_IN_HALF_BUF+i*3+q1+1];
165 audiobuf[BYTES_IN_HALF_BUF+i*3+q0+2]=audiobuf[BYTES_IN_HALF_BUF+i*3+q1+2];
166 }
167 if (readcount>0) {
168 int writecount=fwrite(
169 (void*)&audiobuf[BYTES_IN_HALF_BUF],1,readcount,outfile);
170 if (writecount==0) {
171 cout << "Cannot write output file" << endl;
172 }
173 }
174
175 }
176 while (readcount>0);
177 return;
178}
179void dothefix(FILE* infile, FILE* outfile)
180{
181 copyheader(infile,outfile);
182 findmask(infile);
183 if (simple==1) {
184 simplecopyaudio(infile,outfile);
185 } else {
186 copyaudio(infile,outfile);
187 }
188}
189int main (int argc,char ** argv)
190{
191 int invalid=parsecommandline(argc,argv);
192 if (invalid!=0) {
193 return invalid;
194 }
195 if ((inputfile=="")||(outputfile=="")) {
196 cout << "Usage: hd24wavefix [--simple] --input=<inputfile> --output=<outputfile>" << endl;
197 return 1;
198 }
199 clearaudiobuf();
200 // Open files
201 infile=fopen(inputfile.c_str(),"rb");
202 outfile=fopen(outputfile.c_str(),"wb");
203 dothefix(infile,outfile);
204 fclose(outfile);
205 fclose(infile);
206 return 0;
207}
diff --git a/src/installer/PkgInfo.hd24connect b/src/installer/PkgInfo.hd24connect
new file mode 100644
index 0000000..4907b2c
--- /dev/null
+++ b/src/installer/PkgInfo.hd24connect
@@ -0,0 +1,2 @@
1APPLnone
2
diff --git a/src/installer/PkgInfo.setup b/src/installer/PkgInfo.setup
new file mode 100644
index 0000000..4907b2c
--- /dev/null
+++ b/src/installer/PkgInfo.setup
@@ -0,0 +1,2 @@
1APPLnone
2
diff --git a/src/installer/bin2c.c b/src/installer/bin2c.c
new file mode 100644
index 0000000..6c81fe6
--- /dev/null
+++ b/src/installer/bin2c.c
@@ -0,0 +1,72 @@
1/* BIN2C Converts binary data to be included in C source codes */
2
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <sys/stat.h>
8
9
10static void usage(void)
11{
12 fprintf(stderr, "BIN2C Binary to C converter\n");
13 fprintf(stderr, "usage: BIN2C <binfile> <cfile> <varname>\n");
14 exit(0);
15}
16
17
18int main(int argc, char **argv)
19{
20 FILE* binfile;
21 FILE* cfile;
22 struct stat statbuf;
23 long len;
24 int cntr;
25 unsigned char inbyte;
26 char varname[80], cfilename[80];
27
28 if (argc == 1)
29 usage();
30
31 if (! (binfile = fopen(argv[1], "rb"))) {
32 perror("fopen");
33 exit(1);
34 }
35
36 stat(argv[1], &statbuf);
37 len = statbuf.st_size;
38
39 if (argc > 2)
40 strcpy(cfilename, argv[2]);
41 else
42 strcpy(cfilename,"bin2c.c");
43 cfile = fopen(cfilename, "wt");
44
45 cntr = 0;
46
47 if (argc > 3)
48 strcpy(varname, argv[3]);
49 else
50 strcpy(varname, "varname");
51
52 fprintf(cfile, "unsigned char %s[%ld] = {\n", varname, len);
53
54 fread(&inbyte, 1, 1, binfile);
55 while (1) {
56 fprintf(cfile, "0X%02X", inbyte);
57
58 fread(&inbyte, 1, 1, binfile);
59 if (feof(binfile))
60 break;
61 fprintf(cfile, ",");
62 if (++cntr > 30) {
63 fprintf(cfile, "\n");
64 cntr = 0;
65 }
66 }
67
68 fprintf(cfile, "};\n");
69 fclose(binfile);
70 fclose(cfile);
71 return 0;
72}
diff --git a/src/installer/hd24connect_icon.png b/src/installer/hd24connect_icon.png
new file mode 100644
index 0000000..63bca94
--- /dev/null
+++ b/src/installer/hd24connect_icon.png
Binary files differ
diff --git a/src/installer/icon.icns b/src/installer/icon.icns
new file mode 100644
index 0000000..e1137cd
--- /dev/null
+++ b/src/installer/icon.icns
Binary files differ
diff --git a/src/installer/info.plist.hd24connect b/src/installer/info.plist.hd24connect
new file mode 100644
index 0000000..afc8750
--- /dev/null
+++ b/src/installer/info.plist.hd24connect
@@ -0,0 +1,23 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
3<plist version="0.9">
4<dict>
5 <key>CFBundleIdentifier</key>
6 <string>com.hd24tools.hd24connect</string>
7 <key>CFBundleName</key>
8 <string>hd24connect</string>
9 <key>CFBundlePackageType</key>
10 <string>APPL</string>
11 <key>CFBundleVersion</key>
12 <string>59</string>
13 <key>CFBundleShortVersionString</key>
14 <string>HD24VERSION</string>
15 <key>CFBundleIconFile</key>
16 <string>icon.icns</string>
17 <key>CFBundleSignature</key>
18 <string>none</string>
19 <key>CFBundleExecutable</key>
20 <string>HD24connect</string>
21</dict>
22</plist>
23
diff --git a/src/installer/info.plist.setup b/src/installer/info.plist.setup
new file mode 100644
index 0000000..6f9d4d8
--- /dev/null
+++ b/src/installer/info.plist.setup
@@ -0,0 +1,23 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
3<plist version="0.9">
4<dict>
5 <key>CFBundleIdentifier</key>
6 <string>com.hd24tools.setup</string>
7 <key>CFBundleName</key>
8 <string>setup</string>
9 <key>CFBundlePackageType</key>
10 <string>APPL</string>
11 <key>CFBundleVersion</key>
12 <string>59</string>
13 <key>CFBundleShortVersionString</key>
14 <string>0.6</string>
15 <key>CFBundleIconFile</key>
16 <string>icon.icns</string>
17 <key>CFBundleSignature</key>
18 <string>none</string>
19 <key>CFBundleExecutable</key>
20 <string>HD24tools Setup</string>
21</dict>
22</plist>
23
diff --git a/src/installer/setup.cpp b/src/installer/setup.cpp
new file mode 100755
index 0000000..8083510
--- /dev/null
+++ b/src/installer/setup.cpp
@@ -0,0 +1,353 @@
1// This is a very rudimentary installer framework-
2// it won't do much more than copy a few files to the proper location.
3// Of course there are a few wizard screens which are made in fluid (FLTK),
4// these can be altered as needed.
5// A small portion of the actual install stuff is done in the READY screen
6// (search for it in the code), this could still be moved out to the
7// installer_resources.h file.
8// At this moment, desktop shortcuts are not yet created, for more info
9// read
10// http://delphi.about.com/od/windowsshellapi/a/create_lnk.htm (shell links)
11#include <FL/Fl.H>
12#include <FL/Fl_Window.H>
13#include <FL/Fl_Box.H>
14#include "ui_welcome.h"
15#include "ui_license.h"
16#include "ui_instdir.h"
17#include "ui_ready.h"
18#include "setupapi.cpp"
19#include "installer_resources.h"
20#include <iostream>
21#include <fstream>
22#include <string>
23#ifdef WINDOWS
24#define DEFAULT_INSTDIR "C:\\HD24tools\\"
25#include <windows.h>
26#include <FL/x.H>
27#define IDI_ICON1 101
28#endif
29#ifndef WINDOWS
30#define DEFAULT_INSTDIR "/usr/local/bin/HD24tools/"
31#endif
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <fcntl.h>
35#ifndef WINDOWS
36#include <unistd.h>
37#endif
38
39#define ALLOW_OVERWRITE true
40#define NO_OVERWRITE false
41
42#ifndef S_IXGRP
43#define S_IXGRP 0
44#endif
45#ifndef S_IXOTH
46#define S_IXOTH 0
47#endif
48bool confirm(const char* question)
49{
50 int result=fl_choice(question,"No","Yes",NULL);
51 if (result==1) {
52 return true;
53 }
54return false;
55}
56
57int lastx=0;
58int lasty=0;
59string fullbinname="";
60int installer_writefile(unsigned char* filedata,long long filesize,const char* instdir,const char* filename,bool allow_overwrite)
61{
62 string fname=instdir;
63 fname+=filename;
64 fstream binfile(fname.c_str(),ios::binary|ios::out);
65 binfile.write(reinterpret_cast<char *>(filedata),filesize);
66 binfile.close();
67#ifndef WINDOWS
68 chmod(fname.c_str(),S_IRWXU|S_IXGRP|S_IRGRP|S_IXOTH|S_IROTH);
69#endif
70 return 0;
71}
72void installer_getsysdir(char* sysdir)
73{
74 // on Windows: GetSystemDirectory()
75}
76void installer_getprogdir(char* progdir)
77{
78 // on Windows: getProgramDirectory()
79}
80int main(int argc, char **argv,char *envp[]) {
81 UI_Welcome ui_welcome;
82 UI_License ui_license;
83 UI_Instdir ui_instdir;
84 char* instdir=new char[4096];
85 instdir[0]='\0';
86 bool done=false;
87 char* currscreen;
88 currscreen=new char[9];
89 currscreen="welcome";
90#ifndef WINDOWS
91 // on non-windows systems, default to user home dir
92 // (on non windows or no home found,
93 // defaults to systemwide dir)
94 int count=0;
95 char homedir[255];
96 homedir[0]='\0';
97 while (envp[count] != NULL)
98 {
99 if (strncmp(envp[count],"HOME=",5)==0)
100 {
101 strncpy(&homedir[0],&envp[count][5],250);
102 }
103 ++count;
104 }
105
106 if (strlen(homedir)>0)
107 {
108 strncpy(&instdir[0],&homedir[0],128);
109 int dirlen=strlen(instdir)-1;
110 if ((instdir[dirlen]!='/')
111 &&(instdir[dirlen]!='\\'))
112 {
113#ifdef WINDOWS
114 instdir[dirlen+1]='\\';
115 instdir[dirlen+2]='\0';
116#else
117 instdir[dirlen+1]='/';
118 instdir[dirlen+2]='\0';
119#endif
120 }
121 dirlen=strlen(instdir)-1;
122 strcat(instdir,"HD24tools/");
123 }
124#endif
125 int insterror=0;
126 int result=0;
127 UI_Ready ui_ready;
128 char* sysdir=new char[4096];
129 installer_getsysdir(&sysdir[0]);
130 while (done==false) {
131 if (strncmp(currscreen,"done",4)==0)
132 {
133 done=true;
134 continue;
135 }
136 if (strncmp(currscreen,"welcome",7)==0)
137 {
138 Fl_Window *window = ui_welcome.make_window(&currscreen[0]);
139#ifdef WINDOWS
140 window->icon((char *)LoadIcon(fl_display,MAKEINTRESOURCE(IDI_ICON1)));
141#endif
142 window->position(lastx,lasty);
143 window->end();
144 window->show(); //argc, argv);
145 Fl::run(); lastx=window->x(); lasty=window->y();
146
147 currscreen = ui_welcome.currscreen;
148 if (strncmp(currscreen,"next",4)==0) {
149 currscreen="license\0";
150 continue;
151 }
152 if (strncmp(currscreen,"cancel",4)==0) {
153 currscreen="done\0";
154 continue;
155 }
156 // screen closed otherwise
157 currscreen="done\0";
158 continue;
159 }
160 if (strncmp(currscreen,"license",7)==0)
161 {
162 Fl_Window *window = ui_license.make_window(&currscreen[0]);
163#ifdef WINDOWS
164 window->icon((char *)LoadIcon(fl_display,MAKEINTRESOURCE(IDI_ICON1)));
165#endif
166 window->position(lastx,lasty);
167 window->end();
168 window->show(); //argc, argv);
169 Fl::run(); lastx=window->x(); lasty=window->y();
170 currscreen = ui_license.currscreen;
171 if (strncmp(currscreen,"back",4)==0) {
172 currscreen="welcome\0";
173 continue;
174 }
175 if (strncmp(currscreen,"next",4)==0) {
176 currscreen="instdir\0";
177 continue;
178 }
179 if (strncmp(currscreen,"cancel",4)==0) {
180 currscreen="done\0";
181 continue;
182 }
183 // screen closed otherwise
184 currscreen="done\0";
185 continue;
186 }
187 if (strncmp(currscreen,"instdir",7)==0)
188 {
189 if (instdir[0]=='\0')
190 {
191 strncpy(&instdir[0],DEFAULT_INSTDIR,128);
192 }
193 Fl_Window *window = ui_instdir.make_window(&currscreen[0],&instdir[0]);
194#ifdef WINDOWS
195 window->icon((char *)LoadIcon(fl_display,MAKEINTRESOURCE(IDI_ICON1)));
196#endif
197 window->position(lastx,lasty);
198 window->end();
199 window->show(); //argc, argv);
200 Fl::run(); lastx=window->x(); lasty=window->y();
201 currscreen = ui_instdir.currscreen;
202 instdir = ui_instdir.instdir;
203 int dirlen=strlen(instdir)-1;
204 if ((instdir[dirlen]!='/')
205 &&(instdir[dirlen]!='\\'))
206 {
207#ifdef WINDOWS
208 instdir[dirlen+1]='\\';
209 instdir[dirlen+2]='\0';
210#else
211 instdir[dirlen+1]='/';
212 instdir[dirlen+2]='\0';
213#endif
214 }
215 if (strncmp(currscreen,"cancel",6)==0) {
216 currscreen="done\0";
217 continue;
218 }
219 if (strncmp(currscreen,"back",4)==0) {
220 currscreen="license\0";
221 continue;
222 }
223 if (!setupDirExists(instdir))
224 {
225 bool mustcreate=confirm("Install directory does not exist. Create it?");
226 if (!mustcreate) {
227 currscreen="instdir\0";
228 continue;
229 }
230 setupCreateDir(instdir,0755);
231
232 if (!(setupDirExists(instdir)))
233 {
234 fl_message("Could not create install directory.\nPlease create it manually, then try again.");
235 currscreen="instdir\0";
236 continue;
237 }
238 }
239 if (strncmp(currscreen,"next",4)==0) {
240 currscreen="ready\0";
241 continue;
242 }
243 // screen closed otherwise
244 currscreen="done\0";
245 continue;
246 }
247 if (strncmp(currscreen,"ready",5)==0)
248 {
249 // READY
250 cout << "actually doing the install now" << endl;
251 insterror=0;
252 result=installer_writefile(
253 resource_hd24tools_manual,sizeof(resource_hd24tools_manual),(const char*)instdir,resource_hd24tools_manual_filename,ALLOW_OVERWRITE);
254 if (result!=0) { insterror=1; currscreen="done\0"; continue; }
255 result=installer_writefile(
256 resource_longliverec,sizeof(resource_longliverec),(const char*)instdir,resource_longliverec_filename,ALLOW_OVERWRITE);
257 if (result!=0) { insterror=1; currscreen="done\0"; continue; }
258 result=installer_writefile(
259 resource_unquickformat,sizeof(resource_unquickformat),instdir,resource_unquickformat_filename,ALLOW_OVERWRITE);
260 if (result!=0) { insterror=1; currscreen="done\0"; continue; }
261#ifdef LINUX
262 /* for linux, wrap the binary into a shell script
263 * that prepends the application dir to the library
264 * search path */
265 fullbinname=resource_hd24connect_filename;
266 fullbinname+="_bin";
267 result=installer_writefile(
268 resource_hd24connect,sizeof(resource_hd24connect),(const char*)instdir,fullbinname.c_str(),ALLOW_OVERWRITE);
269 fullbinname=instdir;
270 fullbinname+=resource_hd24connect_filename;
271 fstream wrapper(fullbinname.c_str(),ios::out);
272 wrapper << "#!/bin/sh" << endl;
273 wrapper << "export LD_LIBRARY_PATH=" << instdir <<":$LD_LIBRARY_PATH" << endl;
274 wrapper << "exec " << instdir << "hd24connect_bin $*" << endl;
275 wrapper.close();
276 chmod(fullbinname.c_str(),S_IRWXU|S_IXGRP|S_IRGRP|S_IXOTH|S_IROTH);
277#endif
278#ifdef WINDOWS
279 result=installer_writefile(
280 resource_hd24connect,sizeof(resource_hd24connect),(const char*)instdir,resource_hd24connect_filename,ALLOW_OVERWRITE);
281#endif
282#ifdef DARWIN
283 /* For MacOS, wrap the binary into a .app bundle.
284 * Note: What is called LD_LIBRARY_PATH under Linux
285 * is called DYLD_LIBRARY_PATH on MacOSX
286 */
287 string bundledir=instdir;
288 bundledir+="hd24connect.app/";
289 setupCreateDir(bundledir.c_str(),0755);
290 bundledir+="Contents/";
291 setupCreateDir(bundledir.c_str(),0755);
292 string macosdir;
293 macosdir=bundledir+"MacOS/";
294 setupCreateDir(macosdir.c_str(),0755);
295 string resourcedir=bundledir+"Resources/";
296 setupCreateDir(resourcedir.c_str(),0755);
297 string strplist="Info.plist";
298 string strpkginfo="PkgInfo";
299
300 result=installer_writefile(resource_plist_connect,sizeof(resource_plist_connect),bundledir.c_str(),"info.plist",ALLOW_OVERWRITE);
301 result=installer_writefile(resource_pkginfo_connect,sizeof(resource_pkginfo_connect),bundledir.c_str(),strpkginfo.c_str(),ALLOW_OVERWRITE);
302 result=installer_writefile(resource_hd24connect,sizeof(resource_hd24connect),macosdir.c_str(),resource_hd24connect_filename,ALLOW_OVERWRITE);
303
304
305#endif
306 if (result!=0) { insterror=1; currscreen="done\0"; continue; }
307 result=installer_writefile(
308 resource_hd24hexview,sizeof(resource_hd24hexview),(const char*)instdir,resource_hd24hexview_filename,ALLOW_OVERWRITE);
309 if (result!=0) { insterror=1; currscreen="done\0"; continue; }
310 result=installer_writefile(
311 resource_libsndfile_1,sizeof(resource_libsndfile_1),(const char*)instdir,resource_libsndfile_1_filename,ALLOW_OVERWRITE);
312 if (result!=0) { insterror=1; currscreen="done\0"; continue; }
313// result=installer_writefile(
314// resource_portaudio,sizeof(resource_portaudio),(const char*)instdir,resource_portaudio_filename,NO_OVERWRITE);
315// if (result!=0) { insterror=1; currscreen="done\0"; continue; }
316
317 Fl_Window *window = ui_ready.make_window(&currscreen[0]);
318#ifdef WINDOWS
319 window->icon((char *)LoadIcon(fl_display,MAKEINTRESOURCE(IDI_ICON1)));
320#endif
321 window->position(lastx,lasty);
322 window->end();
323 window->show(); //argc, argv);
324 Fl::run(); lastx=window->x(); lasty=window->y();
325
326 currscreen = ui_ready.currscreen;
327 if (strncmp(currscreen,"back",4)==0) {
328 currscreen="license\0";
329 continue;
330 }
331 if (strncmp(currscreen,"next",4)==0) {
332 currscreen="doinst\0";
333 continue;
334 }
335 if (strncmp(currscreen,"cancel",4)==0) {
336 currscreen="done\0";
337 continue;
338 }
339 // screen closed otherwise
340 cout << "???" << currscreen << endl;
341 currscreen="done\0";
342 continue;
343 }
344 if (strncmp(currscreen,"doinst",6)==0)
345 {
346 currscreen="done\0";
347 continue;
348 }
349 cout << "Unknown screen '" << currscreen << "'." << endl;
350 done=true;
351 }
352 return 0;
353}
diff --git a/src/installer/setupapi.cpp b/src/installer/setupapi.cpp
new file mode 100644
index 0000000..b90fd04
--- /dev/null
+++ b/src/installer/setupapi.cpp
@@ -0,0 +1,473 @@
1/** BEGIN COPYRIGHT BLOCK
2 * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
3 * Copyright (C) 2005 Red Hat, Inc.
4 * All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation version
9 * 2.1 of the License.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * END COPYRIGHT BLOCK **/
20#ifdef WINDOWS
21#define XP_WIN32
22#endif
23#ifndef MAX_PATH
24#define MAX_PATH 127
25#endif
26#ifndef TRUE
27#define TRUE (1==1)
28#endif
29#ifndef FALSE
30#define FALSE (1==0)
31#endif
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <errno.h>
35#include <stdio.h>
36#include <stdarg.h>
37#include <time.h>
38#include <string.h>
39#include <ctype.h>
40
41#ifdef XP_WIN32
42 #include <windows.h>
43 #include <regstr.h>
44 #include <direct.h>
45 #include <io.h> /* For _findfirst */
46#else
47
48
49 #include <sys/types.h>
50 #include <sys/statvfs.h>
51 #include <sys/socket.h> /* socket, bind */
52 #include <netinet/in.h> /* htonl */
53 #include <netdb.h> /* gethostbyname */
54 #include <arpa/inet.h> /* inet_ntoa */
55 #include <dirent.h>
56 #include <assert.h>
57
58#endif
59
60
61#define MINPORT 1024
62#define MAXPORT 65535
63
64
65
66 /*********************************************************************
67 **
68 ** FUNCTION: setupIsDirEmpty
69 ** Replaced: IsDirEmpty
70 **
71 ** DESCRIPTION: checks to see if directory empty
72 **
73 **
74 ** INPUTS:
75 **
76 ** RETURN:
77 ** TRUE or FALSE
78 **
79 ** SIDE EFFECTS:
80 ** none
81 ** RESTRICTIONS:
82 ** None
83 ** MEMORY:
84 **********************************************************************/
85
86int setupIsDirEmpty(const char * pszPath)
87 {
88#ifdef XP_WIN32
89 int iReturn = TRUE;
90 char szFileSpec[MAX_PATH];
91 WIN32_FIND_DATA fd;
92 HANDLE ff;
93
94 if (!(pszPath))
95 {
96 //setupLog(NULL, "setupIsDirEmpty failed: passed in NULL parameter for directory Name");
97 return FALSE;
98 }
99 snprintf(szFileSpec, sizeof(szFileSpec), "%s\\*", pszPath);
100 if (!memchr(szFileSpec, 0, sizeof(szFileSpec))) return FALSE; /*overflow*/
101
102 ff = FindFirstFile(szFileSpec, &fd);
103 if (ff != INVALID_HANDLE_VALUE)
104 {
105 do
106 {
107 if (strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, ".."))
108 {
109 iReturn = FALSE;
110 break;
111 }
112 } while (FindNextFile(ff, &fd));
113 FindClose(ff);
114 }
115
116 return (iReturn);
117#else
118 DIR *dirp;
119 struct dirent *dp;
120 bool rc = TRUE;
121
122 dirp = opendir(pszPath);
123 while ((dp = readdir(dirp)) != NULL)
124 {
125 if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, ".."))
126 {
127 rc = FALSE;
128 break;
129 }
130 }
131 closedir(dirp);
132 return rc;
133#endif
134
135 }
136
137 /*********************************************************************
138 **
139 ** FUNCTION: setupFileExist
140 ** Replaced: FileExist
141 **
142 ** DESCRIPTION: returns 1 if file exists.
143 **
144 ** INPUTS:
145 **
146 ** RETURN:
147 ** TRUE or FALSE
148 **
149 ** SIDE EFFECTS:
150 ** none
151 ** RESTRICTIONS:
152 ** None
153 ** MEMORY:
154 **********************************************************************/
155int setupFileExists(const char * pszFileName)
156 {
157 struct stat fi;
158
159 if ((stat (pszFileName, &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0))
160 {
161 return TRUE;
162 }
163 else
164 {
165 return FALSE;
166 }
167 }
168
169
170 /*********************************************************************
171 **
172 ** FUNCTION: setupDirExists
173 ** Replaced: DirExists
174 **
175 ** DESCRIPTION: checks to see if directory exists
176 **
177 **
178 ** INPUTS:
179 **
180 ** RETURN:
181 ** TRUE or FALSE
182 **
183 ** SIDE EFFECTS:
184 ** none
185 ** RESTRICTIONS:
186 ** None
187 ** MEMORY:
188 **********************************************************************/
189int setupDirExists(const char * pszDirName)
190 {
191#ifdef XP_WIN32
192 unsigned int dwAttrs;
193 if (!(pszDirName))
194 {
195 //setupLog(NULL, "DirExists failed: passed in NULL parameter for directory");
196 return FALSE;
197 }
198 dwAttrs = GetFileAttributes(pszDirName);
199 if ((dwAttrs != 0xFFFFFFFF) && (dwAttrs & FILE_ATTRIBUTE_DIRECTORY))
200 {
201 return TRUE;
202 }
203 return FALSE;
204#else
205 struct stat fi;
206
207 if (stat (pszDirName, &fi) == -1 || !S_ISDIR(fi.st_mode))
208 {
209 return FALSE;
210 }
211 else
212 {
213 return TRUE;
214 }
215#endif
216 }
217
218 /*********************************************************************
219 **
220 ** FUNCTION: setupCreateDir
221 ** Replaced: CreateDir
222 **
223 ** DESCRIPTION: creates a directory
224 **
225 **
226 ** INPUTS:
227 **
228 ** RETURN:
229 ** NT: TRUE or FALSE
230 ** UNIX:
231 ** 0 : OK
232 ** -1 : Can't create directory
233 ** -2 : input exists and is not a directory
234 ** -3 : Can't write to directory
235 **
236 ** SIDE EFFECTS:
237 ** none
238 ** RESTRICTIONS:
239 ** None
240 ** MEMORY:
241 **
242 **********************************************************************/
243bool setupCreateDir(const char * pszDirName, int mode)
244 {
245#ifdef XP_WIN32
246 char *pszDelim;
247 char szDirName[MAX_PATH];
248 char szTmpDir[MAX_PATH] = "";
249 int cbLen;
250
251 if (!(pszDirName))
252 {
253 //setupLog(NULL, "CreateDir failed: passed in NULL parameter for directory");
254 return FALSE;
255 }
256
257 if (strlen(pszDirName) >= sizeof(szDirName))
258 {
259 //setupLog(NULL, "CreateDir failed: passed in too long directory");
260 return FALSE;
261 }
262
263 snprintf(szDirName, sizeof(szDirName), "%s", pszDirName);
264 if (!memchr(szDirName, 0, sizeof(szDirName))) return FALSE; /*overflow*/
265 pszDelim = szDirName;
266 while ((pszDelim = strchr(pszDelim, '/')) != NULL)
267 {
268 *pszDelim = '\\';
269 }
270
271 pszDelim = szDirName;
272 while ((pszDelim = strchr(pszDelim, '\\')) != NULL)
273 {
274 cbLen = (pszDelim - szDirName);
275 strncpy(szTmpDir, szDirName, cbLen);
276 szTmpDir[cbLen] = '\0';
277 CreateDirectory(szTmpDir, NULL);
278 pszDelim++;
279 }
280
281 if (!CreateDirectory(szDirName, NULL))
282 {
283// char szLog[MAX_PATH+50];
284 return FALSE;
285// snprintf(szLog, sizeof(szLog),
286// "setupCreateDir failed to create '%s'", pszDirName);
287// if (!memchr(szLog, 0, sizeof(szLog))) return FALSE; /*overflow*/
288 //setupLog(NULL, szLog);
289 }
290 return TRUE;
291#else
292 struct stat fi;
293 char *s;
294 char *t;
295
296 s = strdup(pszDirName);
297 t = s + 1;
298
299 while (1)
300 {
301 t = strchr(t, '/');
302
303 if (t)
304 *t = '\0';
305 if (stat(s, &fi) == -1)
306 {
307 if (mkdir(s, mode) == -1)
308 {
309 return FALSE;
310 }
311 }
312 else if (!S_ISDIR(fi.st_mode))
313 {
314 return FALSE;
315 }
316 if (t)
317 *t++ = '/';
318 else
319 break;
320 }
321
322 if (access(pszDirName, W_OK) == -1)
323 {
324 return FALSE;
325 }
326 return TRUE;
327#endif
328 }
329 /*********************************************************************
330 **
331 ** FUNCTION: setupConvertsPathSlashes
332 ** Replaced: ConvertsPathSlashes
333 **
334 ** DESCRIPTION: converts slashes TRUE UNIX to NT, FALSE NT to UNIX,
335 **
336 ** INPUTS:
337 **
338 ** RETURN:
339 ** TRUE or FALSE
340 **
341 ** SIDE EFFECTS:
342 ** none
343 ** RESTRICTIONS:
344 ** None
345 ** MEMORY:
346 **********************************************************************/
347int setupConvertPathSlashes(const char * lpszPath, char * lpszNewPath, int bType )
348 {
349 if (lpszPath == NULL)
350 return FALSE;
351
352 /* create reverse slashes and escape them */
353 while (*lpszPath)
354 {
355 if ((*lpszPath == '\\') || (*lpszPath == '/'))
356 {
357 if (bType)
358 *lpszNewPath = '\\';
359 else
360 *lpszNewPath = '/';
361 }
362 else
363 *lpszNewPath = *lpszPath;
364 lpszPath++;
365 lpszNewPath++;
366 }
367 return TRUE;
368 }
369
370
371unsigned int setupExecProgram(const char *program, const char *where)
372{
373 char curdir[MAX_PATH];
374 unsigned int ret;
375#ifdef XP_WIN32
376 char szWhere[MAX_PATH];
377 char szProgram[MAX_PATH];
378 STARTUPINFO si;
379 PROCESS_INFORMATION pi;
380 DWORD dwCreationFlags;
381#endif
382
383 if (!program)
384 {
385 //setupLogMessage("info", "setup", "setupExecProgram called with no program");
386 return 0;
387 }
388 if (!setupFileExists(program))
389 {
390 //setupLogMessage("info", "setup", "setupExecProgram called with invalid program %s", program);
391 }
392 getcwd(curdir, sizeof(curdir));
393
394 if (where)
395 {
396 chdir(where);
397 }
398#ifndef XP_WIN32
399 ret = system(program);
400#else
401 snprintf(szProgram, sizeof(szProgram), "%s", program);
402 if (!memchr(szProgram, 0, sizeof(szProgram))) {
403 //setupLogMessage("info", "setup", "Too long program %s", program);
404 return 0;
405 }
406 snprintf(szWhere, sizeof(szWhere), "%s", where);
407 if (!memchr(szWhere, 0, sizeof(szWhere))) {
408 //setupLogMessage("info", "setup", "Too long arg %s", where);
409 return 0;
410 }
411 memset(&si,0,sizeof(si));
412 si.cb = sizeof(si);
413 GetStartupInfo(&si);
414 si.wShowWindow = SW_SHOWDEFAULT;
415 dwCreationFlags = NORMAL_PRIORITY_CLASS | DETACHED_PROCESS;
416 ret = CreateProcess(NULL, szProgram, NULL, NULL, FALSE, dwCreationFlags, NULL, szWhere, &si, &pi);
417#endif
418
419 if (where)
420 {
421 chdir(curdir);
422 }
423
424 return ret;
425}
426
427
428/*********************************************************************
429**
430** FUNCTION: setupGetDiskFreeSpace
431** DESCRIPTION: get available disk space in Kilobyte
432**
433** INPUTS: Path name
434** OUTPUTS:
435** RETURN: available disk space in kilobyte
436** SIDE EFFECTS:
437** None
438** RESTRICTIONS:
439** None
440** MEMORY:
441**********************************************************************
442*/
443
444unsigned long setupGetDiskFreeSpace(const char *path)
445{
446#ifdef XP_WIN32
447 DWORD dwSectorsPerCluster;
448 DWORD dwBytesPerSector;
449 DWORD dwFreeClusters;
450 DWORD dwTotalClusters;
451
452 if (GetDiskFreeSpace(path, &dwSectorsPerCluster, &dwBytesPerSector, &dwFreeClusters, &dwTotalClusters))
453 {
454 long long clusterSize;
455
456 clusterSize = dwSectorsPerCluster * dwBytesPerSector;
457
458 return (unsigned long)((clusterSize / 1024.0) * dwFreeClusters);
459 }
460
461 return 0;
462#else
463 struct statvfs buf;
464
465 statvfs(path, &buf);
466
467 if (buf.f_frsize == 0)
468 return (unsigned long)(((unsigned long long)buf.f_bavail / 1024.0) * buf.f_bsize);
469 else
470 return (unsigned long)(((unsigned long long)buf.f_bavail / 1024.0) * buf.f_frsize);
471#endif
472}
473
diff --git a/src/installer/starthd24connect.command b/src/installer/starthd24connect.command
new file mode 100755
index 0000000..574d4c4
--- /dev/null
+++ b/src/installer/starthd24connect.command
@@ -0,0 +1,5 @@
1#!/bin/sh
2# to start hd24connect on Mac
3export HD24PATH=`echo $0|sed -e 's/starthd24connect\.command//'|sed -e 's/\/$//'`
4export DYLD_LIBRARY_PATH=$HD24PATH/hd24connect.app/Contents/MacOS/:$DYLD_LIBRARY_PATH
5open $HD24PATH/hd24connect.app $*
diff --git a/src/installer/ui_askpasswd.fl b/src/installer/ui_askpasswd.fl
new file mode 100644
index 0000000..f27357c
--- /dev/null
+++ b/src/installer/ui_askpasswd.fl
@@ -0,0 +1,78 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0107
3header_name {.h}
4code_name {.cxx}
5decl {using namespace std;} {public
6}
7
8decl {\#include <string>} {public
9}
10
11class UI_Askpasswd {open
12} {
13 decl {char* currscreen;} {public
14 }
15 decl {char* instdir;} {public
16 }
17 Function {make_window(char* p_currscreen,char* p_instdir)} {open
18 } {
19 Fl_Window {} {
20 label {HD24tools HD24VERSION - Setup Wizard} open selected
21 xywh {1246 284 590 350} type Double color 7
22 code0 {currscreen=p_currscreen;}
23 code1 {instdir=p_instdir;} visible
24 } {
25 Fl_Box {} {
26 image {welcome.png} xywh {0 -137 165 487}
27 }
28 Fl_Button {} {
29 label {&Browse...}
30 xywh {505 191 80 20} color 53 labelsize 12
31 }
32 Fl_Box {} {
33 label {Please enter your password}
34 xywh {175 -3 320 33} labelfont 1 labelsize 16 align 20
35 }
36 Fl_Group {} {open
37 xywh {-5 315 620 35} box BORDER_BOX color 53 selection_color 47
38 } {
39 Fl_Button button_next {
40 label {&Next >}
41 callback {currscreen="next\\0";
42Fl_Window* winx=Fl::first_window();
43winx->~Fl_Window();}
44 xywh {415 320 85 25} color 53 labelsize 12
45 }
46 Fl_Button {} {
47 label Cancel
48 callback {currscreen="cancel\\0";
49Fl_Window* winx=Fl::first_window();
50winx->~Fl_Window();}
51 xywh {505 320 85 25} color 53 labelsize 12
52 }
53 Fl_Button {} {
54 label {< &Back}
55 callback {currscreen="back\\0";
56Fl_Window* winx=Fl::first_window();
57winx->~Fl_Window();}
58 xywh {330 320 85 25} color 53 labelsize 12
59 }
60 }
61 Fl_Output password {
62 xywh {175 191 325 20} labelsize 12 align 5 textsize 11
63 }
64 Fl_Box {} {
65 label {The setup wizard needs administrator privileges to allow
66writing to the folder where some HD24tools components
67need to be installed.
68
69Please enter your password to allow the setup wizard
70to access this folder.
71
72Alternatively, if you are an experienced user, you can
73temporarily enable write access to the library directory.}
74 xywh {175 38 405 149} labelsize 12 align 21
75 }
76 }
77 }
78}
diff --git a/src/installer/ui_instdir.fl b/src/installer/ui_instdir.fl
new file mode 100644
index 0000000..2f62e78
--- /dev/null
+++ b/src/installer/ui_instdir.fl
@@ -0,0 +1,105 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0107
3header_name {.h}
4code_name {.cxx}
5decl {using namespace std;} {public
6}
7
8decl {\#include <string>} {public
9}
10
11decl {\#include <iostream>} {public
12}
13
14decl {\#include <FL/Fl_File_Chooser.H>} {public
15}
16
17decl {\#include <FL/Fl_Native_File_Chooser.H>} {public
18}
19
20class UI_Instdir {open
21} {
22 decl {char* currscreen;} {public
23 }
24 decl {char* instdir;} {public
25 }
26 Function {make_window(char* p_currscreen,char* p_instdir)} {open
27 } {
28 Fl_Window {} {
29 label {HD24tools HD24VERSION - Setup Wizard} open selected
30 xywh {1246 284 590 350} type Double color 7
31 code0 {currscreen=p_currscreen;}
32 code1 {instdir=p_instdir;} visible
33 } {
34 Fl_Box {} {
35 image {welcome.png} xywh {0 -137 165 487}
36 }
37 Fl_Button {} {
38 label {&Browse...}
39 callback {Fl_Native_File_Chooser chooser;
40chooser.title("Select installation directory");
41chooser.type(Fl_Native_File_Chooser::BROWSE_DIRECTORY||Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY||Fl_Native_File_Chooser::NEW_FOLDER);
42chooser.filter("");
43
44string cdir="";
45cdir+=currdir->value();
46
47chooser.directory(cdir.c_str());
48switch (chooser.show()) {
49 case -1: break; //error
50 case 1: break; //cancel
51 default:
52 if (chooser.filename()) {
53 currdir->value(chooser.filename());
54 }
55
56 break;
57}}
58 xywh {505 125 80 20} color 53 labelsize 12
59 }
60 Fl_Box {} {
61 label {Choose installation directory}
62 xywh {175 -3 320 33} labelfont 1 labelsize 16 align 20
63 }
64 Fl_Group {} {open
65 xywh {-5 315 620 35} box BORDER_BOX color 53 selection_color 47
66 } {
67 Fl_Button button_next {
68 label {&Next >}
69 callback {currscreen="next\\0";
70string newdir=currdir->value();
71strncpy(&instdir[0],newdir.c_str(),128);
72Fl_Window* winx=Fl::first_window();
73winx->~Fl_Window();}
74 xywh {415 320 85 25} color 53 labelsize 12
75 }
76 Fl_Button {} {
77 label Cancel
78 callback {currscreen="cancel\\0";
79Fl_Window* winx=Fl::first_window();
80winx->~Fl_Window();}
81 xywh {505 320 85 25} color 53 labelsize 12
82 }
83 Fl_Button {} {
84 label {< &Back}
85 callback {currscreen="back\\0";
86Fl_Window* winx=Fl::first_window();
87winx->~Fl_Window();}
88 xywh {330 320 85 25} color 53 labelsize 12
89 }
90 }
91 Fl_Input currdir {
92 xywh {175 125 325 20} labelsize 12 align 5 textsize 11
93 code0 {currdir->value(p_instdir);}
94 }
95 Fl_Box {} {
96 label {Setup will install HD24tools in the following folder. To
97install in a different folder, click Browse and select
98another folder.
99
100After that, click Next to start the installation.}
101 xywh {175 38 370 81} labelsize 12 align 21
102 }
103 }
104 }
105}
diff --git a/src/installer/ui_license.fl b/src/installer/ui_license.fl
new file mode 100644
index 0000000..b26bd95
--- /dev/null
+++ b/src/installer/ui_license.fl
@@ -0,0 +1,80 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0107
3header_name {.h}
4code_name {.cxx}
5decl {using namespace std;} {public
6}
7
8decl {\#include <string>} {public
9}
10
11class UI_License {open
12} {
13 decl {char* currscreen;} {public
14 }
15 Function {make_window(char* p_currscreen)} {open
16 } {
17 Fl_Window {} {
18 label {HD24tools HD24VERSION - Setup Wizard} open selected
19 xywh {1302 140 590 350} type Double color 7
20 code0 {currscreen=p_currscreen;} visible
21 } {
22 Fl_Box {} {
23 image {welcome.png} xywh {0 -137 165 487}
24 }
25 Fl_Box {} {
26 label {License Agreement}
27 xywh {175 -3 435 33} labelfont 1 labelsize 16 align 20
28 }
29 Fl_Group agreedisagree {open
30 xywh {170 265 395 45}
31 } {
32 Fl_Round_Button agree {
33 label {I accept the terms in the license agreement}
34 callback {agree->value(1);
35disagree->value(0);
36button_next->activate();}
37 xywh {175 275 385 15} down_box ROUND_DOWN_BOX labelsize 12
38 }
39 Fl_Round_Button disagree {
40 label {I do not accept the terms in the license agreement}
41 callback {agree->value(0);
42disagree->value(1);
43button_next->deactivate();}
44 xywh {175 290 385 20} down_box ROUND_DOWN_BOX value 1 labelsize 12
45 }
46 }
47 Fl_Group {} {open
48 xywh {-5 315 620 35} box BORDER_BOX color 53 selection_color 47
49 } {
50 Fl_Button button_next {
51 label {&Next >}
52 callback {currscreen="next\\0";
53Fl_Window* winx=Fl::first_window();
54winx->~Fl_Window();}
55 xywh {415 320 85 25} color 53 labelsize 12
56 code0 {o->deactivate();}
57 }
58 Fl_Button {} {
59 label Cancel
60 callback {currscreen="cancel\\0";
61Fl_Window* winx=Fl::first_window();
62winx->~Fl_Window();}
63 xywh {505 320 85 25} color 53 labelsize 12
64 }
65 Fl_Button {} {
66 label {< &Back}
67 callback {currscreen="back\\0";
68Fl_Window* winx=Fl::first_window();
69winx->~Fl_Window();}
70 xywh {330 320 85 25} color 53 labelsize 12
71 }
72 }
73 Fl_Output {} {
74 label {Please read the following license agreement carefully.}
75 xywh {175 45 405 220} type Multiline labelsize 12 align 5 textsize 11
76 code0 {o->value("HD24tools End User License Agreement\\n\\nThis program is SHAREWARE. You are hereby granted\\npermission to download and use this software free of\\ncharge, as well as to give away UNALTERED copies of it.\\n\\nThis program is provided in the hope that it\\nwill be useful, but comes with ABSOLUTELY NO WARRANTY.\\n\\nIf you find this program useful, please make a donation\\nto the author. For details, see\\nhttp://ringbreak.dnd.utwente.nl/~mrjb/hd24tools/\\n\\nThis software is not endorsed not affiliated by Alesis.");}
77 }
78 }
79 }
80}
diff --git a/src/installer/ui_ready.fl b/src/installer/ui_ready.fl
new file mode 100644
index 0000000..df550ed
--- /dev/null
+++ b/src/installer/ui_ready.fl
@@ -0,0 +1,49 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0107
3header_name {.h}
4code_name {.cxx}
5decl {using namespace std;} {public
6}
7
8decl {\#include <string>} {public
9}
10
11class UI_Ready {open
12} {
13 decl {char* currscreen;} {public
14 }
15 Function {make_window(char* p_currscreen)} {open
16 } {
17 Fl_Window {} {
18 label {HD24tools HD24VERSION - Setup Wizard} open
19 xywh {1302 140 590 350} type Double color 7
20 code0 {currscreen=p_currscreen;} visible
21 } {
22 Fl_Box {} {
23 image {welcome.png} xywh {0 -137 165 487}
24 }
25 Fl_Box {} {
26 label {Installation Complete}
27 xywh {175 -3 435 33} labelfont 1 labelsize 16 align 20
28 }
29 Fl_Group {} {open
30 xywh {-5 315 620 35} box BORDER_BOX color 53 selection_color 47
31 } {
32 Fl_Button {} {
33 label Close
34 callback {currscreen="cancel\\0";
35Fl_Window* winx=Fl::first_window();
36winx->~Fl_Window();}
37 xywh {505 320 85 25} color 53 labelsize 12
38 }
39 }
40 Fl_Box {} {
41 label {HD24tools installation has been completed successfully.
42You may now run it from the installation path.
43
44Please click Close to terminate the installer.} selected
45 xywh {180 58 385 169} labelsize 12 align 21
46 }
47 }
48 }
49}
diff --git a/src/installer/ui_welcome.fl b/src/installer/ui_welcome.fl
new file mode 100644
index 0000000..f7dcb0c
--- /dev/null
+++ b/src/installer/ui_welcome.fl
@@ -0,0 +1,66 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0107
3header_name {.h}
4code_name {.cxx}
5decl {using namespace std;} {public
6}
7
8decl {\#include <string>} {public
9}
10
11class UI_Welcome {open
12} {
13 decl {char* currscreen;} {public
14 }
15 Function {make_window(char* p_currscreen)} {open
16 } {
17 Fl_Window {} {
18 label {HD24tools HD24VERSION - Setup Wizard} open
19 xywh {308 186 590 350} type Double color 7
20 code0 {currscreen=p_currscreen;} visible
21 } {
22 Fl_Box {} {
23 image {welcome.png} xywh {0 -137 165 487}
24 }
25 Fl_Box {} {
26 label {Welcome to the setup wizard for}
27 xywh {165 -3 440 33} labelfont 1 labelsize 16
28 }
29 Fl_Box {} {
30 label {HD24tools version HD24VERSION}
31 xywh {165 22 440 31} labelfont 1 labelsize 16
32 }
33 Fl_Group {} {open
34 xywh {-5 315 620 35} box BORDER_BOX color 53 selection_color 47
35 } {
36 Fl_Button {} {
37 label {&Next >}
38 callback {currscreen="next\\0";
39Fl_Window* winx=Fl::first_window();
40winx->~Fl_Window();}
41 xywh {415 320 85 25} color 53 labelsize 12
42 }
43 Fl_Button {} {
44 label Cancel
45 callback {currscreen="cancel\\0";
46Fl_Window* winx=Fl::first_window();
47winx->~Fl_Window();}
48 xywh {505 320 85 25} color 53 labelsize 12
49 }
50 }
51 Fl_Box {} {
52 label {This Setup Wizard will install HD24tools version HD24VERSION
53on your computer.
54
55Attention: You may need to run this wizard as administrator/
56superuser/root.
57
58Before continuing, please close all running programs.
59
60
61WARNING: This program is protected by copyright law.} selected
62 xywh {185 77 390 173} labelsize 12 align 21
63 }
64 }
65 }
66}
diff --git a/src/installer/welcome.png b/src/installer/welcome.png
new file mode 100644
index 0000000..88b9a73
--- /dev/null
+++ b/src/installer/welcome.png
Binary files differ
diff --git a/src/lib/FL/FLTKstuff.H b/src/lib/FL/FLTKstuff.H
new file mode 100644
index 0000000..0c1f8d1
--- /dev/null
+++ b/src/lib/FL/FLTKstuff.H
@@ -0,0 +1,6 @@
1#include <FL/Fl_Image_Button.H>
2#include <FL/Fl_Multiline_Output.H>
3#include <FL/Fl_Image_Repeat_Button.H>
4#include <FL/Fl_Image_Toggle_Button.H>
5#include <FL/Fl_Native_File_Chooser.H>
6#include <FL/Fl_Roller.H>
diff --git a/src/lib/FL/Fl_Image_Button.H b/src/lib/FL/Fl_Image_Button.H
new file mode 100644
index 0000000..656e169
--- /dev/null
+++ b/src/lib/FL/Fl_Image_Button.H
@@ -0,0 +1,20 @@
1#ifndef __FL_IMAGE_BUTTON_H
2#define __FL_IMAGE_BUTTON_H
3#include <FL/Fl_Button.H>
4#include <FL/Fl.H>
5
6class Fl_Image_Button: public Fl_Button {
7private:
8 Fl_Image* upimage;
9 Fl_Image* downimage;
10public:
11 Fl_Image* up_image();
12 Fl_Image* down_image();
13 void up_image(Fl_Image* p_up_image);
14 void down_image(Fl_Image* p_down_image);
15 void draw();
16 Fl_Image_Button(int a,int b,int c,int d,const char* e);
17 Fl_Image_Button(int a,int b,int c,int d);
18};
19
20#endif
diff --git a/src/lib/FL/Fl_Image_Button.cxx b/src/lib/FL/Fl_Image_Button.cxx
new file mode 100644
index 0000000..f169396
--- /dev/null
+++ b/src/lib/FL/Fl_Image_Button.cxx
@@ -0,0 +1,110 @@
1#include <FL/Fl_Image_Button.H>
2#include <FL/Fl_Image.H>
3#include <FL/fl_draw.H>
4#ifndef NULL
5#define NULL 0
6#endif
7void Fl_Image_Button::up_image(Fl_Image* p_upimage)
8{
9 upimage=p_upimage;
10}
11
12void Fl_Image_Button::down_image(Fl_Image* p_downimage)
13{
14 downimage=p_downimage;
15}
16
17Fl_Image* Fl_Image_Button::up_image()
18{
19 return upimage;
20}
21
22Fl_Image* Fl_Image_Button::down_image()
23{
24 return downimage;
25}
26
27Fl_Image_Button::Fl_Image_Button(int a,int b,int c,int d,const char* e):Fl_Button(a,b,c,d,e)
28{
29 upimage=NULL;
30 downimage=NULL;
31 Fl_Button::clear_visible_focus();
32}
33Fl_Image_Button::Fl_Image_Button(int a,int b,int c,int d):Fl_Button(a,b,c,d)
34{
35 upimage=NULL;
36 downimage=NULL;
37 Fl_Button::clear_visible_focus();
38}
39
40/*void Fl_Image_Button::draw() {
41 if (value()==0)
42 {
43 if (upimage!=NULL) {
44 this->image(upimage);
45 }
46 } else {
47 if (this->value()==1)
48 {
49 if (downimage!=NULL) {
50 this->image(downimage);
51 }
52 }
53 }
54 Fl_Button::draw();
55}
56
57*/
58
59
60void Fl_Image_Button::draw()
61{
62 // begin - Fl_Button::draw() (box section)
63 if (type() == FL_HIDDEN_BUTTON) return;
64 Fl_Color col = value() ? selection_color() : color();
65
66
67 draw_box(value() ? (down_box()?down_box():fl_down(box())) : box(), col);
68 // end - Fl_Button::draw() (box section)
69
70 // begin - modification to render up/down image
71 Fl_Boxtype box_;
72 Fl_Image* pic_;
73
74 if(value())
75 {
76 box_ = (down_box())? down_box() : fl_down(box());
77 pic_ = downimage;
78 }
79 else
80 {
81 box_ = box();
82 pic_ = upimage;
83 }
84
85 if(pic_)
86 {
87 int xx = x() + Fl::box_dx(box_);
88 int yy = y() + Fl::box_dy(box_);
89 int ww = w() - Fl::box_dw(box_);
90 int hh = h() - Fl::box_dh(box_);
91 int xpos = (ww - pic_->w()) / 2;
92 int ypos = (hh - pic_->h()) / 2;
93
94 fl_push_clip(xx, yy, ww, hh);
95 pic_->draw(xx + xpos, yy + ypos);
96 fl_pop_clip();
97 }
98 // end- modification to render up/down image
99
100 // begin - Fl_Button::draw() (label section)
101 if (labeltype() == FL_NORMAL_LABEL && value()) {
102 Fl_Color c = labelcolor();
103 labelcolor(fl_contrast(c, col));
104 draw_label();
105 labelcolor(c);
106 } else draw_label();
107 if (Fl::focus() == this) draw_focus();
108 // end - Fl_Button::draw() (label section)
109}
110
diff --git a/src/lib/FL/Fl_Image_Repeat_Button.H b/src/lib/FL/Fl_Image_Repeat_Button.H
new file mode 100644
index 0000000..442082a
--- /dev/null
+++ b/src/lib/FL/Fl_Image_Repeat_Button.H
@@ -0,0 +1,20 @@
1#ifndef __FL_IMAGE_Repeat_Button_H
2#define __FL_IMAGE_Repeat_Button_H
3#include <FL/Fl_Repeat_Button.H>
4#include <FL/Fl.H>
5
6class Fl_Image_Repeat_Button: public Fl_Repeat_Button {
7private:
8 Fl_Image* upimage;
9 Fl_Image* downimage;
10public:
11 Fl_Image* up_image();
12 Fl_Image* down_image();
13 void up_image(Fl_Image* p_up_image);
14 void down_image(Fl_Image* p_down_image);
15 void draw();
16 Fl_Image_Repeat_Button(int a,int b,int c,int d,const char* e);
17 Fl_Image_Repeat_Button(int a,int b,int c,int d);
18};
19
20#endif
diff --git a/src/lib/FL/Fl_Image_Repeat_Button.cxx b/src/lib/FL/Fl_Image_Repeat_Button.cxx
new file mode 100644
index 0000000..71530de
--- /dev/null
+++ b/src/lib/FL/Fl_Image_Repeat_Button.cxx
@@ -0,0 +1,86 @@
1#include <FL/Fl_Image_Repeat_Button.H>
2#include <FL/Fl_Image.H>
3#include <FL/fl_draw.H>
4
5#ifndef NULL
6#define NULL 0
7#endif
8void Fl_Image_Repeat_Button::up_image(Fl_Image* p_upimage)
9{
10 upimage=p_upimage;
11}
12
13void Fl_Image_Repeat_Button::down_image(Fl_Image* p_downimage)
14{
15 downimage=p_downimage;
16}
17
18Fl_Image* Fl_Image_Repeat_Button::up_image()
19{
20 return upimage;
21}
22
23Fl_Image* Fl_Image_Repeat_Button::down_image()
24{
25 return downimage;
26}
27
28Fl_Image_Repeat_Button::Fl_Image_Repeat_Button(int a,int b,int c,int d):Fl_Repeat_Button(a,b,c,d)
29{
30 upimage=NULL;
31 downimage=NULL;
32 Fl_Repeat_Button::clear_visible_focus();
33}
34
35
36void Fl_Image_Repeat_Button::draw()
37{
38 // begin - Fl_Button::draw() (box section)
39 if (type() == FL_HIDDEN_BUTTON) return;
40 Fl_Color col = value() ? selection_color() : color();
41
42
43 draw_box(value() ? (down_box()?down_box():fl_down(box())) : box(), col);
44 // end - Fl_Button::draw() (box section)
45
46 // begin - modification to render up/down image
47 Fl_Boxtype box_;
48 Fl_Image* pic_;
49
50 if(value())
51 {
52 box_ = (down_box())? down_box() : fl_down(box());
53 pic_ = downimage;
54 }
55 else
56 {
57 box_ = box();
58 pic_ = upimage;
59 }
60
61 if(pic_)
62 {
63 int xx = x() + Fl::box_dx(box_);
64 int yy = y() + Fl::box_dy(box_);
65 int ww = w() - Fl::box_dw(box_);
66 int hh = h() - Fl::box_dh(box_);
67 int xpos = (ww - pic_->w()) / 2;
68 int ypos = (hh - pic_->h()) / 2;
69
70 fl_push_clip(xx, yy, ww, hh);
71 pic_->draw(xx + xpos, yy + ypos);
72 fl_pop_clip();
73 }
74 // end- modification to render up/down image
75
76 // begin - Fl_Button::draw() (label section)
77 if (labeltype() == FL_NORMAL_LABEL && value()) {
78 Fl_Color c = labelcolor();
79 labelcolor(fl_contrast(c, col));
80 draw_label();
81 labelcolor(c);
82 } else draw_label();
83 if (Fl::focus() == this) draw_focus();
84 // end - Fl_Button::draw() (label section)
85}
86
diff --git a/src/lib/FL/Fl_Image_Toggle_Button.H b/src/lib/FL/Fl_Image_Toggle_Button.H
new file mode 100644
index 0000000..e5f01a7
--- /dev/null
+++ b/src/lib/FL/Fl_Image_Toggle_Button.H
@@ -0,0 +1,20 @@
1#ifndef __FL_IMAGE_Toggle_Button_H
2#define __FL_IMAGE_Toggle_Button_H
3#include <FL/Fl_Toggle_Button.H>
4#include <FL/Fl.H>
5
6class Fl_Image_Toggle_Button: public Fl_Toggle_Button {
7private:
8 Fl_Image* upimage;
9 Fl_Image* downimage;
10public:
11 Fl_Image* up_image();
12 Fl_Image* down_image();
13 void up_image(Fl_Image* p_up_image);
14 void down_image(Fl_Image* p_down_image);
15 void draw();
16 Fl_Image_Toggle_Button(int a,int b,int c,int d,const char* e);
17 Fl_Image_Toggle_Button(int a,int b,int c,int d);
18};
19
20#endif
diff --git a/src/lib/FL/Fl_Image_Toggle_Button.cxx b/src/lib/FL/Fl_Image_Toggle_Button.cxx
new file mode 100644
index 0000000..df006c8
--- /dev/null
+++ b/src/lib/FL/Fl_Image_Toggle_Button.cxx
@@ -0,0 +1,92 @@
1#include <FL/Fl_Image_Toggle_Button.H>
2#include <FL/Fl_Image.H>
3#include <FL/fl_draw.H>
4#ifndef NULL
5#define NULL 0
6#endif
7void Fl_Image_Toggle_Button::up_image(Fl_Image* p_upimage)
8{
9 upimage=p_upimage;
10}
11
12void Fl_Image_Toggle_Button::down_image(Fl_Image* p_downimage)
13{
14 downimage=p_downimage;
15}
16
17Fl_Image* Fl_Image_Toggle_Button::up_image()
18{
19 return upimage;
20}
21
22Fl_Image* Fl_Image_Toggle_Button::down_image()
23{
24 return downimage;
25}
26
27Fl_Image_Toggle_Button::Fl_Image_Toggle_Button(int a,int b,int c,int d,const char* e):Fl_Toggle_Button(a,b,c,d,e)
28{
29 upimage=NULL;
30 downimage=NULL;
31 Fl_Toggle_Button::clear_visible_focus();
32}
33
34Fl_Image_Toggle_Button::Fl_Image_Toggle_Button(int a,int b,int c,int d):Fl_Toggle_Button(a,b,c,d)
35{
36 upimage=NULL;
37 downimage=NULL;
38 Fl_Toggle_Button::clear_visible_focus();
39}
40
41
42void Fl_Image_Toggle_Button::draw()
43{
44 // begin - Fl_Button::draw() (box section)
45 if (type() == FL_HIDDEN_BUTTON) return;
46 Fl_Color col = value() ? selection_color() : color();
47
48
49 draw_box(value() ? (down_box()?down_box():fl_down(box())) : box(), col);
50 // end - Fl_Button::draw() (box section)
51
52 // begin - modification to render up/down image
53 Fl_Boxtype box_;
54 Fl_Image* pic_;
55
56 if(value())
57 {
58 box_ = (down_box())? down_box() : fl_down(box());
59 pic_ = downimage;
60 }
61 else
62 {
63 box_ = box();
64 pic_ = upimage;
65 }
66
67 if(pic_)
68 {
69 int xx = x() + Fl::box_dx(box_);
70 int yy = y() + Fl::box_dy(box_);
71 int ww = w() - Fl::box_dw(box_);
72 int hh = h() - Fl::box_dh(box_);
73 int xpos = (ww - pic_->w()) / 2;
74 int ypos = (hh - pic_->h()) / 2;
75
76 fl_push_clip(xx, yy, ww, hh);
77 pic_->draw(xx + xpos, yy + ypos);
78 fl_pop_clip();
79 }
80 // end- modification to render up/down image
81
82 // begin - Fl_Button::draw() (label section)
83 if (labeltype() == FL_NORMAL_LABEL && value()) {
84 Fl_Color c = Fl_Button::labelcolor();
85 labelcolor(fl_contrast(c, col));
86 draw_label();
87 labelcolor(c);
88 } else draw_label();
89 if (Fl::focus() == this) draw_focus();
90 // end - Fl_Button::draw() (label section)
91}
92
diff --git a/src/lib/FL/Fl_Native_File_Chooser.H b/src/lib/FL/Fl_Native_File_Chooser.H
new file mode 100644
index 0000000..cc5f7bf
--- /dev/null
+++ b/src/lib/FL/Fl_Native_File_Chooser.H
@@ -0,0 +1,40 @@
1//
2// Fl_Native_File_Chooser.H -- FLTK native OS file chooser widget
3//
4// Copyright 2004 by Greg Ercolano.
5//
6// This library is free software; you can redistribute it and/or
7// modify it under the terms of the GNU Library General Public
8// License as published by the Free Software Foundation; either
9// version 2 of the License, or (at your option) any later version.
10//
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// Library General Public License for more details.
15//
16// You should have received a copy of the GNU Library General Public
17// License along with this library; if not, write to the Free Software
18// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19// USA.
20//
21
22#ifndef FL_NATIVE_FILE_CHOOSER_H
23#define FL_NATIVE_FILE_CHOOSER_H
24#include <sys/stat.h>
25// Use Windows' chooser
26#ifdef _WIN32
27#include <FL/Fl_Native_File_Chooser_WIN32.H>
28#endif
29
30// Use Apple's chooser
31#ifdef __APPLE__
32#include <FL/Fl_Native_File_Chooser_MAC.H>
33#endif
34
35// All else falls back to FLTK's own chooser
36#if ! defined(__APPLE__) && !defined(_WIN32)
37#include <FL/Fl_Native_File_Chooser_FLTK.H>
38#endif
39
40#endif /*FL_NATIVE_FILE_CHOOSER_H*/
diff --git a/src/lib/FL/Fl_Native_File_Chooser.cxx b/src/lib/FL/Fl_Native_File_Chooser.cxx
new file mode 100644
index 0000000..cdc4c27
--- /dev/null
+++ b/src/lib/FL/Fl_Native_File_Chooser.cxx
@@ -0,0 +1,44 @@
1//
2// Fl_Native_File_Chooser.cxx -- FLTK native OS file chooser widget
3//
4// Copyright 2004 by Greg Ercolano.
5//
6// This library is free software; you can redistribute it and/or
7// modify it under the terms of the GNU Library General Public
8// License as published by the Free Software Foundation; either
9// version 2 of the License, or (at your option) any later version.
10//
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// Library General Public License for more details.
15//
16// You should have received a copy of the GNU Library General Public
17// License along with this library; if not, write to the Free Software
18// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19// USA.
20//
21// Use Windows' chooser
22#ifdef WINDOWS
23#ifndef _WIN32
24#define _WIN32
25#endif
26#endif
27#ifdef DARWIN
28#define __APPLE__
29#endif
30
31#ifdef _WIN32
32#include "Fl_Native_File_Chooser_WIN32.cxx"
33#endif
34
35// Use Apple's chooser
36#ifdef __APPLE__
37#include "Fl_Native_File_Chooser_MAC.cxx"
38#endif
39
40// All else falls back to FLTK's own chooser
41#if ! defined(__APPLE__) && !defined(_WIN32)
42#include "Fl_Native_File_Chooser_FLTK.cxx"
43#endif
44
diff --git a/src/lib/FL/Fl_Native_File_Chooser_FLTK.H b/src/lib/FL/Fl_Native_File_Chooser_FLTK.H
new file mode 100644
index 0000000..39e4a4a
--- /dev/null
+++ b/src/lib/FL/Fl_Native_File_Chooser_FLTK.H
@@ -0,0 +1,89 @@
1//
2// Fl_Native_File_Chooser_DEFAULT.H -- FLTK native OS file chooser widget
3//
4// Copyright 2005 by Nathan Vander Wilt.
5// March 2005 - wrapper around Fl_File_Chooser
6//
7// This library is free software; you can redistribute it and/or
8// modify it under the terms of the GNU Library General Public
9// License as published by the Free Software Foundation; either
10// version 2 of the License, or (at your option) any later version.
11//
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15// Library General Public License for more details.
16//
17// You should have received a copy of the GNU Library General Public
18// License along with this library; if not, write to the Free Software
19// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20// USA.
21//
22
23// Use FLTK BROWSER
24#include <FL/Fl_File_Chooser.H>
25#include <string.h>
26
27class Fl_Native_File_Chooser {
28public:
29 enum Type {
30 BROWSE_FILE = 0,
31 BROWSE_DIRECTORY,
32 BROWSE_MULTI_FILE,
33 BROWSE_MULTI_DIRECTORY,
34 BROWSE_SAVE_FILE,
35 BROWSE_SAVE_DIRECTORY
36 };
37 enum Option {
38 NO_OPTIONS = 0x0000, // no options enabled
39 SAVEAS_CONFIRM = 0x0001, // Show native 'Save As' overwrite
40 // confirm dialog (if supported)
41 NEW_FOLDER = 0x0002, // Show 'New Folder' icon
42 // (if supported)
43 PREVIEW = 0x0004 // enable preview mode
44 };
45private:
46 int _btype; // kind-of browser to show()
47 int _options; // general options
48 char *_filter; // user supplied filter
49 char *_parsedfilt; // parsed filter
50 int _filtvalue; // selected filter
51 char *_preset_file;
52 char *_prevvalue; // Returned filename
53 char *_directory;
54 char *_errmsg; // error message
55 Fl_File_Chooser *file_chooser;
56 int _nfilters;
57
58 // Private methods
59 void errmsg(const char *msg);
60 int type_fl_file(int);
61 void parse_filter();
62 void keeplocation();
63
64public:
65 Fl_Native_File_Chooser(int val=BROWSE_FILE);
66 ~Fl_Native_File_Chooser();
67
68 // Public methods
69 void type(int);
70 int type() const;
71 void options(int);
72 int options() const;
73 int count() const;
74 const char *filename() const;
75 const char *filename(int i) const;
76 void directory(const char *val);
77 const char *directory() const;
78 void title(const char *);
79 const char* title() const;
80 const char *filter() const;
81 void filter(const char *);
82 int filters() const { return(_nfilters); }
83 void filter_value(int i);
84 int filter_value() const;
85 void preset_file(const char*);
86 const char* preset_file() const;
87 const char *errmsg() const;
88 int show();
89};
diff --git a/src/lib/FL/Fl_Native_File_Chooser_FLTK.cxx b/src/lib/FL/Fl_Native_File_Chooser_FLTK.cxx
new file mode 100644
index 0000000..5d9c1fd
--- /dev/null
+++ b/src/lib/FL/Fl_Native_File_Chooser_FLTK.cxx
@@ -0,0 +1,339 @@
1//
2// Fl_Native_File_Chooser_DEFAULT.cxx -- FLTK native OS file chooser widget
3// March 2005 - wrapper around Fl_File_Chooser by natevw
4//
5// Copyright 2005 by Nathan Vander Wilt.
6//
7//
8// This library is free software; you can redistribute it and/or
9// modify it under the terms of the GNU Library General Public
10// License as published by the Free Software Foundation; either
11// version 2 of the License, or (at your option) any later version.
12//
13// This library is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16// Library General Public License for more details.
17//
18// You should have received a copy of the GNU Library General Public
19// License along with this library; if not, write to the Free Software
20// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21// USA.
22//
23// Please keep code 80 column compliant.
24//
25// 10 20 30 40 50 60 70
26// | | | | | | |
27// 4567890123456789012345678901234567890123456789012345678901234567890123456789
28//
29#include <Fl/x.H>
30#include <FL/Fl_File_Icon.H>
31#include <FL/Fl_Native_File_Chooser.H>
32#include "common.cxx"
33
34static int G_init = 0; // 'first time' initialize flag
35
36// CTOR
37Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) {
38 if ( G_init == 0 ) {
39 // Initialize when instanced for first time
40// Fl_File_Icon::load_system_icons(); // OK to call more than once
41 G_init = 1; // eg. if app already called from main()
42 }
43 _btype = val;
44 _options = NO_OPTIONS;
45 _filter = NULL;
46 _parsedfilt = NULL;
47 _preset_file = NULL;
48 _prevvalue = NULL;
49 _directory = NULL;
50 _errmsg = NULL;
51 file_chooser = new Fl_File_Chooser(NULL, NULL, 0, NULL);
52 type(val); // do this after file_chooser created
53 _nfilters = 0;
54}
55
56// DTOR
57Fl_Native_File_Chooser::~Fl_Native_File_Chooser() {
58 delete file_chooser;
59 _filter = strfree(_filter);
60 _parsedfilt = strfree(_parsedfilt);
61 _preset_file = strfree(_preset_file);
62 _prevvalue = strfree(_prevvalue);
63 _directory = strfree(_directory);
64 _errmsg = strfree(_errmsg);
65}
66
67// PRIVATE: SET ERROR MESSAGE
68void Fl_Native_File_Chooser::errmsg(const char *msg) {
69 _errmsg = strfree(_errmsg);
70 _errmsg = strnew(msg);
71}
72
73// PRIVATE: translate Native types to Fl_File_Chooser types
74int Fl_Native_File_Chooser::type_fl_file(int val) {
75 switch (val) {
76 case BROWSE_FILE:
77 return(Fl_File_Chooser::SINGLE);
78 case BROWSE_DIRECTORY:
79 return(Fl_File_Chooser::SINGLE | Fl_File_Chooser::DIRECTORY);
80 case BROWSE_MULTI_FILE:
81 return(Fl_File_Chooser::MULTI);
82 case BROWSE_MULTI_DIRECTORY:
83 return(Fl_File_Chooser::DIRECTORY | Fl_File_Chooser::MULTI);
84 case BROWSE_SAVE_FILE:
85 return(Fl_File_Chooser::SINGLE | Fl_File_Chooser::CREATE);
86 case BROWSE_SAVE_DIRECTORY:
87 return(Fl_File_Chooser::DIRECTORY | Fl_File_Chooser::SINGLE | Fl_File_Chooser::CREATE);
88 default:
89 return(Fl_File_Chooser::SINGLE);
90 }
91}
92
93void Fl_Native_File_Chooser::type(int val) {
94 _btype = val;
95 file_chooser->type(type_fl_file(val));
96}
97
98int Fl_Native_File_Chooser::type() const {
99 return(_btype);
100}
101
102// SET OPTIONS
103void Fl_Native_File_Chooser::options(int val) {
104 _options = val;
105}
106
107// GET OPTIONS
108int Fl_Native_File_Chooser::options() const {
109 return(_options);
110}
111
112// Show chooser, blocks until done.
113// RETURNS:
114// 0 - user picked a file
115// 1 - user cancelled
116// -1 - failed; errmsg() has reason
117//
118int Fl_Native_File_Chooser::show() {
119 // FILTER
120 if ( _parsedfilt ) {
121 file_chooser->filter(_parsedfilt);
122 }
123
124 // FILTER VALUE
125 // Set this /after/ setting the filter
126 //
127 if (_filtvalue!=-1)
128 {
129 file_chooser->filter_value(_filtvalue);
130 }
131
132 // DIRECTORY
133 if ( _directory && _directory[0] ) {
134 file_chooser->directory(_directory);
135 } else {
136 file_chooser->directory(_prevvalue);
137 }
138
139 // PRESET FILE
140 if ( _preset_file ) {
141 file_chooser->value(_preset_file);
142 }
143
144 // OPTIONS: PREVIEW
145 file_chooser->preview( (options() & PREVIEW) ? 1 : 0);
146
147 // OPTIONS: NEW FOLDER
148 if ( options() & NEW_FOLDER )
149 file_chooser->type(file_chooser->type() | Fl_File_Chooser::CREATE); // on
150
151 // SHOW
152 file_chooser->show();
153
154 while ( file_chooser->shown() ) {
155 Fl::wait(); // block while shown
156 }
157
158 if ( file_chooser->value() && file_chooser->value()[0] ) {
159 _prevvalue = strfree(_prevvalue);
160 _prevvalue = strnew(file_chooser->value());
161 _filtvalue = file_chooser->filter_value(); // update filter value
162
163 // HANDLE SHOWING 'SaveAs' CONFIRM
164 if ( options() & SAVEAS_CONFIRM && type() == BROWSE_SAVE_FILE ) {
165 struct stat buf;
166 if ( stat(file_chooser->value(), &buf) != -1 ) {
167 if ( buf.st_mode & S_IFREG ) { // Regular file + exists?
168 if ( fl_choice("File exists. Are you sure you want to overwrite?", "Cancel", " OK ", NULL) == 0 ) {
169 return(1);
170 }
171 }
172 }
173 }
174 }
175
176 if ( file_chooser->count() ) return(0);
177 else return(1);
178}
179
180// RETURN ERROR MESSAGE
181const char *Fl_Native_File_Chooser::errmsg() const {
182 return(_errmsg ? _errmsg : "No error");
183}
184
185// GET FILENAME
186const char* Fl_Native_File_Chooser::filename() const {
187 if ( file_chooser->count() > 0 ) return(file_chooser->value());
188 return("");
189}
190
191// GET FILENAME FROM LIST OF FILENAMES
192const char* Fl_Native_File_Chooser::filename(int i) const {
193 if ( i < file_chooser->count() ) return(file_chooser->value(i+1)); // convert fltk 1 based to our 0 based
194 return("");
195}
196
197// SET TITLE
198// Can be NULL if no title desired.
199//
200void Fl_Native_File_Chooser::title(const char *val) {
201 file_chooser->label(val);
202}
203
204// GET TITLE
205// Can return NULL if none set.
206//
207const char *Fl_Native_File_Chooser::title() const {
208 return(file_chooser->label());
209}
210
211// SET FILTER
212// Can be NULL if no filter needed
213//
214void Fl_Native_File_Chooser::filter(const char *val) {
215 _filter = strfree(_filter);
216 _filter = strnew(val);
217 parse_filter();
218}
219
220// GET FILTER
221const char *Fl_Native_File_Chooser::filter() const {
222 return(_filter);
223}
224
225// SET SELECTED FILTER
226void Fl_Native_File_Chooser::filter_value(int val) {
227 _filtvalue = val;
228}
229
230// RETURN SELECTED FILTER
231int Fl_Native_File_Chooser::filter_value() const {
232 return(_filtvalue);
233}
234
235// GET TOTAL FILENAMES CHOSEN
236int Fl_Native_File_Chooser::count() const {
237 return(file_chooser->count());
238}
239
240// PRESET PATHNAME
241// Can be NULL if no preset is desired.
242//
243void Fl_Native_File_Chooser::directory(const char *val) {
244 _directory = strfree(_directory);
245 _directory = strnew(val);
246}
247
248// GET PRESET PATHNAME
249// Can return NULL if none set.
250//
251const char *Fl_Native_File_Chooser::directory() const {
252 return(_directory);
253}
254
255// Convert our filter format to Fl_File_Chooser's format
256// FROM TO (FLTK)
257// ------------------------- --------------------------
258// "*.cxx" "*.cxx Files(*.cxx)"
259// "C Files\t*.{cxx,h}" "C Files(*.{cxx,h})"
260// "C Files\t*.{cxx,h}\nText Files\t*.txt" "C Files(*.{cxx,h})\tText Files(*.txt)"
261//
262// Returns a modified version of the filter that the caller is responsible
263// for freeing with strfree().
264//
265void Fl_Native_File_Chooser::parse_filter() {
266 _parsedfilt = strfree(_parsedfilt); // clear previous parsed filter (if any)
267 _nfilters = 0;
268 char *in = _filter;
269 if ( !in ) return;
270
271 int has_name = strchr(in, '\t') ? 1 : 0;
272
273 char mode = has_name ? 'n' : 'w'; // parse mode: n=title, w=wildcard
274 char wildcard[1024] = ""; // parsed wildcard
275 char name[1024] = "";
276
277 // Parse filter user specified
278 for ( ; 1; in++ ) {
279
280 /*** DEBUG
281 printf("WORKING ON '%c': mode=<%c> name=<%s> wildcard=<%s>\n",
282 *in, mode, name, wildcard);
283 ***/
284
285 switch (*in) {
286 // FINISHED PARSING NAME?
287 case '\t':
288 if ( mode != 'n' ) goto regchar;
289 mode = 'w';
290 break;
291
292 // ESCAPE NEXT CHAR
293 case '\\':
294 ++in;
295 goto regchar;
296
297 // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS?
298 case '\r':
299 case '\n':
300 case '\0':
301 // APPEND NEW FILTER TO LIST
302 if ( wildcard[0] ) {
303 // OUT: "name(wild)\tname(wild)"
304 char comp[2048];
305 sprintf(comp, "%s%.511s(%.511s)", ((_parsedfilt)?"\t":""), name, wildcard);
306 _parsedfilt = strapp(_parsedfilt, comp);
307 _nfilters++;
308 //DEBUG printf("DEBUG: PARSED FILT NOW <%s>\n", _parsedfilt);
309 }
310 // RESET
311 wildcard[0] = name[0] = '\0';
312 mode = strchr(in, '\t') ? 'n' : 'w';
313 // DONE?
314 if ( *in == '\0' ) return; // done
315 else continue; // not done yet, more filters
316
317 // Parse all other chars
318 default: // handle all non-special chars
319 regchar: // handle regular char
320 switch ( mode ) {
321 case 'n': chrcat(name, *in); continue;
322 case 'w': chrcat(wildcard, *in); continue;
323 }
324 break;
325 }
326 }
327 //NOTREACHED
328}
329
330// SET PRESET FILENAME
331void Fl_Native_File_Chooser::preset_file(const char* val) {
332 _preset_file = strfree(_preset_file);
333 _preset_file = strnew(val);
334}
335
336// GET PRESET FILENAME
337const char* Fl_Native_File_Chooser::preset_file() const {
338 return(_preset_file);
339}
diff --git a/src/lib/FL/Fl_Native_File_Chooser_MAC.H b/src/lib/FL/Fl_Native_File_Chooser_MAC.H
new file mode 100644
index 0000000..49577c4
--- /dev/null
+++ b/src/lib/FL/Fl_Native_File_Chooser_MAC.H
@@ -0,0 +1,138 @@
1//
2// Fl_Native_File_Chooser_MAC.H -- FLTK native OS file chooser widget
3//
4// Copyright 2004 by Greg Ercolano.
5//
6// This library is free software; you can redistribute it and/or
7// modify it under the terms of the GNU Library General Public
8// License as published by the Free Software Foundation; either
9// version 2 of the License, or (at your option) any later version.
10//
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// Library General Public License for more details.
15//
16// You should have received a copy of the GNU Library General Public
17// License along with this library; if not, write to the Free Software
18// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19// USA.
20//
21// 10 20 30 40 50 60 70
22// | | | | | | |
23// 4567890123456789012345678901234567890123456789012345678901234567890123456789
24
25// OSX-SPECIFIC NATIVE BROWSER
26#ifdef __APPLE_CC__
27#include <Carbon/Carbon.h>
28#else
29#include <Carbon.h>
30#endif
31
32#include <FL/filename.H>
33#define MAXFILTERS 80
34
35class Fl_Native_File_Chooser {
36public:
37 enum Type {
38 BROWSE_FILE = 0,
39 BROWSE_DIRECTORY,
40 BROWSE_MULTI_FILE,
41 BROWSE_MULTI_DIRECTORY,
42 BROWSE_SAVE_FILE,
43 BROWSE_SAVE_DIRECTORY
44 };
45 enum Option {
46 NO_OPTIONS = 0x0000, // no options enabled
47 SAVEAS_CONFIRM = 0x0001, // Show native 'Save As' overwrite
48 // confirm dialog (if supported)
49 NEW_FOLDER = 0x0002, // Show 'New Folder' icon
50 // (if supported)
51 PREVIEW = 0x0004, // enable preview mode
52 };
53protected:
54 NavDialogCreationOptions _opts; // file navigation options
55private:
56 int _btype; // kind-of browser to show()
57 int _options; // general options
58 NavDialogRef _ref; // file navigation reference
59 NavActionState _keepstate; // holds button permissions
60 NavMenuItemSpec _tempitem; // Popup menu selection
61 char **_pathnames; // array of pathnames
62 int _tpathnames; // total pathnames
63 char *_directory; // default pathname to use
64 char *_title; // title for window
65 char *_preset_file; // the 'save as' filename
66
67 char *_filter; // user-side search filter, eg:
68 // C Files\t*.[ch]\nText Files\t*.txt"
69
70 char *_filt_names; // filter names (tab delimited)
71 // eg. "C Files\tText Files"
72
73 char *_filt_patt[MAXFILTERS];
74 // array of filter patterns, eg:
75 // _filt_patt[0]="*.{cxx,h}"
76 // _filt_patt[1]="*.txt"
77
78 int _filt_total; // parse_filter() # of filters loaded
79 int _filt_value; // index of the selected filter
80 char *_errmsg; // error message
81
82 // PRIVATE CLASS TO HANDLE NAVIGATION DIALOG REPLY STRUCT
83 // Class-ified, mainly to ensure proper cleanup.
84 //
85 class NavReply {
86 int _valid_reply;
87 NavReplyRecord _reply;
88 public:
89 NavReply();
90 ~NavReply();
91 int get_reply(NavDialogRef& ref);
92 int get_saveas_basename(char *s, int slen);
93 int get_dirname(char *s, int slen);
94 int get_pathnames(char **&pathnames, int& tpathnames);
95 };
96
97 // Private methods
98 void errmsg(const char *msg);
99 void clear_pathnames();
100 void set_single_pathname(const char *s);
101 int get_saveas_basename(NavDialogRef& ref);
102 int get_pathnames(NavDialogRef& ref);
103 static void event_handler(NavEventCallbackMessage callBackSelector,
104 NavCBRecPtr cbparm, void *data);
105
106 void clear_filters();
107 void add_filter(const char *, const char *);
108 void parse_filter(const char *from);
109 static Boolean filter_proc_cb(AEDesc *, void *, void *, NavFilterModes);
110 Boolean filter_proc_cb2(AEDesc*, void*, void*, NavFilterModes);
111 int post();
112
113public:
114 Fl_Native_File_Chooser(int val = BROWSE_FILE);
115 ~Fl_Native_File_Chooser();
116
117 // Public methods
118 void type(int);
119 int type() const;
120 void options(int);
121 int options() const;
122 int count() const;
123 const char *filename() const;
124 const char *filename(int i) const;
125 void directory(const char *);
126 const char *directory() const;
127 void title(const char *);
128 const char *title() const;
129 const char *filter() const;
130 void filter(const char *);
131 void filter_value(int i) { _filt_value = i; }
132 int filter_value() { return(_filt_value); }
133 int filters() { return(_filt_total); }
134 void preset_file(const char *);
135 const char *preset_file();
136 const char *errmsg() const;
137 int show();
138};
diff --git a/src/lib/FL/Fl_Native_File_Chooser_MAC.cxx b/src/lib/FL/Fl_Native_File_Chooser_MAC.cxx
new file mode 100644
index 0000000..e556edf
--- /dev/null
+++ b/src/lib/FL/Fl_Native_File_Chooser_MAC.cxx
@@ -0,0 +1,833 @@
1//
2// Fl_Native_File_Chooser_MAC.cxx -- FLTK native OS file chooser widget
3//
4// Copyright 2004 by Greg Ercolano.
5//
6// This library is free software; you can redistribute it and/or
7// modify it under the terms of the GNU Library General Public
8// License as published by the Free Software Foundation; either
9// version 2 of the License, or (at your option) any later version.
10//
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// Library General Public License for more details.
15//
16// You should have received a copy of the GNU Library General Public
17// License along with this library; if not, write to the Free Software
18// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19// USA.
20//
21// Please keep code 80 column compliant.
22//
23// 10 20 30 40 50 60 70
24// | | | | | | |
25// 4567890123456789012345678901234567890123456789012345678901234567890123456789
26//
27// TODO:
28// o When doing 'open file', only dir is preset, not filename.
29// Possibly 'preset_file' could be used to select the filename.
30//
31#include <FL/Fl.H>
32#include <FL/Fl_Native_File_Chooser.H>
33#include "common.cxx" // strnew/strfree/strapp/chrcat
34
35// TRY TO CONVERT AN AEDesc TO AN FSSpec
36// As per Apple Technical Q&A QA1274
37// eg: http://developer.apple.com/qa/qa2001/qa1274.html
38// Returns 'noErr' if OK,
39// or an 'OSX result code' on error.
40//
41static int AEDescToFSSpec(const AEDesc* desc, FSSpec* fsspec) {
42 OSStatus err = noErr;
43 AEDesc coerceDesc;
44 // If AEDesc isn't already an FSSpec, convert it to one
45 if ( desc->descriptorType != typeFSS ) {
46 if ( ( err = AECoerceDesc(desc, typeFSS, &coerceDesc) ) == noErr ) {
47 // Get FSSpec out of AEDesc
48 err = AEGetDescData(&coerceDesc, fsspec, sizeof(FSSpec));
49 AEDisposeDesc(&coerceDesc);
50 }
51 } else {
52 err = AEGetDescData(desc, fsspec, sizeof(FSSpec));
53 }
54 return( err );
55}
56
57// CONVERT AN FSSpec TO A PATHNAME
58static void FSSpecToPath(const FSSpec &spec, char *buff, int bufflen) {
59 FSRef fsRef;
60 FSpMakeFSRef(&spec, &fsRef);
61 FSRefMakePath(&fsRef, (UInt8*)buff, bufflen);
62}
63
64// CONVERT REGULAR PATH -> FSSpec
65// If file does not exist, expect fnfErr.
66// Returns 'noErr' if OK,
67// or an 'OSX result code' on error.
68//
69static OSStatus PathToFSSpec(const char *path, FSSpec &spec) {
70 OSStatus err;
71 FSRef ref;
72 if ((err = FSPathMakeRef((const UInt8*)path, &ref, NULL)) != noErr) {
73 return(err);
74 }
75 // FSRef -> FSSpec
76 if ((err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, &spec,
77 NULL)) != noErr) {
78 return(err);
79 }
80 return(noErr);
81}
82
83// NAVREPLY: CTOR
84Fl_Native_File_Chooser::NavReply::NavReply() {
85 _valid_reply = 0;
86}
87
88// NAVREPLY: DTOR
89Fl_Native_File_Chooser::NavReply::~NavReply() {
90 if ( _valid_reply ) {
91 NavDisposeReply(&_reply);
92 }
93}
94
95// GET REPLY FROM THE NAV* DIALOG
96int Fl_Native_File_Chooser::NavReply::get_reply(NavDialogRef& ref) {
97 if ( _valid_reply ) {
98 NavDisposeReply(&_reply); // dispose of previous
99 _valid_reply = 0;
100 }
101 if ( ref == NULL || NavDialogGetReply(ref, &_reply) != noErr ) {
102 return(-1);
103 }
104 _valid_reply = 1;
105 return(0);
106}
107
108// RETURN THE BASENAME USER WANTS TO 'Save As'
109int Fl_Native_File_Chooser::NavReply::get_saveas_basename(char *s, int slen) {
110 if (CFStringGetCString(_reply.saveFileName, s, slen-1,
111 kCFStringEncodingUTF8) == false) {
112 s[0] = '\0';
113 return(-1);
114 }
115 return(0);
116}
117
118// RETURN THE DIRECTORY NAME
119// Returns 0 on success, -1 on error.
120//
121int Fl_Native_File_Chooser::NavReply::get_dirname(char *s, int slen) {
122 FSSpec fsspec;
123 if ( AEDescToFSSpec(&_reply.selection, &fsspec) != noErr ) {
124 // Conversion failed? Return empty name
125 s[0] = 0;
126 return(-1);
127 }
128 FSSpecToPath(fsspec, s, slen);
129 return(0);
130}
131
132// RETURN MULTIPLE DIRECTORIES
133// Returns: 0 on success with pathnames[] containing pathnames selected,
134// -1 on error
135//
136int Fl_Native_File_Chooser::NavReply::get_pathnames(char **&pathnames,
137 int& tpathnames) {
138 // How many items selected?
139 long count = 0;
140 if ( AECountItems(&_reply.selection, &count) != noErr )
141 { return(-1); }
142
143 // Allocate space for that many pathnames
144 pathnames = new char*[count];
145 memset((void*)pathnames, 0, count*sizeof(char*));
146 tpathnames = count;
147
148 // Walk list of pathnames selected
149 for (short index=1; index<=count; index++) {
150 AEKeyword keyWord;
151 AEDesc desc;
152 if (AEGetNthDesc(&_reply.selection, index, typeFSS, &keyWord,
153 &desc) != noErr) {
154 pathnames[index-1] = strnew("");
155 continue;
156 }
157 FSSpec fsspec;
158 if (AEGetDescData(&desc, &fsspec, sizeof(FSSpec)) != noErr ) {
159 pathnames[index-1] = strnew("");
160 continue;
161 }
162 char s[4096];
163 FSSpecToPath(fsspec, s, sizeof(s)-1);
164 pathnames[index-1] = strnew(s);
165 AEDisposeDesc(&desc);
166 }
167 return(0);
168}
169
170// FREE PATHNAMES ARRAY, IF IT HAS ANY CONTENTS
171void Fl_Native_File_Chooser::clear_pathnames() {
172 if ( _pathnames ) {
173 while ( --_tpathnames >= 0 ) {
174 _pathnames[_tpathnames] = strfree(_pathnames[_tpathnames]);
175 }
176 delete [] _pathnames;
177 _pathnames = NULL;
178 }
179 _tpathnames = 0;
180}
181
182// SET A SINGLE PATHNAME
183void Fl_Native_File_Chooser::set_single_pathname(const char *s) {
184 clear_pathnames();
185 _pathnames = new char*[1];
186 _pathnames[0] = strnew(s);
187 _tpathnames = 1;
188}
189
190// GET THE 'Save As' FILENAME
191// Returns -1 on error, errmsg() has reason, filename == "".
192// 0 if OK, filename() has filename chosen.
193//
194int Fl_Native_File_Chooser::get_saveas_basename(NavDialogRef& ref) {
195 if ( ref == NULL ) {
196 errmsg("get_saveas_basename: ref is NULL");
197 return(-1);
198 }
199 NavReply reply;
200 OSStatus err;
201 if ((err = reply.get_reply(ref)) != noErr ) {
202 errmsg("NavReply::get_reply() failed");
203 clear_pathnames();
204 return(-1);
205 }
206
207 char pathname[4096] = "";
208 // Directory name..
209 // -2 leaves room to append '/'
210 //
211 if ( reply.get_dirname(pathname, sizeof(pathname)-2) < 0 ) {
212 clear_pathnames();
213 errmsg("NavReply::get_dirname() failed");
214 return(-1);
215 }
216 // Append '/'
217 int len = strlen(pathname);
218 pathname[len++] = '/';
219 pathname[len] = '\0';
220 // Basename..
221 if ( reply.get_saveas_basename(pathname+len, sizeof(pathname)-len) < 0 ) {
222 clear_pathnames();
223 errmsg("NavReply::get_saveas_basename() failed");
224 return(-1);
225 }
226 set_single_pathname(pathname);
227 return(0);
228}
229
230// GET (POTENTIALLY) MULTIPLE FILENAMES
231// Returns:
232// -1 -- error, errmsg() has reason, filename == ""
233// 0 -- OK, pathnames()/filename() has pathname(s) chosen
234//
235int Fl_Native_File_Chooser::get_pathnames(NavDialogRef& ref) {
236 if ( ref == NULL ) {
237 errmsg("get_saveas_basename: ref is NULL");
238 return(-1);
239 }
240 NavReply reply;
241 OSStatus err;
242 if ((err = reply.get_reply(ref)) != noErr ) {
243 errmsg("NavReply::get_reply() failed");
244 clear_pathnames();
245 return(-1);
246 }
247 // First, clear pathnames array of any previous contents
248 clear_pathnames();
249 if ( reply.get_pathnames(_pathnames, _tpathnames) < 0 ) {
250 clear_pathnames();
251 errmsg("NavReply::get_dirname() failed");
252 return(-1);
253 }
254 return(0);
255}
256
257// NAV CALLBACK EVENT HANDLER
258void Fl_Native_File_Chooser::event_handler(
259 NavEventCallbackMessage callBackSelector,
260 NavCBRecPtr cbparm,
261 void *data) {
262 OSStatus err;
263 Fl_Native_File_Chooser *nfb = (Fl_Native_File_Chooser*)data;
264 switch (callBackSelector) {
265 case kNavCBStart:
266 if ( nfb->directory() || nfb->preset_file() ) {
267 const char *pathname = nfb->directory() ? nfb->directory() : nfb->preset_file();
268 FSSpec spec;
269 if ( ( err = PathToFSSpec(pathname, spec) ) != noErr ) {
270 fprintf(stderr, "PathToFSSpec(%s) failed: err=%d\n",
271 pathname, (int)err);
272 break;
273 }
274 AEDesc desc;
275 if ((err = AECreateDesc(typeFSS,
276 &spec, sizeof(FSSpec), &desc)) != noErr) {
277 fprintf(stderr, "AECreateDesc() failed: err=%d\n",
278 (int)err);
279 }
280 if ((err = NavCustomControl(cbparm->context,
281 kNavCtlSetLocation, &desc)) != noErr) {
282 fprintf(stderr, "NavCustomControl() failed: err=%d\n",
283 (int)err);
284 }
285 AEDisposeDesc(&desc);
286 }
287 if ( nfb->_btype == BROWSE_SAVE_FILE && nfb->preset_file() ) {
288 CFStringRef namestr =
289 CFStringCreateWithCString(NULL,
290 nfb->preset_file(),
291 kCFStringEncodingASCII);
292 NavDialogSetSaveFileName(cbparm->context, namestr);
293 CFRelease(namestr);
294 }
295 NavCustomControl(cbparm->context, kNavCtlSetActionState,
296 &nfb->_keepstate );
297
298 // Select the right filter in pop-up menu
299 if ( nfb->_filt_value == nfb->_filt_total ) {
300 // Select All Documents
301 NavPopupMenuItem kAll = kNavAllFiles;
302 NavCustomControl(cbparm->context, kNavCtlSelectAllType, &kAll);
303 } else if (nfb->_filt_value < nfb->_filt_total) {
304 // Select custom filter
305 nfb->_tempitem.version = kNavMenuItemSpecVersion;
306 nfb->_tempitem.menuCreator = 'extn';
307 nfb->_tempitem.menuType = nfb->_filt_value;
308 *nfb->_tempitem.menuItemName = '\0'; // needed on 10.3+
309 NavCustomControl(cbparm->context,
310 kNavCtlSelectCustomType,
311 &(nfb->_tempitem));
312 }
313 break;
314
315 case kNavCBPopupMenuSelect:
316 NavMenuItemSpecPtr ptr;
317 // they really buried this one!
318 ptr = (NavMenuItemSpecPtr)cbparm->eventData.eventDataParms.param;
319 if ( ptr->menuCreator ) {
320 // Gets index to filter ( menuCreator = 'extn' )
321 nfb->_filt_value = ptr->menuType;
322 } else {
323 // All docs filter selected ( menuCreator = '\0\0\0\0' )
324 nfb->_filt_value = nfb->_filt_total;
325 }
326 break;
327
328 case kNavCBSelectEntry:
329 NavActionState astate;
330 switch ( nfb->_btype ) {
331 // these don't need selection override
332 case BROWSE_MULTI_FILE:
333 case BROWSE_MULTI_DIRECTORY:
334 case BROWSE_SAVE_FILE:
335 break;
336
337 // These need to allow only one item, so disable
338 // Open button if user tries to select multiple files
339 case BROWSE_SAVE_DIRECTORY:
340 case BROWSE_DIRECTORY:
341 case BROWSE_FILE:
342 SInt32 selectcount;
343 AECountItems((AEDescList*)cbparm->
344 eventData.eventDataParms.param,
345 &selectcount);
346 if ( selectcount > 1 ) {
347 NavCustomControl(cbparm->context,
348 kNavCtlSetSelection,
349 NULL);
350 astate = nfb->_keepstate |
351 kNavDontOpenState |
352 kNavDontChooseState;
353 NavCustomControl(cbparm->context,
354 kNavCtlSetActionState,
355 &astate );
356 }
357 else {
358 astate= nfb->_keepstate | kNavNormalState;
359 NavCustomControl(cbparm->context,
360 kNavCtlSetActionState,
361 &astate );
362 }
363 break;
364 }
365 break;
366 }
367}
368
369// CONSTRUCTOR
370Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) {
371 _btype = val;
372 NavGetDefaultDialogCreationOptions(&_opts);
373 _opts.optionFlags |= kNavDontConfirmReplacement; // no confirms for "save as"
374 _options = NO_OPTIONS;
375 _ref = NULL;
376 memset(&_tempitem, 0, sizeof(_tempitem));
377 _pathnames = NULL;
378 _tpathnames = 0;
379 _title = NULL;
380 _filter = NULL;
381 _filt_names = NULL;
382 memset(_filt_patt, 0, sizeof(char*) * MAXFILTERS);
383 _filt_total = 0;
384 _filt_value = 0;
385 _directory = NULL;
386 _preset_file = NULL;
387 _errmsg = NULL;
388 _keepstate = kNavNormalState;
389}
390
391// DESTRUCTOR
392Fl_Native_File_Chooser::~Fl_Native_File_Chooser() {
393 // _opts // nothing to manage
394 if (_ref) { NavDialogDispose(_ref); _ref = NULL; }
395 // _options // nothing to manage
396 // _keepstate // nothing to manage
397 // _tempitem // nothing to manage
398 clear_pathnames();
399 _directory = strfree(_directory);
400 _title = strfree(_title);
401 _preset_file = strfree(_preset_file);
402 _filter = strfree(_filter);
403 //_filt_names // managed by clear_filters()
404 //_filt_patt[i] // managed by clear_filters()
405 //_filt_total // managed by clear_filters()
406 clear_filters();
407 //_filt_value // nothing to manage
408 _errmsg = strfree(_errmsg);
409}
410
411// SET THE TYPE OF BROWSER
412void Fl_Native_File_Chooser::type(int val) {
413 _btype = val;
414}
415
416// GET TYPE OF BROWSER
417int Fl_Native_File_Chooser::type() const {
418 return(_btype);
419}
420
421// SET OPTIONS
422void Fl_Native_File_Chooser::options(int val) {
423 _options = val;
424}
425
426// GET OPTIONS
427int Fl_Native_File_Chooser::options() const {
428 return(_options);
429}
430
431// SHOW THE BROWSER WINDOW
432// Returns:
433// 0 - user picked a file
434// 1 - user cancelled
435// -1 - failed; errmsg() has reason
436//
437int Fl_Native_File_Chooser::show() {
438 // Make sure fltk interface updates before posting our dialog
439 Fl::flush();
440
441 // BROWSER TITLE
442 CFStringRef cfs_title;
443 cfs_title = CFStringCreateWithCString(NULL,
444 _title ? _title : "No Title",
445 kCFStringEncodingASCII);
446 _opts.windowTitle = cfs_title;
447
448 _keepstate = kNavNormalState;
449
450 // BROWSER FILTERS
451 CFArrayRef filter_array = NULL;
452 {
453 // One or more filters specified?
454 if ( _filt_total ) {
455 // NAMES -> CFArrayRef
456 CFStringRef tab = CFSTR("\t");
457 CFStringRef tmp_cfs;
458 tmp_cfs = CFStringCreateWithCString(NULL, _filt_names,
459 kCFStringEncodingASCII);
460 filter_array = CFStringCreateArrayBySeparatingStrings(
461 NULL, tmp_cfs, tab);
462 CFRelease(tmp_cfs);
463 CFRelease(tab);
464 _opts.popupExtension = filter_array;
465 _opts.optionFlags |= kNavAllFilesInPopup;
466 } else {
467 filter_array = NULL;
468 _opts.popupExtension = NULL;
469 _opts.optionFlags |= kNavAllFilesInPopup;
470 }
471 }
472
473 // HANDLE OPTIONS WE SUPPORT
474 if ( _options & SAVEAS_CONFIRM ) {
475 _opts.optionFlags &= ~kNavDontConfirmReplacement; // enables confirm
476 } else {
477 _opts.optionFlags |= kNavDontConfirmReplacement; // disables confirm
478 }
479
480 // POST BROWSER
481 int err = post();
482
483 // RELEASE _FILT_ARR
484 if ( filter_array ) CFRelease(filter_array);
485 filter_array = NULL;
486 _opts.popupExtension = NULL;
487 _filt_total = 0;
488
489 // RELEASE TITLE
490 if ( cfs_title ) CFRelease(cfs_title);
491 cfs_title = NULL;
492
493 return(err);
494}
495
496// POST BROWSER
497// Internal use only.
498// Assumes '_opts' has been initialized.
499//
500// Returns:
501// 0 - user picked a file
502// 1 - user cancelled
503// -1 - failed; errmsg() has reason
504//
505int Fl_Native_File_Chooser::post() {
506
507 // INITIALIZE BROWSER
508 OSStatus err;
509 if ( _filt_total == 0 ) { // Make sure they match
510 _filt_value = 0; // TBD: move to someplace more logical?
511 }
512
513 if ( ! ( _options & NEW_FOLDER ) ) {
514 _keepstate |= kNavDontNewFolderState;
515 }
516
517 switch (_btype) {
518 case BROWSE_FILE:
519 case BROWSE_MULTI_FILE:
520 // Prompt user for one or more files
521 if ((err = NavCreateGetFileDialog(
522 &_opts, // options
523 0, // file types
524 event_handler, // event handler
525 0, // preview callback
526 filter_proc_cb, // filter callback
527 (void*)this, // callback data
528 &_ref)) != noErr ) { // dialog ref
529 errmsg("NavCreateGetFileDialog: failed");
530 return(-1);
531 }
532 break;
533
534 case BROWSE_DIRECTORY:
535 case BROWSE_MULTI_DIRECTORY:
536 case BROWSE_SAVE_DIRECTORY:
537 // Prompts user for one or more files or folders
538 if ((err = NavCreateChooseFolderDialog(
539 &_opts, // options
540 event_handler, // event callback
541 0, // filter callback
542 (void*)this, // callback data
543 &_ref)) != noErr ) { // dialog ref
544 errmsg("NavCreateChooseFolderDialog: failed");
545 return(-1);
546 }
547 break;
548
549 case BROWSE_SAVE_FILE:
550 // Prompt user for filename to 'save as'
551 if ((err = NavCreatePutFileDialog(
552 &_opts, // options
553 0, // file types
554 0, // file creator
555 event_handler, // event handler
556 (void*)this, // callback data
557 &_ref)) != noErr ) { // dialog ref
558 errmsg("NavCreatePutFileDialog: failed");
559 return(-1);
560 }
561 break;
562 }
563
564 // SHOW THE DIALOG
565 if ( ( err = NavDialogRun(_ref) ) != 0 ) {
566 char msg[80];
567 sprintf(msg, "NavDialogRun: failed (err=%d)", (int)err);
568 errmsg(msg);
569 return(-1);
570 }
571
572 // WHAT ACTION DID USER CHOOSE?
573 NavUserAction act = NavDialogGetUserAction(_ref);
574 if ( act == kNavUserActionNone ) {
575 errmsg("Nothing happened yet (dialog still open)");
576 return(-1);
577 }
578 else if ( act == kNavUserActionCancel ) { // user chose 'cancel'
579 return(1);
580 }
581 else if ( act == kNavUserActionSaveAs ) { // user chose 'save as'
582 return(get_saveas_basename(_ref));
583 }
584
585 // TOO MANY FILES CHOSEN?
586 int ret = get_pathnames(_ref);
587 if ( _btype == BROWSE_FILE && ret == 0 && _tpathnames != 1 ) {
588 char msg[80];
589 sprintf(msg, "Expected only one file to be chosen.. you chose %d.",
590 (int)_tpathnames);
591 errmsg(msg);
592 return(-1);
593 }
594 return(err);
595}
596
597// SET ERROR MESSAGE
598// Internal use only.
599//
600void Fl_Native_File_Chooser::errmsg(const char *msg) {
601 _errmsg = strfree(_errmsg);
602 _errmsg = strnew(msg);
603}
604
605// RETURN ERROR MESSAGE
606const char *Fl_Native_File_Chooser::errmsg() const {
607 return(_errmsg ? _errmsg : "No error");
608}
609
610// GET FILENAME
611const char* Fl_Native_File_Chooser::filename() const {
612 if ( _pathnames && _tpathnames > 0 ) return(_pathnames[0]);
613 return("");
614}
615
616// GET FILENAME FROM LIST OF FILENAMES
617const char* Fl_Native_File_Chooser::filename(int i) const {
618 if ( _pathnames && i < _tpathnames ) return(_pathnames[i]);
619 return("");
620}
621
622// GET TOTAL FILENAMES CHOSEN
623int Fl_Native_File_Chooser::count() const {
624 return(_tpathnames);
625}
626
627// PRESET PATHNAME
628// Value can be NULL for none.
629//
630void Fl_Native_File_Chooser::directory(const char *val) {
631 _directory = strfree(_directory);
632 _directory = strnew(val);
633}
634
635// GET PRESET PATHNAME
636// Returned value can be NULL if none set.
637//
638const char* Fl_Native_File_Chooser::directory() const {
639 return(_directory);
640}
641
642// SET TITLE
643// Value can be NULL if no title desired.
644//
645void Fl_Native_File_Chooser::title(const char *val) {
646 _title = strfree(_title);
647 _title = strnew(val);
648}
649
650// GET TITLE
651// Returned value can be NULL if none set.
652//
653const char *Fl_Native_File_Chooser::title() const {
654 return(_title);
655}
656
657// SET FILTER
658// Can be NULL if no filter needed
659//
660void Fl_Native_File_Chooser::filter(const char *val) {
661 _filter = strfree(_filter);
662 _filter = strnew(val);
663
664 // Parse filter user specified
665 // IN: _filter = "C Files\t*.{cxx,h}\nText Files\t*.txt"
666 // OUT: _filt_names = "C Files\tText Files"
667 // _filt_patt[0] = "*.{cxx,h}"
668 // _filt_patt[1] = "*.txt"
669 // _filt_total = 2
670 //
671 parse_filter(_filter);
672}
673
674// GET FILTER
675// Returned value can be NULL if none set.
676//
677const char *Fl_Native_File_Chooser::filter() const {
678 return(_filter);
679}
680
681// CLEAR ALL FILTERS
682// Internal use only.
683//
684void Fl_Native_File_Chooser::clear_filters() {
685 _filt_names = strfree(_filt_names);
686 for (int i=0; i<_filt_total; i++) {
687 _filt_patt[i] = strfree(_filt_patt[i]);
688 }
689 _filt_total = 0;
690}
691
692// PARSE USER'S FILTER SPEC
693// Parses user specified filter ('in'),
694// breaks out into _filt_patt[], _filt_names, and _filt_total.
695//
696// Handles:
697// IN: OUT:_filt_names OUT: _filt_patt
698// ------------------------------------ ------------------ ---------------
699// "*.{ma,mb}" "*.{ma,mb} Files" "*.{ma,mb}"
700// "*.[abc]" "*.[abc] Files" "*.[abc]"
701// "*.txt" "*.txt Files" "*.c"
702// "C Files\t*.[ch]" "C Files" "*.[ch]"
703// "C Files\t*.[ch]\nText Files\t*.cxx" "C Files" "*.[ch]"
704//
705// Parsing Mode:
706// IN:"C Files\t*.{cxx,h}"
707// ||||||| |||||||||
708// mode: nnnnnnn wwwwwwwww
709// \_____/ \_______/
710// Name Wildcard
711//
712void Fl_Native_File_Chooser::parse_filter(const char *in) {
713 clear_filters();
714 if ( ! in ) return;
715 int has_name = strchr(in, '\t') ? 1 : 0;
716
717 char mode = has_name ? 'n' : 'w'; // parse mode: n=title, w=wildcard
718 char wildcard[1024] = ""; // parsed wildcard
719 char name[1024] = "";
720
721 // Parse filter user specified
722 for ( ; 1; in++ ) {
723
724 //// DEBUG
725 //// printf("WORKING ON '%c': mode=<%c> name=<%s> wildcard=<%s>\n",
726 //// *in, mode, name, wildcard);
727
728 switch (*in) {
729 // FINISHED PARSING NAME?
730 case '\t':
731 if ( mode != 'n' ) goto regchar;
732 mode = 'w';
733 break;
734
735 // ESCAPE NEXT CHAR
736 case '\\':
737 ++in;
738 goto regchar;
739
740 // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS?
741 case '\r':
742 case '\n':
743 case '\0':
744 // TITLE
745 // If user didn't specify a name, make one
746 //
747 if ( name[0] == '\0' ) {
748 sprintf(name, "%.*s Files", (int)sizeof(name)-10, wildcard);
749 }
750 // APPEND NEW FILTER TO LIST
751 if ( wildcard[0] ) {
752 // Add to filtername list
753 // Tab delimit if more than one. We later break
754 // tab delimited string into CFArray with
755 // CFStringCreateArrayBySeparatingStrings()
756 //
757 if ( _filt_total ) {
758 _filt_names = strapp(_filt_names, "\t");
759 }
760 _filt_names = strapp(_filt_names, name);
761
762 // Add filter to the pattern array
763 _filt_patt[_filt_total++] = strnew(wildcard);
764 }
765 // RESET
766 wildcard[0] = name[0] = '\0';
767 mode = strchr(in, '\t') ? 'n' : 'w';
768 // DONE?
769 if ( *in == '\0' ) return; // done
770 else continue; // not done yet, more filters
771
772 // Parse all other chars
773 default: // handle all non-special chars
774 regchar: // handle regular char
775 switch ( mode ) {
776 case 'n': chrcat(name, *in); continue;
777 case 'w': chrcat(wildcard, *in); continue;
778 }
779 break;
780 }
781 }
782 //NOTREACHED
783}
784
785// STATIC: FILTER CALLBACK
786Boolean Fl_Native_File_Chooser::filter_proc_cb(AEDesc *theItem,
787 void *info,
788 void *callBackUD,
789 NavFilterModes filterMode) {
790 return((Fl_Native_File_Chooser*)callBackUD)->filter_proc_cb2(
791 theItem, info, callBackUD, filterMode);
792}
793
794// FILTER CALLBACK
795// Return true if match,
796// false if no match.
797//
798Boolean Fl_Native_File_Chooser::filter_proc_cb2(AEDesc *theItem,
799 void *info,
800 void *callBackUD,
801 NavFilterModes filterMode) {
802 // All files chosen or no filters
803 if ( _filt_value == _filt_total ) return(true);
804
805 FSSpec fsspec;
806 char pathname[4096];
807
808 // On fail, filter should return true by default
809 if ( AEDescToFSSpec(theItem, &fsspec) != noErr ) {
810 return(true);
811 }
812 FSSpecToPath(fsspec, pathname, sizeof(pathname)-1);
813
814 if ( fl_filename_isdir(pathname) ) return(true);
815 if ( fl_filename_match(pathname, _filt_patt[_filt_value]) ) return(true);
816 else return(false);
817}
818
819// SET PRESET FILE
820// Value can be NULL for none.
821//
822void Fl_Native_File_Chooser::preset_file(const char* val) {
823 _preset_file = strfree(_preset_file);
824 _preset_file = strnew(val);
825}
826
827// PRESET FILE
828// Returned value can be NULL if none set.
829//
830const char* Fl_Native_File_Chooser::preset_file() {
831 return(_preset_file);
832}
833
diff --git a/src/lib/FL/Fl_Native_File_Chooser_WIN32.H b/src/lib/FL/Fl_Native_File_Chooser_WIN32.H
new file mode 100644
index 0000000..ead87df
--- /dev/null
+++ b/src/lib/FL/Fl_Native_File_Chooser_WIN32.H
@@ -0,0 +1,114 @@
1//
2// Fl_Native_File_Chooser_WINDOWS.H -- FLTK native OS file chooser widget
3//
4// Copyright 2004 by Greg Ercolano.
5// April 2005 - API changes, improved filter processing by Nathan Vander Wilt
6//
7// This library is free software; you can redistribute it and/or
8// modify it under the terms of the GNU Library General Public
9// License as published by the Free Software Foundation; either
10// version 2 of the License, or (at your option) any later version.
11//
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15// Library General Public License for more details.
16//
17// You should have received a copy of the GNU Library General Public
18// License along with this library; if not, write to the Free Software
19// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20// USA.
21//
22#ifndef _FL_NATIVE_FILE_BROWSER_H
23#define _FL_NATIVE_FILE_BROWSER_H
24
25// #define _WIN32_WINNT 0x0501 // needed for OPENFILENAME's 'FlagsEx'
26#include <stdio.h>
27#include <stdlib.h> // malloc
28#include <windows.h>
29#include <commdlg.h> // OPENFILENAME, GetOpenFileName()
30#include <shlobj.h> // BROWSEINFO, SHBrowseForFolder()
31
32#define MAXFILTERS 80
33
34class Fl_Native_File_Chooser {
35public:
36 enum Type {
37 BROWSE_FILE = 0,
38 BROWSE_DIRECTORY,
39 BROWSE_MULTI_FILE,
40 BROWSE_MULTI_DIRECTORY,
41 BROWSE_SAVE_FILE,
42 BROWSE_SAVE_DIRECTORY
43 };
44 enum Option {
45 NO_OPTIONS = 0x0000, // no options enabled
46 SAVEAS_CONFIRM = 0x0001, // Show native 'Save As' overwrite
47 // confirm dialog (if supported)
48 NEW_FOLDER = 0x0002, // Show 'New Folder' icon
49 // (if supported)
50 PREVIEW = 0x0004, // enable preview mode
51 };
52private:
53 int _btype; // kind-of browser to show()
54 int _options; // general options
55 OPENFILENAME _ofn; // GetOpenFileName() & GetSaveFileName() struct
56 BROWSEINFO _binf; // SHBrowseForFolder() struct
57 char **_pathnames; // array of pathnames
58 int _tpathnames; // total pathnames
59 char *_directory; // default pathname to use
60 char *_title; // title for window
61 char *_filter; // user-side search filter
62 char *_parsedfilt; // filter parsed for Windows dialog
63 int _nfilters; // number of filters parse_filter counted
64 char *_preset_file; // the file to preselect
65 char *_errmsg; // error message
66
67 // Private methods
68 void errmsg(const char *msg);
69
70 void clear_pathnames();
71 void set_single_pathname(const char *s);
72 void add_pathname(const char *s);
73
74 void FreePIDL(ITEMIDLIST *pidl);
75 void ClearOFN();
76 void ClearBINF();
77 void Win2Unix(char *s);
78 void Unix2Win(char *s);
79 int showfile();
80 static int CALLBACK Dir_CB(HWND win, UINT msg, LPARAM param, LPARAM data);
81 int showdir();
82
83 void parse_filter(const char *);
84 void clear_filters();
85 void add_filter(const char *, const char *);
86
87public:
88 Fl_Native_File_Chooser(int val = BROWSE_FILE);
89 ~Fl_Native_File_Chooser();
90
91 // Public methods
92 void type(int val);
93 int type() const;
94 void options(int);
95 int options() const;
96 int count() const;
97 const char *filename() const;
98 const char *filename(int i) const;
99 void directory(const char *val);
100 const char *directory() const;
101 void title(const char *val);
102 const char *title() const;
103 const char *filter() const;
104 void filter(const char *val);
105 int filters() const { return _nfilters; }
106 void filter_value(int i);
107 int filter_value() const;
108 void preset_file(const char *);
109 const char *preset_file() const;
110 const char *errmsg() const;
111 int show();
112};
113
114#endif /*_FL_NATIVE_FILE_BROWSER_H*/
diff --git a/src/lib/FL/Fl_Native_File_Chooser_WIN32.cxx b/src/lib/FL/Fl_Native_File_Chooser_WIN32.cxx
new file mode 100644
index 0000000..226cf7b
--- /dev/null
+++ b/src/lib/FL/Fl_Native_File_Chooser_WIN32.cxx
@@ -0,0 +1,765 @@
1//
2// Fl_Native_File_Chooser_WINDOWS.cxx -- FLTK native OS file chooser widget
3//
4// Copyright 2004 by Greg Ercolano.
5// April 2005 - API changes, improved filter processing by Nathan Vander Wilt
6//
7// This library is free software; you can redistribute it and/or
8// modify it under the terms of the GNU Library General Public
9// License as published by the Free Software Foundation; either
10// version 2 of the License, or (at your option) any later version.
11//
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15// Library General Public License for more details.
16//
17// You should have received a copy of the GNU Library General Public
18// License along with this library; if not, write to the Free Software
19// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20// USA.
21//
22// Please keep code 80 column compliant.
23//
24// 10 20 30 40 50 60 70
25// | | | | | | |
26// 4567890123456789012345678901234567890123456789012345678901234567890123456789
27//
28
29// http://www.codeproject.com/dialog/selectfolder.asp - any application to multi-folder implementation?
30
31#include <FL/Fl_Native_File_Chooser.H>
32#include <stdio.h> // debugging
33#include "common.cxx" // strnew/strfree/strapp/chrcat
34
35#define LCURLY_CHR '{'
36#define RCURLY_CHR '}'
37#define LBRACKET_CHR '['
38#define RBRACKET_CHR ']'
39#ifndef BIF_NONEWFOLDERBUTTON
40#define BIF_NONEWFOLDERBUTTON 0x200
41#endif
42// STATIC: PRINT WINDOWS 'DOUBLE NULL' STRING (DEBUG)
43/*
44static void dnullprint(char *wp) {
45 if ( ! wp ) return;
46 for ( int t=0; true; t++ ) {
47 if ( wp[t] == '\0' && wp[t+1] == '\0' ) {
48 printf("\\0\\0");
49 fflush(stdout);
50 return;
51 } else if ( wp[t] == '\0' ) {
52 printf("\\0");
53 } else {
54 printf("%c",wp[t]);
55 }
56 }
57}
58*/
59// RETURN LENGTH OF DOUBLENULL STRING
60// Includes single nulls in count, excludes trailing doublenull.
61//
62// 1234 567
63// |||/\|||
64// IN: "one\0two\0\0"
65// OUT: 7
66//
67static int dnulllen(const char *wp) {
68 int len = 0;
69 while ( ! ( *(wp+0) == 0 && *(wp+1) == 0 ) )
70 { ++wp; ++len; }
71 return(len);
72}
73
74// STATIC: Append a string to another, leaving terminated with DOUBLE NULL.
75// Automatically handles extending length of string.
76// wp can be NULL (a new wp will be allocated and initialized).
77// string must be NULL terminated.
78// The pointer wp may be modified on return.
79//
80static void dnullcat(char*&wp, const char *string, int n = -1 ) {
81 //DEBUG printf("DEBUG: dnullcat IN: <"); dnullprint(wp); printf(">\n");
82 int inlen = ( n < 0 ) ? strlen(string) : n;
83 if ( ! wp ) {
84 wp = new char[inlen + 4];
85 *(wp+0) = '\0';
86 *(wp+1) = '\0';
87 } else {
88 int wplen = dnulllen(wp);
89 // Make copy of wp into larger buffer
90 char *tmp = new char[wplen + inlen + 4];
91 memcpy(tmp, wp, wplen+2); // copy of wp plus doublenull
92 delete [] wp; // delete old wp
93 wp = tmp; // use new copy
94 //DEBUG printf("DEBUG: dnullcat COPY: <"); dnullprint(wp); printf("> (wplen=%d)\n", wplen);
95 }
96
97 // Find end of double null string
98 // *wp2 is left pointing at second null.
99 //
100 char *wp2 = wp;
101 if ( *(wp2+0) != '\0' && *(wp2+1) != '\0' ) {
102 for ( ; 1; wp2++ )
103 if ( *(wp2+0) == '\0' && *(wp2+1) == '\0' )
104 { wp2++; break; }
105 }
106
107 if ( n == -1 ) n = strlen(string);
108 strncpy(wp2, string, n);
109
110 // Leave string double-null terminated
111 *(wp2+n+0) = '\0';
112 *(wp2+n+1) = '\0';
113 //DEBUG printf("DEBUG: dnullcat OUT: <"); dnullprint(wp); printf(">\n\n");
114}
115
116// CTOR
117Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) {
118 _btype = val;
119 _options = NO_OPTIONS;
120 memset((void*)&_ofn, 0, sizeof(OPENFILENAME));
121 _ofn.lStructSize = sizeof(OPENFILENAME);
122 _ofn.hwndOwner = NULL;
123 memset((void*)&_binf, 0, sizeof(BROWSEINFO));
124 _pathnames = NULL;
125 _tpathnames = 0;
126 _directory = NULL;
127 _title = NULL;
128 _filter = NULL;
129 _parsedfilt = NULL;
130 _nfilters = 0;
131 _preset_file = NULL;
132 _errmsg = NULL;
133}
134
135// DTOR
136Fl_Native_File_Chooser::~Fl_Native_File_Chooser() {
137 //_pathnames // managed by clear_pathnames()
138 //_tpathnames // managed by clear_pathnames()
139 _directory = strfree(_directory);
140 _title = strfree(_title);
141 _filter = strfree(_filter);
142 //_parsedfilt // managed by clear_filters()
143 //_nfilters // managed by clear_filters()
144 _preset_file = strfree(_preset_file);
145 _errmsg = strfree(_errmsg);
146 clear_filters();
147 clear_pathnames();
148 ClearOFN();
149 ClearBINF();
150}
151
152// SET TYPE OF BROWSER
153void Fl_Native_File_Chooser::type(int val) {
154 _btype = val;
155}
156
157// GET TYPE OF BROWSER
158int Fl_Native_File_Chooser::type() const {
159 return( _btype );
160}
161
162// SET OPTIONS
163void Fl_Native_File_Chooser::options(int val) {
164 _options = val;
165}
166
167// GET OPTIONS
168int Fl_Native_File_Chooser::options() const {
169 return(_options);
170}
171
172// PRIVATE: SET ERROR MESSAGE
173void Fl_Native_File_Chooser::errmsg(const char *val) {
174 _errmsg = strfree(_errmsg);
175 _errmsg = strnew(val);
176}
177
178// FREE PATHNAMES ARRAY, IF IT HAS ANY CONTENTS
179void Fl_Native_File_Chooser::clear_pathnames() {
180 if ( _pathnames ) {
181 while ( --_tpathnames >= 0 ) {
182 _pathnames[_tpathnames] = strfree(_pathnames[_tpathnames]);
183 }
184 delete [] _pathnames;
185 _pathnames = NULL;
186 }
187 _tpathnames = 0;
188}
189
190// SET A SINGLE PATHNAME
191void Fl_Native_File_Chooser::set_single_pathname(const char *s) {
192 clear_pathnames();
193 _pathnames = new char*[1];
194 _pathnames[0] = strnew(s);
195 _tpathnames = 1;
196}
197
198// ADD PATHNAME TO EXISTING ARRAY
199void Fl_Native_File_Chooser::add_pathname(const char *s) {
200 if ( ! _pathnames ) {
201 // Create first element in array
202 ++_tpathnames;
203 _pathnames = new char*[_tpathnames];
204 } else {
205 // Grow array by 1
206 char **tmp = new char*[_tpathnames+1]; // create new buffer
207 memcpy((void*)tmp, (void*)_pathnames, sizeof(char*)*_tpathnames); // copy old
208 delete [] _pathnames; // delete old
209 _pathnames = tmp; // use new
210 ++_tpathnames;
211 }
212 _pathnames[_tpathnames-1] = strnew(s);
213}
214
215// FREE A PIDL (Pointer to IDentity List)
216void Fl_Native_File_Chooser::FreePIDL(ITEMIDLIST *pidl) {
217 IMalloc *imalloc = NULL;
218 if ( SUCCEEDED(SHGetMalloc(&imalloc)) )
219 { imalloc->Free(pidl); imalloc->Release(); imalloc = NULL; }
220}
221
222// CLEAR MICROSOFT OFN (OPEN FILE NAME) CLASS
223void Fl_Native_File_Chooser::ClearOFN() {
224 int temp;
225 // Free any previously allocated lpstrFile before zeroing out _ofn
226 if ( _ofn.lpstrFile )
227 { _ofn.lpstrFile = strfree((char*)_ofn.lpstrFile); }
228 if ( _ofn.lpstrInitialDir )
229 { _ofn.lpstrInitialDir = (LPCSTR)strfree((char*)_ofn.lpstrInitialDir); }
230 if ( _ofn.lpstrFile )
231 { _ofn.lpstrFile = strfree(_ofn.lpstrFile); }
232 _ofn.lpstrFilter = NULL; // (deleted elsewhere)
233 temp = _ofn.nFilterIndex; // keep the filter_value
234 memset((void*)&_ofn, 0, sizeof(_ofn));
235 _ofn.lStructSize = sizeof(OPENFILENAME);
236 _ofn.nFilterIndex = temp;
237}
238
239// CLEAR MICROSOFT BINF (BROWSER INFO) CLASS
240void Fl_Native_File_Chooser::ClearBINF() {
241 if ( _binf.pidlRoot ) {
242 FreePIDL((ITEMIDLIST*)_binf.pidlRoot);
243 _binf.pidlRoot = NULL;
244 }
245 memset((void*)&_binf, 0, sizeof(_binf));
246}
247
248// CONVERT WINDOWS BACKSLASHES TO UNIX FRONTSLASHES
249void Fl_Native_File_Chooser::Win2Unix(char *s) {
250 for ( ; *s; s++ )
251 if ( *s == '\\' ) *s = '/';
252}
253
254// CONVERT UNIX FRONTSLASHES TO WINDOWS BACKSLASHES
255void Fl_Native_File_Chooser::Unix2Win(char *s) {
256 for ( ; *s; s++ )
257 if ( *s == '/' ) *s = '\\';
258}
259
260// SHOW FILE BROWSER
261int Fl_Native_File_Chooser::showfile() {
262 ClearOFN();
263 clear_pathnames();
264 size_t fsize = 2048;
265 _ofn.Flags |= OFN_NOVALIDATE; // prevent disabling of front slashes
266 _ofn.Flags |= OFN_HIDEREADONLY; // hide goofy readonly flag
267 // USE NEW BROWSER
268 _ofn.Flags |= OFN_EXPLORER; // use newer explorer windows
269// // USE OLD BROWSER
270// _ofn.lpfnHook = MyHook;
271// _ofn.Flags |= OFN_ENABLEHOOK;
272 _ofn.Flags |= OFN_ENABLESIZING; // allow window to be resized (hey, why not?)
273
274 switch ( _btype ) {
275 case BROWSE_DIRECTORY:
276 case BROWSE_MULTI_DIRECTORY:
277 case BROWSE_SAVE_DIRECTORY:
278 abort(); // never happens: handled by showdir()
279 case BROWSE_FILE:
280 fsize = 65536; // XXX: there must be a better way
281 break;
282 case BROWSE_MULTI_FILE:
283 _ofn.Flags |= OFN_ALLOWMULTISELECT;
284 fsize = 65536; // XXX: there must be a better way
285 break;
286 case BROWSE_SAVE_FILE:
287 if ( options() & SAVEAS_CONFIRM && type() == BROWSE_SAVE_FILE ) {
288 _ofn.Flags |= OFN_OVERWRITEPROMPT;
289 }
290 break;
291 }
292 // SPACE FOR RETURNED FILENAME
293 _ofn.lpstrFile = new char[fsize];
294 _ofn.nMaxFile = fsize-1;
295 _ofn.lpstrFile[0] = '\0';
296 _ofn.lpstrFile[1] = '\0';
297 // PARENT WINDOW
298 _ofn.hwndOwner = GetForegroundWindow();
299 // DIALOG TITLE
300 _ofn.lpstrTitle = _title ? _title : NULL;
301 // FILTER
302 _ofn.lpstrFilter = _parsedfilt ? _parsedfilt : NULL;
303 // PRESET FILE
304 // If set, supercedes _directory. See KB Q86920 for details
305 //
306 if ( _preset_file ) {
307 int len = strlen(_preset_file);
308 char *strfile = new char[MAX_PATH]; // as per KB 222003 >8(
309 strcpy(strfile, _preset_file);
310 strfile[len+0] = '\0'; // (multiselect needs dnull)
311 strfile[len+1] = '\0';
312 Unix2Win(strfile);
313 _ofn.lpstrFile = strfile;
314 _ofn.nMaxFile = MAX_PATH; // as per KB 222003 >8(
315 }
316 if ( _directory ) {
317 // PRESET DIR
318 // XXX: See KB Q86920 for doc bug:
319 // http://support.microsoft.com/default.aspx?scid=kb;en-us;86920
320 //
321 if ( _directory ) {
322 _ofn.lpstrInitialDir = strnew(_directory);
323 Unix2Win((char*)_ofn.lpstrInitialDir);
324 }
325 }
326 // OPEN THE DIALOG WINDOW
327 int err;
328 if ( _btype == BROWSE_SAVE_FILE ) {
329 err = GetSaveFileName(&_ofn);
330 } else {
331 err = GetOpenFileName(&_ofn);
332 }
333 if ( err == 0 ) {
334 // EXTENDED ERROR CHECK
335 int err = CommDlgExtendedError();
336 // CANCEL?
337 if ( err == 0 )
338 return(1); // user hit 'cancel'
339 // AN ERROR OCCURRED
340 char msg[80];
341 sprintf(msg, "CommDlgExtendedError() code=%d", err);
342 errmsg(msg);
343 return(-1);
344 }
345 // PREPARE PATHNAMES FOR RETURN
346 switch ( _btype ) {
347 case BROWSE_FILE:
348 case BROWSE_SAVE_FILE:
349 set_single_pathname(_ofn.lpstrFile);
350 Win2Unix(_pathnames[_tpathnames-1]);
351 break;
352 case BROWSE_MULTI_FILE: {
353 // EXTRACT MULTIPLE FILENAMES
354 const char *dirname = _ofn.lpstrFile;
355 int dirlen = strlen(dirname);
356 if ( dirlen > 0 ) {
357 char pathname[2048];
358
359 // WALK STRING SEARCHING FOR 'DOUBLE-NULL'
360 // eg. "/dir/name\0foo1\0foo2\0foo3\0\0"
361 //
362 for ( const char *s = _ofn.lpstrFile + dirlen + 1;
363 *s; s+= (strlen(s)+1)) {
364 strcpy(pathname, dirname);
365 strcat(pathname, "\\");
366 strcat(pathname, s);
367 add_pathname(pathname);
368 Win2Unix(_pathnames[_tpathnames-1]);
369 }
370 }
371 // XXX
372 // Work around problem where pasted forward-slash pathname
373 // into the file browser causes new "Explorer" interface
374 // not to grok forward slashes, passing back as a 'filename'..!
375 //
376 if ( _tpathnames == 0 ) {
377 add_pathname(dirname);
378 Win2Unix(_pathnames[_tpathnames-1]);
379 }
380 break;
381 }
382 case BROWSE_DIRECTORY:
383 case BROWSE_MULTI_DIRECTORY:
384 case BROWSE_SAVE_DIRECTORY:
385 abort(); // not here
386 }
387 return(0);
388}
389
390// Used by SHBrowseForFolder(), sets initial selected dir.
391// Ref: Usenet: microsoft.public.vc.mfc, Dec 8 2000, 1:38p David Lowndes
392// Subject: How to specify to select an initial folder .."
393//
394int CALLBACK Fl_Native_File_Chooser::Dir_CB(HWND win, UINT msg, LPARAM param, LPARAM data) {
395 switch (msg) {
396 case BFFM_INITIALIZED:
397 if (data) ::SendMessage(win, BFFM_SETSELECTION, TRUE, data);
398 break;
399 case BFFM_SELCHANGED:
400 TCHAR path[MAX_PATH];
401 if ( SHGetPathFromIDList((ITEMIDLIST*)param, path) ) {
402 ::SendMessage(win, BFFM_ENABLEOK, 0, 1);
403 } else {
404 //disable ok button if not a path
405 ::SendMessage(win, BFFM_ENABLEOK, 0, 0);
406 }
407 break;
408 case BFFM_VALIDATEFAILED:
409 // we could pop up an annoying message here.
410 // also needs set ulFlags |= BIF_VALIDATE
411 break;
412 default:
413 break;
414 }
415 return(0);
416}
417
418// SHOW DIRECTORY BROWSER
419int Fl_Native_File_Chooser::showdir() {
420 OleInitialize(NULL); // init needed by BIF_USENEWUI
421 ClearBINF();
422 clear_pathnames();
423 // PARENT WINDOW
424 _binf.hwndOwner = GetForegroundWindow();
425 // DIALOG TITLE
426 _binf.lpszTitle = _title ? _title : NULL;
427 // FLAGS
428 _binf.ulFlags =0; // initialize
429
430 // TBD: make sure matches to runtime system, if need be.
431 //( what if _WIN32_IE doesn't match system? does the program not run? )
432 // TBD: match all 3 types of directories
433
434#if defined(BIF_NONEWFOLDERBUTTON) // Version 6.0
435 if ( _btype == BROWSE_DIRECTORY ) _binf.ulFlags &= !BIF_NONEWFOLDERBUTTON;
436 _binf.ulFlags |= BIF_USENEWUI | BIF_SHAREABLE | BIF_RETURNONLYFSDIRS;
437#elif defined(BIF_USENEWUI) // Version 5.0
438 if ( _btype == BROWSE_DIRECTORY ) _binf.ulFlags |= BIF_EDITBOX;
439 else if ( _btype == BROWSE_SAVE_DIRECTORY ) _binf.ulFlags |= BIF_USENEWUI;
440 _binf.ulFlags |= BIF_SHAREABLE | BIF_RETURNONLYFSDIRS;
441#elif defined(BIF_EDITBOX) // Version 4.71
442 _binf.ulFlags |= BIF_RETURNONLYFSDIRS | BIF_EDITBOX;
443#else // Version Old
444 _binf.ulFlags |= BIF_RETURNONLYFSDIRS;
445#endif
446
447
448 // BUFFER
449 char displayname[MAX_PATH];
450 _binf.pszDisplayName = displayname;
451 // PRESET DIR
452 char presetname[MAX_PATH];
453 if ( _directory ) {
454 strcpy(presetname, _directory);
455 Unix2Win(presetname);
456 _binf.lParam = (LPARAM)presetname;
457 }
458 else _binf.lParam = 0;
459 _binf.lpfn = Dir_CB;
460 // OPEN BROWSER
461 ITEMIDLIST *pidl = SHBrowseForFolder(&_binf);
462 // CANCEL?
463 if ( pidl == NULL ) return(1);
464
465 // GET THE PATHNAME(S) THE USER SELECTED
466 // TBD: expand NetHood shortcuts from this PIDL??
467 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/functions/shbrowseforfolder.asp
468
469 TCHAR path[MAX_PATH];
470 if ( SHGetPathFromIDList(pidl, path) )
471 { Win2Unix(path); add_pathname(path); }
472 FreePIDL(pidl);
473 if ( !strlen(path) ) return(1); // don't return empty pathnames
474 return(0);
475}
476
477// RETURNS:
478// 0 - user picked a file
479// 1 - user cancelled
480// -1 - failed; errmsg() has reason
481//
482int Fl_Native_File_Chooser::show() {
483 if ( _btype == BROWSE_DIRECTORY ||
484 _btype == BROWSE_MULTI_DIRECTORY ||
485 _btype == BROWSE_SAVE_DIRECTORY )
486 return(showdir());
487 else
488 return(showfile());
489}
490
491// RETURN ERROR MESSAGE
492const char *Fl_Native_File_Chooser::errmsg() const {
493 return(_errmsg ? _errmsg : "No error");
494}
495
496// GET FILENAME
497const char* Fl_Native_File_Chooser::filename() const {
498 if ( _pathnames && _tpathnames > 0 ) return(_pathnames[0]);
499 return("");
500}
501
502// GET FILENAME FROM LIST OF FILENAMES
503const char* Fl_Native_File_Chooser::filename(int i) const {
504 if ( _pathnames && i < _tpathnames ) return(_pathnames[i]);
505 return("");
506}
507
508// GET TOTAL FILENAMES CHOSEN
509int Fl_Native_File_Chooser::count() const {
510 return(_tpathnames);
511}
512
513// PRESET PATHNAME
514// Can be NULL if no preset is desired.
515//
516void Fl_Native_File_Chooser::directory(const char *val) {
517 _directory = strfree(_directory);
518 _directory = strnew(val);
519}
520
521// GET PRESET PATHNAME
522// Can return NULL if none set.
523//
524const char *Fl_Native_File_Chooser::directory() const {
525 return(_directory);
526}
527
528// SET TITLE
529// Can be NULL if no title desired.
530//
531void Fl_Native_File_Chooser::title(const char *val) {
532 _title = strfree(_title);
533 _title = strnew(val);
534}
535
536// GET TITLE
537// Can return NULL if none set.
538//
539const char *Fl_Native_File_Chooser::title() const {
540 return(_title);
541}
542
543// SET FILTER
544// Can be NULL if no filter needed
545//
546void Fl_Native_File_Chooser::filter(const char *val) {
547 _filter = strfree(_filter);
548 clear_filters();
549 if ( val ) {
550 _filter = strnew(val);
551 parse_filter(_filter);
552 }
553 add_filter("All Files", "*.*"); // always include 'all files' option
554
555#ifdef DEBUG
556 nullprint(_parsedfilt);
557#endif /*DEBUG*/
558}
559
560// GET FILTER
561// Can return NULL if none set.
562//
563const char *Fl_Native_File_Chooser::filter() const {
564 return(_filter);
565}
566
567// CLEAR FILTERS
568void Fl_Native_File_Chooser::clear_filters() {
569 _nfilters = 0;
570 _parsedfilt = strfree(_parsedfilt);
571}
572
573// ADD A FILTER
574void Fl_Native_File_Chooser::add_filter(
575 const char *name_in, // name of filter (optional: can be null)
576 const char *winfilter // windows style filter (eg. "*.cxx;*.h")
577 ) {
578 // No name? Make one..
579 char name[1024];
580 if ( !name_in || name_in[0] == '\0' ) {
581 sprintf(name, "%.*s Files", sizeof(name)-10, winfilter);
582 } else {
583 sprintf(name, "%.*s", sizeof(name)-10, name_in);
584 }
585 dnullcat(_parsedfilt, name);
586 dnullcat(_parsedfilt, winfilter);
587 //DEBUG printf("DEBUG: ADD FILTER name=<%s> winfilter=<%s>\n", name, winfilter);
588}
589
590// CONVERT FLTK STYLE PATTERN MATCHES TO WINDOWS 'DOUBLENULL' PATTERN
591// Handles:
592// IN OUT
593// ----------- -----------------------------
594// *.{ma,mb} "*.{ma,mb} Files\0*.ma;*.mb\0\0"
595// *.[abc] "*.[abc] Files\0*.a;*.b;*.c\0\0"
596// *.txt "*.txt Files\0*.txt\0\0"
597// C Files\t*.[ch] "C Files\0*.c;*.h\0\0"
598//
599// Example:
600// IN: "*.{ma,mb}"
601// OUT: "*.ma;*.mb Files\0*.ma;*.mb\0All Files\0*.*\0\0"
602// --------------- --------- --------- ---
603// | | | |
604// Title Wildcards Title Wildcards
605//
606// Parsing Mode:
607// IN:"C Files\t*.{cxx,h}"
608// ||||||| |||||||||
609// mode: nnnnnnn ww{{{{{{{
610// \_____/ \_______/
611// Name Wildcard
612//
613void Fl_Native_File_Chooser::parse_filter(const char *in) {
614 clear_filters();
615 if ( ! in ) return;
616
617 int has_name = strchr(in, '\t') ? 1 : 0;
618 //const char *savein = in;
619
620 char mode = has_name ? 'n' : 'w'; // parse mode: n=name, w=wildcard
621 int nwildcards = 0;
622 char wildcards[MAXFILTERS][1024]; // parsed wildcards (can be several)
623 char wildprefix[512] = "";
624 char name[512] = "";
625
626 // Init
627 int t;
628 for ( t=0; t<MAXFILTERS; t++ ) {
629 wildcards[t][0] = '\0';
630 }
631
632 // Parse
633 for ( ; 1; in++ ) {
634
635 //// DEBUG
636 //// printf("WORKING ON '%c': mode=<%c> name=<%s> wildprefix=<%s> nwildcards=%d wildcards[n]=<%s>\n",
637 //// *in, mode, name, wildprefix, nwildcards, wildcards[nwildcards]);
638
639 switch (*in) {
640 case ',':
641 case '|':
642 if ( mode == LCURLY_CHR ) {
643 // create new wildcard, copy in prefix
644 strcat(wildcards[nwildcards++], wildprefix);
645 continue;
646 } else {
647 goto regchar;
648 }
649 continue;
650
651 // FINISHED PARSING A NAME?
652 case '\t':
653 if ( mode != 'n' ) goto regchar;
654 // finish parsing name? switch to wildcard mode
655 mode = 'w';
656 break;
657
658 // ESCAPE NEXT CHAR
659 case '\\':
660 ++in;
661 goto regchar;
662
663 // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS?
664 case '\r':
665 case '\n':
666 case '\0':
667 {
668 if ( mode == 'w' ) { // finished parsing wildcard?
669 if ( nwildcards == 0 ) {
670 strcpy(wildcards[nwildcards++], wildprefix);
671 }
672 // Append wildcards in Microsoft's "*.one;*.two" format
673 char comp[4096] = "";
674 for ( t=0; t<nwildcards; t++ ) {
675 if ( t != 0 ) strcat(comp, ";");
676 strcat(comp, wildcards[t]);
677 }
678 // Add if not empty
679 if ( comp[0] ) {
680 add_filter(name, comp);
681 }
682 }
683 // RESET
684 for ( t=0; t<MAXFILTERS; t++ ) {
685 wildcards[t][0] = '\0';
686 }
687 nwildcards = 0;
688 wildprefix[0] = name[0] = '\0';
689 mode = strchr(in,'\t') ? 'n' : 'w';
690 // DONE?
691 if ( *in == '\0' ) return; // done
692 continue; // not done yet, more filters
693 }
694
695 // STARTING A WILDCARD?
696 case LBRACKET_CHR:
697 case LCURLY_CHR:
698 mode = *in;
699 if ( *in == LCURLY_CHR ) {
700 // create new wildcard
701 strcat(wildcards[nwildcards++], wildprefix);
702 }
703 continue;
704
705 // ENDING A WILDCARD?
706 case RBRACKET_CHR:
707 case RCURLY_CHR:
708 mode = 'w'; // back to wildcard mode
709 continue;
710
711 // ALL OTHER NON-SPECIAL CHARACTERS
712 default:
713 regchar: // handle regular char
714 switch ( mode ) {
715 case LBRACKET_CHR:
716 // create new wildcard
717 ++nwildcards;
718 // copy in prefix
719 strcpy(wildcards[nwildcards-1], wildprefix);
720 // append search char
721 chrcat(wildcards[nwildcards-1], *in);
722 continue;
723
724 case LCURLY_CHR:
725 if ( nwildcards > 0 ) {
726 chrcat(wildcards[nwildcards-1], *in);
727 }
728 continue;
729
730 case 'n':
731 chrcat(name, *in);
732 continue;
733
734 case 'w':
735 chrcat(wildprefix, *in);
736 for ( t=0; t<nwildcards; t++ ) {
737 chrcat(wildcards[t], *in);
738 }
739 continue;
740 }
741 break;
742 }
743 }
744}
745
746// SET 'CURRENTLY SELECTED FILTER'
747void Fl_Native_File_Chooser::filter_value(int i) {
748 _ofn.nFilterIndex = i + 1;
749}
750
751// RETURN VALUE OF 'CURRENTLY SELECTED FILTER'
752int Fl_Native_File_Chooser::filter_value() const {
753 return(_ofn.nFilterIndex ? _ofn.nFilterIndex-1 : _nfilters+1);
754}
755
756// PRESET FILENAME FOR 'SAVE AS' CHOOSER
757void Fl_Native_File_Chooser::preset_file(const char* val) {
758 _preset_file = strfree(_preset_file);
759 _preset_file = strnew(val);
760}
761
762// GET PRESET FILENAME FOR 'SAVE AS' CHOOSER
763const char* Fl_Native_File_Chooser::preset_file() const {
764 return(_preset_file);
765}
diff --git a/src/lib/FL/WidgetPDial.fl b/src/lib/FL/WidgetPDial.fl
new file mode 100644
index 0000000..5b7ec05
--- /dev/null
+++ b/src/lib/FL/WidgetPDial.fl
@@ -0,0 +1,131 @@
1# data file for the Fltk User Interface Designer (fluid)
2version 1.0105
3header_name {.h}
4code_name {.cc}
5decl {//Copyright (c) 2003-2005 Nasca Octavian Paul} {}
6
7decl {//License: GNU GPL version 2 or later} {}
8
9decl {\#include <FL/Fl_Dial.H>} {public
10}
11
12decl {\#include <FL/fl_draw.H>} {public
13}
14
15decl {\#include <stdio.h>} {public
16}
17
18decl {\#include <math.h>} {public
19}
20
21class WidgetPDial {: {public Fl_Dial}
22} {
23 Function {WidgetPDial(int x,int y, int w, int h, const char *label=0):Fl_Dial(x,y,w,h,label)} {} {
24 code {oldvalue=0.0;} {}
25 }
26 Function {handle(int event)} {return_type int
27 } {
28 code {double dragsize,v,min=minimum(),max=maximum();
29int my;
30
31switch (event){
32case FL_PUSH:oldvalue=value();
33case FL_DRAG:
34 my=-(Fl::event_y()-y()-h()/2);
35
36 dragsize=200.0;
37 if (Fl::event_state(FL_BUTTON1)==0) dragsize*=10;
38 v=oldvalue+my/dragsize*(max-min);
39 if (v<min) v=min;
40 else if (v>max) v=max;
41
42 //printf("%d %g %g\\n",my,v,oldvalue);
43 value(v);
44 value_damage();
45 if (this->when()!=0) do_callback();
46 return(1);
47 break;
48case FL_RELEASE:
49 if (this->when()==0) do_callback();
50 return(1);
51 break;
52};
53return(0);} {selected
54 }
55 }
56 Function {drawgradient(int cx,int cy,int sx,double m1,double m2)} {return_type void
57 } {
58 code {for (int i=(int)(m1*sx);i<(int)(m2*sx);i++){
59 double tmp=1.0-pow(i*1.0/sx,2.0);
60 pdialcolor(140+(int) (tmp*90),140+(int)(tmp*90),140+(int) (tmp*100));
61 fl_arc(cx+sx/2-i/2,cy+sx/2-i/2,i,i,0,360);
62};} {}
63 }
64 Function {draw()} {} {
65 code {int cx=x(),cy=y(),sx=w(),sy=h();
66
67
68//clears the button face
69pdialcolor(190,190,200);
70fl_pie(cx-1,cy-1,sx+2,sy+2,0,360);
71
72//Draws the button face (gradinet)
73drawgradient(cx,cy,sx,0.5,1.0);
74
75double val=(value()-minimum())/(maximum()-minimum());
76
77//draws the scale
78pdialcolor(220,220,250);
79double a1=angle1(),a2=angle2();
80for (int i=0;i<12;i++){
81 double a=-i/12.0*360.0-val*(a2-a1)-a1;
82 fl_pie(cx,cy,sx,sy,a+270-3,a+3+270);
83};
84
85drawgradient(cx,cy,sx,0.0,0.75);
86
87//draws the value
88double a=-(a2-a1)*val-a1;
89
90
91
92
93
94//draws the max and min points
95pdialcolor(0,100,200);
96int xp=(int)(cx+sx/2.0+sx/2.0*sin(angle1()/180.0*3.141592));
97int yp=(int)(cy+sy/2.0+sy/2.0*cos(angle1()/180.0*3.141592));
98fl_pie(xp-2,yp-2,4,4,0,360);
99
100xp=(int)(cx+sx/2.0+sx/2.0*sin(angle2()/180.0*3.141592));
101yp=(int)(cy+sy/2.0+sy/2.0*cos(angle2()/180.0*3.141592));
102fl_pie(xp-2,yp-2,4,4,0,360);
103
104
105
106
107
108fl_push_matrix();
109
110 fl_translate(cx+sx/2,cy+sy/2);
111 fl_rotate(a-90.0);
112
113 fl_translate(sx/2,0);
114
115
116 fl_begin_polygon();
117 pdialcolor(0,0,0);
118 fl_vertex(-10,-4);
119 fl_vertex(-10,4);
120 fl_vertex(0,0);
121 fl_end_polygon();
122
123
124fl_pop_matrix();} {}
125 }
126 Function {pdialcolor(int r,int g,int b)} {} {
127 code {if (active_r()) fl_color(r,g,b);
128 else fl_color(160-(160-r)/3,160-(160-b)/3,160-(160-b)/3);} {}
129 }
130 decl {double oldvalue;} {}
131}
diff --git a/src/lib/FL/common.cxx b/src/lib/FL/common.cxx
new file mode 100644
index 0000000..852b0e7
--- /dev/null
+++ b/src/lib/FL/common.cxx
@@ -0,0 +1,60 @@
1// COPY A STRING WITH 'new'
2// Value can be NULL
3//
4static char *strnew(const char *val)
5{
6 if ( val == NULL )
7 return(NULL);
8
9 char *s = new char[strlen(val)+1];
10 strcpy(s, val);
11
12 return(s);
13}
14
15// FREE STRING CREATED WITH strnew(), NULLS OUT STRING
16// Value can be NULL
17//
18static char *strfree(char *val)
19{
20 if ( val )
21 delete [] val;
22
23 return(NULL);
24}
25
26// 'DYNAMICALLY' APPEND ONE STRING TO ANOTHER
27// Returns newly allocated string, or NULL
28// if s && val == NULL.
29// 's' can be NULL; returns a strnew(val).
30// 'val' can be NULL; s is returned unmodified.
31//
32// Usage:
33// char *s = strnew("foo"); // s = "foo"
34// s = strapp(s, "bar"); // s = "foobar"
35//
36#ifndef WINDOWS
37static char *strapp(char *s, const char *val)
38{
39 if ( ! val )
40 return(s); // Nothing to append? return s
41
42 if ( ! s )
43 return(strnew(val)); // New string? return copy of val
44
45 char *news = new char[strlen(s)+strlen(val)+1];
46 strcpy(news, s);
47 strcat(news, val);
48
49 delete [] s; // delete old string
50 return(news); // return new copy
51}
52#endif
53// APPEND A CHARACTER TO A STRING
54static void chrcat(char *s, char c)
55{
56 char tmp[2] = { c, '\0' };;
57 strcat(s, tmp);
58}
59
60
diff --git a/src/lib/config.h b/src/lib/config.h
new file mode 100755
index 0000000..cd5e634
--- /dev/null
+++ b/src/lib/config.h
@@ -0,0 +1,11 @@
1#ifdef WINDOWS
2# define __sint64 signed __int64
3# define __uint64 unsigned __int64
4#else
5# define __sint64 signed long long
6# define __uint64 unsigned long long
7#endif
8
9#define __sint32 signed long
10#define __uint32 unsigned long
11
diff --git a/src/lib/convertlib.cpp b/src/lib/convertlib.cpp
new file mode 100755
index 0000000..ebbfaff
--- /dev/null
+++ b/src/lib/convertlib.cpp
@@ -0,0 +1,311 @@
1#include <stdlib.h>
2#include "convertlib.h"
3
4bool Convert::isnibble(string x)
5{
6 if ((x >= "0") && (x <= "9")) return true;
7 if ((x >= "a") && (x <= "f")) return true;
8 if ((x >= "A") && (x <= "F")) return true;
9 return false;
10}
11
12string* Convert::byte2hex(unsigned char x)
13{
14 int b = x % 16;
15 int a = x >> 4;
16
17 string hex = "0123456789ABCDEF";
18 string * newst = new string("");
19 *newst = *newst + hex.substr(a, 1);
20 *newst = *newst + hex.substr(b, 1);
21 return newst;
22}
23
24long Convert::str2long(string decstr)
25{
26 return strtol(decstr.c_str(), 0, 10);
27}
28
29double Convert::str2dbl(string decstr)
30{
31 return strtod(decstr.c_str(), 0);
32}
33
34string* Convert::int2str(int x, unsigned int pad, string padchar)
35{
36 string* newst = int2str(x);
37
38 if (pad > 1)
39 {
40 while (newst->length() < pad)
41 {
42 *newst = padchar + *newst;
43 }
44 }
45
46 return newst;
47}
48
49string* Convert::int64tostr(__sint64 x)
50{
51 bool isneg=false;
52 string * newst = new string("");
53 if (x == 0)
54 {
55 *newst = "0";
56 }
57 else
58 {
59 if (x<0)
60 {
61 isneg=true;
62 x=0-x;
63 }
64 while (x != 0)
65 {
66 long long digit = x % (long long) 10;
67 string dec = "0123456789";
68 *newst = dec.substr(digit, 1) + *newst;
69
70 x -= (long long) (x % (long long) 10);
71 x /= (long long) 10;
72 }
73 }
74 if (isneg)
75 {
76 *newst="-"+*newst;
77 }
78 return newst;
79}
80
81string* Convert::int2str(int x)
82{
83 long long y = x;
84 return int64tostr(y);
85}
86
87string* Convert::int32tostr(__uint32 x)
88{
89 long long y = x;
90 return int64tostr(y);
91}
92
93long Convert::hex2long(string hexstr)
94{
95 return strtol(hexstr.c_str(), 0, 16);
96}
97
98unsigned char Convert::hex2byte(string hexstr)
99{
100 long x = hex2long(hexstr);
101 return (unsigned char) x % 256;
102}
103
104unsigned char Convert::safebyte(unsigned char x)
105{
106 if (x < 32) return '.';
107 return x;
108}
109
110string* Convert::int64tohex(__sint64 x)
111{
112 __sint64 q = x;
113 unsigned char a = q % 256; q = q >> 8;
114 unsigned char b = q % 256; q = q >> 8;
115 unsigned char c = q % 256; q = q >> 8;
116 unsigned char d = q % 256; q = q >> 8;
117 unsigned char e = q % 256; q = q >> 8;
118 unsigned char f = q % 256; q = q >> 8;
119 unsigned char g = q % 256; q = q >> 8;
120 unsigned char h = q % 256;
121 string* b2h8 = byte2hex(h);
122 string* b2h7 = byte2hex(g);
123 string* b2h6 = byte2hex(f);
124 string* b2h5 = byte2hex(e);
125 string* b2h4 = byte2hex(d);
126 string* b2h3 = byte2hex(c);
127 string* b2h2 = byte2hex(b);
128 string* b2h1 = byte2hex(a);
129 string* newst = new string();
130 *newst += *b2h8 + *b2h7 + ":" + *b2h6 + *b2h5 + "." + *b2h4 + *b2h3 + ":" + *b2h2 + *b2h1;
131 delete (b2h1);
132 delete (b2h2);
133 delete (b2h3);
134 delete (b2h4);
135 delete (b2h5);
136 delete (b2h6);
137 delete (b2h7);
138 delete (b2h8);
139 return newst;
140}
141
142string* Convert::int32tohex(unsigned long x)
143{
144 __sint64 q = x;
145 unsigned char a = q % 256; q = q >> 8;
146 unsigned char b = q % 256; q = q >> 8;
147 unsigned char c = q % 256; q = q >> 8;
148 unsigned char d = q % 256; q = q >> 8;
149 string* b2h4 = byte2hex(d);
150 string* b2h3 = byte2hex(c);
151 string* b2h2 = byte2hex(b);
152 string* b2h1 = byte2hex(a);
153 string* newst = new string();
154 *newst += *b2h4 + *b2h3 + ":" + *b2h2 + *b2h1;
155 delete (b2h1);
156 delete (b2h2);
157 delete (b2h3);
158 delete (b2h4);
159 return newst;
160}
161
162unsigned int Convert::getint24(unsigned char * buf, int loc)
163{
164 unsigned int q = 0;
165
166 q = buf[loc + 2]
167 + (buf[loc + 1] << 8)
168 + (buf [loc + 0] << 16);
169 return q;
170}
171
172
173unsigned int Convert::getint32(unsigned char * buf, int loc)
174{
175 unsigned int q = 0;
176
177 q = buf[loc + 3]
178 + (buf[loc + 2] << 8)
179 + (buf [loc + 1] << 16)
180 + (buf [loc] << 24);
181 return q;
182}
183
184void Convert::setint32(unsigned char * buf, int loc, __uint32 newval)
185{
186 buf[loc + 0] = (newval >> 24) % 256;
187 buf[loc + 1] = (newval >> 16) % 256;
188 buf[loc + 2] = (newval >> 8) % 256;
189 buf[loc + 3] = newval % 256;
190}
191
192void Convert::setfloat80(unsigned char * buf, int loc, __uint32 newval)
193{
194 /* Thanks, Erik */
195 unsigned int mask = 0x40000000 ;
196 int count ;
197
198 for (int i=0;i<10;i++)
199 {
200 buf[loc+i]=0;
201 }
202 if (newval <= 1)
203 { buf[loc+0] = 0x3F ;
204 buf[loc+1] = 0xFF ;
205 buf[loc+2] = 0x80 ;
206 return ;
207 } ;
208
209 buf[loc+0] = 0x40 ;
210
211 if (newval >= mask)
212 { buf[loc+1] = 0x1D ;
213 return ;
214 } ;
215
216 for (count = 0 ; count <= 32 ; count ++)
217 { if (newval & mask)
218 break ;
219 mask >>= 1 ;
220 } ;
221
222 newval <<= count + 1 ;
223 buf[loc+1] = 29 - count ;
224 buf[loc+2] = (newval >> 24) & 0xFF ;
225 buf[loc+3] = (newval >> 16) & 0xFF ;
226 buf[loc+4] = (newval >> 8) & 0xFF ;
227 buf[loc+5] = newval & 0xFF ;
228 return;
229}
230
231string* Convert::readstring(unsigned char * orig, int offset, int len)
232{
233 string * newst = new string("");
234 int i;
235
236 for (i = offset; i < offset + len; i++)
237 {
238 if (i >= offset + len)
239 return newst;
240
241 if (orig[i] == 0) break;
242 *newst += orig[i];
243 }
244
245 return newst;
246}
247
248string* Convert::padright(string & strinput, int inlen, string strpad)
249{
250 int currlen = strinput.length();
251
252 if (currlen > inlen)
253 {
254 strinput=strinput.substr(0,inlen);
255 return new string(strinput);
256 }
257
258 int pad = inlen - currlen;
259 if (pad > 0)
260 {
261 for (int i = 0; i < pad; i++)
262 {
263 strinput += strpad;
264 }
265 }
266
267 return new string(strinput);
268}
269
270string* Convert::padleft(string & strinput, int inlen, string strpad)
271{
272 int currlen = strinput.length();
273
274 if (currlen > inlen)
275 {
276 return new string(strinput.substr(0, inlen));
277 }
278
279 int pad = inlen - currlen;
280 if (pad > 0)
281 {
282 string strtmp = "";
283 for (int i = 0; i < pad; i++)
284 {
285 strtmp += strpad;
286 }
287 strinput = strtmp + strinput;
288 }
289 return new string(strinput);
290}
291
292string* Convert::trim(string* strinput)
293{
294 if (strinput->length() == 0)
295 {
296 string* x = new string("");
297 return x;
298 }
299
300 string* strresult = new string(*strinput);
301 while (strresult->substr(0, 1) == " ")
302 {
303 *strresult = strresult->substr(1, strresult->length() - 1);
304 }
305
306 while (strresult->substr(strresult->length() - 1, 1) == " ")
307 {
308 *strresult = strresult->substr(0, strresult->length() - 1);
309 }
310 return strresult;
311}
diff --git a/src/lib/convertlib.h b/src/lib/convertlib.h
new file mode 100755
index 0000000..3e742ff
--- /dev/null
+++ b/src/lib/convertlib.h
@@ -0,0 +1,39 @@
1#ifndef __convert_h__
2#define __convert_h__
3
4using namespace std;
5
6#include "config.h"
7#include <string>
8#include <iostream>
9
10class Convert
11{
12 public:
13 Convert() {};
14 ~Convert() {};
15
16 static bool isnibble(string x);
17 static long str2long(string hexstr);
18 static double str2dbl(string hexstr);
19 static long hex2long(string hexstr);
20 static string* byte2hex(unsigned char x);
21 static string* int2str(int x,unsigned int pad,string padchar);
22 static string* int2str(int x);
23 static string* int32tostr(__uint32 x);
24 static string* int64tostr(__sint64 x);
25 static string* int64tohex(__sint64 x);
26 static string* int32tohex(unsigned long x);
27 static string* readstring(unsigned char * orig,int offset,int len);
28 static string* padright(string & strinput,int inlen,string strpad);
29 static string* padleft(string & strinput,int inlen,string strpad);
30 static unsigned int getint32(unsigned char * buf,int loc);
31 static unsigned int getint24(unsigned char * buf,int loc);
32 static void setint32(unsigned char * buf,int loc,__uint32 newval);
33 static void setfloat80(unsigned char * buf, int loc, __uint32 newval); /* Only for use in AIFF files */
34 static unsigned char hex2byte(string hexstr);
35 static unsigned char safebyte(unsigned char x);
36 static string* trim(string* strinput);
37};
38
39#endif
diff --git a/src/lib/hd24devicenamegenerator.cpp b/src/lib/hd24devicenamegenerator.cpp
new file mode 100644
index 0000000..99ad4a7
--- /dev/null
+++ b/src/lib/hd24devicenamegenerator.cpp
@@ -0,0 +1,286 @@
1#include "hd24devicenamegenerator.h"
2#define DEVGENDEBUG 0
3#include <stdio.h>
4#include <string.h>
5#include <stdlib.h>
6#ifdef DARWIN
7#include <sys/malloc.h>
8#else
9#include <malloc.h>
10#endif
11#include <sys/types.h>
12#include <dirent.h>
13int endswith(const char* str, const char* end)
14{
15#if (DEVGENDEBUG==1)
16cout << "endswith("<<str<<","<<end<<")"<<endl;
17#endif
18 if (str==NULL) return false;
19 if (end==NULL) return false;
20 size_t str_len = strlen(str);
21 size_t end_len = strlen(end);
22 if (str_len<end_len) return false;
23
24 const char *str_end = str + str_len - end_len;
25 return strcmp(str_end, end) == 0;
26}
27
28__uint32 hd24devicenamegenerator::hd24filecount(const char* dirname)
29{
30#if (DEVGENDEBUG==1)
31cout << "hd24devicenamegenerator::hd24filecount("<<dirname<<")"<< endl;
32#endif
33 unsigned char isFile =0x8;
34 DIR *Dir;
35 struct dirent *DirEntry;
36 Dir = opendir(dirname);
37
38 int foundcount=0;
39 do
40 {
41 DirEntry=readdir(Dir);
42 if (!DirEntry) break;
43 if ( DirEntry->d_type != isFile) continue;
44
45 if (!( endswith(DirEntry->d_name,".h24")
46 ||endswith(DirEntry->d_name,".H24"))) continue;
47
48 foundcount++;
49
50 if (filelist==NULL)
51 {
52 filelist=new vector<string>();
53 }
54 string* fname=new string(dirname);
55 *fname+=DirEntry->d_name;
56 filelist->push_back(*fname);
57#if (DEVGENDEBUG==1)
58 cout <<"Found a File : " << *fname << endl;
59#endif
60 delete fname;
61
62 // validity of file image will be extablished by hd24fs device scan
63 } while(1);
64
65 return foundcount;
66}
67
68void hd24devicenamegenerator::initvars()
69{
70 imagespath=NULL;
71 filelist=NULL;
72 filecount=0; // cache for getnumberoffiles
73}
74
75void hd24devicenamegenerator::clearfilelist()
76{
77 if (filelist==NULL)
78 {
79 return;
80 }
81 while (filelist->size()!=0)
82 {
83 filelist->pop_back();
84 }
85 delete filelist;
86 filelist=NULL;
87}
88
89hd24devicenamegenerator::~hd24devicenamegenerator()
90{
91 clearfilelist();
92}
93hd24devicenamegenerator::hd24devicenamegenerator()
94{
95 initvars();
96}
97
98const char* hd24devicenamegenerator::imagedir()
99{
100#if (DEVGENDEBUG==1)
101cout << "hd24devicenamegenerator::imagedir()"<<endl;
102#endif
103 return imagespath;
104}
105
106const char* hd24devicenamegenerator::imagedir(const char* newdir)
107{
108#if (DEVGENDEBUG==1)
109if (newdir==NULL)
110{
111 cout << "hd24devicenamegenerator::imagedir(NULL)"<< endl;
112}
113else
114{
115 cout << "hd24devicenamegenerator::imagedir("<<newdir<<")"<< endl;
116}
117#endif
118
119 filecount=0;
120 clearfilelist();
121
122 if (imagespath!=NULL)
123 {
124 free (imagespath);
125 imagespath=NULL;
126 }
127
128 if (newdir!=NULL)
129 {
130 imagespath=(char*)malloc(strlen(newdir)+1);
131 if (imagespath!=NULL)
132 {
133 strncpy(imagespath,newdir,strlen(newdir)+1);
134 }
135#if (DEVGENDEBUG==1)
136 cout << "new images path is " ;
137 if (imagespath==NULL)
138 {
139 cout << "NULL" << endl;
140 } else {
141 cout << imagespath << endl;
142 }
143#endif
144 }
145
146 return (const char*)imagespath;
147}
148
149__uint32 hd24devicenamegenerator::getnumberoffiles()
150{
151#if (DEVGENDEBUG==1)
152cout << "hd24devicenamegenerator::getnumberoffiles()"<< endl;
153#endif
154 // Files in the image directory will also be considered devices.
155 if (filecount==0)
156 {
157 if (imagedir()==NULL)
158 {
159 return 0;
160 }
161 // retrieve a list of .h24 image files.
162 filecount=hd24filecount(imagedir());
163 }
164 return filecount;
165}
166
167__uint32 hd24devicenamegenerator::getnumberofsysdevs()
168{
169#if (DEVGENDEBUG==1)
170cout << "hd24devicenamegenerator::getnumberofsysdevs()"<< endl;
171#endif
172#ifdef LINUX
173 // For linux the total number of names is 26x /dev/hd* + 26x /dev/sd*
174 return 52;
175#endif
176#ifdef WINDOWS
177 return 128;
178#endif
179#ifdef DARWIN
180 return 100;
181#endif
182}
183
184__uint32 hd24devicenamegenerator::getnumberofnames()
185{
186#if (DEVGENDEBUG==1)
187cout << "hd24devicenamegenerator::getnumberofnames()"<< endl;
188#endif
189 __uint32 filecount=this->getnumberoffiles();
190 __uint32 devcount=this->getnumberofsysdevs();
191#if (DEVGENDEBUG==1)
192 cout << "return: filecount="<<filecount<<", devcount="<<devcount<<endl;
193#endif
194 return filecount+devcount;
195}
196
197const char* hd24devicenamegenerator::getfilename(__uint32 filenum)
198{
199#if (DEVGENDEBUG==1)
200cout << "hd24devicenamegenerator::getfilename("<<filenum<<")"<< endl;
201#endif
202 // Given the list of files, this will return the Nth name (base 0).
203 if (filelist==NULL)
204 {
205 return "";
206 }
207 if (filelist->size()==0)
208 {
209 return "";
210 }
211 return filelist->at(filenum).c_str();
212}
213
214#ifdef LINUX
215string* hd24devicenamegenerator::getdevicename(__uint32 devicenumber)
216{
217#if (DEVGENDEBUG==1)
218cout << "hd24devicenamegenerator::getdevicename("<<devicenumber<<")"<< endl;
219#endif
220 if (devicenumber>=this->getnumberofsysdevs())
221 {
222 return new string(getfilename(devicenumber-this->getnumberofsysdevs()));
223 }
224 string* devname;
225 __uint32 devgroup = devicenumber;
226 devicenumber = (devicenumber%26);
227 devgroup -= devicenumber;
228 devgroup /= 26;
229
230 switch (devgroup)
231 {
232 case 0:
233 devname = new string("/dev/hd");
234 break;
235 case 1:
236 devname = new string("/dev/sd");
237 break;
238 default:
239 return new string("");
240 }
241
242 char devletter = (char) ('a' + devicenumber);
243 *devname += devletter;
244
245 return devname;
246}
247#endif
248
249#ifdef WINDOWS
250
251string* hd24devicenamegenerator::getdevicename(__uint32 devicenumber)
252{
253#if (DEVGENDEBUG==1)
254cout << "hd24devicenamegenerator::getdevicename("<<devicenumber<<")"<< endl;
255#endif
256 if (devicenumber>=this->getnumberofsysdevs())
257 {
258 return new string(getfilename(devicenumber-this->getnumberofsysdevs()));
259 }
260
261 string* devname = new string("//./PHYSICALDRIVE");
262 string* devnum = Convert::int2str(devicenumber);
263 *devname += *devnum;
264 delete devnum;
265 return devname;
266}
267#endif
268
269#ifdef DARWIN
270string* hd24devicenamegenerator::getdevicename(__uint32 devicenumber)
271{
272#if (DEVGENDEBUG==1)
273cout << "hd24devicenamegenerator::getdevicename("<<devicenumber<<")"<< endl;
274#endif
275 if (devicenumber>=this->getnumberofsysdevs())
276 {
277 return new string(getfilename(devicenumber-this->getnumberofsysdevs()));
278 }
279
280 string* devname = new string("/dev/disk");
281 string* devnum = Convert::int2str(devicenumber);
282 *devname += *devnum;
283 delete devnum;
284 return devname;
285}
286#endif
diff --git a/src/lib/hd24devicenamegenerator.h b/src/lib/hd24devicenamegenerator.h
new file mode 100755
index 0000000..40349ab
--- /dev/null
+++ b/src/lib/hd24devicenamegenerator.h
@@ -0,0 +1,52 @@
1#ifndef __hd24devnamegenerator_h__
2#define __hd24devnamegenerator_h__
3
4#include <config.h>
5#include <stdio.h>
6#include <string>
7#include <iostream>
8#include <vector>
9#include "convertlib.h"
10
11using namespace std;
12
13class hd24devicenamegenerator
14{
15 private:
16 char* imagespath; // path of device images
17 vector<string>* filelist;
18 __uint32 getnumberoffiles();
19 __uint32 filecount; // cache for getnumberoffiles
20 __uint32 getnumberofsysdevs();
21 __uint32 hd24filecount(const char* imagedir);
22 void initvars();
23 const char* getfilename(__uint32 filenum);
24 void clearfilelist();
25 public:
26 ~hd24devicenamegenerator();
27 hd24devicenamegenerator();
28
29 __uint32 getnumberofnames();
30 string* getdevicename(__uint32 number);
31
32 const char* imagedir();
33
34 /*
35 Setting the image dir resets the filecount to 0
36 which means the next call will actually count the image
37 files in the image dir (a rather heavy operation), and
38 caches the result in filecount.
39 imagedir(imagedir()) will force a filecount reset.
40
41 If the image dir is NULL, only system devices are returned.
42 */
43
44 const char* imagedir(const char* newdir);
45 /*
46 returns NULL on alloc error, const char*=dirname otherwise
47 */
48
49};
50
51#endif
52
diff --git a/src/lib/hd24fs.cpp b/src/lib/hd24fs.cpp
new file mode 100755
index 0000000..5c6b3fc
--- /dev/null
+++ b/src/lib/hd24fs.cpp
@@ -0,0 +1,3002 @@
1#define ALLOC_SECTORS_PER_SONG 5
2#define SONG_SECTORS_PER_SONG 2
3#define TOTAL_SECTORS_PER_SONG (ALLOC_SECTORS_PER_SONG+SONG_SECTORS_PER_SONG)
4#ifdef DARWIN
5#define creat64 creat
6#endif
7#define HD24FSDEBUG 0 /* generic hd24fs debugging */
8#define HD24FSDEBUG_QUICKFORMAT 0 /* debugging for calculation of # of free clusters */
9#define HD24FSDEBUG_WRITE 0 /* output debugging messages on disk writes */
10#define HD24FSDEBUG_BITSET 0 /* output debugging messages on disk writes */
11#define HD24FSDEBUG_COMMIT 0 /* output debugging messages on disk writes */
12#define HD24FSDEBUG_DEVSCAN 0 /* output debugging messages for device scan */
13#include "hd24fs.h"
14#include <string>
15#include <sys/types.h>
16#include <sys/stat.h>
17#include <fcntl.h>
18#ifndef WINDOWS
19#include <unistd.h>
20#endif
21#define RESULT_SUCCESS 0
22#define RESULT_FAIL 1
23#include <stdio.h>
24#include <stdlib.h>
25#include <iostream>
26#include <fstream>
27#include <math.h>
28#include "convertlib.h"
29#include "memutils.h"
30
31#include <hd24devicenamegenerator.h>
32#define _LARGE_FILES
33#define _FILE_OFFSET_BITS 64
34#define FILE_OFFSET_BITS 64
35#define LARGE_FILES
36#define LARGEFILE64_SOURCE
37#define SECTORSIZE 512
38#ifdef DARWIN
39#define open64 open
40#define lseek64 lseek
41#define pread64 pread
42#define pwrite64 pwrite
43#endif
44#define FSINFO_VERSION_MAJOR 0x8
45#define FSINFO_VERSION_MINOR 0x9
46#define FSINFO_BLOCKSIZE_IN_SECTORS 0x10
47#define FSINFO_AUDIOBLOCKS_PER_CLUSTER 0x14
48#define FSINFO_STARTSECTOR_DRIVEUSAGE 0x38
49#define FSINFO_NUMSECTORS_DRIVEUSAGE 0x3c
50#define FSINFO_FREE_CLUSTERS_ON_DISK 0x44
51#define FSINFO_FIRST_PROJECT_SECTOR 0x48
52#define FSINFO_SECTORS_PER_PROJECT 0x4C
53#define FSINFO_MAXPROJECTS 0x50
54#define FSINFO_MAXSONGSPERPROJECT 0x54
55#define FSINFO_FIRST_SONG_SECTOR 0x58
56#define FSINFO_SECTORS_IN_SONGENTRY 0x5C
57#define FSINFO_SECTORS_IN_SONGALLOC 0x60
58#define FSINFO_SECTORS_PER_SONG 0x64
59#define FSINFO_CURRENT_SONGS_ON_DISK 0x68
60#define FSINFO_ALLOCATABLE_SECTORCOUNT 0x80
61#define FSINFO_LAST_SECTOR 0x84
62#define FSINFO_DATAAREA 0x7c
63
64#define DRIVEINFO_VOLUME 0x1b8
65#define DRIVEINFO_VOLUME_8 0x00
66#define DRIVEINFO_PROJECTCOUNT 0x0c
67#define DRIVEINFO_LASTPROJ 0x10
68#define DRIVEINFO_LASTPROJECT 0x10
69#define DRIVEINFO_PROJECTLIST 0x20
70
71#include "hd24project.cpp"
72#include "hd24song.cpp"
73#if defined(LINUX) || defined(DARWIN)
74const int hd24fs::MODE_RDONLY=O_RDONLY;
75const int hd24fs::MODE_RDWR=O_RDWR;
76#endif
77#ifdef WINDOWS
78#include <shellapi.h>
79const int hd24fs::MODE_RDONLY=GENERIC_READ;
80const int hd24fs::MODE_RDWR=GENERIC_READ|GENERIC_WRITE;
81#define popen _popen
82#define pclose _pclose
83#endif
84
85const int hd24fs::TRANSPORTSTATUS_STOP =0;
86const int hd24fs::TRANSPORTSTATUS_REC =1;
87const int hd24fs::TRANSPORTSTATUS_PLAY =2;
88
89void dumpsector(const char* buffer)
90{
91 for (int i=0;i<512;i+=16) {
92 string* dummy=Convert::int32tohex(i);
93 cout << *dummy << " ";
94 delete dummy; dummy=NULL;
95 for (int j=0;j<16;j++) {
96 string* dummy= Convert::byte2hex(buffer[i+j]);
97 cout << *dummy;
98 if (j==7) {
99 cout << "-" ;
100 } else {
101 cout << " " ;
102 }
103 delete dummy; dummy=NULL;
104 }
105 cout << " ";
106 for (int j=0;j<16;j++) {
107 cout << Convert::safebyte(buffer[i+j]);
108 }
109 cout << "" << endl;
110 }
111}
112
113__uint32 hd24fs::songentry2sector(__uint32 songentry)
114{
115 // Given the possibility to store 99*99 songs,
116 // converts the song number (0..99*99-1) to
117 // the sector where the info of that song starts.
118 // TODO: answer is FSINFO_FIRST_SONG_SECTOR+(FSINFO_SECTORS_PER_SONG*songentry)
119 // returns 0 when entry number is not legal.
120 getsector_bootinfo();
121 if (sector_boot==NULL) {
122 // info needed for the calculation is missing.
123 return 0;
124 }
125 __uint32 firstsongsec=Convert::getint32(sector_boot,FSINFO_FIRST_SONG_SECTOR);
126 __uint32 secspersong=Convert::getint32(sector_boot,FSINFO_SECTORS_PER_SONG);
127 if (songentry<(99*99)) {
128 __uint32 secnum=(firstsongsec+(songentry*secspersong));
129 return secnum;
130 }
131 return 0; // entry number is not legal.
132}
133
134__uint32 hd24fs::songsondisk()
135{
136 getsector_bootinfo();
137 if (sector_boot==NULL) {
138 // info needed for the calculation is missing.
139 return 0;
140 }
141 return Convert::getint32(sector_boot,FSINFO_CURRENT_SONGS_ON_DISK);
142}
143
144void hd24fs::songsondisk(__uint32 songcount)
145{
146 getsector_bootinfo();
147 if (sector_boot==NULL) {
148 // info needed for the calculation is missing.
149 return; //cannot update.
150 }
151 Convert::setint32(sector_boot,FSINFO_CURRENT_SONGS_ON_DISK,songcount);
152}
153
154__uint32 hd24fs::songsector2entry(__uint32 songsector)
155{
156 // given the sector where a song entry starts,
157 // returns the entry number of that song.
158 // Entry number typically ranges from 0
159 // to (99*99)-1.
160 // A value 0xffffffff is returned when the
161 // sector number is not valid.
162 getsector_bootinfo();
163 if (sector_boot==NULL) {
164 // info needed for the calculation is missing.
165 return 0xFFFFFFFF; // sector number is not valid.
166 }
167 __uint32 firstsongsec=Convert::getint32(sector_boot,FSINFO_FIRST_SONG_SECTOR);
168 __uint32 secspersong=Convert::getint32(sector_boot,FSINFO_SECTORS_PER_SONG);
169 __uint32 offset=songsector-firstsongsec;
170 if ((offset%secspersong) !=0) {
171 return 0xFFFFFFFF; // sector number is not valid.
172 }
173 __uint32 resultentry=(offset/secspersong);
174 if (resultentry>=(99*99)) return 0xFFFFFFFF;
175 return resultentry;
176}
177
178__uint32 hd24fs::cluster2sector(__uint32 clusternum)
179{
180 getsector_bootinfo();
181 if (sector_boot==NULL) {
182 // unknown cluster size.
183 return 0;
184 }
185 return Convert::getint32(sector_boot,FSINFO_DATAAREA) /* first audio sector */
186 +(
187 Convert::getint32(sector_boot,FSINFO_BLOCKSIZE_IN_SECTORS)
188 * Convert::getint32(sector_boot,FSINFO_AUDIOBLOCKS_PER_CLUSTER)
189 * clusternum
190 );
191}
192
193__uint32 hd24fs::sector2cluster(__uint32 sectornum)
194{
195 getsector_bootinfo();
196 if (sector_boot==NULL) {
197 // unknown cluster size. Return 'undefined' cluster number.
198 return CLUSTER_UNDEFINED;
199 }
200 __uint32 dataarea=Convert::getint32(sector_boot,FSINFO_DATAAREA);
201
202 if (sectornum<dataarea) {
203 // A cluster number of a sector outside the data area was requested.
204 return CLUSTER_UNDEFINED;
205 }
206
207 __uint32 unoffsetsector=sectornum-dataarea;
208 __uint32 sectorspercluster=
209 Convert::getint32(sector_boot,FSINFO_BLOCKSIZE_IN_SECTORS)
210 * Convert::getint32(sector_boot,FSINFO_AUDIOBLOCKS_PER_CLUSTER);
211 __uint32 firstsectorofcluster=unoffsetsector-(unoffsetsector%sectorspercluster);
212 __uint32 cluster=firstsectorofcluster/sectorspercluster;
213 return cluster;
214}
215
216__uint32 hd24fs::getnextfreesector(__uint32 cluster)
217{
218 if (cluster==CLUSTER_UNDEFINED) {
219 __uint32 result=getnextfreesectorword();
220#if (HD24FSDEBUG==1)
221 cout << result << endl;
222#endif
223 return result;
224 }
225 if (isfreecluster(cluster+1,&sectors_driveusage[0]))
226 {
227 return cluster2sector(cluster+1);
228 }
229 return getnextfreesectorword();
230}
231
232__uint32 hd24fs::getnextfreesectorword()
233{
234 __uint32 cluster=getnextfreeclusterword();
235 if (cluster==CLUSTER_UNDEFINED) {
236 return 0;
237 }
238 return cluster2sector(cluster);
239}
240
241__uint32 hd24fs::getnextfreeclusterword()
242{
243 getsectors_driveusage();
244 __uint32 driveusagecount=driveusagesectorcount();
245 __uint32 driveusagewords=driveusagecount*(512/4);
246
247 // For performance reasons, we start searching
248 // at last result+1 (this will typically result
249 // in an immediate hit).
250 // Wrap around to cluster 0 if nothing found.
251
252#if (HD24FSDEBUG==1)
253 cout << " start search at " << nextfreeclusterword << endl;
254#endif
255 __uint32 i=nextfreeclusterword;
256 __uint32 initsec=i;
257
258 bool foundfree=false;
259 while (i<driveusagewords) {
260 if (Convert::getint32(&sectors_driveusage[0],i*4)==0) {
261 foundfree=true;
262 break;
263 }
264 i++;
265 }
266 if (!foundfree) {
267 if (initsec==0) {
268 // we didnt find anything although
269 // we started searching at cluster 0.
270 return CLUSTER_UNDEFINED;
271 } else {
272 // we didnt find anything but started
273 // searching at a cluster>0. Wrap around.
274 nextfreeclusterword=0;
275 return getnextfreeclusterword();
276 }
277 }
278 // we found a (set of 32) free cluster(s).
279 nextfreeclusterword=i;
280 return (i*32);
281}
282
283unsigned long hd24fs::getlastsectornum()
284{
285#if (HD24FSDEBUG==1)
286 cout <<"hd24fs::getlastsectornum()" << endl;
287#endif
288 // cache result.
289 if (gotlastsectornum==false) {
290 foundlastsectornum=getlastsectornum(devhd24);
291 gotlastsectornum=true;
292 }
293 return foundlastsectornum;
294}
295
296void hd24fs::setwavefixmode(int mode)
297{
298 wavefixmode=mode;
299}
300
301void hd24fs::setmaintenancemode(int mode)
302{
303 maintenancemode=mode;
304}
305
306int hd24fs::getmaintenancemode()
307{
308 return maintenancemode;
309}
310
311string* hd24fs::getdevicename() {
312
313 return this->devicename;
314}
315
316void hd24fs::setdevicename(const char* orig,string* devname)
317{
318 if (this->devicename!=NULL) {
319 delete this->devicename;
320 this->devicename=NULL;
321 }
322 this->devicename=new string(devname->c_str());
323}
324
325unsigned long hd24fs::getlastsectornum(FSHANDLE handle)
326{
327#if (HD24FSDEBUG==1)
328 cout <<"hd24fs::getlastsectornum(FSHANDLE handle)" << endl;
329#endif
330#if defined(LINUX) || defined(DARWIN)
331 __uint64 curroff=lseek64(handle,0,SEEK_CUR);
332 __uint64 sectors=(lseek64(handle,0,SEEK_END)+1)>>9;
333 lseek64(handle,curroff,SEEK_SET);
334 return sectors-1;
335#endif
336 /* unfortunately, apart from other functions being needed
337 * to read 64 bit files, the elegant solution above won't
338 * work on Windows, because it is not possible to
339 * request the file size of a device.
340 */
341
342#ifdef WINDOWS
343 unsigned char buffer[2048];
344 LARGE_INTEGER lizero;
345 lizero.QuadPart=0;
346 LARGE_INTEGER saveoff;
347 LARGE_INTEGER filelen;
348 filelen.QuadPart=0;
349 SetFilePointerEx(handle,lizero,&saveoff,FILE_CURRENT); // save offset
350 /* If things would work properly, the following would
351 * not only work for regular files, but also for devices.
352 * Perhaps the next version of Windows has proper hardware
353 * abstraction and this will magically start working.
354 */
355 if (0!=SetFilePointerEx(handle,lizero,&filelen,FILE_END)) {
356 SetFilePointerEx(handle,saveoff,NULL,FILE_BEGIN); // restore offset
357 return ((filelen.QuadPart)/512);
358 }
359 SetFilePointerEx(handle,saveoff,NULL,FILE_BEGIN); // restore offset
360#if (HD24FSDEBUG==1)
361 cout << "fileptr method failed" << endl;
362#endif
363 /* The proper way to do things has failed (probably because
364 * we are dealing with a device file instead of with a
365 * regular one.
366 */
367
368 /* TODO: Before trying a raw sectornum scan,
369 we can still check if we're dealing with a valid
370 superblock, not using a headerfile and checking if
371 the last sector as indicated by the superblock points
372 to a copy of that superblock. This won't work on a raw
373 drive, of course, but will provide a reasonably safe
374 workaround for valid HD24 drives. */
375
376 /* The workaround has also failed, so we need to perform
377 raw drive size detection. Windows does not have a reliable
378 way to get the real LBA sector count, so we need to perform
379 the following semi-smart trick (if you have a better idea that
380 works on all windows versions and all drive types,
381 I'd be thrilled to know!)
382
383 - First, iterate reading sector numbers until it fails.
384 To keep speed acceptable, multiply sector number by 2
385 each time.
386 - After failed read, do a binary search between the
387 failed read sector number and the sector number of
388 the last successful read.
389 - As the drive MUST be aware of its own size, this will
390 give the real sector count of the drive.
391 */
392 lizero.QuadPart=0;
393 saveoff.QuadPart=0;
394
395 LARGE_INTEGER maxbytes;
396 maxbytes.QuadPart=0;
397 SetFilePointerEx(handle,lizero,&saveoff,FILE_CURRENT); // save offset
398
399 long bytesread=1;
400 unsigned long trysector=1;
401 unsigned long oldtrysector=1;
402 int drivetoosmall=1;
403 bytesread=readsectors(handle,trysector,buffer,1); // raw/audio read (no fstfix needed)
404 unsigned long lastok=0;
405 unsigned long firstfail=0;
406 //int dummy;
407 /* This loop doubles the sector number. Actually stays at 2^n-1,
408 * this will likely perform better than 2^n because chances are
409 * greater that it stays below disk boundaries, preventing slow
410 * timeouts.
411 */
412 while (bytesread>0)
413 {
414#if (HD24FSDEBUG==1)
415 cout << "trysector=" << trysector << endl;
416#endif
417// cin >> dummy;
418 drivetoosmall=0;
419 oldtrysector=trysector;
420 trysector=trysector*2+1; // count will be 1,3,7,15,31,... =(2^n)-1
421 if (oldtrysector==trysector)
422 {
423 // x*2+1 yields x - this means all
424 // bits are turned on and we overflow.
425 // So we're at 4 tera limit.
426 // 4 terabyte and still nothing found? hmmmm
427 SetFilePointerEx(handle,saveoff,NULL,FILE_BEGIN);
428 return 0;
429 }
430 bytesread=0;
431 bytesread=readsectors(handle,trysector,buffer,1); // raw/audio read (no fstfix needed)
432#if (HD24FSDEBUG==1)
433 cout << " bytesread=" <<bytesread << endl;
434#endif
435 if (bytesread>0) {
436 lastok=trysector;
437 } else {
438 firstfail=trysector;
439 }
440 }
441 /* We have the sector number of the last successful read and
442 * of the failed read. Time to do a binary search. */
443 unsigned long lowerbound=lastok;
444#if (HD24FSDEBUG==1)
445 cout << "lastok=" << lastok << endl;
446 cout << "firstfaiL=" << firstfail << endl;
447
448#endif
449 if (lastok==0)
450 {
451 if (firstfail==0)
452 {
453 return 0;
454 }
455 }
456 unsigned long upperbound=lastok*2;
457 unsigned long midpos=0;
458 while (lowerbound<=upperbound)
459 {
460 //midpos=lowerbound+floor((upperbound-lowerbound)/2);
461 midpos=lowerbound+(__uint32)floor((upperbound-lowerbound)/8);
462 // prefer asymmetrical search due to time out when
463 // searching past upperbound
464// cout << "try=" << midpos << endl;
465 bytesread=readsectors(handle,midpos,buffer,1); // raw/audio read (no fstfix needed)
466 if (bytesread>0) {
467 lowerbound=midpos+1;
468 } else {
469 // could not read midpos,
470 // so upperbound is before that.
471 upperbound=midpos-1;
472 }
473 }
474 if (midpos==lowerbound)
475 {
476 midpos--;
477 }
478 /* midpos is now last sector number. counting starts at sector 0
479 * so total number of sectors is one more. */
480 midpos++;
481 SetFilePointerEx(handle,saveoff,&saveoff,FILE_BEGIN); //restore
482
483 __uint64 sectors=midpos;
484// cout << "found " <<sectors << "sectors " <<endl;
485 return sectors;
486#endif
487}
488
489/* The hd24raw class provides sector level access to hd24 disks
490 * which is functionality that is shielded off in hd24fs.
491 */
492
493__uint32 hd24raw::songsondisk()
494{
495 return fsys->songsondisk();
496}
497
498__uint32 hd24raw::getlastsectornum()
499{
500 return fsys->getlastsectornum();
501}
502
503__uint32 hd24raw::getprojectsectornum(__uint32 x)
504{
505 return fsys->getprojectsectornum(x);
506}
507
508__uint32 hd24raw::quickformat(char* message)
509{
510 return fsys->quickformat(message);
511}
512
513unsigned long hd24raw::getnextfreesector(__uint32 cluster)
514{
515 return fsys->getnextfreesector(cluster);
516}
517
518hd24raw::hd24raw(hd24fs* p_fsys)
519{
520 fsys=p_fsys;
521}
522
523long hd24raw::readsectors(unsigned long secnum, unsigned char* buffer,int sectors)
524{
525 return fsys->readsectors(fsys->devhd24, secnum, buffer,sectors);
526}
527
528long hd24raw::writesectors(unsigned long secnum, unsigned char* buffer,int sectors)
529{
530 return fsys->writesectors(fsys->devhd24, secnum, buffer,sectors);
531};
532
533bool hd24fs::isinvalidhandle(FSHANDLE handle)
534{
535#ifdef WINDOWS
536 if (handle==FSHANDLE_INVALID) {
537 return true;
538 }
539#endif
540#if defined(LINUX) || defined(DARWIN)
541 if (handle==0) {
542 return true;
543 }
544 if (handle==FSHANDLE_INVALID) {
545 return true;
546 }
547#endif
548 return false;
549}
550
551bool hd24fs::isexistingdevice(string* devname)
552{
553#if defined(LINUX) || defined(DARWIN)
554#if (HD24FSDEBUG==1)
555cout << "try open device " << devname->c_str() << endl;
556#endif
557 FSHANDLE handle=open64(devname->c_str(),MODE_RDONLY); //read binary
558#endif
559#ifdef WINDOWS
560 FSHANDLE handle=CreateFile(devname->c_str(),MODE_RDONLY,
561 FILE_SHARE_READ|FILE_SHARE_WRITE,
562 NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
563#endif
564 if (!isinvalidhandle(handle)) return true;
565 return false;
566}
567
568FSHANDLE hd24fs::findhd24device(int mode,string* devname,bool force,bool tryharder)
569{
570#if (HD24FSDEBUG_DEVSCAN==1)
571 cout << "FSHANDLE hd24fs::findhd24device(" << mode << ", " << *devname << ", force=" << force << ",tryharder=" << tryharder <<")" << endl;
572#endif
573 unsigned char findhdbuf[1024];
574 unsigned char compare1buf[1024];
575 unsigned char compare2buf[1024];
576#if defined(LINUX)
577 FSHANDLE handle=open64(devname->c_str(),mode,0); //read binary
578#endif
579#if defined(DARWIN)
580 FSHANDLE handle=open64(devname->c_str(),mode); //read binary
581#endif
582#ifdef WINDOWS
583#if (HD24FSDEBUG_DEVSCAN==1)
584 cout << "Mode=" << mode << endl;
585#endif
586 FSHANDLE handle=CreateFile(devname->c_str(),mode,
587 FILE_SHARE_READ|FILE_SHARE_WRITE,
588 NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
589#endif
590
591 if (isinvalidhandle(handle)) {
592 if (mode==MODE_RDWR)
593 {
594 // attempt fallback to read-only mode
595 // (for CDROM/DVD devices etc)
596 mode=MODE_RDONLY;
597#if defined(LINUX) || defined(DARWIN)
598 handle=open64(devname->c_str(),mode); //read binary
599#endif
600#ifdef WINDOWS
601#if (HD24FSDEBUG==1)
602// cout << "Mode=" << mode << endl;
603#endif
604 handle=CreateFile(devname->c_str(),mode,
605 FILE_SHARE_READ|FILE_SHARE_WRITE,
606 NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
607#endif
608
609 }
610
611
612 }
613
614 if (isinvalidhandle(handle)) {
615 return handle;
616 }
617
618 // can open device.
619 __uint32 sectornum=0;
620 if (tryharder) {
621 sectornum=getlastsectornum(handle);
622 }
623
624 readsector_noheader(handle,sectornum,findhdbuf); // fstfix follows
625 fstfix(findhdbuf,512);
626 string* fstype=Convert::readstring(findhdbuf,0,8);
627 bool isadat=false;
628
629 if (*fstype=="ADAT FST") {
630 /* Okay, but if we are 'trying harder' we can run into
631 a false positive for old HD24 drives that are now in
632 use as OS drive. So we'll demand that the second and
633 secondlast sector are equal.
634 */
635 if (tryharder)
636 {
637 readsector_noheader(handle,sectornum-1,compare1buf);
638 readsector_noheader(handle,1,compare2buf);
639 if (memcmp(compare1buf,compare2buf,512)==0)
640 {
641 isadat=true;
642 }
643 else
644 {
645 /* Drive may have been an ADAT drive,
646 but no longer is. If it is in fact an
647 ADAT drive but corrupted, it is still
648 possible to force detection using force
649 mode. Give it another chance; do not
650 enable write prevention for now.
651 */
652 isadat=false;
653 }
654 }
655 else
656 {
657 isadat=true;
658 }
659 }
660 delete fstype;
661
662 if (isadat) return handle;
663
664 if (force)
665 {
666 forcemode=true;
667 m_isOpen=true;
668 this->writeprotected=true; // TODO: unless expert mode is enabled too. May also be overridden to allow formatting.
669 return handle;
670 }
671 hd24closedevice(handle);
672 return FSHANDLE_INVALID;
673}
674
675unsigned long hd24fs::hd24devicecount()
676{
677 /* Attempt to auto-detect a hd24 disk on all IDE and SCSI devices.
678 (this should include USB and firewire) */
679 FSHANDLE handle;
680 int devcount=0;
681#if (HD24FSDEBUG==1)
682 cout << "====PERFORMING DEVICE COUNT====" << endl;
683#endif
684 hd24devicenamegenerator* dng=new hd24devicenamegenerator();
685 dng->imagedir(this->imagedir);
686
687 __uint32 totnames=dng->getnumberofnames();
688// cout << totnames << " devices" << endl;
689 for (__uint32 j=0;j<2;j++)
690 {
691 // 2 loops: one to try, one to try harder
692 // first loop searches strictly valid devices
693 // second loop searches for possibly corrupted devices
694 bool tryharder=false;
695 if (j==1) {
696 tryharder=true;
697 }
698 for (__uint32 i=0;i<totnames;i++)
699 {
700 string* devname=dng->getdevicename(i);
701 handle=findhd24device(MODE_RDONLY,devname,false,tryharder);
702#if (HD24FSDEBUG_DEVSCAN==1)
703 cout << "try device no " <<i << "with name" << *devname << "...";
704#endif
705 delete (devname);
706 if (!(isinvalidhandle(handle)))
707 {
708 devcount++;
709 // cout << "found" << endl;
710 hd24closedevice(handle);
711 } else {
712 // cout << "nope." << endl;
713 }
714 }
715
716 if (devcount>0) {
717 break;
718 }
719 }
720#if (HD24FSDEBUG==1)
721 cout << "====END OF DEVICE COUNT, " << devcount << " DEVICES FOUND ====" << endl;
722#endif
723 delete (dng);
724 return devcount;
725}
726
727void hd24fs::setimagedir(const char* newdir)
728{
729#if (HD24FSDEBUG==1)
730if (newdir==NULL)
731{
732 cout << "hd24fs::setimagedir(NULL)"<< endl;
733}
734else
735{
736 cout << "hd24fs::setimagedir("<<newdir<<")"<< endl;
737}
738#endif
739
740 if (this->imagedir!=NULL)
741 {
742 free ((void*)imagedir);
743 this->imagedir=NULL;
744 }
745
746 if (newdir!=NULL)
747 {
748 this->imagedir=(char*)malloc(strlen(newdir)+1);
749 if (this->imagedir!=NULL)
750 {
751 strncpy((char*)imagedir,newdir,strlen(newdir)+1);
752 }
753 }
754
755 return; //return (const char*)imagedir;
756}
757
758FSHANDLE hd24fs::findhd24device(int mode,int base0devnum)
759{
760#if (HD24FSDEBUG_DEVSCAN==1)
761 cout << "hd24fs::findhd24device(" << mode << "," << base0devnum << ")" << endl;
762#endif
763 // TODO: Reduce code duplication in this subroutine
764 // and hd24devicecount
765 /* Attempt to auto-detect a hd24 disk on all known
766 IDE and SCSI devices. (this should include USB
767 and firewire) */
768 int currdev=0;
769 FSHANDLE handle;
770 hd24devicenamegenerator* dng=new hd24devicenamegenerator();
771 dng->imagedir(this->imagedir);
772
773 __uint32 totnames=dng->getnumberofnames();
774#if (HD24FSDEBUG==1)
775 cout << totnames << " devices" << endl;
776#endif
777 for (__uint32 j=0;j<2;j++)
778 {
779 // 2 loops: one to try, one to try harder
780 // first loop searches strictly valid devices
781 // second loop searches for possibly corrupted devices
782
783 bool tryharder=false;
784 if (j==1) {
785 tryharder=true;
786 }
787
788 for (__uint32 i=0;i<totnames;i++)
789 {
790 string* devname=dng->getdevicename(i);
791 handle=findhd24device(mode,devname,false,tryharder);
792
793 if (!(isinvalidhandle(handle))) {
794 if (currdev==base0devnum) {
795 // String "3" indicates origin, i.e.
796 // who is setting the device name.
797 // Useful for debugging purposes.
798 setdevicename("3",devname);
799 deviceid=i;
800 p_mode=mode;
801 delete (devname);
802 delete (dng);
803 return handle;
804 }
805 hd24closedevice(handle);
806 currdev++;
807 }
808 delete (devname);
809 }
810 }
811 delete (dng);
812 return FSHANDLE_INVALID;
813}
814
815void hd24fs::hd24closedevice(FSHANDLE handle) {
816#if defined(LINUX) || defined(DARWIN)
817 close(handle);
818#endif
819#ifdef WINDOWS
820 CloseHandle(handle);
821#endif
822}
823
824FSHANDLE hd24fs::findhd24device(int mode)
825{
826 /* Attempt to auto-detect a hd24 disk on all IDE and SCSI devices.
827 (this should include USB and firewire) */
828 return findhd24device(mode,0);
829}
830
831FSHANDLE hd24fs::findhd24device()
832{
833 return findhd24device(MODE_RDONLY);
834}
835
836int hd24fs::gettransportstatus()
837{
838 return this->transportstatus;
839}
840
841void hd24fs::settransportstatus(int newstatus)
842{
843 this->transportstatus=newstatus;
844}
845
846int hd24fs::getdeviceid()
847{
848 return deviceid;
849}
850
851void hd24fs::initvars()
852{
853 this->deviceid=-1;
854 this->writeprotected=false; // by default allow writes.
855 // can be disabled if corrupt
856 // state is detected.
857 this->transportstatus=TRANSPORTSTATUS_STOP;
858 this->imagedir=NULL;
859 this->nextfreeclusterword=0;
860 this->gotlastsectornum=false;
861 this->foundlastsectornum=0;
862 this->forcemode=false;
863 this->headersectors=0;
864 sector_boot=NULL;
865 sector_diskinfo=NULL;
866 sectors_driveusage=NULL;
867 sectors_orphan=NULL;
868 sectors_songusage=NULL;
869 projlist=NULL;
870 this->m_isOpen=false;
871 this->allinput=false;
872 this->autoinput=false;
873 this->wavefixmode=false;
874 this->formatting=false;
875 this->maintenancemode=false;
876 this->headermode=false;
877 this->devicename=NULL;
878 this->highestFSsectorwritten=0;
879 // 0x10c76 is last sector of song/project area (without undo buffer)
880 return;
881}
882
883hd24fs::hd24fs(const char* imagedir,int mode)
884{
885 initvars();
886 setimagedir(imagedir);
887 devicename=new string("");
888 devhd24=findhd24device(mode);
889 if (!(isinvalidhandle(devhd24))) {
890 m_isOpen=true;
891 p_mode=mode;
892 }
893 return;
894}
895
896hd24fs::hd24fs(const char* imagedir,int mode,int base0devnum)
897{
898#if (HD24FSDEBUG==1)
899 cout << "hd24fs::hd24fs(" << mode << "," << base0devnum << ")" << endl;
900#endif
901 initvars();
902 setimagedir(imagedir);
903 devicename=new string("");
904 devhd24=findhd24device(mode,base0devnum);
905 if (!(isinvalidhandle(devhd24))) {
906 m_isOpen=true;
907 p_mode=mode;
908 }
909 return;
910}
911
912hd24fs::hd24fs(const char* imagedir,int mode,string* devname,bool force)
913{
914 initvars();
915 setimagedir(imagedir);
916 devicename=new string(devname->c_str());
917 bool tryharder=false;
918 devhd24=findhd24device(mode,devname,force,tryharder);
919 if (!(isinvalidhandle(devhd24))) {
920 m_isOpen=true;
921 p_mode=mode;
922 }
923 return;
924}
925
926hd24fs::hd24fs(const char* imagedir)
927{
928 initvars();
929 setimagedir(imagedir);
930 devicename=new string("");
931 devhd24=findhd24device(MODE_RDONLY);
932 if (!(isinvalidhandle(devhd24))) {
933 m_isOpen=true;
934 p_mode=MODE_RDONLY;
935 }
936 return;
937}
938
939hd24fs::~hd24fs()
940{
941#if (HD24FSDEBUG==1)
942 cout << "Deleting devicename" << endl;
943#endif
944 if (devicename!=NULL) {
945 delete devicename;
946 devicename=NULL;
947 }
948#if (HD24FSDEBUG==1)
949 cout << "Close FS handle" << endl;
950#endif
951 if (isOpen())
952 {
953 hd24close();
954 }
955#if (HD24FSDEBUG==1)
956 cout << "Free superblock mem" << endl;
957#endif
958 if (sector_boot!=NULL)
959 {
960 memutils::myfree("sectors_boot",sector_boot);
961 sector_boot=NULL;
962 }
963#if (HD24FSDEBUG==1)
964 cout << "Free diskinfo mem" << endl;
965#endif
966 if (sector_diskinfo!=NULL)
967 {
968 memutils::myfree("sectors_diskinfo",sector_diskinfo);
969 sector_diskinfo=NULL;
970 }
971#if (HD24FSDEBUG==1)
972 cout << "Free drive usage mem" << endl;
973#endif
974 if (sectors_driveusage!=NULL)
975 {
976 memutils::myfree("sectors_driveusage",sectors_driveusage);
977 sectors_driveusage=NULL;
978 }
979#if (HD24FSDEBUG==1)
980 cout << "Free orphan sectors mem" << endl;
981#endif
982 if (sectors_orphan!=NULL)
983 {
984 memutils::myfree("sectors_orphan",sectors_orphan);
985 sectors_orphan=NULL;
986 }
987#if (HD24FSDEBUG==1)
988 cout << "Free song usage sectors mem" << endl;
989#endif
990 if (sectors_songusage!=NULL)
991 {
992 memutils::myfree("sectors_songusage",sectors_songusage);
993 sectors_songusage=NULL;
994 };
995 // commit?
996}
997
998bool hd24fs::isOpen()
999{
1000 if (this->m_isOpen)
1001 {
1002 return true;
1003 }
1004 return false;
1005}
1006
1007void hd24fs::hd24close()
1008{
1009 // TODO: At the point that we start supporting
1010 // write access, we will need to flush and close
1011 // the device here.
1012
1013 hd24closedevice(this->devhd24);
1014}
1015
1016void hd24fs::fstfix(unsigned char * bootblock,int fixsize)
1017{
1018 if (bootblock==NULL) return;
1019 if (fixsize<=0) return;
1020#if (HD24FSDEBUG==1)
1021 cout << "fstfix("<<bootblock<<","<<fixsize/512 <<"*512)"<< endl;
1022#endif
1023 for (int i=0;i<fixsize;i+=4)
1024 {
1025 unsigned char a=bootblock[i];
1026 unsigned char b=bootblock[i+1];
1027 unsigned char c=bootblock[i+2];
1028 unsigned char d=bootblock[i+3];
1029 bootblock[i]=d;
1030 bootblock[i+1]=c;
1031 bootblock[i+2]=b;
1032 bootblock[i+3]=a;
1033 }
1034}
1035
1036void hd24fs::hd24seek(FSHANDLE devhd24,__uint64 seekpos) {
1037#if defined(LINUX) || defined(DARWIN)
1038 lseek64(devhd24,seekpos,SEEK_SET);
1039#endif
1040#ifdef WINDOWS
1041// cout << "setfp to " <<seekpos << endl;
1042 LARGE_INTEGER li;
1043 li.HighPart=seekpos>>32;
1044 li.LowPart=seekpos%((__uint64)1<<32);
1045//LowPart=seekpos%
1046// SetFilePointer(devhd24,seekpos,NULL,FILE_BEGIN);
1047 SetFilePointerEx(devhd24,li,NULL,FILE_BEGIN);
1048 // TODO: SetFilePointer vs SetFilePointerEx
1049 // DWORD SetFilePointer(
1050 // HANDLE hFile,
1051 // LONG lDistanceToMove,
1052 // PLONG lpDistanceToMoveHigh,
1053 // DWORD dwMoveMethod
1054 // );
1055 //
1056 // vs.
1057 // BOOL SetFilePointerEx(
1058 // HANDLE hFile,
1059 // LARGE_INTEGER liDistanceToMove,
1060 // PLARGE_INTEGER lpNewFilePointer,
1061 // DWORD dwMoveMethod
1062 // );
1063 //
1064#endif
1065 return;
1066}
1067
1068long hd24fs::writesectors(FSHANDLE devhd24,unsigned long sectornum,unsigned char * buffer,int sectors)
1069{
1070 //////
1071 // this bit keeps track of the highest FS sector written
1072 // to keep commit times acceptable: commit function will then
1073 // only backup up to the highest sector used.
1074 // (this is still suboptimal performance-wise but requires
1075 // a minimum of memory and administration during writes).
1076 __uint32 lastsec=sectornum+(sectors-1);
1077 if (lastsec<=0x10c76)
1078 {
1079 // 0x10c76 is last sector of song/project area (without
1080 // undo buffer). TODO: calculate based on superblock. info.
1081 if (lastsec>highestFSsectorwritten)
1082 {
1083 highestFSsectorwritten=lastsec;
1084 }
1085 }
1086 //////
1087
1088#if (HD24FSDEBUG_WRITE==1)
1089 cout << " writesectors sectornum " << sectornum << ", sectorcount=" << sectors << endl;
1090#endif
1091 if (this!=NULL)
1092 {
1093 if (this->writeprotected)
1094 {
1095#if (HD24FSDEBUG_WRITE==1)
1096 cout << "Write protected- not writing. " << endl;
1097#endif
1098 return 0;
1099 }
1100 }
1101 FSHANDLE currdevice=devhd24;
1102
1103#if (HD24FSDEBUG_WRITE==1)
1104 cout << "WRITESECTORS sec=" << sectornum << " buf=" << buffer << "#=" << sectors << endl;
1105#endif
1106 int WRITESIZE=SECTORSIZE*sectors; // allows searching across sector boundaries
1107
1108// cout << "headersectors=" << this->headersectors << "this=" <<this << endl;
1109 if (this!=NULL)
1110 {
1111 if ((this->headersectors)!=0)
1112 {
1113// cout << "headermode enabled." << endl;
1114 // Header mode is active. Only allow writing over header area.
1115 if (sectornum<this->headersectors)
1116 {
1117// cout << "Headermode enabled for sector " << sectornum << endl;
1118 currdevice=hd24header;
1119
1120 } else {
1121 // headermode is active yet caller is trying to write over drive
1122 // data area. We cannot allow this (for safety reasons).
1123 return 0;
1124
1125// cout << "Headermode disabled for sector " << sectornum << endl;
1126 }
1127 } else {
1128// cout << "Headermode disabled. " << sectornum << endl;
1129 }
1130 }
1131
1132 hd24seek(currdevice,(__uint64)sectornum*512);
1133
1134#if defined(LINUX) || defined(DARWIN) || defined(__APPLE__)
1135 long bytes=pwrite64(currdevice,buffer,WRITESIZE,(__uint64)sectornum*512); //1,devhd24);
1136// cout << "BYTES=" << bytes << endl;
1137#endif
1138#ifdef WINDOWS
1139 DWORD dummy;
1140 long bytes=0;
1141 if (WriteFile(currdevice,buffer,WRITESIZE,&dummy,NULL)) {
1142 bytes=WRITESIZE;
1143 };
1144#endif
1145 return bytes;
1146}
1147
1148long hd24fs::readsectors(FSHANDLE devhd24,unsigned long sectornum,unsigned char * buffer,int sectors)
1149{
1150 FSHANDLE currdevice=devhd24;
1151 // The following prints the sector num in hex:
1152#if (HD24FSDEBUG==1)
1153/* string* x=this->p_convert->int32tohex(sectornum);
1154 cout << *x << endl;
1155 delete x;
1156*/
1157#endif
1158
1159// cout << "headersectors=" << this->headersectors << "this=" <<this << endl;
1160 if ((this->headersectors)!=0)
1161 {
1162// cout << "headermode enabled." << endl;
1163 if (sectornum<this->headersectors)
1164 {
1165// cout << "Headermode enabled for sector " << sectornum << endl;
1166 currdevice=hd24header;
1167 } else {
1168// cout << "Headermode disabled for sector " << sectornum << endl;
1169 }
1170 } else {
1171// cout << "Headermode disabled. " << sectornum << endl;
1172 }
1173 hd24seek(currdevice,(__uint64)sectornum*SECTORSIZE);
1174 int READSIZE=SECTORSIZE*(sectors);
1175#if defined(LINUX) || defined(DARWIN)
1176 long bytes_read=pread64(currdevice,buffer,READSIZE,(__uint64)sectornum*512); //1,currdevice);
1177#endif
1178#ifdef WINDOWS
1179// cout << "Readsectors: num="<<sectornum<<"buffer available, numsecs=" <<sectors << endl;
1180 DWORD bytes_read;
1181 //long bytes=0;
1182 if( ReadFile(currdevice,buffer,READSIZE,&bytes_read,NULL)) {
1183// cout << "read succes"<< bytes_read << "bytes" << endl;
1184 } else {
1185// cout << "read fail" << endl;
1186 bytes_read = 0;
1187 }
1188#endif
1189 return bytes_read;
1190}
1191
1192long hd24fs::readsector(FSHANDLE devhd24,unsigned long sectornum,unsigned char * bootblock)
1193{
1194 return readsectors(devhd24,sectornum,bootblock,1);
1195}
1196
1197long hd24fs::readsector_noheader(hd24fs* currhd24,unsigned long sectornum,unsigned char * bootblock)
1198{
1199 return readsector_noheader(currhd24->devhd24,sectornum,bootblock);
1200}
1201
1202long hd24fs::readsector_noheader(FSHANDLE devhd24,unsigned long sectornum,unsigned char * bootblock)
1203{
1204 unsigned long headersecs=this->headersectors;
1205 this->headersectors=0; // disable header processing, if applies
1206 long number_read=readsectors(devhd24,sectornum,bootblock,1);
1207 this->headersectors=headersecs; // re-enable header processing
1208 return number_read;
1209}
1210
1211long hd24fs::writesector(FSHANDLE devhd24,unsigned long sectornum,unsigned char * bootblock)
1212{
1213 return writesectors(devhd24,sectornum,bootblock,1);
1214}
1215
1216string* hd24fs::gethd24currentdir(int argc,char* argv[])
1217{
1218 /* For future use. We may save a file in the
1219 homedir of the user containing info about which
1220 "path" (project/songname/file format) was last
1221 selected by the user.
1222 */
1223
1224 return new string("/");
1225}
1226
1227string* hd24fs::gethd24currentdir()
1228{
1229 return new string("/");
1230}
1231
1232unsigned char* hd24fs::readdiskinfo()
1233{
1234#if (HD24FSDEBUG==1)
1235 cout << "Driveusage before readdiskinfo=" << (int)(this->sectors_driveusage) << endl;
1236#endif
1237 // read disk info
1238 if (/*formatting||*/(sector_boot==NULL))
1239 {
1240 this->readbootinfo();
1241 }
1242 if (sector_diskinfo!=NULL)
1243 {
1244 memutils::myfree("readdiskinfo",sector_diskinfo);
1245 sector_diskinfo=NULL;
1246 }
1247 sector_diskinfo=(unsigned char *)memutils::mymalloc("readdiskinfo",1024,1);
1248 if (sector_diskinfo!=NULL)
1249 {
1250 readsector(devhd24,1,sector_diskinfo); // fstfix follows
1251 fstfix (sector_diskinfo,512);
1252 }
1253#if (HD24FSDEBUG==1)
1254 cout << "Driveusage after readdiskinfo=" << (int)(this->sectors_driveusage) << endl;
1255#endif
1256 return sector_diskinfo;
1257}
1258
1259bool hd24fs::useheaderfile(string headerfilename)
1260{
1261 getsector_bootinfo();
1262 if (sector_boot==NULL)
1263 {
1264 /* we haven't got a main device yet
1265 so we cannot apply a header to it */
1266 return false;
1267 }
1268 // allow writing to header.
1269#if defined(LINUX) || defined(DARWIN)
1270 FSHANDLE handle=open64(headerfilename.c_str(),MODE_RDWR); //read binary
1271#endif
1272#ifdef WINDOWS
1273// cout << "Mode=" << mode << endl;
1274 FSHANDLE handle=CreateFile(headerfilename.c_str(),MODE_RDWR,
1275 FILE_SHARE_READ|FILE_SHARE_WRITE,
1276 NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
1277#endif
1278
1279 if (isinvalidhandle(handle)) return false;
1280// cout << "Trying to enable header mode with file " << headerfilename << endl;
1281 hd24header=handle;
1282 this->headersectors=0;
1283 this->headersectors=getlastsectornum(hd24header)+1;
1284 // re-read disk info as number of projects etc can differ with header
1285 readsector(devhd24,1,sector_diskinfo); // fstfix follows
1286 fstfix (sector_diskinfo,512);
1287
1288// cout << "headersectors=" << this->headersectors << "this=" <<this << endl;
1289 return true;
1290}
1291
1292void hd24fs::clearbuffer(unsigned char* buffer,unsigned int bytes)
1293{
1294 /* clear buffer */
1295 for (unsigned int i=0;i<bytes;i++) {
1296 buffer[i]=0;
1297 }
1298 return;
1299}
1300
1301void hd24fs::clearbuffer(unsigned char* buffer)
1302{
1303 clearbuffer(buffer,512);
1304}
1305
1306
1307void hd24fs::cleardriveinfo(unsigned char* buffer)
1308{
1309 clearbuffer(buffer);
1310 string drivename="Drive Name";
1311 this->setname(buffer,drivename,DRIVEINFO_VOLUME_8,DRIVEINFO_VOLUME);
1312 return;
1313}
1314
1315void hd24fs::useinternalboot(unsigned char* buffer,__uint32 lastsector)
1316{
1317 unsigned char internal_boot[136]=
1318 {
1319 0x54,0x41,0x44,0x41,0x54,0x53,0x46,0x20, 0x20,0x30,0x31,0x31,0x33,0xcc,0xaa,0x55,
1320 0x80,0x04,0x00,0x00,0x02,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1321 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1322 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00, 0x05,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,
1323 0x2f,0x04,0x00,0x00,0x00,0x00,0x00,0x00, 0x14,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
1324 0x63,0x00,0x00,0x00,0x63,0x00,0x00,0x00, 0x77,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
1325 0x05,0x00,0x00,0x00,0x07,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x49,0x26,0x00,0x00,
1326 0x76,0x0c,0x01,0x00,0x80,0x8b,0x12,0x00, 0x1f,0x04,0x00,0x00,0xf6,0x97,0x13,0x00,
1327 0x14,0x89,0xb4,0x04,0x7f,0x2d,0xc9,0x04
1328 };
1329
1330 clearbuffer(buffer);
1331
1332 /* fill buffer with default boot info */
1333 for (unsigned int i=0;i<sizeof(internal_boot);i++) {
1334 buffer[i]=internal_boot[i];
1335 }
1336
1337 /* If a specific FS size (in sectors) was given, update boot info
1338 to match that size */
1339 if (lastsector!=0)
1340 {
1341#if (HD24FSDEBUG_QUICKFORMAT==1)
1342 cout << "Calculating number of clusters on the drive" << endl;
1343#endif
1344 fstfix(buffer,512); // convert into editable format
1345
1346 Convert::setint32(buffer,FSINFO_LAST_SECTOR,lastsector);
1347#if (HD24FSDEBUG_QUICKFORMAT==1)
1348 cout << "Last sector=" << lastsector << endl;
1349#endif
1350 // allocatable sectors=total sectors-(2*fs sectors+undo area)
1351 // tot secs-0x14a46b
1352
1353 __uint32 allocatablesectors=lastsector-0x14a46b;
1354#if (HD24FSDEBUG_QUICKFORMAT==1)
1355 cout << "# allocatable sectors=" << allocatablesectors << endl;
1356#endif
1357 Convert::setint32(buffer,FSINFO_ALLOCATABLE_SECTORCOUNT,allocatablesectors);
1358
1359 // (15 sectors of drive usage info=((15*512)-8)*8 bits
1360 //
1361 __uint32 maxclusters=((15 /*sectors of alloc info*/
1362 *512 /*bytes*/)
1363 -8 /* checksum bytes */)
1364 *8 /* bits per byte */;
1365 // represents ~ 61376 allocatable clusters
1366#if (HD24FSDEBUG_QUICKFORMAT==1)
1367 cout << "max # of clusters=" << maxclusters << endl;
1368#endif
1369 __uint32 allocatableaudioblocks=(allocatablesectors - (allocatablesectors%0x480))/0x480;
1370#if (HD24FSDEBUG_QUICKFORMAT==1)
1371 cout << "allocatable audio blocks=" << allocatableaudioblocks << endl;
1372#endif
1373 // given the maximum number of clusters
1374 // and the total number of allocatable audio blocks,
1375 // we must decide on the number of audio blocks per cluster.
1376 __uint32 rest=0;
1377 if ((allocatableaudioblocks%maxclusters)>0) rest++;
1378 __uint32 blockspercluster=rest+((allocatableaudioblocks-(allocatableaudioblocks%maxclusters))/maxclusters);
1379#if (HD24FSDEBUG_QUICKFORMAT==1)
1380 cout << "blocks per cluster="<<blockspercluster<< endl;
1381#endif
1382 Convert::setint32(buffer,FSINFO_AUDIOBLOCKS_PER_CLUSTER,blockspercluster);
1383
1384 // offset 0x14h: number of audio blocks per cluster
1385 __uint32 allocatableclusters=(allocatableaudioblocks-(allocatableaudioblocks%blockspercluster))/blockspercluster;
1386 Convert::setint32(buffer,FSINFO_FREE_CLUSTERS_ON_DISK,allocatableclusters);
1387#if (HD24FSDEBUG_QUICKFORMAT==1)
1388 cout << "allocatableclusters="<<allocatableclusters<< endl;
1389#endif
1390 fstfix(buffer,512); // convert back into native format
1391 }
1392
1393 /* Calculate the proper checksum for the bootinfo */
1394 setsectorchecksum(buffer,
1395 0 /* startoffset */,
1396 0 /* sector */,
1397 1 /*sectorcount */
1398 );
1399 return;
1400}
1401
1402unsigned char* hd24fs::readbootinfo()
1403{
1404 // read boot info
1405
1406 if (sector_boot==NULL)
1407 {
1408#if (HD24FSDEBUG_QUICKFORMAT==1)
1409 cout << "Malloc space for bootsector" << endl;
1410#endif
1411 sector_boot=(unsigned char *)memutils::mymalloc("readbootinfo",1024,1);
1412 }
1413
1414 if (sector_boot!=NULL)
1415 {
1416#if (HD24FSDEBUG_QUICKFORMAT==1)
1417 cout << "Malloc space for bootsector succeeded" << endl;
1418 cout << "forcemode=" << forcemode << endl;
1419#endif
1420 if (formatting||(!forcemode)) {
1421#if (HD24FSDEBUG_QUICKFORMAT==1)
1422 cout << "Reading sector (From disk)" << endl;
1423#endif
1424 readsector(devhd24,0,sector_boot);
1425 } else {
1426#if (HD24FSDEBUG_QUICKFORMAT==1)
1427 cout << "Using internal boot." << endl;
1428#endif
1429 useinternalboot(sector_boot,0);
1430 }
1431 fstfix(sector_boot,512);
1432 } else {
1433#if (HD24FSDEBUG_QUICKFORMAT==1)
1434 cout << "Malloc space for bootsector failed" << endl;
1435#endif
1436 }
1437#if (HD24FSDEBUG_QUICKFORMAT==1)
1438 dumpsector((const char*)sector_boot);
1439#endif
1440 return sector_boot;
1441}
1442
1443unsigned char* hd24fs::readdriveusageinfo()
1444{
1445#if (HD24FSDEBUG==1)|| (HD24FSDEBUG_QUICKFORMAT==1)
1446 cout << "hd24fs::readdriveusageinfo()" << endl;
1447#endif
1448
1449 // read file allocation table/disk usage table
1450 unsigned int driveusagecount=driveusagesectorcount();
1451 if (sectors_driveusage==NULL)
1452 {
1453
1454 sectors_driveusage=(unsigned char *)memutils::mymalloc("readdriveusageinfo/sectors_driveusage",512*(driveusagecount+1),1);
1455 }
1456 //cout << "ptr=" << sectors_driveusage << endl;
1457 if (sectors_driveusage!=NULL)
1458 {
1459#if (HD24FSDEBUG_QUICKFORMAT==1)
1460 cout << "hd24fs::readdriveusageinfo() reading "
1461 << driveusagecount << "sectors into buffer at "
1462 << &sectors_driveusage << endl;
1463#endif
1464 readsectors(devhd24,driveusagefirstsector(),sectors_driveusage,driveusagecount);
1465 fstfix(sectors_driveusage,512*driveusagecount);
1466
1467 }
1468#if (HD24FSDEBUG_QUICKFORMAT==1)
1469 cout << "Dumping newly read sector to screen:" << endl ;
1470 dumpsector((const char*)sectors_driveusage);
1471#endif
1472 return sectors_driveusage;
1473}
1474
1475unsigned char* hd24fs::resetsongusage()
1476{
1477 // Reset song usage table. First we occupy all of it;
1478 // then we make only accessible entries available.
1479 if (sectors_songusage==NULL)
1480 {
1481 sectors_songusage=(unsigned char *)memutils::mymalloc("resetsongusage",512*3,1);
1482 if (sectors_songusage==NULL)
1483 {
1484 return NULL;
1485 }
1486 }
1487
1488 if (sectors_songusage!=NULL)
1489 {
1490 for (int i=0;i<512*3;i++)
1491 {
1492 sectors_songusage[i]=0xff;
1493 }
1494 }
1495
1496 __uint32 i;
1497 // table is initialized, now populate it.
1498 __uint32 maxprojs=this->maxprojects();
1499 __uint32 maxsongcount=this->maxsongsperproject();
1500 __uint32 totentries=maxprojs*maxsongcount; // 99 songs, 99 projects
1501#if (HD24FSDEBUG==1)
1502 cout << "Clear song usage table..."<< endl;
1503 cout << "this=" << this << endl;
1504#endif
1505 for (i=0;i<totentries;i++) {
1506 disablebit(i,sectors_songusage);
1507 // this is based on song sectors.
1508 // That is, entry 0=sec 0x77,
1509 // entry 1=sec 0x77+7, etc.
1510 }
1511#if (HD24FSDEBUG==1)
1512 cout << "Usage table cleared." << endl;
1513#endif
1514 return sectors_songusage;
1515}
1516
1517unsigned char* hd24fs::resetdriveusage()
1518{
1519#if (HD24FSDEBUG==1)||(HD24FSDEBUG_QUICKFORMAT==1)
1520 cout << "hd24fs::resetdriveusage()" << endl;
1521#endif
1522 // Reset drive usage table. First we occupy all of it;
1523 // then we make only accessible entries available.
1524
1525 if (this->sectors_driveusage==NULL)
1526 {
1527 unsigned char* du=(unsigned char *)memutils::mymalloc("resetdriveusage/sectors_driveusage",512*15,1);
1528 sectors_driveusage=du;
1529 if (this->sectors_driveusage==NULL)
1530 {
1531 return NULL;
1532 }
1533 }
1534
1535 for (int i=0;i<512*15;i++)
1536 {
1537 sectors_driveusage[i]=0xff;
1538 }
1539
1540 if (formatting||(sector_boot==NULL) )
1541 {
1542#if (HD24FSDEBUG_QUICKFORMAT==1)
1543 cout << "hd24fs::resetdriveusage() - reloading boot info " << endl;
1544#endif
1545
1546 this->readbootinfo();
1547 } else {
1548#if (HD24FSDEBUG_QUICKFORMAT==1)
1549 cout << "hd24fs::resetdriveusage() - using current (not reloading) boot info " << endl;
1550#endif
1551
1552 }
1553
1554 __uint32 i;
1555 // table is initialized, now populate it.
1556 __uint32 totentries=Convert::getint32(sector_boot,FSINFO_FREE_CLUSTERS_ON_DISK);
1557#if (HD24FSDEBUG_QUICKFORMAT==1)
1558 cout << "According to superblock, free clusters on disk=" << totentries << endl;
1559 dumpsector((const char*)sector_boot);
1560#endif
1561#if (HD24FSDEBUG_QUICKFORMAT==1)
1562 cout << "before reset, drive usage looks as follows: "<< endl;
1563 dumpsector((const char*)sectors_driveusage);
1564#endif
1565 for (i=0;i<totentries;i++) {
1566 disablebit(i,sectors_driveusage);
1567 }
1568#if (HD24FSDEBUG_QUICKFORMAT==1)
1569 cout << "after reset, drive usage looks as follows: "<< endl;
1570 dumpsector((const char*)sectors_driveusage);
1571#endif
1572
1573#if (HD24FSDEBUG==1)
1574 cout << "Drive usage table cleared." << endl;
1575#endif
1576 return sectors_driveusage;
1577}
1578
1579unsigned char* hd24fs::calcsongusage()
1580{
1581 resetsongusage();
1582
1583 hd24project* currproj=NULL;
1584 __uint32 projcount=projectcount();
1585 __uint32 i;
1586 __uint32 j;
1587 for (i=1; i<=projcount;i++)
1588 {
1589 if (currproj!=NULL)
1590 {
1591 delete(currproj);
1592 currproj=NULL;
1593 }
1594 currproj=getproject(i);
1595 if (currproj==NULL)
1596 {
1597 continue;
1598 }
1599
1600 // currproj!=NULL.
1601 __uint32 currsongcount=currproj->songcount();
1602 for (j=1; j<=currsongcount;j++)
1603 {
1604 // get song sector info.
1605 __uint32 songsector = currproj->getsongsectornum(j);
1606 if (songsector==0)
1607 {
1608 // song at given entry is not in use
1609 // in this project, no need to mark it as used.
1610 continue;
1611 }
1612
1613 // mark the song used based on its entry number
1614 // (calculated from the sector where it lives)
1615 __uint32 songentry=songsector2entry(songsector);
1616 if (songentry!=INVALID_SONGENTRY)
1617 {
1618 enablebit(songentry,sectors_songusage);
1619 }
1620 }
1621
1622 if (currproj!=NULL)
1623 {
1624 delete(currproj);
1625 currproj=NULL;
1626 }
1627 }
1628 return sectors_songusage;
1629}
1630
1631void hd24fs::refreshsongusage()
1632{
1633 unsigned char* songusage=calcsongusage();
1634 __uint32 sectornum=2; /* TODO: get from fs */
1635 __uint32 sectorcount=3; /* TODO: get from fs */
1636 fstfix(songusage,sectorcount*512);
1637 setsectorchecksum(songusage,
1638 0 /* startoffset */,
1639 sectornum /* sector */,
1640 sectorcount /*sectorcount */
1641 );
1642 this->writesectors(this->devhd24,
1643 sectornum,
1644 songusage,
1645 sectorcount);
1646 fstfix(songusage,sectorcount*512);
1647
1648 /* this also implies we need to update the superblock
1649 with the current song count */
1650 __uint32 songcount=0;
1651 for (int i=0;i<99*99;i++) {
1652 if (!(isbitzero(i,songusage)))
1653 {
1654 songcount++;
1655 }
1656 };
1657 songsondisk(songcount);
1658 fstfix(sector_boot,512);
1659 setsectorchecksum(sector_boot,
1660 0 /* startoffset */,
1661 0 /* sector */,
1662 1 /*sectorcount */);
1663 this->writesectors(this->devhd24,
1664 0,
1665 sector_boot,
1666 1);
1667 fstfix(sector_boot,512);
1668 return;
1669}
1670
1671unsigned char* hd24fs::getsector_diskinfo()
1672{
1673 getsector_bootinfo();
1674 unsigned char* targetbuf=sector_diskinfo;
1675 if (/*formatting||*/(sector_diskinfo==NULL) )
1676 {
1677 targetbuf=readdiskinfo();
1678 }
1679 return sector_diskinfo;
1680}
1681
1682unsigned char* hd24fs::getsector_bootinfo()
1683{
1684 unsigned char* targetbuf=sector_boot;
1685 if (/*formatting||*/(sector_boot==NULL) )
1686 {
1687#if (HD24FSDEBUG_QUICKFORMAT==1)
1688 cout << "Re-reading bootinfo now." << endl;
1689#endif
1690 targetbuf=readbootinfo();
1691 }
1692 return targetbuf;
1693}
1694
1695unsigned char* hd24fs::getsectors_driveusage()
1696{
1697#if (HD24FSDEBUG_QUICKFORMAT==1)
1698 cout << "hd24fs::getsectors_driveusage()" << endl;
1699#endif
1700
1701 readbootinfo();
1702 if (sectors_driveusage==NULL)
1703 {
1704 sectors_driveusage=readdriveusageinfo();
1705 }
1706 return sectors_driveusage;
1707}
1708
1709unsigned char* hd24fs::getcopyofusagetable()
1710{
1711 unsigned char* copyusagetable=(unsigned char*)memutils::mymalloc("copyusagetable",15*512,1);
1712 if (copyusagetable==NULL)
1713 {
1714 /* Out of memory */
1715 return NULL;
1716 }
1717
1718 // copy current drive usage table to a copy;
1719 readdriveusageinfo();
1720 int i;
1721 for (i=0;i<(512*15);i++) {
1722 copyusagetable[i]=sectors_driveusage[i];
1723 }
1724 return copyusagetable;
1725}
1726
1727string* hd24fs::volumename()
1728{
1729 if (!(isOpen()))
1730 {
1731 return new string("");
1732 }
1733 getsector_diskinfo();
1734 return Convert::readstring(sector_diskinfo,DRIVEINFO_VOLUME,64);
1735}
1736
1737void hd24fs::setvolumename(string newname)
1738{
1739 if (sector_diskinfo==NULL)
1740 {
1741 readdiskinfo();
1742 }
1743 this->setname(sector_diskinfo,newname,DRIVEINFO_VOLUME_8,DRIVEINFO_VOLUME);
1744 return;
1745}
1746
1747unsigned long hd24fs::driveusagesectorcount()
1748{
1749 if (!(isOpen()))
1750 {
1751 cout << "FS not open!";
1752 return 0;
1753 }
1754#if (HD24FSDEBUG_QUICKFORMAT==1)
1755 cout << "Figuring out number of sectors used for drive usage"
1756 << endl;
1757#endif
1758
1759 getsector_bootinfo();
1760 return Convert::getint32(sector_boot,FSINFO_NUMSECTORS_DRIVEUSAGE);
1761}
1762
1763unsigned long hd24fs::clustercount()
1764{
1765 /*
1766 Clustercount=
1767 (number of allocatable sectors on disk)/
1768 ((sectors per audioblock)*(audioblocks per cluster))
1769 */
1770 if (!(isOpen()))
1771 {
1772 return 0;
1773 }
1774 getsector_bootinfo();
1775 __uint32 allocatablesectorcount=
1776 Convert::getint32(sector_boot,FSINFO_ALLOCATABLE_SECTORCOUNT);
1777 __uint32 audioblocksize=
1778 Convert::getint32(sector_boot,FSINFO_BLOCKSIZE_IN_SECTORS);
1779 __uint32 clustersize=
1780 Convert::getint32(sector_boot,FSINFO_AUDIOBLOCKS_PER_CLUSTER)
1781 *audioblocksize;
1782
1783 allocatablesectorcount-=(allocatablesectorcount%clustersize);
1784 return allocatablesectorcount/clustersize;
1785}
1786
1787void hd24fs::dumpclusterusage(unsigned char* usagebuffer)
1788{
1789 if (!(isOpen()))
1790 {
1791 return;
1792 }
1793 __uint32 clusters=clustercount();
1794 for (__uint32 i=0;i<clusters;i++) {
1795 if (isfreecluster(i,usagebuffer)) {
1796 cout << "0";
1797 } else {
1798 cout << "1";
1799 }
1800 }
1801 cout <<endl;
1802 return;
1803}
1804
1805void hd24fs::dumpclusterusage2(unsigned char* usagebuffer)
1806{
1807 __uint32 clusters=clustercount();
1808 __uint32 currpos=0;
1809 cout << "DumpClusterUsage2" << endl;
1810 while (currpos<clusters) {
1811 __uint32 blockstart=currpos;
1812 while (isfreecluster(blockstart,usagebuffer) && (blockstart<clusters)) {
1813 blockstart++;
1814 }
1815// cout << "Block starts at cluster " <<blockstart << endl;
1816 if (blockstart==clusters) {
1817 break;
1818 }
1819
1820 // blockstart now points to a nonfree cluster
1821 __uint32 blockend=blockstart;
1822 while (!isfreecluster(blockend,usagebuffer) && (blockend<clusters)) {
1823 blockend++;
1824 }
1825 // blockend now points to a free cluster
1826 currpos=blockend;
1827 __uint32 blocklen=blockend-blockstart;
1828 printf("%x %x\n",(unsigned int) cluster2sector(blockstart),(unsigned int)( getblockspercluster()*blocklen ));
1829 }
1830}
1831
1832unsigned long hd24fs::driveusagefirstsector()
1833{
1834 if (!(isOpen()))
1835 {
1836 return 0;
1837 }
1838 getsector_bootinfo();
1839
1840 return Convert::getint32(sector_boot,FSINFO_STARTSECTOR_DRIVEUSAGE);
1841}
1842
1843unsigned char* hd24fs::findorphanclusters()
1844{
1845 if (!(isOpen()))
1846 {
1847 return NULL;
1848 }
1849 __uint32 driveusagecount=driveusagesectorcount();
1850 getsectors_driveusage();
1851 int numprojs=projectcount();
1852
1853 if (sectors_orphan==NULL) {
1854 // only allocate once (free on object destruct)
1855 sectors_orphan=(unsigned char *)memutils::mymalloc("findorphanclusters",512*(driveusagecount+1),1);
1856 }
1857 readsectors(devhd24,driveusagefirstsector(),sectors_orphan,driveusagecount);
1858 fstfix(sectors_orphan,512*driveusagecount);
1859
1860 for (int proj=1; proj<=numprojs; proj++) {
1861 hd24project* currproj=this->getproject(proj);
1862 int numsongs=currproj->songcount();
1863 for (int song=1; song<=numsongs; song++) {
1864 hd24song* currsong=currproj->getsong(song);
1865 if (currsong==NULL) continue;
1866 currsong->unmark_used_clusters(sectors_orphan);
1867 delete currsong;
1868 }
1869 if (currproj!=NULL) {
1870 delete currproj;
1871 currproj=NULL;
1872 }
1873 }
1874 return sectors_orphan;
1875}
1876
1877bool hd24fs::isbitzero(unsigned long i,unsigned char* usagebuffer)
1878{
1879 int bitnum=i%32;
1880 i-=bitnum;
1881 i/=32; // i now is word num
1882 i*=4; // i now is offset
1883 __uint32 getword=Convert::getint32(usagebuffer,i);
1884 __uint32 mask=1;
1885#if (HD24FSDEBUG_BITSET==1)
1886 cout << "bitnum=" << bitnum << " ";
1887#endif
1888 mask=mask<<bitnum;
1889 __uint32 bitval=(getword & mask);
1890#if (HD24FSDEBUG_BITSET==1)
1891 cout << "bitval=" << bitval << endl;
1892#endif
1893 if (bitval == 0) return true;
1894 return false;
1895}
1896
1897void hd24fs::enablebit(__uint32 ibitnum,unsigned char* usagebuffer)
1898{
1899#if (HD24FSDEBUG_BITSET==1)
1900 cout << "enable bit " << ibitnum << endl;
1901#endif
1902 int bitnum=ibitnum%32;
1903 ibitnum-=bitnum;
1904 ibitnum/=32; // i now is word num
1905 ibitnum*=4; // i now is byte offset of word
1906 __uint32 getword=Convert::getint32(usagebuffer,ibitnum);
1907 __uint32 mask=1;
1908 mask=mask<<bitnum;
1909#if (HD24FSDEBUG_BITSET==1)
1910 cout << "getword=" << getword << "mask=" << mask << endl;
1911#endif
1912 getword=getword|mask;
1913 Convert::setint32(usagebuffer,ibitnum,getword);
1914}
1915
1916void hd24fs::disablebit(__uint32 ibitnum,unsigned char* usagebuffer)
1917{
1918#if (HD24FSDEBUG_BITSET==1)
1919 cout << "disable bit " << ibitnum << endl;
1920#endif
1921 int bitnum=ibitnum%32;
1922 ibitnum-=bitnum;
1923 ibitnum/=32; // i now is word num
1924 ibitnum*=4; // i now is offset
1925 __uint32 getword=Convert::getint32(usagebuffer,ibitnum);
1926 __uint32 mask=1;
1927 mask=mask<<bitnum;
1928#if (HD24FSDEBUG_BITSET==1)
1929 cout << "getword=" << getword << "mask=" << mask << endl;
1930#endif
1931 getword=getword& (0xFFFFFFFF ^ mask);
1932#if (HD24FSDEBUG_BITSET==1)
1933 cout << "new getword=" << getword << endl;
1934#endif
1935 Convert::setint32(usagebuffer,ibitnum,getword);
1936}
1937
1938bool hd24fs::isfreecluster(unsigned long i,unsigned char* usagebuffer)
1939{
1940 return isbitzero(i,usagebuffer);
1941}
1942
1943void hd24fs::allocatecluster(__uint32 clusternum,unsigned char* usagebuffer)
1944{
1945 enablebit(clusternum,usagebuffer);
1946}
1947
1948void hd24fs::freecluster(__uint32 clusternum,unsigned char* usagebuffer)
1949{
1950 disablebit(clusternum,usagebuffer);
1951}
1952void hd24fs::allocatecluster(__uint32 clusternum)
1953{
1954 allocatecluster(clusternum,sectors_driveusage);
1955}
1956
1957void hd24fs::freecluster(__uint32 clusternum)
1958{
1959 freecluster(clusternum,sectors_driveusage);
1960}
1961
1962unsigned long hd24fs::freeclustercount()
1963{
1964 if (!(isOpen()))
1965 {
1966 return 0;
1967 }
1968#if (HD24FSDEBUG_QUICKFORMAT==1)
1969 cout << "hd24fs::freeclustercount()" << endl;
1970#endif
1971
1972 sectors_driveusage=getsectors_driveusage();
1973
1974 if (sectors_driveusage==NULL)
1975 {
1976 return 0; // cannot get driveusage sectors, 0 clusters free.
1977 }
1978 unsigned long i=0;
1979 __uint32 fsc=driveusagesectorcount();
1980
1981 if (fsc>0xFF) return 0;
1982#if (HD24FSDEBUG_QUICKFORMAT==1)
1983 cout << "Sectors used for drive usage=" << fsc << endl;
1984#endif
1985 __uint32 clusters=((fsc /*sectors of alloc info*/
1986 *512 /*bytes*/)
1987 -8 /* checksum bytes */)
1988 *8 /* bits per byte */;
1989 //unsigned long clusters=((512*fsc-1)+504)*8;
1990#if (HD24FSDEBUG_QUICKFORMAT==1)
1991 cout << "Total clusters=" << clusters << endl;
1992#endif
1993
1994 unsigned long freeclusters=0;
1995 for (i=0;i<clusters;i++) {
1996 if (isfreecluster(i,sectors_driveusage))
1997 {
1998#if (HD24FSDEBUG_QUICKFORMAT==1)
1999 cout << "Cluster " << i << " is free" << endl;
2000#endif
2001 freeclusters++;
2002 }
2003 }
2004 return freeclusters;
2005}
2006
2007string* hd24fs::freespace(unsigned long rate,unsigned long tracks)
2008{
2009 if (!(isOpen()))
2010 {
2011 return new string("");
2012 }
2013
2014 unsigned long freeclusters=freeclustercount();
2015#if (HD24FSDEBUG_QUICKFORMAT==1)
2016 cout << "free clusters=" << freeclusters << endl;
2017#endif
2018 __uint64 freesectors=freeclusters*getblocksizeinsectors()*getblockspercluster();
2019#if (HD24FSDEBUG_QUICKFORMAT==1)
2020 cout << "free sectors=" << freesectors << endl;
2021#endif
2022 __uint64 freebytes=freesectors*SECTORSIZE;
2023#if (HD24FSDEBUG_QUICKFORMAT==1)
2024 cout << "free bytes=" << freesectors << endl;
2025#endif
2026 __uint64 freesamples=(__uint64)(freebytes/3);
2027#if (HD24FSDEBUG_QUICKFORMAT==1)
2028 cout << "free samples=" << freesamples << endl;
2029#endif
2030 __uint64 freeseconds=(__uint64)(freesamples/rate/tracks);
2031 unsigned long freehours=(freeseconds-(freeseconds%3600))/3600;
2032 freeseconds-=(freehours*3600);
2033 unsigned long freeminutes=(freeseconds-(freeseconds%60))/60;
2034 freeseconds-=(freeminutes*60);
2035 string* newst=Convert::int2str(freehours);
2036 *newst+=" hr ";
2037 string* freemins=Convert::int2str(freeminutes,2,"0");
2038 *newst+=*freemins;
2039 delete freemins;
2040 *newst+=" min ";
2041 string* freesecs=Convert::int2str(freeseconds,2,"0");
2042 *newst+=*freesecs;
2043 delete freesecs;
2044 *newst+=" sec ";
2045 return newst; // throw exception?
2046}
2047
2048string* hd24fs::version()
2049{
2050 if (!(isOpen()))
2051 {
2052 return new string("");
2053 }
2054 getsector_bootinfo();
2055 string* newst=Convert::readstring(sector_boot,FSINFO_VERSION_MAJOR,1);
2056 *newst+=".";
2057 string* dummy=Convert::readstring(sector_boot,FSINFO_VERSION_MINOR,2);
2058 *newst+=*dummy;
2059 delete dummy;
2060 return newst;
2061}
2062
2063unsigned long hd24fs::maxprojects()
2064{
2065 if (!(isOpen()))
2066 {
2067 return 0;
2068 }
2069 getsector_bootinfo();
2070 unsigned long maxprojs=Convert::getint32(sector_boot,FSINFO_MAXPROJECTS);
2071 if (maxprojs>99) {
2072 maxprojs=99;
2073 /* safety feature while no larger project
2074 counts are known to be valid; gives
2075 more stability when working with corrupt drives */
2076 this->writeprotected=true;
2077 }
2078 return maxprojs;
2079}
2080
2081unsigned long hd24fs::getblocksizeinsectors()
2082{
2083 if (!(isOpen()))
2084 {
2085 return 0;
2086 }
2087 getsector_bootinfo();
2088 if (forcemode) {
2089 return 0x480;
2090 }
2091 unsigned long blocksize=Convert::getint32(sector_boot,FSINFO_BLOCKSIZE_IN_SECTORS);
2092 if (blocksize!=0x480)
2093 {
2094 this->writeprotected=true;
2095 }
2096 return blocksize;
2097}
2098
2099unsigned long hd24fs::getbytesperaudioblock()
2100{
2101 return getblocksizeinsectors()*512;
2102}
2103
2104unsigned long hd24fs::getblockspercluster()
2105{
2106 if (!(isOpen()))
2107 {
2108 return 0;
2109 }
2110 getsector_bootinfo();
2111 unsigned long maxprojs=Convert::getint32(sector_boot,FSINFO_AUDIOBLOCKS_PER_CLUSTER);
2112 return maxprojs;
2113}
2114
2115unsigned long hd24fs::maxsongsperproject()
2116{
2117 if (!(isOpen()))
2118 {
2119 return 0;
2120 }
2121 getsector_bootinfo();
2122 unsigned long maxsongs=Convert::getint32(sector_boot,FSINFO_MAXSONGSPERPROJECT);
2123 return maxsongs;
2124}
2125
2126__uint32 hd24fs::getprojectsectornum(__uint32 i)
2127{
2128#if (HD24FSDEBUG==1)
2129 cout << "hd24fs::getprojectsectornum("<<i<<")"<< endl;
2130#endif
2131 // 1-based project sectornum
2132 if (!(isOpen()))
2133 {
2134 return 0;
2135 }
2136 if (i<1)
2137 {
2138 return 0;
2139 }
2140 if (i>maxprojects())
2141 {
2142 return 0;
2143 }
2144 getsector_diskinfo();
2145 unsigned long projsec=Convert::getint32(sector_diskinfo,
2146 DRIVEINFO_PROJECTLIST+((i-1)*4));
2147
2148#if (HD24FSDEBUG==1)
2149 cout << "projsec = " << projsec << endl;
2150#endif
2151 return projsec;
2152}
2153
2154void hd24fs::lastprojectid(signed long projectid)
2155{
2156 if (!(isOpen()))
2157 {
2158 return;
2159 }
2160 getsector_diskinfo();
2161 __uint32 lastprojsec=getprojectsectornum(projectid);
2162 if (lastprojsec==0) {
2163 return;
2164 }
2165 if (projectid==lastprojectid())
2166 {
2167 // nothing changed- nothing to save
2168 return;
2169 }
2170
2171 Convert::setint32(sector_diskinfo,DRIVEINFO_LASTPROJ,lastprojsec);
2172 savedriveinfo();
2173 return;
2174}
2175
2176signed long hd24fs::lastprojectid()
2177{
2178 if (!(isOpen()))
2179 {
2180 return -1;
2181 }
2182 getsector_diskinfo();
2183 unsigned long lastprojsec=Convert::getint32(sector_diskinfo,DRIVEINFO_LASTPROJ);
2184 if (lastprojsec==0) {
2185 // TODO: This differs from the real HD24 where even
2186 // on a freshly formatted drive there always is at least
2187 // one project.
2188 return -1;
2189 }
2190 int i;
2191 int maxprojs=maxprojects();
2192 for (i=1;i<=maxprojs;i++)
2193 {
2194 unsigned long projsec=getprojectsectornum(i);
2195
2196 if (projsec==lastprojsec)
2197 {
2198 return i;
2199 }
2200 }
2201 // no default project. hm......
2202 if (maxprojs>=1) {
2203 return 1;
2204 }
2205 return -1;
2206}
2207
2208__uint32 hd24fs::getunusedsongsector()
2209{
2210 if (!(isOpen()))
2211 {
2212 return 0; // return 0- this is an invalid songsector
2213 // so error is detectable
2214 }
2215
2216 // generate an up-to-date song usage table.
2217 unsigned char* songusage=calcsongusage();
2218
2219 int currsongentry=0;
2220 signed long foundentry=-1;
2221 int maxprojs=this->maxprojects();
2222 int maxsongcount=this->maxsongsperproject();
2223 int totentries=maxprojs*maxsongcount; // 99 songs, 99 projects
2224 while (currsongentry<totentries) // 99 sec, 99 proj
2225 {
2226 if (isbitzero(currsongentry,songusage)) {
2227 foundentry=currsongentry;
2228 break;
2229 }
2230 currsongentry++;
2231 }
2232 if (foundentry==-1)
2233 {
2234 return 0;
2235 }
2236 return songentry2sector(foundentry);
2237}
2238
2239void hd24fs::allocsongentry(unsigned long songentry)
2240{
2241 enablebit(songentry,sectors_songusage);
2242}
2243
2244unsigned long hd24fs::projectcount()
2245{
2246 if (!(isOpen()))
2247 {
2248 return 0;
2249 }
2250 getsector_diskinfo();
2251 unsigned long lastprojsec=Convert::getint32(sector_diskinfo,DRIVEINFO_LASTPROJ);
2252 if (lastprojsec==0)
2253 {
2254 return 0;
2255 }
2256 __uint32 projcount=Convert::getint32(sector_diskinfo,DRIVEINFO_PROJECTCOUNT);
2257 if (projcount>maxprojects()) return maxprojects();
2258
2259 return projcount;
2260}
2261
2262int hd24fs::mode() {
2263 return p_mode;
2264}
2265
2266hd24project* hd24fs::getproject(__sint32 projectid)
2267{
2268 __uint32 projsec=getprojectsectornum(projectid); // 1-based
2269 if (projsec==0) {
2270 return NULL;
2271 }
2272 return new hd24project(this,projectid);
2273}
2274
2275hd24project* hd24fs::createproject(const char* projectname)
2276{
2277#if (HD24FSDEBUG==1)
2278 cout << "hd24fs::createproject(" << projectname << ")" << endl;
2279// cout << "Driveusage before createproject=" << (int)(this->sectors_driveusage) << endl;
2280#endif
2281 /* This creates a new project (with given project name)
2282 on the drive (if possible).
2283 NULL is returned when unsuccessful, a pointer to the
2284 project otherwise.
2285 */
2286#if (HD24FSDEBUG==1)
2287 cout << "hd24fs asked to create project " << projectname << endl;
2288#endif
2289 int i;
2290 // find first project with project sector num 0!
2291 int maxprojs=maxprojects();
2292
2293 getsector_bootinfo();
2294 if (sector_boot==NULL) {
2295 // unknown cluster size.
2296 return 0;
2297 }
2298 __uint32 firstprojsec=Convert::getint32(sector_boot,FSINFO_FIRST_PROJECT_SECTOR);
2299 cout << "Firstprojsec="<< firstprojsec << endl;
2300 __uint32 secsperproj=Convert::getint32(sector_boot,FSINFO_SECTORS_PER_PROJECT);
2301 cout << "Sectors per project="<< secsperproj << endl;
2302
2303 // Let's calculate a list of unused project sectors
2304 char* projused=(char*)memutils::mymalloc("createproject",maxprojs,1);
2305 if (projused==NULL) {
2306 return 0; // out of memory
2307 }
2308
2309 for (i=0;i<maxprojs;i++) {
2310 projused[i]=0;
2311 }
2312
2313 for (i=1;i<=maxprojs;i++) {
2314 __uint32 projsec=getprojectsectornum(i); // 1-based
2315 if (projsec!=0)
2316 {
2317 /* projects do not necessarily have to
2318 be stored on disk in the same order
2319 as their project numbers-
2320 so project 1 can be at sector 0x15
2321 while project 2 is at sector 0x14.
2322 This is why we have to convert project
2323 sector to project slot. The cast to int
2324 makes sure we don't accidentally end up
2325 with a float index that can be misinterpreted. */
2326 projused[(int)((projsec-firstprojsec)/secsperproj)]=1;
2327 }
2328 }
2329
2330 int foundslotnum=0;
2331 for (i=1;i<=maxprojs;i++)
2332 {
2333 __uint32 projsec=getprojectsectornum(i); // 1-based
2334
2335 if (projsec==0)
2336 {
2337 foundslotnum=i;
2338 break;
2339 }
2340 }
2341
2342 // Now find an unused project sector
2343 __uint32 foundsecnum=0;
2344 for (i=0;i<maxprojs;i++) {
2345 if (projused[i]==0) {
2346 foundsecnum=(i*secsperproj)+firstprojsec;
2347 break;
2348 }
2349 }
2350 memutils::myfree("projused",projused);
2351
2352 if (foundslotnum==0)
2353 {
2354 // no unused slots.
2355 return NULL;
2356 }
2357 __uint32 projectid=foundslotnum;
2358 foundslotnum--; // use 0-based slot num
2359
2360 if (foundsecnum==0) {
2361 // no unsused project sectors found.
2362 // This is seriously fishy as there *are*
2363 // unused slots- so that should never happen.
2364 // Looks like we're dealing with a corrupt FS!
2365 this->writeprotected=true;
2366 return NULL;
2367 }
2368 // Now to assign the first unused project sector
2369 // to the first unused project slot.
2370
2371 // First, update the drive info.
2372 getsector_diskinfo();
2373
2374 // Add the new project pointer to the disk info:
2375 Convert::setint32(sector_diskinfo,DRIVEINFO_PROJECTLIST+(foundslotnum*4),foundsecnum);
2376 Convert::setint32(sector_diskinfo,DRIVEINFO_LASTPROJ,foundsecnum);
2377
2378 Convert::setint32(sector_diskinfo,DRIVEINFO_PROJECTCOUNT,
2379 Convert::getint32(sector_diskinfo,DRIVEINFO_PROJECTCOUNT)+1);
2380
2381 bool isnew=true;
2382 hd24project* newproject=new hd24project(this,projectid,foundsecnum,projectname,isnew);
2383 savedriveinfo();
2384
2385 return newproject;
2386}
2387
2388bool hd24fs::isallinput()
2389{
2390 return this->allinput;
2391}
2392
2393void hd24fs::setallinput(bool p_allinput)
2394{
2395 this->allinput=p_allinput;
2396}
2397
2398void hd24fs::setallinput(void)
2399{
2400 this->setallinput(true);
2401}
2402
2403/* These three functions are for the 'auto input' button
2404 (having to do with automatic toggling of monitoring
2405 between 'tape' and inputs during a punch in */
2406bool hd24fs::isautoinput()
2407{
2408 return this->autoinput;
2409}
2410
2411void hd24fs::setautoinput(bool p_autoinput)
2412{
2413 this->autoinput=p_autoinput;
2414}
2415
2416void hd24fs::setautoinput(void)
2417{
2418 this->setautoinput(true);
2419}
2420
2421void hd24fs::writebackupblock(__uint32 p_sector,__uint32 p_blocksize,
2422 __uint32 lastsec,bool fullcommit)
2423{
2424 /** Used by commit. This writes a logical block
2425 of file system data to the end of the drive. */
2426 unsigned char backbuf[1024];
2427
2428 __uint32 i;
2429 __uint32 blocksize=p_blocksize;
2430
2431 if (fullcommit==false)
2432 {
2433 // we're doing a quick commit, so only backup
2434 // changed blocks.
2435 if (p_sector>highestFSsectorwritten) return;
2436 }
2437
2438 for (i=1;i<=blocksize;i++) {
2439 // read sector $sector+$i-1
2440 // write to sector -($sector+1+$blocksize-$i)
2441 // (where -1= last sector)
2442 __uint32 currentsourcesector=p_sector+(i-1);
2443
2444 readsector_noheader(this, currentsourcesector, backbuf);
2445 __uint32 targetsector=(lastsec-(p_sector+1+blocksize-i))+1;
2446 // cout << "write sec " << targetsector << endl;
2447 writesector(this->devhd24,targetsector,backbuf);
2448 }
2449}
2450
2451bool hd24fs::commit()
2452{
2453 // default commit is a quick commit rather than full commit.
2454 // A quick commit only commits sectors up to the last project/song
2455 // sector changed.
2456 return this->commit(false);
2457}
2458bool hd24fs::commit(bool fullcommit)
2459{
2460 /** This creates a backup of the file system to the end of the drive. */
2461
2462
2463#if (HD24FSDEBUG==1)
2464 cout << "hd24fs::commit()" << endl;
2465// cout << "Driveusage before commit=" << (int)(this->sectors_driveusage) << endl;
2466#endif
2467 if (this->headersectors!=0)
2468 {
2469 // ehm. Obviously we're not going to overwrite the
2470 // end of the drive with header file information,
2471 // as that would defeat the purpose of header files
2472 // (which is to allow safe read-only operation).
2473 return true;
2474 };
2475 __uint32 sector=0;
2476 __uint32 blocksize=1;
2477 __uint32 count=1;
2478 __uint32 lastsec=getlastsectornum();
2479 writebackupblock(sector,blocksize,lastsec,fullcommit); // backup superblock
2480
2481 sector+=(blocksize*count);
2482 blocksize=1;
2483 count=1;
2484
2485 writebackupblock(sector,blocksize,lastsec,fullcommit); // backup drive info
2486
2487 sector+=(blocksize*count);
2488 blocksize=3;
2489 count=1;
2490 writebackupblock(sector,blocksize,lastsec,fullcommit); // Backup undo (?) usage
2491
2492 sector+=(blocksize*count);
2493 blocksize=15;
2494 count=1;
2495 writebackupblock(sector,blocksize,lastsec,fullcommit); // Backup drive usage table
2496
2497 sector+=(blocksize*count);
2498 blocksize=1;
2499 count=99;
2500
2501 __uint32 i;
2502 for (i=1;i<=count;i++)
2503 {
2504#if (HD24FSDEBUG_COMMIT==1)
2505 cout <<"Going to write proj backup block no. " << i << endl;
2506#endif
2507 writebackupblock(sector+(i-1),blocksize,lastsec,fullcommit); // Backup project
2508 }
2509
2510 sector+=(blocksize*count);
2511 count=99*99;
2512 for (i=1;i<=count;i++)
2513 {
2514#if (HD24FSDEBUG_COMMIT==1)
2515 cout <<"Going to write song backup block no. " << i << endl;
2516#endif
2517 blocksize=2;
2518 writebackupblock(sector+(7*(i-1)),blocksize,lastsec,fullcommit); // Backup song
2519
2520 blocksize=5;
2521 writebackupblock(sector+(7*(i-1))+2,blocksize,lastsec,fullcommit); // Backup song alloc info
2522 }
2523#if (HD24FSDEBUG_COMMIT==1)
2524 cout <<"Wrote backup blocks" << endl;
2525 cout << "Driveusage after commit=" << (int)(this->sectors_driveusage) << endl;
2526#endif
2527 highestFSsectorwritten=0; // reset
2528 return true;
2529}
2530
2531long unsigned int hd24fs::setsectorchecksum(unsigned char* buffer,unsigned int startoffset,unsigned int startsector,unsigned int sectors)
2532{
2533 // Calculates and sets the checksum for a block of data.
2534 // Data must be in drive-native format.
2535 long unsigned int checksum32 = 0;
2536 unsigned long int totbytes=(SECTORSIZE*sectors);
2537
2538 buffer[startoffset+totbytes-8]=startsector%256;
2539 buffer[startoffset+totbytes-7]=(startsector>>8)%256;
2540 buffer[startoffset+totbytes-6]=255- buffer[startoffset+totbytes-8];
2541 buffer[startoffset+totbytes-5]=255- buffer[startoffset+totbytes-7];
2542
2543 for (unsigned long i = 0; i < totbytes; i += 4)
2544 {
2545 unsigned long num = Convert::getint32(buffer, i+startoffset);
2546 int byte1 = num % 256;
2547 int byte2 = (num >> 8) % 256;
2548 int byte3 = (num >> 16) % 256;
2549 int byte4 = (num >> 24) % 256;
2550 num = byte4 + (byte3 << 8) + (byte2 << 16) + (byte1 << 24);
2551 checksum32 += num;
2552 }
2553 unsigned long oldchecksum=0;
2554 oldchecksum+=((unsigned char)(buffer[startoffset+totbytes-1])); oldchecksum=oldchecksum <<8;
2555 oldchecksum+=((unsigned char)(buffer[startoffset+totbytes-2])); oldchecksum=oldchecksum <<8;
2556 oldchecksum+=((unsigned char)(buffer[startoffset+totbytes-3])); oldchecksum=oldchecksum <<8;
2557 oldchecksum+=((unsigned char)(buffer[startoffset+totbytes-4]));
2558 oldchecksum-=checksum32;
2559 buffer[startoffset+totbytes-4]=oldchecksum%256; oldchecksum=oldchecksum >> 8;
2560 buffer[startoffset+totbytes-3]=oldchecksum%256; oldchecksum=oldchecksum >> 8;
2561 buffer[startoffset+totbytes-2]=oldchecksum%256; oldchecksum=oldchecksum >> 8;
2562 buffer[startoffset+totbytes-1]=oldchecksum%256; oldchecksum=oldchecksum >> 8;
2563 return checksum32;
2564}
2565
2566void hd24fs::savedriveinfo()
2567{
2568 // This is capable of handling only 1-sector-per-project projects
2569 __uint32 driveinfosector=1;
2570 if (sector_diskinfo==NULL)
2571 {
2572 // diskinfo is not available, nothing to do.
2573 return;
2574 }
2575#if (HD24FSDEBUG==1)
2576 cout << "FSTFIX" << endl;
2577#endif
2578 this->fstfix(sector_diskinfo,512); // sector is now once again in native format
2579
2580#if (HD24FSDEBUG==1)
2581 cout << "set checksum" << endl;
2582#endif
2583 this->setsectorchecksum(sector_diskinfo,0,driveinfosector,1);
2584#if (HD24FSDEBUG==1)
2585 cout << "write sectors" << endl;
2586#endif
2587 this->writesectors(this->devhd24,
2588 driveinfosector,
2589 sector_diskinfo,1);
2590
2591#if (HD24FSDEBUG==1)
2592 cout << "unfix" << endl;
2593#endif
2594 this->fstfix(sector_diskinfo,512); // sector is now in 'fixed' format
2595#if (HD24FSDEBUG==1)
2596 cout << "commit" << endl;
2597#endif
2598 this->commit();
2599}
2600
2601void hd24fs::setname(unsigned char* namebuf,string newname,__uint32 shortnameoff,__uint32 longnameoff)
2602{
2603 /** Used for setting song/project/drive names
2604 Long name is up to 64 characters; short name
2605 is up to 10 chars.
2606 */
2607#if (HD24FSDEBUG==1)
2608 cout << "hd24fs::setname("
2609 << "*namebuf=" << *namebuf << ","
2610 << "newname=" << newname << ","
2611 << "shortnameoff="<<shortnameoff << ","
2612 << "longnameoff=" << longnameoff <<");" << endl;
2613#endif
2614 bool foundzero=false;
2615 for (__uint32 i=0;i<64;i++)
2616 {
2617 if (!foundzero)
2618 {
2619 namebuf[longnameoff+i]=newname.c_str()[i];
2620 if (namebuf[longnameoff+i]==0) {
2621 foundzero=true;
2622#if (HD24FSDEBUG==1)
2623 cout << "Found zero at " << i << endl;
2624#endif
2625 }
2626 }
2627 else
2628 {
2629 namebuf[longnameoff+i]=0;
2630 }
2631 }
2632 // Now set FST 1.0 short name
2633 unsigned char* target=namebuf+shortnameoff;
2634 foundzero=false;
2635 __uint32 count=0;
2636 for (__uint32 i=0;i<10;i++)
2637 {
2638 if (!foundzero)
2639 {
2640 target[count]=newname.c_str()[i];
2641 if (target[count]==0)
2642 {
2643 foundzero=true;
2644 }
2645 }
2646 else
2647 {
2648 target[count]=0x20; /* short name is filled out
2649 with spaces */
2650
2651 }
2652 count++;
2653 if (count==8)
2654 {
2655 count=0;
2656 target+=10;
2657 }
2658 }
2659 return;
2660}
2661
2662void hd24fs::savedriveusage()
2663{
2664 __uint32 driveusagesector=5;
2665 __uint32 totsectors=15;
2666 this->fstfix(sectors_driveusage,totsectors*512); // sector is now once again in native format
2667
2668 this->setsectorchecksum(sectors_driveusage,0,driveusagesector,totsectors);
2669 this->writesectors(this->devhd24,
2670 driveusagesector,
2671 sectors_driveusage,totsectors);
2672
2673 this->fstfix(sectors_driveusage,totsectors*512); // sector is now in 'fixed' format
2674#if (HD24FSDEBUG==1)
2675 cout << "free cluster count=" << freeclustercount() << endl;
2676#endif
2677 unsigned char* bootrec=readbootinfo();
2678 // update FSINFO_FREE_CLUSTERS_ON_DISK
2679
2680 Convert::setint32(bootrec,FSINFO_FREE_CLUSTERS_ON_DISK,freeclustercount());
2681 fstfix(bootrec,512); // convert back into native format
2682
2683 /* Calculate the proper checksum for the bootinfo */
2684 setsectorchecksum(bootrec,
2685 0 /* startoffset */,
2686 0 /* sector */,
2687 1 /*sectorcount */
2688 );
2689 this->writesectors(this->devhd24, 0,bootrec,1);
2690 fstfix(bootrec,512); // convert back into fixed format
2691 this->commit();
2692}
2693
2694
2695__uint32 hd24fs::writesuperblock(__uint32 lastsec)
2696{
2697 // writes a new superblock to an unformatted drive.
2698 //
2699 // normal start of data area=1397f6
2700 // size of 1 audio block=0x480 sectors
2701 // fs size=0x77+7*99
2702 // so minimum usable drive is 0x1397f6+0x480+(0x77+(7*99*99))
2703 // =0x14a8ec sectors
2704 if (lastsec<0x14a8ec)
2705 {
2706 // drive is smaller than the minimum needed for
2707 // storing at least 1 audio block.
2708 return RESULT_FAIL;
2709 }
2710 unsigned char superblock[512];
2711 useinternalboot(superblock,lastsec); // this automatically sets sector checksum
2712 writesectors(this->devhd24,0,&superblock[0],1);
2713#if (HD24FSDEBUG_QUICKFORMAT==1)
2714
2715 cout << "Writing superblock." << endl;
2716 dumpsector((const char*)superblock);
2717
2718#endif
2719
2720 force_reload();
2721
2722 readbootinfo();
2723
2724#if (HD24FSDEBUG_CLUSTERddCALC==1)
2725 cout << "Displaying sector after reload." << endl;
2726 dumpsector((const char*)sector_boot);
2727#endif
2728
2729 return RESULT_SUCCESS;
2730}
2731
2732void hd24fs::force_reload()
2733{
2734#if (HD24FSDEBUG==1)
2735 cout << "Free superblock mem" << endl;
2736#endif
2737 if (sector_boot!=NULL)
2738 {
2739 memutils::myfree("sectors_boot",sector_boot);
2740 sector_boot=NULL;
2741 }
2742#if (HD24FSDEBUG==1)
2743 cout << "Free diskinfo mem" << endl;
2744#endif
2745 if (sector_diskinfo!=NULL)
2746 {
2747 memutils::myfree("sectors_diskinfo",sector_diskinfo);
2748 sector_diskinfo=NULL;
2749 }
2750#if (HD24FSDEBUG==1)
2751 cout << "Free drive usage mem" << endl;
2752#endif
2753 if (sectors_driveusage!=NULL)
2754 {
2755 memutils::myfree("sectors_driveusage",sectors_driveusage);
2756 sectors_driveusage=NULL;
2757 }
2758#if (HD24FSDEBUG==1)
2759 cout << "Free orphan sectors mem" << endl;
2760#endif
2761 if (sectors_orphan!=NULL)
2762 {
2763 memutils::myfree("sectors_orphan",sectors_orphan);
2764 sectors_orphan=NULL;
2765 }
2766#if (HD24FSDEBUG==1)
2767 cout << "Free song usage sectors mem" << endl;
2768#endif
2769 if (sectors_songusage!=NULL)
2770 {
2771 memutils::myfree("sectors_songusage",sectors_songusage);
2772 sectors_songusage=NULL;
2773 };
2774
2775}
2776__uint32 hd24fs::writedriveinfo()
2777{
2778 readdiskinfo();
2779 cleardriveinfo(sector_diskinfo);
2780 fstfix(sector_diskinfo,512); // back into native format
2781 writesectors(this->devhd24,1,sector_diskinfo,1);
2782 if (sector_diskinfo!=NULL) {
2783 memutils::myfree("sector_diskinfo",sector_diskinfo);
2784 sector_diskinfo=NULL; // force re-read
2785 }
2786 hd24project* firstproject=createproject("Proj Name");
2787 memutils::myfree("firstproject",firstproject);
2788
2789 if (sector_diskinfo!=NULL) {
2790 memutils::myfree("sector_diskinfo",sector_diskinfo);
2791 sector_diskinfo=NULL; // force re-read
2792 }
2793 __uint32 psec=getprojectsectornum(1);
2794 if (sector_diskinfo!=NULL) {
2795 memutils::myfree("sector_diskinfo",sector_diskinfo);
2796 sector_diskinfo=NULL; // force re-read
2797 }
2798 readdiskinfo();
2799 Convert::setint32(sector_diskinfo,DRIVEINFO_LASTPROJ,psec);
2800 savedriveinfo();
2801
2802 return RESULT_SUCCESS;
2803}
2804
2805__uint32 hd24fs::writesongusage()
2806{
2807 unsigned char* buffer=resetsongusage();
2808 if (buffer==NULL)
2809 {
2810 return RESULT_FAIL;
2811 }
2812 __uint32 sectornum=2;
2813 __uint32 sectorcount=3;
2814 fstfix(buffer,sectorcount*512);
2815 setsectorchecksum(buffer,
2816 0 /* startoffset */,
2817 sectornum /* sector */,
2818 sectorcount /*sectorcount */
2819 );
2820 this->writesectors(this->devhd24,
2821 sectornum,
2822 buffer,
2823 sectorcount);
2824 fstfix(buffer,sectorcount*512);
2825 return RESULT_SUCCESS;
2826}
2827
2828__uint32 hd24fs::writedriveusage()
2829{
2830 if (sectors_driveusage!=NULL)
2831 {
2832 memutils::myfree("sectors_driveusage",sectors_driveusage);
2833 sectors_driveusage=NULL;
2834 }
2835
2836 unsigned char* buffer=resetdriveusage();
2837 if (buffer==NULL)
2838 {
2839 return RESULT_FAIL;
2840 }
2841 __uint32 sectornum=5;
2842 __uint32 sectorcount=15;
2843 fstfix(buffer,sectorcount*512);
2844 setsectorchecksum(buffer,
2845 0 /* startoffset */,
2846 sectornum /* sector */,
2847 sectorcount /*sectorcount */
2848 );
2849
2850 this->writesectors(this->devhd24,
2851 sectornum,
2852 buffer,
2853 sectorcount);
2854 fstfix(buffer,sectorcount*512);
2855
2856 return RESULT_SUCCESS;
2857}
2858
2859__uint32 hd24fs::quickformat(char* message)
2860{
2861 // This procedure performs a quickformat on the current drive.
2862 // There is no need for the drive to be a valid HD24 drive
2863 // for this to work.
2864 // Safety confirmations etc. are considered to be the
2865 // responsibility of the caller.
2866
2867 gotlastsectornum=false; // force re-finding last sector num
2868 __uint32 lastsec=getlastsectornum();
2869
2870 formatting=true;
2871
2872 if (lastsec==0)
2873 {
2874 if (message!=NULL) strcpy(message,(const char*)&"Lastsec=0");
2875 return 0;
2876 }
2877 __uint32 result=writesuperblock(lastsec);
2878
2879 if (result==RESULT_FAIL)
2880 {
2881 if (message!=NULL) strcpy(message,(const char*)&"Write superblock failed");
2882 return 0; // lastsec 0 means failed format
2883 }
2884
2885 result=writedriveinfo();
2886 if (result==RESULT_FAIL)
2887 {
2888 if (message!=NULL) strcpy(message,(const char*)&"Write driveinfo failed");
2889 return 0; // lastsec 0 means failed format
2890 }
2891
2892 result=writesongusage();
2893 if (result==RESULT_FAIL)
2894 {
2895 if (message!=NULL) strcpy(message,(const char*)&"Write song usage failed");
2896 return 0; // lastsec 0 means failed format
2897 }
2898
2899 result=writedriveusage();
2900 if (result==RESULT_FAIL)
2901 {
2902 if (message!=NULL) strcpy(message,(const char*)&"Write drive usage failed");
2903 return 0; // lastsec 0 means failed format
2904 }
2905
2906 // write empty song-entry usage table
2907 // write empty drive usage table
2908 // write 99 empty projects
2909 // create default project
2910 // (write 99*99 empty songs)
2911 // (empty audio space)
2912 // commit fs
2913 commit();
2914 formatting=false;
2915 force_reload();
2916 return lastsec;
2917}
2918
2919void hd24fs::setprojectsectornum(int i,__uint32 sector)
2920{
2921 getsector_diskinfo();
2922 Convert::setint32(sector_diskinfo,
2923 DRIVEINFO_PROJECTLIST + ((i - 1) * 4),sector);
2924
2925 return;
2926}
2927
2928__uint32 hd24fs::deleteproject(__sint32 projid)
2929{
2930 if (projid<1)
2931 {
2932 /* Illegal project id;
2933 project IDs are set in base 1. */
2934 return RESULT_FAIL;
2935 }
2936
2937 getsector_diskinfo(); // has list of pointers to project sectors
2938 __uint32 pcount = Convert::getint32(sector_diskinfo, DRIVEINFO_PROJECTCOUNT);
2939
2940 if (pcount<=1)
2941 {
2942 /* Attempt to delete last project on drive-
2943 not allowed, a drive must always contain
2944 at least 1 project */
2945 return RESULT_FAIL;
2946 }
2947
2948 hd24project* projtodel=this->getproject(projid);
2949 if (projtodel==NULL) {
2950 return RESULT_FAIL;
2951 }
2952
2953 /* If there still all songs in the project, delete them */
2954 __uint32 currsongcount=projtodel->songcount();
2955 if (currsongcount>0)
2956 {
2957 for (__uint32 j=1; j<=currsongcount;j++)
2958 {
2959 projtodel->deletesong(1); // songs will shift
2960 projtodel->save();
2961 }
2962 }
2963
2964 /* delete project from project list by shifting left
2965 all other projects... */
2966 if (projid<99)
2967 {
2968 /* When project 99 is deleted no shifting is needed */
2969 for (__uint32 i=projid;i<99;i++)
2970 {
2971 setprojectsectornum(i,getprojectsectornum(i+1));
2972 }
2973 }
2974
2975 setprojectsectornum(99,0); // ...and clearing the last entry.
2976
2977 Convert::setint32(sector_diskinfo,DRIVEINFO_PROJECTCOUNT,pcount-1);
2978
2979 /* Set 'last accessed project' to first in list
2980 (the project being deleted needs to be accessed
2981 prior to deletion so this must always be updated)
2982 */
2983 Convert::setint32(sector_diskinfo, DRIVEINFO_LASTPROJECT,getprojectsectornum(1));
2984#if (HD24FSDEBUG==1)
2985 cout << "save project." << endl;
2986#endif
2987
2988 savedriveinfo();
2989 delete projtodel;
2990 return RESULT_SUCCESS;
2991}
2992
2993void hd24fs::write_enable()
2994{
2995 this->writeprotected=false;
2996}
2997
2998void hd24fs::write_disable()
2999{
3000 this->writeprotected=true;
3001}
3002
diff --git a/src/lib/hd24fs.h b/src/lib/hd24fs.h
new file mode 100755
index 0000000..b91d4c1
--- /dev/null
+++ b/src/lib/hd24fs.h
@@ -0,0 +1,432 @@
1#ifndef __hd24fs_h__
2#define __hd24fs_h__
3
4#include <config.h>
5#include <stdio.h>
6#include <string>
7#include <hd24utils.h>
8#include "memutils.h"
9#include "convertlib.h"
10#define CLUSTER_UNDEFINED (0xFFFFFFFF)
11
12#if defined(LINUX) || defined(DARWIN)
13# define FSHANDLE int
14# define FSHANDLE_INVALID -1
15#endif
16
17#ifdef WINDOWS
18# include <windows.h>
19# include <winioctl.h>
20# define FSHANDLE HANDLE
21# define FSHANDLE_INVALID INVALID_HANDLE_VALUE
22#endif
23
24using namespace std;
25
26class hd24fs;
27class hd24project;
28class hd24raw;
29class hd24song;
30
31class AudioStorage
32{
33public:
34 virtual __uint32 samplerate() { return 0; };
35 virtual void currentlocation(__uint32 newpos) { return; };
36 virtual __uint32 currentlocation() { return 0; };
37 virtual __uint32 getlocatepos(int locatepoint) { return 0; };
38 virtual __uint32 setlocatepos(int locatepoint,__uint32 newpos) { return 0; };
39 virtual bool trackarmed(__uint32 base1tracknum) { return false; }
40 virtual void trackarmed(__uint32 base1tracknum,bool arm) { return; }
41 virtual ~AudioStorage() { return; } ;
42};
43
44class hd24song : public AudioStorage
45{
46 friend class hd24project;
47 friend class hd24fs;
48 friend class hd24transferjob;
49 friend class hd24transferengine;
50 private:
51 __uint32 framespersec;
52 unsigned char* buffer; // for songinfo
53 unsigned char* audiobuffer; // for audio data
54 unsigned char* scratchbook; // for write-back audio data
55 __uint32* blocksector;
56 int evenodd; /* specifies if we are dealing with
57 even or odd samples in high speed mode. */
58 bool lengthened; /* Indicate if reallocating song length change occured */
59 bool busyrecording;
60 int mysongid;
61 int polling;
62 int currentreadmode;
63 int currcachebufnum;
64 bool rehearsemode;
65 bool lastallocentrynum;
66 hd24fs* parentfs;
67 unsigned char** cachebuf_ptr;
68 __uint32* cachebuf_blocknum;
69 hd24project* parentproject;
70 hd24song(hd24project* p_parent,__uint32 p_songid);
71 unsigned char* getcachedbuffer(long unsigned int);
72 void queuecacheblock(__uint32 blocknum);
73 void loadblockintocache(__uint32 blocknum);
74 void setblockcursor(__uint32 blocknum);
75 void memoizeblocksectors(__uint32 lastblock);
76 __uint32 memblocksector(__uint32 blocknum);
77 __uint32 blocktoqueue; // next block to cache
78 __uint32 songcursor; // current cursor pos within song, in samples
79 __uint32 allocentrynum; // which allocation entry is currently being used
80 __uint32 allocstartblock; // the first audioblock in given entry
81 __uint32 allocstartsector; // the sector pointed to by that entry
82 __uint32 allocaudioblocks; // the number of audioblocks in the block
83 __uint32 divider;
84 __uint32 lastreadblock;
85 __uint32 lastavailablecacheblock;
86 __uint32 mustreadblock;
87 __uint32 track_armed[24];
88 __uint32 track_readenabled[24]; // used to speed up copy mode.
89 void unmark_used_clusters(unsigned char* sectors_orphan);
90 __uint32 used_alloctable_entries();
91 __uint32 audioblocks_in_alloctable();
92 void silenceaudioblocks(__uint32 allocsector,__uint32 blocks);
93 bool allocatenewblocks(long unsigned int, bool, char*, int*, int (*)());
94
95 public:
96 ~hd24song();
97 string* songname();
98 __uint32 songid();
99 hd24fs* fs();
100 static void sectorinit(unsigned char* sectorbuf);
101 static void settrackcount(unsigned char* sectorbuf,__uint32 trackcount);
102 static void songname(unsigned char* sectorbuf,string newname);
103 void songname(string newname);
104 static string* songname(hd24fs* parentfs,unsigned char* sectorbuf);
105 void bufferpoll();
106
107 void readenabletrack(__uint32 tracknum);
108 void readenabletrack(__uint32 tracknum,bool enable);
109
110 bool isrehearsemode();
111 void setrehearsemode(bool p_rehearsemode);
112 bool recording();
113
114 bool trackarmed(__uint32 tracknum);
115 void trackarmed(__uint32 tracknum,bool arm);
116
117 bool istrackmonitoringinput(__uint32 tracknum);
118 void startrecord(int record_mode);
119 void stoprecord();
120 __uint32 samplerate();
121 static void samplerate(unsigned char* sectorbuf,__uint32 samplerate);
122 void samplerate(__uint32 newrate);
123 static __uint32 samplerate(unsigned char* songbuf);
124 __uint32 bitdepth();
125 __uint32 physical_channels();
126 static __uint32 physical_channels(unsigned char* songbuf);
127 void physical_channels(__uint32 newchannelcount);
128 static void physical_channels(unsigned char* songbuf,__uint32 newchannelcount);
129 __uint32 logical_channels();
130 static __uint32 logical_channels(unsigned char* songbuf);
131 void logical_channels(__uint32 newchannelcount);
132 static void logical_channels(unsigned char* songbuf,__uint32 channelcount);
133 __uint32 songlength_in_samples();
134 __uint32 songlength_in_samples(__uint32 newlen);
135 __uint32 songlength_in_samples(__uint32 newlen,bool silence);
136 __uint32 songlength_in_samples(__uint32 newlen,bool silence,char* savemessage,int* cancel);
137 __uint32 songlength_in_samples(__uint32 newlen,bool silence,char* savemessage,int* cancel,int (*checkfunc)());
138
139 __uint32 display_hours();
140 __uint32 display_hours(__uint32 offset);
141 static __uint32 display_hours(__uint32 offset,__uint32 samrate);
142
143 __uint32 display_minutes();
144 __uint32 display_minutes(__uint32 offset);
145 static __uint32 display_minutes(__uint32 offset,__uint32 samrate);
146
147 __uint32 display_seconds();
148 __uint32 display_seconds(__uint32 offset);
149 static __uint32 display_seconds(__uint32 offset,__uint32 samrate);
150
151 __uint32 display_subseconds();
152 __uint32 display_subseconds(__uint32 offset);
153 static __uint32 display_subseconds(__uint32 offset,__uint32 samrate);
154
155 string* display_duration();
156 string* display_duration(__uint32 offset);
157 string* display_duration(__uint32 offset,__uint32 samrate);
158
159 string* display_cursor();
160 __uint32 cursorpos();
161 __uint32 locatepointcount();
162 __uint32 getlocatepos(int locatepoint);
163
164 __uint32 currentlocation();
165 void currentlocation(__uint32 offset);
166 __uint32 golocatepos(__uint32 offset);
167
168 __uint32 setlocatepos(int locatepoint,__uint32 offset);
169 void setlocatename(int locatepoint,string newname);
170 string* getlocatename(int locatepoint);
171 bool iswriteprotected();
172 void setwriteprotected(bool prot);
173 void getmultitracksample(long* mtsample,int readmode);
174 int getmtrackaudiodata(__uint32 firstsamnum,__uint32 samples,unsigned char* buffer,int readmode);
175 int putmtrackaudiodata(__uint32 firstsamnum,__uint32 samples,unsigned char* buffer,int writemode);
176 void deinterlaceblock(unsigned char* buffer,unsigned char* targetbuffer);
177 void interlaceblock(unsigned char* buffer,unsigned char* targetbuffer);
178 static const int LOCATEPOS_SONGSTART;
179 static const int LOCATEPOS_LOOPSTART;
180 static const int LOCATEPOS_LOOPEND;
181 static const int LOCATEPOS_PUNCHIN;
182 static const int LOCATEPOS_PUNCHOUT;
183 static const int LOCATEPOS_EDITIN;
184 static const int LOCATEPOS_EDITOUT;
185 static const int LOCATEPOS_LAST;
186 static const int READMODE_COPY;
187 static const int READMODE_REALTIME;
188 static const int WRITEMODE_COPY;
189 static const int WRITEMODE_REALTIME;
190
191 __uint32 getnextfreesector(__uint32 allocsector);
192 bool has_unexpected_end(); // indicates if there is an 'unexpected end of song' error
193 bool is_fixable_unexpected_end(); // ...and if so, if we know how to fix it.
194 bool setallocinfo(bool silencenew);
195 bool setallocinfo(bool silencenew,char* message,int* cancel,int (*checkfunc)());
196 __uint32 requiredaudioblocks(__uint32 songlen);
197 void appendorphanclusters(unsigned char*,bool allowsongresize);
198 void save();
199};
200
201class hd24project
202{
203 friend class hd24fs;
204 friend class hd24song;
205
206 private:
207 unsigned char* buffer;
208 hd24fs* parentfs;
209 __sint32 myprojectid;
210 hd24song* songlist;
211 hd24project(hd24fs* p_parent,__sint32 projectid);
212 hd24project(hd24fs* p_parent,__sint32 projectid,__uint32 projsector,const char* projectname,bool isnew);
213 __uint32 getsongsectornum(int i);
214 void setsongsectornum(int i,__uint32 newsector);
215 void save(__uint32 projsector);
216 void populatesongusagetable(unsigned char* songused);
217 __uint32 getunusedsongslot();
218 void initvars(hd24fs* p_parent,__sint32 p_projectid);
219 public:
220 ~hd24project();
221 string* projectname();
222 void projectname(string newname);
223 __sint32 lastsongid();
224 void lastsongid(signed long songid);
225 __uint32 songcount();
226 __uint32 maxsongs();
227 __sint32 projectid();
228 hd24song* getsong(__uint32 songid);
229 hd24song* createsong(const char* songname,__uint32 trackcount,__uint32 samplerate);
230 __uint32 deletesong(__uint32 songid);
231 void save();
232 void sort();
233};
234
235class hd24fs
236{
237 friend class hd24project;
238 friend class hd24song;
239 friend class hd24raw;
240 friend class hd24utils;
241
242 private:
243 const char* imagedir;
244 int transportstatus;
245 bool writeprotected;
246 bool allinput;
247 bool autoinput;
248 bool forcemode;
249 bool formatting; // true during a format operation
250 bool headermode;
251 bool maintenancemode;
252 bool wavefixmode;
253 __uint32 highestFSsectorwritten;
254
255 __uint32 nextfreeclusterword; // memoization cache for write allocation
256
257 FSHANDLE devhd24; // device handle
258 FSHANDLE hd24header; // header device handle
259 bool m_isOpen;
260 bool gotlastsectornum;
261 __uint32 foundlastsectornum;
262 int p_mode;
263 hd24project* projlist;
264 string* devicename;
265 unsigned char* sector_boot;
266 unsigned char* sector_diskinfo;
267 unsigned char* sectors_driveusage;
268 unsigned char* sectors_orphan;
269 unsigned char* sectors_songusage;
270 long readsectors(FSHANDLE handle, __uint32 secnum, unsigned char* buffer,int sectors);
271 long readsector(FSHANDLE handle, __uint32 secnum, unsigned char* buffer);
272 long readsector_noheader(FSHANDLE handle, __uint32 secnum, unsigned char* buffer);
273 long readsector_noheader(hd24fs* currenthd24, __uint32 secnum, unsigned char* buffer);
274 long writesectors(FSHANDLE handle, __uint32 secnum, unsigned char* buffer,int sectors);
275 long writesector(FSHANDLE handle, __uint32 secnum, unsigned char* buffer);
276
277 string* gethd24currentdir(int, char**);
278 void hd24close();
279 void hd24closedevice(FSHANDLE handle);
280 static void hd24seek(FSHANDLE handle,__uint64 seekpos);
281 void clearbuffer(unsigned char* buffer);
282 void clearbuffer(unsigned char* buffer,unsigned int bytes);
283 FSHANDLE findhd24device();
284 FSHANDLE findhd24device(int mode);
285 FSHANDLE findhd24device(int mode, int base0devnum);
286 FSHANDLE findhd24device(int mode, string* dev,bool force,bool tryharder);
287 static bool isinvalidhandle(FSHANDLE handle);
288 unsigned char* readbootinfo();
289 unsigned char* readdiskinfo();
290 unsigned char* readdriveusageinfo();
291 unsigned char* resetsongusage();
292 unsigned char* resetdriveusage();
293 unsigned char* calcsongusage();
294 void refreshsongusage();
295 unsigned char* getsector_bootinfo();
296 unsigned char* getsector_diskinfo();
297 unsigned char* getsectors_driveusage();
298 unsigned char* getcopyofusagetable(); // allocates memory and fills it up with a copy of the current usage table
299 void initvars();
300 __uint32 driveusagesectorcount();
301 __uint32 clustercount();
302 __uint32 driveusagefirstsector();
303 __uint32 getblockspercluster();
304 __uint32 getprojectsectornum(__uint32 base1proj);
305 bool isfreecluster(__uint32 clusternum);
306 bool isfreecluster(__uint32 clusternum,unsigned char* usagebuffer);
307 __uint32 freeclustercount();
308 __uint32 getlastsectornum();
309 __uint32 getlastsectornum(FSHANDLE handle);
310 __uint32 headersectors;
311 void writebackupblock(__uint32 sector,__uint32 blocksize,
312 __uint32 lastsec,bool fullcommit);
313 __uint32 getnextfreesectorword();
314 __uint32 getnextfreeclusterword();
315 __uint32 getnextfreesector(__uint32 cluster);
316 void enablebit(__uint32 ibit,unsigned char* usagebuffer);
317 void disablebit(__uint32 ibit,unsigned char* usagebuffer);
318 bool isbitzero(__uint32 ibit,unsigned char* usagebuffer);
319 long unsigned int songentry2songsector(long unsigned int entry);
320 long unsigned int songsector2songentry(long unsigned int entry);
321 void allocsongentry(__uint32 entrynum);
322 void allocatecluster(__uint32 clusternum);
323 void allocatecluster(__uint32 clusternum,unsigned char* usagebuffer);
324 void freecluster(__uint32 clusternum);
325 void freecluster(__uint32 clusternum,unsigned char* usagebuffer);
326 signed long nextunusedsongentry();
327 void useinternalboot(unsigned char*, long unsigned int);
328 __uint32 getunusedsongsector();
329 __uint32 songsondisk();
330 void songsondisk(__uint32 songsondisk);
331 void setprojectsectornum(int i,__uint32 newsector);
332 void setimagedir(const char* newdir);
333 int deviceid;
334 public:
335 __uint32 lasterror;
336 void force_reload();
337 static void setname(unsigned char* namebuf,string newname,__uint32 shortnameoff,__uint32 longnameoff);
338 void dumpclusterusage();
339 void dumpclusterusage(unsigned char* buffer);
340 void dumpclusterusage2();
341 void dumpclusterusage2(unsigned char* buffer);
342 unsigned char* findorphanclusters();
343 static const int TRANSPORTSTATUS_PLAY;
344 static const int TRANSPORTSTATUS_STOP;
345 static const int TRANSPORTSTATUS_REC;
346 __uint32 cluster2sector(__uint32 clusternum);
347 __uint32 sector2cluster(__uint32 sectornum);
348 __uint32 songentry2sector(__uint32 entrynum);
349 __uint32 songsector2entry(__uint32 sectornum);
350 void settransportstatus(int newstatus);
351 int gettransportstatus();
352 bool isallinput();
353 void setallinput(bool p_allinput);
354 void setallinput(void);
355 bool isautoinput();
356 void setautoinput(bool p_autoinput);
357 void setautoinput(void);
358
359 hd24fs(const char* imagedir);
360 hd24fs(const char* imagedir,int mode);
361 hd24fs(const char* imagedir,int mode,int base0devnum);
362 hd24fs(const char* imagedir,int mode,string* dev,bool force);
363 ~hd24fs();
364 __uint32 getblocksizeinsectors();
365 __uint32 getbytesperaudioblock();
366 static void fstfix(unsigned char* bootblock,int fixsize);
367 bool isOpen();
368 int mode();
369 string* volumename();
370 string* getdevicename();
371 int getdeviceid();
372 void setdevicename(const char* orig,string* newname);
373 void setvolumename(string newname);
374 string* version();
375 __uint32 hd24devicecount();
376 __sint32 lastprojectid();
377 void lastprojectid(signed long projectid);
378 __uint32 projectcount();
379 __uint32 maxprojects();
380 __uint32 maxsongsperproject();
381 hd24project* getproject(__sint32 projectid);
382 hd24project* createproject(const char* projectname);
383 void setmaintenancemode(int mode);
384 int getmaintenancemode();
385 void setwavefixmode(int mode);
386 int getwavefixmode();
387 string* gethd24currentdir();
388 static const int MODE_RDONLY;
389 static const int MODE_RDWR;
390 string* freespace(__uint32 rate,__uint32 tracks);
391 bool useheaderfile(string headerfilename);
392 bool isexistingdevice(string *devname);
393 bool commit(bool fullcommit);
394 bool commit();
395 long unsigned int setsectorchecksum(unsigned char* buffer,unsigned int startoffset,unsigned int startsector,unsigned int sectors);
396 void savedriveinfo();
397 void savedriveusage();
398 __uint32 writesuperblock(__uint32 lastsectornum);
399 void cleardriveinfo(unsigned char* buffer);
400 __uint32 writedriveinfo();
401 __uint32 writesongusage();
402 __uint32 writedriveusage();
403 __uint32 quickformat(char* lasterror);
404 __uint32 deleteproject(__sint32 projid);
405 void write_enable();
406 void write_disable();
407};
408
409/* Provides sector level access to hd24 disks
410 * (functionality which is private in hd24fs)
411 */
412class hd24raw
413{
414 friend class hd24fs;
415
416 private:
417 hd24fs* fsys;
418
419 public:
420 hd24raw(hd24fs* fsys);
421 hd24raw(hd24fs* fsys,bool notranslate);
422 ~hd24raw() {};
423 long readsectors(__uint32 secnum, unsigned char* buffer,int sectors);
424 long writesectors(__uint32 secnum, unsigned char* buffer,int sectors);
425 __uint32 getnextfreesector(__uint32 cluster);
426 __uint32 getprojectsectornum(__uint32 projectid);
427 __uint32 getlastsectornum();
428 __uint32 songsondisk();
429 __uint32 quickformat(char* lasterror);
430};
431
432#endif
diff --git a/src/lib/hd24project.cpp b/src/lib/hd24project.cpp
new file mode 100755
index 0000000..1111003
--- /dev/null
+++ b/src/lib/hd24project.cpp
@@ -0,0 +1,477 @@
1#define PROJDEBUG 0
2#define PROJINFO_PROJECTNAME_8 0x0
3#define PROJINFO_SONGCOUNT 0x0c
4#define PROJINFO_LASTSONG 0x10
5#define PROJINFO_SONGLIST 0x20
6#define PROJINFO_PROJECTNAME 0x1b8
7#define INVALID_SONGENTRY 0xFFFFFFFF
8#define RESULT_SUCCESS 0
9#define RESULT_FAIL 1
10#include <hd24utils.h>
11#include "memutils.h"
12void hd24project::initvars(hd24fs* p_parent,__sint32 p_myprojectid)
13{
14 this->myprojectid=p_myprojectid;
15 this->parentfs = p_parent;
16 return;
17}
18
19__sint32 hd24project::projectid()
20{
21 return this->myprojectid;
22}
23
24hd24project::hd24project(hd24fs* p_parent, __sint32 p_myprojectid,
25 __uint32 p_projectsector, const char* p_projectname,
26 bool isnew)
27{
28#if (PROJDEBUG == 1)
29 cout << "CONSTRUCT hd24project " << p_myprojectid << endl;
30#endif
31 // initialize a new project.
32 // Boolean is obligatory to prevent accidents;
33 // one can still create a project and not save it immediately.
34 this->myprojectid = p_myprojectid;
35 buffer = (unsigned char*)memutils::mymalloc("hd24project(1)",1024,1);
36 parentfs = p_parent;
37 if (!isnew) {
38 p_parent->readsector(p_parent->devhd24,
39 p_parent->getprojectsectornum(myprojectid),
40 buffer); // fstfix follows
41
42 p_parent->fstfix(buffer, 512);
43 projectname(p_projectname);
44 } else {
45#if (PROJDEBUG == 1)
46 cout << "Create new project " <<projectname << " with id "
47 << p_myprojectid << " on sec " <<p_projectsector << endl;
48#endif
49
50 for (int i=0;i<1024;i++) {
51 buffer[i]=0;
52 }
53 projectname(p_projectname);
54 this->save(p_projectsector);
55 }
56}
57
58hd24project::hd24project(hd24fs* p_parent, __sint32 p_myprojectid)
59{
60 // project id is 1-based
61#if (PROJDEBUG == 1)
62 cout << "Here we are. time to create the project object for proj. "
63 << p_myprojectid << endl;
64#endif
65 this->myprojectid = p_myprojectid;
66 buffer = (unsigned char*)memutils::mymalloc("hd24project(2)",1024,1);
67 if (buffer==NULL) {
68 return;
69 }
70 parentfs = p_parent;
71 __uint32 projsecnum=p_parent->getprojectsectornum(myprojectid);
72 if (projsecnum==0) {
73 for (int i=0;i<512;i++) {
74 buffer[i]=0;
75 }
76 } else {
77 p_parent->readsector(p_parent->devhd24,
78 projsecnum,
79 buffer); // fstfix follows
80
81 p_parent->fstfix(buffer, 512);
82 //this->sort();
83 }
84
85}
86
87hd24project::~hd24project()
88{
89#if (PROJDEBUG == 1)
90 cout << "DESTRUCT hd24project " << myprojectid << endl;
91#endif
92 if (buffer != NULL) memutils::myfree("hd24project::buffer",buffer);
93}
94
95string* hd24project::projectname()
96{
97 string* ver=parentfs->version();
98 if (*ver == "1.00")
99 {
100 delete ver;
101 // version 1.0 filesystem.
102 string* tmp = new string("");
103 string* dummy = Convert::readstring(buffer, PROJINFO_PROJECTNAME_8, 8);
104
105 *tmp += *dummy;
106 delete dummy;
107
108 if (tmp->length() == 8)
109 {
110 dummy = Convert::readstring(buffer, PROJINFO_PROJECTNAME_8 + 10, 2);
111 *tmp += *dummy;
112 delete dummy;
113 }
114
115 return tmp;
116 }
117 delete ver;
118 return Convert::readstring(buffer, PROJINFO_PROJECTNAME, 64);
119}
120
121void hd24project::projectname(string newname)
122{
123 hd24fs::setname(this->buffer,newname,PROJINFO_PROJECTNAME_8,PROJINFO_PROJECTNAME);
124 return;
125}
126
127unsigned long hd24project::maxsongs()
128{
129 return parentfs->maxsongsperproject();
130}
131
132unsigned long hd24project::getsongsectornum(int i)
133{
134 unsigned int songsec = Convert::getint32(buffer,
135 PROJINFO_SONGLIST + ((i - 1) * 4));
136 // FIXME: Check for sensible values.
137 return songsec;
138}
139
140void hd24project::setsongsectornum(int i,__uint32 sector)
141{
142 Convert::setint32(buffer,
143 PROJINFO_SONGLIST + ((i - 1) * 4),sector);
144 // FIXME: Check for sensible values.
145 return;
146}
147
148void hd24project::lastsongid(signed long songid)
149{
150 if (songid<1)
151 {
152 return;
153
154 }
155 int maxsongsperproj = maxsongs();
156 if (songid>maxsongsperproj)
157 {
158 return;
159 }
160 if (songid==lastsongid())
161 {
162 /* same 'last song id' as before-
163 nothing changes.
164 */
165 return;
166 }
167 Convert::setint32(buffer, PROJINFO_LASTSONG,getsongsectornum(songid));
168 this->save();
169 return;
170}
171
172signed long hd24project::lastsongid()
173{
174 unsigned int lastsongsec = Convert::getint32(buffer, PROJINFO_LASTSONG);
175
176 if (lastsongsec == 0)
177 {
178 return -1;
179 }
180
181 int maxsongsperproj = maxsongs();
182 for (int i = 1; i <= maxsongsperproj; i++)
183 {
184 unsigned int songsec = getsongsectornum(i);
185
186 if (songsec == lastsongsec)
187 {
188 return i;
189 }
190 }
191
192 if (maxsongsperproj >= 1)
193 {
194 return 1;
195 }
196
197 return -1;
198}
199
200__uint32 hd24project::songcount()
201{
202 if (this==NULL)
203 {
204 return 0;
205 }
206 if (myprojectid == -1)
207 {
208 return 0;
209 }
210 if (buffer==NULL) {
211 return 0;
212 }
213 __uint32 scount = Convert::getint32(buffer, PROJINFO_SONGCOUNT);
214
215 if (scount > 99)
216 {
217 return 99;
218 }
219
220 return scount;
221}
222
223hd24song* hd24project::getsong(unsigned long songid)
224{
225#if (PROJDEBUG == 1)
226 cout << "get song " << songid << endl;
227#endif
228 return new hd24song(this,songid);
229}
230
231void hd24project::save(__uint32 projsector)
232{
233#if (PROJDEBUG == 1)
234 cout << "save project info to sector " << projsector << endl;
235#endif
236 if (buffer==NULL)
237 {
238 return; // nothing to do!
239 }
240 parentfs->fstfix(buffer,512); // sector is now in native format again
241 parentfs->setsectorchecksum(buffer,0,projsector,1);
242 parentfs->writesectors(parentfs->devhd24,
243 projsector,
244 buffer,1);
245
246 parentfs->fstfix(buffer,512); // sector is now in 'fixed' format
247 parentfs->commit();
248}
249
250void hd24project::save()
251{
252 // This is capable of handling only 1-sector-per-project projects.
253 // save(projsector) is only intended for new projects.
254 __uint32 projsector=parentfs->getprojectsectornum(this->myprojectid);
255#if (PROJDEBUG == 1)
256 cout << "save project info to sector " << projsector << endl;
257#endif
258 if (projsector==0)
259 {
260 return; // safety measure
261 }
262 save(projsector);
263}
264
265__uint32 hd24project::getunusedsongslot()
266{
267 // Find the first unused song slot in the current project.
268 __uint32 unusedsongslot=INVALID_SONGENTRY;
269
270 int maxsongcount=this->maxsongs();
271 for (int j=1; j<=maxsongcount;j++)
272 {
273 // get song sector info.
274 __uint32 songsector = getsongsectornum(j);
275 if (songsector==0)
276 {
277 unusedsongslot=(j-1);
278 break;
279 }
280 }
281
282 return unusedsongslot;
283}
284
285hd24song* hd24project::createsong(const char* songname,__uint32 trackcount,
286 __uint32 samplerate)
287{
288 /* This creates a new song (with given songname)
289 on the drive (if possible).
290 NULL is returned when unsuccessful, a pointer to the
291 new song object otherwise.
292 */
293 __uint32 songslot=getunusedsongslot();
294 if (songslot==INVALID_SONGENTRY)
295 {
296 // project is full.
297 return NULL;
298 }
299
300 // Project is not full so there must be unused song sectors
301 // (if not, something seriously fishy is going on).
302 __uint32 newsongsector=this->parentfs->getunusedsongsector();
303 if (newsongsector==0)
304 {
305 // no songsector found (0 is not a valid songsector)
306 return NULL;
307 }
308
309 // So, we have got a free songsector and a free song slot.
310 unsigned char songbuf[512*7];
311 for (int i=0;i<(7*512);i++)
312 {
313 songbuf[i]=(unsigned char)(0);
314 }
315 hd24song::sectorinit(songbuf); // put some default info in there
316
317 hd24song::songname((unsigned char*)songbuf,songname);
318 string* setsongname=hd24song::songname(parentfs,songbuf);
319 delete setsongname;
320
321 hd24song::samplerate((unsigned char*)songbuf,samplerate);
322 hd24song::logical_channels((unsigned char*)songbuf,trackcount) ;// depends on samplerate
323 __uint32 songsector=newsongsector;
324
325 // - Create the empty song at the songsector
326 // (2 sectors in size)
327 // - Create empty allocation info at songsector+2
328 // (5 sectors in size)
329 // write song info to drive
330
331 parentfs->fstfix(songbuf,TOTAL_SECTORS_PER_SONG*512); // sector is now once again in native format
332 parentfs->setsectorchecksum(songbuf,0,songsector,2);
333 parentfs->setsectorchecksum(songbuf,2*512,songsector+2,5);
334 parentfs->writesectors(parentfs->devhd24,songsector,songbuf,TOTAL_SECTORS_PER_SONG);
335 parentfs->fstfix(songbuf,TOTAL_SECTORS_PER_SONG*512); // sector is now once again in fixed format
336
337 /////////////////////////////
338 // -Update the project slot info to point at that sector
339 Convert::setint32(buffer,PROJINFO_SONGLIST+(songslot*4),songsector);
340 this->lastsongid(songslot+1);
341 Convert::setint32(buffer,PROJINFO_SONGCOUNT,
342 Convert::getint32(buffer,PROJINFO_SONGCOUNT)+1);
343 this->save();
344 parentfs->refreshsongusage();
345
346 ////////////////////////
347 // Now commit the FS
348 parentfs->commit();
349
350 return getsong(songslot+1);
351}
352
353__uint32 hd24project::deletesong(__uint32 songid)
354{
355 hd24song* songtodel=this->getsong(songid);
356#if (PROJDEBUG == 1)
357 cout << "del song with id " << songid << endl;
358#endif
359 __uint32 songsector=getsongsectornum(songid);
360#if (PROJDEBUG == 1)
361 cout << "sector " << songsector << endl;
362#endif
363 songsector++; songsector--; // prevent 'variable not used' warning
364
365 if (songtodel==NULL)
366 {
367#if (PROJDEBUG == 1)
368 cout << "song to del==null " << endl;
369#endif
370 return RESULT_FAIL;
371 }
372 songtodel->songlength_in_samples(0,false);
373 songtodel->save();
374
375 // delete song from project list by shifting left
376 // all other songs...
377 for (__uint32 i=songid;i<99;i++)
378 {
379#if (PROJDEBUG == 1)
380 cout << "set new sector for song id " << i <<" to " << getsongsectornum(i+1) << endl;
381#endif
382 setsongsectornum(i,getsongsectornum(i+1));
383 }
384 setsongsectornum(99,0); // ...and clearing the last entry.
385 __uint32 scount = Convert::getint32(buffer, PROJINFO_SONGCOUNT);
386 Convert::setint32(buffer,PROJINFO_SONGCOUNT,scount-1);
387#if (PROJDEBUG == 1)
388 cout << "set new song count to " << (scount-1) << endl;
389#endif
390
391 // set 'last accessed song' to first song in list
392 // (if there are no songs anymore, this automatically
393 // results in 'last song' to be on sector zero.
394#if (PROJDEBUG ==1)
395 cout << "set default project song to song 1 with sectornum " << getsongsectornum(1) << endl;
396#endif
397 Convert::setint32(buffer, PROJINFO_LASTSONG,getsongsectornum(1));
398#if (PROJDEBUG ==1)
399 cout << "save project." << endl;
400#endif
401
402 this->save();
403#if (PROJDEBUG ==1)
404 cout << "refresh song usage table (+superblock) " << endl;
405#endif
406 parentfs->refreshsongusage(); // or calcsongusage?
407
408 unsigned char* sectors_driveusage=parentfs->getsectors_driveusage();
409
410 // now, we still have the song object songtodel,
411 // plus its original sector number.
412#if (PROJDEBUG ==1)
413 cout << "Reset song length" << endl;
414#endif
415#if (PROJDEBUG ==1)
416 cout << "Unmark used clusters " << endl;
417#endif
418 songtodel->unmark_used_clusters(sectors_driveusage);
419#if (PROJDEBUG ==1)
420 cout << "Destruct song object." << endl;
421#endif
422 delete(songtodel);
423#if (PROJDEBUG ==1)
424 cout << "Save drive usage." << endl;
425#endif
426 parentfs->savedriveusage();
427#if (PROJDEBUG ==1)
428 cout << "Commit FS" << endl;
429#endif
430 parentfs->commit();
431 return RESULT_SUCCESS;
432}
433
434void hd24project::sort()
435{
436 // a max. of 99 elements is still doable by bubble sort.
437 int songs=this->songcount();
438 if (songs<2) return; // nothing to sort!
439 string** songnames=(string**)memutils::mymalloc("hd24project::sort",99,sizeof(string*));
440 hd24song* song1=NULL;
441
442 int i, j;
443 int arrayLength = songs;
444 for (i=1;i<=arrayLength;i++)
445 {
446 song1=getsong(i);
447 songnames[i-1]=song1->songname();
448 delete song1;
449 song1=NULL;
450 }
451
452 for(i = 1; i <= arrayLength ; i++)
453 {
454 for (j=0; j < (arrayLength -1); j++)
455 {
456 int compare=strncmp(songnames[j]->c_str(),songnames[j+1]->c_str(),64);
457 if (compare>0)
458 {
459 // swap entries
460 __uint32 a=getsongsectornum(j+1);
461 __uint32 b=getsongsectornum(j+2);
462 setsongsectornum(j+2,a);
463 setsongsectornum(j+1,b);
464 string* tmp=songnames[j];
465 songnames[j]=songnames[j+1];
466 songnames[j+1]=tmp;
467 }
468 }
469 }
470
471 for (i=1;i<=arrayLength;i++)
472 {
473 free(songnames[i-1]);
474 }
475 free(songnames);
476 return;
477}
diff --git a/src/lib/hd24sndfile.cpp b/src/lib/hd24sndfile.cpp
new file mode 100644
index 0000000..470a465
--- /dev/null
+++ b/src/lib/hd24sndfile.cpp
@@ -0,0 +1,270 @@
1#include "hd24sndfile.h"
2#include <sndfile.h>
3#include <fstream>
4#include <iostream>
5#include <convertlib.h>
6using std::ofstream;
7using std::cout;
8using std::endl;
9hd24sndfile::hd24sndfile(int p_format,SoundFileWrapper* p_soundfile)
10{
11 sndfilehandle=(SNDFILE*)NULL;
12 outfilehandle=(ofstream*)NULL;
13 _handletype=0; // default is 0=libsndfile, 1=native file
14 sf_format=p_format;
15 soundfile=p_soundfile;
16}
17
18hd24sndfile::~hd24sndfile()
19{
20 //if (sndfilehandle!=NULL)
21 //{
22 // delete sndfilehandle;
23 //}
24 //if (outfilehandle!=NULL)
25 //{
26 // /delete outfilehandle;
27 //}
28}
29
30int hd24sndfile::handletype()
31{
32 return _handletype;
33}
34
35void* hd24sndfile::handle()
36{
37 if (_handletype==0)
38 {
39 return (void*)sndfilehandle;
40 }
41 return (void*)outfilehandle;
42}
43
44void hd24sndfile::handle(SNDFILE* newhandle)
45{
46 sndfilehandle=newhandle;
47 _handletype=0;
48}
49
50void hd24sndfile::handle(ofstream* newhandle)
51{
52 outfilehandle=newhandle;
53
54 _handletype=1;
55 // TODO: Write empty header (for filling in later)
56}
57
58void hd24sndfile::handle(void* newhandle,int htype)
59{
60 _handletype=htype;
61 if (htype==1) {
62 outfilehandle=(ofstream*)newhandle;
63 return;
64 }
65
66 sndfilehandle=(SNDFILE*)newhandle;
67}
68
69void hd24sndfile::open(const char* filename,int filemode,SF_INFO* infoblock,SoundFileWrapper* _soundfile)
70{
71 _handletype=0; // soundfile
72 soundfile=_soundfile;
73 sfinfo=infoblock;
74 sndfilehandle=soundfile->sf_open(filename,filemode,infoblock);
75 outfilehandle=NULL;
76
77 if (!sndfilehandle)
78 {
79 cout << "Problem opening file with the following specs: " << endl;
80 cout << "rate=" << infoblock->samplerate << endl;
81 cout << "frames=" << infoblock->frames << endl;
82 cout << "channels=" << infoblock->channels << endl;
83 cout << "sections=" << infoblock->sections << endl;
84 cout << "seekable=" << infoblock->seekable << endl;
85 cout << "format=" << infoblock->format << endl;
86 }
87}
88
89void hd24sndfile::open(const char* filename,int filemode,SF_INFO* infoblock)
90{
91 _handletype=1; // iostream
92 sfinfo=infoblock;
93 sndfilehandle=NULL;
94 outfilehandle=new ofstream(filename,ios_base::out|ios_base::trunc|ios_base::binary);
95
96 if ((sf_format & 0xFF0000) ==SF_FORMAT_WAV)
97 {
98 char buf[44]={
99 'R','I','F','F', 0,0,0,0, 'W','A','V','E', 'f','m','t',' ',
100 16,0,0,0, 1,0,1,0, 0,0,0,0, 0,0,0,0,
101 3,0,24,0, 'd','a','t','a', 0,0,0,0
102 };
103
104 // samplerate follows
105 long rate=sfinfo->samplerate; // FIXME: Get proper rate from sfinfo
106 buf[24]=(char)((rate)%256);
107 buf[25]=(char)(((rate)>>8)%256);
108 buf[26]=(char)(((rate)>>16)%256);
109 buf[27]=(char)(((rate)>>24)%256);
110
111 rate*=3;
112 buf[28]=(char)((rate)%256);
113 buf[29]=(char)(((rate)>>8)%256);
114 buf[30]=(char)(((rate)>>16)%256);
115 buf[31]=(char)(((rate)>>24)%256);
116
117 outfilehandle->write(buf,44);
118 return;
119
120 }
121
122 if ((sf_format & 0xFF0000) ==SF_FORMAT_AIFF)
123 {
124 char buf[54]={
125 'F','O','R','M',
126 0,0,0,0, /* Bytes that follow in this file */
127 'A','I','F','F', 'C','O','M','M',
128 0,0,0,18, /* chunksize */
129 0,1, /*numchannels*/
130 0,0,0,0, /*sampleframes */
131 0,24, /* Samplesize in bits */
132 0,0,0,0,0,0,0,0,0,0, /* sample rate as 80 bit IEEE float */
133 'S','S','N','D',
134 0,0,0,0, /* sound block datalen, to be filled afterwards */
135 0,0,0,0, /* offset */
136 0,0,0,0 /* blocksize */ /* -> data follows */
137 };
138
139 // samplerate follows
140 long rate=sfinfo->samplerate; // FIXME: Get proper rate from sfinfo
141 Convert::setfloat80((unsigned char*)buf,28,rate);
142
143 outfilehandle->write(buf,54);
144 return;
145
146 }
147}
148void hd24sndfile::writerawbuf(unsigned char* buf,__uint32 subblockbytes)
149{
150 if ((sf_format & 0xFF0000) ==SF_FORMAT_AIFF)
151 {
152 // and we're doing 24 bits.
153 for (__uint32 i=0;i<subblockbytes;i+=3)
154 {
155 char a=buf[i];
156 buf[i]=buf[i+2];
157 buf[i+2]=a;
158 }
159 }
160
161 // maybe we want to do 24->16 bit conversion here
162
163 if (sndfilehandle != NULL)
164 {
165 #if (HD24DEBUG==1)
166 cout << "soundfile=" << soundfile <<endl;
167 #endif
168 #if (HD24DEBUG==1)
169 cout << "soundfile->sf_write_raw(sndfilehandle,buf,subblockbytes);" << endl;
170 #endif
171 soundfile->sf_write_raw(sndfilehandle,buf,subblockbytes);
172 return;
173 }
174 if (outfilehandle!=NULL)
175 {
176 outfilehandle->write((const char*)buf,subblockbytes);
177 }
178}
179
180void hd24sndfile::close()
181{
182 if (sndfilehandle != NULL)
183 {
184 soundfile->sf_close(sndfilehandle);
185 return;
186 }
187 if (outfilehandle == NULL) return;
188
189
190 switch (sf_format & 0xFF0000)
191 {
192 case SF_FORMAT_WAV:
193 {
194 // TODO: set sample rate, len, etc. in header
195 long pos=outfilehandle->tellp();
196 char bufword[4];
197 bufword[0]=(char)((pos-8)%256);
198 bufword[1]=(char)(((pos-8)>>8)%256);
199 bufword[2]=(char)(((pos-8)>>16)%256);
200 bufword[3]=(char)(((pos-8)>>24)%256);
201 outfilehandle->seekp(4);
202 outfilehandle->write(bufword,4);
203
204 bufword[0]=(char)((pos-44)%256);
205 bufword[1]=(char)(((pos-44)>>8)%256);
206 bufword[2]=(char)(((pos-44)>>16)%256);
207 bufword[3]=(char)(((pos-44)>>24)%256);
208 outfilehandle->seekp(40);
209 outfilehandle->write(bufword,4);
210
211 outfilehandle->close();
212 break;
213 }
214 case SF_FORMAT_AIFF:
215 {
216 long pos=outfilehandle->tellp();
217 char bufword[4];
218 bufword[3]=(char)((pos-8)%256);
219 bufword[2]=(char)(((pos-8)>>8)%256);
220 bufword[1]=(char)(((pos-8)>>16)%256);
221 bufword[0]=(char)(((pos-8)>>24)%256);
222
223 outfilehandle->seekp(4);
224 outfilehandle->write(bufword,4);
225
226 long chunksize=(pos-46);
227 long sambytes=chunksize-8;
228
229
230 long samframes=sambytes/3; // Bytes per sample. TODO: Not hardcode this
231 bufword[3]=(char)(samframes%256);
232 bufword[2]=(char)((samframes>>8)%256);
233 bufword[1]=(char)((samframes>>16)%256);
234 bufword[0]=(char)((samframes>>24)%256);
235 outfilehandle->seekp(22);
236 outfilehandle->write(bufword,4);
237
238
239 bufword[3]=(char)(chunksize%256);
240 bufword[2]=(char)((chunksize>>8)%256);
241 bufword[1]=(char)((chunksize>>16)%256);
242 bufword[0]=(char)((chunksize>>24)%256);
243 outfilehandle->seekp(42);
244 outfilehandle->write(bufword,4);
245
246
247
248 outfilehandle->close();
249 break;
250
251 }
252 default:
253 {
254 outfilehandle->close();
255 break;
256
257 }
258 }
259}
260
261void hd24sndfile::write_float(float* buf,__uint32 frames)
262{
263 if (sndfilehandle != NULL)
264 {
265 soundfile->sf_write_float(sndfilehandle,buf,frames);
266 }
267 return;
268}
269
270
diff --git a/src/lib/hd24sndfile.h b/src/lib/hd24sndfile.h
new file mode 100644
index 0000000..bd31145
--- /dev/null
+++ b/src/lib/hd24sndfile.h
@@ -0,0 +1,37 @@
1#ifndef __hd24sndfile_h__
2#define __hd24sndfile_h__
3class SoundFileWrapper;
4#include <config.h>
5#include <fstream>
6using std::ofstream;
7#include <sharedlibs.h>
8#include <sndfile.h>
9
10class hd24sndfile
11{
12private:
13
14 SF_INFO* sfinfo;
15 int _handletype;
16 SoundFileWrapper* soundfile; /* runtime loading wrapper for libsndfile */
17 int sf_format;
18public:
19 SNDFILE* sndfilehandle;
20 ofstream *outfilehandle;
21
22 hd24sndfile(int p_format,SoundFileWrapper* p_soundfile);
23 ~hd24sndfile();
24 int handletype();
25 void* handle();
26 void handle(SNDFILE* newhandle);
27 void handle(ofstream* newhandle);
28 void handle(void* newhandle,int htype);
29 void open(const char* filename,int filemode,SF_INFO* infoblock,
30 SoundFileWrapper* _soundfile);
31 void open(const char* filename,int filemode,SF_INFO* infoblock);
32 void writerawbuf(unsigned char* buf,__uint32 subblockbytes);
33 void close();
34 void write_float(float* buf,__uint32 frames);
35};
36
37#endif
diff --git a/src/lib/hd24song.cpp b/src/lib/hd24song.cpp
new file mode 100755
index 0000000..ac1db77
--- /dev/null
+++ b/src/lib/hd24song.cpp
@@ -0,0 +1,2188 @@
1#include <config.h>
2#include "hd24fs.h"
3#include "convertlib.h"
4#include "memutils.h"
5#define FRAMESPERSEC 30 /* 30 or 100; 30=default for HD24 (=SMPTE rate) */
6#define SONGDEBUG 0
7#if (SONGDEBUG==1)
8#define MEMLEAKMULT 10000
9#else
10#define MEMLEAKMULT 1
11#endif
12#define CACHEBUFFERS 30 /* enough for 25 locate points+some lookahead */
13#define NOTHINGTOQUEUE 0xFFFFFFFF
14#define CACHEBLOCK_UNUSED 0xFFFFFFFF /* a song can never have this number of blocks
15 because this is the max no. of samples in a song
16 and a block consists of multiple samples */
17#define SONGINFO_AUDIOBLOCKS 0x00
18#define SONGINFO_SECSAMPLESWITCH 0x8 /* *512=samples before switch to next track */
19#define SONGINFO_SECBYTESWITCH 0xC /* *512=bytes before switch to next track */
20#define SONGINFO_SONGNAME_8 0x28
21#define SONGINFO_CHANNELS 0x31
22#define SONGINFO_SAMPLERATE 0x34
23#define SONGINFO_BITDEPTH 0x37
24#define SONGINFO_SONGLENGTH_IN_SAMPLES 0x38
25#define SONGINFO_WRITEPROTECTED 0x3c
26#define SONGINFO_LOCATEPOINTLIST 0xb8
27#define LOCATEENTRY_LENGTH 12
28#define SONGINFO_SONGNAME 0x3b8
29#define SONGINFO_ALLOCATIONLIST 0x400
30#define ALLOCINFO_ENTRYLEN 8
31#define ALLOCINFO_SECTORNUM 0x00
32#define ALLOCINFO_AUDIOBLOCKSINBLOCK 0x04
33#define ALLOC_ENTRIES_PER_SONG (ALLOC_SECTORS_PER_SONG*(512/ALLOCINFO_ENTRYLEN))
34#define LOCATE_TIMECODE 0
35#define LOCATE_NAME 4
36/* Quick calculation: A song is max 2^32 samples * 3 bytes *24 tracks
37 = 309 237 645 312 bytes
38 1 block=0x480h sectors = 589 824 bytes
39 So the max number of blocks in a song = (309237645312 / 589824) blocks = 524288 blocks
40*/
41#define MAX_BLOCKS_IN_SONG 524288
42const int hd24song::LOCATEPOS_SONGSTART =0;
43const int hd24song::LOCATEPOS_LOOPSTART =1;
44const int hd24song::LOCATEPOS_LOOPEND =2;
45const int hd24song::LOCATEPOS_PUNCHIN =21;
46const int hd24song::LOCATEPOS_PUNCHOUT =22;
47const int hd24song::LOCATEPOS_EDITIN =23;
48const int hd24song::LOCATEPOS_EDITOUT =24;
49const int hd24song::LOCATEPOS_LAST =24;
50const int hd24song::READMODE_COPY =0;
51const int hd24song::READMODE_REALTIME =1;
52const int hd24song::WRITEMODE_COPY =2;
53const int hd24song::WRITEMODE_REALTIME =3;
54void hd24song::loadblockintocache(__uint32 blocktoqueue)
55{
56 __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors();
57
58 for (int i=LOCATEPOS_LAST;i<CACHEBUFFERS;i++) {
59 if (cachebuf_blocknum[i]==blocktoqueue) {
60 return; // already in cache.
61 }
62 }
63// cout << "Caching block " << blocktoqueue << endl;
64 cachebuf_blocknum[currcachebufnum]=blocktoqueue;
65
66////////////////////// TODO: THIS BLOCK OF CODE CAN BE REPLACED BY GETFIRSTBLOCKSECTOR
67 __uint32 rtallocentrynum=0; // reset cursor to start of song
68 __uint32 rtallocstartblock=0; // blocknum of first block in current allocation entry
69 __uint32 rtallocstartsector=Convert::getint32(buffer,SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*rtallocentrynum)+ALLOCINFO_SECTORNUM);
70 __uint32 rtallocaudioblocks=Convert::getint32(buffer,SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*rtallocentrynum)+ALLOCINFO_AUDIOBLOCKSINBLOCK);
71 __uint32 blocknum=blocktoqueue;
72
73 while ((blocknum-rtallocstartblock) >= rtallocaudioblocks) {
74 rtallocentrynum++; // reset cursor to start of song
75 if (rtallocentrynum>=ALLOC_ENTRIES_PER_SONG ) break;
76 rtallocstartblock+=rtallocaudioblocks; // blocknum of first block in current allocation entry
77 rtallocstartsector=Convert::getint32(buffer,
78 SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*rtallocentrynum)+ALLOCINFO_SECTORNUM);
79 rtallocaudioblocks=Convert::getint32(buffer,
80 SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*rtallocentrynum)+ALLOCINFO_AUDIOBLOCKSINBLOCK);
81
82 }
83///////////////////////////////////////////////////
84// cout << "allocentrynum=" << rtallocentrynum << endl;
85 parentfs->readsectors(parentfs->devhd24,
86 rtallocstartsector+((blocknum-rtallocstartblock)*blocksize_in_sectors),
87 cachebuf_ptr[currcachebufnum],blocksize_in_sectors); // raw read
88
89// cachebuf_ptr[currcachebufnum]=NULL; // TODO: READ SECTORS!!!
90
91 currcachebufnum++;
92 if (currcachebufnum>=CACHEBUFFERS)
93 {
94 currcachebufnum=LOCATEPOS_LAST+1;
95 }
96 return;
97}
98
99
100void hd24song::bufferpoll() {
101 // A process can call this procedure to tell the song
102 // object to check the cache request queue for blocks
103 // to cache.
104 if (currentreadmode==READMODE_COPY) return;
105 if (polling==1)
106 {
107 // Previous poll is still in progress.
108 // This is not a proper semaphore system but will
109 // help relief processing weight should the system
110 // get overloaded. Normally bufferpoll shouldn't be
111 // called much more than around 20 times per second,
112 // so the chance two polls interfere with one another
113 // is minimal.
114 return;
115 }
116 polling=1; // semaphore
117 if (blocktoqueue!=NOTHINGTOQUEUE)
118 {
119// cout << "queue request for " <<blocktoqueue << endl;
120 loadblockintocache(blocktoqueue);
121 blocktoqueue=NOTHINGTOQUEUE;
122 }
123 polling=0; // poll done
124}
125
126__uint32 hd24song::locatepointcount() {
127 return LOCATEPOS_LAST+1;
128}
129
130__uint32 hd24song::getlocatepos(int locatepoint)
131{
132 if (locatepoint<0) locatepoint=0;
133 if (locatepoint>LOCATEPOS_LAST) return songlength_in_samples();
134 long entryoffset=SONGINFO_LOCATEPOINTLIST+(locatepoint*LOCATEENTRY_LENGTH);
135 return Convert::getint32(buffer,entryoffset+LOCATE_TIMECODE);
136}
137
138string* hd24song::getlocatename(int locatepoint)
139{
140 if (locatepoint<0) locatepoint=0;
141 if (locatepoint>LOCATEPOS_LAST) {
142 string* newstr=new string("END");
143 return newstr;
144 }
145 long entryoffset=SONGINFO_LOCATEPOINTLIST+(locatepoint*LOCATEENTRY_LENGTH);
146 return Convert::readstring(buffer,entryoffset+LOCATE_NAME,8);
147}
148
149
150void hd24song::setlocatename(int locatepoint,string newname)
151{
152
153 if (locatepoint<0) locatepoint=0;
154 if (locatepoint>LOCATEPOS_LAST) return;
155 while (newname.length()<8) {
156 newname+=" ";
157 }
158 long entryoffset=SONGINFO_LOCATEPOINTLIST+(locatepoint*LOCATEENTRY_LENGTH);
159 for (__uint32 i=0;i<8;i++) {
160 buffer[entryoffset+LOCATE_NAME+i]=newname.c_str()[i];
161 }
162 return;
163}
164void hd24song::silenceaudioblocks(__uint32 allocsector,__uint32 numblocks)
165{
166 /* Given a sector number and a block count, silence the
167 given number of audio blocks on the drive starting
168 from the given sector number.
169 This function has 2 modes- one working with a 1-sector
170 stack-allocated block (slow), the other working with
171 a heap-allocated cluster (fast but memory intensive).
172 The heap method may need up to a few (2.3 or so) megabytes of RAM.
173 If heap allocation fails, the slow method is used.
174 */
175 unsigned char onesector[512];
176 memset(onesector,0,512);
177
178 __uint32 sectorstoclear=parentfs->getblocksizeinsectors();
179 sectorstoclear*=numblocks;
180 unsigned char* clearblock=(unsigned char*)memutils::mymalloc("silenceaudioblocks",sectorstoclear*512,1);
181 if (clearblock==NULL)
182 {
183 // Alloc failed, use low-memory use version
184 for (__uint32 i=0;i<sectorstoclear;i++)
185 {
186 parentfs->writesectors(parentfs->devhd24,
187 allocsector+i,
188 onesector,
189 1);
190 }
191 }
192 else
193 {
194 memset(clearblock,0,512*sectorstoclear);
195 parentfs->writesectors(parentfs->devhd24,
196 allocsector,
197 clearblock,
198 sectorstoclear);
199 memutils::myfree("silenceaudioblocks",clearblock);
200 }
201 return;
202}
203
204bool hd24song::setallocinfo(bool silencenew)
205{
206 return setallocinfo(silencenew,NULL,NULL,NULL);
207}
208
209__uint32 hd24song::requiredaudioblocks(__uint32 songlen)
210{
211 /* Figure out how many audio blocks we would expect
212 the song to have based on the songlength in samples. */
213 __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors();
214 __uint32 blocksize_in_bytes=blocksize_in_sectors*SECTORSIZE;
215 __uint32 bits=(this->bitdepth());
216 __uint32 bytes_per_sample=bits/8;
217 __uint32 tracks_per_song=physical_channels();
218 __uint32 tracksamples_per_block=0;
219 if (tracks_per_song>0) {
220 tracksamples_per_block=(blocksize_in_bytes / bytes_per_sample) / tracks_per_song;
221 }
222
223 __uint32 remainder=songlen%tracksamples_per_block;
224 __uint32 blocks_expected=(songlen-remainder)/tracksamples_per_block;
225 if (remainder!=0) {
226 blocks_expected++;
227 }
228 return blocks_expected;
229}
230
231bool hd24song::allocatenewblocks(__uint32 blockstoalloc,bool silencenew,char* message,int* cancel,int (*checkfunc)())
232{
233 /* Allocate space in the real drive usage table.
234 Mind that we've been asked to allocate a certain
235 number of blocks, although in reality we are not
236 allocating blocks but clusters of blocks. */
237#if (SONGDEBUG == 1)
238 cout << "Total blocks to alloc=" << blockstoalloc << endl;
239#endif
240 __uint32 totblockstoalloc=blockstoalloc;
241 __uint32 allocsector=0;
242 __uint32 blockspercluster=parentfs->getblockspercluster();
243 cancel=cancel;
244 while (blockstoalloc>0)
245 {
246 __uint32 pct=(__uint32)((100*(totblockstoalloc-blockstoalloc))/totblockstoalloc);
247 if (message!=NULL) {
248 sprintf(message,
249 "Lengthening song... allocating block %ld of %ld, %ld%% done",
250 (long)(totblockstoalloc-blockstoalloc),
251 (long)totblockstoalloc,
252 (long)pct
253 );
254 }
255 if (checkfunc!=NULL)
256 {
257 checkfunc();
258 }
259 allocsector=getnextfreesector(allocsector);
260
261#if (SONGDEBUG == 1)
262 cout << "Allocsector=" << allocsector << endl;
263 cout << "Blockstoalloc=" << blockstoalloc << endl;
264#endif
265 if (allocsector==0) {
266#if (SONGDEBUG == 1)
267 cout << "Ran out of space with " << blockstoalloc
268 <<" left to alloc " << endl;
269#endif
270
271 return false;
272 }
273 if (silencenew)
274 {
275 // overwrite cluster with silence.
276#if (SONGDEBUG == 1)
277 cout << "Overwriting cluster with silence." << endl;
278#endif
279 this->silenceaudioblocks(allocsector,blockspercluster);
280 }
281 __uint32 alloccluster=parentfs->sector2cluster(allocsector);
282#if (SONGDEBUG == 1)
283 cout << "Alloccluster=" << alloccluster << endl;
284#endif
285 parentfs->enablebit(alloccluster,parentfs->sectors_driveusage);
286 if (blockstoalloc>=blockspercluster)
287 {
288 blockstoalloc-=blockspercluster;
289 }
290 else
291 {
292 blockstoalloc=0;
293 }
294 }
295 return true;
296}
297
298bool hd24song::setallocinfo(bool silencenew,char* message,int* cancel,int (*checkfunc)())
299{
300 /* This function is intended for recovering live recordings
301 and lengthening songs. To use it, set a new song length
302 first, then call this function- it will add the required
303 number of blocks to the song.
304
305 Boolean 'silencenew' indicates if newly allocated space
306 should be overwritten with silence.
307
308 For initializing songs to nonzero length, you will want
309 to set this to TRUE.
310
311 For recovering live recordings you will want to set it
312 to FALSE.
313
314 For realtime recording, it is set to FALSE for efficiency
315 reasons, as the recording algorithm itself will overwrite
316 newly allocated space with audio (and silence as needed).
317
318 Savemessage allows giving textual feedback to the user
319 and the int pointed to by cancel will be set to 1 by the
320 GUI if the user interrupts the process.
321 In case of recovering a song, after setting the length of
322 a crashed song to the estimated duration, we want to try
323 to find back the audio.
324
325 It is reasonable that this previously recorded audio can be
326 found by simply allocating as many unused clusters to the
327 song as needed to reach the desired length; because those
328 same clusters would have been allocated to the song after
329 pressing 'stop'.
330
331 This function attempts to perform this allocation (which
332 should also allow people to perform headerless
333 live recoveries).
334
335 The way this will work is:
336 -- find out how many audio blocks are allocated to the song;
337 -- find out how many we think there *should* be allocated;
338 -- then, allocate those blocks (in a copy of the usage table);
339 -- finally, append the newly allocated blocks to the song.
340 -- the last can be done by subtracting the old usage table
341 from the new one and calling appendorphanclusters.
342
343 FIXME: operation is not correct when running out of drive space.
344 TODO: we count blocks to allocate but in reality clusters are
345 being reserved. Shouldn't we work cluster based all the
346 way?
347 */
348
349 __uint32 blocksinalloctable=audioblocks_in_alloctable();
350 __uint32 blocks_expected=requiredaudioblocks(songlength_in_samples());
351
352
353#if (SONGDEBUG == 1)
354 cout << "Actual blocks allocated for song:" << blocksinalloctable << endl;
355 cout << "Expected blocks allocated for song:" << blocks_expected << endl;
356#endif
357 if (blocksinalloctable==blocks_expected)
358 {
359 // right amount of space is already allocated.
360 return true;
361 }
362
363 if (blocksinalloctable>blocks_expected)
364 {
365 // looks like too much space is allocated,
366 // but setallocinfo() won't support song shrinking
367 // for now.
368 return false;
369 }
370
371 /* Not enough space is allocated-- allocate as much extra as needed. */
372#if (SONGDEBUG == 1)
373 cout << "Allocating space for song. " <<endl;
374#endif
375 __uint32 blockstoalloc=blocks_expected-blocksinalloctable;
376
377 unsigned char* copyusagetable=parentfs->getcopyofusagetable();
378 if (copyusagetable==NULL)
379 {
380 /* Cannot get usage table (out of memory?) */
381 return false;
382 }
383
384 bool tryallocnew=this->allocatenewblocks(blockstoalloc,silencenew,message,cancel,checkfunc);
385 if (tryallocnew==false)
386 {
387 /* Cannot allocate new blocks (out of drive space?) */
388 memutils::myfree("copyusagetable",copyusagetable);
389 return false;
390 }
391
392 /* Cluster allocation succeeded.
393 To find out which clusters have been allocated,
394 XOR the previous copy of the usage table over it.
395 This will result in a list of newly allocated
396 (orphan) clusters still to be appended to the song.
397 */
398 for (__uint32 i=0;i<(512*15);i++)
399 {
400 copyusagetable[i]=(copyusagetable[i])
401 ^(parentfs->sectors_driveusage[i]);
402 }
403
404#if (SONGDEBUG == 1)
405 cout << "Alloc action successful- append orphan clusters now." << endl;
406#endif
407 // call appendorphanclusters
408 if (message!=NULL)
409 {
410 sprintf(message,"Adding allocated space to song...");
411 if (checkfunc!=NULL)
412 {
413 checkfunc();
414 }
415 }
416 bool songresize;
417 if (silencenew) {
418 songresize=false;
419 }
420 else
421 {
422 songresize=true;
423 }
424 appendorphanclusters(copyusagetable,songresize);
425 memutils::myfree("copyusagetable",copyusagetable);
426 // save for either song or drive usage table is not
427 // to be called here- it would violate the concept
428 // of safe, read-only recovery.
429 return true;
430}
431
432void hd24song::appendorphanclusters(unsigned char* usagebuffer,bool allowsongresize)
433{
434 __uint32 clusters=parentfs->clustercount();
435 __uint32 currpos=0;
436 __uint32 curralloctableentry=used_alloctable_entries();
437#if (SONGDEBUG == 1)
438 cout << "Appending orphan clusters to song. Used alloctable entries=" << curralloctableentry
439 << "clusters=" << clusters
440 << endl;
441#endif
442
443 while (currpos<clusters) {
444 __uint32 blockstart=currpos;
445 while (parentfs->isfreecluster(blockstart,usagebuffer) && (blockstart<clusters)) {
446 blockstart++;
447 }
448#if (SONGDEBUG == 1)
449 cout << "Block starts at cluster " <<blockstart << endl;
450#endif
451 if (blockstart==clusters) {
452 break;
453 }
454
455 // blockstart now points to a nonfree cluster
456 __uint32 blockend=blockstart;
457 while (!parentfs->isfreecluster(blockend,usagebuffer) && (blockend<clusters)) {
458 blockend++;
459 }
460 // blockend now points to a free cluster
461 currpos=blockend;
462 __uint32 blocklen=blockend-blockstart;
463
464 __uint32 entrystartsector=(unsigned int) (parentfs->cluster2sector(blockstart));
465 __uint32 entrynumblocks=(unsigned int)( parentfs->getblockspercluster()*blocklen );
466 Convert::setint32(buffer,
467 SONGINFO_ALLOCATIONLIST+ALLOCINFO_SECTORNUM
468 +(ALLOCINFO_ENTRYLEN*curralloctableentry),entrystartsector);
469
470 Convert::setint32(buffer,
471 SONGINFO_ALLOCATIONLIST+ALLOCINFO_AUDIOBLOCKSINBLOCK
472 +(ALLOCINFO_ENTRYLEN*curralloctableentry),entrynumblocks);
473 curralloctableentry++;
474#if (SONGDEBUG == 1)
475 printf("%x %x\n",(unsigned int)parentfs->cluster2sector(blockstart),(unsigned int)( parentfs->getblockspercluster()*blocklen ));
476#endif
477 }
478 /* the operation may have resulted in the song getting
479 longer. This is due to the fact that while recording,
480 'stop' may be pressed before all audio blocks of the
481 cluster have been used.
482 Also, of course, there may be more orphaned clusters
483 around than belong to the song- for whatever reason.
484 */
485
486 __uint32 blocksinalloctable=audioblocks_in_alloctable();
487
488 __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors();
489 __uint32 blocksize_in_bytes=blocksize_in_sectors*SECTORSIZE;
490 __uint32 bits=(this->bitdepth());
491 __uint32 bytes_per_sample=bits/8;
492 __uint32 tracks_per_song=physical_channels();
493 __uint32 tracksamples_per_block=0;
494 if (tracks_per_song>0) {
495 tracksamples_per_block=(blocksize_in_bytes / bytes_per_sample) / tracks_per_song;
496 }
497 __uint32 newsonglen=tracksamples_per_block*blocksinalloctable;
498 Convert::setint32(buffer,SONGINFO_AUDIOBLOCKS,blocksinalloctable);
499
500 /* The following directly sets the songlength in the song buffer
501 rather than via songlength_in_samples(val) to prevent
502 testing whether more space needs to be allocated-
503 which is not needed as space has just been allocated.
504 (Also, the below number may be less accurate than the
505 number some user might specify via songlength_in_samples(val)).
506 */
507 if (allowsongresize)
508 {
509 Convert::setint32(buffer,SONGINFO_SONGLENGTH_IN_SAMPLES,newsonglen);
510 }
511 return;
512}
513
514void hd24song::setblockcursor(__uint32 blocknum)
515{
516 allocentrynum=0; // reset cursor to start of song
517 allocstartblock=0; // blocknum of first block in current allocation entry
518 allocstartsector=Convert::getint32(buffer,SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*allocentrynum)+ALLOCINFO_SECTORNUM);
519 allocaudioblocks=Convert::getint32(buffer,SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*allocentrynum)+ALLOCINFO_AUDIOBLOCKSINBLOCK);
520 // cout << " allocaudioblocks=" << allocaudioblocks << endl;
521 while ((blocknum-allocstartblock) >= allocaudioblocks) {
522 allocentrynum++; // reset cursor to start of song
523 allocstartblock+=allocaudioblocks; // blocknum of first block in current allocation entry
524 allocstartsector=Convert::getint32(buffer,
525 SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*allocentrynum)+ALLOCINFO_SECTORNUM);
526 allocaudioblocks=Convert::getint32(buffer,
527 SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*allocentrynum)+ALLOCINFO_AUDIOBLOCKSINBLOCK);
528 }
529 return;
530}
531
532void hd24song::unmark_used_clusters(unsigned char* sectors_inuse)
533{
534 /*
535 * Given an image of used clusters, this function
536 * will alter that image to unmark the clusters
537 * in use by this song.
538 * Under normal circumstances, this is used to
539 * delete songs.
540 * However, it is also useful to search for orphan
541 * clusters (by unmarking all clusters in use by
542 * all songs- the remaining clusters then must be
543 * orphan clusters)
544 */
545#if (SONGDEBUG == 1)
546 cout << "unmark used clusters." << endl;
547#endif
548 __uint32 allocentries=used_alloctable_entries();
549
550 if (allocentries==0) {
551#if (SONGDEBUG == 1)
552 cout << "Song claims no used allocation entries." << endl;
553#endif
554 return;
555 }
556
557 __uint32 blockspercluster=parentfs->getblockspercluster();
558
559 for (__uint32 i=0; i<allocentries; i++)
560 {
561 __uint32 entrystartsector=Convert::getint32(buffer,
562 SONGINFO_ALLOCATIONLIST+ALLOCINFO_SECTORNUM
563 +(ALLOCINFO_ENTRYLEN*i));
564
565 __uint32 entrynumblocks=Convert::getint32(buffer,
566 SONGINFO_ALLOCATIONLIST+ALLOCINFO_AUDIOBLOCKSINBLOCK
567 +(ALLOCINFO_ENTRYLEN*i));
568
569
570 __uint32 entrystartcluster=parentfs->sector2cluster(entrystartsector);
571#if (SONGDEBUG == 1)
572 cout << "startsector=" <<entrystartsector << " blocks=" << entrynumblocks <<" clust=" << entrystartcluster << endl;
573#endif
574
575 __uint32 entrynumclusters=(entrynumblocks-(entrynumblocks%blockspercluster))/blockspercluster;
576 if ((entrynumblocks%blockspercluster)!=0)
577 {
578 entrynumclusters++;
579 }
580#if (SONGDEBUG == 1)
581 cout << "buffer=" << buffer << endl;
582#endif
583 if (entrynumclusters==0)
584 {
585#if (SONGDEBUG == 1)
586 cout << "nothing to free here." << endl;
587#endif
588
589 }
590 for (__uint32 j=0;j<entrynumclusters;j++) {
591 __uint32 clust2free=j+entrystartcluster;
592 parentfs->freecluster(clust2free,sectors_inuse);
593#if (SONGDEBUG == 1)
594 cout << clust2free << " ";
595#endif
596 }
597#if (SONGDEBUG == 1)
598 cout << endl;
599#endif
600 }
601}
602
603__uint32 hd24song::currentlocation()
604{
605 return songcursor;
606}
607void hd24song::currentlocation(__uint32 offset)
608{
609 golocatepos(offset);
610}
611
612__uint32 hd24song::golocatepos(__uint32 offset)
613{
614 /* Offset indicates next sample that will be
615 played back (or recorded). A song of 1 sample long
616 can have the cursor set at offset 0 or offset 1;
617 offset 1 is then beyond the end of the song, which is
618 meaningful for recording but not for playback. */
619
620 __uint32 songlen=songlength_in_samples();
621
622 if (offset>songlen) {
623 offset=songlen;
624 //return offset;
625 }
626
627 songcursor=offset;
628 evenodd=0;
629
630 __uint32 samplenumber=songcursor;
631#if (SONGDEBUG == 1)
632// cout << "songcursor=" << songcursor << endl;
633#endif
634 __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors();
635 __uint32 blocksize_in_bytes=blocksize_in_sectors*SECTORSIZE;
636 __uint32 bits=(this->bitdepth());
637 __uint32 bytes_per_sample=bits/8;
638 __uint32 tracks_per_song=physical_channels();
639 __uint32 tracksamples_per_block=0;
640 if (tracks_per_song>0) {
641 tracksamples_per_block=(blocksize_in_bytes / bytes_per_sample) / tracks_per_song;
642 }
643 __uint32 blocknum=0;
644 if (tracksamples_per_block>0) {
645 blocknum=(samplenumber/(tracksamples_per_block));
646 }
647
648#if (SONGDEBUG == 1)
649// cout << "still going strong" << endl;
650#endif
651
652 setblockcursor(blocknum);
653
654 return songcursor;
655}
656
657__uint32 hd24song::setlocatepos(int locatepoint,__uint32 offset)
658{
659 /** Sets the value of a locate point to the given offset.
660 Parameters:
661 locatepoint
662 The 0-based locate point identifier
663 offset
664 The new offset (in samples*) for the locate point.
665 * In high samplerate songs (88k2, 96k), the offset is given as
666 number of sample pairs, because audio data is interlaced
667 across 2 physical tracks.
668 */
669
670 if (locatepoint<0)
671 {
672 locatepoint=0;
673 }
674
675 if (locatepoint>LOCATEPOS_LAST)
676 {
677 return 0;
678 }
679
680 long entryoffset=SONGINFO_LOCATEPOINTLIST
681 +(locatepoint*LOCATEENTRY_LENGTH);
682
683 buffer[entryoffset+LOCATE_TIMECODE+3]=offset%256;
684 offset=offset>>8;
685 buffer[entryoffset+LOCATE_TIMECODE+2]=offset%256;
686 offset=offset>>8;
687 buffer[entryoffset+LOCATE_TIMECODE+1]=offset%256;
688 offset=offset>>8;
689 buffer[entryoffset+LOCATE_TIMECODE+0]=offset%256;
690 return getlocatepos(locatepoint);
691}
692
693hd24song::hd24song(hd24project* p_parent,__uint32 p_songid)
694{
695#if (SONGDEBUG == 1)
696 cout << "CONSTRUCT hd24song " << p_songid << endl;
697#endif
698 currentreadmode=READMODE_COPY;
699 blocktoqueue=NOTHINGTOQUEUE;
700 polling=0;
701 evenodd=0;
702 audiobuffer=NULL;
703 scratchbook=NULL;
704 buffer=NULL;
705 framespersec=FRAMESPERSEC;
706 lastallocentrynum=0;
707 busyrecording=false;
708 mysongid=p_songid;
709 rehearsemode=false;
710 lengthened=false;
711 lastavailablecacheblock=0xFFFFFFFF;
712 currcachebufnum=LOCATEPOS_LAST+1;
713 buffer=(unsigned char*)memutils::mymalloc("hd24song-buffer",16384,1);
714 parentfs=p_parent->parentfs;
715 parentproject=p_parent;
716 __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors();
717 __uint32 blocksize_in_bytes=blocksize_in_sectors*SECTORSIZE;
718
719 for (__uint32 tracknum=1;tracknum<=24;tracknum++)
720 {
721 track_armed[tracknum-1]=false;
722 }
723
724 // 'read enabled' is used in copy mode to reduce the amount of
725 // secors that need to be read from disk.
726 for (__uint32 tracknum=1;tracknum<=24;tracknum++)
727 {
728 track_readenabled[tracknum-1]=true; // by default all are read enabled.
729 }
730
731#if (SONGDEBUG == 1)
732 cout << "2" << endl;
733#endif
734 audiobuffer=(unsigned char *)memutils::mymalloc("hd24song-audiobuffer",blocksize_in_bytes+SECTORSIZE,1);
735 scratchbook=(unsigned char *)memutils::mymalloc("hd24song-scratchbook",blocksize_in_bytes+SECTORSIZE,1);
736
737 if (audiobuffer==NULL) {
738#if (SONGDEBUG ==1)
739 cout << "could not allocate audio buffer" << endl;
740#endif
741 }
742
743 // Set up cache buffers for realtime access
744 // first, dynamically create pointer array
745 cachebuf_blocknum=(__uint32*)memutils::mymalloc("hd24song-cachebuf",sizeof(__uint32)*CACHEBUFFERS,1);
746 cachebuf_ptr=(unsigned char**)memutils::mymalloc("hd24song-cachebufptr",sizeof (unsigned char *)*CACHEBUFFERS,1);
747 // then, allocate blocks and point array to it.
748 int i;
749
750 for (i=0;i<CACHEBUFFERS;i++)
751 {
752 cachebuf_ptr[i]=NULL;
753 }
754
755 for (i=0;i<CACHEBUFFERS;i++)
756 {
757 cachebuf_blocknum[i]=CACHEBLOCK_UNUSED;
758 cachebuf_ptr[i]=(unsigned char*)memutils::mymalloc("hd24song-cachebufptr[i]",blocksize_in_bytes,1);
759 }
760
761 __uint32 songsector=parentproject->getsongsectornum(mysongid);
762#if (SONGDEBUG ==1)
763 cout << "Reading # song sectors= " << TOTAL_SECTORS_PER_SONG
764 << "from sec " << songsector << endl;
765#endif
766 parentfs->readsectors(parentfs->devhd24,
767 songsector,
768 buffer,TOTAL_SECTORS_PER_SONG);
769 parentfs->fstfix(buffer,TOTAL_SECTORS_PER_SONG*512);
770 //ncout << "sectors read="<<dummy<<endl;
771
772#if (SONGDEBUG ==1)
773 cout << "alloc mem for blocksectors" << endl;
774#endif
775
776 blocksector=(__uint32*)memutils::mymalloc("blocksector",600000,sizeof(__uint32));
777#if (SONGDEBUG ==1)
778 cout << "Blocksector=" <<blocksector << endl;
779 cout << "clear blocksectors" << endl;
780#endif
781 for (int i=0; i<600000;i++) {
782 blocksector[i]=0;
783 }
784 // how many blocks in this song?
785#if (SONGDEBUG == 1)
786 cout << "cleared blocksectors" << endl;
787
788 cout << "create song" << mysongid << endl;
789 cout << "blocksize in bytes=" << blocksize_in_bytes << endl;
790 cout << "bitdepth in bytes=" << bitdepth()/8 << endl;
791 cout << "phys_channels=" << physical_channels() << endl;
792#endif
793 if (physical_channels() >0)
794 {
795 __uint32 blocksize_in_samples=blocksize_in_bytes / (physical_channels()* (bitdepth()/8));
796 __uint32 number_of_blocks=(__uint32) floor ( songlength_in_samples() / blocksize_in_samples );
797#if (SONGDEBUG == 1)
798 cout << "songlen in sam=" << songlength_in_samples() << endl;
799#endif
800 if ( ( songlength_in_samples() % blocksize_in_samples ) !=0 )
801 {
802 number_of_blocks++;
803 }
804
805
806#if (SONGDEBUG == 1)
807 cout << " blocksize in sams = " << blocksize_in_samples;
808 cout << "=" << number_of_blocks << "blocks " << endl;
809
810 cout << "memoize alloc info for " << number_of_blocks << "blocks." << endl;
811#endif
812 memoizeblocksectors(number_of_blocks);
813 }
814
815 divider=0;
816 lastreadblock=0;
817 mustreadblock=1; // next time a sample is requested, we must read from disk
818 //cout << "golocatepos" << endl;
819 golocatepos(0);
820 //cout << "locate done" << endl;
821}
822
823__uint32 hd24song::songid()
824{
825 return this->mysongid;
826}
827
828bool hd24song::has_unexpected_end()
829{
830 // Check if this song has an 'unexpected end of song' error
831 // (in header mode, this always returns false)
832 if (this->parentfs->headersectors!=0)
833 {
834 return false;
835 }
836 // find out how many audioblocks are claimed to be allocated in the
837 // song allocation info table
838
839 __uint32 blocksinalloctable=audioblocks_in_alloctable();
840
841 if ( blocksinalloctable < Convert::getint32(buffer,SONGINFO_AUDIOBLOCKS) )
842 {
843 // the song itself claims it should have more audioblocks
844 return true;
845 }
846 // Over here we could also verify the expected number of blocks
847 // against the given song length in samples.
848 return false;
849}
850
851bool hd24song::is_fixable_unexpected_end()
852{
853 /** Checks if this song has a FIXABLE 'unexpected end of song' error */
854 __uint32 blocksinalloctable=audioblocks_in_alloctable();
855#if (SONGDEBUG == 1)
856 cout << "Blocks in alloctable=" << blocksinalloctable << endl;
857#endif
858 __uint32 songblockcount=Convert::getint32(buffer,SONGINFO_AUDIOBLOCKS);
859 if (songblockcount>MAX_BLOCKS_IN_SONG)
860 {
861 /* Safety feature: corruption detected,
862 block count of song is greater than theoretical maximum. */
863 songblockcount=MAX_BLOCKS_IN_SONG;
864 }
865
866 /* Values in songblockcount and blocksinalloctable should be equal
867 unless the song is corrupt. If the latter value lower,
868 there is an 'unexpected end of song' error. */
869
870 if (!( blocksinalloctable < songblockcount ))
871 {
872 // No unexpected end of song error, nothing to fix
873 return false;
874 }
875
876 /* There is an unexpected end of song error. But is it one of
877 the type we know how to automatically fix? */
878
879 if (used_alloctable_entries() == (512/ALLOCINFO_ENTRYLEN) ) {
880 /* Yes, it is. We have exactly 1 sector of allocated data and
881 the rest is zero data, due to a known (presumed) bug in
882 the HD24 recorder. */
883 return true;
884 }
885
886 /* No, it isn't. Then assume we cannot fix it. */
887 return false;
888}
889
890__uint32 hd24song::used_alloctable_entries()
891{
892 /** Counts how many entries in the song allocation table
893 are in use. */
894 __uint32 MAXALLOCENTRIES=((512/ALLOCINFO_ENTRYLEN)*5)-1;
895
896 for (__uint32 i=0;i<MAXALLOCENTRIES;i++)
897 {
898 __uint32 entrystartsector=Convert::getint32(buffer,
899 SONGINFO_ALLOCATIONLIST+ALLOCINFO_SECTORNUM
900 +(ALLOCINFO_ENTRYLEN*i));
901 if (entrystartsector==0) {
902 return i;
903 }
904 }
905 return MAXALLOCENTRIES;
906}
907
908__uint32 hd24song::audioblocks_in_alloctable()
909{
910 /** Finds out how many audio blocks are claimed in
911 the allocation table of the song. */
912 __uint32 checkentries=used_alloctable_entries();
913 if (checkentries==0) {
914 return 0;
915 }
916 __uint32 totblocks=0;
917
918 for (__uint32 i=0; i<checkentries; i++)
919 {
920 __uint32 entrynumblocks=Convert::getint32(buffer,
921 SONGINFO_ALLOCATIONLIST+ALLOCINFO_AUDIOBLOCKSINBLOCK
922 +(ALLOCINFO_ENTRYLEN*i));
923 totblocks+=entrynumblocks;
924
925 if (totblocks>MAX_BLOCKS_IN_SONG)
926 {
927 /* Safety net: Corruption detected, song claims to use
928 more blocks than the theoretical possible maximum. */
929 return MAX_BLOCKS_IN_SONG;
930 }
931 }
932
933 return totblocks;
934}
935
936hd24song::~hd24song()
937{
938#if (SONGDEBUG == 1)
939 cout << "DESTRUCT hd24song " << mysongid << endl;
940#endif
941 if (buffer!=NULL)
942 {
943 memutils::myfree("buffer",buffer);
944 buffer=NULL;
945 }
946 if (scratchbook != NULL)
947 {
948 memutils::myfree("scratchbook",scratchbook);
949 scratchbook=NULL;
950 }
951 if (audiobuffer != NULL)
952 {
953 memutils::myfree("audiobuffer",audiobuffer);
954 audiobuffer=NULL;
955 }
956 if (blocksector != NULL)
957 {
958 memutils::myfree("blocksector",blocksector);
959 blocksector=NULL;
960 }
961 int i;
962
963 // clear cache
964 for (i=0;i<CACHEBUFFERS;i++)
965 {
966 if (cachebuf_ptr[i]!=NULL) {
967 memutils::myfree("cachebuf_ptr[i]",cachebuf_ptr[i] );
968 }
969 }
970 if (cachebuf_ptr!=NULL)
971 {
972 memutils::myfree("cachebuf_ptr",cachebuf_ptr);
973 }
974 if (cachebuf_blocknum!=NULL)
975 {
976 memutils::myfree("cachebuf_blocknum",cachebuf_blocknum);
977 }
978// cout << "del song " << mysongid << endl;
979}
980
981void hd24song::queuecacheblock(__uint32 blocknum)
982{
983 // Only process request if the block is neither cached nor queued yeta
984 // This function is only called if a block is not cached.
985 // In addition, as playback progresses, the more blocks are queued,
986 // the less importance the oldest blocks have.
987 // For this reason, a circular queue would make sense-- if too many blocks
988 // get queued, the last one requested can be ignored.
989 // The queue needn't be very big; a shortcut is to use a queue of
990 // just 1 element long. This should still work OK because a block
991 // queue request may be issued over and over again until it is cached.
992 if (blocknum!=blocktoqueue)
993 {
994 // block not yet queued
995// cout << "Processing request to queue block " << blocknum << " for caching " << endl;
996 }
997 blocktoqueue=blocknum;
998 return;
999}
1000
1001string* hd24song::songname(hd24fs* parentfs, unsigned char* songbuf)
1002{
1003 string* ver=parentfs->version();
1004 if (*ver == "1.00") {
1005 // version 1.0 filesystem.
1006 delete ver;
1007 string* tmp=new string("");
1008 string* dummy=Convert::readstring(songbuf,SONGINFO_SONGNAME_8,8);
1009
1010 *tmp+=*dummy;
1011 delete dummy;
1012 if (tmp->length()==8) {
1013 dummy=Convert::readstring(songbuf,SONGINFO_SONGNAME_8+10,2);
1014 *tmp+=*dummy;
1015 delete dummy;
1016 }
1017 return tmp;
1018 }
1019 delete ver;
1020 string* tmp=Convert::readstring(songbuf,SONGINFO_SONGNAME,64);
1021 return tmp;
1022}
1023
1024string* hd24song::songname()
1025{
1026 return songname(this->parentfs,buffer);
1027}
1028
1029void hd24song::songname(string newname)
1030{
1031 songname(buffer,newname);
1032}
1033
1034void hd24song::songname(unsigned char* songbuf,string newname)
1035{
1036 hd24fs::setname(songbuf,newname,SONGINFO_SONGNAME_8,SONGINFO_SONGNAME);
1037 return;
1038}
1039
1040bool hd24song::iswriteprotected()
1041{
1042 __uint32 writeprot=(Convert::getint32(buffer,SONGINFO_WRITEPROTECTED));
1043 writeprot&=0x04000000;
1044 if (writeprot==0) return false;
1045 return true;
1046}
1047
1048void hd24song::setwriteprotected(bool prot)
1049{
1050 __uint32 writeprot=(Convert::getint32(buffer,SONGINFO_WRITEPROTECTED));
1051 writeprot&=0xFBFFFFFF;
1052
1053 if (prot) {
1054 writeprot|=0x04000000;
1055 }
1056 Convert::setint32(buffer,SONGINFO_WRITEPROTECTED,writeprot);
1057 return;
1058}
1059
1060void hd24song::physical_channels(unsigned char* songbuf,__uint32 newchannelcount)
1061{
1062 if (newchannelcount>24) newchannelcount=24;
1063 songbuf[SONGINFO_CHANNELS]=(unsigned char)(newchannelcount&0xFF);
1064}
1065
1066void hd24song::physical_channels(__uint32 newchannelcount)
1067{
1068 physical_channels(buffer,newchannelcount);
1069}
1070
1071__uint32 hd24song::physical_channels(unsigned char* songbuf)
1072{
1073 int channels=Convert::getint32(songbuf,SONGINFO_CHANNELS)>>24;
1074 channels=(channels & 0x1f);
1075 if (channels>24) channels=24;
1076 return channels;
1077}
1078
1079__uint32 hd24song::physical_channels()
1080{
1081 return physical_channels(buffer);
1082}
1083
1084__uint32 hd24song::logical_channels()
1085{
1086 if (this->samplerate()>=88200)
1087 {
1088 return (physical_channels()>>1);
1089 } else {
1090 return (physical_channels());
1091 }
1092}
1093
1094__uint32 hd24song::logical_channels(unsigned char* songbuf)
1095{
1096 if (samplerate(songbuf)>=88200)
1097 {
1098 return (physical_channels(songbuf)>>1);
1099 } else {
1100 return (physical_channels(songbuf));
1101 }
1102}
1103
1104void hd24song::logical_channels(unsigned char* songbuf,__uint32 channelcount)
1105{
1106 if (samplerate(songbuf)>=88200) {
1107 physical_channels(songbuf,channelcount*2);
1108 } else {
1109 physical_channels(songbuf,channelcount);
1110 }
1111}
1112
1113__uint32 hd24song::samplerate(unsigned char* songbuf)
1114{
1115 __uint32 samrate=Convert::getint32(songbuf,SONGINFO_SAMPLERATE)>>8;
1116 return samrate;
1117}
1118
1119__uint32 hd24song::samplerate()
1120{
1121 return samplerate(buffer);
1122}
1123
1124void hd24song::samplerate(unsigned char* songbuf,__uint32 newrate)
1125{
1126 __uint32 samrate=(newrate<<8);
1127 __uint32 bd=((unsigned char)songbuf[SONGINFO_BITDEPTH]);
1128 samrate|=bd;
1129 Convert::setint32(songbuf,SONGINFO_SAMPLERATE,samrate);
1130}
1131
1132void hd24song::samplerate(__uint32 newrate)
1133{
1134 samplerate(buffer,newrate);
1135}
1136
1137
1138__uint32 hd24song::bitdepth()
1139{
1140 __uint32 depth=(__uint32)((unsigned char)buffer[SONGINFO_BITDEPTH]);
1141 if ((depth!=24) && (depth !=16) && (depth!=32)) return 24;
1142 return depth;
1143}
1144
1145__uint32 hd24song::songlength_in_samples()
1146{
1147 return (Convert::getint32(buffer,SONGINFO_SONGLENGTH_IN_SAMPLES));
1148}
1149
1150__uint32 hd24song::songlength_in_samples(__uint32 newlen,bool silencenew)
1151{
1152 return hd24song::songlength_in_samples(newlen,silencenew,NULL,NULL);
1153}
1154
1155__uint32 hd24song::songlength_in_samples(__uint32 newlen,bool silencenew,char* savemessage,int* cancel)
1156{
1157 return hd24song::songlength_in_samples(newlen,silencenew,savemessage,cancel,NULL);
1158}
1159
1160hd24fs* hd24song::fs()
1161{
1162 return this->parentfs;
1163}
1164
1165__uint32 hd24song::songlength_in_samples(__uint32 newlen,bool silencenew,char* savemessage,int* cancel,int (*checkfunc)())
1166{
1167 /* Sets the length of a song and updates any allocation
1168 info as needed.
1169 The return value of the function is the actual song length
1170 set. Return value may differ from newlen if not enough drive
1171 space was available or if allocating ran into problems
1172 otherwise. */
1173 if (this==NULL)
1174 {
1175#if (SONGDEBUG==1)
1176 cout << "Song object is NULL! Cannot lengthen song." << endl;
1177#endif
1178 return 0;
1179 }
1180 __uint32 oldlen=songlength_in_samples();
1181 if (savemessage!=NULL)
1182 {
1183 // clear default save message
1184 savemessage[0]='\0';
1185 }
1186 if (cancel!=NULL)
1187 {
1188 *cancel=0;
1189 }
1190#if (SONGDEBUG==1)
1191 cout << "Lengthening song to " << newlen << " samples" << endl;
1192 if (silencenew) {
1193 cout << "(And silencing new blocks)" << endl;
1194 }
1195#endif
1196 Convert::setint32(buffer,SONGINFO_SONGLENGTH_IN_SAMPLES,newlen);
1197 if (newlen==0) {
1198 Convert::setint32(buffer,SONGINFO_AUDIOBLOCKS,0);
1199 return 0;
1200 }
1201
1202 // the above is required by setallocinfo
1203 if (setallocinfo(silencenew,savemessage,cancel,checkfunc)) {
1204 // setting alloc info succeeded
1205#if (SONGDEBUG==1)
1206 cout << "Success lengthening song to " << newlen << " samples" << endl;
1207#endif
1208 this->lengthened=true;
1209 memoizeblocksectors(Convert::getint32(buffer,SONGINFO_AUDIOBLOCKS));
1210 return newlen;
1211 }
1212 // setting new length failed- reset song to old length.
1213#if (SONGDEBUG==1)
1214 cout << "Failed. Keep at old length of " <<oldlen << endl;
1215#endif
1216 Convert::setint32(buffer,SONGINFO_SONGLENGTH_IN_SAMPLES,oldlen);
1217 return oldlen;
1218}
1219
1220__uint32 hd24song::songlength_in_samples(__uint32 newlen)
1221{
1222 return songlength_in_samples(newlen,true);
1223}
1224
1225string* hd24song::display_cursor()
1226{
1227 return (display_duration(songcursor));
1228}
1229__uint32 hd24song::cursorpos()
1230{
1231 return songcursor;
1232}
1233
1234
1235string* hd24song::display_duration(__uint32 offset,__uint32 samrate)
1236{
1237 //cout << "dispdur" << offset << endl;
1238 if (samrate==0)
1239 {
1240 string* nulldur=Convert::int2str(0,2,"0");
1241 *nulldur+=":00:00.00";
1242 return nulldur;
1243 }
1244 //cout <<"disphours "<<offset << endl;
1245 //cout << "samrateh=" <<samplerate() << endl;
1246 if (samrate>=88200) { samrate=samrate>>1; }
1247 __uint32 subsec=display_subseconds(offset,samrate);
1248 if (samrate>0) {
1249 subsec=this->framespersec*subsec/samrate;
1250 }
1251 string* newstr= Convert::int2str(display_hours(offset),2,"0");
1252 *newstr+=":";
1253 string* mins=Convert::int2str(display_minutes(offset),2,"0");
1254 *newstr+=*mins;
1255 delete mins;
1256 *newstr+=":";
1257 string* secs=Convert::int2str(display_seconds(offset),2,"0");
1258 *newstr+=*secs;
1259 delete secs;
1260 *newstr+=".";
1261 string* subsecs=Convert::int2str(subsec,2,"0");
1262 *newstr+=*subsecs;
1263 delete subsecs;
1264 return newstr;
1265}
1266
1267string* hd24song::display_duration(__uint32 offset)
1268{
1269 return display_duration(offset,samplerate());
1270}
1271
1272string* hd24song::display_duration()
1273{
1274 __uint32 songlen=songlength_in_samples();
1275 return display_duration(songlen);
1276}
1277
1278__uint32 hd24song::display_hours()
1279{
1280 __uint32 songlen=songlength_in_samples();
1281 return display_hours(songlen);
1282}
1283
1284__uint32 hd24song::display_hours(__uint32 offset,__uint32 samrate)
1285{
1286 if (samrate==0)
1287 {
1288 return 0;
1289 }
1290 //cout <<"disphours "<<offset << endl;
1291 //cout << "samrateh=" <<samplerate() << endl;
1292 if (samrate>=88200) { samrate=samrate>>1; }
1293
1294 __uint32 totsonglen=offset;
1295 __uint32 songsubsecs=totsonglen%samrate;
1296 __uint32 cutsonglen=(totsonglen-songsubsecs);
1297 __uint32 totsongsecs=(cutsonglen/samrate);
1298 __uint32 viewsongsecs=totsongsecs%60;
1299 __uint32 totsongmins=(totsongsecs-viewsongsecs)/60;
1300 __uint32 viewsongmins=(totsongmins%60);
1301 __uint32 totsonghours=(totsongmins-viewsongmins)/60;
1302 return totsonghours;
1303}
1304
1305__uint32 hd24song::display_minutes()
1306{
1307 return display_minutes(songlength_in_samples());
1308}
1309
1310__uint32 hd24song::display_minutes(__uint32 offset,__uint32 samrate)
1311{
1312 if (samrate==0)
1313 {
1314 return 0;
1315 }
1316 //cout <<"dispmin "<<offset << endl;
1317 //cout << "samratem=" <<samplerate() << endl;
1318 if (samrate>=88200) { samrate=samrate>>1; }
1319 __uint32 totsonglen=offset;
1320 __uint32 songsubsecs=totsonglen%samrate;
1321 __uint32 cutsonglen=(totsonglen-songsubsecs);
1322 __uint32 totsongsecs=(cutsonglen/samrate);
1323 __uint32 viewsongsecs=totsongsecs%60;
1324 __uint32 totsongmins=(totsongsecs-viewsongsecs)/60;
1325 __uint32 viewsongmins=(totsongmins%60);
1326 return viewsongmins;
1327}
1328
1329__uint32 hd24song::display_seconds()
1330{
1331 return display_seconds(songlength_in_samples());
1332}
1333
1334void hd24song::sectorinit(unsigned char* songsector)
1335{
1336 unsigned char emptysong[512] = {
1337 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X10,0X00,0X00,0X00,0X30,0X00,0X00,0X00,
1338 0X00,0X20,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
1339 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X67,0X6E,0X6F,0X53,0X6D,0X61,0X4E,0X20,
1340 0X20,0X65,0X18,0X00,0X18,0X44,0XAC,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
1341 0X00,0X00,0X00,0X00,0X01,0X02,0X00,0X00,0XE4,0X12,0X04,0X30,0XA8,0X10,0X00,0X20,
1342 0X00,0X00,0X00,0X20,0X01,0X00,0X13,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
1343 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
1344 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
1345 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
1346 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
1347 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
1348 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X41,0X54,0X53,0X20,
1349 0X20,0X20,0X54,0X52,0X00,0X00,0X00,0X00,0X4E,0X63,0X6F,0X4C,0X31,0X30,0X6D,0X61,
1350 0X00,0X00,0X00,0X00,0X4E,0X63,0X6F,0X4C,0X32,0X30,0X6D,0X61,0X00,0X00,0X00,0X00,
1351 0X4E,0X63,0X6F,0X4C,0X33,0X30,0X6D,0X61,0X00,0X00,0X00,0X00,0X4E,0X63,0X6F,0X4C,
1352 0X34,0X30,0X6D,0X61,0X00,0X00,0X00,0X00,0X4E,0X63,0X6F,0X4C,0X35,0X30,0X6D,0X61,
1353 0X00,0X00,0X00,0X00,0X4E,0X63,0X6F,0X4C,0X36,0X30,0X6D,0X61,0X00,0X00,0X00,0X00,
1354 0X4E,0X63,0X6F,0X4C,0X37,0X30,0X6D,0X61,0X00,0X00,0X00,0X00,0X4E,0X63,0X6F,0X4C,
1355 0X38,0X30,0X6D,0X61,0X00,0X00,0X00,0X00,0X4E,0X63,0X6F,0X4C,0X39,0X30,0X6D,0X61,
1356 0X00,0X00,0X00,0X00,0X4E,0X63,0X6F,0X4C,0X30,0X31,0X6D,0X61,0X00,0X00,0X00,0X00,
1357 0X4E,0X63,0X6F,0X4C,0X31,0X31,0X6D,0X61,0X00,0X00,0X00,0X00,0X4E,0X63,0X6F,0X4C,
1358 0X32,0X31,0X6D,0X61,0X00,0X00,0X00,0X00,0X4E,0X63,0X6F,0X4C,0X33,0X31,0X6D,0X61,
1359 0X00,0X00,0X00,0X00,0X4E,0X63,0X6F,0X4C,0X34,0X31,0X6D,0X61,0X00,0X00,0X00,0X00,
1360 0X4E,0X63,0X6F,0X4C,0X35,0X31,0X6D,0X61,0X00,0X00,0X00,0X00,0X4E,0X63,0X6F,0X4C,
1361 0X36,0X31,0X6D,0X61,0X00,0X00,0X00,0X00,0X4E,0X63,0X6F,0X4C,0X37,0X31,0X6D,0X61,
1362 0X00,0X00,0X00,0X00,0X4E,0X63,0X6F,0X4C,0X38,0X31,0X6D,0X61,0X00,0X00,0X00,0X00,
1363 0X4E,0X63,0X6F,0X4C,0X39,0X31,0X6D,0X61,0X00,0X00,0X00,0X00,0X4E,0X63,0X6F,0X4C,
1364 0X30,0X32,0X6D,0X61,0X00,0X00,0X00,0X00,0X63,0X6E,0X75,0X50,0X20,0X6E,0X49,0X68,
1365 0X00,0X00,0X00,0X00,0X63,0X6E,0X75,0X50,0X74,0X75,0X4F,0X68,0X00,0X00,0X00,0X00,
1366 0X74,0X69,0X64,0X45,0X20,0X6E,0X49,0X20,0X00,0X00,0X00,0X00,0X74,0X69,0X64,0X45,
1367 0X74,0X75,0X4F,0X20,0X04,0X04,0X00,0X00,0X78,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
1368 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00
1369 };
1370 for (int i=0;i<1024;i++) {
1371 songsector[i]=0; // wipe clean entire buffer
1372 }
1373 for (int i=0;i<512;i++) {
1374 songsector[i]=emptysong[i]; // init with empty song info
1375 }
1376 hd24fs::fstfix(songsector,1024); // from native drive format to normal byte ordering
1377 songname(songsector,"Song Name");
1378}
1379
1380__uint32 hd24song::display_seconds(__uint32 offset,__uint32 samrate)
1381{
1382 if (samrate==0)
1383 {
1384 return 0;
1385 }
1386 if (samrate>=88200) { samrate=samrate>>1; }
1387 __uint32 cutsonglen=offset-display_subseconds(offset,samrate);
1388 __uint32 totsongsecs=(cutsonglen/samrate);
1389 __uint32 viewsongsecs=totsongsecs%60;
1390 return viewsongsecs;
1391}
1392
1393__uint32 hd24song::display_subseconds() {
1394 return display_subseconds(songlength_in_samples());
1395}
1396
1397__uint32 hd24song::display_subseconds(__uint32 offset,__uint32 samrate)
1398{
1399 if (samrate==0)
1400 {
1401 return 0;
1402 }
1403 if (samrate>=88200) { samrate=samrate>>1; }
1404 __uint32 totsonglen=offset;
1405 __uint32 songsubsecs=totsonglen%samrate;
1406 return songsubsecs;
1407}
1408
1409__uint32 hd24song::display_hours(__uint32 offset)
1410{
1411 return display_hours(offset,samplerate());
1412}
1413
1414__uint32 hd24song::display_minutes(__uint32 offset)
1415{
1416 return display_minutes(offset,samplerate());
1417}
1418
1419__uint32 hd24song::display_seconds(__uint32 offset)
1420{
1421 return display_seconds(offset,samplerate());
1422}
1423
1424__uint32 hd24song::display_subseconds(__uint32 offset)
1425{
1426 return display_subseconds(offset,samplerate());
1427}
1428
1429unsigned char* hd24song::getcachedbuffer(__uint32 blocknum)
1430{
1431 // This will return a pointer to an audio buffer containing
1432 // the audio of the given blocknum, if available.
1433 // If not available, it will return a pointer to a silent
1434 // block and queue the blocknum for caching
1435 int i;
1436 bool foundbuf=false;
1437 unsigned char* bufptr=NULL;
1438
1439 /* A straight loop isn't the fastest way to find the
1440 * correct buffer (a binary tree or hash would perform
1441 * better). However the advantage for a total of around
1442 * 40 blocks (25 locate points and some lookahead)
1443 * would be rather marginal. */
1444
1445 bool havenext=false;
1446 bool haveprev=false;
1447
1448 for (i=LOCATEPOS_LAST;i<CACHEBUFFERS;i++)
1449 {
1450 if (blocknum>0) {
1451 if (cachebuf_blocknum[i]==(blocknum-1)) {
1452 haveprev=true;
1453 if (havenext && foundbuf) break;
1454 }
1455 }
1456 if (cachebuf_blocknum[i]==(blocknum+1)) {
1457 havenext=true;
1458 if (haveprev && foundbuf) break;
1459 }
1460 if (cachebuf_blocknum[i]==blocknum)
1461 {
1462 bufptr=cachebuf_ptr[i];
1463 foundbuf=true;
1464 if (havenext && haveprev) break;
1465 }
1466 }
1467 if (!(foundbuf))
1468 {
1469 if (!haveprev)
1470 {
1471 queuecacheblock(blocknum-1);
1472 }
1473 if (!havenext)
1474 {
1475 queuecacheblock(blocknum+1);
1476 }
1477 queuecacheblock(blocknum);
1478 return NULL;
1479 }
1480 if (!haveprev)
1481 {
1482 queuecacheblock(blocknum-1);
1483 }
1484 if (!havenext)
1485 {
1486 queuecacheblock(blocknum+1);
1487 }
1488 // Cache buffer was found.
1489 // If we want we can optimize the cache here.
1490 // Otherwise, just return the buffer pointer.
1491 lastavailablecacheblock=blocknum;
1492 return bufptr;
1493}
1494
1495void hd24song::memoizeblocksectors(__uint32 number_of_blocks)
1496{
1497 __uint32 totblocksfound=0;
1498 __uint32 myallocentrynum=0;
1499
1500 __uint32 entrystartsector=0;
1501 __uint32 entrynumblocks=0;
1502
1503 __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors();
1504
1505 while (
1506 (totblocksfound < number_of_blocks)
1507 && (totblocksfound <= MAX_BLOCKS_IN_SONG)
1508 && (myallocentrynum<ALLOC_ENTRIES_PER_SONG)
1509 )
1510 {
1511
1512 entrystartsector=Convert::getint32(buffer,
1513 SONGINFO_ALLOCATIONLIST+ALLOCINFO_SECTORNUM
1514 +(ALLOCINFO_ENTRYLEN*myallocentrynum));
1515 entrynumblocks=Convert::getint32(buffer,
1516 SONGINFO_ALLOCATIONLIST+ALLOCINFO_AUDIOBLOCKSINBLOCK
1517 +(ALLOCINFO_ENTRYLEN*myallocentrynum));
1518#if (SONGDEBUG == 1)
1519 cout << "Entry " << myallocentrynum << " start sector=" << entrystartsector ;
1520 cout << "# blocks in entry=" << entrynumblocks << endl;
1521#endif
1522
1523 for (__uint32 filler=0;filler<entrynumblocks;filler++) {
1524 if (totblocksfound+filler > MAX_BLOCKS_IN_SONG) break;
1525 blocksector[totblocksfound+filler]=entrystartsector+(blocksize_in_sectors*filler);
1526 }
1527 totblocksfound+=entrynumblocks;
1528 myallocentrynum++;
1529 }
1530 lastallocentrynum=myallocentrynum;
1531#if (SONGDEBUG == 1)
1532 cout << "Tot blocks found = " << totblocksfound << "/" << number_of_blocks << endl;
1533#endif
1534 return ;
1535}
1536
1537/* Quick calculation:
1538 Saving 1 block sectornum=32 bit (4 bytes).
1539 MAX_BLOCKS_IN_SONG=524288, so the maximum number of bytes needed to
1540 memoize all song allocation info=524288*4=2097152 bytes (~2 megabyte)
1541 for the worst case song, which is certainly doable.
1542
1543 As memoization can be done efficiently when carried out sequentially, it can be done in O(n)
1544
1545 When this function is called once with last blocknum, all blocks can be memoized during a
1546 single pass of the WHILE loop
1547 Lookup will be O(1).
1548 A typical song transfer will take X tracks
1549 (each track requires a sector calc for all blocks).
1550*/
1551
1552void hd24song::getmultitracksample(long* mtsample,int readmode)
1553{
1554 /* This procedure is intended for copying audio from disk (and for realtime
1555 playback). This procedure assumes sequential reading.
1556
1557 If reverse playback is desired, golocatepos() must be called for
1558 every sample. This is a bit more expensive in resources.
1559 However, as golocatepos()
1560 doesn't cause any I/O, it should still be light enough for regular use.
1561
1562 As such, allocation info for every sample will only be recalculated
1563 when needed. This results in the best possible performance.
1564
1565 There are two playback modes: copy and realtime. Copy mode guarantees
1566 that a bit-accurate copy of the disk contents is returned, but may
1567 require (slow) disk reads in the process, which makes it unsuitable
1568 for anything requiring realtime response.
1569
1570 Realtime mode guarantees to return a result in a short amount of time,
1571 by using a cache. This makes it suitable for realtime playback.
1572 When a block is not available in cache, silence is returned. This makes
1573 realtime mode unsuitable for accurate transfers, but suitable for direct
1574 from-disk mixing. Blocks that are not available in cache are queued for
1575 caching. Periodic background checks should be performed on this queue to
1576 help guarantee availability of the blocks to cache.
1577
1578 In high samplerate mode, samples are interlaced between odd tracks and
1579 even tracks. This allows the song cursor to keep running at normal speed-
1580 the difference is that at double the speed the songcursor is only
1581 updated every other multitrack sample request. This means that at the
1582 cost of only being able to do locate operations to even samples,
1583 we can maintain use the same code for block calculation.
1584 */
1585#if (SONGDEBUG==1)
1586 cout << "Getmultitracksample mtsample=" << mtsample <<" mode=" <<readmode<< "this=" <<this << endl;
1587 cout << "parentfs=" << parentfs << endl;
1588#endif
1589 unsigned char* buffertouse=NULL;
1590 currentreadmode=readmode;
1591 __uint32 samrate=samplerate();
1592 __uint32 samplenumber=songcursor;
1593 __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors();
1594 __uint32 blocksize_in_bytes=blocksize_in_sectors*SECTORSIZE;
1595 __uint32 bits=(this->bitdepth());
1596 __uint32 bytes_per_sample=bits/8;
1597 __uint32 tracks_per_song=physical_channels();
1598 __uint32 tracksamples_per_block=(blocksize_in_bytes / bytes_per_sample) / tracks_per_song;
1599 __uint32 blocknum=(samplenumber/(tracksamples_per_block));
1600#if (SONGDEBUG==1)
1601 cout << "tracksamples per block="<<tracksamples_per_block << endl;
1602 cout << "readmtsample MARK" << endl;
1603#endif
1604 bool mustgetaudiodata=false;
1605 if (parentfs->maintenancemode==1) {
1606 readmode=hd24song::READMODE_COPY;
1607 }
1608 switch (readmode)
1609 {
1610 case hd24song::READMODE_COPY:
1611 if ((lastreadblock!=blocknum)||(mustreadblock==1))
1612 {
1613 mustgetaudiodata=true;
1614 }
1615 break;
1616 case hd24song::READMODE_REALTIME:
1617 mustgetaudiodata=false;
1618 if ((lastavailablecacheblock!=blocknum)||(mustreadblock==1)) {
1619 mustgetaudiodata=true;
1620 }
1621 break;
1622 default:
1623 mustgetaudiodata=false;
1624 break;
1625 }
1626
1627#if (SONGDEBUG==1)
1628 cout << "readmtsample MARK2" << endl;
1629#endif
1630 if (mustgetaudiodata)
1631 {
1632 // We advanced a block. This means we need to read more audio data.
1633 // (or in case of realtime reading, at least find out what next block to get)
1634 if (blocknum==(allocstartblock+allocaudioblocks))
1635 {
1636 // In fact, we've read all data in the current allocation entry.
1637 allocentrynum++; // reset cursor to start of song
1638 allocstartblock=blocknum; // blocknum of first block in current allocation entry
1639 allocstartsector=Convert::getint32(buffer,
1640 SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*allocentrynum)+ALLOCINFO_SECTORNUM);
1641 allocaudioblocks=Convert::getint32(buffer,
1642 SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*allocentrynum)+ALLOCINFO_AUDIOBLOCKSINBLOCK);
1643 }
1644
1645 switch (readmode)
1646 {
1647 case (hd24song::READMODE_COPY):
1648 if (parentfs->maintenancemode==1)
1649 {
1650 // in maintenance mode, we will display the sector currently
1651 // being played back (that is what maintenance mode is all
1652 // about
1653
1654 string* bla=Convert::int32tohex(allocstartsector+((blocknum-allocstartblock)*blocksize_in_sectors));
1655 cout << *bla << "-1" << endl; // maintenance mode
1656 delete bla;
1657 }
1658
1659 parentfs->readsectors(parentfs->devhd24,
1660 allocstartsector+((blocknum-allocstartblock)*blocksize_in_sectors),
1661 audiobuffer,blocksize_in_sectors); // raw audio read, no fstfix needed
1662 mustreadblock=0;
1663 break;
1664 case (hd24song::READMODE_REALTIME):
1665 buffertouse=getcachedbuffer(blocknum);
1666
1667 default: break;
1668 }
1669 // cout << "read done. " << endl;
1670 }
1671#if (SONGDEBUG==1)
1672 cout << "readmtsample MARK 3" << endl;
1673 cout << "audiobuffer=" << audiobuffer << endl;
1674 cout << "readmtsample MARK 3b" << endl;
1675#endif
1676
1677 int sample_within_block=samplenumber%(tracksamples_per_block);
1678 if (readmode==hd24song::READMODE_COPY)
1679 {
1680 buffertouse=audiobuffer;
1681 }
1682 __uint32 trackspersam;
1683 if (samrate>=88200) {
1684 trackspersam=2;
1685 } else {
1686 trackspersam=1;
1687 }
1688#if (SONGDEBUG==1)
1689 cout << "readmtsample MARK 3c" << endl;
1690#endif
1691 __uint32 tottracks=logical_channels();
1692 for (__uint32 tracknum=0;tracknum<tottracks;tracknum++)
1693 {
1694 __uint32 samval;
1695 if (buffertouse==NULL)
1696 {
1697 samval=0;
1698 }
1699 else
1700 {
1701 int offset_first_blocksample=(((tracknum*trackspersam)+evenodd)*tracksamples_per_block*bytes_per_sample);
1702 int sample_offset=offset_first_blocksample+(sample_within_block*bytes_per_sample);
1703 samval=Convert::getint24(buffertouse,sample_offset);
1704 // TODO: Handle word lengths other than 24 bits
1705 }
1706#if (SONGDEBUG==1)
1707 cout << "readmtsample MARK 3e" << endl;
1708 cout << "tracknum=" << tracknum << endl;
1709#endif
1710 mtsample[tracknum]=samval;
1711#if ( SONGDEBUG == 1 )
1712 cout << "posttracknum=" << tracknum << endl;
1713 if ((tracknum==0) && (songcursor<20)) {
1714 string* bla=Convert::int32tohex(samval);
1715 cout << *bla << "-2"<< endl;
1716 delete bla;
1717 }
1718 cout << "readmtsample MARK 3f" << endl;
1719#endif
1720 }
1721#if (SONGDEBUG==1)
1722 cout << "readmtsample MARK 4" << endl;
1723#endif
1724 lastreadblock=blocknum;
1725 if (samrate>=88200)
1726 {
1727 // only for high sample rate mode:
1728 evenodd=1-evenodd;
1729 if (evenodd==0) {
1730 songcursor++;
1731 }
1732 } else {
1733 songcursor++;
1734 }
1735
1736 return;
1737}
1738
1739int hd24song::getmtrackaudiodata(__uint32 firstsamnum,__uint32 samples,unsigned char* buffer,int readmode)
1740{
1741 /* WARNING: For best performance the number of samples must not cross
1742 audio block boundaries. This function has been tested in such a fashion only.
1743
1744 This procedure is intended for reading audio data from disk,
1745 in a completely random access fashion.
1746 It assumes single track audio and will always read only whole blocks,
1747 directly to the given buffer. Return value is a pointer to the
1748 first sample that was supposed to be read.
1749
1750 The buffer should be sufficiently large to hold the total audio size.
1751 (number of samples*3 bytes for normal sample rates or
1752 number of samples*3*2 bytes for high sample rates (88k2, 96k).
1753
1754 In copy mode, only required blocks will be read from disk
1755 (no caching will take place- we'll leave this to the OS)
1756
1757 Realtime mode guarantees to return a result in a short amount of time,
1758 by using a cache. This makes it suitable for realtime playback.
1759 REALTIME MODE IS NOT IMPLEMENTED YET.
1760 When a block is not available in cache, silence is returned. This makes
1761 realtime mode unsuitable for accurate transfers, but suitable for direct
1762 from-disk mixing. Blocks that are not available in cache are queued for
1763 caching. Periodic background checks should be performed on this queue to
1764 help guarantee availability of the blocks to cache.
1765 */
1766
1767 currentreadmode=readmode;
1768 __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors();
1769 __uint32 blocksize_in_bytes=blocksize_in_sectors*SECTORSIZE;
1770
1771 __uint32 bits=(this->bitdepth());
1772 __uint32 bytes_per_sample=bits/8;
1773 __uint32 tracks_per_song=logical_channels();
1774 __uint32 tracksamples_per_block=(blocksize_in_bytes / bytes_per_sample) / tracks_per_song;
1775
1776 __uint32 startblocknum=((firstsamnum-(firstsamnum%tracksamples_per_block))/(tracksamples_per_block));
1777 __uint32 lastsamnum=firstsamnum+samples-1;
1778 __uint32 endblocknum=((lastsamnum-(lastsamnum%tracksamples_per_block))/(tracksamples_per_block));
1779
1780 // check read enable flags to allow reducing number of sectors to be transferred.
1781 __uint32 first_readenabled=0;
1782 __uint32 last_readenabled=23;
1783 for (__uint32 i=0;i<logical_channels();i++)
1784 {
1785 if (track_readenabled[i])
1786 {
1787 first_readenabled=i;
1788 break;
1789 }
1790 }
1791 for (__uint32 i=logical_channels();i>0;i--)
1792 {
1793 if (track_readenabled[i-1])
1794 {
1795 last_readenabled=i-1;
1796 break;
1797 }
1798 }
1799#if (SONGDEBUG==1)
1800 cout << "first,last track="<<first_readenabled<<","<<last_readenabled<<endl;
1801#endif
1802 __uint32 chanmult=physical_channels()/logical_channels();
1803
1804 __uint32 physicaltracksreadenabled=chanmult*(last_readenabled-first_readenabled)+1;
1805 __uint32 firsttrackoffset=chanmult*first_readenabled*tracksamples_per_block*bytes_per_sample;
1806 __uint32 sectoroffset=firsttrackoffset/SECTORSIZE;
1807 __uint32 readlength=(physicaltracksreadenabled*bytes_per_sample*tracksamples_per_block)/SECTORSIZE;
1808#if (SONGDEBUG==1)
1809 cout << "sectoroffset,readlength="<<sectoroffset<<","<<readlength<< endl;
1810#endif
1811 for (__uint32 blocknum=startblocknum;blocknum<=endblocknum;blocknum++)
1812 {
1813#if (SONGDEBUG == 1)
1814 string* bla=Convert::int32tohex(blocksector[blocknum]);
1815 cout << *bla << "-3" << endl; // maintenance mode
1816 delete bla;
1817#endif
1818 // now read trackblocksize_in_sectors sectors from sector blocksec into buffer
1819 parentfs->readsectors(parentfs->devhd24,
1820 blocksector[blocknum]+sectoroffset,
1821 &buffer[firsttrackoffset],
1822 readlength); // raw audio read, no fstfix needed
1823 }
1824 return firstsamnum%tracksamples_per_block;
1825}
1826
1827void hd24song::interlaceblock(unsigned char* sourcebuffer,unsigned char* targetbuffer)
1828{
1829 /* This is needed for high sample rates as high sample rate recordings
1830 take up two physical channels for each logical audio channel */
1831 __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors();
1832 __uint32 blocksize_in_bytes=blocksize_in_sectors*SECTORSIZE;
1833 __uint32 blocksize_doubleblock=blocksize_in_bytes/logical_channels();
1834 __uint32 blocksize_halfblock=blocksize_in_bytes/physical_channels();
1835
1836 __uint32 bits=(this->bitdepth());
1837 __uint32 bytes_per_sample=bits/8;
1838 __uint32 tracksamples_per_halfblock=(blocksize_halfblock/bytes_per_sample);
1839 __uint32 choffset=0;
1840 for (__uint32 ch=0;ch<logical_channels();ch++)
1841 {
1842 for (__uint32 i=0;i<tracksamples_per_halfblock;i++)
1843 {
1844 __uint32 samoff_target=i*bytes_per_sample+choffset;
1845 __uint32 samoff_source=2*i*bytes_per_sample+choffset;
1846 for (__uint32 j=0;j<bytes_per_sample;j++) {
1847 targetbuffer[samoff_target+j]
1848 =sourcebuffer[samoff_source+j];
1849 targetbuffer[samoff_target+j+bytes_per_sample]
1850 =sourcebuffer[samoff_source+j+blocksize_halfblock];
1851 }
1852 }
1853 choffset+=blocksize_doubleblock;
1854 }
1855}
1856
1857void hd24song::deinterlaceblock(unsigned char* sourcebuffer,unsigned char* targetbuffer)
1858{
1859 /* This is needed for high sample rates as high sample rate recordings
1860 take up two physical channels for each logical audio channel */
1861 __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors();
1862 __uint32 blocksize_in_bytes=blocksize_in_sectors*SECTORSIZE;
1863 __uint32 blocksize_doubleblock=blocksize_in_bytes/logical_channels();
1864 __uint32 blocksize_halfblock=blocksize_in_bytes/physical_channels();
1865
1866 __uint32 bits=(this->bitdepth());
1867 __uint32 bytes_per_sample=bits/8;
1868 __uint32 tracksamples_per_halfblock=(blocksize_halfblock/bytes_per_sample);
1869 __uint32 choffset=0;
1870 for (__uint32 ch=0;ch<logical_channels();ch++)
1871 {
1872 for (__uint32 i=0;i<tracksamples_per_halfblock;i++)
1873 {
1874 __uint32 samoff_source=i*bytes_per_sample+choffset;
1875 __uint32 samoff_target=2*i*bytes_per_sample+choffset;
1876 for (__uint32 j=0;j<bytes_per_sample;j++) {
1877 targetbuffer[samoff_target+j]
1878 =sourcebuffer[samoff_source+j];
1879 targetbuffer[samoff_target+j+bytes_per_sample]
1880 =sourcebuffer[samoff_source+j+blocksize_halfblock];
1881 }
1882 }
1883 choffset+=blocksize_doubleblock;
1884 }
1885}
1886
1887int hd24song::putmtrackaudiodata(__uint32 firstsamnum,__uint32 samples,unsigned char* writebuffer,int writemode)
1888{
1889// cout << " first 30 bytes of write buffer: " ;
1890// for (int i=0;i<30;i++) { cout << " " << (short)((unsigned char)writebuffer[i]); }
1891// cout << endl;
1892 /*
1893 This procedure is intended for writing audio data to disk.
1894 Contrary to reading audio (where realtime mode is OK to drop
1895 some audio during heavy seeking), write mode should always
1896 write reliably- caching is not allowed.
1897 As such only sequential operation is allowed.
1898
1899 NOTE: THIS FUNCTION WAS NOT TESTED FOR REALTIME OPERATION.
1900
1901 Before writing, you need to arm the tracks that you want to
1902 write to (using the unarmtrack and armtrack functions),
1903 then enable record mode (function startrecord).
1904
1905 Startrecord will disable seeking while recording and perform
1906 any tasks needed to initialize drive usage administration.
1907
1908 When no tracks are armed or record mode is not enabled,
1909 nothing will be written to disk. (A rehearse mode may be
1910 added at some point to prevent writing to disk even in
1911 record mode).
1912
1913 After writing, you need to call stoprecord. This will
1914 re-enable seek operations and write out any drive usage
1915 information, increase file length etc, should any space have
1916 been allocated during the write operation.
1917
1918 Before calling this function, the write buffer needs to contain
1919 the audio to record in the tracks that are armed.
1920
1921 After calling this function, the write buffer contents will be
1922 altered: the non-armed tracks will contain the audio that
1923 was already on disk.
1924
1925 The write buffer should be sufficiently large to hold the total
1926 audio size for all tracks.
1927
1928 */
1929
1930 currentreadmode=writemode;
1931
1932 __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors();
1933 __uint32 blocksize_in_bytes=blocksize_in_sectors*SECTORSIZE;
1934
1935 __uint32 bits=(this->bitdepth());
1936 __uint32 bytes_per_sample=bits/8;
1937 __uint32 tracks_per_song=logical_channels();
1938 __uint32 tracksamples_per_block=(blocksize_in_bytes / bytes_per_sample) / tracks_per_song;
1939 __uint32 trackbytes_per_block=(blocksize_in_bytes / tracks_per_song);
1940
1941 __uint32 startblocknum=((firstsamnum-(firstsamnum%tracksamples_per_block))/(tracksamples_per_block));
1942 __uint32 lastsamnum=firstsamnum+samples-1;
1943 __uint32 endblocknum=((lastsamnum-(lastsamnum%tracksamples_per_block))/(tracksamples_per_block));
1944 for (__uint32 blocknum=startblocknum;blocknum<=endblocknum;blocknum++)
1945 {
1946 // now read trackblocksize_in_sectors sectors from sector blocksec into buffer
1947 //cout << "Reading sec " << blocksector[blocknum] << endl;
1948
1949 if (blocksector[blocknum]<0x1397f6) {
1950 // safety feature- drop out of write mode when superblock is targeted.
1951 cout << "Detected audio write request to administration area. " << endl;
1952 cout << "Possible bug, dropping out of write mode. " << endl;
1953 setrehearsemode(true);
1954 }
1955
1956 parentfs->readsectors(parentfs->devhd24,
1957 blocksector[blocknum],
1958 scratchbook,
1959 blocksize_in_sectors); // raw audio read, no fstfix needed
1960
1961 // now overwrite only the armed tracks with contents of buffer
1962 __uint32 numtracks=0;
1963 if (!(this->isrehearsemode())) {
1964
1965 for (__uint32 tracknum=1; tracknum<=tracks_per_song; tracknum++) {
1966 if (!(this->trackarmed(tracknum))) {
1967 continue;
1968 }
1969 numtracks++;
1970 //cout << "track "<<tracknum<<" is armed." <<endl;
1971 __uint32 firsttrackbyte=(tracknum-1)*trackbytes_per_block;
1972 for (__uint32 q=0; q<trackbytes_per_block;q++) {
1973 if (q<10) {
1974//nn cout << "scratchbook[" << firsttrackbyte+q <<"]=writebuffer[dito]=" << (int)((unsigned char)writebuffer[firsttrackbyte+q]) << endl;
1975 }
1976 scratchbook[firsttrackbyte+q]=(unsigned char)writebuffer[firsttrackbyte+q];
1977 }
1978 }
1979 if (numtracks>0) {
1980 //cout << "writing back " << numtracks
1981 // << " tracks to sector "<< blocksector[blocknum] << endl;
1982 parentfs->writesectors(parentfs->devhd24,
1983 blocksector[blocknum],
1984 scratchbook,
1985 blocksize_in_sectors);
1986 }
1987 }
1988 }
1989 return firstsamnum%tracksamples_per_block;
1990}
1991
1992void hd24song::startrecord(int recordmode)
1993{
1994 // TODO: recordmode to distinguish between realtime and copy mode
1995 recordmode=recordmode;
1996 this->busyrecording=true;
1997}
1998
1999void hd24song::stoprecord()
2000{
2001 this->busyrecording=false;
2002}
2003
2004bool hd24song::recording()
2005{
2006 return (this->busyrecording);
2007}
2008
2009
2010void hd24song::readenabletrack(__uint32 tracknum,bool enable)
2011{
2012 if (tracknum<1) return;
2013 if (tracknum>24) return;
2014 if (tracknum>logical_channels()) return;
2015 track_readenabled[tracknum-1]=enable;
2016}
2017
2018void hd24song::readenabletrack(__uint32 tracknum)
2019{
2020 readenabletrack(tracknum,true);
2021}
2022
2023bool hd24song::isrehearsemode()
2024{
2025 return this->rehearsemode;
2026}
2027
2028void hd24song::setrehearsemode(bool p_rehearsemode)
2029{
2030 this->rehearsemode=p_rehearsemode;
2031 return;
2032}
2033
2034void hd24song::trackarmed(__uint32 tracknum,bool arm)
2035{
2036 if (tracknum<1) return;
2037 if (tracknum>24) return;
2038 if (tracknum>logical_channels()) return;
2039 track_armed[tracknum-1]=arm;
2040 return;
2041}
2042
2043bool hd24song::trackarmed(__uint32 tracknum)
2044{
2045 if (tracknum<1) return false;
2046 if (tracknum>24) return false;
2047 return track_armed[tracknum-1];
2048}
2049
2050bool hd24song::istrackmonitoringinput(__uint32 tracknum)
2051{
2052 // TODO: PROPERLY SET TRANSPORT STATUS! (for now done by GUI)
2053
2054 if (tracknum<1) return false;
2055 if (tracknum>(this->logical_channels())) return false;
2056
2057 // indicates if a given track is (supposed to be)
2058 // monitoring input (if false, playback is being monitored).
2059 // This is based on the following decision matrix:
2060 //
2061 // All input | auto input | Track rec-enabled | Transport status | result
2062 // ----------+------------+-------------------+------------------+--------
2063 // on | | don't care | don't care | true
2064 // off | off | false | stop | false
2065 // off | off | false | play | false
2066 // off | off | false | rec | false
2067 // off | off | true | stop | true
2068 // off | off | true | play | true
2069 // off | off | true | rec | true
2070 // off | on | false | stop | false
2071 // off | on | false | play | false
2072 // off | on | false | rec | false
2073 // off | on | true | stop | true
2074 // off | on | true | play | false
2075 // off | on | true | rec | true
2076 // ----------+------------+-------------------+------------------+--------
2077 if (parentfs->isallinput()) {
2078 return true;
2079 }
2080 if (!(this->trackarmed(tracknum))) return false;
2081
2082 if (this->parentfs->transportstatus==hd24fs::TRANSPORTSTATUS_PLAY) {
2083 if (this->parentfs->isautoinput()) {
2084 return false;
2085 }
2086 }
2087 return true;
2088}
2089
2090__uint32 hd24song::getnextfreesector(__uint32 lastallocsector)
2091{
2092 /* Based on the alloc info of the current song, this function
2093 will return the sector number of the next unallocated cluster.
2094 When no unallocated sectors are found, the function will return 0.
2095
2096 Sector 0 is never in the data area, so this will allow us to
2097 distinguish between this situation and real cluster numbers.
2098 Sector 0 is the superblock- as allocation implies writing to the
2099 drive, the code calling this function MUST verify the result.
2100
2101 When the allocation info cannot be decided upon based on just
2102 the unallocated song sectors within the last allocated cluster
2103 for the song, this function will ask the file system for the
2104 sector number of the next unused cluster.
2105
2106 */
2107#if (SONGDEBUG==1)
2108 cout << "Song::getnextfreesec(" << lastallocsector << ")" << endl;
2109#endif
2110 // lastallocentrynum=last used allocation entry
2111 __uint32 allocsector=Convert::getint32(buffer,SONGINFO_ALLOCATIONLIST
2112 +(ALLOCINFO_ENTRYLEN*lastallocentrynum)+ALLOCINFO_SECTORNUM);
2113 __uint32 allocblocks=Convert::getint32(buffer,SONGINFO_ALLOCATIONLIST
2114 +(ALLOCINFO_ENTRYLEN*lastallocentrynum)+ALLOCINFO_AUDIOBLOCKSINBLOCK);
2115 __uint32 nextsec=0;
2116
2117 if ((allocsector==0) && (lastallocsector==0))
2118 {
2119 // no sectors allocated yet within song.
2120 nextsec=this->parentfs->getnextfreesector(CLUSTER_UNDEFINED);
2121 } else {
2122 // find out first cluster used by allocation unit
2123 __uint32 alloccluster;
2124 __uint32 blockspercluster;
2125 __uint32 clustersused;
2126 __uint32 lastalloccluster;
2127 if (allocsector==0) {
2128 lastalloccluster=parentfs->sector2cluster(lastallocsector);
2129 } else {
2130 alloccluster=parentfs->sector2cluster(allocsector);
2131 blockspercluster=parentfs->getblockspercluster();
2132 clustersused=allocblocks/blockspercluster;
2133 lastalloccluster=alloccluster+(clustersused-1);
2134 }
2135
2136 // check if allocation entry fills up the current cluster word
2137 // if not, allocate another cluster within current alloc entry
2138 // otherwise, ask the FS for drive space
2139 // (update song alloc info)
2140
2141 nextsec=this->parentfs->getnextfreesector(lastalloccluster);
2142 }
2143
2144 if (nextsec==0)
2145 {
2146 /*
2147 TODO: safety feature: If getnextfreesector returns 0, record
2148 mode will be disabled to prevent accidentally overwriting the
2149 superblock. (Alternatively transport may be stopped but
2150 auto-stop hasn't been fully designed yet). */
2151 // write protect of some sort
2152 setrehearsemode(true);
2153 }
2154 return nextsec;
2155}
2156
2157void hd24song::save()
2158{
2159 __uint32 songsector=parentproject->getsongsectornum(this->mysongid);
2160#if (SONGDEBUG == 1)
2161 cout << "writing buffer to sector " << songsector << ", " <<TOTAL_SECTORS_PER_SONG<<" sectors" << endl;
2162#endif
2163
2164 parentfs->fstfix(buffer,TOTAL_SECTORS_PER_SONG*512); // sector is now once again in native format
2165
2166 parentfs->setsectorchecksum(buffer,0,songsector,2); // checksum for 2 sectors of song data
2167 parentfs->setsectorchecksum(buffer,2*512,songsector+2,5); // checksum for 5 sectors of allocation data
2168
2169 parentfs->writesectors(parentfs->devhd24,
2170 songsector,
2171 buffer,TOTAL_SECTORS_PER_SONG);
2172
2173 parentfs->fstfix(buffer,TOTAL_SECTORS_PER_SONG*512); // sector is now in 'fixed' format again
2174 if (this->lengthened)
2175 {
2176#if (SONGDEBUG == 1)
2177 cout << "song was lengthened, update of drive usage needed." << endl;
2178#endif
2179 parentfs->savedriveusage();
2180 this->lengthened=false;
2181 } else
2182 {
2183#if (SONGDEBUG == 1)
2184 cout << "song was not lengthened, no update of drive usage needed." << endl;
2185#endif
2186 }
2187 parentfs->commit();
2188}
diff --git a/src/lib/hd24transferengine.cpp b/src/lib/hd24transferengine.cpp
new file mode 100644
index 0000000..32db2d8
--- /dev/null
+++ b/src/lib/hd24transferengine.cpp
@@ -0,0 +1,2143 @@
1#include "hd24transferengine.h"
2#include <config.h>
3#include <hd24fs.h>
4#include <hd24sndfile.h>
5
6#define HD24TRANSFERDEBUG 0
7#define MAXCHANNELS 24
8#define TRACKACTION_UNDEF -1
9
10hd24transferjob::hd24transferjob()
11{
12#if (HD24TRANSFERDEBUG==1)
13 cout << "hd24transferjob::hd24transferjob();" << endl;
14#endif
15 init_vars();
16}
17
18hd24transferjob::~hd24transferjob()
19{
20#if (HD24TRANSFERDEBUG==1)
21 cout << "hd24transferjob::~hd24transferjob();" << endl;
22#endif
23
24 if (trackselected!=NULL)
25 {
26 delete trackselected;
27 trackselected=NULL;
28 }
29 usecustomrate=0; // by default, match export samrate with song rate
30 if (m_projectdir!=NULL)
31 {
32 delete m_projectdir;
33 m_projectdir=NULL;
34 }
35}
36
37void hd24transferjob::init_vars()
38{
39#if (HD24TRANSFERDEBUG==1)
40 cout << "hd24transferjob::init_vars()" << endl;
41#endif
42 this->wantsplit=1;
43 trackselected=new int[MAXCHANNELS];
44 for (int i=0;i<MAXCHANNELS;i++)
45 {
46 trackselected[i]=0;
47 }
48 m_projectdir=NULL;
49 llsizelimit=1024*1024*1024;
50 mixleft=0;
51 mixright=0;
52 m_selectedformat=0;
53 usecustomrate=0;
54 stamprate=48000;
55 wantsplit=1;
56
57 jobsourcesong=NULL;
58 jobtargetsong=NULL;
59 jobsourcefs=NULL;
60 jobtargetfs=NULL;
61 have_smpte=false;
62
63 m_startoffset=0;
64 m_endoffset=0;
65 for (int i=0;i<24;i++)
66 {
67 this->filepath[i]=NULL;
68 this->filehandle[i]=NULL;
69 this->m_trackaction[i]=TRACKACTION_UNDEF; // undefined trackaction
70 }
71 return;
72}
73
74void hd24transferjob::trackaction(int base1tracknum,int action)
75{
76#if (HD24TRANSFERDEBUG==1)
77 cout << "hd24transferjob::trackaction(base1track="
78 << base1tracknum << ", action=" << action << ")" << endl;
79#endif
80
81 m_trackaction[base1tracknum-1]=action;
82}
83
84int hd24transferjob::trackaction(int base1tracknum)
85{
86#if (HD24TRANSFERDEBUG==1)
87 cout << "returning hd24transferjob::trackaction(base1track="
88 << base1tracknum << ")=" << m_trackaction[base1tracknum-1]
89 << endl;
90#endif
91 return m_trackaction[base1tracknum-1];
92}
93
94void hd24transferengine::trackaction(int base1tracknum,int action)
95{
96 job->trackaction(base1tracknum,action);
97}
98
99int hd24transferengine::trackaction(int base1tracknum)
100{
101 return job->trackaction(base1tracknum);
102}
103
104char* hd24transferjob::sourcefilename(int base1tracknum)
105{
106 if (base1tracknum<1) return NULL;
107 if (base1tracknum>24) return NULL;
108 return filepath[base1tracknum-1];
109}
110
111void hd24transferjob::sourcefilename(int base1tracknum,const char* filename)
112{
113 /* set nth filename to the given char string */
114 if (base1tracknum<1) return;
115 if (base1tracknum>24) return;
116
117 if (filepath[base1tracknum-1]!=NULL)
118 {
119 free(filepath[base1tracknum-1]);
120 }
121 __uint32 n=strlen(filename);
122 char* tmpbuf=(char*)malloc(n);
123 filepath[base1tracknum-1]=tmpbuf;
124 strncpy(tmpbuf,filename,n+1);
125 return;
126}
127
128void hd24transferengine::sourcefilename(int base1tracknum,const char* filename)
129{
130 job->sourcefilename(base1tracknum,filename);
131}
132
133char* hd24transferengine::sourcefilename(int base1tracknum)
134{
135 return job->sourcefilename(base1tracknum);
136}
137
138void hd24transferjob::startoffset(__uint32 newoff)
139{
140 m_startoffset=newoff;
141}
142
143void hd24transferjob::endoffset(__uint32 newoff)
144{
145 m_endoffset=newoff;
146}
147
148__uint32 hd24transferjob::startoffset()
149{
150 return m_startoffset;
151}
152
153__uint32 hd24transferjob::endoffset()
154{
155 return m_endoffset;
156}
157
158hd24fs* hd24transferjob::sourcefs()
159{
160 return this->jobsourcefs;
161}
162
163hd24song* hd24transferjob::sourcesong()
164{
165 return this->jobsourcesong;
166}
167
168void hd24transferjob::sourcefs(hd24fs* fs)
169{
170 this->jobsourcefs=fs;
171}
172
173void hd24transferjob::sourcesong(hd24song* song)
174{
175 this->jobsourcesong=song;
176 this->jobsourcefs=jobsourcesong->parentfs;
177}
178
179hd24fs* hd24transferjob::targetfs()
180{
181 return this->jobtargetfs;
182}
183
184hd24song* hd24transferjob::targetsong()
185{
186 return this->jobtargetsong;
187}
188
189void hd24transferjob::targetfs(hd24fs* fs)
190{
191 this->jobtargetfs=fs;
192}
193
194void hd24transferjob::targetsong(hd24song* song)
195{
196 this->jobtargetsong=song;
197 this->jobtargetfs=jobtargetsong->parentfs;
198}
199
200void hd24transferjob::projectdir(const char* projdir)
201{
202#if (HD24TRANSFERDEBUG==1)
203 cout << "hd24transferjob::projectdir("<<projdir<< ")"<<endl;
204#endif
205 if (m_projectdir!=NULL)
206 {
207 delete m_projectdir;
208 m_projectdir=NULL;
209 }
210 m_projectdir=new string(projdir);
211 return;
212}
213
214const char* hd24transferjob::projectdir()
215{
216#if (HD24TRANSFERDEBUG==1)
217 cout << "returning hd24transferjob::projectdir()=";
218 if (m_projectdir==NULL)
219 {
220 cout <<" NULL " << endl;
221 } else {
222 cout <<*m_projectdir<<endl;
223 }
224#endif
225 return m_projectdir->c_str();
226}
227
228void hd24transferengine::lasterror(const char* errormessage)
229{
230 if (m_lasterror!=NULL)
231 {
232 delete m_lasterror;
233 }
234 m_lasterror=new string(errormessage);
235 return;
236}
237
238string* hd24transferengine::lasterror()
239{
240 return m_lasterror;
241}
242
243
244int hd24transferengine::format_outputchannels(int format)
245{
246 return m_format_outputchannels[format];
247}
248
249const char* hd24transferengine::projectdir()
250{
251 cout << "returning hd24transferengine::projectdir()"<<endl;
252 return job->projectdir();
253}
254
255void hd24transferengine::projectdir(const char* projdir)
256{
257#if (HD24TRANSFERDEBUG==1)
258 cout << "hd24transferengine::projectdir("<<projdir<< ")"<<endl;
259#endif
260 job->projectdir(projdir);
261 return;
262}
263
264hd24transferengine::hd24transferengine()
265{
266#if (HD24TRANSFERDEBUG==1)
267 cout <<"hd24transferengine::hd24transferengine()" << endl;
268#endif
269 init_vars();
270}
271
272hd24transferengine::~hd24transferengine()
273{
274#if (HD24TRANSFERDEBUG==1)
275 cout <<"hd24transferengine::~hd24transferengine()" << endl;
276#endif
277 if (m_lasterror!=NULL)
278 {
279 delete m_lasterror;
280 m_lasterror=NULL;
281 }
282 if (job!=NULL)
283 {
284 delete job;
285 job=NULL;
286 }
287}
288
289void hd24transferengine::init_vars()
290{
291 songnum=0;
292 totsongs=0;
293 ui=NULL;
294 totbytestotransfer=0;
295 totbytestransferred=0;
296 prefix=0;
297 transfer_cancel=0;
298 trackspergroup=0;
299 transfermixer=NULL;
300 job=NULL;
301 m_lasterror=NULL;
302 job=new hd24transferjob();
303 this->uiconfirmfunction=NULL;
304 this->setstatusfunction=NULL;
305 soundfile=NULL;
306#if (HD24TRANSFERDEBUG==1)
307 cout << "hd24transferengine::init_vars() - job="<<job<<endl;
308#endif
309 m_format_outputextension=new vector<string>;
310 m_format_shortdesc=new vector<string>;
311 populate_formatlist();
312}
313
314void hd24transferengine::populate_formatlist()
315{
316#if (HD24TRANSFERDEBUG==1)
317 cout << "hd24transferengine::populate_formatlist()" << endl;
318#endif
319/* Set up transfer format list */
320 formatcount=0;
321 m_format_shortdesc->push_back("WAV (24 bit), mono");
322 m_format_outputformat[formatcount]=SF_FORMAT_WAV|SF_FORMAT_PCM_24|SF_ENDIAN_LITTLE;
323 m_format_outputchannels[formatcount]=1; // mono
324 m_format_bitdepth[formatcount]=24;
325 m_format_sndfile[formatcount]=false; // do not use libsndfile for this file format.
326 m_format_outputextension->push_back(".wav");
327 formatcount++;
328
329 m_format_shortdesc->push_back("WAV (24 bit), stereo");
330 m_format_outputformat[formatcount]=SF_FORMAT_WAV|SF_FORMAT_PCM_24|SF_ENDIAN_LITTLE;
331 m_format_outputchannels[formatcount]=2; // stereo
332 m_format_bitdepth[formatcount]=24;
333 m_format_sndfile[formatcount]=true;
334 m_format_outputextension->push_back(".wav");
335 formatcount++;
336
337 m_format_shortdesc->push_back("WAV (24 bit), multi");
338 m_format_outputformat[formatcount]=SF_FORMAT_WAV|SF_FORMAT_PCM_24|SF_ENDIAN_LITTLE;
339 m_format_outputchannels[formatcount]=0; // multi
340 m_format_bitdepth[formatcount]=24;
341 m_format_sndfile[formatcount]=true;
342 m_format_outputextension->push_back(".wav");
343 formatcount++;
344
345 m_format_shortdesc->push_back("AIF (24 bit), mono");
346 m_format_outputformat[formatcount]=SF_FORMAT_AIFF|SF_FORMAT_PCM_24;
347 m_format_outputchannels[formatcount]=1; // mono
348 m_format_bitdepth[formatcount]=24;
349 m_format_sndfile[formatcount]=false;
350 m_format_outputextension->push_back(".aif");
351 formatcount++;
352
353 m_format_shortdesc->push_back("AIF (24 bit), stereo");
354 m_format_outputformat[formatcount]=SF_FORMAT_AIFF|SF_FORMAT_PCM_24;
355 m_format_outputchannels[formatcount]=2; // stereo
356 m_format_bitdepth[formatcount]=24;
357 m_format_sndfile[formatcount]=true;
358 m_format_outputextension->push_back(".aif");
359 formatcount++;
360
361 m_format_shortdesc->push_back("AIF (24 bit), multi");
362 m_format_outputformat[formatcount]=SF_FORMAT_AIFF|SF_FORMAT_PCM_24;
363 m_format_outputchannels[formatcount]=0; // stereo
364 m_format_bitdepth[formatcount]=24;
365 m_format_sndfile[formatcount]=true;
366 m_format_outputextension->push_back(".aif");
367 formatcount++;
368 selectedformat(0);
369}
370
371const char* hd24transferengine::getformatdesc(int formatnum)
372{
373 return ((*m_format_shortdesc)[formatnum]).c_str();
374}
375
376int hd24transferengine::supportedformatcount()
377{
378 return formatcount;
379}
380
381void hd24transferengine::trackselected(__uint32 base0tracknum,bool selected)
382{
383 if (base0tracknum<0) return;
384 if (base0tracknum>=MAXCHANNELS) return;
385
386 if (selected)
387 {
388 job->trackselected[base0tracknum]=1;
389 } else {
390 job->trackselected[base0tracknum]=0;
391 }
392 return;
393}
394
395bool hd24transferengine::trackselected(__uint32 base0tracknum)
396{
397 if (base0tracknum<0) return false;
398 if (base0tracknum>=MAXCHANNELS) return false;
399
400 return ((job->trackselected[base0tracknum])==1);
401}
402
403
404void hd24transferengine::openbuffers(unsigned char** audiobuf,
405 unsigned int channels,
406 unsigned int bufsize)
407{
408#if (HD24TRANSFERDEBUG==1)
409 cout << "hd24transferengine::openbuffers" << endl;
410#endif
411
412 for (unsigned int handle=0;handle<channels;handle++)
413 {
414 if (!trackselected(handle)) {
415 // channel not selected for export
416 continue;
417 }
418 audiobuf[handle]=
419 (unsigned char *)memutils::mymalloc("openbuffers",
420 bufsize,1);
421 }
422 #if (HD24TRANSFERDEBUG==1)
423 cout << "opened buffers" << endl;
424 #endif
425}
426
427void hd24transferengine::closebuffers(unsigned char** audiobuf,unsigned int channels)
428{
429#if (HD24TRANSFERDEBUG==1)
430 cout << "hd24transferengine::closebuffers" << endl;
431#endif
432 for (__uint32 handle=0;handle<channels;handle++)
433 {
434 if (!trackselected(handle)) {
435 // channel not selected for export
436 continue;
437 }
438 if (audiobuf[handle]!=NULL)
439 {
440 memutils::myfree("closebuffers",audiobuf[handle]);
441 }
442 }
443}
444
445void hd24transferengine::writerawbuf(hd24sndfile* filehandle,unsigned char* buf,long subblockbytes)
446{
447#if (HD24TRANSFERDEBUG==2)
448 cout << "writerawbuf (filehandle="<<filehandle<<", buf="<<buf<<", subblockbytes="<<subblockbytes<<endl;
449#endif
450 filehandle->writerawbuf(buf,subblockbytes);
451#if (HD24TRANSFERDEBUG==2 )
452 cout << "end writerawbuf (filehandle="<<filehandle<<", buf="<<buf<<", subblockbytes="<<subblockbytes<<endl;
453#endif
454}
455
456bool hd24transferengine::openinputfiles(SNDFILE** filehandle,SF_INFO* sfinfoin,unsigned int channels)
457{
458 int cannotopen=0;
459 cout << "TODO: hd24transferengine::openinputfiles" << endl;
460 if (job==NULL)
461 {
462 lasterror("No job found, transfer aborted.");
463 return false;
464 }
465
466 int trackcount=0;
467 for (unsigned int handle=0;handle<channels;handle++)
468 {
469#if (HD24TRANSFERDEBUG!=0)
470 cout << "Openinputfiles - handle=" << handle << endl;
471#endif
472 if (job->sourcefilename(handle+1)==NULL) {
473#if (HD24TRANSFERDEBUG!=0)
474 cout << "Channel not selected for transfer, skipping" << endl;
475#endif
476 continue;
477 }
478 if (strlen(job->sourcefilename(handle+1))==0) {
479#if (HD24TRANSFERDEBUG!=0)
480 cout << "Channel not selected for transfer, skipping" << endl;
481#endif
482 continue;
483 }
484 trackcount++;
485
486#if (HD24TRANSFERDEBUG!=0)
487 cout << "Channel selected for transfer" << endl;
488 cout << "That brings the total track count to "
489 << trackcount << endl;
490 cout << "job=" << job << endl;
491 cout << "soundfile=" << soundfile << endl;
492 cout << "sourcefilename=" << job->sourcefilename(handle+1)
493 << endl;
494#endif
495
496 job->filehandle[handle]=soundfile->sf_open(job->sourcefilename(handle+1),SFM_READ,&sfinfoin[handle]);
497 if (!(job->filehandle[handle]))
498 {
499 cannotopen=1;
500 continue;
501 }
502 }
503
504 return (cannotopen==0); // return true if successful, flase otherwise
505}
506
507bool hd24transferengine::openoutputfiles(hd24sndfile** filehandle,unsigned int channels,unsigned int partnum,int prefix)
508{
509 trackspergroup=0;
510
511 SF_INFO sfinfoout;
512 bool uselibsndfile=m_format_sndfile[selectedformat()];
513 sfinfoout.format=m_format_outputformat[selectedformat()];
514 int chcount=0;
515 if (m_format_outputchannels[selectedformat()]==0) {
516 // count channels
517 for (unsigned int handle=0;handle<channels;handle++)
518 {
519 if (job->trackselected[handle]!=0) {
520 chcount++;
521 }
522 }
523 sfinfoout.channels=chcount;
524 } else {
525 sfinfoout.channels=m_format_outputchannels[selectedformat()];
526 }
527 if (job->usecustomrate==1) {
528 long samrate=job->stamprate;
529 sfinfoout.samplerate=samrate;
530 } else {
531 sfinfoout.samplerate=job->sourcesong()->samplerate();
532 }
533 // chcount and lasthandle are intended to allow
534 // support for writing multichannel files.
535 int lasthandle=0;
536 int lasttrack=-1;
537 int trackcount=0;
538 int cannotopen=0;
539 chcount=0;
540 for (unsigned int handle=0;handle<channels;handle++)
541 {
542
543 islastchanofgroup[handle]=false;
544 isfirstchanofgroup[handle]=false;
545
546 if (job->trackselected[handle]==0) {
547 // channel not selected for export
548 continue;
549 }
550 trackcount++;
551 lasttrack=handle;
552
553 string* fname=generate_filename(handle,partnum,prefix);
554 if (fname==NULL)
555 {
556 /* cannot generate filename. Most likely cause is
557 no song set */
558 return false; // problem opening files.
559 }
560 if (chcount==0) {
561 isfirstchanofgroup[handle]=true;
562 if (uselibsndfile)
563 {
564 filehandle[handle]->sndfilehandle=NULL;
565 if (soundfile->sf_open) {
566 filehandle[handle]->open(fname->c_str(),(int)SFM_WRITE,&sfinfoout,soundfile);
567 }
568 if (!(filehandle[handle]->handle()))
569 {
570 cannotopen=1;
571 }
572 }
573 else
574 {
575 filehandle[handle]->open(fname->c_str(),(int)SFM_WRITE,&sfinfoout);
576 }
577 lasthandle=handle;
578 } else {
579 // copy handle of previously opened file to current track
580 filehandle[handle]->handle(filehandle[lasthandle]->handle(),filehandle[lasthandle]->handletype());
581 if (!(filehandle[handle]->handle()))
582 {
583 cannotopen=1;
584 }
585 }
586 chcount++;
587 if ((sfinfoout.channels)!=0)
588 {
589 // sfinfoout.channels=0 means full multitrack file
590 // so only a single file will be opened.
591 chcount=chcount%(sfinfoout.channels);
592 if (chcount==0) {
593 islastchanofgroup[handle]=true;
594 if (trackspergroup==0) {
595 trackspergroup=trackcount;
596 }
597 }
598 }
599
600 delete fname;
601 }
602 if (lasttrack>=0)
603 {
604 if (trackspergroup==0) {
605 trackspergroup=trackcount;
606 }
607
608 islastchanofgroup[lasttrack]=true;
609 }
610 return (cannotopen==0); // return true if successful, false otherwise
611}
612
613void hd24transferengine::closeinputfiles(SNDFILE** filehandle,unsigned int channels)
614{
615 SNDFILE* lasthandle=NULL;
616 for (unsigned int handle=0;handle<channels;handle++)
617 {
618 if (job->trackselected[handle]==0) continue;
619 if (filehandle[handle]!=lasthandle) {
620 soundfile->sf_close(filehandle[handle]);
621 lasthandle=filehandle[handle];
622 filehandle[handle]=NULL;
623 }
624 }
625}
626
627void hd24transferengine::closeoutputfiles(hd24sndfile** filehandle,unsigned int channels)
628{
629 void* lasthandle=NULL;
630
631 for (unsigned int handle=0;handle<channels;handle++)
632 {
633 if (job->trackselected[handle]==0) continue;
634 if (filehandle[handle]->handle()!=lasthandle) {
635 lasthandle=(void*)filehandle[handle]->handle();
636 if (lasthandle!=NULL) {
637 filehandle[handle]->close();
638 }
639 }
640 }
641}
642
643bool hd24transferengine::confirmfileoverwrite()
644{
645 if (this->uiconfirmfunction==NULL)
646 {
647 lasterror("Output files already exist, transfer aborted.");
648 return false;
649 }
650
651 return uiconfirmfunction(ui,"One or more output files already exist. "
652 "Do you want to overwrite them?");
653}
654
655bool hd24transferengine::overwritegivesproblems(hd24song* thesong,int partnum)
656{
657 /* this function will return TRUE if overwriting
658 existing files causes a problem, FALSE otherwise.
659
660 Overwriting files does NOT cause problems if
661 - no files are going to be overwritten
662 or
663 - Files are going to be overwritten but the user
664 permits us to do so.
665
666 */
667
668 if (anyfilesexist(thesong))
669 {
670 return (!(confirmfileoverwrite()));
671 }
672 return false;
673}
674
675bool hd24transferengine::dontopenoutputfiles(hd24sndfile** filehandle,unsigned int channels,unsigned int partnum,int prefix)
676{
677 // HACK
678 trackspergroup=0;
679
680 SF_INFO sfinfoout;
681 //bool uselibsndfile=m_format_sndfile[selectedformat()];
682 sfinfoout.format=m_format_outputformat[selectedformat()];
683 int chcount=0;
684 if (m_format_outputchannels[selectedformat()]==0) {
685 // count channels
686 for (unsigned int handle=0;handle<channels;handle++)
687 {
688 if (job->trackselected[handle]!=0) {
689 chcount++;
690 }
691 }
692 sfinfoout.channels=chcount;
693 } else {
694 sfinfoout.channels=m_format_outputchannels[selectedformat()];
695 }
696 if (job->usecustomrate==1) {
697 long samrate=job->stamprate;
698 sfinfoout.samplerate=samrate;
699 } else {
700 sfinfoout.samplerate=job->sourcesong()->samplerate();
701 }
702 // chcount and lasthandle are intended to allow
703 // support for writing multichannel files.
704 int lasthandle=0;
705 int lasttrack=-1;
706 int trackcount=0;
707 int cannotopen=0;
708 chcount=0;
709 for (unsigned int handle=0;handle<channels;handle++)
710 {
711
712 islastchanofgroup[handle]=false;
713 isfirstchanofgroup[handle]=false;
714
715 if (job->trackselected[handle]==0) {
716 // channel not selected for export
717 continue;
718 }
719 trackcount++;
720 lasttrack=handle;
721
722 string* fname=generate_filename(handle,partnum,prefix);
723 if (fname==NULL)
724 {
725 // Cannot generate filename. No song set?
726 return false; // problem (not) opening files.
727 }
728 if (chcount==0) {
729 isfirstchanofgroup[handle]=true;
730 // if (uselibsndfile)
731 // {
732 // filehandle[handle]->sndfilehandle=NULL;
733 // if (soundfile->sf_open) {
734 // filehandle[handle]->open(fname->c_str(),(int)SFM_WRITE,&sfinfoout,soundfile);
735 // }
736 // if (!(filehandle[handle]->handle()))
737 // {
738 // cannotopen=1;
739 // }
740 // }
741 // else
742 // {
743 // filehandle[handle]->open(fname->c_str(),(int)SFM_WRITE,&sfinfoout);
744 // }
745 lasthandle=handle;
746 } else {
747 // copy handle of previously opened file to current track
748 // filehandle[handle]->handle(filehandle[lasthandle]->handle(),filehandle[lasthandle]->handletype());
749 // if (!(filehandle[handle]->handle()))
750 // {
751 // cannotopen=1;
752 // }
753 }
754 chcount++;
755 // if ((sfinfoout.channels)!=0)
756 // {
757 // // sfinfoout.channels=0 means full multitrack file
758 // // so only a single file will be opened.
759 // chcount=chcount%(sfinfoout.channels);
760 // if (chcount==0) {
761 // islastchanofgroup[handle]=true;
762 // if (trackspergroup==0) {
763 // trackspergroup=trackcount;
764 // }
765 // }
766 // }
767
768 delete fname;
769 }
770
771 if (lasttrack>=0)
772 {
773 if (trackspergroup==0) {
774 trackspergroup=trackcount;
775 }
776
777 islastchanofgroup[lasttrack]=true;
778 }
779 return (cannotopen==0); // return true if successful, false otherwise
780}
781void hd24transferengine::flushbuffer(hd24sndfile** filehandle,unsigned char** buffer,__uint32 flushbytes,unsigned int channels)
782{
783 #if (HD24TRANSFERDEBUG==1)
784 cout << "Flushbuffer " << flushbytes << " bytes" <<endl;
785 #endif
786 for (unsigned int handle=0;handle<channels;handle++)
787 {
788 if (job->trackselected[handle]==0) continue;
789
790 writerawbuf(&(*filehandle)[handle],buffer[handle],flushbytes);
791 }
792 #if (HD24TRANSFERDEBUG==1)
793 cout << "Flushed" << endl;
794 #endif
795}
796
797void hd24transferengine::prepare_transfer_to_pc(__uint32 songnum,
798 __uint32 totsongs,__sint64 totbytestotransfer,
799 __sint64 totbytestransferred,
800 int wantsplit,__uint32 prefix)
801{
802 // set properties as needed
803 cout << "prepare transfer to pc:" << endl;
804 cout << "song "<< songnum<< "/" << totsongs << ", ";
805 cout << totbytestotransfer << " total bytes to transfer" << endl;
806 cout << totbytestransferred << " transferred so far" << endl;
807 cout << "wantsplit=" << wantsplit ;
808 cout << ", prefix=" << prefix << endl;
809 this->totbytestotransfer=totbytestotransfer;
810 // this->transfer_to_pc();
811}
812
813void hd24transferengine::transfer_in_progress(bool active)
814{
815 // TODO: callback function
816 // stop_transfer->show();
817}
818
819void hd24transferengine::mixleft(bool select)
820{
821 if (select) { job->mixleft=1; }
822}
823
824bool hd24transferengine::mixleft()
825{
826 if (job->mixleft==1)
827 {
828 return true;
829 }
830 return false;
831}
832
833void hd24transferengine::mixright(bool select)
834{
835 if (select) { job->mixright=1; }
836}
837
838bool hd24transferengine::mixright()
839{
840 if (job->mixright==1)
841 {
842 return true;
843 }
844 return false;
845}
846
847
848__sint64 hd24transferengine::transfer_to_pc()
849{
850 // function returns bytes transferred for the transfer of only the current file.
851
852 __sint64 totsamcount; /* Total number of samples exported */
853 __sint64 partsamcount; /* When splitting up the song into multiple parts,
854 number of samples exported to current part */
855 __sint64 blockcount; /* Allows us to keep a write buffer as cache for
856 better export performance */
857 if (job->sourcesong()==NULL)
858 {
859 return 0;
860 }
861 if (transfer_cancel==1)
862 {
863 return 0;
864 }
865
866 // limit which tracks need to be actually read from HD24 disk
867 for (__uint32 i=1;i<=MAXCHANNELS;i++)
868 {
869 if (job->trackselected[i-1]==1)
870 {
871 job->sourcesong()->readenabletrack(i,true);
872 } else {
873 job->sourcesong()->readenabletrack(i,false);
874 }
875 }
876 bool mustmixdown=false;
877 if (job->mixleft==1)
878 {
879 mustmixdown=true;
880 }
881 if (job->mixright==1)
882 {
883 mustmixdown=true;
884 }
885 if (transfermixer==NULL)
886 {
887 /* as much as we'd like, there is no mixer so we can't mix. */
888 mustmixdown=false;
889 }
890
891 #if (HD24TRANSFERDEBUG==1)
892 cout << "start export 1" << endl;
893 #endif
894 __uint32 lastremain=0xffffffff; //a
895 __uint64 songlen_sam=job->sourcesong()->songlength_in_samples()*(job->sourcesong()->physical_channels()/job->sourcesong()->logical_channels());
896 __uint32 channels=job->sourcesong()->logical_channels();
897 __uint32 bytespersam=(job->sourcesong()->bitdepth()/8);
898 int mustdeinterlace=0;
899 if ((job->sourcesong()->samplerate())>=88200)
900 {
901 mustdeinterlace=1;
902 }
903 __uint32 oldmixersamplerate=0;
904 if (mustmixdown)
905 {
906 if (transfermixer!=NULL) {
907 oldmixersamplerate=transfermixer->samplerate();
908 transfermixer->samplerate(job->sourcesong()->samplerate());
909 }
910 }
911
912 #if (HD24TRANSFERDEBUG==1)
913 cout << "Channels="<<channels << endl;
914 cout << "Songlen="<<songlen_sam << endl;
915 #endif
916 double oldpct=0;
917 #if (HD24TRANSFERDEBUG==1)
918 cout << "start export 2" << endl;
919 #endif
920
921 //SNDFILE* filehandle[channels];
922 hd24sndfile* filehandle[24];
923
924 for (int i=0;i<MAXCHANNELS;i++)
925 {
926 filehandle[i]=new hd24sndfile(m_format_outputformat[selectedformat()],soundfile);
927 }
928
929 __uint32 partnum=0;
930 __uint64 MAXBYTES=job->sizelimit();
931
932 /*
933 if total number of samples is likely to overflow
934 max allowable length, ask if user wants to split up
935 the files.
936 */
937 if (job->wantsplit==1) {
938 partnum=1; // count part numbers in filename
939 } else {
940 partnum=0; // do not count part numbers in filename
941 MAXBYTES=songlen_sam*bytespersam; // allow the full song length in a single file
942 }
943
944 /* Start location 0 is absolute, all other offsets
945 are relative to the start offset. The only difference
946 is in the timecode.
947 Because of this, if startoffset>0 is given, we
948 can ignore this. */
949 __uint64 translen;
950 __uint64 tottranslen=0; // for percentage calc in multi-song exports
951 signed int stepsize;
952 if (job->startoffset()>job->endoffset())
953 {
954 __uint32 tempoffset=job->startoffset();
955 job->startoffset(job->endoffset());
956 job->endoffset(tempoffset);
957 }
958
959 translen=(job->endoffset()-job->startoffset())*(job->sourcesong()->physical_channels()/job->sourcesong()->logical_channels());
960 #if (HD24TRANSFERDEBUG==1)
961 cout << "startoffset=" << job->startoffset() << endl;
962 cout << "endoffset=" << job->endoffset() << endl;
963 #endif
964
965 if (translen==0)
966 {
967 lasterror("Start offset equals end offset- nothing to do!");
968 }
969 stepsize=1;
970
971 bool canopen=true;
972 MixerChannelControl* mixerchannel[24];
973 for (unsigned int tracknum=0;tracknum<MAXCHANNELS;tracknum++)
974 {
975 mixerchannel[tracknum]=NULL;
976 }
977
978 if (mustmixdown)
979 {
980 for (unsigned int tracknum=0;tracknum<MAXCHANNELS;tracknum++)
981 {
982 mixerchannel[tracknum]=transfermixer->parentui()->mixerchannel[tracknum]->control;
983 }
984 // HACK
985 canopen=dontopenoutputfiles(
986 (hd24sndfile**)&filehandle[0],
987 channels,
988 partnum,
989 prefix); // partnum is for splitting large files
990 } else {
991 canopen=openoutputfiles(
992 (hd24sndfile**)&filehandle[0],
993 channels,
994 partnum,
995 prefix); // partnum is for splitting large files
996 }
997
998 if (!canopen)
999 {
1000 #if (HD24TRANSFERDEBUG==1)
1001 cout << "error opening output files" << endl;
1002 #endif
1003 transfer_cancel=1;
1004 return 0;
1005 } else {
1006 transfer_cancel=0;
1007 }
1008
1009 this->transfer_in_progress(true);
1010 time (&starttime);
1011
1012 partsamcount=0; totsamcount=0;
1013 int trackwithingroup=0;
1014 #if (HD24TRANSFERDEBUG==1)
1015 cout << "songlen in samples=" << songlen_sam << endl;
1016 #endif
1017 blockcount=0; // for buffered writing.
1018 hd24fs* currenthd24=job->sourcefs();
1019 if (currenthd24==NULL)
1020 {
1021 cout << "Critical error- current FS not defined." << endl;
1022 }
1023 int blocksize=currenthd24->getbytesperaudioblock();
1024 // to hold normally read audio data:
1025 unsigned char* audiodata=(unsigned char*)memutils::mymalloc("ftransfer_to_pc",blocksize,1);
1026
1027 // for high-samplerate block deinterlacing:
1028 unsigned char* deinterlacedata=(unsigned char*)memutils::mymalloc("ftransfer_to_pc",blocksize,1);
1029
1030 // for interlacing multi-track data:
1031 unsigned char* interlacedata=(unsigned char*)memutils::mymalloc("ftransfer_to_pc",blocksize,1);
1032
1033
1034 __uint32 samplesperblock=(blocksize/channels)/bytespersam;
1035 float* outputBuffer=NULL;
1036 SF_INFO infoblock;
1037 hd24sndfile* mixdownfile=NULL;
1038 if (mustmixdown)
1039 {
1040 outputBuffer=(float*)malloc(2*samplesperblock*sizeof(float)); // 2 because it is stereo
1041 mixdownfile=new hd24sndfile(SF_FORMAT_WAV|SF_FORMAT_PCM_32
1042 |SF_FORMAT_FLOAT,soundfile);
1043 infoblock.channels=2;
1044 infoblock.samplerate=job->sourcesong()->samplerate();
1045 infoblock.format=SF_FORMAT_WAV|SF_FORMAT_PCM_32|SF_FORMAT_FLOAT;
1046
1047 int mixdownfilenum=0;
1048 int fileopensuccess=0;
1049 do {
1050 string* mixdownfilename=new string("");
1051 *mixdownfilename+=*job->m_projectdir;
1052 string* currsongname=job->sourcesong()->songname();
1053 *mixdownfilename+=*currsongname;
1054 delete currsongname;
1055 *mixdownfilename+="_mixdown";
1056 if (mixdownfilenum>0)
1057 {
1058 *mixdownfilename+="_";
1059 string* mixnumstr=Convert::int2str(mixdownfilenum);
1060 *mixdownfilename+=*mixnumstr;
1061 delete mixnumstr;
1062 }
1063 *mixdownfilename+=".wav";
1064 if (!hd24utils::fileExists(mixdownfilename->c_str()))
1065 {
1066 mixdownfile->open(mixdownfilename->c_str(),SFM_WRITE,&infoblock,soundfile);
1067 fileopensuccess=1;
1068 }
1069 mixdownfilenum++;
1070 delete mixdownfilename;
1071 } while (fileopensuccess==0);
1072 }
1073
1074
1075 __uint32 samplesinfirstblock=samplesperblock;
1076 if (job->startoffset()!=0) {
1077 if (job->startoffset()>=samplesperblock) {
1078 samplesinfirstblock=samplesperblock-(job->startoffset()%samplesperblock);
1079 } else {
1080 samplesinfirstblock=samplesperblock-(job->startoffset());
1081 }
1082 }
1083 #if (HD24TRANSFERDEBUG==1)
1084 cout << "go to startoffset " << job->startoffset() << endl;
1085 #endif
1086 job->sourcesong()->golocatepos(job->startoffset());
1087 #if (HD24TRANSFERDEBUG==1)
1088 cout << "got to startoffset " << job->startoffset() << endl;
1089 cout << "translen= " << translen << endl;
1090 #endif
1091 __uint32 subblocksize=samplesperblock*bytespersam;
1092 __uint32 samplesinblock=samplesinfirstblock;
1093 if (translen<samplesperblock)
1094 {
1095 samplesinfirstblock=translen;
1096 }
1097
1098 __sint64 difseconds=0;
1099 __sint64 olddifseconds=0;
1100 __uint64 bytestransferred=0;
1101
1102 for (__uint32 samplenum=0;
1103 samplenum<translen;
1104 samplenum+=samplesinblock)
1105 {
1106 if (transfer_cancel==1)
1107 {
1108 break;
1109 }
1110 __uint32 subblockbytes=subblocksize;
1111 if (translen==samplesinfirstblock)
1112 {
1113 #if (HD24TRANSFERDEBUG==1)
1114 cout << "translen==samplesinfirstblock" << endl;
1115 subblockbytes=translen*bytespersam;
1116 samplesinblock=samplesinfirstblock;
1117 #endif
1118 } else {
1119 if (samplenum==0) {
1120 samplesinblock=samplesinfirstblock;
1121 }
1122 else
1123 {
1124 samplesinblock=samplesperblock;
1125 }
1126
1127 if (samplenum+samplesinblock>=translen)
1128 {
1129 subblockbytes=((translen-samplesinfirstblock) % samplesperblock ) *bytespersam;
1130 } else {
1131 if (samplesinblock!=samplesperblock)
1132 {
1133 subblockbytes=samplesinblock*bytespersam;
1134 }
1135 }
1136 }
1137
1138 #if (HD24TRANSFERDEBUG==1)
1139 cout << "samplenum=" << samplenum << ", sams in block=" << samplesinblock << endl;
1140 #endif
1141
1142 int skipsams=job->sourcesong()->getmtrackaudiodata(samplenum+job->startoffset(),samplesinblock,&audiodata[0],hd24song::READMODE_COPY);
1143 unsigned char* whattowrite=&audiodata[0];
1144 if (mustdeinterlace==1)
1145 {
1146 job->sourcesong()->deinterlaceblock(&audiodata[0],&deinterlacedata[0]);
1147 whattowrite=&deinterlacedata[0];
1148 }
1149
1150 #if (HD24TRANSFERDEBUG==1)
1151 cout << "check for split" << endl;
1152 #endif
1153 if (job->wantsplit==1)
1154 {
1155 __uint64 filesize=partsamcount;
1156 filesize+=samplesinblock;
1157 filesize*=bytespersam;
1158 if (filesize>MAXBYTES) /// total filesize reached for current part
1159 {
1160 closeoutputfiles((hd24sndfile**)&filehandle[0],channels);
1161 partnum++;
1162 openoutputfiles((hd24sndfile**)&filehandle[0],channels,partnum,prefix); // partnum is for splitting large files
1163 partsamcount=0;
1164 }
1165 }
1166
1167 // check if we need to save a mixdown
1168 if (mustmixdown)
1169 {
1170#if (HD24TRANSFERDEBUG==1)
1171 cout << "Mixing " << endl;
1172#endif
1173
1174 for (__uint32 tracknum=0;tracknum<channels;tracknum++)
1175 {
1176 unsigned char* currsam=&whattowrite[tracknum*subblocksize
1177 +((mustdeinterlace+1)*skipsams*bytespersam)];
1178 for (__uint32 samnum=0;samnum<subblockbytes;samnum+=3)
1179 {
1180 float subsamval=currsam[samnum+0]
1181 +(currsam[samnum+1]<<8)
1182 +(currsam[samnum+2]<<16);
1183
1184 if (subsamval>=(1<<23)) {
1185 subsamval-=(1<<24);
1186 }
1187 subsamval=(subsamval/(double)0x800000);
1188 mixerchannel[tracknum]->sample(samnum/3,subsamval);
1189 }
1190 }
1191 transfermixer->mix(subblockbytes/3);
1192
1193 if (outputBuffer!=NULL)
1194 {
1195 // if stereo output, interlace (TODO: check if this is what we want)
1196 for (__uint32 i=0;i<(subblockbytes/3);i++)
1197 {
1198 ((float*)outputBuffer)[i*2] = transfermixer->masterout(0,i); // left
1199 ((float*)outputBuffer)[i*2+1] = transfermixer->masterout(1,i); // right
1200 }
1201 mixdownfile->write_float(outputBuffer,(subblockbytes/3)*infoblock.channels);
1202 }
1203 }
1204 // when mixing down, let's not export raw files as well.
1205
1206 for (__uint32 tracknum=0;tracknum<channels;tracknum++)
1207 {
1208 if (job->trackselected[tracknum]==0)
1209 {
1210 // track not selected for export
1211#if (HD24TRANSFERDEBUG==1)
1212 cout << "Track " << tracknum+1 << " not selected for export " << endl;
1213#endif
1214 continue;
1215 }
1216
1217 if (transfer_cancel==1)
1218 {
1219#if (HD24TRANSFERDEBUG==1)
1220 cout << "Transfer cancelled by user. " << endl;
1221#endif
1222 break;
1223 }
1224
1225 // Mono files or multiple tracks?
1226 if (
1227 (isfirstchanofgroup[tracknum])
1228 &&(islastchanofgroup[tracknum])
1229 ) {
1230 // file is mono
1231 if (!mustmixdown) {
1232 writerawbuf(filehandle[tracknum],&whattowrite[tracknum*subblocksize+((mustdeinterlace+1)*skipsams*bytespersam)],subblockbytes);
1233 }
1234 bytestransferred+=subblockbytes;
1235 } else {
1236 if (isfirstchanofgroup[tracknum]) {
1237 // first channel of group, clear interlace buffer
1238 trackwithingroup=0;
1239#if (HD24TRANSFERDEBUG==1)
1240 cout << "first track " << samplenum << endl;
1241#endif
1242 } else {
1243 trackwithingroup++;
1244 #if (HD24TRANSFERDEBUG==1)
1245 cout << "nonfirst track " << samplenum << endl;
1246 #endif
1247 }
1248 // interlace channel onto multi channel file buffer
1249 if (!mustmixdown) {
1250 hd24utils::interlacetobuffer(&whattowrite[tracknum*subblocksize+((mustdeinterlace+1)*skipsams*bytespersam)],&interlacedata[0],subblockbytes,bytespersam,trackwithingroup,trackspergroup);
1251 }
1252
1253 if (islastchanofgroup[tracknum]) {
1254 // last channel of group, write interlace buffer to file
1255 #if (HD24TRANSFERDEBUG==1)
1256 cout << "write track " << samplenum << endl;
1257 #endif
1258 //soundfile->sf_write_raw(filehandle[tracknum],&interlacedata[0],subblockbytes*trackspergroup);
1259 if (!mustmixdown) {
1260 writerawbuf(filehandle[tracknum],&interlacedata[0],subblockbytes*trackspergroup);
1261 }
1262 bytestransferred+=subblockbytes*trackspergroup;
1263 }
1264 }
1265 }
1266 partsamcount+=(subblockbytes/bytespersam);
1267 // totsamcount+=subblockbytes;
1268
1269 __uint32 pct; // to use for display percentage
1270 double dblpct; // to use for ETA calculation
1271 #if (HD24TRANSFERDEBUG==1)
1272 cout << "about to calc pct" << endl;
1273 cout << "totbytestransferred=" << totbytestransferred;
1274 cout << ", currbytestransferred=" << bytestransferred;
1275 cout << ", totbytestotransfer=" << totbytestotransfer;
1276 cout << endl;
1277 #endif
1278
1279 /* following two calculations give the same mathematical result
1280 but help keep the required word length narrow for large numbers
1281 and reduce floating point rounding errors for small numbers.
1282 */
1283 if (tottranslen<100000)
1284 {
1285 dblpct=(
1286 (
1287 (
1288 (double)totbytestransferred
1289 +(double)bytestransferred
1290 )
1291 *(double)100
1292 )
1293 /
1294 (double)totbytestotransfer
1295 );
1296 }
1297 else
1298 {
1299 dblpct=(
1300 (
1301 (double)totbytestransferred
1302 +(double)bytestransferred
1303 )
1304 /
1305 (double)
1306 (
1307 (double)totbytestotransfer
1308 /
1309 (double)100
1310 )
1311 );
1312 }
1313 pct=(__uint32)(dblpct);
1314
1315 #if (HD24TRANSFERDEBUG==1)
1316 cout << "about to calc pct2" << endl;
1317 #endif
1318
1319 #if (HD24TRANSFERDEBUG==1)
1320 cout << "computed pct " << samplenum << endl;
1321 #endif
1322 time (&endtime);
1323 olddifseconds=difseconds;
1324 difseconds=(long long int)difftime(endtime,starttime);
1325
1326 if (((dblpct-oldpct)>=1) || ((difseconds-olddifseconds)>=1))
1327 {
1328 /* update on percentage change, and also every
1329 so many samples (to allow frequent enough
1330 screen updates with large audio files) */
1331 oldpct=dblpct;
1332
1333 string pctmsg="Transferring audio to PC... ";
1334 if (totsongs>1)
1335 {
1336 pctmsg+="Song ";
1337 string* cursongnum=Convert::int2str(songnum);
1338 pctmsg+=*cursongnum+"/";
1339 delete cursongnum;
1340 string* totsongnum=Convert::int2str(totsongs);
1341 pctmsg+=*totsongnum+", ";
1342 delete totsongnum;
1343 }
1344 string* strpct=Convert::int2str(pct);
1345 pctmsg+=*strpct+"%";
1346
1347 if (pct>0)
1348 {
1349 __uint32 estimated_seconds=(__uint32)((difseconds*100)/dblpct);
1350 __uint32 remaining_seconds=estimated_seconds-difseconds;
1351
1352 lastremain=remaining_seconds;
1353
1354 __uint32 seconds=(lastremain%60);
1355 __uint32 minutes=(lastremain-seconds)/60;
1356 __uint32 hours=0;
1357
1358 pctmsg+=" Time remaining: ";
1359
1360 if (minutes>59) {
1361 hours=(minutes/60);
1362 minutes=(minutes%60);
1363 string* strhours=Convert::int2str(hours,2,"0");
1364 pctmsg+=*strhours;
1365 pctmsg+=":";
1366 delete(strhours);
1367 }
1368
1369 string* minsec=Convert::int2str(minutes,2,"0");
1370
1371 *minsec+=":";
1372
1373 string* strsecs=Convert::int2str(seconds,2,"0");
1374 *minsec+=*strsecs;
1375 delete(strsecs);
1376
1377 pctmsg+=*minsec;
1378 delete(minsec);
1379 }
1380
1381 delete (strpct);
1382 setstatus(ui,&pctmsg,dblpct);
1383 }
1384 }
1385
1386 closeoutputfiles((hd24sndfile**)&filehandle[0],channels);
1387 for (int i=0;i<MAXCHANNELS;i++) {
1388 if (filehandle[i]!=NULL)
1389 {
1390 delete filehandle[i];
1391 }
1392 }
1393 // from now on we'll read all tracks again
1394 for (__uint32 i=1;i<=MAXCHANNELS;i++)
1395 {
1396 if (job->trackselected[i-1]==1)
1397 {
1398 job->sourcesong()->readenabletrack(i,true);
1399 }
1400 }
1401 if (audiodata!=NULL)
1402 {
1403 free (audiodata);
1404 }
1405 if (deinterlacedata!=NULL)
1406 {
1407 free (deinterlacedata);
1408 }
1409 if (interlacedata!=NULL)
1410 {
1411 free (interlacedata);
1412 }
1413 if (outputBuffer!=NULL)
1414 {
1415 free (outputBuffer);
1416 }
1417 if (mixdownfile!=NULL)
1418 {
1419 mixdownfile->close();
1420 }
1421 if (transfermixer!=NULL) {
1422 transfermixer->samplerate(oldmixersamplerate);
1423 }
1424
1425 return bytestransferred;
1426}
1427
1428void hd24transferengine::selectedformat(int i)
1429{
1430 if (i>=formatcount) return;
1431 job->selectedformat(i);
1432}
1433void hd24transferjob::selectedformat(int i)
1434{
1435 m_selectedformat=i;
1436}
1437
1438int hd24transferengine::selectedformat()
1439{
1440 return job->selectedformat();
1441}
1442int hd24transferjob::selectedformat()
1443{
1444 return m_selectedformat;
1445}
1446
1447void hd24transferengine::mixer(MixerControl* m_mixer)
1448{
1449 this->transfermixer=m_mixer;
1450}
1451
1452MixerControl* hd24transferengine::mixer()
1453{
1454 return this->transfermixer;
1455}
1456
1457string* hd24transferengine::generate_filename(int tracknum,int partnum,int prefix)
1458{
1459#if (HD24TRANSFERDEBUG==1)
1460 cout << "hd24transferengine::generate_filename(track=" << tracknum << ",part="<<partnum<<",prefix="<<prefix<<endl;
1461 cout << "Selected format="<<selectedformat() << endl;
1462#endif
1463#if (HD24TRANSFERDEBUG==1)
1464 cout << "Job="<<job<<endl;
1465#endif
1466#if (HD24TRANSFERDEBUG==1)
1467 cout << "Projdir="<<job->m_projectdir<<endl;
1468#endif
1469 if (job->m_projectdir==NULL)
1470 {
1471 cout << "No project dir set!" << endl;
1472 return NULL;
1473 }
1474 const char* pdir=job->m_projectdir->c_str(); //projectdir();
1475#if (HD24TRANSFERDEBUG==1)
1476 cout << "Projdir (const char*)="<<pdir << endl;
1477#endif
1478
1479 if (pdir==NULL)
1480 {
1481 cout << "No project dir set!" << endl;
1482 return NULL;
1483 }
1484 string* dirname=new string(pdir);
1485 if (dirname->substr(dirname->length()-1,1)!="/") {
1486 *dirname+="/";
1487 }
1488#if (HD24TRANSFERDEBUG==1)
1489 cout << "filename so far is just dir with slash=" << *dirname << endl;
1490#endif
1491 string* fname=new string(dirname->c_str());
1492 delete dirname;
1493 if (prefix!=0)
1494 {
1495 string* strsongnum=Convert::int2str(prefix,2,"0");
1496 *fname+="Song";
1497 *fname+=*strsongnum;
1498 *fname+="-";
1499 delete (strsongnum);
1500 }
1501#if (HD24TRANSFERDEBUG==1)
1502 cout << "filename so far is " << *fname << endl;
1503 cout << "About to add songname" << endl;
1504#endif
1505 if (job->sourcesong()==NULL)
1506 {
1507#if (HD24TRANSFERDEBUG==1)
1508 cout << "No song set!" << endl;
1509#endif
1510 return NULL;
1511 }
1512
1513 string* strsongname=job->sourcesong()->songname();
1514 *fname+=*strsongname;
1515 delete (strsongname);
1516
1517#if (HD24TRANSFERDEBUG==1)
1518 cout << "filename so far is " << *fname << endl;
1519 cout << "About to add track constant" << endl;
1520#endif
1521 *fname+="-Track";
1522#if (HD24TRANSFERDEBUG==1)
1523 cout << "filename so far is " << *fname << endl;
1524 cout << "About to add tracknum" << (tracknum+2) << endl;
1525#endif
1526 string* strtracknum=Convert::int2str(tracknum+1,2,"0");
1527 *fname+=*strtracknum;
1528 delete (strtracknum);
1529 if (partnum>0) {
1530 /* partnum 0 implies no splitting and thus no partnum
1531 added to the filename. In other words, we either use
1532 partnum 0 (invisible in filename), or partnum 1-n. */
1533 *fname+="_part";
1534 *fname+=*Convert::int2str(partnum);
1535 }
1536 string* extension=new string((*m_format_outputextension)[selectedformat()]);
1537 *fname+=*extension;
1538 delete extension;
1539#if (HD24TRANSFERDEBUG==1)
1540 cout << "Generated filename="<<fname<<endl;
1541#endif
1542 return fname;
1543}
1544
1545void hd24transferjob::sizelimit(__sint64 p_sizelimit)
1546{
1547 this->llsizelimit=p_sizelimit;
1548}
1549
1550__sint64 hd24transferjob::sizelimit()
1551{
1552 return this->llsizelimit;
1553}
1554
1555void hd24transferengine::sizelimit(__sint64 p_sizelimit)
1556{
1557 job->sizelimit(p_sizelimit);
1558}
1559
1560__sint64 hd24transferengine::sizelimit()
1561{
1562 return job->sizelimit();
1563}
1564
1565bool hd24transferengine::anyfilesexist(hd24song* thesong)
1566{
1567 bool anyexist=false;
1568 struct stat fi;
1569 __uint32 channels=thesong->logical_channels();
1570 for (unsigned int q=0; q<100; q++)
1571 {
1572 for (unsigned int handle=0;handle<channels;handle++)
1573 {
1574 if (job->trackselected[handle]==0)
1575 {
1576 // channel not selected for export
1577 continue;
1578 }
1579 string* fname=this->generate_filename(handle,0,q);
1580 if (fname==NULL)
1581 {
1582 // cannot generate filename (no song set?)
1583 break;
1584 }
1585#if (HD24TRANSFERDEBUG==1)
1586 cout << "check if file exists:" << *fname << endl;
1587#endif
1588 if ((stat (fname->c_str(), &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0))
1589 {
1590 anyexist=true;
1591#if (HD24TRANSFERDEBUG==1)
1592 cout << "yes, exists" << *fname << endl;
1593#endif
1594 delete fname;
1595 break;
1596 }
1597
1598 fname=this->generate_filename(handle,1,q);
1599 if (fname==NULL)
1600 {
1601 // cannot generate filename (no song set?)
1602 break;
1603 }
1604#if (HD24TRANSFERDEBUG==1)
1605 cout << "check if file exists:" << *fname << endl;
1606#endif
1607 if ((stat (fname->c_str(), &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0))
1608 {
1609 anyexist=true;
1610#if (HD24TRANSFERDEBUG==1)
1611 cout << "yes, exists" << *fname << endl;
1612#endif
1613 delete fname;
1614 break;
1615 }
1616#if (HD24TRANSFERDEBUG==1)
1617 cout << "no, doesnt exist" << endl;
1618#endif
1619
1620 delete fname;
1621 }
1622 if (anyexist==true) break;
1623 }
1624 return anyexist;
1625}
1626
1627void hd24transferengine::setstatus(void* ui,string* message,double percentage)
1628{
1629#if (HD24TRANSFERDEBUG==1)
1630 printf(message->c_str(),percentage);
1631 cout << endl;
1632#endif
1633 if (setstatusfunction!=NULL)
1634 {
1635 setstatusfunction(ui,message->c_str(),percentage);
1636 }
1637 return;
1638}
1639
1640void hd24transferengine::set_ui(void* p_ui)
1641{
1642 this->ui=p_ui;
1643}
1644
1645void hd24transferengine::sourcesong(hd24song* song)
1646{
1647#if (HD24TRANSFERDEBUG==1)
1648 cout << "hd24transferengine::sourcesong(" << song << ")" << endl;
1649#endif
1650 if (this->job==NULL)
1651 {
1652 return;
1653 }
1654 this->job->sourcesong(song);
1655}
1656
1657hd24song* hd24transferengine::sourcesong()
1658{
1659#if (HD24TRANSFERDEBUG==1)
1660 cout << "hd24transferengine::sourcesong()="
1661 << this->job->sourcesong()<< endl;
1662#endif
1663 if (this->job==NULL)
1664 {
1665 return NULL;
1666 }
1667 return this->job->sourcesong();
1668}
1669
1670void hd24transferengine::startoffset(__uint32 newoff)
1671{
1672 job->startoffset(newoff);
1673}
1674
1675void hd24transferengine::endoffset(__uint32 newoff)
1676{
1677 job->endoffset(newoff);
1678}
1679
1680__uint32 hd24transferengine::startoffset()
1681{
1682 return job->startoffset();
1683}
1684
1685__uint32 hd24transferengine::endoffset()
1686{
1687 return job->endoffset();
1688}
1689
1690void hd24transferengine::targetsong(hd24song* song)
1691{
1692 if (job==NULL)
1693 {
1694 return;
1695 }
1696 job->targetsong(song);
1697}
1698
1699hd24song* hd24transferengine::targetsong()
1700{
1701 if (job==NULL)
1702 {
1703 return NULL;
1704 }
1705 return job->targetsong();
1706}
1707
1708__sint64 hd24transferengine::transfer_to_hd24()
1709{
1710 if (job->targetsong()==NULL)
1711 {
1712 lasterror("No target song selected, transfer aborted.");
1713 return 0;
1714 }
1715 if (soundfile==NULL)
1716 {
1717 lasterror("soundfile library not defined, transfer aborted");
1718 return 0;
1719 }
1720 job->targetsong()->golocatepos(0);
1721 job->targetsong()->startrecord(hd24song::WRITEMODE_COPY);
1722
1723 //mustdisplaytimer=false;
1724 __sint64 bytestransferred=0;
1725
1726 for (unsigned int currchan=0;currchan<MAXCHANNELS;currchan++) {
1727 job->filehandle[currchan]=NULL;
1728 audiobuf[currchan]=NULL;
1729 }
1730 SF_INFO sfinfoin[24];
1731 bool canopen=this->openinputfiles((SNDFILE**)&(job->filehandle[0]),(SF_INFO*)&sfinfoin[0],job->targetsong()->logical_channels());
1732 if (!canopen)
1733 {
1734 return 0;
1735 }
1736 // Find file with largest number of samples;
1737 // if song is shorter than that, lengthen song to fit it.
1738 __sint64 translen=job->targetsong()->songlength_in_samples();
1739 __uint32 maxlen=(__uint32)translen;
1740 bool mustlengthensong=false;
1741 for (int i=0;i<MAXCHANNELS;i++) {
1742 if (job->filehandle[i]==NULL) continue;
1743 if (((__sint64)sfinfoin[i].frames) > (__sint64)maxlen) {
1744 maxlen=sfinfoin[i].frames;
1745 mustlengthensong=true;
1746 }
1747 }
1748 if (mustlengthensong) {
1749 string* lengthening=new string("Transferring audio to HD24... ");
1750 setstatus(ui,lengthening,0);
1751 delete lengthening;
1752 #if (HD24TRANSFERDEBUG==1)
1753 cout << "about to start lengthening song to maxlen=" << maxlen << endl;
1754 #endif
1755 bool clearnew=false; // do not silence newly allocated part
1756 // (it is done automatically during transfer)
1757 translen=job->targetsong()->songlength_in_samples(maxlen,clearnew);
1758 #if (HD24TRANSFERDEBUG==1)
1759 cout << "verifying actual song length " << endl;
1760 cout << "new len=" << translen << endl;
1761 #endif
1762 if (translen!=maxlen)
1763 {
1764 #if (HD24TRANSFERDEBUG==1)
1765 cout << "new len<> maxlen so not enough space." << endl;
1766 #endif
1767 this->lasterror("Not enough space on HD24 drive.");
1768 return 0;
1769 }
1770 job->targetsong()->save();
1771 // ui_refresh("tohd24");
1772 #if (HD24TRANSFERDEBUG==1)
1773 cout << "translen is now " << translen << endl;
1774 #endif
1775
1776 }
1777 hd24fs* currenthd24=job->targetfs();
1778 int blocksize=currenthd24->getbytesperaudioblock();
1779 // to hold normally read audio data:
1780 unsigned char* audiodata=NULL;
1781 transfer_cancel=0;
1782// ui->stop_transfer->show();
1783
1784 audiodata=(unsigned char*)memutils::mymalloc("button_transfertohd24",blocksize,1);
1785 __uint32 channels=job->targetsong()->logical_channels();
1786 __uint32 bytespersam=(job->targetsong()->bitdepth()/8);
1787 __uint32 samplesperblock=(blocksize/channels)/bytespersam;
1788 job->smptegen=new SMPTEgenerator(job->targetsong()->samplerate());
1789
1790 for (unsigned int fh=0;fh<MAXCHANNELS;fh++) {
1791 int action=job->trackaction(fh+1);
1792 if ((job->filehandle[fh]!=NULL)||(action<=1 /* erase, SMPTE stripe */)) {
1793 __uint32 chans=((action==0)||(action==1))?(1):(sfinfoin[fh].channels);
1794 __uint32 bytestoalloc=chans*samplesperblock*sizeof(int);
1795 audiobuf[fh]=(int*)memutils::mymalloc(
1796 "button_transfertohd24 audiobuf",bytestoalloc,1
1797 );
1798
1799 if (action == 0) {
1800 // clear erase buffer once
1801 int* buf=audiobuf[fh];
1802 for (__uint32 samnum=0;samnum<samplesperblock;samnum++) {
1803 buf[samnum]=0;
1804 }
1805 }
1806 if (action == 1) {
1807 // clear SMPTE buffer once (mostly for debugging purposes)
1808 int* buf=audiobuf[fh];
1809 for (__uint32 samnum=0;samnum<samplesperblock;samnum++) {
1810 buf[samnum]=1;
1811 }
1812 }
1813 // if action==1, we need to repopulate the buffer while striping
1814 } else {
1815 audiobuf[fh]=NULL;
1816 }
1817 }
1818
1819 // number of samples in current block- equal to block samples for full song
1820 // transfer
1821 __uint32 subblocksize=samplesperblock*bytespersam;
1822
1823 int mustinterlace=0;
1824 if ((job->targetsong()->samplerate())>=88200)
1825 {
1826 mustinterlace=1;
1827 }
1828 #if (HD24TRANSFERDEBUG==1)
1829 cout << "Channels="<<channels << endl;
1830 #endif
1831 __uint32 startoffset=0;
1832 //__uint32 endoffset=currsong->songlength_in_samples();
1833 __uint32 samplesinfirstblock=samplesperblock;
1834
1835 job->targetsong()->getlocatepos(25); // 25= virtual endpoint of song
1836 // calc number of samples to transfer.
1837 // for high samplerate songs, this is twice the songlength.
1838 // (for partial transfers, which are not supported at this time, the
1839 // number of samples is based on (endoffset-startoffset) instead of songlength
1840 translen=job->targetsong()->songlength_in_samples()*(job->targetsong()->physical_channels()/job->targetsong()->logical_channels());
1841 __uint64 totbytestotransfer=translen*bytespersam;
1842 //transfer_to_hd24();
1843
1844 if (startoffset!=0) {
1845 if (startoffset>=samplesperblock) {
1846 samplesinfirstblock=samplesperblock-(startoffset%samplesperblock);
1847 } else {
1848 samplesinfirstblock=samplesperblock-startoffset;
1849 }
1850 }
1851 #if (HD24TRANSFERDEBUG==1)
1852 cout << "go to startoffset " << startoffset << endl;
1853 #endif
1854 job->targetsong()->golocatepos(startoffset);
1855 #if (HD24TRANSFERDEBUG==1)
1856 cout << "got to startoffset " << startoffset << endl;
1857 cout << "translen= " << translen << endl;
1858 #endif
1859
1860 __uint32 samplesinblock=samplesinfirstblock;
1861 if (translen<samplesperblock)
1862 {
1863 samplesinfirstblock=translen;
1864 }
1865
1866 __sint64 difseconds=0;
1867 __sint64 olddifseconds=0;
1868 __uint64 totbytestransferred=0; // only for multi song transfer- does not apply.
1869 //deactivate_ui();
1870 for (__uint32 samplenum=0;
1871 samplenum<translen;
1872 samplenum+=samplesinblock)
1873 {
1874 if (transfer_cancel==1)
1875 {
1876 //ui_refresh("tohd24_cancel");
1877 break;
1878 }
1879 #if (HD24TRANSFERDEBUG==1)
1880 cout << "samnum= " << samplenum << endl;
1881 #endif
1882 __uint32 subblockbytes=subblocksize;
1883 if (translen==samplesinfirstblock)
1884 {
1885 #if (HD24TRANSFERDEBUG==1)
1886 cout << "translen==samplesinfirstblock" << endl;
1887 subblockbytes=translen*bytespersam;
1888 samplesinblock=samplesinfirstblock;
1889 #endif
1890 } else {
1891 if (samplenum==0) {
1892 samplesinblock=samplesinfirstblock;
1893 }
1894 else
1895 {
1896 samplesinblock=samplesperblock;
1897 }
1898
1899 if (samplenum+samplesinblock>=translen)
1900 {
1901 subblockbytes=((translen-samplesinfirstblock) % samplesperblock ) *bytespersam;
1902 } else {
1903 if (samplesinblock!=samplesperblock)
1904 {
1905 subblockbytes=samplesinblock*bytespersam;
1906 }
1907 }
1908 }
1909
1910 #if (HD24TRANSFERDEBUG==1)
1911 cout << "samplenum=" << samplenum << ", sams in block=" << samplesinblock << endl;
1912 #endif
1913
1914 /*
1915 // disable multipart files for now (this function transfers TO HD24 drives)
1916 if (wantsplit==1)
1917 {
1918 if (((partsamcount+samplesinblock)*bytespersam)>MAXBYTES) /// total filesize reached for current part
1919 {
1920 this->closeoutputfiles((SNDFILE**)&filehandle[0],channels);
1921 partnum++;
1922 this->openoutputfiles((SNDFILE**)&filehandle[0],channels,partnum,prefix); // partnum is for splitting large files
1923 partsamcount=0;
1924 }
1925 }
1926 */
1927 for (__uint32 tracknum=0;tracknum<channels;tracknum++)
1928 {
1929 if (!(job->targetsong()->trackarmed(tracknum+1)))
1930 {
1931 // track not selected for export
1932 continue;
1933 }
1934 __uint32 samsread=0;
1935 int action=job->trackaction(tracknum+1);
1936 unsigned int trackchans=1;
1937
1938 if (action==0) { /* 0=ERASE */
1939 #if (HD24TRANSFERDEBUG==1)
1940 cout << "track " << tracknum+1 << " marked for erase" << endl;
1941
1942 #endif
1943 samsread=samplesinblock;
1944 } else {
1945 if (action==1)
1946 {
1947 #if (HD24TRANSFERDEBUG==1)
1948 cout << "track " << tracknum+1 << " marked for stripe" << endl;
1949
1950 #endif
1951 /* Stripe track with SMPTE/LTC here */
1952
1953 int* buf=audiobuf[tracknum];
1954
1955 for (__uint32 samnum=0;samnum<samplesinblock;samnum++) {
1956 // smpte stripe:
1957 buf[samnum]=((job->smptegen->getbit(samplenum+samnum)*2)-1)*2000000;
1958 }
1959 /* End of stripe */
1960 samsread=samplesinblock;
1961 } else {
1962 trackchans=sfinfoin[tracknum].channels;
1963 if (job->filehandle[tracknum] == NULL) {
1964 continue;
1965 }
1966 samsread=soundfile->sf_read_int(
1967 job->filehandle[tracknum],
1968 audiobuf[tracknum],
1969 samplesinblock*trackchans);
1970 #if (HD24TRANSFERDEBUG==1)
1971 cout << "sams read="
1972 << samsread
1973 << endl;
1974 #endif
1975 }
1976 }
1977 // we replace the deinterlaced data with file audio
1978 //sf_write_raw(filehandle[tracknum],&whattowrite[tracknum*subblocksize+((mustdeinterlace+1)*skipsams*bytespersam)],subblockbytes);
1979
1980
1981
1982 // cout << "replace audio block on track " << tracknum+1 << endl;
1983
1984 //filehandle[tracknum];
1985
1986 // libsndfile converts all files to 32-bit samples, but we only use 24 bit,
1987 // so we divide by 256 to shift out the unused 8 bits.
1988
1989 __uint32 firstbyte=tracknum*samplesinblock*bytespersam;
1990 __uint32 whichbyte=firstbyte;
1991
1992 int samval;
1993 for (unsigned int sam=0;sam<samsread;sam+=trackchans)
1994 {
1995 int whichsam=sam;
1996 if (action>2) {
1997 // multi track
1998 // use only 24 out of 32 bit
1999 samval = (audiobuf[tracknum][whichsam+(action-3)])/256;
2000 } else {
2001 if (action<2)
2002 {
2003 samval=(audiobuf[tracknum][whichsam]);
2004 } else {
2005 // action=2 (mono track).
2006 if (trackchans==1)
2007 {
2008 // use the only track
2009 samval=(audiobuf[tracknum][whichsam])/256;
2010 }
2011 else {
2012 // convert multiple tracks to 1 mono track
2013 samval=0;
2014 for (unsigned int whichchan=0;whichchan<trackchans;whichchan++) {
2015 samval+=(audiobuf[tracknum][whichsam+whichchan])/256;
2016 }
2017 // TODO: clip handling
2018 samval/=trackchans;
2019 }
2020 }
2021 }
2022#if (HD24TRANSFERDEBUG==1)
2023 cout << "whichsam=" << whichsam << " " ;//
2024
2025
2026 cout << "buf[" << tracknum*samplesinblock+(whichsam*bytespersam) << "]=";
2027 cout << (samval & 0xff) << " " << ((samval>>8) & 0xff) << " " << ((samval>>16) & 0xff) <<"//";
2028 if (sam==0) {
2029 cout << "writing to byte " << whichbyte << " of audiodata " <<endl;
2030 }
2031#endif
2032 audiodata[whichbyte]=(unsigned char)samval & 0xff;
2033 audiodata[whichbyte+1]=(unsigned char)(samval>>8) & 0xff;
2034 audiodata[whichbyte+2]=(unsigned char)(samval>>16) & 0xff;
2035 whichbyte+=bytespersam;
2036 }
2037 // cout << endl;
2038
2039 if (transfer_cancel==1) {
2040 //ui_refresh("tohd24_cancel2");
2041 break;
2042 }
2043 }
2044
2045 // finally we write the audio. the hd24 library will make sure only the relevant
2046 // tracks will be overwritten and the rest are protected.
2047 #if (HD24TRANSFERDEBUG==1)
2048 cout << "1st 30 bytes of track: " << endl;
2049 for (unsigned int fbyte=0; fbyte<30; fbyte++) {
2050 cout << audiodata[samplesinblock+fbyte] << " ";
2051 }
2052 cout << endl;
2053 #endif
2054 //int writesams= (result was not used)
2055 job->targetsong()->putmtrackaudiodata(
2056 samplenum+startoffset,
2057 samplesinblock,
2058 &audiodata[0],
2059 hd24song::WRITEMODE_COPY
2060 );
2061
2062 totbytestransferred+=(samplesinblock*bytespersam);
2063
2064 __uint32 pct; // to use for display percentage
2065 __uint32 oldpct=0; // to use for display percentage
2066 double dblpct; // to use for ETA calculation
2067 #if (HD24TRANSFERDEBUG==1)
2068 cout << "about to calc pct" << endl;
2069 cout << "totbytestransferred=" << totbytestransferred;
2070 cout << ", currbytestransferred=" << bytestransferred;
2071 cout << ", totbytestotransfer=" << totbytestotransfer;
2072 cout << endl;
2073 #endif
2074
2075 if (translen<100000) {
2076 pct=(__uint32)(((totbytestransferred+bytestransferred)*100)/(totbytestotransfer));
2077 } else {
2078 pct=(__uint32)((totbytestransferred+bytestransferred)/(totbytestotransfer/100));
2079 }
2080 #if (HD24TRANSFERDEBUG==1)
2081 cout << "about to calc pct2" << endl;
2082 #endif
2083 if (translen<100000) {
2084 dblpct=(((totbytestransferred+bytestransferred)*100)/(totbytestotransfer));
2085 } else {
2086 dblpct=((totbytestransferred+bytestransferred)/(totbytestotransfer/100));
2087 }
2088
2089 #if (HD24TRANSFERDEBUG==1)
2090 cout << "computed pct " << samplenum << endl;
2091 #endif
2092 time (&endtime);
2093 olddifseconds=difseconds;
2094 difseconds=(long long int)difftime(endtime,starttime);
2095
2096 if ((pct!=oldpct) || ((difseconds-olddifseconds)>=1))
2097 {
2098 /* update on percentage change, and also every
2099 so many samples (to allow frequent enough
2100 screen updates with large audio files) */
2101 oldpct=pct;
2102
2103 string* pctmsg=new string("Transferring audio to HD24... %d%%");
2104 // TODO: Estimated time remaining goes here
2105 setstatus(ui,pctmsg,pct);
2106 delete pctmsg;
2107 }
2108
2109 // fl_check(); covered by setstatus
2110 }
2111
2112 // fl_check(); covered by setstatus
2113 if (job->smptegen!=NULL)
2114 {
2115 // TODO: move to job destructor?
2116 delete job->smptegen;
2117 job->smptegen=NULL;
2118 }
2119 if (audiodata!=NULL)
2120 {
2121 free (audiodata);
2122 audiodata=NULL;
2123 }
2124 for (unsigned int bufnum=0;bufnum<MAXCHANNELS;bufnum++) {
2125 if (audiobuf[bufnum]!=NULL) {
2126 memutils::myfree("audiobuf transfer_to_hd24",audiobuf[bufnum]);
2127 audiobuf[bufnum]=NULL;
2128 }
2129 }
2130
2131 //end transfer_to_hd24
2132
2133
2134
2135 job->targetsong()->stoprecord();
2136
2137 for (unsigned int chnum=1;chnum<=job->targetsong()->logical_channels();chnum++) {
2138 job->targetsong()->trackarmed(chnum,false);
2139 }
2140 this->closeinputfiles((SNDFILE**)&(job->filehandle[0]),job->targetsong()->logical_channels());
2141 return totbytestransferred;
2142}
2143
diff --git a/src/lib/hd24transferengine.h b/src/lib/hd24transferengine.h
new file mode 100644
index 0000000..03d8392
--- /dev/null
+++ b/src/lib/hd24transferengine.h
@@ -0,0 +1,188 @@
1#ifndef __hd24transferengine_h__
2#define __hd24transferengine_h__
3
4class MixerControl;
5
6#include <config.h>
7#include <hd24fs.h>
8#include <hd24sndfile.h>
9#include <ui_mixer.h>
10#include <smpte.h>
11class hd24transferjob
12{
13friend class hd24transferengine;
14private:
15 long long llsizelimit; /* to hold max filesize for autosplit */
16 int mixleft;
17 int mixright;
18 int m_selectedformat;
19 hd24fs* jobsourcefs;
20 hd24song* jobsourcesong;
21 hd24fs* jobtargetfs;
22 hd24song* jobtargetsong;
23 __uint32 m_startoffset;
24 __uint32 m_endoffset;
25 SNDFILE* filehandle[24]; /* todo: implement as hd24sndfile* */
26 char* filepath[24]; /* one full file path/name per track
27 mainly to be used for export to hd24 */
28 bool have_smpte;
29 int m_trackaction[24];
30 SMPTEgenerator* smptegen;
31public:
32
33 string* m_projectdir;
34 int usecustomrate; // 1 to stamp export with custom sample rate
35 // 0 to keep song sample rate
36 __uint32 stamprate; //sample rate to use if usecustomrate==1
37 int wantsplit;
38 int* trackselected;
39 hd24transferjob();
40 ~hd24transferjob();
41 void init_vars();
42
43 void sizelimit(__sint64 llsizelimit);
44 __sint64 sizelimit();
45
46 __uint32 startoffset();
47 __uint32 endoffset();
48 void startoffset(__uint32 newoff);
49 void endoffset(__uint32 newoff);
50
51 void projectdir(const char* projectdir);
52 const char* projectdir();
53 void selectedformat(int format);
54 int selectedformat();
55 hd24fs* sourcefs();
56 hd24fs* targetfs();
57 hd24song* sourcesong();
58 hd24song* targetsong();
59 void sourcefs(hd24fs* fs);
60 void targetfs(hd24fs* fs);
61 void sourcesong(hd24song* song);
62 void targetsong(hd24song* song);
63 char* sourcefilename(int base1tracknum);
64 void sourcefilename(int base1tracknum,const char* name);
65 void trackaction(int base1tracknum,int action);
66 int trackaction(int base1tracknum);
67};
68
69class hd24transferengine
70{
71private:
72 void* ui;
73
74 MixerControl* transfermixer;
75 hd24transferjob* job;
76
77 __uint32 songnum;
78 __uint32 totsongs;
79 __sint64 totbytestotransfer;
80 __sint64 totbytestransferred;
81
82 int prefix;
83 int transfer_cancel;
84 int trackspergroup;
85 int* audiobuf[24]; /* for libsndfile int reading from file */
86 bool isfirstchanofgroup[24]; /* for exporting stereo pairs/groups of channels */
87 bool islastchanofgroup[24]; /* for exporting stereo pairs/groups of channels */
88
89 void setstatus(void* ui,string* message,double percent);
90
91 void openbuffers(unsigned char** audiobuf,unsigned int channels,unsigned int bufsize);
92 void closebuffers(unsigned char** audiobuf,unsigned int channels);
93 void writerawbuf(hd24sndfile* filehandle,unsigned char* buf,long subblockbytes);
94 void flushbuffer(hd24sndfile** filehandle,unsigned char** buffer,__uint32 flushbytes,unsigned int channels);
95
96
97 bool overwritegivesproblems(hd24song* thesong,int partnum);
98 bool confirmfileoverwrite(); // perform interactive/GUI callback
99 // to confirm if file overwriting is OK
100 bool anyfilesexist(hd24song* thesong);
101 void transfer_in_progress(bool active);
102
103 time_t starttime; // these are for benchmarking the transfer
104 time_t endtime;
105
106 /* Regarding populating list of supported file formats
107 TODO: Move to a separate class?
108 */
109 int formatcount;
110 void populate_formatlist();
111 vector<string>* m_format_outputextension;
112 vector<string>* m_format_shortdesc;
113 int m_format_outputformat[100];
114 int m_format_outputchannels[100];
115 int m_format_bitdepth[100];
116 bool m_format_sndfile[100];
117 string* m_lasterror;
118
119public:
120 SoundFileWrapper* soundfile;
121 bool (*uiconfirmfunction)(void* ui,const char*);
122 void (*setstatusfunction)(void* ui,const char*,double progress_pct);
123
124 void set_ui(void* p_ui);
125
126 hd24transferengine();
127 ~hd24transferengine();
128
129 void mixer(MixerControl* m_mixer);
130 MixerControl* mixer();
131
132 void lasterror(const char* errormessage);
133 string* lasterror();
134
135 int supportedformatcount();
136 int format_outputchannels(int i);
137 const char* getformatdesc(int formatnum);
138
139 void trackselected(__uint32 base0tracknum,bool select);
140 bool trackselected(__uint32 base0tracknum);
141
142 void mixleft(bool select);
143 bool mixleft();
144 void mixright(bool select);
145 bool mixright();
146
147 void init_vars();
148 void prepare_transfer_to_pc(
149 __uint32 songnum, __uint32 totsongs,
150 __sint64 totbytestotransfer,
151 __sint64 totbytestransferred,
152 int wantsplit,__uint32 prefix);
153
154 __sint64 transfer_to_pc();
155 __sint64 transfer_to_hd24();
156
157 bool openinputfiles(SNDFILE** filehandle,SF_INFO* sfinfoin,unsigned int channels);
158 void closeinputfiles(SNDFILE** filehandle,unsigned int channels);
159 bool dontopenoutputfiles(hd24sndfile** filehandle,unsigned int channels,unsigned int partnum,int prefix); //HACK
160
161 bool openoutputfiles(hd24sndfile** filehandle,unsigned int channels,unsigned int partnum,int prefix);
162 void closeoutputfiles(hd24sndfile** filehandle,unsigned int channels);
163 string* generate_filename(int tracknum,int partnum,int prefix);
164 void sizelimit(__sint64 llsizelimit);
165 __sint64 sizelimit();
166 void projectdir(const char* projectdir);
167 const char* projectdir();
168
169 void selectedformat(int format);
170 int selectedformat();
171
172 void sourcesong(hd24song* newsong);
173 hd24song* sourcesong();
174 void targetsong(hd24song* newsong);
175 hd24song* targetsong();
176
177 __uint32 startoffset();
178 __uint32 endoffset();
179 void startoffset(__uint32 newoff);
180 void endoffset(__uint32 newoff);
181 char* sourcefilename(int base1tracknum);
182 void sourcefilename(int base1tracknum,const char* name);
183 void trackaction(int base1tracknum,int action);
184 int trackaction(int base1tracknum);
185
186};
187
188#endif
diff --git a/src/lib/hd24utils.cpp b/src/lib/hd24utils.cpp
new file mode 100755
index 0000000..6efb3a7
--- /dev/null
+++ b/src/lib/hd24utils.cpp
@@ -0,0 +1,637 @@
1#define UTILDEBUG 0
2#ifdef DARWIN
3# define creat64 creat
4# define open64 open
5# define lseek64 lseek
6# define pread64 pread
7# define pwrite64 pwrite
8#endif
9
10#if defined(LINUX) || defined(DARWIN)
11# define PRINTAPP "lp"
12#endif
13
14#ifdef WINDOWS
15# include <windows.h>
16# include <shellapi.h>
17# define PRINTAPP "print"
18# define popen _popen
19# define pclose _pclose
20#else
21# include <unistd.h>
22#endif
23
24#include <string>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <fcntl.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <iostream>
31#include <fstream>
32#include <math.h>
33#include <hd24devicenamegenerator.h>
34#include <FL/FLTKstuff.H>
35#include <FL/Fl_Preferences.H>
36#include <FL/filename.H>
37#include "convertlib.h"
38#include "hd24utils.h"
39#include "memutils.h"
40#define _LARGE_FILES
41#define LARGE_FILES
42#define LARGEFILE64_SOURCE
43#define _FILE_OFFSET_BITS 64
44#define FILE_OFFSET_BITS 64
45#define SECTORSIZE 512
46#define FSINFO_VERSION_MAJOR 0x8
47#define FSINFO_VERSION_MINOR 0x9
48#define FSINFO_BLOCKSIZE_IN_SECTORS 0x10
49#define FSINFO_AUDIOBLOCKS_PER_CLUSTER 0x14
50#define FSINFO_STARTSECTOR_FAT 0x38
51#define FSINFO_NUMSECTORS_FAT 0x3c
52#define FSINFO_CLUSTERS_ON_DISK 0x44
53#define FSINFO_MAXPROJECTS 0x50
54#define FSINFO_MAXSONGSPERPROJECT 0x54
55#define FSINFO_DATAAREA 0x7c
56#define DRIVEINFO_VOLUME 0x1b8
57#define DRIVEINFO_PROJECTCOUNT 0x0c
58#define DRIVEINFO_LASTPROJ 0x10
59#define DRIVEINFO_PROJECTLIST 0x20
60
61void hd24utils::gencatalog_showsongs(hd24project* currentproj,string* strcatalog)
62{
63 if (currentproj==NULL) {
64 return;
65 }
66 if (strcatalog==NULL) {
67 return;
68 }
69 int numsongs=currentproj->songcount();
70 *strcatalog+=" ======================================================================\n";
71 if (numsongs==0) {
72 *strcatalog+=" There are no songs in this project.\n";
73 return;
74 }
75 hd24song* currsong=NULL;
76 for (int i=1; i<=numsongs; i++) {
77 currsong=currentproj->getsong(i);
78 if (currsong==NULL) continue;
79
80 *strcatalog+=" ";
81 *strcatalog+=" ";
82 if (i<10) {
83 *strcatalog+=" ";
84 }
85 string* songnum=Convert::int2str(i);
86 *strcatalog+=*songnum;
87 *strcatalog+=": ";
88 delete songnum;
89
90 string* currsname=currsong->songname();
91 string* pad=Convert::padright(*currsname,35," ");
92 delete(currsname);
93 *strcatalog+=*pad;
94 delete pad;
95 string* dur=currsong->display_duration();
96 *strcatalog+=*dur;
97 delete dur;
98 *strcatalog+= ", " ;
99
100 string* chans=Convert::int2str(currsong->logical_channels());
101 string* chans2=Convert::padleft(*chans,2," ");
102 *strcatalog+=*chans;
103 delete chans;
104 delete chans2;
105 *strcatalog+="ch. ";
106
107 string* samrate=Convert::int2str(currsong->samplerate());
108 *strcatalog+=*samrate;
109 delete samrate;
110 *strcatalog+=" Hz";
111
112
113 if (currsong->iswriteprotected())
114 {
115 *strcatalog+="*";
116 }
117
118 *strcatalog+="\n";
119
120 delete currsong;
121 currsong=NULL;
122 }
123 return;
124}
125
126void hd24utils::gencatalog_showprojects(hd24fs* currenthd24,string* strcatalog)
127{
128 int numprojs=currenthd24->projectcount();
129 hd24project* currproj=NULL;
130 for (int i=1; i<=numprojs; i++)
131 {
132 currproj=currenthd24->getproject(i);
133
134 *strcatalog+=" ======================================================================\n";
135 *strcatalog+=" Project ";
136 string* projnum=Convert::int2str(i);
137 *strcatalog+=*projnum;
138 delete projnum;
139 *strcatalog+=": ";
140
141 string* currpname=currproj->projectname();
142 *strcatalog+= *currpname;
143 delete(currpname);
144
145 *strcatalog+="\n"; // << endl;
146 gencatalog_showsongs (currproj,strcatalog); //to_out);
147 delete(currproj);
148 }
149
150}
151
152int hd24utils::gencatalog(hd24fs* currenthd24,string* strcatalog)
153{
154
155 time_t currenttime;
156 struct tm timestamp;
157 char timebuf[80];
158 time(&currenttime);
159 timestamp = *localtime(&currenttime);
160 strftime(timebuf,sizeof(timebuf),"%a %Y-%m-%d %H:%M:%S %Z", &timestamp);
161 *strcatalog+= " Catalog timestamp : ";
162 *strcatalog+= timebuf ;
163 *strcatalog+="\n";
164
165 *strcatalog+=" Volume name : ";
166 string* volname=currenthd24->volumename();
167 *strcatalog+=*volname;
168 delete volname;
169 *strcatalog+="\n";
170
171 *strcatalog+=" Number of projects : ";
172 string* pcount=Convert::int2str(currenthd24->projectcount());
173 *strcatalog+=*pcount;
174 delete pcount;
175
176 *strcatalog+="\n";
177 gencatalog_showprojects(currenthd24,strcatalog);
178 return 0;
179}
180
181string* hd24utils::savecatalog(hd24fs* currenthd24,string* filename)
182{
183 string* error=new string("");
184
185 // gencatalog
186 string* catalog=new string("");
187
188 if (hd24utils::gencatalog(currenthd24,catalog)!=0)
189 {
190 *error+="Error generating catalog.";
191 return error;
192 }
193 fstream to_out(filename->c_str(),ios::out);
194 if (to_out==NULL)
195 {
196 *error+="Cannot write catalog.";
197 return error;
198 }
199 to_out << *catalog ;
200
201 to_out.flush();
202 to_out.close();
203 return NULL;
204}
205
206string* hd24utils::printcatalog(hd24fs* currenthd24)
207{
208
209 string* error=new string("");
210 string catname="_hd24cat.txt";
211
212
213 // gencatalog
214 string* catalog=new string("");
215
216 if (hd24utils::gencatalog(currenthd24,catalog)!=0)
217 {
218 *error+="Error generating catalog.";
219 return error;
220 }
221 fstream to_out(catname.c_str(),ios::out);
222 if (to_out==NULL)
223 {
224 *error+="Cannot write catalog.";
225 return error;
226 }
227 *catalog += "\f\n"; // form feed
228 to_out << *catalog ;
229
230 to_out.flush();
231 to_out.close();
232
233#ifdef WINDOWS
234 SHELLEXECUTEINFO ShExecInfo = {0};
235 ShExecInfo.cbSize = sizeof (SHELLEXECUTEINFO);
236 ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; //SEE_MASK_INVOKEIDLIST;
237 ShExecInfo.hwnd = NULL;
238 ShExecInfo.lpVerb="print";
239 ShExecInfo.lpFile=catname.c_str();
240 ShExecInfo.lpParameters = "";
241 ShExecInfo.lpDirectory=NULL;
242 ShExecInfo.nShow = SW_HIDE;
243 ShExecInfo.hInstApp = NULL;
244 ShellExecuteEx(&ShExecInfo);
245 WaitForSingleObject(ShExecInfo.hProcess,INFINITE);
246 unlink (catname.c_str());
247#else
248 char s[1024];
249 string* catcmd = new string (PRINTAPP);
250 *catcmd += " ";
251 *catcmd += catname;
252 *catcmd += " 2>&1";
253 FILE *fp = popen(catcmd->c_str() , "r");
254 while (fgets(s, sizeof(s)-1, fp))
255 {
256 *error += s;
257 }
258 pclose(fp);
259 unlink (catname.c_str());
260#endif
261 return error;
262}
263
264
265void hd24utils::interlacetobuffer(unsigned char* sourcebuf,unsigned char* targetbuf,
266 __uint32 totbytes,__uint32 bytespersam,__uint32 trackwithingroup,__uint32 trackspergroup)
267{
268 __uint32 samplenum;
269 __uint32 totsams=totbytes/bytespersam;
270 __uint32 trackoff=(trackwithingroup*bytespersam);
271 __uint32 q=0;
272 // unroll loop for bytespersam=1,2,3
273 switch (bytespersam)
274 {
275 case 3:
276 for (samplenum=0;samplenum<totsams;samplenum++)
277 {
278 __uint32 samoff=(samplenum*bytespersam);
279 q=trackspergroup*samoff+trackoff;
280 targetbuf[q++]=sourcebuf[samoff];
281 targetbuf[q++]=sourcebuf[samoff+1];
282 targetbuf[q++]=sourcebuf[samoff+2];
283 }
284 break;
285 case 1:
286 for (samplenum=0;samplenum<totsams;samplenum++)
287 {
288 __uint32 samoff=(samplenum*bytespersam);
289 q=trackspergroup*samoff+trackoff;
290 targetbuf[q]=sourcebuf[samoff];
291 }
292 break;
293 case 2:
294 for (samplenum=0;samplenum<totsams;samplenum++)
295 {
296 __uint32 samoff=(samplenum*bytespersam);
297 q=trackspergroup*samoff+trackoff;
298 targetbuf[q++]=sourcebuf[samoff];
299 targetbuf[q++]=sourcebuf[samoff+1];
300 }
301 break;
302 default:
303 for (samplenum=0;samplenum<totsams;samplenum++)
304 {
305 __uint32 samoff=(samplenum*bytespersam);
306 q=trackspergroup*samoff;
307 for (__uint32 j=0; j<bytespersam; j++) {
308 targetbuf[q+j+trackoff]=sourcebuf[samoff+j];
309 }
310 }
311 break;
312 }
313}
314
315bool hd24utils::dirExists(const char * pszDirName)
316{
317#ifdef WIN32
318 unsigned int dwAttrs;
319 if (!(pszDirName))
320 {
321 //setupLog(NULL, "DirExists failed: passed in NULL parameter for directory");
322 return (1==0);
323 }
324 dwAttrs = GetFileAttributes(pszDirName);
325 if ((dwAttrs != 0xFFFFFFFF) && (dwAttrs & FILE_ATTRIBUTE_DIRECTORY))
326 {
327 return (1==1);
328 }
329 return (1==0);
330#else
331 struct stat fi;
332
333 if (stat (pszDirName, &fi) == -1 || !S_ISDIR(fi.st_mode))
334 {
335 return (1==0);
336 }
337 else
338 {
339 return (1==1);
340 }
341#endif
342}
343int hd24utils::savedrivesectors(hd24fs* currenthd24,string* outputfilename,unsigned long firstsector,unsigned long endsector,char* message,int* cancel) {
344 unsigned long i;
345#define MULTISECTOR 100
346 unsigned char bootblock[(MULTISECTOR+1)*512]; // 1 sector spare
347 memset(bootblock,0,MULTISECTOR*512);
348#if defined(LINUX) || defined(DARWIN)
349#if (UTILDEBUG==1)
350 cout << "creat64" << endl;
351#endif
352 FSHANDLE handle=creat64(outputfilename->c_str(),O_WRONLY);
353#endif
354#ifdef WINDOWS
355 FSHANDLE handle=CreateFile(outputfilename->c_str(),GENERIC_WRITE|GENERIC_READ,
356 FILE_SHARE_READ|FILE_SHARE_WRITE,
357 NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
358 if (hd24fs::isinvalidhandle(handle)) {
359 handle=CreateFile(outputfilename->c_str(),GENERIC_WRITE|GENERIC_READ,
360 FILE_SHARE_READ|FILE_SHARE_WRITE,
361 NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
362 }
363
364 #endif
365 if (hd24fs::isinvalidhandle(handle)) {
366 // cout << "Cannot open file "<<filename <<" for writing. Access denied?" << endl;
367 return 1;
368 }
369 int q=0;
370 for (i=firstsector;i<=endsector;i++) {
371 q++;
372 int numsectors=1;
373 if ((endsector-i) >=MULTISECTOR) {
374 numsectors=MULTISECTOR;
375 }
376 if (currenthd24!=NULL) {
377 currenthd24->readsector_noheader(currenthd24,i,bootblock); // raw reading
378 }
379#if defined(LINUX) || defined(DARWIN)
380 __uint64 targetoff=i;
381 targetoff-=firstsector;
382 targetoff*=512;
383 ssize_t byteswritten=0;
384 if (currenthd24!=NULL) {
385 byteswritten=pwrite64(handle,bootblock,512,targetoff);
386 } else {
387 byteswritten=pwrite64(handle,bootblock,512*numsectors,targetoff);
388 i+=(numsectors-1);
389 }
390#endif
391#ifdef WINDOWS
392 //DWORD dummy;
393 //long bytes=0;
394 __uint64 targetoff=i;
395 targetoff-=firstsector;
396 __uint64 byteswritten=0;
397 if (currenthd24!=NULL) {
398 byteswritten=currenthd24->writesectors(handle,targetoff,bootblock,1);
399 } else {
400 byteswritten=currenthd24->writesectors(handle,targetoff,bootblock,numsectors);
401 i+=(numsectors-1);
402 }
403#endif
404 if (byteswritten==0) {
405#if defined(LINUX) || defined(DARWIN)
406 close (handle);
407#endif
408#ifdef WINDOWS
409 CloseHandle(handle);
410#endif
411 return 1;
412 }
413 if (message!=NULL) {
414 if (q%1000==0) {
415 sprintf(message,"Saving sector %ld of %ld",i,(endsector+1));
416
417 // cout << i << endl;
418 Fl::wait(0);
419 }
420 }
421 }
422#if defined(LINUX) || defined(DARWIN)
423 close (handle);
424 chmod(outputfilename->c_str(),0664);
425#endif
426#ifdef WINDOWS
427 CloseHandle(handle);
428#endif
429
430 return 0;
431}
432
433int hd24utils::savedriveimage(hd24fs* currenthd24,string* imagefilename,char* message,int* cancel) {
434 unsigned long firstsector=0;
435 unsigned long endsector=currenthd24->getlastsectornum();
436 return savedrivesectors(currenthd24,imagefilename,firstsector,endsector,message,cancel);
437}
438
439int hd24utils::newdriveimage(string* imagefilename,__uint32 endsector,char* message,int* cancel) {
440 if (endsector<1353964)
441 {
442 // requested drive size is less than possible minimum size
443 return -1;
444 }
445
446 unsigned long firstsector=0;
447#if (UTILDEBUG==1)
448cout << "about to save drive sectors" <<endl;
449#endif
450 int result=savedrivesectors(NULL,imagefilename,firstsector,endsector,message,cancel);
451 if (result!=0)
452 {
453 return result;
454 }
455#if (UTILDEBUG==1)
456cout << "saved drive sectors, creating new fs object to format" <<endl;
457#endif
458 hd24fs* newfs=new hd24fs((const char*)NULL,hd24fs::MODE_RDWR,imagefilename,true);
459#if (UTILDEBUG==1)
460cout << "write enabling fs" <<endl;
461#endif
462 newfs->write_enable();
463#if (UTILDEBUG==1)
464cout << "quickformatting fs" <<endl;
465#endif
466 newfs->quickformat(message);
467#if (UTILDEBUG==1)
468 cout << "format result=" << *message << endl;
469cout << "deleting format fs object" <<endl;
470#endif
471 delete newfs;
472#if (UTILDEBUG==1)
473cout << "destructed fs object" <<endl;
474#endif
475 return 0;
476}
477
478void hd24utils::dumpsector(const char* buffer)
479{
480 for (int i=0;i<512;i+=16) {
481 string* dummy=Convert::int32tohex(i);
482 cout << *dummy << " ";
483 delete dummy; dummy=NULL;
484 for (int j=0;j<16;j++) {
485 string* dummy= Convert::byte2hex(buffer[i+j]);
486 cout << *dummy;
487 if (j==7) {
488 cout << "-" ;
489 } else {
490 cout << " " ;
491 }
492 delete dummy; dummy=NULL;
493 }
494 cout << " ";
495 for (int j=0;j<16;j++) {
496 cout << Convert::safebyte(buffer[i+j]);
497 }
498 cout << "" << endl;
499 }
500}
501int hd24utils::saveheader(hd24fs* currenthd24,string* headerfilename) {
502 return savedrivesectors(currenthd24,headerfilename,0,0x700,NULL,NULL);
503 // TODO: 0x700 sectors is arbitrary. First song entry is at 0x77,
504 // total of 99*99 songs of 7 sectors each puts actual required length
505 // at 0x10c76. However, this has served fine so far.
506
507}
508
509void hd24utils::findfile(const char* rawname,const char* path,char* result)
510{
511 string* strpath=new string(path);
512#ifdef WINDOWS
513 string* pathsep=new string(";");
514#else
515 string* pathsep=new string(":");
516#endif
517 int last=0;
518 string* exename;
519 string* exepath;
520#if (UTILDEBUG==1)
521 cout << "search path for exe " << endl;
522#endif
523 while (last==0)
524 {
525 unsigned int idx=strpath->find(pathsep->c_str());
526 if (idx==string::npos) {
527 last=1;
528 exepath=new string(strpath->c_str());
529 exename=new string(strpath->c_str());
530 *strpath="";
531 } else {
532 exepath=new string(strpath->substr(0,idx));
533 exename=new string(strpath->substr(0,idx));
534 *strpath=strpath->substr(idx+1);
535 }
536#if (UTILDEBUG==1)
537 cout << "exepath= " << *exepath << endl;
538#endif
539 if (exepath->substr(exepath->length()-1,1)!=PATHSLASH) {
540 *exepath+=PATHSLASH;
541 }
542 if (exename->substr(exename->length()-1,1)!=PATHSLASH) {
543 *exename+=PATHSLASH;
544 }
545
546 *exename+=rawname;
547#if (UTILDEBUG==1)
548 cout << "test if file " << exename->c_str() << " exists" << endl;
549#endif
550 if (hd24utils::fileExists(exename->c_str())) {
551 strncpy(result,exepath->c_str(),2048);
552 if (exename!=NULL) {
553 delete exename;
554 exename=NULL;
555 }
556 if (exepath!=NULL) {
557 delete exepath;
558 exepath=NULL;
559 }
560 if (strpath!=NULL) {
561 delete strpath;
562 strpath=NULL;
563 }
564 if (pathsep!=NULL) {
565 delete pathsep;
566 pathsep=NULL;
567 }
568 return ;
569 }
570 if (exename!=NULL) {
571 delete exename;
572 exename=NULL;
573 }
574 if (exepath!=NULL) {
575 delete exepath;
576 exepath=NULL;
577 }
578 }
579
580 if (strpath!=NULL) {
581 delete strpath;
582 strpath=NULL;
583 }
584 if (pathsep!=NULL) {
585 delete pathsep;
586 pathsep=NULL;
587 }
588
589 result[0]=(char)0;
590 return;
591}
592
593bool hd24utils::fileExists(const char* strFilename) {
594 struct stat stFileInfo;
595 int intStat;
596
597 // Attempt to get the file attributes
598 intStat = stat(strFilename,&stFileInfo);
599 if(intStat == 0)
600 {
601 // We were able to get the file attributes
602 // so the file obviously exists.
603 return true;
604 }
605 // We were not able to get the file attributes.
606 // This may mean that we don't have permission to
607 // access the folder which contains this file. If you
608 // need to do that level of checking, lookup the
609 // return values of stat which will give you
610 // more details on why stat failed.
611 return false;
612}
613
614string* hd24utils::getlastdir(string which)
615{
616 string* whichdir;
617 char buffer[FL_PATH_MAX];
618
619 Fl_Preferences* userprefs=new Fl_Preferences(Fl_Preferences::USER, "HD24","HD24connect" );
620 /* Attempt to find last used project dir */
621 if (userprefs->entryExists(which.c_str())) {
622 userprefs->get(which.c_str(),buffer,".",FL_PATH_MAX);
623 whichdir=new string(buffer);
624 } else {
625 whichdir=new string(".");
626 }
627 delete userprefs;
628 return whichdir;
629}
630
631void hd24utils::setlastdir(string which,const char* newdir)
632{
633 Fl_Preferences* userprefs=new Fl_Preferences(Fl_Preferences::USER, "HD24","HD24connect" );
634 userprefs->set(which.c_str(),newdir);
635 // cout << "just set " << which << " to " << newdir << endl;
636 delete userprefs;
637}
diff --git a/src/lib/hd24utils.h b/src/lib/hd24utils.h
new file mode 100755
index 0000000..b7a9fa7
--- /dev/null
+++ b/src/lib/hd24utils.h
@@ -0,0 +1,64 @@
1#ifndef __hd24utils_h__
2#define __hd24utils_h__
3#ifndef WINDOWS
4#define PATHSLASH "/"
5# include <sys/dir.h>
6# include <dirent.h>
7#else
8#define PATHSLASH "\\"
9# include <dir.h>
10# include <windows.h>
11# include <winioctl.h>
12# define FSHANDLE HANDLE
13# define FSHANDLE_INVALID INVALID_HANDLE_VALUE
14#endif
15
16#if defined(LINUX) || defined(DARWIN)
17# define FSHANDLE int
18# define FSHANDLE_INVALID -1
19#endif
20
21#include <config.h>
22#include <stdio.h>
23#include <string>
24#include <FL/FLTKstuff.H>
25#include "convertlib.h"
26#include "memutils.h"
27#include <hd24fs.h>
28
29using namespace std;
30class hd24fs;
31class hd24project;
32class hd24song;
33
34class hd24utils
35{
36 friend class hd24fs;
37 friend class hd24project;
38 friend class hd24song;
39 private:
40 // static void savecatalog_showprojects(hd24fs* currenthd24,fstream & to_out);
41 // static void savecatalog_showsongs(hd24project* currentproj,fstream & to_out);
42 static void gencatalog_showprojects(hd24fs* currenthd24,string* strcatalog);
43 static void gencatalog_showsongs(hd24project* currentproj,string* strcatalog);
44
45 public:
46 // static int savecatalog(hd24fs* currenthd24,string* headerfilename,bool toprint);
47 // static int gencatalog(hd24fs* currenthd24,string* headerfilename,bool toprint);
48 static string* savecatalog(hd24fs* currenthd24,string* filename);
49 static void findfile(const char* rawfilename, const char* searchpath, char* result);
50 static int gencatalog(hd24fs* currenthd24,string* strcatalog);
51 static string* printcatalog(hd24fs* currenthd24);
52 static int saveheader(hd24fs* currenthd24,string* headerfilename);
53 static int savedriveimage(hd24fs* currenthd24,string* imagefilename, char* message,int* cancel);
54 static int newdriveimage(string* imagefilename,__uint32 endsector,char* message,int* cancel);
55 static int savedrivesectors(hd24fs* currenthd24,string* imagefilename,unsigned long startsector,unsigned long endsector,char* message,int* cancel);
56 static void interlacetobuffer(unsigned char* sourcebuf,unsigned char* targetbuf, __uint32 totbytes,__uint32 bytespersam,__uint32 trackwithingroup,__uint32 trackspergroup);
57 static bool dirExists(const char * pszDirName);
58 static bool fileExists(const char * filename);
59 static string* getlastdir(string which);
60 static void dumpsector (const char* buffer);
61 static void setlastdir(string which,const char* newdir);
62};
63
64#endif
diff --git a/src/lib/memutils.cpp b/src/lib/memutils.cpp
new file mode 100644
index 0000000..e12b208
--- /dev/null
+++ b/src/lib/memutils.cpp
@@ -0,0 +1,27 @@
1#include <stdlib.h>
2#include <iostream>
3#include "memutils.h"
4#define MEMDEBUG 0
5void* memutils::mymalloc(const char* wherefrom,__uint32 elcount,__uint32 elsize)
6{
7 void* q=calloc(elcount,elsize);
8#if (MEMDEBUG==1)
9 cout << "ALLOC: " << wherefrom
10 <<" allocated "
11 << elcount<<" bytes at " << q << endl;
12#else
13 wherefrom=NULL;
14#endif
15 return q;
16}
17
18void memutils::myfree(const char* wherefrom,void* freewhat)
19{
20#if (MEMDEBUG==1)
21 cout << "FREE: "<< wherefrom <<" free bytes at " << freewhat << endl;
22#else
23 wherefrom=NULL;
24#endif
25 free(freewhat);
26}
27
diff --git a/src/lib/memutils.h b/src/lib/memutils.h
new file mode 100644
index 0000000..0798296
--- /dev/null
+++ b/src/lib/memutils.h
@@ -0,0 +1,15 @@
1#ifndef __memutils_h__
2#define __memutils_h__
3
4using namespace std;
5#include <config.h>
6
7class memutils
8{
9public:
10 static void* mymalloc(const char* wherefrom,__uint32 elcount,__uint32 elsize);
11 static void myfree(const char* wherefrom,void* freewhat);
12};
13
14#endif
15
diff --git a/src/lib/nojack.cpp b/src/lib/nojack.cpp
new file mode 100755
index 0000000..206557d
--- /dev/null
+++ b/src/lib/nojack.cpp
@@ -0,0 +1,223 @@
1#include "nojack.h"
2#ifndef NULL
3#define NULL 0
4#endif
5jack_client_t *jack_client_new (const char *client_name) { return NULL; };
6int jack_client_close (jack_client_t *client) { return 0; };
7int jack_client_name_size(void) { return 0; };
8int jack_internal_client_new (const char *client_name, const char *so_name,
9 const char *so_data) { return 0; };
10void jack_internal_client_close (const char *client_name) { return; }
11int jack_is_realtime (jack_client_t *client) { return 0; }
12void jack_on_shutdown (jack_client_t *client, void (*function)(void *arg), void *arg) { return; }
13int jack_set_process_callback (jack_client_t *client,
14 JackProcessCallback process_callback,
15 void *arg) {return 0; }
16int jack_set_thread_init_callback (jack_client_t *client,
17 JackThreadInitCallback thread_init_callback,
18 void *arg) { return 0;}
19int jack_set_freewheel_callback (jack_client_t *client,
20 JackFreewheelCallback freewheel_callback,
21 void *arg) { return 0;}
22int jack_set_freewheel(jack_client_t* client, int onoff) { return 0;}
23
24int jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes) {return 0;}
25int jack_set_buffer_size_callback (jack_client_t *client,
26 JackBufferSizeCallback bufsize_callback,
27 void *arg) {return 0;};
28int jack_set_sample_rate_callback (jack_client_t *client,
29 JackSampleRateCallback srate_callback,
30 void *arg) { return 0;};
31int jack_transport_query(jack_client_t *x,__uint64* y) {return 0;}
32int jack_set_port_registration_callback (jack_client_t *,
33 JackPortRegistrationCallback
34 registration_callback, void *arg) {return 0;};
35int jack_set_graph_order_callback (jack_client_t *, JackGraphOrderCallback graph_callback, void *) {return 0;};
36
37int jack_set_xrun_callback (jack_client_t *, JackXRunCallback xrun_callback, void *arg) { return 0;};
38int jack_activate (jack_client_t *client) {return 0;};
39int jack_deactivate (jack_client_t *client) {return 0;};
40jack_port_t *jack_port_register (jack_client_t *client,
41 const char *port_name,
42 const char *port_type,
43 unsigned long flags,
44 unsigned long buffer_size) { return NULL; }
45int jack_port_unregister (jack_client_t *, jack_port_t *) { return 0; }
46void *jack_port_get_buffer (jack_port_t *, jack_nframes_t) { return NULL;}
47const char *jack_port_name (const jack_port_t *port) { return NULL; }
48const char *jack_port_short_name (const jack_port_t *port) { return NULL; }
49int jack_port_flags (const jack_port_t *port) { return 0;}
50const char *jack_port_type (const jack_port_t *port) { return 0;}
51
52int jack_port_is_mine (const jack_client_t *, const jack_port_t *port) {return 0;};
53
54int jack_port_connected (const jack_port_t *port);
55int jack_port_connected_to (const jack_port_t *port,
56 const char *port_name);
57const char **jack_port_get_connections (const jack_port_t *port);
58const char **jack_port_get_all_connections (const jack_client_t *client,
59 const jack_port_t *port);
60int jack_port_tie (jack_port_t *src, jack_port_t *dst);
61int jack_port_untie (jack_port_t *port);
62int jack_port_lock (jack_client_t *, jack_port_t *);
63int jack_port_unlock (jack_client_t *, jack_port_t *);
64jack_nframes_t jack_port_get_latency (jack_port_t *port);
65jack_nframes_t jack_port_get_total_latency (jack_client_t *,
66 jack_port_t *port);
67void jack_port_set_latency (jack_port_t *, jack_nframes_t);
68int jack_port_set_name (jack_port_t *port, const char *port_name);
69int jack_port_request_monitor (jack_port_t *port, int onoff);
70int jack_port_ensure_monitor (jack_port_t *port, int onoff);
71int jack_port_monitoring_input (jack_port_t *port);
72int jack_connect (jack_client_t *,
73 const char *source_port,
74 const char *destination_port);
75int jack_disconnect (jack_client_t *,
76 const char *source_port,
77 const char *destination_port);
78int jack_port_disconnect (jack_client_t *, jack_port_t *);
79int jack_port_name_size(void);
80
81/**
82 * @return the maximum number of characters in a JACK port type name
83 * including the final NULL character. This value is a constant.
84 */
85int jack_port_type_size(void);
86
87/**
88 * @return the sample rate of the jack system, as set by the user when
89 * jackd was started.
90 */
91jack_nframes_t jack_get_sample_rate (jack_client_t *);
92
93/**
94 * @return the current maximum size that will ever be passed to the @a
95 * process_callback. It should only be used *before* the client has
96 * been activated. This size may change, clients that depend on it
97 * must register a @a bufsize_callback so they will be notified if it
98 * does.
99 *
100 * @see jack_set_buffer_size_callback()
101 */
102jack_nframes_t jack_get_buffer_size (jack_client_t *);
103
104/**
105 * @param port_name_pattern A regular expression used to select
106 * ports by name. If NULL or of zero length, no selection based
107 * on name will be carried out.
108 * @param type_name_pattern A regular expression used to select
109 * ports by type. If NULL or of zero length, no selection based
110 * on type will be carried out.
111 * @param flags A value used to select ports by their flags.
112 * If zero, no selection based on flags will be carried out.
113 *
114 * @return a NULL-terminated array of ports that match the specified
115 * arguments. The caller is responsible for calling free(3) any
116 * non-NULL returned value.
117 *
118 * @see jack_port_name_size(), jack_port_type_size()
119 */
120const char **jack_get_ports (jack_client_t *,
121 const char *port_name_pattern,
122 const char *type_name_pattern,
123 unsigned long flags);
124
125/**
126 * @return address of the jack_port_t named @a port_name.
127 *
128 * @see jack_port_name_size()
129 */
130jack_port_t *jack_port_by_name (jack_client_t *, const char *port_name);
131
132/**
133 * @return address of the jack_port_t of a @a port_id.
134 */
135jack_port_t *jack_port_by_id (const jack_client_t *client,
136 jack_port_id_t port_id);
137
138/**
139 * Old-style interface to become the timebase for the entire JACK
140 * subsystem.
141 *
142 * @deprecated This function still exists for compatibility with the
143 * earlier transport interface, but it does nothing. Instead, see
144 * transport.h and use jack_set_timebase_callback().
145 *
146 * @return ENOSYS, function not implemented.
147 */
148int jack_engine_takeover_timebase (jack_client_t *);
149
150/**
151 * @return the time in frames that has passed since the JACK server
152 * began the current process cycle.
153 */
154jack_nframes_t jack_frames_since_cycle_start (const jack_client_t *);
155
156/**
157 * @return an estimate of the current time in frames. This is a
158 * running counter, no significance should be attached to its value,
159 * but it can be compared to a previously returned value.
160 */
161jack_nframes_t jack_frame_time (const jack_client_t *);
162
163/**
164 * @return the frame_time after the last processing of the graph
165 * this is only to be used from the process callback.
166 *
167 * This function can be used to put timestamps generated by
168 * jack_frame_time() in correlation to the current process cycle.
169 */
170jack_nframes_t jack_last_frame_time (const jack_client_t *client);
171
172
173/**
174 * @return the current CPU load estimated by JACK. This is a running
175 * average of the time it takes to execute a full process cycle for
176 * all clients as a percentage of the real time available per cycle
177 * determined by the buffer size and sample rate.
178 */
179float jack_cpu_load (jack_client_t *client);
180
181/**
182 * Set the directory in which the server is expected
183 * to have put its communication FIFOs. A client
184 * will need to call this before calling
185 * jack_client_new() if the server was started
186 * with arguments telling it to use a non-standard
187 * directory.
188 *
189 * @deprecated This function is deprecated. Don't use in new programs
190 * and remove it in old programs.
191 */
192void jack_set_server_dir (const char *path);
193
194/**
195 * @return the pthread ID of the thread running the JACK client side
196 * code.
197 */
198pthread_t jack_client_thread_id (jack_client_t *);
199
200/**
201 * Display JACK error message.
202 *
203 * Set via jack_set_error_function(), otherwise a JACK-provided
204 * default will print @a msg (plus a newline) to stderr.
205 *
206 * @param msg error message text (no newline at end).
207 */
208extern void (*jack_error_callback)(const char *msg);
209
210/**
211 * Set the @ref jack_error_callback for error message display.
212 *
213 * The JACK library provides two built-in callbacks for this purpose:
214 * default_jack_error_callback() and silent_jack_error_callback().
215 */
216void jack_set_error_function (void (*func)(const char *));
217__uint64 jack_get_current_transport_frame(void* client) { return 0; }
218void jack_transport_stop (void * dummy) { return; };
219void jack_transport_start (void * dummy) { return; };
220void jack_transport_locate (void * dummy,int x) { return; };
221//void* jack_port_register (void* dummy,const void* dum2,int q,int y,int z) {return NULL;};
222#define JACK_DEFAULT_AUDIO_TYPE 0
223
diff --git a/src/lib/nojack.h b/src/lib/nojack.h
new file mode 100755
index 0000000..6a8ab9b
--- /dev/null
+++ b/src/lib/nojack.h
@@ -0,0 +1,467 @@
1/*
2 Copyright (C) 2001 Paul Davis
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 $Id: jack.h,v 1.64 2004/07/15 03:07:28 trutkin Exp $
19*/
20
21#ifndef __jack_h__
22#define __jack_h__
23
24#include "config.h"
25#define __int64 long long
26#ifdef __cplusplus
27extern "C" {
28#endif
29#define jack_client_t void
30#define jack_nframes_t __uint64
31#define jack_position_t __uint64
32#define jack_default_audio_sample_t int
33#define jack_port_t void*
34#define JackPortIsOutput 0
35#define JackPortIsInput 0
36typedef int(*JackProcessCallback)(__uint64, int,void*);
37#define JackThreadInitCallback void*
38#define JackPortRegistrationCallback void*
39#define JackGraphOrderCallback void*
40#define JackXRunCallback void*
41#define JackFreewheelCallback void*
42#define JackBufferSizeCallback void*
43#define JackSampleRateCallback void*
44#define jack_port_id_t void*
45#define jack_transport_state_t int
46#define JackTransportStopped 0
47#define pthread_t void*
48jack_client_t *jack_client_new (const char *client_name);
49int jack_client_close (jack_client_t *client);
50int jack_client_name_size(void);
51int jack_internal_client_new (const char *client_name, const char *so_name,
52 const char *so_data);
53void jack_internal_client_close (const char *client_name);
54int jack_is_realtime (jack_client_t *client);
55void jack_on_shutdown (jack_client_t *client, void (*function)(void *arg), void *arg) ;
56int jack_set_process_callback (jack_client_t *client,
57 JackProcessCallback process_callback,
58 void *arg) ;
59int jack_set_thread_init_callback (jack_client_t *client,
60 JackThreadInitCallback thread_init_callback,
61 void *arg) ;
62int jack_set_freewheel_callback (jack_client_t *client,
63 JackFreewheelCallback freewheel_callback,
64 void *arg) ;
65int jack_set_freewheel(jack_client_t* client, int onoff) ;
66
67int jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes) ;
68int jack_set_buffer_size_callback (jack_client_t *client,
69 JackBufferSizeCallback bufsize_callback,
70 void *arg);
71int jack_set_sample_rate_callback (jack_client_t *client,
72 JackSampleRateCallback srate_callback,
73 void *arg);
74int jack_transport_query(jack_client_t *x,__uint64* y);
75int jack_set_port_registration_callback (jack_client_t *,
76 JackPortRegistrationCallback
77 registration_callback, void *arg) ;
78int jack_set_graph_order_callback (jack_client_t *, JackGraphOrderCallback graph_callback, void *) ;
79
80int jack_set_xrun_callback (jack_client_t *, JackXRunCallback xrun_callback, void *arg) ;
81int jack_activate (jack_client_t *client) ;
82int jack_deactivate (jack_client_t *client) ;
83jack_port_t *jack_port_register (jack_client_t *client,
84 const char *port_name,
85 const char *port_type,
86 unsigned long flags,
87 unsigned long buffer_size) ;
88int jack_port_unregister (jack_client_t *, jack_port_t *) ;
89void *jack_port_get_buffer (jack_port_t *, jack_nframes_t) ;
90const char *jack_port_name (const jack_port_t *port) ;
91const char *jack_port_short_name (const jack_port_t *port) ;
92int jack_port_flags (const jack_port_t *port) ;
93const char *jack_port_type (const jack_port_t *port) ;
94
95int jack_port_is_mine (const jack_client_t *, const jack_port_t *port) ;
96
97/**
98 * @return number of connections to or from @a port.
99 *
100 * @pre The calling client must own @a port.
101 */
102int jack_port_connected (const jack_port_t *port);
103
104/**
105 * @return TRUE if the locally-owned @a port is @b directly connected
106 * to the @a port_name.
107 *
108 * @see jack_port_name_size()
109 */
110int jack_port_connected_to (const jack_port_t *port,
111 const char *port_name);
112
113/**
114 * @return a null-terminated array of full port names to which the @a
115 * port is connected. If none, returns NULL.
116 *
117 * The caller is responsible for calling free(3) on any non-NULL
118 * returned value.
119 *
120 * @param port locally owned jack_port_t pointer.
121 *
122 * @see jack_port_name_size(), jack_port_get_all_connections()
123 */
124const char **jack_port_get_connections (const jack_port_t *port);
125
126/**
127 * @return a null-terminated array of full port names to which the @a
128 * port is connected. If none, returns NULL.
129 *
130 * The caller is responsible for calling free(3) on any non-NULL
131 * returned value.
132 *
133 * This differs from jack_port_get_connections() in two important
134 * respects:
135 *
136 * 1) You may not call this function from code that is
137 * executed in response to a JACK event. For example,
138 * you cannot use it in a GraphReordered handler.
139 *
140 * 2) You need not be the owner of the port to get information
141 * about its connections.
142 *
143 * @see jack_port_name_size()
144 */
145const char **jack_port_get_all_connections (const jack_client_t *client,
146 const jack_port_t *port);
147
148/**
149 * A client may call this on a pair of its own ports to
150 * semi-permanently wire them together. This means that
151 * a client that wants to direct-wire an input port to
152 * an output port can call this and then no longer
153 * have to worry about moving data between them. Any data
154 * arriving at the input port will appear automatically
155 * at the output port.
156 *
157 * The 'destination' port must be an output port. The 'source'
158 * port must be an input port. Both ports must belong to
159 * the same client. You cannot use this to tie ports between
160 * clients. That is what a connection is for.
161 *
162 * @return 0 on success, otherwise a non-zero error code
163 */
164int jack_port_tie (jack_port_t *src, jack_port_t *dst);
165
166/**
167 * This undoes the effect of jack_port_tie(). The port
168 * should be same as the 'destination' port passed to
169 * jack_port_tie().
170 *
171 * @return 0 on success, otherwise a non-zero error code
172 */
173int jack_port_untie (jack_port_t *port);
174
175/**
176 * A client may call this function to prevent other objects
177 * from changing the connection status of a port. The port
178 * must be owned by the calling client.
179 *
180 * @return 0 on success, otherwise a non-zero error code
181 */
182int jack_port_lock (jack_client_t *, jack_port_t *);
183
184/**
185 * This allows other objects to change the connection status of a port.
186 *
187 * @return 0 on success, otherwise a non-zero error code
188 */
189int jack_port_unlock (jack_client_t *, jack_port_t *);
190
191/**
192 * @return the time (in frames) between data being available or
193 * delivered at/to a port, and the time at which it arrived at or is
194 * delivered to the "other side" of the port. E.g. for a physical
195 * audio output port, this is the time between writing to the port and
196 * when the signal will leave the connector. For a physical audio
197 * input port, this is the time between the sound arriving at the
198 * connector and the corresponding frames being readable from the
199 * port.
200 */
201jack_nframes_t jack_port_get_latency (jack_port_t *port);
202
203/**
204 * The maximum of the sum of the latencies in every
205 * connection path that can be drawn between the port and other
206 * ports with the @ref JackPortIsTerminal flag set.
207 */
208jack_nframes_t jack_port_get_total_latency (jack_client_t *,
209 jack_port_t *port);
210
211/**
212 * The port latency is zero by default. Clients that control
213 * physical hardware with non-zero latency should call this
214 * to set the latency to its correct value. Note that the value
215 * should include any systemic latency present "outside" the
216 * physical hardware controlled by the client. For example,
217 * for a client controlling a digital audio interface connected
218 * to an external digital converter, the latency setting should
219 * include both buffering by the audio interface *and* the converter.
220 */
221void jack_port_set_latency (jack_port_t *, jack_nframes_t);
222
223/**
224 * Modify a port's short name. May be called at any time. If the
225 * resulting full name (including the @a "client_name:" prefix) is
226 * longer than jack_port_name_size(), it will be truncated.
227 *
228 * @return 0 on success, otherwise a non-zero error code.
229 */
230int jack_port_set_name (jack_port_t *port, const char *port_name);
231
232/**
233 * If @ref JackPortCanMonitor is set for this @a port, turn input
234 * monitoring on or off. Otherwise, do nothing.
235 */
236int jack_port_request_monitor (jack_port_t *port, int onoff);
237
238/**
239 * If @ref JackPortCanMonitor is set for this @a port_name, turn input
240 * monitoring on or off. Otherwise, do nothing.
241 *
242 * @return 0 on success, otherwise a non-zero error code.
243 *
244 * @see jack_port_name_size()
245 */
246int jack_port_request_monitor_by_name (jack_client_t *client,
247 const char *port_name, int onoff);
248
249/**
250 * If @ref JackPortCanMonitor is set for a port, this function turns
251 * on input monitoring if it was off, and turns it off if only one
252 * request has been made to turn it on. Otherwise it does nothing.
253 *
254 * @return 0 on success, otherwise a non-zero error code
255 */
256int jack_port_ensure_monitor (jack_port_t *port, int onoff);
257
258/**
259 * @return TRUE if input monitoring has been requested for @a port.
260 */
261int jack_port_monitoring_input (jack_port_t *port);
262
263/**
264 * Establish a connection between two ports.
265 *
266 * When a connection exists, data written to the source port will
267 * be available to be read at the destination port.
268 *
269 * @pre The port types must be identical.
270 *
271 * @pre The @ref JackPortFlags of the @a source_port must include @ref
272 * JackPortIsOutput.
273 *
274 * @pre The @ref JackPortFlags of the @a destination_port must include
275 * @ref JackPortIsInput.
276 *
277 * @return 0 on success, EEXIST if the connection is already made,
278 * otherwise a non-zero error code
279 */
280int jack_connect (jack_client_t *,
281 const char *source_port,
282 const char *destination_port);
283
284/**
285 * Remove a connection between two ports.
286 *
287 * @pre The port types must be identical.
288 *
289 * @pre The @ref JackPortFlags of the @a source_port must include @ref
290 * JackPortIsOutput.
291 *
292 * @pre The @ref JackPortFlags of the @a destination_port must include
293 * @ref JackPortIsInput.
294 *
295 * @return 0 on success, otherwise a non-zero error code
296 */
297int jack_disconnect (jack_client_t *,
298 const char *source_port,
299 const char *destination_port);
300
301/**
302 * Perform the same function as jack_disconnect() using port handles
303 * rather than names. This avoids the name lookup inherent in the
304 * name-based version.
305 *
306 * Clients connecting their own ports are likely to use this function,
307 * while generic connection clients (e.g. patchbays) would use
308 * jack_disconnect().
309 */
310int jack_port_disconnect (jack_client_t *, jack_port_t *);
311
312/**
313 * @return the maximum number of characters in a full JACK port name
314 * including the final NULL character. This value is a constant.
315 *
316 * A port's full name contains the owning client name concatenated
317 * with a colon (:) followed by its short name and a NULL
318 * character.
319 */
320int jack_port_name_size(void);
321
322/**
323 * @return the maximum number of characters in a JACK port type name
324 * including the final NULL character. This value is a constant.
325 */
326int jack_port_type_size(void);
327
328/**
329 * @return the sample rate of the jack system, as set by the user when
330 * jackd was started.
331 */
332jack_nframes_t jack_get_sample_rate (jack_client_t *);
333
334/**
335 * @return the current maximum size that will ever be passed to the @a
336 * process_callback. It should only be used *before* the client has
337 * been activated. This size may change, clients that depend on it
338 * must register a @a bufsize_callback so they will be notified if it
339 * does.
340 *
341 * @see jack_set_buffer_size_callback()
342 */
343jack_nframes_t jack_get_buffer_size (jack_client_t *);
344
345/**
346 * @param port_name_pattern A regular expression used to select
347 * ports by name. If NULL or of zero length, no selection based
348 * on name will be carried out.
349 * @param type_name_pattern A regular expression used to select
350 * ports by type. If NULL or of zero length, no selection based
351 * on type will be carried out.
352 * @param flags A value used to select ports by their flags.
353 * If zero, no selection based on flags will be carried out.
354 *
355 * @return a NULL-terminated array of ports that match the specified
356 * arguments. The caller is responsible for calling free(3) any
357 * non-NULL returned value.
358 *
359 * @see jack_port_name_size(), jack_port_type_size()
360 */
361const char **jack_get_ports (jack_client_t *,
362 const char *port_name_pattern,
363 const char *type_name_pattern,
364 unsigned long flags);
365
366/**
367 * @return address of the jack_port_t named @a port_name.
368 *
369 * @see jack_port_name_size()
370 */
371jack_port_t *jack_port_by_name (jack_client_t *, const char *port_name);
372
373/**
374 * @return address of the jack_port_t of a @a port_id.
375 */
376jack_port_t *jack_port_by_id (const jack_client_t *client,
377 jack_port_id_t port_id);
378
379/**
380 * Old-style interface to become the timebase for the entire JACK
381 * subsystem.
382 *
383 * @deprecated This function still exists for compatibility with the
384 * earlier transport interface, but it does nothing. Instead, see
385 * transport.h and use jack_set_timebase_callback().
386 *
387 * @return ENOSYS, function not implemented.
388 */
389int jack_engine_takeover_timebase (jack_client_t *);
390
391/**
392 * @return the time in frames that has passed since the JACK server
393 * began the current process cycle.
394 */
395jack_nframes_t jack_frames_since_cycle_start (const jack_client_t *);
396
397/**
398 * @return an estimate of the current time in frames. This is a
399 * running counter, no significance should be attached to its value,
400 * but it can be compared to a previously returned value.
401 */
402jack_nframes_t jack_frame_time (const jack_client_t *);
403
404/**
405 * @return the frame_time after the last processing of the graph
406 * this is only to be used from the process callback.
407 *
408 * This function can be used to put timestamps generated by
409 * jack_frame_time() in correlation to the current process cycle.
410 */
411jack_nframes_t jack_last_frame_time (const jack_client_t *client);
412
413
414/**
415 * @return the current CPU load estimated by JACK. This is a running
416 * average of the time it takes to execute a full process cycle for
417 * all clients as a percentage of the real time available per cycle
418 * determined by the buffer size and sample rate.
419 */
420float jack_cpu_load (jack_client_t *client);
421
422/**
423 * Set the directory in which the server is expected
424 * to have put its communication FIFOs. A client
425 * will need to call this before calling
426 * jack_client_new() if the server was started
427 * with arguments telling it to use a non-standard
428 * directory.
429 *
430 * @deprecated This function is deprecated. Don't use in new programs
431 * and remove it in old programs.
432 */
433void jack_set_server_dir (const char *path);
434
435/**
436 * @return the pthread ID of the thread running the JACK client side
437 * code.
438 */
439pthread_t jack_client_thread_id (jack_client_t *);
440
441/**
442 * Display JACK error message.
443 *
444 * Set via jack_set_error_function(), otherwise a JACK-provided
445 * default will print @a msg (plus a newline) to stderr.
446 *
447 * @param msg error message text (no newline at end).
448 */
449extern void (*jack_error_callback)(const char *msg);
450
451/**
452 * Set the @ref jack_error_callback for error message display.
453 *
454 * The JACK library provides two built-in callbacks for this purpose:
455 * default_jack_error_callback() and silent_jack_error_callback().
456 */
457void jack_set_error_function (void (*func)(const char *));
458__uint64 jack_get_current_transport_frame(void* client) ;
459void jack_transport_stop (void * dummy) ;
460void jack_transport_start (void * dummy) ;
461void jack_transport_locate (void * dummy,int x) ;
462#define JACK_DEFAULT_AUDIO_TYPE 0
463#ifdef __cplusplus
464}
465#endif
466
467#endif /* __jack_h__ */
diff --git a/src/lib/portwin.h b/src/lib/portwin.h
new file mode 100644
index 0000000..14c85b1
--- /dev/null
+++ b/src/lib/portwin.h
@@ -0,0 +1,6 @@
1#ifdef LINUX
2#include <FL/x.H> //dave
3#include <X11/xpm.h> //dave
4
5#endif
6
diff --git a/src/lib/sharedlibs.cpp b/src/lib/sharedlibs.cpp
new file mode 100644
index 0000000..32e5fd8
--- /dev/null
+++ b/src/lib/sharedlibs.cpp
@@ -0,0 +1,332 @@
1#include <sharedlibs.h>
2#include <FL/fl_message.H>
3void SmartLoader::SmartFind(const char* filename,const char* absprogpath,char* result)
4{
5/* Find the given file in a clever way:
6 * Search the given path first
7 * (on the Mac, perhaps recursively)
8 * Then the environment PATH variable
9 * and finally any predefined library paths */
10 result[0]=(char)0;
11 hd24utils::findfile(filename,absprogpath,result);
12 if (strlen(result)!=0)
13 {
14 // found it already
15 return;
16 }
17
18 hd24utils::findfile(filename,getenv("PATH"),result);
19 if (strlen(result)!=0)
20 {
21 // found it already
22 return;
23 }
24
25 hd24utils::findfile(filename,DEFAULTLIBPATH,result);
26 if (strlen(result)!=0)
27 {
28 // found it already
29 return;
30 }
31 return;
32};
33
34PortAudioWrapper::PortAudioWrapper(char* absprogpath)
35{
36 libloaded=false;
37 Pa_Initialize=NULL;
38 Pa_Terminate=NULL;
39 char result[2048];
40 SmartFind(LIBFILE_PORTAUDIO,absprogpath,&result[0]);
41
42 string abslib="";
43 abslib+=result;
44 abslib+=LIBFILE_PORTAUDIO;
45 #if (RECORDERDEBUG==1)
46 cout << "Opening from smartpath: " << abslib.c_str() << endl;
47 #endif
48
49 LIBHANDLE_T* handle=dlopen(abslib.c_str(),RTLD_NOW);
50 if (handle==NULL) {
51 #if (RECORDERDEBUG==1)
52 cout << "Fail. Opening from default path instead." << endl;
53 #endif
54
55 handle=dlopen(LIBFILE_PORTAUDIO,RTLD_NOW);
56 if (handle==NULL) {
57 #if (RECORDERDEBUG==1)
58 cout << dlerror() << endl;
59 #endif
60 } else {
61 #if (RECORDERDEBUG==1)
62 cout << dlerror() << endl;
63 cout << "Defining functions from default path." << endl;
64 #endif
65 define_functions(handle);
66
67 }
68 } else {
69 #if (RECORDERDEBUG==1)
70 cout << "Defining functions from smart path." << endl;
71 #endif
72
73 define_functions(handle);
74 }
75}
76
77PortAudioWrapper::~PortAudioWrapper()
78{
79 if (libhandle!=NULL)
80 {
81 dlclose(libhandle);
82 }
83}
84
85void PortAudioWrapper::define_functions(LIBHANDLE_T* handle)
86{
87 if (handle==NULL) return;
88 libhandle=handle;
89 libloaded=false;
90 // Given a handle to a dynamic library, define functions that are in it.
91
92 #if (RECORDERDEBUG==1)
93 cout << "Define Pa_Initialize..." << endl;
94 #endif
95 Pa_Initialize=(PaError (*)(void))dlsym(handle,"Pa_Initialize");
96
97 if (Pa_Initialize==NULL) { fl_message("Error loading Pa_Initialize"); return; }
98 #if (RECORDERDEBUG==1)
99 cout << "Define Pa_Terminate..." << endl;
100 #endif
101
102
103 Pa_Terminate=(PaError (*)(void))dlsym(handle,"Pa_Terminate");
104 if (Pa_Terminate==NULL) { fl_message("Error loading Pa_Terminate"); return; }
105
106 #if (RECORDERDEBUG==1)
107 cout << "Define Pa_StartStream..." << endl;
108 #endif
109
110 Pa_StartStream=(PaError (*)(PaStream*))dlsym(handle,"Pa_StartStream");
111 if (Pa_StartStream==NULL) { fl_message("Error loading Pa_StartStream"); return; }
112
113 #if (RECORDERDEBUG==1)
114 cout << "Define Pa_StopStream..." << endl;
115 #endif
116
117 Pa_StopStream=(PaError (*)(PaStream*))dlsym(handle,"Pa_StopStream");
118 if (Pa_StopStream==NULL) { fl_message("Error loading Pa_StopStream"); return; }
119
120 #if (RECORDERDEBUG==1)
121 cout << "Define Pa_AbortStream..." << endl;
122 #endif
123
124 Pa_AbortStream=(PaError (*)(PaStream*))dlsym(handle,"Pa_AbortStream");
125 if (Pa_AbortStream==NULL) { fl_message("Error loading Pa_AbortStream"); return; }
126
127 #if (RECORDERDEBUG==1)
128 cout << "Define Pa_CloseStream..." << endl;
129 #endif
130
131 Pa_CloseStream=(PaError (*)(PaStream*))dlsym(handle,"Pa_CloseStream");
132 if (Pa_CloseStream==NULL) { fl_message("Error loading Pa_CloseStream"); return; }
133
134 #if (RECORDERDEBUG==1)
135 cout << "Define Pa_GetStreamTime..." << endl;
136 #endif
137
138 Pa_GetStreamTime=(PaTime (*)(PaStream*))dlsym(handle,"Pa_GetStreamTime");
139 if (Pa_GetStreamTime==NULL) { fl_message("Error loading Pa_GetStreamTime"); return; }
140
141 #if (RECORDERDEBUG==1)
142 cout << "Define Pa_StreamActive..." << endl;
143 #endif
144
145 Pa_StreamActive=(PaError (*)(PaStream*))dlsym(handle,"Pa_IsStreamActive");
146 if (Pa_StreamActive==NULL) {
147 Pa_StreamActive=(PaError (*)(PaStream*))dlsym(handle,"Pa_StreamActive");
148 }
149 if (Pa_StreamActive==NULL) {
150 fl_message("Error loading Pa_StreamActive"); return;
151 }
152
153 #if (RECORDERDEBUG==1)
154 cout << "Define Pa_OpenStream..." << endl;
155 #endif
156 Pa_OpenStream=(PaError (*)(PaStream**,
157 const PaStreamParameters*,
158 const PaStreamParameters*,
159 double,
160 unsigned long,
161 PaStreamFlags,
162 PaStreamCallback*,
163 void*))dlsym(handle,"Pa_OpenStream");
164
165 if (Pa_OpenStream==NULL) { fl_message("Error loading Pa_OpenStream"); return; }
166
167 #if (RECORDERDEBUG==1)
168 cout << "Define Pa_GetDeviceCount..." << endl;
169 #endif
170
171 Pa_GetDeviceCount=(int (*)(void))dlsym(handle,"Pa_GetDeviceCount");
172 if (Pa_GetDeviceCount==NULL) { fl_message("Error loading Pa_GetDeviceCount"); return; }
173
174 #if (RECORDERDEBUG==1)
175 cout << "Define Pa_GetDeviceInfo..." << endl;
176 #endif
177
178 Pa_GetDeviceInfo=(const PaDeviceInfo* (*)(int))dlsym(handle,"Pa_GetDeviceInfo");
179 if (Pa_GetDeviceInfo==NULL) { fl_message("Error loading Pa_GetDeviceInfo"); return; }
180
181 #if (RECORDERDEBUG==1)
182 cout << "Define Pa_GetDefaultInputDevice..." << endl;
183 #endif
184
185 Pa_GetDefaultInputDevice=(PaDeviceIndex (*)(void))dlsym(handle,"Pa_GetDefaultInputDevice");
186 if (Pa_GetDefaultInputDevice==NULL) { fl_message("Error loading Pa_GetDefaultInputDevice"); return; }
187
188 #if (RECORDERDEBUG==1)
189 cout << "Define Pa_GetDefaultOutputDevice..." << endl;
190 #endif
191
192 Pa_GetDefaultOutputDevice=(PaDeviceIndex (*)(void))dlsym(handle,"Pa_GetDefaultOutputDevice");
193 if (Pa_GetDefaultOutputDevice==NULL) { fl_message("Error loading Pa_GetDefaultOutputDevice"); return; }
194
195 #if (RECORDERDEBUG==1)
196 cout << "Define Pa_GetVersionText..." << endl;
197 #endif
198
199 Pa_GetVersionText=(const char* (*)(void))dlsym(handle,"Pa_GetVersionText");
200
201 #if (RECORDERDEBUG==1)
202 cout << "Define Pa_GetErrorText..." << endl;
203 #endif
204
205 Pa_GetErrorText=(const char* (*)(PaError))dlsym(handle,"Pa_GetErrorText");
206
207 #if (RECORDERDEBUG==1)
208 PaError initerror=(*(this->Pa_Initialize))();
209 cout << "initerror=" <<initerror << endl;
210 cout << "Portaudio version=" << (*(this->Pa_GetVersionText))() << endl;
211 #endif
212
213 #if (RECORDERDEBUG==1)
214 int devcount=(*(this->Pa_GetDeviceCount))();
215 cout << "Portaudio Device count=" << devcount << endl;
216 cout << "Default Portaudio Input Device =" << (*(this->Pa_GetDefaultInputDevice))() << endl;
217 cout << "Default Portaudio Output Device =" << (*(this->Pa_GetDefaultOutputDevice))() << endl;
218 #endif
219
220 libloaded=true;
221}
222
223SoundFileWrapper::SoundFileWrapper(char* absprogpath)
224{
225 sf_open=NULL;
226 sf_close=NULL;
227 libloaded=false;
228
229 char result[2048];
230// TODO: Was there a reason why this said PORTAUDIO?
231// SmartFind(LIBFILE_PORTAUDIO,absprogpath,&result[0]);
232 SmartFind(LIBFILE_SNDFILE,absprogpath,&result[0]);
233
234 string abslib="";
235 abslib+=result;
236 abslib+=LIBFILE_SNDFILE;
237 LIBHANDLE_T* handle=dlopen(abslib.c_str(),RTLD_NOW);
238 if (handle==NULL) {
239 fl_message("%s",dlerror());
240 }
241 if (handle==NULL) {
242 handle=dlopen(LIBFILE_SNDFILE,RTLD_NOW);
243 if (handle==NULL) {
244 fl_message("%s",dlerror());
245 } else {
246 define_functions(handle);
247 }
248 } else {
249 define_functions(handle);
250 }
251}
252
253SoundFileWrapper::~SoundFileWrapper()
254{
255 if (libhandle!=NULL)
256 {
257 dlclose(libhandle);
258 }
259
260}
261
262void SoundFileWrapper::define_functions(LIBHANDLE_T* handle)
263{
264 if (handle==NULL) return;
265 libhandle=handle;
266 // Given a handle to a dynamic library, define functions that are in it.
267 sf_open=(SNDFILE*(*)(const char*,int,SF_INFO*))dlsym(handle,"sf_open");
268 if (sf_open==NULL) {
269 fl_message("Unable to load libsndfile, file transfers won't work.");
270 }
271 sf_close=(int(*)(SNDFILE*))dlsym(handle,"sf_close");
272 sf_read_int=(sf_count_t(*)(SNDFILE*,int*,sf_count_t))dlsym(handle,"sf_read_int");
273 sf_write_raw=(sf_count_t(*)(SNDFILE*,const void*,sf_count_t))dlsym(handle,"sf_write_raw");
274 sf_write_float=(sf_count_t(*)(SNDFILE*,const void*,sf_count_t))dlsym(handle,"sf_write_float");
275 if (sf_open!=NULL) {
276 libloaded=true;
277 }
278}
279
280JackWrapper::JackWrapper(char* absprogpath)
281{
282 libloaded=false;
283 char result[2048];
284// TODO: Was there a reason why this said PORTAUDIO?
285// SmartFind(LIBFILE_PORTAUDIO,absprogpath,&result[0]);
286 SmartFind(LIBFILE_JACK,absprogpath,&result[0]);
287
288 string abslib="";
289 abslib+=result;
290 abslib+=LIBFILE_JACK;
291 LIBHANDLE_T* handle=dlopen(abslib.c_str(),RTLD_NOW);
292 if (handle==NULL) {
293 handle=dlopen(LIBFILE_JACK,RTLD_NOW);
294 if (handle==NULL) {
295 // cout << dlerror() << endl;
296 } else {
297 define_functions(handle);
298 }
299 } else {
300 define_functions(handle);
301 }
302}
303
304JackWrapper::~JackWrapper()
305{
306 if (libhandle!=NULL)
307 {
308 dlclose(libhandle);
309 }
310
311}
312
313void JackWrapper::define_functions(LIBHANDLE_T* handle)
314{
315 if (handle==NULL) return;
316 libhandle=handle;
317 // Given a handle to a dynamic library, define functions that are in it.
318 jack_client_new=(jack_client_t*(*)(const char*))dlsym(handle,"jack_client_new");
319 jack_set_process_callback=(int(*)(jack_client_t*,JackProcessCallback,void*))dlsym(handle,"jack_set_process_callback");
320 jack_on_shutdown=(void (*)(jack_client_t*,void (*function)(void *), void *))dlsym(handle,"jack_on_shutdown");
321 jack_get_sample_rate=(jack_nframes_t (*)(jack_client_t*))dlsym(handle,"jack_get_sample_rate");
322 jack_port_get_buffer=(void* (*)(jack_port_t*,jack_nframes_t))dlsym(handle,"jack_port_get_buffer");
323 jack_transport_query=(jack_transport_state_t (*)(const jack_client_t*,jack_position_t*))dlsym(handle,"jack_transport_query");
324 jack_port_register=(jack_port_t* (*)(jack_client_t*,const char*,const char*,unsigned long,unsigned long))dlsym(handle,"jack_port_register");
325 jack_activate=(int (*)(jack_client_t*))dlsym(handle,"jack_activate");
326 jack_get_current_transport_frame=(jack_nframes_t (*)(const jack_client_t*))dlsym(handle,"jack_get_current_transport_frame");
327 jack_transport_locate=(int (*)(jack_client_t*,jack_nframes_t))dlsym(handle,"jack_transport_locate");
328 jack_transport_start=(void (*)(jack_client_t*))dlsym(handle,"jack_transport_start");
329 jack_transport_stop=(void (*)(jack_client_t*))dlsym(handle,"jack_transport_stop");
330 libloaded=true;
331}
332
diff --git a/src/lib/sharedlibs.h b/src/lib/sharedlibs.h
new file mode 100644
index 0000000..325e301
--- /dev/null
+++ b/src/lib/sharedlibs.h
@@ -0,0 +1,88 @@
1#ifndef __sharedlibs_h__
2#define __sharedlibs_h__
3
4#include <xplat_dlfcn.h>
5#include <soundlibs.h>
6#include <sndfile.h>
7#include <hd24utils.h>
8
9class SmartLoader
10{
11public:
12 void SmartFind(const char* filename,const char* absprogpath,char* result);
13};
14
15class PortAudioWrapper:SmartLoader
16{
17/* This class dynamically smart-loads the portaudio library, if available */
18private:
19
20 char libloadedstring[1024];
21
22public:
23
24 PaError (*Pa_Initialize)(void);
25 PaError (*Pa_Terminate)(void);
26 PaError (*Pa_StartStream)(PaStream*);
27 PaError (*Pa_StopStream)(PaStream*);
28 PaError (*Pa_AbortStream)(PaStream*);
29 PaError (*Pa_CloseStream)(PaStream*);
30 PaError (*Pa_StreamActive)(PaStream*);
31 PaTime (*Pa_GetStreamTime)(PaStream*);
32 PaError (*Pa_OpenStream)(PaStream **stream,const PaStreamParameters *inputParameters,const PaStreamParameters *outputParameters,double sampleRate,unsigned long framesPerBuffer,PaStreamFlags streamFlags,PaStreamCallback *streamCallback,void* userData);
33 int (*Pa_GetDefaultInputDevice)(void);
34 int (*Pa_GetDefaultOutputDevice)(void);
35 int (*Pa_GetDeviceCount)(void);
36 const char* (*Pa_GetVersionText)(void);
37 const char* (*Pa_GetErrorText)(PaError ErrorCode);
38 const PaDeviceInfo* (*Pa_GetDeviceInfo)(int);
39
40 void define_functions(LIBHANDLE_T* handle);
41 PortAudioWrapper(char* absprogpath);
42 ~PortAudioWrapper();
43 int libloaded;
44 void* libhandle;
45
46};
47
48class SoundFileWrapper:SmartLoader
49{
50public:
51 /* This class dynamically smart-loads libsndfile, if available */
52 SNDFILE* (*sf_open)(const char*,int,SF_INFO*);
53 int (*sf_close)(SNDFILE*);
54 sf_count_t (*sf_read_int)(SNDFILE*,int*,sf_count_t);
55 sf_count_t (*sf_write_raw)(SNDFILE*,const void*,sf_count_t);
56 sf_count_t (*sf_write_float)(SNDFILE*,const void*,sf_count_t);
57 void define_functions(LIBHANDLE_T* handle);
58 SoundFileWrapper(char* absprogpath);
59 ~SoundFileWrapper();
60 int libloaded;
61 void* libhandle;
62};
63
64class JackWrapper:SmartLoader
65{
66public:
67 jack_client_t* (*jack_client_new)(const char*);
68 int (*jack_set_process_callback)(jack_client_t*,JackProcessCallback,void*);
69 void (*jack_on_shutdown)(jack_client_t*,void (*function)(void *), void *);
70 jack_nframes_t (*jack_get_sample_rate)(jack_client_t*);
71 void* (*jack_port_get_buffer)(jack_port_t*,jack_nframes_t);
72
73 jack_transport_state_t (*jack_transport_query)(const jack_client_t*,jack_position_t*);
74 jack_port_t* (*jack_port_register)(jack_client_t*,const char*,const char*,unsigned long,unsigned long);
75 int (*jack_activate)(jack_client_t*);
76 jack_nframes_t (*jack_get_current_transport_frame)(const jack_client_t*);
77 int (*jack_transport_locate)(jack_client_t*,jack_nframes_t);
78 void (*jack_transport_start)(jack_client_t*);
79 void (*jack_transport_stop)(jack_client_t*);
80 void define_functions(LIBHANDLE_T* handle);
81 JackWrapper(char* absprogpath);
82 ~JackWrapper();
83 int libloaded;
84 void* libhandle;
85
86};
87
88#endif
diff --git a/src/lib/smpte.cpp b/src/lib/smpte.cpp
new file mode 100644
index 0000000..537834c
--- /dev/null
+++ b/src/lib/smpte.cpp
@@ -0,0 +1,221 @@
1#include "smpte.h"
2#include "memutils.h"
3#define SMPTE_DEBUG 0
4SMPTEgenerator::SMPTEgenerator(__uint32 p_samplerate)
5{
6#if (SMPTE_DEBUG==1)
7 cout << "Construct SMPTE generator with samrate=" << p_samplerate << endl;
8#endif
9// this->lastframe=-1;
10 this->prevbitnum=-1;
11 this->prevhalfbit=-1;
12 this->haveframe=0;
13 this->prevoutval=0;
14 this->framerate=30; // 30 is default for HD24.
15 this->bitsperframe=80;
16 this->nondrop=1;
17 this->setsamplerate(p_samplerate);
18 this->smpteword=(short*)memutils::mymalloc("smptegenerator::smptegenerator",80,sizeof(short));
19 // pre-fill sync word
20 for (int i=0;i<64;i++)
21 {
22 this->smpteword[i]=0;
23 }
24 this->smpteword[64]=0;
25 this->smpteword[65]=0;
26 this->smpteword[66]=1;
27 this->smpteword[67]=1;
28 this->smpteword[68]=1;
29 this->smpteword[69]=1;
30 this->smpteword[70]=1;
31 this->smpteword[71]=1;
32 this->smpteword[72]=1;
33 this->smpteword[73]=1;
34 this->smpteword[74]=1;
35 this->smpteword[75]=1;
36 this->smpteword[76]=1;
37 this->smpteword[77]=1;
38 this->smpteword[78]=0;
39 this->smpteword[79]=1;
40}
41
42SMPTEgenerator::~SMPTEgenerator()
43{
44 if (this==NULL)
45 {
46 return;
47 }
48 if (smpteword==NULL)
49 {
50 return;
51 }
52 memutils::myfree("SMPTE",smpteword);
53 smpteword=NULL;
54}
55void SMPTEgenerator::recalcrates()
56{
57
58 this->bitspersecond=bitsperframe*framerate;
59
60}
61
62void SMPTEgenerator::setsamplerate(__uint32 p_samplerate)
63{
64 this->samplerate=p_samplerate;
65 this->recalcrates();
66 return;
67}
68
69void SMPTEgenerator::setframerate(__uint32 p_framerate)
70{
71 this->framerate=p_framerate;
72 this->recalcrates();
73}
74
75void SMPTEgenerator::fillword(int hour,int minute,int second,int frame)
76{
77#if (SMPTE_DEBUG==1)
78 cout << "fill word for "
79 << hour << ":" << minute << ":" << second <<"."<<frame << endl;
80#endif
81 int frameunits=(frame%10);
82 int frametens=(int)((frame-frameunits)/10);
83
84 int secondsunits=(second%10);
85 int secondstens=(int)((second-secondsunits)/10);
86
87 int minuteunits=(minute%10);
88 int minutetens=(int)((minute-minuteunits)/10);
89
90 int hourunits=(hour%10);
91 int hourtens=(int)((hour-hourunits)/10);
92
93
94 this->smpteword[0]=((frameunits ) & 1);
95 this->smpteword[1]=((frameunits>>1) & 1);
96 this->smpteword[2]=((frameunits>>2) & 1);
97 this->smpteword[3]=((frameunits>>3) & 1);
98// this->smpteword[4]=0;
99// this->smpteword[5]=0;
100// this->smpteword[6]=0;
101// this->smpteword[7]=0;
102 this->smpteword[8]=((frametens) & 1);
103 this->smpteword[9]=((frametens>>1) & 1);
104// this->smpteword[10]=0;
105// this->smpteword[11]=0;
106// this->smpteword[12]=0;
107// this->smpteword[13]=0;
108// this->smpteword[14]=0;
109// this->smpteword[15]=0;
110 this->smpteword[16]=((secondsunits ) & 1);
111 this->smpteword[17]=((secondsunits>>1) & 1);
112 this->smpteword[18]=((secondsunits>>2) & 1);
113 this->smpteword[19]=((secondsunits>>3) & 1);
114// this->smpteword[20]=0;
115// this->smpteword[21]=0;
116// this->smpteword[22]=0;
117// this->smpteword[23]=0;
118 this->smpteword[24]=((secondstens )&1);
119 this->smpteword[25]=((secondstens>>1)&1);
120 this->smpteword[26]=((secondstens>>2)&1);
121 this->smpteword[27]=0; // is biphasemark, filled in later
122 // but reset here to prevent its influence
123
124// this->smpteword[28]=0;
125// this->smpteword[29]=0;
126// this->smpteword[30]=0;
127// this->smpteword[31]=0;
128 this->smpteword[32]=((minuteunits ) & 1);
129 this->smpteword[33]=((minuteunits>>1) & 1);
130 this->smpteword[34]=((minuteunits>>2) & 1);
131 this->smpteword[35]=((minuteunits>>3) & 1);
132// this->smpteword[36]=0;
133// this->smpteword[37]=0;
134// this->smpteword[38]=0;
135// this->smpteword[39]=0;
136 this->smpteword[40]=((minutetens ) & 1);
137 this->smpteword[41]=((minutetens>>1) & 1);
138 this->smpteword[42]=((minutetens>>2) & 1);
139// this->smpteword[43]=0; # binary group flag bit
140// this->smpteword[44]=0;
141// this->smpteword[45]=0;
142// this->smpteword[46]=0;
143// this->smpteword[47]=0;
144 this->smpteword[48]=((hourunits )&1);
145 this->smpteword[49]=((hourunits>>1)&1);
146 this->smpteword[50]=((hourunits>>2)&1);
147 this->smpteword[51]=((hourunits>>3)&1);
148// this->smpteword[52]=0;
149// this->smpteword[53]=0;
150// this->smpteword[54]=0;
151// this->smpteword[55]=0;
152 this->smpteword[56]=((hourtens )&1);
153 this->smpteword[57]=((hourtens>>1)&1);
154// this->smpteword[58]=0; // reserved, must be 0
155// this->smpteword[59]=0; // binary group flag bit
156// this->smpteword[60]=0;
157// this->smpteword[61]=0;
158// this->smpteword[62]=0;
159// this->smpteword[63]=0;
160
161 // sync word already set in constructor
162 unsigned parity = 0;
163 for (int i=0; i<80; ++i) {
164 parity += this->smpteword[i];
165 }
166 this->smpteword[27] = (parity & 1);
167#if (SMPTE_DEBUG==1)
168 for (int i=0;i<80;i++)
169 {
170 cout << this->smpteword[i];
171 }
172 cout << endl;
173#endif
174 return;
175
176}
177int SMPTEgenerator::modulate(int currbitval,int bitnum,int halfbit)
178{
179 if ((bitnum!=this->prevbitnum) || ((halfbit!=this->prevhalfbit) && (currbitval==1)))
180 {
181 this->prevoutval=1-(this->prevoutval);
182 }
183 this->prevbitnum=bitnum;
184 this->prevhalfbit=halfbit;
185 return this->prevoutval;
186}
187
188int SMPTEgenerator::getbit(__uint32 insamnum)
189{
190
191 this->samplesperbit=(int)((this->samplerate)/this->bitspersecond);
192 this->samplesperframe=(int)((this->samplerate)/framerate);
193
194 __uint32 sampleinsecond=insamnum % this->samplerate;
195 __uint32 currentsecond=(insamnum-sampleinsecond)/(this->samplerate);
196 __uint32 currenthour=int(currentsecond/3600);
197 currentsecond-=3600*currenthour;
198 __uint32 currentminute=int(currentsecond/60);
199 currentsecond-=60*currentminute;
200
201 __uint32 currentframe=(int)(sampleinsecond/this->samplesperframe);
202 __uint32 sampleinframe=sampleinsecond-(currentframe*this->samplesperframe);
203 __uint32 bitinframe=(int)(sampleinframe/this->samplesperbit);
204 __uint32 subbit=(int)(sampleinframe-(bitinframe*this->samplesperbit));
205 __uint32 halfbit=(this->samplesperbit/2);
206 if ((bitinframe==0)&&(subbit==0))
207 {
208 this->haveframe=0;
209 }
210 if (this->haveframe==0)
211 {
212 this->fillword(currenthour,currentminute,currentsecond,currentframe);
213 this->haveframe=1;
214 }
215
216 if (subbit<halfbit) {
217 return this->modulate(smpteword[bitinframe],bitinframe,0);
218 }
219 return this->modulate(smpteword[bitinframe],bitinframe,1);
220}
221
diff --git a/src/lib/smpte.h b/src/lib/smpte.h
new file mode 100644
index 0000000..fdaef3a
--- /dev/null
+++ b/src/lib/smpte.h
@@ -0,0 +1,41 @@
1#ifndef __smpte_h__
2#define __smpte_h__
3
4using namespace std;
5#include "config.h"
6#include <string>
7#include <iostream>
8
9class SMPTEgenerator
10{
11 private:
12
13 short* smpteword;
14 int prevbitnum;
15 int prevhalfbit;
16 int prevoutval;
17 int framerate;
18 int nondrop;
19 int haveframe; // indicates if a new frame word must be generated
20 int samplerate;
21
22 /* These are pre-calculated: */
23 int bitsperframe;
24 int bitspersecond;
25 int samplesperbit;
26 int samplesperframe;
27 void recalcrates();
28 void fillword(int hour,int min,int sec,int frame);
29
30 void setsamplerate(__uint32 p_samplerate);
31 void setframerate(__uint32 p_samplerate);
32
33 int modulate(int currbitval,int bitnum,int halfbit);
34 public:
35 SMPTEgenerator(__uint32 p_samplerate);
36 ~SMPTEgenerator();
37 int getbit(__uint32 insamnum);
38
39};
40
41#endif
diff --git a/src/lib/soundlibs.h b/src/lib/soundlibs.h
new file mode 100644
index 0000000..faa7231
--- /dev/null
+++ b/src/lib/soundlibs.h
@@ -0,0 +1,15 @@
1#ifdef LIBJACK
2# include <jack/jack.h>
3# include <jack/transport.h>
4#else
5# include "../lib/nojack.h"
6#endif
7
8#ifdef LIBPORTAUDIO
9# include "portaudio.h"
10# define portaudiostreamtype PaStream
11#else
12# define portaudiostreamtype void
13# define PaTime unsigned long
14#endif
15
diff --git a/src/lib/xplat_dlfcn.h b/src/lib/xplat_dlfcn.h
new file mode 100644
index 0000000..3b1c98c
--- /dev/null
+++ b/src/lib/xplat_dlfcn.h
@@ -0,0 +1,12 @@
1#ifdef WINDOWS
2 #include <windows.h>
3 #define dlopen(a,b) LoadLibrary(a)
4 #define dlsym(a,b) GetProcAddress(a,b)
5 #define dlclose(a) /* CloseLibrary(a) */
6 #define dlerror() "Error loading library"
7 #define LIBHANDLE_T HINSTANCE__
8#else
9 #include <dlfcn.h>
10 #define LIBHANDLE_T void
11#endif
12
diff --git a/src/test/co b/src/test/co
new file mode 100755
index 0000000..d6216bf
--- /dev/null
+++ b/src/test/co
@@ -0,0 +1,2 @@
1#!/bin/bash
2g++ -O3 portaudiotest.cpp -l portaudio -o portaudiotest
diff --git a/src/test/portaudiotest.cpp b/src/test/portaudiotest.cpp
new file mode 100644
index 0000000..58f6cac
--- /dev/null
+++ b/src/test/portaudiotest.cpp
@@ -0,0 +1,158 @@
1using namespace std;
2#include <iostream>
3#include <portaudio.h>
4#include "portaudiotest.h"
5#define PA_FRAMESPERBUF 512
6#define __uint32 unsigned long
7
8int HD24UserInterface::portaudio_process(
9 const void *inputBuffer,
10 void *outputBuffer,
11 __uint32 nframes,
12 const PaStreamCallbackTimeInfo* timeinfo,
13 PaStreamCallbackFlags,
14 void *userData)
15{
16 HD24UserInterface* mythis=(HD24UserInterface*)userData;
17 if (!mythis->havestreamtime)
18 {
19 mythis->streamtime=0;
20 mythis->timeoffset=timeinfo->currentTime;
21 mythis->havestreamtime=true;
22 }
23 mythis->streamtime+=nframes;
24 cout << ((mythis->streamtime)/48000) << " nframes=" << nframes <<" streamtime=" << timeinfo->currentTime-(mythis->timeoffset) << endl;
25 float sval=1;
26 for (int i=0;i<nframes;i++)
27 {
28 if ((i%16)==0) sval=-sval;
29 ((float*)(outputBuffer))[i]=sval;
30 }
31 return paContinue;
32}
33
34
35void HD24UserInterface::portaudioinit()
36{
37 cout << "portaudioinit" << endl;
38 PaError err;
39 inputParameters=new PaStreamParameters;
40 outputParameters=new PaStreamParameters;
41 err=Pa_Initialize();
42 if (err!=paNoError)
43 {
44 Pa_Terminate();
45 return;
46 }
47 m_isportaudioinitialized=true;
48}
49
50HD24UserInterface::HD24UserInterface()
51{
52 m_isportaudioinitialized=false;
53 portaudiostream=NULL;
54 return;
55}
56
57bool HD24UserInterface::isportaudioinitialized()
58{
59 return m_isportaudioinitialized;
60}
61
62void HD24UserInterface::portaudio_transport_start()
63{
64
65 cout << "portaudio transport start" << endl;
66
67 if (!isportaudioinitialized())
68 {
69 PaError err=Pa_Initialize();
70 if (err != paNoError)
71 {
72 cout << "Cannot initialize portaudio- exiting." << endl;
73 }
74 }
75
76 if (isportaudioinitialized() && (portaudiostream!=NULL))
77 {
78 cout << "already have stream- done starting" << endl;
79 return;
80 }
81
82 PaDeviceIndex indevice=Pa_GetDefaultInputDevice();
83 bzero(inputParameters,sizeof(*inputParameters));
84 inputParameters->device=indevice;
85 inputParameters->channelCount=1;
86 inputParameters->sampleFormat=paFloat32;
87 inputParameters->suggestedLatency = Pa_GetDeviceInfo( inputParameters->device )->defaultLowInputLatency;
88 inputParameters->hostApiSpecificStreamInfo = NULL;
89
90 cout << "Input params set" << endl;
91 cout << "Device=" << inputParameters->device << endl;
92 cout << "Channelcount=" << inputParameters->channelCount << endl;
93 cout << "sampleFormat=" << inputParameters->sampleFormat << endl;
94 cout << "suggestedlatency=" << inputParameters->suggestedLatency << endl;
95 cout << "================================="<<endl;
96 bzero(outputParameters,sizeof(*outputParameters));
97 PaDeviceIndex outdevice=Pa_GetDefaultOutputDevice();
98 outputParameters->device=outdevice;
99 outputParameters->channelCount=1;
100 outputParameters->sampleFormat=paFloat32;
101 outputParameters->suggestedLatency = Pa_GetDeviceInfo( outputParameters->device )->defaultLowOutputLatency;
102 outputParameters->hostApiSpecificStreamInfo = NULL;
103
104 cout << "Output params set" << endl;
105 cout << "Device=" << outputParameters->device << endl;
106 cout << "Channelcount=" << outputParameters->channelCount << endl;
107 cout << "sampleFormat=" << outputParameters->sampleFormat << endl;
108 cout << "suggestedlatency=" << outputParameters->suggestedLatency << endl;
109 cout << "================================="<<endl;
110
111 double samrate=48000;
112 cout << "trying samerate="<<samrate<<endl;
113 cout << "framesperbuf=" << PA_FRAMESPERBUF << endl;
114
115 PaError err=Pa_OpenStream(
116 &portaudiostream,
117 this->inputParameters,
118 this->outputParameters,
119 samrate,
120 PA_FRAMESPERBUF, /* frames per buffer */
121 paClipOff | paDitherOff,
122 portaudio_process,
123 (void*)this);
124 this->havestreamtime=false;
125
126 if (err!=paNoError)
127 {
128 cout << "Error opening stream" << endl;
129 Pa_Terminate();
130 return;
131 }
132
133 cout << "Stream opened, going to start it now..." << endl;
134
135 err=Pa_StartStream(portaudiostream);
136
137 if (err!=paNoError)
138 {
139 cout << "Error starting stream" << endl;
140 Pa_Terminate();
141 return;
142 }
143
144 cout << "Stream started" << endl;
145
146 return;
147}
148
149int main()
150{
151 HD24UserInterface* ui=new HD24UserInterface();
152 ui->portaudioinit();
153 ui->portaudio_transport_start();
154 int blah;
155 cin >> blah;
156
157}
158
diff --git a/src/test/portaudiotest.h b/src/test/portaudiotest.h
new file mode 100644
index 0000000..f3dbe32
--- /dev/null
+++ b/src/test/portaudiotest.h
@@ -0,0 +1,33 @@
1#ifndef __portaudiotest_h__
2#define __portaudiotest_h__
3#ifndef __uint32
4#define __uint32 unsigned long
5#endif
6class HD24UserInterface
7{
8private:
9 PaStream* portaudiostream;
10 bool m_isportaudioinitialized;
11 bool havestreamtime;
12 PaTime streamtime;
13 PaTime timeoffset;
14 static int portaudio_process
15 (
16 const void *inputBuffer,
17 void *outputBuffer,
18 __uint32 nframes,
19 const PaStreamCallbackTimeInfo* timeinfo,
20 PaStreamCallbackFlags,
21 void *userData
22 );
23
24 PaStreamParameters* inputParameters;
25 PaStreamParameters* outputParameters;
26public:
27 HD24UserInterface();
28 bool isportaudioinitialized();
29 void portaudioinit();
30 void portaudio_transport_start();
31};
32
33#endif
diff --git a/src/test/portaudiotestold.cpp b/src/test/portaudiotestold.cpp
new file mode 100644
index 0000000..954c64e
--- /dev/null
+++ b/src/test/portaudiotestold.cpp
@@ -0,0 +1,157 @@
1using namespace std;
2#include <iostream>
3#include <portaudio.h>
4#include "portaudiotest.h"
5#define PA_FRAMESPERBUF 512
6#define __uint32 unsigned long
7
8int HD24UserInterface::portaudio_process(
9 const void *inputBuffer,
10 void *outputBuffer,
11 __uint32 nframes,
12 const PaStreamCallbackTimeInfo* timeinfo,
13 PaStreamCallbackFlags,
14 void *userData)
15{
16 HD24UserInterface* mythis=(HD24UserInterface*)userData;
17 const PaStreamInfo* streaminfo=Pa_GetStreamInfo(mythis->portaudiostream);
18 double samplerate=streaminfo->sampleRate;
19 if (!mythis->havestreamtime)
20 {
21 mythis->streamtime=0;
22 mythis->havestreamtime=true;
23 }
24 mythis->streamtime+=nframes;
25 for (int i=0;i<nframes*2;i++)
26 {
27 float sval=(((i%20)/20)-.5);
28 ((float*)(outputBuffer))[i]=sval;
29 }
30 return paContinue;
31}
32
33
34void HD24UserInterface::portaudioinit()
35{
36 cout << "portaudioinit" << endl;
37 PaError err;
38 inputParameters=new PaStreamParameters;
39 outputParameters=new PaStreamParameters;
40 err=Pa_Initialize();
41 if (err!=paNoError)
42 {
43 Pa_Terminate();
44 return;
45 }
46 m_isportaudioinitialized=true;
47}
48
49HD24UserInterface::HD24UserInterface()
50{
51 m_isportaudioinitialized=false;
52 portaudiostream=NULL;
53 return;
54}
55
56bool HD24UserInterface::isportaudioinitialized()
57{
58 return m_isportaudioinitialized;
59}
60
61void HD24UserInterface::portaudio_transport_start()
62{
63
64 cout << "portaudio transport start" << endl;
65
66 if (!isportaudioinitialized())
67 {
68 PaError err=Pa_Initialize();
69 if (err != paNoError)
70 {
71 cout << "Cannot initialize portaudio- exiting." << endl;
72 }
73 }
74
75 if (isportaudioinitialized() && (portaudiostream!=NULL))
76 {
77 cout << "already have stream- done starting" << endl;
78 return;
79 }
80
81 PaDeviceIndex indevice=Pa_GetDefaultInputDevice();
82 bzero(inputParameters,sizeof(*inputParameters));
83 inputParameters->device=indevice;
84 inputParameters->channelCount=1;
85 inputParameters->sampleFormat=paFloat32;
86 inputParameters->suggestedLatency = Pa_GetDeviceInfo( inputParameters->device )->defaultLowInputLatency;
87 inputParameters->hostApiSpecificStreamInfo = NULL;
88
89 cout << "Input params set" << endl;
90 cout << "Device=" << inputParameters->device << endl;
91 cout << "Channelcount=" << inputParameters->channelCount << endl;
92 cout << "sampleFormat=" << inputParameters->sampleFormat << endl;
93 cout << "suggestedlatency=" << inputParameters->suggestedLatency << endl;
94 cout << "================================="<<endl;
95 bzero(outputParameters,sizeof(*outputParameters));
96 PaDeviceIndex outdevice=Pa_GetDefaultOutputDevice();
97 outputParameters->device=outdevice;
98 outputParameters->channelCount=1;
99 outputParameters->sampleFormat=paFloat32;
100 outputParameters->suggestedLatency = Pa_GetDeviceInfo( outputParameters->device )->defaultLowOutputLatency;
101 outputParameters->hostApiSpecificStreamInfo = NULL;
102
103 cout << "Output params set" << endl;
104 cout << "Device=" << outputParameters->device << endl;
105 cout << "Channelcount=" << outputParameters->channelCount << endl;
106 cout << "sampleFormat=" << outputParameters->sampleFormat << endl;
107 cout << "suggestedlatency=" << outputParameters->suggestedLatency << endl;
108 cout << "================================="<<endl;
109
110 double samrate=44100;
111 cout << "trying samerate="<<samrate<<endl;
112 cout << "framesperbuf=" << PA_FRAMESPERBUF << endl;
113
114 PaError err=Pa_OpenStream(
115 &portaudiostream,
116 this->inputParameters,
117 this->outputParameters,
118 samrate,
119 PA_FRAMESPERBUF, /* frames per buffer */
120 paClipOff | paDitherOff,
121 portaudio_process,
122 (void*)this);
123 this->havestreamtime=false;
124
125 if (err!=paNoError)
126 {
127 cout << "Error opening stream" << endl;
128 Pa_Terminate();
129 return;
130 }
131
132 cout << "Stream opened, going to start it now..." << endl;
133
134 err=Pa_StartStream(portaudiostream);
135
136 if (err!=paNoError)
137 {
138 cout << "Error starting stream" << endl;
139 Pa_Terminate();
140 return;
141 }
142
143 cout << "Stream started" << endl;
144
145 return;
146}
147
148int main()
149{
150 HD24UserInterface* ui=new HD24UserInterface();
151 ui->portaudioinit();
152 ui->portaudio_transport_start();
153 int blah;
154 cin >> blah;
155
156}
157
diff --git a/windows/hd24connect.dsp b/windows/hd24connect.dsp
new file mode 100644
index 0000000..46ef8e7
--- /dev/null
+++ b/windows/hd24connect.dsp
@@ -0,0 +1,338 @@
1# Microsoft Developer Studio Project File - Name="hd24connect" - Package Owner=<4>
2# Microsoft Developer Studio Generated Build File, Format Version 6.00
3# ** DO NOT EDIT **
4
5# TARGTYPE "Win32 (x86) Application" 0x0101
6
7CFG=hd24connect - Win32 Debug
8!MESSAGE This is not a valid makefile. To build this project using NMAKE,
9!MESSAGE use the Export Makefile command and run
10!MESSAGE
11!MESSAGE NMAKE /f "hd24connect.mak".
12!MESSAGE
13!MESSAGE You can specify a configuration when running NMAKE
14!MESSAGE by defining the macro CFG on the command line. For example:
15!MESSAGE
16!MESSAGE NMAKE /f "hd24connect.mak" CFG="hd24connect - Win32 Debug"
17!MESSAGE
18!MESSAGE Possible choices for configuration are:
19!MESSAGE
20!MESSAGE "hd24connect - Win32 Release" (based on "Win32 (x86) Application")
21!MESSAGE "hd24connect - Win32 Debug" (based on "Win32 (x86) Application")
22!MESSAGE
23
24# Begin Project
25# PROP AllowPerConfigDependencies 0
26# PROP Scc_ProjName ""
27# PROP Scc_LocalPath ""
28CPP=cl.exe
29MTL=midl.exe
30RSC=rc.exe
31
32!IF "$(CFG)" == "hd24connect - Win32 Release"
33
34# PROP BASE Use_MFC 0
35# PROP BASE Use_Debug_Libraries 0
36# PROP BASE Output_Dir "Release"
37# PROP BASE Intermediate_Dir "Release"
38# PROP BASE Target_Dir ""
39# PROP Use_MFC 0
40# PROP Use_Debug_Libraries 0
41# PROP Output_Dir "Release"
42# PROP Intermediate_Dir "Release"
43# PROP Target_Dir ""
44# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
45# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
46# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
47# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
48# ADD BASE RSC /l 0x409 /d "NDEBUG"
49# ADD RSC /l 0x409 /d "NDEBUG"
50BSC32=bscmake.exe
51# ADD BASE BSC32 /nologo
52# ADD BSC32 /nologo
53LINK32=link.exe
54# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
55# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
56
57!ELSEIF "$(CFG)" == "hd24connect - Win32 Debug"
58
59# PROP BASE Use_MFC 0
60# PROP BASE Use_Debug_Libraries 1
61# PROP BASE Output_Dir "Debug"
62# PROP BASE Intermediate_Dir "Debug"
63# PROP BASE Target_Dir ""
64# PROP Use_MFC 0
65# PROP Use_Debug_Libraries 1
66# PROP Output_Dir "Debug"
67# PROP Intermediate_Dir "Debug"
68# PROP Ignore_Export_Lib 0
69# PROP Target_Dir ""
70# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
71# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "../libsndfile" /I "../fltk" /I "./setup" /I "./src/lib" /I "./src/frontend" /I "../portaudio/portaudio/pa_common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "WINDOWS" /FR /YX /FD /GZ /c
72# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
73# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
74# ADD BASE RSC /l 0x409 /d "_DEBUG"
75# ADD RSC /l 0x409 /d "_DEBUG"
76BSC32=bscmake.exe
77# ADD BASE BSC32 /nologo
78# ADD BSC32 /nologo
79LINK32=link.exe
80# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
81# ADD LINK32 user32.lib shell32.lib gdi32.lib winmm.lib ole32.lib advapi32.lib wsock32.lib comctl32.lib comdlg32.lib fltkd.lib fltkformsd.lib fltkimagesd.lib PAStaticWMMED.lib libsndfile.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:"../fltk/lib" /libpath:"../portaudio/lib" /libpath:"../libsndfile"
82
83!ENDIF
84
85# Begin Target
86
87# Name "hd24connect - Win32 Release"
88# Name "hd24connect - Win32 Debug"
89# Begin Group "Source Files"
90
91# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
92# Begin Source File
93
94SOURCE=.\src\lib\convertlib.cpp
95# End Source File
96# Begin Source File
97
98SOURCE=.\src\lib\FL\Fl_Native_File_Chooser_WIN32.cxx
99# End Source File
100# Begin Source File
101
102SOURCE=.\src\frontend\hd24connect.cpp
103# End Source File
104# Begin Source File
105
106SOURCE=.\src\lib\hd24devicenamegenerator.cpp
107# End Source File
108# Begin Source File
109
110SOURCE=.\src\lib\hd24fs.cpp
111# End Source File
112# End Group
113# Begin Group "Header Files"
114
115# PROP Default_Filter "h;hpp;hxx;hm;inl"
116# Begin Source File
117
118SOURCE=.\src\lib\FL\Fl_Native_File_Chooser_WIN32.H
119# End Source File
120# End Group
121# Begin Group "Resource Files"
122
123# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
124# End Group
125# Begin Group "Fluid Source Files"
126
127# PROP Default_Filter "fl"
128# Begin Source File
129
130SOURCE=.\src\frontend\dialog_choosedevice.fl
131
132!IF "$(CFG)" == "hd24connect - Win32 Release"
133
134!ELSEIF "$(CFG)" == "hd24connect - Win32 Debug"
135
136# Begin Custom Build - Running fluid on $(InputPath)...
137InputDir=.\src\frontend
138WkspDir=.
139InputPath=.\src\frontend\dialog_choosedevice.fl
140InputName=dialog_choosedevice
141
142BuildCmds= \
143 $(WkspDir)/../fltk/fluid/fluidd -c $(InputPath) \
144 mv $(InputName).cxx $(InputDir) \
145 mv $(InputName).h $(InputDir) \
146
147
148"$(InputDir)/$(InputName).cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
149 $(BuildCmds)
150
151"$(InputDir)/$(InputName).h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
152 $(BuildCmds)
153# End Custom Build
154
155!ENDIF
156
157# End Source File
158# Begin Source File
159
160SOURCE=.\src\frontend\dialog_fromto.fl
161
162!IF "$(CFG)" == "hd24connect - Win32 Release"
163
164!ELSEIF "$(CFG)" == "hd24connect - Win32 Debug"
165
166# Begin Custom Build - Running fluid on $(InputPath)...
167InputDir=.\src\frontend
168WkspDir=.
169InputPath=.\src\frontend\dialog_fromto.fl
170InputName=dialog_fromto
171
172BuildCmds= \
173 $(WkspDir)/../fltk/fluid/fluidd -c $(InputPath) \
174 mv $(InputName).cxx $(InputDir) \
175 mv $(InputName).h $(InputDir) \
176
177
178"$(InputDir)/$(InputName).cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
179 $(BuildCmds)
180
181"$(InputDir)/$(InputName).h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
182 $(BuildCmds)
183# End Custom Build
184
185!ENDIF
186
187# End Source File
188# Begin Source File
189
190SOURCE=.\src\frontend\dialog_rename.fl
191
192!IF "$(CFG)" == "hd24connect - Win32 Release"
193
194!ELSEIF "$(CFG)" == "hd24connect - Win32 Debug"
195
196# Begin Custom Build - Running fluid on $(InputPath)...
197InputDir=.\src\frontend
198WkspDir=.
199InputPath=.\src\frontend\dialog_rename.fl
200InputName=dialog_rename
201
202BuildCmds= \
203 $(WkspDir)/../fltk/fluid/fluidd -c $(InputPath) \
204 mv $(InputName).cxx $(InputDir) \
205 mv $(InputName).h $(InputDir) \
206
207
208"$(InputDir)/$(InputName).cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
209 $(BuildCmds)
210
211"$(InputDir)/$(InputName).h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
212 $(BuildCmds)
213# End Custom Build
214
215!ENDIF
216
217# End Source File
218# Begin Source File
219
220SOURCE=.\src\frontend\dialog_setlocate.fl
221
222!IF "$(CFG)" == "hd24connect - Win32 Release"
223
224!ELSEIF "$(CFG)" == "hd24connect - Win32 Debug"
225
226# Begin Custom Build - Running fluid on $(InputPath)...
227InputDir=.\src\frontend
228WkspDir=.
229InputPath=.\src\frontend\dialog_setlocate.fl
230InputName=dialog_setlocate
231
232BuildCmds= \
233 $(WkspDir)/../fltk/fluid/fluidd -c $(InputPath) \
234 mv $(InputName).cxx $(InputDir) \
235 mv $(InputName).h $(InputDir) \
236
237
238"$(InputDir)/$(InputName).cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
239 $(BuildCmds)
240
241"$(InputDir)/$(InputName).h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
242 $(BuildCmds)
243# End Custom Build
244
245!ENDIF
246
247# End Source File
248# Begin Source File
249
250SOURCE=.\src\frontend\ui_hd24connect.fl
251
252!IF "$(CFG)" == "hd24connect - Win32 Release"
253
254!ELSEIF "$(CFG)" == "hd24connect - Win32 Debug"
255
256# Begin Custom Build - Running fluid on $(InputPath)...
257InputDir=.\src\frontend
258WkspDir=.
259InputPath=.\src\frontend\ui_hd24connect.fl
260InputName=ui_hd24connect
261
262BuildCmds= \
263 $(WkspDir)/../fltk/fluid/fluidd -c $(InputPath) \
264 mv $(InputName).cxx $(InputDir) \
265 mv $(InputName).h $(InputDir) \
266
267
268"$(InputDir)/$(InputName).cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
269 $(BuildCmds)
270
271"$(InputDir)/$(InputName).h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
272 $(BuildCmds)
273# End Custom Build
274
275!ENDIF
276
277# End Source File
278# Begin Source File
279
280SOURCE=.\src\frontend\ui_help_about.fl
281
282!IF "$(CFG)" == "hd24connect - Win32 Release"
283
284!ELSEIF "$(CFG)" == "hd24connect - Win32 Debug"
285
286# Begin Custom Build - Running fluid on $(InputPath)...
287InputDir=.\src\frontend
288WkspDir=.
289InputPath=.\src\frontend\ui_help_about.fl
290InputName=ui_help_about
291
292BuildCmds= \
293 $(WkspDir)/../fltk/fluid/fluidd -c $(InputPath) \
294 mv $(InputName).cxx $(InputDir) \
295 mv $(InputName).h $(InputDir) \
296
297
298"$(InputDir)/$(InputName).cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
299 $(BuildCmds)
300
301"$(InputDir)/$(InputName).h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
302 $(BuildCmds)
303# End Custom Build
304
305!ENDIF
306
307# End Source File
308# End Group
309# Begin Group "Fluid Generated Source Files"
310
311# PROP Default_Filter "cxx"
312# Begin Source File
313
314SOURCE=.\src\frontend\dialog_choosedevice.cxx
315# End Source File
316# Begin Source File
317
318SOURCE=.\src\frontend\dialog_fromto.cxx
319# End Source File
320# Begin Source File
321
322SOURCE=.\src\frontend\dialog_rename.cxx
323# End Source File
324# Begin Source File
325
326SOURCE=.\src\frontend\dialog_setlocate.cxx
327# End Source File
328# Begin Source File
329
330SOURCE=.\src\frontend\ui_hd24connect.cxx
331# End Source File
332# Begin Source File
333
334SOURCE=.\src\frontend\ui_help_about.cxx
335# End Source File
336# End Group
337# End Target
338# End Project
diff --git a/windows/hd24connect.dsw b/windows/hd24connect.dsw
new file mode 100644
index 0000000..e5856bb
--- /dev/null
+++ b/windows/hd24connect.dsw
@@ -0,0 +1,29 @@
1Microsoft Developer Studio Workspace File, Format Version 6.00
2# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
3
4###############################################################################
5
6Project: "hd24connect"=.\hd24connect.dsp - Package Owner=<4>
7
8Package=<5>
9{{{
10}}}
11
12Package=<4>
13{{{
14}}}
15
16###############################################################################
17
18Global:
19
20Package=<5>
21{{{
22}}}
23
24Package=<3>
25{{{
26}}}
27
28###############################################################################
29
diff --git a/windows/hd24hexview.dsp b/windows/hd24hexview.dsp
new file mode 100644
index 0000000..c71e867
--- /dev/null
+++ b/windows/hd24hexview.dsp
@@ -0,0 +1,118 @@
1# Microsoft Developer Studio Project File - Name="hd24hexview" - Package Owner=<4>
2# Microsoft Developer Studio Generated Build File, Format Version 6.00
3# ** DO NOT EDIT **
4
5# TARGTYPE "Win32 (x86) Application" 0x0101
6
7CFG=hd24hexview - Win32 Debug
8!MESSAGE This is not a valid makefile. To build this project using NMAKE,
9!MESSAGE use the Export Makefile command and run
10!MESSAGE
11!MESSAGE NMAKE /f "hd24hexview.mak".
12!MESSAGE
13!MESSAGE You can specify a configuration when running NMAKE
14!MESSAGE by defining the macro CFG on the command line. For example:
15!MESSAGE
16!MESSAGE NMAKE /f "hd24hexview.mak" CFG="hd24hexview - Win32 Debug"
17!MESSAGE
18!MESSAGE Possible choices for configuration are:
19!MESSAGE
20!MESSAGE "hd24hexview - Win32 Release" (based on "Win32 (x86) Application")
21!MESSAGE "hd24hexview - Win32 Debug" (based on "Win32 (x86) Application")
22!MESSAGE
23
24# Begin Project
25# PROP AllowPerConfigDependencies 0
26# PROP Scc_ProjName ""
27# PROP Scc_LocalPath ""
28CPP=cl.exe
29MTL=midl.exe
30RSC=rc.exe
31
32!IF "$(CFG)" == "hd24hexview - Win32 Release"
33
34# PROP BASE Use_MFC 0
35# PROP BASE Use_Debug_Libraries 0
36# PROP BASE Output_Dir "Release"
37# PROP BASE Intermediate_Dir "Release"
38# PROP BASE Target_Dir ""
39# PROP Use_MFC 0
40# PROP Use_Debug_Libraries 0
41# PROP Output_Dir "Release"
42# PROP Intermediate_Dir "Release"
43# PROP Target_Dir ""
44# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
45# ADD CPP /nologo /W3 /GX /O2 /I "./setup" /I "./src/lib" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "WINDOWS" /YX /FD /c
46# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
47# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
48# ADD BASE RSC /l 0x409 /d "NDEBUG"
49# ADD RSC /l 0x409 /d "NDEBUG"
50BSC32=bscmake.exe
51# ADD BASE BSC32 /nologo
52# ADD BSC32 /nologo
53LINK32=link.exe
54# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
55# ADD LINK32 fltk.lib /nologo /subsystem:windows /machine:I386 /libpath:"./fltk/lib"
56
57!ELSEIF "$(CFG)" == "hd24hexview - Win32 Debug"
58
59# PROP BASE Use_MFC 0
60# PROP BASE Use_Debug_Libraries 1
61# PROP BASE Output_Dir "Debug"
62# PROP BASE Intermediate_Dir "Debug"
63# PROP BASE Target_Dir ""
64# PROP Use_MFC 0
65# PROP Use_Debug_Libraries 1
66# PROP Output_Dir "Debug"
67# PROP Intermediate_Dir "Debug"
68# PROP Ignore_Export_Lib 0
69# PROP Target_Dir ""
70# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
71# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "./setup" /I "./src/lib" /I "../fltk" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "WINDOWS" /FR /YX /FD /GZ /c
72# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
73# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
74# ADD BASE RSC /l 0x409 /d "_DEBUG"
75# ADD RSC /l 0x409 /d "_DEBUG"
76BSC32=bscmake.exe
77# ADD BASE BSC32 /nologo
78# ADD BSC32 /nologo
79LINK32=link.exe
80# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
81# ADD LINK32 fltkd.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:"../fltk/lib"
82
83!ENDIF
84
85# Begin Target
86
87# Name "hd24hexview - Win32 Release"
88# Name "hd24hexview - Win32 Debug"
89# Begin Group "Source Files"
90
91# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
92# Begin Source File
93
94SOURCE=.\src\lib\convertlib.cpp
95# End Source File
96# Begin Source File
97
98SOURCE=.\src\lib\hd24devicenamegenerator.cpp
99# End Source File
100# Begin Source File
101
102SOURCE=.\src\lib\hd24fs.cpp
103# End Source File
104# Begin Source File
105
106SOURCE=.\src\hd24hexview.cpp
107# End Source File
108# End Group
109# Begin Group "Header Files"
110
111# PROP Default_Filter "h;hpp;hxx;hm;inl"
112# End Group
113# Begin Group "Resource Files"
114
115# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
116# End Group
117# End Target
118# End Project
diff --git a/windows/hd24info.dsp b/windows/hd24info.dsp
new file mode 100644
index 0000000..cf5b6c3
--- /dev/null
+++ b/windows/hd24info.dsp
@@ -0,0 +1,118 @@
1# Microsoft Developer Studio Project File - Name="hd24info" - Package Owner=<4>
2# Microsoft Developer Studio Generated Build File, Format Version 6.00
3# ** DO NOT EDIT **
4
5# TARGTYPE "Win32 (x86) Application" 0x0101
6
7CFG=hd24info - Win32 Debug
8!MESSAGE This is not a valid makefile. To build this project using NMAKE,
9!MESSAGE use the Export Makefile command and run
10!MESSAGE
11!MESSAGE NMAKE /f "hd24info.mak".
12!MESSAGE
13!MESSAGE You can specify a configuration when running NMAKE
14!MESSAGE by defining the macro CFG on the command line. For example:
15!MESSAGE
16!MESSAGE NMAKE /f "hd24info.mak" CFG="hd24info - Win32 Debug"
17!MESSAGE
18!MESSAGE Possible choices for configuration are:
19!MESSAGE
20!MESSAGE "hd24info - Win32 Release" (based on "Win32 (x86) Application")
21!MESSAGE "hd24info - Win32 Debug" (based on "Win32 (x86) Application")
22!MESSAGE
23
24# Begin Project
25# PROP AllowPerConfigDependencies 0
26# PROP Scc_ProjName ""
27# PROP Scc_LocalPath ""
28CPP=cl.exe
29MTL=midl.exe
30RSC=rc.exe
31
32!IF "$(CFG)" == "hd24info - Win32 Release"
33
34# PROP BASE Use_MFC 0
35# PROP BASE Use_Debug_Libraries 0
36# PROP BASE Output_Dir "Release"
37# PROP BASE Intermediate_Dir "Release"
38# PROP BASE Target_Dir ""
39# PROP Use_MFC 0
40# PROP Use_Debug_Libraries 0
41# PROP Output_Dir "Release"
42# PROP Intermediate_Dir "Release"
43# PROP Target_Dir ""
44# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
45# ADD CPP /nologo /W3 /GX /O2 /I "./setup" /I "./src/lib" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "WINDOWS" /YX /FD /c
46# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
47# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
48# ADD BASE RSC /l 0x409 /d "NDEBUG"
49# ADD RSC /l 0x409 /d "NDEBUG"
50BSC32=bscmake.exe
51# ADD BASE BSC32 /nologo
52# ADD BSC32 /nologo
53LINK32=link.exe
54# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
55# ADD LINK32 fltk.lib libsndfile.lib /nologo /subsystem:windows /machine:I386 /libpath:"./fltk/lib" /libpath:"./libsndfile"
56
57!ELSEIF "$(CFG)" == "hd24info - Win32 Debug"
58
59# PROP BASE Use_MFC 0
60# PROP BASE Use_Debug_Libraries 1
61# PROP BASE Output_Dir "Debug"
62# PROP BASE Intermediate_Dir "Debug"
63# PROP BASE Target_Dir ""
64# PROP Use_MFC 0
65# PROP Use_Debug_Libraries 1
66# PROP Output_Dir "Debug"
67# PROP Intermediate_Dir "Debug"
68# PROP Ignore_Export_Lib 0
69# PROP Target_Dir ""
70# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
71# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "./setup" /I "./src/lib" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "WINDOWS" /FR /YX /FD /GZ /c
72# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
73# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
74# ADD BASE RSC /l 0x409 /d "_DEBUG"
75# ADD RSC /l 0x409 /d "_DEBUG"
76BSC32=bscmake.exe
77# ADD BASE BSC32 /nologo
78# ADD BSC32 /nologo
79LINK32=link.exe
80# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
81# ADD LINK32 fltkd.lib libsndfile.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:"../fltk/lib" /libpath:"../libsndfile"
82
83!ENDIF
84
85# Begin Target
86
87# Name "hd24info - Win32 Release"
88# Name "hd24info - Win32 Debug"
89# Begin Group "Source Files"
90
91# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
92# Begin Source File
93
94SOURCE=.\src\lib\convertlib.cpp
95# End Source File
96# Begin Source File
97
98SOURCE=.\src\lib\hd24devicenamegenerator.cpp
99# End Source File
100# Begin Source File
101
102SOURCE=.\src\lib\hd24fs.cpp
103# End Source File
104# Begin Source File
105
106SOURCE=.\src\hd24info.cpp
107# End Source File
108# End Group
109# Begin Group "Header Files"
110
111# PROP Default_Filter "h;hpp;hxx;hm;inl"
112# End Group
113# Begin Group "Resource Files"
114
115# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
116# End Group
117# End Target
118# End Project
diff --git a/windows/hd24tools.dsw b/windows/hd24tools.dsw
new file mode 100644
index 0000000..90fc4e0
--- /dev/null
+++ b/windows/hd24tools.dsw
@@ -0,0 +1,65 @@
1Microsoft Developer Studio Workspace File, Format Version 6.00
2# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
3
4###############################################################################
5
6Project: "hd24connect"=.\hd24connect.dsp - Package Owner=<4>
7
8Package=<5>
9{{{
10}}}
11
12Package=<4>
13{{{
14}}}
15
16###############################################################################
17
18Project: "hd24hexview"=.\hd24hexview.dsp - Package Owner=<4>
19
20Package=<5>
21{{{
22}}}
23
24Package=<4>
25{{{
26}}}
27
28###############################################################################
29
30Project: "hd24info"=.\hd24info.dsp - Package Owner=<4>
31
32Package=<5>
33{{{
34}}}
35
36Package=<4>
37{{{
38}}}
39
40###############################################################################
41
42Project: "hd24towav"=.\hd24towav.dsp - Package Owner=<4>
43
44Package=<5>
45{{{
46}}}
47
48Package=<4>
49{{{
50}}}
51
52###############################################################################
53
54Global:
55
56Package=<5>
57{{{
58}}}
59
60Package=<3>
61{{{
62}}}
63
64###############################################################################
65
diff --git a/windows/hd24towav.dsp b/windows/hd24towav.dsp
new file mode 100644
index 0000000..ee71095
--- /dev/null
+++ b/windows/hd24towav.dsp
@@ -0,0 +1,111 @@
1# Microsoft Developer Studio Project File - Name="hd24towav" - Package Owner=<4>
2# Microsoft Developer Studio Generated Build File, Format Version 6.00
3# ** DO NOT EDIT **
4
5# TARGTYPE "Win32 (x86) Application" 0x0101
6
7CFG=hd24towav - Win32 Debug
8!MESSAGE This is not a valid makefile. To build this project using NMAKE,
9!MESSAGE use the Export Makefile command and run
10!MESSAGE
11!MESSAGE NMAKE /f "hd24towav.mak".
12!MESSAGE
13!MESSAGE You can specify a configuration when running NMAKE
14!MESSAGE by defining the macro CFG on the command line. For example:
15!MESSAGE
16!MESSAGE NMAKE /f "hd24towav.mak" CFG="hd24towav - Win32 Debug"
17!MESSAGE
18!MESSAGE Possible choices for configuration are:
19!MESSAGE
20!MESSAGE "hd24towav - Win32 Release" (based on "Win32 (x86) Application")
21!MESSAGE "hd24towav - Win32 Debug" (based on "Win32 (x86) Application")
22!MESSAGE
23
24# Begin Project
25# PROP AllowPerConfigDependencies 0
26# PROP Scc_ProjName ""
27# PROP Scc_LocalPath ""
28CPP=cl.exe
29MTL=midl.exe
30RSC=rc.exe
31
32!IF "$(CFG)" == "hd24towav - Win32 Release"
33
34# PROP BASE Use_MFC 0
35# PROP BASE Use_Debug_Libraries 0
36# PROP BASE Output_Dir "Release"
37# PROP BASE Intermediate_Dir "Release"
38# PROP BASE Target_Dir ""
39# PROP Use_MFC 0
40# PROP Use_Debug_Libraries 0
41# PROP Output_Dir "Release"
42# PROP Intermediate_Dir "Release"
43# PROP Ignore_Export_Lib 0
44# PROP Target_Dir ""
45# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
46# ADD CPP /nologo /W3 /GX /O2 /I "./setup" /I "./src/lib" /I "./libsndfile" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "WINDOWS" /YX /FD /c
47# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
48# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
49# ADD BASE RSC /l 0x409 /d "NDEBUG"
50# ADD RSC /l 0x409 /d "NDEBUG"
51BSC32=bscmake.exe
52# ADD BASE BSC32 /nologo
53# ADD BSC32 /nologo
54LINK32=link.exe
55# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
56# ADD LINK32 fltk.lib libsndfile.lib /nologo /subsystem:windows /machine:I386 /libpath:"./fltk/lib" /libpath:"./portaudio/lib" /libpath:"./libsndfile"
57
58!ELSEIF "$(CFG)" == "hd24towav - Win32 Debug"
59
60# PROP BASE Use_MFC 0
61# PROP BASE Use_Debug_Libraries 1
62# PROP BASE Output_Dir "Debug"
63# PROP BASE Intermediate_Dir "Debug"
64# PROP BASE Target_Dir ""
65# PROP Use_MFC 0
66# PROP Use_Debug_Libraries 1
67# PROP Output_Dir "Debug"
68# PROP Intermediate_Dir "Debug"
69# PROP Ignore_Export_Lib 0
70# PROP Target_Dir ""
71# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
72# ADD CPP /nologo /MDd /Gm /GX /ZI /Od /I "./setup" /I "./src/lib" /I "../libsndfile" /D "_DEBUG" /D "WINDOWS" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /FR /YX /FD /GZ /c
73# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
74# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
75# ADD BASE RSC /l 0x409 /d "_DEBUG"
76# ADD RSC /l 0x409 /d "_DEBUG"
77BSC32=bscmake.exe
78# ADD BASE BSC32 /nologo
79# ADD BSC32 /nologo
80LINK32=link.exe
81# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
82# ADD LINK32 fltkd.lib libsndfile.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:"../fltk/lib" /libpath:"../libsndfile"
83
84!ENDIF
85
86# Begin Target
87
88# Name "hd24towav - Win32 Release"
89# Name "hd24towav - Win32 Debug"
90# Begin Group "Source Files"
91
92# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
93# Begin Source File
94
95SOURCE=.\src\lib\convertlib.cpp
96# End Source File
97# Begin Source File
98
99SOURCE=.\src\hd24towav.cpp
100# End Source File
101# End Group
102# Begin Group "Header Files"
103
104# PROP Default_Filter "h;hpp;hxx;hm;inl"
105# End Group
106# Begin Group "Resource Files"
107
108# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
109# End Group
110# End Target
111# End Project